Insert Image model + Uploads Folders list

This commit is contained in:
NGPixel 2016-09-18 23:03:19 -04:00
parent 405e23f01e
commit 567e1307da
14 changed files with 293 additions and 78 deletions

View File

@ -75,12 +75,15 @@ var job = new cron({
let jobs = []; let jobs = [];
let repoPath = path.resolve(ROOTPATH, appconfig.datadir.repo); let repoPath = path.resolve(ROOTPATH, appconfig.datadir.repo);
let uploadsPath = path.join(repoPath, 'uploads');
// ---------------------------------------- // ----------------------------------------
// Compile Jobs // Compile Jobs
// ---------------------------------------- // ----------------------------------------
//*****************************************
//-> Resync with Git remote //-> Resync with Git remote
//*****************************************
jobs.push(git.onReady.then(() => { jobs.push(git.onReady.then(() => {
return git.resync().then(() => { return git.resync().then(() => {
@ -140,6 +143,24 @@ var job = new cron({
}); });
})); }));
//*****************************************
//-> Refresh uploads data
//*****************************************
jobs.push(fs.readdirAsync(uploadsPath).then((ls) => {
return Promise.map(ls, (f) => {
return fs.statAsync(path.join(uploadsPath, f)).then((s) => { return { filename: f, stat: s }; });
}).filter((s) => { return s.stat.isDirectory(); }).then((arrStats) => {
ws.emit('uploadsSetFolders', {
auth: WSInternalKey,
content: _.map(arrStats, 'filename')
});
return true;
});
}));
// ---------------------------------------- // ----------------------------------------
// Run // Run
// ---------------------------------------- // ----------------------------------------

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -2,23 +2,54 @@
let vueImage = new Vue({ let vueImage = new Vue({
el: '#modal-editor-image', el: '#modal-editor-image',
data: { data: {
modeSelected: 'text' isLoading: false,
isLoadingText: '',
newFolderName: '',
newFolderShow: false,
folders: [],
currentFolder: '',
images: []
}, },
methods: { methods: {
open: () => {
mdeModalOpenState = true;
$('#modal-editor-image').slideDown();
vueImage.refreshFolders();
},
cancel: (ev) => { cancel: (ev) => {
mdeModalOpenState = false; mdeModalOpenState = false;
$('#modal-editor-image').slideUp(); $('#modal-editor-image').slideUp();
}, },
insertImage: (ev) => { newFolder: (ev) => {
vueImage.newFolderShow = true;
if(mde.codemirror.doc.somethingSelected()) { },
mde.codemirror.execCommand('singleSelection'); newFolderDiscard: (ev) => {
} vueImage.newFolderShow = false;
let codeBlockText = '\n```' + vueCodeBlock.modeSelected + '\n' + codeEditor.getValue() + '\n```\n'; },
selectFolder: (fldName) => {
mde.codemirror.doc.replaceSelection(codeBlockText); vueImage.currentFolder = fldName;
vueCodeBlock.cancel(); vueImage.loadImages();
},
refreshFolders: () => {
vueImage.isLoading = true;
vueImage.isLoadingText = 'Fetching folders list...';
vueImage.currentFolder = '';
Vue.nextTick(() => {
socket.emit('uploadsGetFolders', { }, (data) => {
vueImage.folders = data;
vueImage.loadImages();
});
});
},
loadImages: () => {
vueImage.isLoading = true;
vueImage.isLoadingText = 'Fetching images...';
Vue.nextTick(() => {
socket.emit('uploadsGetImages', { folder: vueImage.currentFolder }, (data) => {
vueImage.images = data;
vueImage.isLoading = false;
});
});
} }
} }
}); });

View File

@ -90,8 +90,7 @@ if($('#mk-editor').length === 1) {
name: "image", name: "image",
action: (editor) => { action: (editor) => {
if(!mdeModalOpenState) { if(!mdeModalOpenState) {
mdeModalOpenState = true; vueImage.open();
$('#modal-editor-image').slideDown();
} }
}, },
className: "fa fa-image", className: "fa fa-image",

View File

@ -33,6 +33,38 @@
} }
.editor-modal-load {
display: flex;
align-items: center;
opacity: 0;
transition: opacity .5s ease;
span {
font-size: 12px;
color: $blue;
}
i {
margin-left: 10px;
width: 32px;
height: 32px;
display: flex;
justify-content: center;
align-items: center;
&::before {
content: " ";
@include spinner($blue,0.5s,24px);
}
}
&.is-active {
opacity: 1;
}
}
.CodeMirror { .CodeMirror {
border-left: none; border-left: none;
border-right: none; border-right: none;

View File

@ -14,6 +14,17 @@
} }
.menu {
.menu-list a, .menu-nav a {
display: flex;
align-items: center;
}
.menu-list .icon {
margin-right: 8px
}
}
.section.is-small { .section.is-small {
padding: 20px 20px; padding: 20px 20px;
} }

View File

@ -119,7 +119,7 @@ module.exports = {
winston.error('Git remote error!'); winston.error('Git remote error!');
throw err; throw err;
}).then(() => { }).then(() => {
winston.info('[GIT] Git repository is now ready.'); winston.info('[GIT] Git repository is OK.');
return true; return true;
}); });

View File

@ -9,10 +9,43 @@ var fs = require('fs'),
* *
* @param {Object} appconfig The application configuration * @param {Object} appconfig The application configuration
*/ */
module.exports = (appconfig) => { module.exports = {
_uploadsPath: './repo/uploads',
_uploadsFolders: [],
/**
* Initialize Local Data Storage model
*
* @param {Object} appconfig The application config
* @return {Object} Local Data Storage model instance
*/
init(appconfig, skipFolderCreation = false) {
let self = this;
self._uploadsPath = path.join(ROOTPATH, appconfig.datadir.db, 'uploads');
// Create data directories // Create data directories
if(!skipFolderCreation) {
self.createBaseDirectories(appconfig);
}
return self;
},
/**
* Creates a base directories (Synchronous).
*
* @param {Object} appconfig The application config
* @return {Void} Void
*/
createBaseDirectories(appconfig) {
winston.info('[SERVER] Create data directories if they don\'t exist...');
try { try {
fs.mkdirSync(appconfig.datadir.db); fs.mkdirSync(appconfig.datadir.db);
} catch (err) { } catch (err) {
@ -31,4 +64,41 @@ module.exports = (appconfig) => {
} }
} }
try {
fs.mkdirSync(path.join(appconfig.datadir.db, 'thumbs'));
} catch (err) {
if(err.code !== 'EEXIST') {
winston.error(err);
process.exit(1);
}
}
winston.info('[SERVER] Data directories are OK.');
return;
},
/**
* Sets the uploads folders.
*
* @param {Array<String>} arrFolders The arr folders
* @return {Void} Void
*/
setUploadsFolders(arrFolders) {
this._uploadsFolders = arrFolders;
return;
},
/**
* Gets the uploads folders.
*
* @return {Array<String>} The uploads folders.
*/
getUploadsFolders() {
return this._uploadsFolders;
}
}; };

View File

@ -36,7 +36,7 @@
"bcryptjs-then": "^1.0.1", "bcryptjs-then": "^1.0.1",
"bluebird": "^3.4.6", "bluebird": "^3.4.6",
"body-parser": "^1.15.2", "body-parser": "^1.15.2",
"bson": "^0.5.4", "bson": "^0.5.5",
"cheerio": "^0.22.0", "cheerio": "^0.22.0",
"child-process-promise": "^2.1.3", "child-process-promise": "^2.1.3",
"compression": "^1.6.2", "compression": "^1.6.2",
@ -54,13 +54,13 @@
"fs-extra": "^0.30.0", "fs-extra": "^0.30.0",
"git-wrapper2-promise": "^0.2.9", "git-wrapper2-promise": "^0.2.9",
"highlight.js": "^9.6.0", "highlight.js": "^9.6.0",
"i18next": "^3.4.1", "i18next": "^3.4.2",
"i18next-express-middleware": "^1.0.1", "i18next-express-middleware": "^1.0.2",
"i18next-node-fs-backend": "^0.1.2", "i18next-node-fs-backend": "^0.1.2",
"js-yaml": "^3.6.1", "js-yaml": "^3.6.1",
"lodash": "^4.15.0", "lodash": "^4.15.0",
"lokijs": "^1.4.1", "lokijs": "^1.4.1",
"markdown-it": "^7.0.1", "markdown-it": "^8.0.0",
"markdown-it-abbr": "^1.0.4", "markdown-it-abbr": "^1.0.4",
"markdown-it-anchor": "^2.5.0", "markdown-it-anchor": "^2.5.0",
"markdown-it-attrs": "^0.7.0", "markdown-it-attrs": "^0.7.0",
@ -69,7 +69,7 @@
"markdown-it-external-links": "0.0.5", "markdown-it-external-links": "0.0.5",
"markdown-it-footnote": "^3.0.1", "markdown-it-footnote": "^3.0.1",
"markdown-it-task-lists": "^1.4.1", "markdown-it-task-lists": "^1.4.1",
"moment": "^2.14.1", "moment": "^2.15.0",
"moment-timezone": "^0.5.5", "moment-timezone": "^0.5.5",
"passport": "^0.3.2", "passport": "^0.3.2",
"passport-local": "^1.0.0", "passport-local": "^1.0.0",
@ -82,7 +82,7 @@
"snyk": "^1.19.1", "snyk": "^1.19.1",
"socket.io": "^1.4.8", "socket.io": "^1.4.8",
"sticky-js": "^1.0.7", "sticky-js": "^1.0.7",
"validator": "^5.6.0", "validator": "^5.7.0",
"validator-as-promised": "^1.0.2", "validator-as-promised": "^1.0.2",
"winston": "^2.2.0" "winston": "^2.2.0"
}, },

View File

@ -25,7 +25,7 @@ winston.add(winston.transports.Console, {
winston.info('[SERVER] Requarks Wiki is initializing...'); winston.info('[SERVER] Requarks Wiki is initializing...');
var appconfig = require('./models/config')('./config.yml'); var appconfig = require('./models/config')('./config.yml');
let lcdata = require('./models/localdata'); let lcdata = require('./models/localdata').init(appconfig, false);
global.db = require('./models/db')(appconfig); global.db = require('./models/db')(appconfig);
global.git = require('./models/git').init(appconfig, false); global.git = require('./models/git').init(appconfig, false);

View File

@ -4,18 +4,23 @@
.columns .columns
.column .column
h3 Image h3 Insert Image
.column.is-narrow.editor-modal-load(v-bind:class="{ 'is-active': isLoading }")
span {{ isLoadingText }}
i
.column.is-narrow .column.is-narrow
.control.is-grouped .control.is-grouped
p.control p.control
a.button.is-dark.is-outlined(v-on:click="cancel") a.button.is-dark.is-outlined(v-on:click="newFolder")
span.icon.is-small: i.fa.fa-folder span.icon.is-small: i.fa.fa-folder
span New Folder span New Folder
.control.has-addons .control.has-addons
a.button.is-info.is-outlined(v-on:click="cancel") a.button.is-info.is-outlined(v-on:click="uploadImage")
span.icon.is-small: i.fa.fa-upload span.icon.is-small: i.fa.fa-upload
span Upload Image span Upload Image
a.button.is-info.is-outlined(v-on:click="cancel") a.button.is-info.is-outlined(v-on:click="fetchFromUrl")
span.icon.is-small: i.fa.fa-download span.icon.is-small: i.fa.fa-download
span Fetch from URL span Fetch from URL
.column.is-narrow .column.is-narrow
@ -27,9 +32,36 @@
.columns .columns
.column.is-one-quarter(style={'max-width':'350px'}) .column.is-one-quarter(style={'max-width':'350px'})
.box .box(style={'max-height': '400px', overflow: 'auto', 'overflow-x': 'hidden'})
aside.menu
p.menu-label
| Folders | Folders
ul.menu-list
li
a(v-on:click="selectFolder('')", v-bind:class="{ 'is-active': currentFolder === '' }")
span.icon.is-small: i.fa.fa-folder-o
span /
li(v-for="fld in folders")
a(v-on:click="selectFolder(fld)", v-bind:class="{ 'is-active': currentFolder === fld }")
span.icon.is-small: i.fa.fa-folder
span / {{ fld }}
.column .column
| Files figure.image.is-128x128
img(src='http://placehold.it/128x128')
.modal(v-bind:class="{ 'is-active': newFolderShow }")
.modal-background
.modal-container
.modal-content
.card.is-fullwidth
header.card-header
p.card-header-title New Folder
.card-content
.content
label.label Enter the new folder name:
p.control
input.input(type='text', placeholder='folder name', v-model='newFolderName')
span.help.is-danger.is-hidden This folder name is invalid!
footer.card-footer
a.card-footer-item(v-on:click="newFolderDiscard") Discard
a.card-footer-item(v-on:click="newFolderCreate") Create

View File

@ -39,6 +39,7 @@ global.internalAuth = require('./lib/internalAuth').init(process.argv[2]);;
winston.info('[WS] WS Server is initializing...'); winston.info('[WS] WS Server is initializing...');
var appconfig = require('./models/config')('./config.yml'); var appconfig = require('./models/config')('./config.yml');
let lcdata = require('./models/localdata').init(appconfig, true);
global.entries = require('./models/entries').init(appconfig); global.entries = require('./models/entries').init(appconfig);
global.mark = require('./models/markdown'); global.mark = require('./models/markdown');
@ -104,6 +105,10 @@ server.listen(appconfig.wsPort, () => {
io.on('connection', (socket) => { io.on('connection', (socket) => {
//-----------------------------------------
// SEARCH
//-----------------------------------------
socket.on('searchAdd', (data) => { socket.on('searchAdd', (data) => {
if(internalAuth.validateKey(data.auth)) { if(internalAuth.validateKey(data.auth)) {
search.add(data.content); search.add(data.content);
@ -122,11 +127,25 @@ io.on('connection', (socket) => {
}); });
}); });
//-----------------------------------------
// UPLOADS
//-----------------------------------------
socket.on('uploadsSetFolders', (data, cb) => {
if(internalAuth.validateKey(data.auth)) {
lcdata.setUploadsFolders(data.content);
}
}); });
/*setTimeout(() => { socket.on('uploadsGetFolders', (data, cb) => {
search._si.searchAsync({ query: { AND: [{'*': ['unit']}] }}).then((stuff) => { console.log(stuff.hits); }); cb(lcdata.getUploadsFolders());
}, 8000);*/ });
socket.on('uploadsGetImages', (data, cb) => {
cb([]);
});
});
// ---------------------------------------- // ----------------------------------------
// Shutdown gracefully // Shutdown gracefully