@vipindev/tinymce-s3-uploader-plugin
Version:
152 lines (124 loc) • 5.15 kB
JavaScript
import tinymce from 'tinymce/tinymce'
import AWS from 'aws-sdk'
/**
* This class contains all core logic for the AWS plugin.
*
* @class tinymce.AWsS3Upload.Plugin
* @private
*/
tinymce.PluginManager.add('AwsS3Upload', (editor, url) => {
// Grab the params from TinyMCE init
const { bucketName, folderName = '', awsAuth, buttonText = 'Upload File', conditions = {}, progress, secondFileSelectedBeforeFirstUpload } = editor.getParam('Awss3UploadSettings')
const { secretAccessKey, accessKeyId, region } = awsAuth
const { contentLengthRange = { min: 0, max: null } } = conditions
let inProgress = false
// Initializing parameters control
if (!bucketName) {
console.log('`bucketName` parameter missing on init AwsS3Upload TinyMCE plugin.')
return false
}
// awsAuth control
if (awsAuth && typeof awsAuth === 'object') {
if (!accessKeyId) {
console.log('`awsAuth` parameter missing `accessKeyId` property on init AwsS3Upload TinyMCE plugin.')
return false
}
if (!secretAccessKey) {
console.log('`awsAuth` parameter missing `secretAccessKey` property on init AwsS3Upload TinyMCE plugin.')
return false
}
if (!region) {
console.log('`awsAuth` parameter missing `secretAccessKey` property on init AwsS3Upload TinyMCE plugin.')
return false
}
// Let's update the auth config
AWS.config.update({
region,
accessKeyId,
secretAccessKey
})
}
// Adding file input to DOM
const textarea = editor.targetElm
let inputEl = document.createElement('input')
inputEl.type = 'file'
inputEl.style.cssText = 'display:none'
textarea.parentNode.insertBefore(inputEl, textarea)
// Create progress element
let progressEl = document.createElement('progress')
progressEl.max = 100
progressEl.value = 10
progressEl.style.cssText = 'display:none'
textarea.parentNode.insertBefore(progressEl, textarea)
// Creating bucket
let bucket = new AWS.S3({
params: {
Bucket: bucketName
}
})
inputEl.addEventListener('change', e => {
e.preventDefault()
// Select the file & contentAreaContainer
let file = inputEl.files[0]
let contentAreaContainer = editor.contentAreaContainer
// If file exists
if (file) {
checkContentLenghtRange(file)
// Put the progress bar inside content area of TinyMCE
contentAreaContainer.parentNode.insertBefore(progressEl, contentAreaContainer)
if (progress.bar && typeof progress.bar === 'boolean') { progressEl.style.cssText = 'display:block;position: absolute;z-index: 9999;width: 120px;height: 15px;right: 10px;top:45px' }
// We are uploading right now
inProgress = true
let extension = file.name.split('.').pop()
let fileName = file.name.split('.' + extension)[0]
let objKey = (folderName ? `${folderName}/` : '') + fileName + '-' + Date.now() + '.' + extension
let params = {
Key: objKey,
ContentType: file.type,
Body: file,
ACL: 'public-read'
}
bucket
.putObject(params)
.on('httpUploadProgress', progressObj => {
let progressPercentage = parseInt((progressObj.loaded / progressObj.total) * 100)
// Change the value of progressbar. No matter if it's visible or not
progressEl.value = progressPercentage
// Call the callback function if it's exists
if (progress.callback && typeof progress.callback === 'function') { progress.callback(progressPercentage) }
}).send((err, data) => {
inProgress = false
progressEl.style.cssText = 'display:none'
if (err) {
if (progress.errorCallback && typeof progress.errorCallback === 'function') { progress.errorCallback(err) }
} else {
let url = `https://${bucketName}.s3.amazonaws.com/${objKey}`
if (progress.successCallback && typeof progress.successCallback === 'function') { progress.successCallback(editor, url) }
}
})
} else {
}
})
editor.ui.registry.addButton('AwsS3UploadButton', {
text: buttonText,
onAction () {
if (!inProgress) { inputEl.click() } else {
if (secondFileSelectedBeforeFirstUpload.callback && typeof secondFileSelectedBeforeFirstUpload.callback === 'function') { secondFileSelectedBeforeFirstUpload.callback() } else { alert('Progress allready') }
}
}
})
function checkContentLenghtRange (file) {
let isContentLengthOutOfRange =
(typeof contentLengthRange.min === 'number' && file.size < contentLengthRange.min) ||
(typeof contentLengthRange.max === 'number' && file.size > contentLengthRange.max)
if (isContentLengthOutOfRange) {
let err = new RangeError(
`The content length of '${file.name}' must be between ${contentLengthRange.min} and ${contentLengthRange.max} bytes.`
)
// err.fileSize = file.size;
if (contentLengthRange.errorCallback && typeof contentLengthRange.errorCallback === 'function') { contentLengthRange.errorCallback(err) }
throw err
}
}
})
export default function () {}