Standard JS code conversion + fixes
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
"use strict";
|
||||
'use strict'
|
||||
|
||||
/**
|
||||
* Alerts
|
||||
@@ -10,25 +10,23 @@ class Alerts {
|
||||
*
|
||||
* @class
|
||||
*/
|
||||
constructor() {
|
||||
constructor () {
|
||||
let self = this
|
||||
|
||||
let self = this;
|
||||
self.mdl = new Vue({
|
||||
el: '#alerts',
|
||||
data: {
|
||||
children: []
|
||||
},
|
||||
methods: {
|
||||
acknowledge: (uid) => {
|
||||
self.close(uid)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
self.mdl = new Vue({
|
||||
el: '#alerts',
|
||||
data: {
|
||||
children: []
|
||||
},
|
||||
methods: {
|
||||
acknowledge: (uid) => {
|
||||
self.close(uid);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
self.uidNext = 1;
|
||||
|
||||
}
|
||||
self.uidNext = 1
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a new Alert
|
||||
@@ -36,29 +34,27 @@ class Alerts {
|
||||
* @param {Object} options Alert properties
|
||||
* @return {null} Void
|
||||
*/
|
||||
push(options) {
|
||||
push (options) {
|
||||
let self = this
|
||||
|
||||
let self = this;
|
||||
let nAlert = _.defaults(options, {
|
||||
_uid: self.uidNext,
|
||||
class: 'info',
|
||||
message: '---',
|
||||
sticky: false,
|
||||
title: '---'
|
||||
})
|
||||
|
||||
let nAlert = _.defaults(options, {
|
||||
_uid: self.uidNext,
|
||||
class: 'info',
|
||||
message: '---',
|
||||
sticky: false,
|
||||
title: '---'
|
||||
});
|
||||
self.mdl.children.push(nAlert)
|
||||
|
||||
self.mdl.children.push(nAlert);
|
||||
if (!nAlert.sticky) {
|
||||
_.delay(() => {
|
||||
self.close(nAlert._uid)
|
||||
}, 5000)
|
||||
}
|
||||
|
||||
if(!nAlert.sticky) {
|
||||
_.delay(() => {
|
||||
self.close(nAlert._uid);
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
self.uidNext++;
|
||||
|
||||
}
|
||||
self.uidNext++
|
||||
}
|
||||
|
||||
/**
|
||||
* Shorthand method for pushing errors
|
||||
@@ -66,14 +62,14 @@ class Alerts {
|
||||
* @param {String} title The title
|
||||
* @param {String} message The message
|
||||
*/
|
||||
pushError(title, message) {
|
||||
this.push({
|
||||
class: 'error',
|
||||
message,
|
||||
sticky: false,
|
||||
title
|
||||
});
|
||||
}
|
||||
pushError (title, message) {
|
||||
this.push({
|
||||
class: 'error',
|
||||
message,
|
||||
sticky: false,
|
||||
title
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Shorthand method for pushing success messages
|
||||
@@ -81,35 +77,33 @@ class Alerts {
|
||||
* @param {String} title The title
|
||||
* @param {String} message The message
|
||||
*/
|
||||
pushSuccess(title, message) {
|
||||
this.push({
|
||||
class: 'success',
|
||||
message,
|
||||
sticky: false,
|
||||
title
|
||||
});
|
||||
}
|
||||
pushSuccess (title, message) {
|
||||
this.push({
|
||||
class: 'success',
|
||||
message,
|
||||
sticky: false,
|
||||
title
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Close an alert
|
||||
*
|
||||
* @param {Integer} uid The unique ID of the alert
|
||||
*/
|
||||
close(uid) {
|
||||
close (uid) {
|
||||
let self = this
|
||||
|
||||
let self = this;
|
||||
let nAlertIdx = _.findIndex(self.mdl.children, ['_uid', uid])
|
||||
let nAlert = _.nth(self.mdl.children, nAlertIdx)
|
||||
|
||||
let nAlertIdx = _.findIndex(self.mdl.children, ['_uid', uid]);
|
||||
let nAlert = _.nth(self.mdl.children, nAlertIdx);
|
||||
if (nAlertIdx >= 0 && nAlert) {
|
||||
nAlert.class += ' exit'
|
||||
Vue.set(self.mdl.children, nAlertIdx, nAlert)
|
||||
_.delay(() => {
|
||||
self.mdl.children.splice(nAlertIdx, 1)
|
||||
}, 500)
|
||||
}
|
||||
}
|
||||
|
||||
if(nAlertIdx >= 0 && nAlert) {
|
||||
nAlert.class += ' exit';
|
||||
Vue.set(self.mdl.children, nAlertIdx, nAlert);
|
||||
_.delay(() => {
|
||||
self.mdl.children.splice(nAlertIdx, 1);
|
||||
}, 500);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -1,78 +1,74 @@
|
||||
|
||||
let modelist = ace.require("ace/ext/modelist");
|
||||
let codeEditor = null;
|
||||
let modelist = ace.require('ace/ext/modelist')
|
||||
let codeEditor = null
|
||||
|
||||
// ACE - Mode Loader
|
||||
|
||||
let modelistLoaded = [];
|
||||
let modelistLoaded = []
|
||||
let loadAceMode = (m) => {
|
||||
return $.ajax({
|
||||
url: '/js/ace/mode-' + m + '.js',
|
||||
dataType: "script",
|
||||
cache: true,
|
||||
beforeSend: () => {
|
||||
if(_.includes(modelistLoaded, m)) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
success: () => {
|
||||
modelistLoaded.push(m);
|
||||
}
|
||||
});
|
||||
};
|
||||
return $.ajax({
|
||||
url: '/js/ace/mode-' + m + '.js',
|
||||
dataType: 'script',
|
||||
cache: true,
|
||||
beforeSend: () => {
|
||||
if (_.includes(modelistLoaded, m)) {
|
||||
return false
|
||||
}
|
||||
},
|
||||
success: () => {
|
||||
modelistLoaded.push(m)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Vue Code Block instance
|
||||
|
||||
let vueCodeBlock = new Vue({
|
||||
el: '#modal-editor-codeblock',
|
||||
data: {
|
||||
modes: modelist.modesByName,
|
||||
modeSelected: 'text',
|
||||
initContent: ''
|
||||
},
|
||||
watch: {
|
||||
modeSelected: (val, oldVal) => {
|
||||
loadAceMode(val).done(() => {
|
||||
ace.require("ace/mode/" + val);
|
||||
codeEditor.getSession().setMode("ace/mode/" + val);
|
||||
});
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
open: (ev) => {
|
||||
el: '#modal-editor-codeblock',
|
||||
data: {
|
||||
modes: modelist.modesByName,
|
||||
modeSelected: 'text',
|
||||
initContent: ''
|
||||
},
|
||||
watch: {
|
||||
modeSelected: (val, oldVal) => {
|
||||
loadAceMode(val).done(() => {
|
||||
ace.require('ace/mode/' + val)
|
||||
codeEditor.getSession().setMode('ace/mode/' + val)
|
||||
})
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
open: (ev) => {
|
||||
$('#modal-editor-codeblock').addClass('is-active')
|
||||
|
||||
$('#modal-editor-codeblock').addClass('is-active');
|
||||
_.delay(() => {
|
||||
codeEditor = ace.edit('codeblock-editor')
|
||||
codeEditor.setTheme('ace/theme/tomorrow_night')
|
||||
codeEditor.getSession().setMode('ace/mode/' + vueCodeBlock.modeSelected)
|
||||
codeEditor.setOption('fontSize', '14px')
|
||||
codeEditor.setOption('hScrollBarAlwaysVisible', false)
|
||||
codeEditor.setOption('wrap', true)
|
||||
|
||||
_.delay(() => {
|
||||
codeEditor = ace.edit("codeblock-editor");
|
||||
codeEditor.setTheme("ace/theme/tomorrow_night");
|
||||
codeEditor.getSession().setMode("ace/mode/" + vueCodeBlock.modeSelected);
|
||||
codeEditor.setOption('fontSize', '14px');
|
||||
codeEditor.setOption('hScrollBarAlwaysVisible', false);
|
||||
codeEditor.setOption('wrap', true);
|
||||
codeEditor.setValue(vueCodeBlock.initContent)
|
||||
|
||||
codeEditor.setValue(vueCodeBlock.initContent);
|
||||
codeEditor.focus()
|
||||
codeEditor.renderer.updateFull()
|
||||
}, 300)
|
||||
},
|
||||
cancel: (ev) => {
|
||||
mdeModalOpenState = false
|
||||
$('#modal-editor-codeblock').removeClass('is-active')
|
||||
vueCodeBlock.initContent = ''
|
||||
},
|
||||
insertCode: (ev) => {
|
||||
if (mde.codemirror.doc.somethingSelected()) {
|
||||
mde.codemirror.execCommand('singleSelection')
|
||||
}
|
||||
let codeBlockText = '\n```' + vueCodeBlock.modeSelected + '\n' + codeEditor.getValue() + '\n```\n'
|
||||
|
||||
codeEditor.focus();
|
||||
codeEditor.renderer.updateFull();
|
||||
}, 300);
|
||||
|
||||
},
|
||||
cancel: (ev) => {
|
||||
mdeModalOpenState = false;
|
||||
$('#modal-editor-codeblock').removeClass('is-active');
|
||||
vueCodeBlock.initContent = '';
|
||||
},
|
||||
insertCode: (ev) => {
|
||||
|
||||
if(mde.codemirror.doc.somethingSelected()) {
|
||||
mde.codemirror.execCommand('singleSelection');
|
||||
}
|
||||
let codeBlockText = '\n```' + vueCodeBlock.modeSelected + '\n' + codeEditor.getValue() + '\n```\n';
|
||||
|
||||
mde.codemirror.doc.replaceSelection(codeBlockText);
|
||||
vueCodeBlock.cancel();
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
mde.codemirror.doc.replaceSelection(codeBlockText)
|
||||
vueCodeBlock.cancel()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@@ -1,365 +1,351 @@
|
||||
|
||||
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: {
|
||||
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');
|
||||
},
|
||||
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) => {
|
||||
selectFile: (fileId) => {
|
||||
vueFile.currentFile = fileId
|
||||
},
|
||||
insertFileLink: (ev) => {
|
||||
if (mde.codemirror.doc.somethingSelected()) {
|
||||
mde.codemirror.execCommand('singleSelection')
|
||||
}
|
||||
|
||||
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 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 + '")'
|
||||
|
||||
let fileText = '[' + selFile.titleGuess + '](/uploads/' + selFile.normalizedPath + ' "' + selFile.titleGuess + '")';
|
||||
|
||||
mde.codemirror.doc.replaceSelection(fileText);
|
||||
vueFile.cancel();
|
||||
|
||||
},
|
||||
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) => {
|
||||
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))
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
if(_.isEmpty(vueFile.newFolderName) || !regFolderName.test(vueFile.newFolderName)) {
|
||||
vueFile.newFolderError = true;
|
||||
return;
|
||||
}
|
||||
vueFile.newFolderDiscard()
|
||||
vueFile.isLoadingText = 'Creating new folder...'
|
||||
vueFile.isLoading = true
|
||||
|
||||
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;
|
||||
});
|
||||
});
|
||||
|
||||
},
|
||||
Vue.nextTick(() => {
|
||||
socket.emit('uploadsCreateFolder', { foldername: vueFile.newFolderName }, (data) => {
|
||||
vueFile.folders = data
|
||||
vueFile.currentFolder = vueFile.newFolderName
|
||||
vueFile.files = []
|
||||
vueFile.isLoading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
// -------------------------------------------
|
||||
// RENAME FILE
|
||||
// -------------------------------------------
|
||||
|
||||
renameFile: () => {
|
||||
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
|
||||
|
||||
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);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
},
|
||||
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);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
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();
|
||||
});
|
||||
});
|
||||
},
|
||||
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();
|
||||
},
|
||||
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();
|
||||
});
|
||||
});
|
||||
},
|
||||
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);
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
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) => {
|
||||
waitChangeComplete: (oldAmount, expectChange) => {
|
||||
expectChange = (_.isBoolean(expectChange)) ? expectChange : true
|
||||
|
||||
expectChange = (_.isBoolean(expectChange)) ? expectChange : true;
|
||||
vueFile.postUploadChecks++
|
||||
vueFile.isLoadingText = 'Processing...'
|
||||
|
||||
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);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
},
|
||||
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);
|
||||
}
|
||||
};
|
||||
});
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
$.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
|
||||
|
||||
let curFileAmount = vueFile.files.length;
|
||||
$(ev.currentTarget).simpleUpload('/uploads/file', {
|
||||
|
||||
$(ev.currentTarget).simpleUpload("/uploads/file", {
|
||||
name: 'binfile',
|
||||
data: {
|
||||
folder: vueFile.currentFolder
|
||||
},
|
||||
limit: 20,
|
||||
expect: 'json',
|
||||
maxFileSize: 0,
|
||||
|
||||
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
|
||||
},
|
||||
|
||||
init: (totalUploads) => {
|
||||
vueFile.uploadSucceeded = false;
|
||||
vueFile.isLoadingText = 'Preparing to upload...';
|
||||
vueFile.isLoading = true;
|
||||
},
|
||||
progress: (progress) => {
|
||||
vueFile.isLoadingText = 'Uploading...' + Math.round(progress) + '%'
|
||||
},
|
||||
|
||||
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)
|
||||
}
|
||||
},
|
||||
|
||||
success: (data) => {
|
||||
if(data.ok) {
|
||||
error: (error) => {
|
||||
alerts.pushError(error.message, this.upload.file.name)
|
||||
},
|
||||
|
||||
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;
|
||||
}
|
||||
finish: () => {
|
||||
if (vueFile.uploadSucceeded) {
|
||||
vueFile.waitChangeComplete(curFileAmount, true)
|
||||
} else {
|
||||
vueFile.isLoading = false
|
||||
}
|
||||
}
|
||||
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
})
|
||||
})
|
||||
|
@@ -1,412 +1,396 @@
|
||||
|
||||
let vueImage = new Vue({
|
||||
el: '#modal-editor-image',
|
||||
data: {
|
||||
isLoading: false,
|
||||
isLoadingText: '',
|
||||
newFolderName: '',
|
||||
newFolderShow: false,
|
||||
newFolderError: false,
|
||||
fetchFromUrlURL: '',
|
||||
fetchFromUrlShow: false,
|
||||
folders: [],
|
||||
currentFolder: '',
|
||||
currentImage: '',
|
||||
currentAlign: 'left',
|
||||
images: [],
|
||||
uploadSucceeded: false,
|
||||
postUploadChecks: 0,
|
||||
renameImageShow: false,
|
||||
renameImageId: '',
|
||||
renameImageFilename: '',
|
||||
deleteImageShow: false,
|
||||
deleteImageId: '',
|
||||
deleteImageFilename: ''
|
||||
},
|
||||
methods: {
|
||||
el: '#modal-editor-image',
|
||||
data: {
|
||||
isLoading: false,
|
||||
isLoadingText: '',
|
||||
newFolderName: '',
|
||||
newFolderShow: false,
|
||||
newFolderError: false,
|
||||
fetchFromUrlURL: '',
|
||||
fetchFromUrlShow: false,
|
||||
folders: [],
|
||||
currentFolder: '',
|
||||
currentImage: '',
|
||||
currentAlign: 'left',
|
||||
images: [],
|
||||
uploadSucceeded: false,
|
||||
postUploadChecks: 0,
|
||||
renameImageShow: false,
|
||||
renameImageId: '',
|
||||
renameImageFilename: '',
|
||||
deleteImageShow: false,
|
||||
deleteImageId: '',
|
||||
deleteImageFilename: ''
|
||||
},
|
||||
methods: {
|
||||
|
||||
open: () => {
|
||||
mdeModalOpenState = true;
|
||||
$('#modal-editor-image').addClass('is-active');
|
||||
vueImage.refreshFolders();
|
||||
},
|
||||
cancel: (ev) => {
|
||||
mdeModalOpenState = false;
|
||||
$('#modal-editor-image').removeClass('is-active');
|
||||
},
|
||||
open: () => {
|
||||
mdeModalOpenState = true
|
||||
$('#modal-editor-image').addClass('is-active')
|
||||
vueImage.refreshFolders()
|
||||
},
|
||||
cancel: (ev) => {
|
||||
mdeModalOpenState = false
|
||||
$('#modal-editor-image').removeClass('is-active')
|
||||
},
|
||||
|
||||
// -------------------------------------------
|
||||
// INSERT IMAGE
|
||||
// -------------------------------------------
|
||||
|
||||
selectImage: (imageId) => {
|
||||
vueImage.currentImage = imageId;
|
||||
},
|
||||
insertImage: (ev) => {
|
||||
selectImage: (imageId) => {
|
||||
vueImage.currentImage = imageId
|
||||
},
|
||||
insertImage: (ev) => {
|
||||
if (mde.codemirror.doc.somethingSelected()) {
|
||||
mde.codemirror.execCommand('singleSelection')
|
||||
}
|
||||
|
||||
if(mde.codemirror.doc.somethingSelected()) {
|
||||
mde.codemirror.execCommand('singleSelection');
|
||||
}
|
||||
let selImage = _.find(vueImage.images, ['_id', vueImage.currentImage])
|
||||
selImage.normalizedPath = (selImage.folder === 'f:') ? selImage.filename : selImage.folder.slice(2) + '/' + selImage.filename
|
||||
selImage.titleGuess = _.startCase(selImage.basename)
|
||||
|
||||
let selImage = _.find(vueImage.images, ['_id', vueImage.currentImage]);
|
||||
selImage.normalizedPath = (selImage.folder === 'f:') ? selImage.filename : selImage.folder.slice(2) + '/' + selImage.filename;
|
||||
selImage.titleGuess = _.startCase(selImage.basename);
|
||||
let imageText = ''
|
||||
switch (vueImage.currentAlign) {
|
||||
case 'center':
|
||||
imageText += '{.align-center}'
|
||||
break
|
||||
case 'right':
|
||||
imageText += '{.align-right}'
|
||||
break
|
||||
case 'logo':
|
||||
imageText += '{.pagelogo}'
|
||||
break
|
||||
}
|
||||
|
||||
let imageText = '';
|
||||
switch(vueImage.currentAlign) {
|
||||
case 'center':
|
||||
imageText += '{.align-center}';
|
||||
break;
|
||||
case 'right':
|
||||
imageText += '{.align-right}';
|
||||
break;
|
||||
case 'logo':
|
||||
imageText += '{.pagelogo}';
|
||||
break;
|
||||
}
|
||||
|
||||
mde.codemirror.doc.replaceSelection(imageText);
|
||||
vueImage.cancel();
|
||||
|
||||
},
|
||||
mde.codemirror.doc.replaceSelection(imageText)
|
||||
vueImage.cancel()
|
||||
},
|
||||
|
||||
// -------------------------------------------
|
||||
// NEW FOLDER
|
||||
// -------------------------------------------
|
||||
|
||||
newFolder: (ev) => {
|
||||
vueImage.newFolderName = '';
|
||||
vueImage.newFolderError = false;
|
||||
vueImage.newFolderShow = true;
|
||||
_.delay(() => { $('#txt-editor-image-newfoldername').focus(); }, 400);
|
||||
},
|
||||
newFolderDiscard: (ev) => {
|
||||
vueImage.newFolderShow = false;
|
||||
},
|
||||
newFolderCreate: (ev) => {
|
||||
newFolder: (ev) => {
|
||||
vueImage.newFolderName = ''
|
||||
vueImage.newFolderError = false
|
||||
vueImage.newFolderShow = true
|
||||
_.delay(() => { $('#txt-editor-image-newfoldername').focus() }, 400)
|
||||
},
|
||||
newFolderDiscard: (ev) => {
|
||||
vueImage.newFolderShow = false
|
||||
},
|
||||
newFolderCreate: (ev) => {
|
||||
let regFolderName = new RegExp('^[a-z0-9][a-z0-9\-]*[a-z0-9]$')
|
||||
vueImage.newFolderName = _.kebabCase(_.trim(vueImage.newFolderName))
|
||||
|
||||
let regFolderName = new RegExp("^[a-z0-9][a-z0-9\-]*[a-z0-9]$");
|
||||
vueImage.newFolderName = _.kebabCase(_.trim(vueImage.newFolderName));
|
||||
if (_.isEmpty(vueImage.newFolderName) || !regFolderName.test(vueImage.newFolderName)) {
|
||||
vueImage.newFolderError = true
|
||||
return
|
||||
}
|
||||
|
||||
if(_.isEmpty(vueImage.newFolderName) || !regFolderName.test(vueImage.newFolderName)) {
|
||||
vueImage.newFolderError = true;
|
||||
return;
|
||||
}
|
||||
vueImage.newFolderDiscard()
|
||||
vueImage.isLoadingText = 'Creating new folder...'
|
||||
vueImage.isLoading = true
|
||||
|
||||
vueImage.newFolderDiscard();
|
||||
vueImage.isLoadingText = 'Creating new folder...';
|
||||
vueImage.isLoading = true;
|
||||
|
||||
Vue.nextTick(() => {
|
||||
socket.emit('uploadsCreateFolder', { foldername: vueImage.newFolderName }, (data) => {
|
||||
vueImage.folders = data;
|
||||
vueImage.currentFolder = vueImage.newFolderName;
|
||||
vueImage.images = [];
|
||||
vueImage.isLoading = false;
|
||||
});
|
||||
});
|
||||
|
||||
},
|
||||
Vue.nextTick(() => {
|
||||
socket.emit('uploadsCreateFolder', { foldername: vueImage.newFolderName }, (data) => {
|
||||
vueImage.folders = data
|
||||
vueImage.currentFolder = vueImage.newFolderName
|
||||
vueImage.images = []
|
||||
vueImage.isLoading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
// -------------------------------------------
|
||||
// FETCH FROM URL
|
||||
// -------------------------------------------
|
||||
|
||||
fetchFromUrl: (ev) => {
|
||||
vueImage.fetchFromUrlURL = '';
|
||||
vueImage.fetchFromUrlShow = true;
|
||||
_.delay(() => { $('#txt-editor-image-fetchurl').focus(); }, 400);
|
||||
},
|
||||
fetchFromUrlDiscard: (ev) => {
|
||||
vueImage.fetchFromUrlShow = false;
|
||||
},
|
||||
fetchFromUrlGo: (ev) => {
|
||||
|
||||
vueImage.fetchFromUrlDiscard();
|
||||
vueImage.isLoadingText = 'Fetching image...';
|
||||
vueImage.isLoading = true;
|
||||
fetchFromUrl: (ev) => {
|
||||
vueImage.fetchFromUrlURL = ''
|
||||
vueImage.fetchFromUrlShow = true
|
||||
_.delay(() => { $('#txt-editor-image-fetchurl').focus() }, 400)
|
||||
},
|
||||
fetchFromUrlDiscard: (ev) => {
|
||||
vueImage.fetchFromUrlShow = false
|
||||
},
|
||||
fetchFromUrlGo: (ev) => {
|
||||
vueImage.fetchFromUrlDiscard()
|
||||
vueImage.isLoadingText = 'Fetching image...'
|
||||
vueImage.isLoading = true
|
||||
|
||||
Vue.nextTick(() => {
|
||||
socket.emit('uploadsFetchFileFromURL', { folder: vueImage.currentFolder, fetchUrl: vueImage.fetchFromUrlURL }, (data) => {
|
||||
if(data.ok) {
|
||||
vueImage.waitChangeComplete(vueImage.images.length, true);
|
||||
} else {
|
||||
vueImage.isLoading = false;
|
||||
alerts.pushError('Upload error', data.msg);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
},
|
||||
Vue.nextTick(() => {
|
||||
socket.emit('uploadsFetchFileFromURL', { folder: vueImage.currentFolder, fetchUrl: vueImage.fetchFromUrlURL }, (data) => {
|
||||
if (data.ok) {
|
||||
vueImage.waitChangeComplete(vueImage.images.length, true)
|
||||
} else {
|
||||
vueImage.isLoading = false
|
||||
alerts.pushError('Upload error', data.msg)
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
// -------------------------------------------
|
||||
// RENAME IMAGE
|
||||
// -------------------------------------------
|
||||
|
||||
renameImage: () => {
|
||||
renameImage: () => {
|
||||
let c = _.find(vueImage.images, ['_id', vueImage.renameImageId ])
|
||||
vueImage.renameImageFilename = c.basename || ''
|
||||
vueImage.renameImageShow = true
|
||||
_.delay(() => {
|
||||
$('#txt-editor-image-rename').focus()
|
||||
_.defer(() => { $('#txt-editor-image-rename').select() })
|
||||
}, 400)
|
||||
},
|
||||
renameImageDiscard: () => {
|
||||
vueImage.renameImageShow = false
|
||||
},
|
||||
renameImageGo: () => {
|
||||
vueImage.renameImageDiscard()
|
||||
vueImage.isLoadingText = 'Renaming image...'
|
||||
vueImage.isLoading = true
|
||||
|
||||
let c = _.find(vueImage.images, ['_id', vueImage.renameImageId ]);
|
||||
vueImage.renameImageFilename = c.basename || '';
|
||||
vueImage.renameImageShow = true;
|
||||
_.delay(() => {
|
||||
$('#txt-editor-image-rename').focus();
|
||||
_.defer(() => { $('#txt-editor-image-rename').select(); });
|
||||
}, 400);
|
||||
},
|
||||
renameImageDiscard: () => {
|
||||
vueImage.renameImageShow = false;
|
||||
},
|
||||
renameImageGo: () => {
|
||||
|
||||
vueImage.renameImageDiscard();
|
||||
vueImage.isLoadingText = 'Renaming image...';
|
||||
vueImage.isLoading = true;
|
||||
|
||||
Vue.nextTick(() => {
|
||||
socket.emit('uploadsRenameFile', { uid: vueImage.renameImageId, folder: vueImage.currentFolder, filename: vueImage.renameImageFilename }, (data) => {
|
||||
if(data.ok) {
|
||||
vueImage.waitChangeComplete(vueImage.images.length, false);
|
||||
} else {
|
||||
vueImage.isLoading = false;
|
||||
alerts.pushError('Rename error', data.msg);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
},
|
||||
Vue.nextTick(() => {
|
||||
socket.emit('uploadsRenameFile', { uid: vueImage.renameImageId, folder: vueImage.currentFolder, filename: vueImage.renameImageFilename }, (data) => {
|
||||
if (data.ok) {
|
||||
vueImage.waitChangeComplete(vueImage.images.length, false)
|
||||
} else {
|
||||
vueImage.isLoading = false
|
||||
alerts.pushError('Rename error', data.msg)
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
// -------------------------------------------
|
||||
// MOVE IMAGE
|
||||
// -------------------------------------------
|
||||
|
||||
moveImage: (uid, fld) => {
|
||||
vueImage.isLoadingText = 'Moving image...';
|
||||
vueImage.isLoading = true;
|
||||
Vue.nextTick(() => {
|
||||
socket.emit('uploadsMoveFile', { uid, folder: fld }, (data) => {
|
||||
if(data.ok) {
|
||||
vueImage.loadImages();
|
||||
} else {
|
||||
vueImage.isLoading = false;
|
||||
alerts.pushError('Rename error', data.msg);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
moveImage: (uid, fld) => {
|
||||
vueImage.isLoadingText = 'Moving image...'
|
||||
vueImage.isLoading = true
|
||||
Vue.nextTick(() => {
|
||||
socket.emit('uploadsMoveFile', { uid, folder: fld }, (data) => {
|
||||
if (data.ok) {
|
||||
vueImage.loadImages()
|
||||
} else {
|
||||
vueImage.isLoading = false
|
||||
alerts.pushError('Rename error', data.msg)
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
// -------------------------------------------
|
||||
// DELETE IMAGE
|
||||
// -------------------------------------------
|
||||
|
||||
deleteImageWarn: (show) => {
|
||||
if(show) {
|
||||
let c = _.find(vueImage.images, ['_id', vueImage.deleteImageId ]);
|
||||
vueImage.deleteImageFilename = c.filename || 'this image';
|
||||
}
|
||||
vueImage.deleteImageShow = show;
|
||||
},
|
||||
deleteImageGo: () => {
|
||||
vueImage.deleteImageWarn(false);
|
||||
vueImage.isLoadingText = 'Deleting image...';
|
||||
vueImage.isLoading = true;
|
||||
Vue.nextTick(() => {
|
||||
socket.emit('uploadsDeleteFile', { uid: vueImage.deleteImageId }, (data) => {
|
||||
vueImage.loadImages();
|
||||
});
|
||||
});
|
||||
},
|
||||
deleteImageWarn: (show) => {
|
||||
if (show) {
|
||||
let c = _.find(vueImage.images, ['_id', vueImage.deleteImageId ])
|
||||
vueImage.deleteImageFilename = c.filename || 'this image'
|
||||
}
|
||||
vueImage.deleteImageShow = show
|
||||
},
|
||||
deleteImageGo: () => {
|
||||
vueImage.deleteImageWarn(false)
|
||||
vueImage.isLoadingText = 'Deleting image...'
|
||||
vueImage.isLoading = true
|
||||
Vue.nextTick(() => {
|
||||
socket.emit('uploadsDeleteFile', { uid: vueImage.deleteImageId }, (data) => {
|
||||
vueImage.loadImages()
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
// -------------------------------------------
|
||||
// LOAD FROM REMOTE
|
||||
// -------------------------------------------
|
||||
|
||||
selectFolder: (fldName) => {
|
||||
vueImage.currentFolder = fldName;
|
||||
vueImage.loadImages();
|
||||
},
|
||||
selectFolder: (fldName) => {
|
||||
vueImage.currentFolder = fldName
|
||||
vueImage.loadImages()
|
||||
},
|
||||
|
||||
refreshFolders: () => {
|
||||
vueImage.isLoadingText = 'Fetching folders list...';
|
||||
vueImage.isLoading = true;
|
||||
vueImage.currentFolder = '';
|
||||
vueImage.currentImage = '';
|
||||
Vue.nextTick(() => {
|
||||
socket.emit('uploadsGetFolders', { }, (data) => {
|
||||
vueImage.folders = data;
|
||||
vueImage.loadImages();
|
||||
});
|
||||
});
|
||||
},
|
||||
refreshFolders: () => {
|
||||
vueImage.isLoadingText = 'Fetching folders list...'
|
||||
vueImage.isLoading = true
|
||||
vueImage.currentFolder = ''
|
||||
vueImage.currentImage = ''
|
||||
Vue.nextTick(() => {
|
||||
socket.emit('uploadsGetFolders', { }, (data) => {
|
||||
vueImage.folders = data
|
||||
vueImage.loadImages()
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
loadImages: (silent) => {
|
||||
if(!silent) {
|
||||
vueImage.isLoadingText = 'Fetching images...';
|
||||
vueImage.isLoading = true;
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
Vue.nextTick(() => {
|
||||
socket.emit('uploadsGetImages', { folder: vueImage.currentFolder }, (data) => {
|
||||
vueImage.images = data;
|
||||
if(!silent) {
|
||||
vueImage.isLoading = false;
|
||||
}
|
||||
vueImage.attachContextMenus();
|
||||
resolve(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
loadImages: (silent) => {
|
||||
if (!silent) {
|
||||
vueImage.isLoadingText = 'Fetching images...'
|
||||
vueImage.isLoading = true
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
Vue.nextTick(() => {
|
||||
socket.emit('uploadsGetImages', { folder: vueImage.currentFolder }, (data) => {
|
||||
vueImage.images = data
|
||||
if (!silent) {
|
||||
vueImage.isLoading = false
|
||||
}
|
||||
vueImage.attachContextMenus()
|
||||
resolve(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
waitChangeComplete: (oldAmount, expectChange) => {
|
||||
waitChangeComplete: (oldAmount, expectChange) => {
|
||||
expectChange = (_.isBoolean(expectChange)) ? expectChange : true
|
||||
|
||||
expectChange = (_.isBoolean(expectChange)) ? expectChange : true;
|
||||
vueImage.postUploadChecks++
|
||||
vueImage.isLoadingText = 'Processing...'
|
||||
|
||||
vueImage.postUploadChecks++;
|
||||
vueImage.isLoadingText = 'Processing...';
|
||||
|
||||
Vue.nextTick(() => {
|
||||
vueImage.loadImages(true).then(() => {
|
||||
if((vueImage.images.length !== oldAmount) === expectChange) {
|
||||
vueImage.postUploadChecks = 0;
|
||||
vueImage.isLoading = false;
|
||||
} else if(vueImage.postUploadChecks > 5) {
|
||||
vueImage.postUploadChecks = 0;
|
||||
vueImage.isLoading = false;
|
||||
alerts.pushError('Unable to fetch updated listing', 'Try again later');
|
||||
} else {
|
||||
_.delay(() => {
|
||||
vueImage.waitChangeComplete(oldAmount, expectChange);
|
||||
}, 1500);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
},
|
||||
Vue.nextTick(() => {
|
||||
vueImage.loadImages(true).then(() => {
|
||||
if ((vueImage.images.length !== oldAmount) === expectChange) {
|
||||
vueImage.postUploadChecks = 0
|
||||
vueImage.isLoading = false
|
||||
} else if (vueImage.postUploadChecks > 5) {
|
||||
vueImage.postUploadChecks = 0
|
||||
vueImage.isLoading = false
|
||||
alerts.pushError('Unable to fetch updated listing', 'Try again later')
|
||||
} else {
|
||||
_.delay(() => {
|
||||
vueImage.waitChangeComplete(oldAmount, expectChange)
|
||||
}, 1500)
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
// -------------------------------------------
|
||||
// IMAGE CONTEXT MENU
|
||||
// -------------------------------------------
|
||||
|
||||
attachContextMenus: () => {
|
||||
|
||||
let moveFolders = _.map(vueImage.folders, (f) => {
|
||||
return {
|
||||
name: (f !== '') ? f : '/ (root)',
|
||||
icon: 'fa-folder',
|
||||
callback: (key, opt) => {
|
||||
let moveImageId = _.toString($(opt.$trigger).data('uid'));
|
||||
let moveImageDestFolder = _.nth(vueImage.folders, key);
|
||||
vueImage.moveImage(moveImageId, moveImageDestFolder);
|
||||
}
|
||||
};
|
||||
});
|
||||
attachContextMenus: () => {
|
||||
let moveFolders = _.map(vueImage.folders, (f) => {
|
||||
return {
|
||||
name: (f !== '') ? f : '/ (root)',
|
||||
icon: 'fa-folder',
|
||||
callback: (key, opt) => {
|
||||
let moveImageId = _.toString($(opt.$trigger).data('uid'))
|
||||
let moveImageDestFolder = _.nth(vueImage.folders, key)
|
||||
vueImage.moveImage(moveImageId, moveImageDestFolder)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
$.contextMenu('destroy', '.editor-modal-image-choices > figure');
|
||||
$.contextMenu({
|
||||
selector: '.editor-modal-image-choices > figure',
|
||||
appendTo: '.editor-modal-image-choices',
|
||||
position: (opt, x, y) => {
|
||||
$(opt.$trigger).addClass('is-contextopen');
|
||||
let trigPos = $(opt.$trigger).position();
|
||||
let trigDim = { w: $(opt.$trigger).width() / 2, 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) => {
|
||||
vueImage.renameImageId = _.toString(opt.$trigger[0].dataset.uid);
|
||||
vueImage.renameImage();
|
||||
}
|
||||
},
|
||||
move: {
|
||||
name: "Move to...",
|
||||
icon: "fa-folder-open-o",
|
||||
items: moveFolders
|
||||
},
|
||||
delete: {
|
||||
name: "Delete",
|
||||
icon: "fa-trash",
|
||||
callback: (key, opt) => {
|
||||
vueImage.deleteImageId = _.toString(opt.$trigger[0].dataset.uid);
|
||||
vueImage.deleteImageWarn(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
$.contextMenu('destroy', '.editor-modal-image-choices > figure')
|
||||
$.contextMenu({
|
||||
selector: '.editor-modal-image-choices > figure',
|
||||
appendTo: '.editor-modal-image-choices',
|
||||
position: (opt, x, y) => {
|
||||
$(opt.$trigger).addClass('is-contextopen')
|
||||
let trigPos = $(opt.$trigger).position()
|
||||
let trigDim = { w: $(opt.$trigger).width() / 2, 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) => {
|
||||
vueImage.renameImageId = _.toString(opt.$trigger[0].dataset.uid)
|
||||
vueImage.renameImage()
|
||||
}
|
||||
},
|
||||
move: {
|
||||
name: 'Move to...',
|
||||
icon: 'fa-folder-open-o',
|
||||
items: moveFolders
|
||||
},
|
||||
delete: {
|
||||
name: 'Delete',
|
||||
icon: 'fa-trash',
|
||||
callback: (key, opt) => {
|
||||
vueImage.deleteImageId = _.toString(opt.$trigger[0].dataset.uid)
|
||||
vueImage.deleteImageWarn(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
$('#btn-editor-image-upload input').on('change', (ev) => {
|
||||
let curImageAmount = vueImage.images.length
|
||||
|
||||
let curImageAmount = vueImage.images.length;
|
||||
$(ev.currentTarget).simpleUpload('/uploads/img', {
|
||||
|
||||
$(ev.currentTarget).simpleUpload("/uploads/img", {
|
||||
name: 'imgfile',
|
||||
data: {
|
||||
folder: vueImage.currentFolder
|
||||
},
|
||||
limit: 20,
|
||||
expect: 'json',
|
||||
allowedExts: ['jpg', 'jpeg', 'gif', 'png', 'webp'],
|
||||
allowedTypes: ['image/png', 'image/jpeg', 'image/gif', 'image/webp'],
|
||||
maxFileSize: 3145728, // max 3 MB
|
||||
|
||||
name: 'imgfile',
|
||||
data: {
|
||||
folder: vueImage.currentFolder
|
||||
},
|
||||
limit: 20,
|
||||
expect: 'json',
|
||||
allowedExts: ["jpg", "jpeg", "gif", "png", "webp"],
|
||||
allowedTypes: ['image/png', 'image/jpeg', 'image/gif', 'image/webp'],
|
||||
maxFileSize: 3145728, // max 3 MB
|
||||
init: (totalUploads) => {
|
||||
vueImage.uploadSucceeded = false
|
||||
vueImage.isLoadingText = 'Preparing to upload...'
|
||||
vueImage.isLoading = true
|
||||
},
|
||||
|
||||
init: (totalUploads) => {
|
||||
vueImage.uploadSucceeded = false;
|
||||
vueImage.isLoadingText = 'Preparing to upload...';
|
||||
vueImage.isLoading = true;
|
||||
},
|
||||
progress: (progress) => {
|
||||
vueImage.isLoadingText = 'Uploading...' + Math.round(progress) + '%'
|
||||
},
|
||||
|
||||
progress: (progress) => {
|
||||
vueImage.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.'
|
||||
})
|
||||
vueImage.uploadSucceeded = true
|
||||
}
|
||||
} else {
|
||||
vueImage.uploadSucceeded = true
|
||||
}
|
||||
} else {
|
||||
alerts.pushError('Upload error', data.msg)
|
||||
}
|
||||
},
|
||||
|
||||
success: (data) => {
|
||||
if(data.ok) {
|
||||
error: (error) => {
|
||||
alerts.pushError(error.message, this.upload.file.name)
|
||||
},
|
||||
|
||||
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.'
|
||||
});
|
||||
vueImage.uploadSucceeded = true;
|
||||
}
|
||||
} else {
|
||||
vueImage.uploadSucceeded = true;
|
||||
}
|
||||
finish: () => {
|
||||
if (vueImage.uploadSucceeded) {
|
||||
vueImage.waitChangeComplete(curImageAmount, true)
|
||||
} else {
|
||||
vueImage.isLoading = false
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
alerts.pushError('Upload error', data.msg);
|
||||
}
|
||||
},
|
||||
|
||||
error: (error) => {
|
||||
alerts.pushError(error.message, this.upload.file.name);
|
||||
},
|
||||
|
||||
finish: () => {
|
||||
if(vueImage.uploadSucceeded) {
|
||||
vueImage.waitChangeComplete(curImageAmount, true);
|
||||
} else {
|
||||
vueImage.isLoading = false;
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
})
|
||||
})
|
||||
|
@@ -1,49 +1,47 @@
|
||||
|
||||
const videoRules = {
|
||||
'youtube': new RegExp(/(?:(?:youtu\.be\/|v\/|vi\/|u\/\w\/|embed\/)|(?:(?:watch)?\?v(?:i)?=|\&v(?:i)?=))([^#\&\?]*).*/, 'i'),
|
||||
'vimeo': new RegExp(/vimeo.com\/(?:channels\/(?:\w+\/)?|groups\/(?:[^\/]*)\/videos\/|album\/(?:\d+)\/video\/|)(\d+)(?:$|\/|\?)/, 'i'),
|
||||
'dailymotion': new RegExp(/(?:dailymotion\.com(?:\/embed)?(?:\/video|\/hub)|dai\.ly)\/([0-9a-z]+)(?:[\-_0-9a-zA-Z]+(?:#video=)?([a-z0-9]+)?)?/, 'i')
|
||||
};
|
||||
'youtube': new RegExp(/(?:(?:youtu\.be\/|v\/|vi\/|u\/\w\/|embed\/)|(?:(?:watch)?\?v(?:i)?=|\&v(?:i)?=))([^#\&\?]*).*/, 'i'),
|
||||
'vimeo': new RegExp(/vimeo.com\/(?:channels\/(?:\w+\/)?|groups\/(?:[^\/]*)\/videos\/|album\/(?:\d+)\/video\/|)(\d+)(?:$|\/|\?)/, 'i'),
|
||||
'dailymotion': new RegExp(/(?:dailymotion\.com(?:\/embed)?(?:\/video|\/hub)|dai\.ly)\/([0-9a-z]+)(?:[\-_0-9a-zA-Z]+(?:#video=)?([a-z0-9]+)?)?/, 'i')
|
||||
}
|
||||
|
||||
// Vue Video instance
|
||||
|
||||
let vueVideo = new Vue({
|
||||
el: '#modal-editor-video',
|
||||
data: {
|
||||
link: ''
|
||||
},
|
||||
methods: {
|
||||
open: (ev) => {
|
||||
$('#modal-editor-video').addClass('is-active');
|
||||
$('#modal-editor-video input').focus();
|
||||
},
|
||||
cancel: (ev) => {
|
||||
mdeModalOpenState = false;
|
||||
$('#modal-editor-video').removeClass('is-active');
|
||||
vueVideo.link = '';
|
||||
},
|
||||
insertVideo: (ev) => {
|
||||
|
||||
if(mde.codemirror.doc.somethingSelected()) {
|
||||
mde.codemirror.execCommand('singleSelection');
|
||||
}
|
||||
el: '#modal-editor-video',
|
||||
data: {
|
||||
link: ''
|
||||
},
|
||||
methods: {
|
||||
open: (ev) => {
|
||||
$('#modal-editor-video').addClass('is-active')
|
||||
$('#modal-editor-video input').focus()
|
||||
},
|
||||
cancel: (ev) => {
|
||||
mdeModalOpenState = false
|
||||
$('#modal-editor-video').removeClass('is-active')
|
||||
vueVideo.link = ''
|
||||
},
|
||||
insertVideo: (ev) => {
|
||||
if (mde.codemirror.doc.somethingSelected()) {
|
||||
mde.codemirror.execCommand('singleSelection')
|
||||
}
|
||||
|
||||
// Guess video type
|
||||
|
||||
let videoType = _.findKey(videoRules, (vr) => {
|
||||
return vr.test(vueVideo.link);
|
||||
});
|
||||
if(_.isNil(videoType)) {
|
||||
videoType = 'video';
|
||||
}
|
||||
let videoType = _.findKey(videoRules, (vr) => {
|
||||
return vr.test(vueVideo.link)
|
||||
})
|
||||
if (_.isNil(videoType)) {
|
||||
videoType = 'video'
|
||||
}
|
||||
|
||||
// Insert video tag
|
||||
|
||||
let videoText = '[video](' + vueVideo.link + '){.' + videoType + '}\n';
|
||||
let videoText = '[video](' + vueVideo.link + '){.' + videoType + '}\n'
|
||||
|
||||
mde.codemirror.doc.replaceSelection(videoText);
|
||||
vueVideo.cancel();
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
mde.codemirror.doc.replaceSelection(videoText)
|
||||
vueVideo.cancel()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@@ -3,215 +3,210 @@
|
||||
// Markdown Editor
|
||||
// ====================================
|
||||
|
||||
if($('#mk-editor').length === 1) {
|
||||
if ($('#mk-editor').length === 1) {
|
||||
let mdeModalOpenState = false
|
||||
let mdeCurrentEditor = null
|
||||
|
||||
let mdeModalOpenState = false;
|
||||
let mdeCurrentEditor = null;
|
||||
Vue.filter('filesize', (v) => {
|
||||
return _.toUpper(filesize(v))
|
||||
})
|
||||
|
||||
Vue.filter('filesize', (v) => {
|
||||
return _.toUpper(filesize(v));
|
||||
});
|
||||
// =include editor-image.js
|
||||
// =include editor-file.js
|
||||
// =include editor-video.js
|
||||
// =include editor-codeblock.js
|
||||
|
||||
//=include editor-image.js
|
||||
//=include editor-file.js
|
||||
//=include editor-video.js
|
||||
//=include editor-codeblock.js
|
||||
|
||||
var mde = new SimpleMDE({
|
||||
autofocus: true,
|
||||
autoDownloadFontAwesome: false,
|
||||
element: $("#mk-editor").get(0),
|
||||
placeholder: 'Enter Markdown formatted content here...',
|
||||
spellChecker: false,
|
||||
status: false,
|
||||
toolbar: [{
|
||||
name: "bold",
|
||||
action: SimpleMDE.toggleBold,
|
||||
className: "icon-bold",
|
||||
title: "Bold",
|
||||
},
|
||||
{
|
||||
name: "italic",
|
||||
action: SimpleMDE.toggleItalic,
|
||||
className: "icon-italic",
|
||||
title: "Italic",
|
||||
},
|
||||
{
|
||||
name: "strikethrough",
|
||||
action: SimpleMDE.toggleStrikethrough,
|
||||
className: "icon-strikethrough",
|
||||
title: "Strikethrough",
|
||||
},
|
||||
'|',
|
||||
{
|
||||
name: "heading-1",
|
||||
action: SimpleMDE.toggleHeading1,
|
||||
className: "icon-header fa-header-x fa-header-1",
|
||||
title: "Big Heading",
|
||||
},
|
||||
{
|
||||
name: "heading-2",
|
||||
action: SimpleMDE.toggleHeading2,
|
||||
className: "icon-header fa-header-x fa-header-2",
|
||||
title: "Medium Heading",
|
||||
},
|
||||
{
|
||||
name: "heading-3",
|
||||
action: SimpleMDE.toggleHeading3,
|
||||
className: "icon-header fa-header-x fa-header-3",
|
||||
title: "Small Heading",
|
||||
},
|
||||
{
|
||||
name: "quote",
|
||||
action: SimpleMDE.toggleBlockquote,
|
||||
className: "icon-quote-left",
|
||||
title: "Quote",
|
||||
},
|
||||
'|',
|
||||
{
|
||||
name: "unordered-list",
|
||||
action: SimpleMDE.toggleUnorderedList,
|
||||
className: "icon-th-list",
|
||||
title: "Bullet List",
|
||||
},
|
||||
{
|
||||
name: "ordered-list",
|
||||
action: SimpleMDE.toggleOrderedList,
|
||||
className: "icon-list-ol",
|
||||
title: "Numbered List",
|
||||
},
|
||||
'|',
|
||||
{
|
||||
name: "link",
|
||||
action: (editor) => {
|
||||
/*if(!mdeModalOpenState) {
|
||||
var mde = new SimpleMDE({
|
||||
autofocus: true,
|
||||
autoDownloadFontAwesome: false,
|
||||
element: $('#mk-editor').get(0),
|
||||
placeholder: 'Enter Markdown formatted content here...',
|
||||
spellChecker: false,
|
||||
status: false,
|
||||
toolbar: [{
|
||||
name: 'bold',
|
||||
action: SimpleMDE.toggleBold,
|
||||
className: 'icon-bold',
|
||||
title: 'Bold'
|
||||
},
|
||||
{
|
||||
name: 'italic',
|
||||
action: SimpleMDE.toggleItalic,
|
||||
className: 'icon-italic',
|
||||
title: 'Italic'
|
||||
},
|
||||
{
|
||||
name: 'strikethrough',
|
||||
action: SimpleMDE.toggleStrikethrough,
|
||||
className: 'icon-strikethrough',
|
||||
title: 'Strikethrough'
|
||||
},
|
||||
'|',
|
||||
{
|
||||
name: 'heading-1',
|
||||
action: SimpleMDE.toggleHeading1,
|
||||
className: 'icon-header fa-header-x fa-header-1',
|
||||
title: 'Big Heading'
|
||||
},
|
||||
{
|
||||
name: 'heading-2',
|
||||
action: SimpleMDE.toggleHeading2,
|
||||
className: 'icon-header fa-header-x fa-header-2',
|
||||
title: 'Medium Heading'
|
||||
},
|
||||
{
|
||||
name: 'heading-3',
|
||||
action: SimpleMDE.toggleHeading3,
|
||||
className: 'icon-header fa-header-x fa-header-3',
|
||||
title: 'Small Heading'
|
||||
},
|
||||
{
|
||||
name: 'quote',
|
||||
action: SimpleMDE.toggleBlockquote,
|
||||
className: 'icon-quote-left',
|
||||
title: 'Quote'
|
||||
},
|
||||
'|',
|
||||
{
|
||||
name: 'unordered-list',
|
||||
action: SimpleMDE.toggleUnorderedList,
|
||||
className: 'icon-th-list',
|
||||
title: 'Bullet List'
|
||||
},
|
||||
{
|
||||
name: 'ordered-list',
|
||||
action: SimpleMDE.toggleOrderedList,
|
||||
className: 'icon-list-ol',
|
||||
title: 'Numbered List'
|
||||
},
|
||||
'|',
|
||||
{
|
||||
name: 'link',
|
||||
action: (editor) => {
|
||||
/* if(!mdeModalOpenState) {
|
||||
mdeModalOpenState = true;
|
||||
$('#modal-editor-link').slideToggle();
|
||||
}*/
|
||||
},
|
||||
className: "icon-link2",
|
||||
title: "Insert Link",
|
||||
},
|
||||
{
|
||||
name: "image",
|
||||
action: (editor) => {
|
||||
if(!mdeModalOpenState) {
|
||||
vueImage.open();
|
||||
}
|
||||
},
|
||||
className: "icon-image",
|
||||
title: "Insert Image",
|
||||
},
|
||||
{
|
||||
name: "file",
|
||||
action: (editor) => {
|
||||
if(!mdeModalOpenState) {
|
||||
vueFile.open();
|
||||
}
|
||||
},
|
||||
className: "icon-paper",
|
||||
title: "Insert File",
|
||||
},
|
||||
{
|
||||
name: "video",
|
||||
action: (editor) => {
|
||||
if(!mdeModalOpenState) {
|
||||
vueVideo.open();
|
||||
}
|
||||
},
|
||||
className: "icon-video-camera2",
|
||||
title: "Insert Video Player",
|
||||
},
|
||||
'|',
|
||||
{
|
||||
name: "inline-code",
|
||||
action: (editor) => {
|
||||
} */
|
||||
},
|
||||
className: 'icon-link2',
|
||||
title: 'Insert Link'
|
||||
},
|
||||
{
|
||||
name: 'image',
|
||||
action: (editor) => {
|
||||
if (!mdeModalOpenState) {
|
||||
vueImage.open()
|
||||
}
|
||||
},
|
||||
className: 'icon-image',
|
||||
title: 'Insert Image'
|
||||
},
|
||||
{
|
||||
name: 'file',
|
||||
action: (editor) => {
|
||||
if (!mdeModalOpenState) {
|
||||
vueFile.open()
|
||||
}
|
||||
},
|
||||
className: 'icon-paper',
|
||||
title: 'Insert File'
|
||||
},
|
||||
{
|
||||
name: 'video',
|
||||
action: (editor) => {
|
||||
if (!mdeModalOpenState) {
|
||||
vueVideo.open()
|
||||
}
|
||||
},
|
||||
className: 'icon-video-camera2',
|
||||
title: 'Insert Video Player'
|
||||
},
|
||||
'|',
|
||||
{
|
||||
name: 'inline-code',
|
||||
action: (editor) => {
|
||||
if (!editor.codemirror.doc.somethingSelected()) {
|
||||
return alerts.pushError('Invalid selection', 'You must select at least 1 character first.')
|
||||
}
|
||||
let curSel = editor.codemirror.doc.getSelections()
|
||||
curSel = _.map(curSel, (s) => {
|
||||
return '`' + s + '`'
|
||||
})
|
||||
editor.codemirror.doc.replaceSelections(curSel)
|
||||
},
|
||||
className: 'icon-terminal',
|
||||
title: 'Inline Code'
|
||||
},
|
||||
{
|
||||
name: 'code-block',
|
||||
action: (editor) => {
|
||||
if (!mdeModalOpenState) {
|
||||
mdeModalOpenState = true
|
||||
|
||||
if(!editor.codemirror.doc.somethingSelected()) {
|
||||
return alerts.pushError('Invalid selection','You must select at least 1 character first.');
|
||||
}
|
||||
let curSel = editor.codemirror.doc.getSelections();
|
||||
curSel = _.map(curSel, (s) => {
|
||||
return '`' + s + '`';
|
||||
});
|
||||
editor.codemirror.doc.replaceSelections(curSel);
|
||||
if (mde.codemirror.doc.somethingSelected()) {
|
||||
vueCodeBlock.initContent = mde.codemirror.doc.getSelection()
|
||||
}
|
||||
|
||||
},
|
||||
className: "icon-terminal",
|
||||
title: "Inline Code",
|
||||
},
|
||||
{
|
||||
name: "code-block",
|
||||
action: (editor) => {
|
||||
if(!mdeModalOpenState) {
|
||||
mdeModalOpenState = true;
|
||||
vueCodeBlock.open()
|
||||
}
|
||||
},
|
||||
className: 'icon-code',
|
||||
title: 'Code Block'
|
||||
},
|
||||
'|',
|
||||
{
|
||||
name: 'table',
|
||||
action: (editor) => {
|
||||
// todo
|
||||
},
|
||||
className: 'icon-table',
|
||||
title: 'Insert Table'
|
||||
},
|
||||
{
|
||||
name: 'horizontal-rule',
|
||||
action: SimpleMDE.drawHorizontalRule,
|
||||
className: 'icon-minus2',
|
||||
title: 'Horizontal Rule'
|
||||
}
|
||||
],
|
||||
shortcuts: {
|
||||
'toggleBlockquote': null,
|
||||
'toggleFullScreen': null
|
||||
}
|
||||
})
|
||||
|
||||
if(mde.codemirror.doc.somethingSelected()) {
|
||||
vueCodeBlock.initContent = mde.codemirror.doc.getSelection();
|
||||
}
|
||||
// -> Save
|
||||
|
||||
vueCodeBlock.open();
|
||||
let saveCurrentDocument = (ev) => {
|
||||
$.ajax(window.location.href, {
|
||||
data: {
|
||||
markdown: mde.value()
|
||||
},
|
||||
dataType: 'json',
|
||||
method: 'PUT'
|
||||
}).then((rData, rStatus, rXHR) => {
|
||||
if (rData.ok) {
|
||||
window.location.assign('/' + pageEntryPath)
|
||||
} else {
|
||||
alerts.pushError('Something went wrong', rData.error)
|
||||
}
|
||||
}, (rXHR, rStatus, err) => {
|
||||
alerts.pushError('Something went wrong', 'Save operation failed.')
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
className: "icon-code",
|
||||
title: "Code Block",
|
||||
},
|
||||
'|',
|
||||
{
|
||||
name: "table",
|
||||
action: (editor) => {
|
||||
//todo
|
||||
},
|
||||
className: "icon-table",
|
||||
title: "Insert Table",
|
||||
},
|
||||
{
|
||||
name: "horizontal-rule",
|
||||
action: SimpleMDE.drawHorizontalRule,
|
||||
className: "icon-minus2",
|
||||
title: "Horizontal Rule",
|
||||
}
|
||||
],
|
||||
shortcuts: {
|
||||
"toggleBlockquote": null,
|
||||
"toggleFullScreen": null
|
||||
}
|
||||
});
|
||||
$('.btn-edit-save, .btn-create-save').on('click', (ev) => {
|
||||
saveCurrentDocument(ev)
|
||||
})
|
||||
|
||||
//-> Save
|
||||
|
||||
let saveCurrentDocument = (ev) => {
|
||||
$.ajax(window.location.href, {
|
||||
data: {
|
||||
markdown: mde.value()
|
||||
},
|
||||
dataType: 'json',
|
||||
method: 'PUT'
|
||||
}).then((rData, rStatus, rXHR) => {
|
||||
if(rData.ok) {
|
||||
window.location.assign('/' + pageEntryPath);
|
||||
} else {
|
||||
alerts.pushError('Something went wrong', rData.error);
|
||||
}
|
||||
}, (rXHR, rStatus, err) => {
|
||||
alerts.pushError('Something went wrong', 'Save operation failed.');
|
||||
});
|
||||
};
|
||||
|
||||
$('.btn-edit-save, .btn-create-save').on('click', (ev) => {
|
||||
saveCurrentDocument(ev);
|
||||
});
|
||||
|
||||
$(window).bind('keydown', (ev) => {
|
||||
if (ev.ctrlKey || ev.metaKey) {
|
||||
switch (String.fromCharCode(ev.which).toLowerCase()) {
|
||||
case 's':
|
||||
ev.preventDefault();
|
||||
saveCurrentDocument(ev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
$(window).bind('keydown', (ev) => {
|
||||
if (ev.ctrlKey || ev.metaKey) {
|
||||
switch (String.fromCharCode(ev.which).toLowerCase()) {
|
||||
case 's':
|
||||
ev.preventDefault()
|
||||
saveCurrentDocument(ev)
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@@ -1,84 +1,81 @@
|
||||
"use strict";
|
||||
'use strict'
|
||||
|
||||
if($('#search-input').length) {
|
||||
if ($('#search-input').length) {
|
||||
$('#search-input').focus()
|
||||
|
||||
$('#search-input').focus();
|
||||
$('.searchresults').css('display', 'block')
|
||||
|
||||
$('.searchresults').css('display', 'block');
|
||||
|
||||
var vueHeader = new Vue({
|
||||
el: '#header-container',
|
||||
data: {
|
||||
searchq: '',
|
||||
searchres: [],
|
||||
searchsuggest: [],
|
||||
searchload: 0,
|
||||
searchactive: false,
|
||||
searchmoveidx: 0,
|
||||
searchmovekey: '',
|
||||
searchmovearr: []
|
||||
},
|
||||
watch: {
|
||||
searchq: (val, oldVal) => {
|
||||
vueHeader.searchmoveidx = 0;
|
||||
if(val.length >= 3) {
|
||||
vueHeader.searchactive = true;
|
||||
vueHeader.searchload++;
|
||||
socket.emit('search', { terms: val }, (data) => {
|
||||
vueHeader.searchres = data.match;
|
||||
vueHeader.searchsuggest = data.suggest;
|
||||
vueHeader.searchmovearr = _.concat([], vueHeader.searchres, vueHeader.searchsuggest);
|
||||
if(vueHeader.searchload > 0) { vueHeader.searchload--; }
|
||||
});
|
||||
} else {
|
||||
vueHeader.searchactive = false;
|
||||
vueHeader.searchres = [];
|
||||
vueHeader.searchsuggest = [];
|
||||
vueHeader.searchmovearr = [];
|
||||
vueHeader.searchload = 0;
|
||||
}
|
||||
},
|
||||
searchmoveidx: (val, oldVal) => {
|
||||
if(val > 0) {
|
||||
vueHeader.searchmovekey = (vueHeader.searchmovearr[val - 1]) ?
|
||||
var vueHeader = new Vue({
|
||||
el: '#header-container',
|
||||
data: {
|
||||
searchq: '',
|
||||
searchres: [],
|
||||
searchsuggest: [],
|
||||
searchload: 0,
|
||||
searchactive: false,
|
||||
searchmoveidx: 0,
|
||||
searchmovekey: '',
|
||||
searchmovearr: []
|
||||
},
|
||||
watch: {
|
||||
searchq: (val, oldVal) => {
|
||||
vueHeader.searchmoveidx = 0
|
||||
if (val.length >= 3) {
|
||||
vueHeader.searchactive = true
|
||||
vueHeader.searchload++
|
||||
socket.emit('search', { terms: val }, (data) => {
|
||||
vueHeader.searchres = data.match
|
||||
vueHeader.searchsuggest = data.suggest
|
||||
vueHeader.searchmovearr = _.concat([], vueHeader.searchres, vueHeader.searchsuggest)
|
||||
if (vueHeader.searchload > 0) { vueHeader.searchload-- }
|
||||
})
|
||||
} else {
|
||||
vueHeader.searchactive = false
|
||||
vueHeader.searchres = []
|
||||
vueHeader.searchsuggest = []
|
||||
vueHeader.searchmovearr = []
|
||||
vueHeader.searchload = 0
|
||||
}
|
||||
},
|
||||
searchmoveidx: (val, oldVal) => {
|
||||
if (val > 0) {
|
||||
vueHeader.searchmovekey = (vueHeader.searchmovearr[val - 1]) ?
|
||||
'res.' + vueHeader.searchmovearr[val - 1]._id :
|
||||
'sug.' + vueHeader.searchmovearr[val - 1];
|
||||
} else {
|
||||
vueHeader.searchmovekey = '';
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
useSuggestion: (sug) => {
|
||||
vueHeader.searchq = sug;
|
||||
},
|
||||
closeSearch: () => {
|
||||
vueHeader.searchq = '';
|
||||
},
|
||||
moveSelectSearch: () => {
|
||||
if(vueHeader.searchmoveidx < 1) { return; }
|
||||
let i = vueHeader.searchmoveidx - 1;
|
||||
'sug.' + vueHeader.searchmovearr[val - 1]
|
||||
} else {
|
||||
vueHeader.searchmovekey = ''
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
useSuggestion: (sug) => {
|
||||
vueHeader.searchq = sug
|
||||
},
|
||||
closeSearch: () => {
|
||||
vueHeader.searchq = ''
|
||||
},
|
||||
moveSelectSearch: () => {
|
||||
if (vueHeader.searchmoveidx < 1) { return }
|
||||
let i = vueHeader.searchmoveidx - 1
|
||||
|
||||
if(vueHeader.searchmovearr[i]) {
|
||||
window.location.assign('/' + vueHeader.searchmovearr[i]._id);
|
||||
} else {
|
||||
vueHeader.searchq = vueHeader.searchmovearr[i];
|
||||
}
|
||||
if (vueHeader.searchmovearr[i]) {
|
||||
window.location.assign('/' + vueHeader.searchmovearr[i]._id)
|
||||
} else {
|
||||
vueHeader.searchq = vueHeader.searchmovearr[i]
|
||||
}
|
||||
},
|
||||
moveDownSearch: () => {
|
||||
if (vueHeader.searchmoveidx < vueHeader.searchmovearr.length) {
|
||||
vueHeader.searchmoveidx++
|
||||
}
|
||||
},
|
||||
moveUpSearch: () => {
|
||||
if (vueHeader.searchmoveidx > 0) {
|
||||
vueHeader.searchmoveidx--
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
},
|
||||
moveDownSearch: () => {
|
||||
if(vueHeader.searchmoveidx < vueHeader.searchmovearr.length) {
|
||||
vueHeader.searchmoveidx++;
|
||||
}
|
||||
},
|
||||
moveUpSearch: () => {
|
||||
if(vueHeader.searchmoveidx > 0) {
|
||||
vueHeader.searchmoveidx--;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$('main').on('click', vueHeader.closeSearch);
|
||||
|
||||
}
|
||||
$('main').on('click', vueHeader.closeSearch)
|
||||
}
|
||||
|
Reference in New Issue
Block a user