|
@@ -0,0 +1,365 @@
|
|
|
+
|
|
|
+let vueFile = new Vue({
|
|
|
+ el: '#modal-editor-file',
|
|
|
+ data: {
|
|
|
+ isLoading: false,
|
|
|
+ isLoadingText: '',
|
|
|
+ newFolderName: '',
|
|
|
+ newFolderShow: false,
|
|
|
+ newFolderError: false,
|
|
|
+ folders: [],
|
|
|
+ currentFolder: '',
|
|
|
+ currentFile: '',
|
|
|
+ files: [],
|
|
|
+ uploadSucceeded: false,
|
|
|
+ postUploadChecks: 0,
|
|
|
+ renameFileShow: false,
|
|
|
+ renameFileId: '',
|
|
|
+ renameFileFilename: '',
|
|
|
+ deleteFileShow: false,
|
|
|
+ deleteFileId: '',
|
|
|
+ deleteFileFilename: ''
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+
|
|
|
+ open: () => {
|
|
|
+ mdeModalOpenState = true;
|
|
|
+ $('#modal-editor-file').addClass('is-active');
|
|
|
+ vueFile.refreshFolders();
|
|
|
+ },
|
|
|
+ cancel: (ev) => {
|
|
|
+ mdeModalOpenState = false;
|
|
|
+ $('#modal-editor-file').removeClass('is-active');
|
|
|
+ },
|
|
|
+
|
|
|
+ // -------------------------------------------
|
|
|
+ // INSERT LINK TO FILE
|
|
|
+ // -------------------------------------------
|
|
|
+
|
|
|
+ selectFile: (fileId) => {
|
|
|
+ vueFile.currentFile = fileId;
|
|
|
+ },
|
|
|
+ insertFileLink: (ev) => {
|
|
|
+
|
|
|
+ if(mde.codemirror.doc.somethingSelected()) {
|
|
|
+ mde.codemirror.execCommand('singleSelection');
|
|
|
+ }
|
|
|
+
|
|
|
+ let selFile = _.find(vueFile.files, ['_id', vueFile.currentFile]);
|
|
|
+ selFile.normalizedPath = (selFile.folder === 'f:') ? selFile.filename : selFile.folder.slice(2) + '/' + selFile.filename;
|
|
|
+ selFile.titleGuess = _.startCase(selFile.basename);
|
|
|
+
|
|
|
+ let fileText = '[' + selFile.titleGuess + '](/uploads/' + selFile.normalizedPath + ' "' + selFile.titleGuess + '")';
|
|
|
+
|
|
|
+ mde.codemirror.doc.replaceSelection(fileText);
|
|
|
+ vueFile.cancel();
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ // -------------------------------------------
|
|
|
+ // NEW FOLDER
|
|
|
+ // -------------------------------------------
|
|
|
+
|
|
|
+ newFolder: (ev) => {
|
|
|
+ vueFile.newFolderName = '';
|
|
|
+ vueFile.newFolderError = false;
|
|
|
+ vueFile.newFolderShow = true;
|
|
|
+ _.delay(() => { $('#txt-editor-file-newfoldername').focus(); }, 400);
|
|
|
+ },
|
|
|
+ newFolderDiscard: (ev) => {
|
|
|
+ vueFile.newFolderShow = false;
|
|
|
+ },
|
|
|
+ newFolderCreate: (ev) => {
|
|
|
+
|
|
|
+ let regFolderName = new RegExp("^[a-z0-9][a-z0-9\-]*[a-z0-9]$");
|
|
|
+ vueFile.newFolderName = _.kebabCase(_.trim(vueFile.newFolderName));
|
|
|
+
|
|
|
+ if(_.isEmpty(vueFile.newFolderName) || !regFolderName.test(vueFile.newFolderName)) {
|
|
|
+ vueFile.newFolderError = true;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ vueFile.newFolderDiscard();
|
|
|
+ vueFile.isLoadingText = 'Creating new folder...';
|
|
|
+ vueFile.isLoading = true;
|
|
|
+
|
|
|
+ Vue.nextTick(() => {
|
|
|
+ socket.emit('uploadsCreateFolder', { foldername: vueFile.newFolderName }, (data) => {
|
|
|
+ vueFile.folders = data;
|
|
|
+ vueFile.currentFolder = vueFile.newFolderName;
|
|
|
+ vueFile.files = [];
|
|
|
+ vueFile.isLoading = false;
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ // -------------------------------------------
|
|
|
+ // RENAME FILE
|
|
|
+ // -------------------------------------------
|
|
|
+
|
|
|
+ renameFile: () => {
|
|
|
+
|
|
|
+ let c = _.find(vueFile.files, ['_id', vueFile.renameFileId ]);
|
|
|
+ vueFile.renameFileFilename = c.basename || '';
|
|
|
+ vueFile.renameFileShow = true;
|
|
|
+ _.delay(() => {
|
|
|
+ $('#txt-editor-renamefile').focus();
|
|
|
+ _.defer(() => { $('#txt-editor-file-rename').select(); });
|
|
|
+ }, 400);
|
|
|
+ },
|
|
|
+ renameFileDiscard: () => {
|
|
|
+ vueFile.renameFileShow = false;
|
|
|
+ },
|
|
|
+ renameFileGo: () => {
|
|
|
+
|
|
|
+ vueFile.renameFileDiscard();
|
|
|
+ vueFile.isLoadingText = 'Renaming file...';
|
|
|
+ vueFile.isLoading = true;
|
|
|
+
|
|
|
+ Vue.nextTick(() => {
|
|
|
+ socket.emit('uploadsRenameFile', { uid: vueFile.renameFileId, folder: vueFile.currentFolder, filename: vueFile.renameFileFilename }, (data) => {
|
|
|
+ if(data.ok) {
|
|
|
+ vueFile.waitChangeComplete(vueFile.files.length, false);
|
|
|
+ } else {
|
|
|
+ vueFile.isLoading = false;
|
|
|
+ alerts.pushError('Rename error', data.msg);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ // -------------------------------------------
|
|
|
+ // MOVE FILE
|
|
|
+ // -------------------------------------------
|
|
|
+
|
|
|
+ moveFile: (uid, fld) => {
|
|
|
+ vueFile.isLoadingText = 'Moving file...';
|
|
|
+ vueFile.isLoading = true;
|
|
|
+ Vue.nextTick(() => {
|
|
|
+ socket.emit('uploadsMoveFile', { uid, folder: fld }, (data) => {
|
|
|
+ if(data.ok) {
|
|
|
+ vueFile.loadFiles();
|
|
|
+ } else {
|
|
|
+ vueFile.isLoading = false;
|
|
|
+ alerts.pushError('Rename error', data.msg);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ // -------------------------------------------
|
|
|
+ // DELETE FILE
|
|
|
+ // -------------------------------------------
|
|
|
+
|
|
|
+ deleteFileWarn: (show) => {
|
|
|
+ if(show) {
|
|
|
+ let c = _.find(vueFile.files, ['_id', vueFile.deleteFileId ]);
|
|
|
+ vueFile.deleteFileFilename = c.filename || 'this file';
|
|
|
+ }
|
|
|
+ vueFile.deleteFileShow = show;
|
|
|
+ },
|
|
|
+ deleteFileGo: () => {
|
|
|
+ vueFile.deleteFileWarn(false);
|
|
|
+ vueFile.isLoadingText = 'Deleting file...';
|
|
|
+ vueFile.isLoading = true;
|
|
|
+ Vue.nextTick(() => {
|
|
|
+ socket.emit('uploadsDeleteFile', { uid: vueFile.deleteFileId }, (data) => {
|
|
|
+ vueFile.loadFiles();
|
|
|
+ });
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ // -------------------------------------------
|
|
|
+ // LOAD FROM REMOTE
|
|
|
+ // -------------------------------------------
|
|
|
+
|
|
|
+ selectFolder: (fldName) => {
|
|
|
+ vueFile.currentFolder = fldName;
|
|
|
+ vueFile.loadFiles();
|
|
|
+ },
|
|
|
+
|
|
|
+ refreshFolders: () => {
|
|
|
+ vueFile.isLoadingText = 'Fetching folders list...';
|
|
|
+ vueFile.isLoading = true;
|
|
|
+ vueFile.currentFolder = '';
|
|
|
+ vueFile.currentImage = '';
|
|
|
+ Vue.nextTick(() => {
|
|
|
+ socket.emit('uploadsGetFolders', { }, (data) => {
|
|
|
+ vueFile.folders = data;
|
|
|
+ vueFile.loadFiles();
|
|
|
+ });
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ loadFiles: (silent) => {
|
|
|
+ if(!silent) {
|
|
|
+ vueFile.isLoadingText = 'Fetching files...';
|
|
|
+ vueFile.isLoading = true;
|
|
|
+ }
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
+ Vue.nextTick(() => {
|
|
|
+ socket.emit('uploadsGetFiles', { folder: vueFile.currentFolder }, (data) => {
|
|
|
+ vueFile.files = data;
|
|
|
+ if(!silent) {
|
|
|
+ vueFile.isLoading = false;
|
|
|
+ }
|
|
|
+ vueFile.attachContextMenus();
|
|
|
+ resolve(true);
|
|
|
+ });
|
|
|
+ });
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ waitChangeComplete: (oldAmount, expectChange) => {
|
|
|
+
|
|
|
+ expectChange = (_.isBoolean(expectChange)) ? expectChange : true;
|
|
|
+
|
|
|
+ vueFile.postUploadChecks++;
|
|
|
+ vueFile.isLoadingText = 'Processing...';
|
|
|
+
|
|
|
+ Vue.nextTick(() => {
|
|
|
+ vueFile.loadFiles(true).then(() => {
|
|
|
+ if((vueFile.files.length !== oldAmount) === expectChange) {
|
|
|
+ vueFile.postUploadChecks = 0;
|
|
|
+ vueFile.isLoading = false;
|
|
|
+ } else if(vueFile.postUploadChecks > 5) {
|
|
|
+ vueFile.postUploadChecks = 0;
|
|
|
+ vueFile.isLoading = false;
|
|
|
+ alerts.pushError('Unable to fetch updated listing', 'Try again later');
|
|
|
+ } else {
|
|
|
+ _.delay(() => {
|
|
|
+ vueFile.waitChangeComplete(oldAmount, expectChange);
|
|
|
+ }, 1500);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ // -------------------------------------------
|
|
|
+ // IMAGE CONTEXT MENU
|
|
|
+ // -------------------------------------------
|
|
|
+
|
|
|
+ attachContextMenus: () => {
|
|
|
+
|
|
|
+ let moveFolders = _.map(vueFile.folders, (f) => {
|
|
|
+ return {
|
|
|
+ name: (f !== '') ? f : '/ (root)',
|
|
|
+ icon: 'fa-folder',
|
|
|
+ callback: (key, opt) => {
|
|
|
+ let moveFileId = _.toString($(opt.$trigger).data('uid'));
|
|
|
+ let moveFileDestFolder = _.nth(vueFile.folders, key);
|
|
|
+ vueFile.moveFile(moveFileId, moveFileDestFolder);
|
|
|
+ }
|
|
|
+ };
|
|
|
+ });
|
|
|
+
|
|
|
+ $.contextMenu('destroy', '.editor-modal-file-choices > figure');
|
|
|
+ $.contextMenu({
|
|
|
+ selector: '.editor-modal-file-choices > figure',
|
|
|
+ appendTo: '.editor-modal-file-choices',
|
|
|
+ position: (opt, x, y) => {
|
|
|
+ $(opt.$trigger).addClass('is-contextopen');
|
|
|
+ let trigPos = $(opt.$trigger).position();
|
|
|
+ let trigDim = { w: $(opt.$trigger).width() / 5, h: $(opt.$trigger).height() / 2 };
|
|
|
+ opt.$menu.css({ top: trigPos.top + trigDim.h, left: trigPos.left + trigDim.w });
|
|
|
+ },
|
|
|
+ events: {
|
|
|
+ hide: (opt) => {
|
|
|
+ $(opt.$trigger).removeClass('is-contextopen');
|
|
|
+ }
|
|
|
+ },
|
|
|
+ items: {
|
|
|
+ rename: {
|
|
|
+ name: "Rename",
|
|
|
+ icon: "fa-edit",
|
|
|
+ callback: (key, opt) => {
|
|
|
+ vueFile.renameFileId = _.toString(opt.$trigger[0].dataset.uid);
|
|
|
+ vueFile.renameFile();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ move: {
|
|
|
+ name: "Move to...",
|
|
|
+ icon: "fa-folder-open-o",
|
|
|
+ items: moveFolders
|
|
|
+ },
|
|
|
+ delete: {
|
|
|
+ name: "Delete",
|
|
|
+ icon: "fa-trash",
|
|
|
+ callback: (key, opt) => {
|
|
|
+ vueFile.deleteFileId = _.toString(opt.$trigger[0].dataset.uid);
|
|
|
+ vueFile.deleteFileWarn(true);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+});
|
|
|
+
|
|
|
+$('#btn-editor-file-upload input').on('change', (ev) => {
|
|
|
+
|
|
|
+ let curFileAmount = vueFile.files.length;
|
|
|
+
|
|
|
+ $(ev.currentTarget).simpleUpload("/uploads/file", {
|
|
|
+
|
|
|
+ name: 'binfile',
|
|
|
+ data: {
|
|
|
+ folder: vueFile.currentFolder
|
|
|
+ },
|
|
|
+ limit: 20,
|
|
|
+ expect: 'json',
|
|
|
+ maxFileSize: 0,
|
|
|
+
|
|
|
+ init: (totalUploads) => {
|
|
|
+ vueFile.uploadSucceeded = false;
|
|
|
+ vueFile.isLoadingText = 'Preparing to upload...';
|
|
|
+ vueFile.isLoading = true;
|
|
|
+ },
|
|
|
+
|
|
|
+ progress: (progress) => {
|
|
|
+ vueFile.isLoadingText = 'Uploading...' + Math.round(progress) + '%';
|
|
|
+ },
|
|
|
+
|
|
|
+ success: (data) => {
|
|
|
+ if(data.ok) {
|
|
|
+
|
|
|
+ let failedUpls = _.filter(data.results, ['ok', false]);
|
|
|
+ if(failedUpls.length) {
|
|
|
+ _.forEach(failedUpls, (u) => {
|
|
|
+ alerts.pushError('Upload error', u.msg);
|
|
|
+ });
|
|
|
+ if(failedUpls.length < data.results.length) {
|
|
|
+ alerts.push({
|
|
|
+ title: 'Some uploads succeeded',
|
|
|
+ message: 'Files that are not mentionned in the errors above were uploaded successfully.'
|
|
|
+ });
|
|
|
+ vueFile.uploadSucceeded = true;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ vueFile.uploadSucceeded = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+ alerts.pushError('Upload error', data.msg);
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ error: (error) => {
|
|
|
+ alerts.pushError(error.message, this.upload.file.name);
|
|
|
+ },
|
|
|
+
|
|
|
+ finish: () => {
|
|
|
+ if(vueFile.uploadSucceeded) {
|
|
|
+ vueFile.waitChangeComplete(curFileAmount, true);
|
|
|
+ } else {
|
|
|
+ vueFile.isLoading = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ });
|
|
|
+
|
|
|
+});
|