diff --git a/client/js/app.js b/client/js/app.js index bbbcfeb2..743b5c5a 100644 --- a/client/js/app.js +++ b/client/js/app.js @@ -12,6 +12,8 @@ import io from 'socket-io-client' import i18next from 'i18next' import i18nextXHR from 'i18next-xhr-backend' import VueI18Next from '@panter/vue-i18next' +import 'jquery-contextmenu' +import 'jquery-simple-upload' import 'jquery-smooth-scroll' import 'jquery-sticky' @@ -19,8 +21,8 @@ import 'jquery-sticky' // Load minimal lodash // ==================================== -import concat from 'lodash/concat' import cloneDeep from 'lodash/cloneDeep' +import concat from 'lodash/concat' import debounce from 'lodash/debounce' import deburr from 'lodash/deburr' import delay from 'lodash/delay' @@ -29,6 +31,7 @@ import find from 'lodash/find' import findKey from 'lodash/findKey' import forEach from 'lodash/forEach' import includes from 'lodash/includes' +import isBoolean from 'lodash/isBoolean' import isEmpty from 'lodash/isEmpty' import isNil from 'lodash/isNil' import join from 'lodash/join' @@ -39,8 +42,10 @@ import pullAt from 'lodash/pullAt' import reject from 'lodash/reject' import slice from 'lodash/slice' import split from 'lodash/split' -import trim from 'lodash/trim' +import startCase from 'lodash/startCase' +import toString from 'lodash/toString' import toUpper from 'lodash/toUpper' +import trim from 'lodash/trim' // ==================================== // Load Helpers @@ -56,6 +61,7 @@ import alertComponent from './components/alert.vue' import anchorComponent from './components/anchor.vue' import colorPickerComponent from './components/color-picker.vue' import editorCodeblockComponent from './components/editor-codeblock.vue' +import editorFileComponent from './components/editor-file.vue' import editorVideoComponent from './components/editor-video.vue' import loadingSpinnerComponent from './components/loading-spinner.vue' import modalCreatePageComponent from './components/modal-create-page.vue' @@ -88,6 +94,7 @@ const _ = { findKey, forEach, includes, + isBoolean, isEmpty, isNil, join, @@ -98,6 +105,8 @@ const _ = { reject, slice, split, + startCase, + toString, toUpper, trim } @@ -159,6 +168,7 @@ $(() => { contentView: contentViewComponent, editor: editorComponent, editorCodeblock: editorCodeblockComponent, + editorFile: editorFileComponent, editorVideo: editorVideoComponent, loadingSpinner: loadingSpinnerComponent, modalCreatePage: modalCreatePageComponent, diff --git a/client/js/components/editor-file.vue b/client/js/components/editor-file.vue new file mode 100644 index 00000000..d995ab2b --- /dev/null +++ b/client/js/components/editor-file.vue @@ -0,0 +1,413 @@ + + + diff --git a/client/js/components/editor.component.js b/client/js/components/editor.component.js index 1ffea4ad..b5db8c71 100644 --- a/client/js/components/editor.component.js +++ b/client/js/components/editor.component.js @@ -1,6 +1,5 @@ 'use strict' -import filesize from 'filesize.js' import $ from 'jquery' let mde @@ -8,11 +7,6 @@ let mde export default { name: 'editor', props: ['currentPath'], - filters: { - filesize(v) { - return this._.toUpper(filesize(v)) - } - }, data() { return {} }, @@ -124,11 +118,8 @@ export default { { name: 'link', action: (editor) => { - /* if(!mdeModalOpenState) { - mdeModalOpenState = true; - $('#modal-editor-link').slideToggle(); - } */ window.alert('Coming soon!') + // todo }, className: 'icon-link2', title: 'Insert Link' @@ -136,9 +127,7 @@ export default { { name: 'image', action: (editor) => { - // if (!mdeModalOpenState) { - // vueImage.open() - // } + self.$store.dispatch('editorImage/open') }, className: 'icon-image', title: 'Insert Image' @@ -146,9 +135,7 @@ export default { { name: 'file', action: (editor) => { - // if (!mdeModalOpenState) { - // vueFile.open() - // } + self.$store.dispatch('editorFile/open') }, className: 'icon-paper', title: 'Insert File' diff --git a/client/js/helpers/common.js b/client/js/helpers/common.js new file mode 100644 index 00000000..bfbeabc5 --- /dev/null +++ b/client/js/helpers/common.js @@ -0,0 +1,15 @@ +'use strict' + +import filesize from 'filesize.js' +import toUpper from 'lodash/toUpper' + +module.exports = { + /** + * Convert bytes to humanized form + * @param {number} rawSize Size in bytes + * @returns {string} Humanized file size + */ + filesize(rawSize) { + return toUpper(filesize(rawSize)) + } +} diff --git a/client/js/helpers/index.js b/client/js/helpers/index.js index bd94a1e8..6f802e8b 100644 --- a/client/js/helpers/index.js +++ b/client/js/helpers/index.js @@ -1,6 +1,7 @@ 'use strict' const helpers = { + common: require('./common'), form: require('./form'), pages: require('./pages') } diff --git a/client/js/store/index.js b/client/js/store/index.js index a4708e00..a9829deb 100644 --- a/client/js/store/index.js +++ b/client/js/store/index.js @@ -5,6 +5,7 @@ import alert from './modules/alert' import anchor from './modules/anchor' import editor from './modules/editor' import editorCodeblock from './modules/editor-codeblock' +import editorFile from './modules/editor-file' import editorVideo from './modules/editor-video' import modalCreatePage from './modules/modal-create-page' import modalCreateUser from './modules/modal-create-user' @@ -32,6 +33,7 @@ export default new Vuex.Store({ anchor, editor, editorCodeblock, + editorFile, editorVideo, modalCreatePage, modalCreateUser, diff --git a/client/js/store/modules/editor-file.js b/client/js/store/modules/editor-file.js new file mode 100644 index 00000000..ded21980 --- /dev/null +++ b/client/js/store/modules/editor-file.js @@ -0,0 +1,19 @@ +'use strict' + +export default { + namespaced: true, + state: { + shown: false + }, + getters: {}, + mutations: { + shownChange: (state, shownState) => { state.shown = shownState } + }, + actions: { + open({ commit }, opts) { + commit('shownChange', true) + wikijs.$emit('editorFile/init') + }, + close({ commit }) { commit('shownChange', false) } + } +} diff --git a/package.json b/package.json index 900091ea..d756e7d5 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ }, "dependencies": { "auto-load": "^2.1.0", - "axios": "0.16.1", + "axios": "^0.16.2", "bcryptjs-then": "^1.0.1", "bluebird": "^3.5.0", "body-parser": "^1.17.2", @@ -89,7 +89,7 @@ "mime-types": "^2.1.15", "moment": "^2.18.1", "moment-timezone": "^0.5.13", - "mongodb": "^2.2.27", + "mongodb": "^2.2.28", "mongoose": "^4.10.4", "multer": "^1.3.0", "node-graceful": "^0.2.3", @@ -105,7 +105,7 @@ "passport-windowslive": "^1.0.2", "passport.socketio": "^3.7.0", "pm2": "2.4.6", - "pug": "^2.0.0-rc.1", + "pug": "^2.0.0-rc.2", "read-chunk": "^2.0.0", "remove-markdown": "^0.1.0", "request": "^2.81.0", @@ -117,7 +117,7 @@ "socket.io": "^2.0.2", "stopword": "^0.1.1", "stream-to-promise": "^2.2.0", - "tar": "^3.1.3", + "tar": "^3.1.5", "through2": "^2.0.3", "validator": "^7.0.0", "validator-as-promised": "^1.0.2", @@ -136,7 +136,7 @@ "eslint": "^3.19.0", "eslint-config-standard": "^10.2.1", "eslint-plugin-import": "^2.3.0", - "eslint-plugin-node": "^4.2.2", + "eslint-plugin-node": "^5.0.0", "eslint-plugin-promise": "^3.5.0", "eslint-plugin-standard": "^3.0.1", "fuse-box": "2.1.0-beta.10", diff --git a/server/locales/en/browser.json b/server/locales/en/browser.json index 4c951ca9..d0f87357 100644 --- a/server/locales/en/browser.json +++ b/server/locales/en/browser.json @@ -1,53 +1,86 @@ { "editor": { - "discard": "Discard", - "codeblocktitle": "Insert Code Block", "codeblockinsert": "Insert Code Block", "codeblocklanguage": "Language", "codeblockloading": "Loading code syntax for {{name}}", "codeblockloadingerror": "Error: Unable to load language syntax.", "codeblocksuccess": "Your code block has been inserted.", - "videotitle": "Insert Video", - "videolinktitle": "Enter the link to the video to be embedded:", - "videoinsert": "Insert Video", - "videonotsupported": "This URL is invalid or not supported!", - "videosupportedtitle": "The following are supported:", + "codeblocktitle": "Insert Code Block", + "discard": "Discard", + "filedeleteaction": "Delete", + "filedeleteloading": "Deleting file...", + "filedeletedefault": "this file", + "fileerror": "Unable to fetch updated listing.", + "filefolderempty": "This folder is empty.", + "fileinsert": "Insert Link to File", + "fileloading": "Fetching files...", + "filemoveaction": "Move to...", + "filemoveerror": "Move error: {{err}}", + "filemoveloading": "Moving file...", + "fileprocessing": "Processing...", + "filerenameaction": "Rename", + "filesuccess": "File link has been inserted.", + "filetitle": "Insert File", + "fileupload": "Upload File", + "folders": "Folders", + "foldersloading": "Fetching folders list...", + "newfolder": "New Folder", "videoanymp4file": "Any standard MP4 file", - "videosuccess": "The video code has been inserted." + "videoinsert": "Insert Video", + "videolinktitle": "Enter the link to the video to be embedded:", + "videonotsupported": "This URL is invalid or not supported!", + "videosuccess": "The video code has been inserted.", + "videosupportedtitle": "The following are supported:", + "videotitle": "Insert Video" }, "modal": { "abort": "Abort", - "anchortitle": "Copy link to this section", - "anchorsuccess": "The URL has been copied to your clipboard.", "anchorerror": "Clipboard copy failed. Copy the URL manually.", + "anchorsuccess": "The URL has been copied to your clipboard.", + "anchortitle": "Copy link to this section", "copyclipboard": "Copy to Clipboard", "create": "Create", - "createpagetitle": "Create New Page", - "createpagepath": "Enter the new page path:", "createpageinvalid": "This page path is invalid!", - "createusertitle": "Create / Authorize User", - "createuseremail": "Email address:", - "createuseremailplaceholder": "e.g. john.doe@company.com", - "createuserprovider": "Provider:", - "createuserpassword": "Password:", - "createusername": "Full Name:", - "createusernameplaceholder": "e.g. John Doe", + "createpagepath": "Enter the new page path:", + "createpagetitle": "Create New Page", "createuser": "Create User", "createuserauthorize": "Authorize User", - "discard": "Discard", - "discardpagestay": "Stay on page", - "discardpagetitle": "Discard?", - "discardpagecreate": "Are you sure you want to leave this page and loose anything you wrote so far?", - "discardpageedit": "Are you sure you want to leave this page and loose any modifications?", + "createuseremail": "Email address:", + "createuseremailplaceholder": "e.g. john.doe@company.com", + "createusername": "Full Name:", + "createusernameplaceholder": "e.g. John Doe", + "createuserpassword": "Password:", + "createuserprovider": "Provider:", + "createusertitle": "Create / Authorize User", "delete": "Delete", + "deletefiletitle": "Delete?", + "deletefilewarn": "Are you sure you want to delete", "deleteusertitle": "Delete User Account?", "deleteuserwarning": "Are you sure you want to delete this user account? This action cannot be undone!", + "discard": "Discard", + "discardpagecreate": "Are you sure you want to leave this page and loose anything you wrote so far?", + "discardpageedit": "Are you sure you want to leave this page and loose any modifications?", + "discardpagestay": "Stay on page", + "discardpagetitle": "Discard?", "move": "Move", - "movepagetitle": "Move Page", - "movepagepath": "Enter the new page path:", "movepageinvalid": "This page path is invalid or not allowed!", + "movepagepath": "Enter the new page path:", + "movepageplaceholder": "page-name", + "movepagetitle": "Move Page", "movepagewarning": "Note that moving or renaming pages can lead to broken links. Make sure to edit any page that links to this page afterwards!", - "movepageplaceholder": "page-name" + "newfolderinvalid": "This folder name is invalid!", + "newfolderloading": "Creating new folder...", + "newfoldername": "Enter the new folder name:", + "newfoldernameplaceholder": "folder name", + "newfoldersuccess": "New folder {{name}} created.", + "newfoldertitle": "New Folder", + "renamefile": "Rename", + "renamefileerror": "Rename error: {{err}}", + "renamefileinvalid": "This filename is invalid!", + "renamefileloading": "Renaming file...", + "renamefilename": "Enter the new filename (without the extension) of the file:", + "renamefilenameplaceholder": "filename", + "renamefiletitle": "Rename File" }, "nav": { "home": "Home" @@ -61,9 +94,9 @@ "savechanges": "Save Changes" }, "search": { - "placeholder": "Search...", - "results": "Search Results", + "didyoumean": "Did you mean...?", "nomatch": "No results matching your query", - "didyoumean": "Did you mean...?" + "placeholder": "Search...", + "results": "Search Results" } -} \ No newline at end of file +} diff --git a/server/views/pages/edit.pug b/server/views/pages/edit.pug index 4d851c23..7373e967 100644 --- a/server/views/pages/edit.pug +++ b/server/views/pages/edit.pug @@ -18,6 +18,7 @@ block content .editor-area textarea(ref='editorTextArea', v-pre)= pageData.markdown + editor-file editor-video editor-codeblock modal-discard-page(mode='edit', current-path=pageData.meta.path) diff --git a/server/views/pages/source.pug b/server/views/pages/source.pug index c15fe4d6..271acc22 100644 --- a/server/views/pages/source.pug +++ b/server/views/pages/source.pug @@ -25,7 +25,7 @@ block content source-view(inline-template, entrypath=pageData.meta.path, v-cloak) .ace-container - #source-display= pageData.markdown + #source-display(v-pre)= pageData.markdown modal-create-page(basepath=pageData.meta.path) modal-move-page(current-path=pageData.meta.path) diff --git a/yarn.lock b/yarn.lock index f3061aef..879b6cec 100644 --- a/yarn.lock +++ b/yarn.lock @@ -376,11 +376,12 @@ aws4@^1.2.1: version "1.6.0" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" -axios@0.16.1: - version "0.16.1" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.16.1.tgz#c0b6d26600842384b8f509e57111f0d2df8223ca" +axios@^0.16.2: + version "0.16.2" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.16.2.tgz#ba4f92f17167dfbab40983785454b9ac149c3c6d" dependencies: follow-redirects "^1.2.3" + is-buffer "^1.1.5" babel-cli@^6.24.1: version "6.24.1" @@ -2038,14 +2039,13 @@ eslint-plugin-import@^2.3.0: minimatch "^3.0.3" read-pkg-up "^2.0.0" -eslint-plugin-node@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-4.2.2.tgz#82959ca9aed79fcbd28bb1b188d05cac04fb3363" +eslint-plugin-node@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-5.0.0.tgz#948b1fb82e3f0a744e86fad19aa4f49537d246cc" dependencies: - ignore "^3.0.11" - minimatch "^3.0.2" - object-assign "^4.0.1" - resolve "^1.1.7" + ignore "^3.3.3" + minimatch "^3.0.4" + resolve "^1.3.3" semver "5.3.0" eslint-plugin-promise@^3.5.0: @@ -3044,7 +3044,7 @@ ignore-by-default@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" -ignore@^3.0.11, ignore@^3.2.0: +ignore@^3.2.0, ignore@^3.3.3: version "3.3.3" resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.3.tgz#432352e57accd87ab3110e82d3fea0e47812156d" @@ -4475,7 +4475,14 @@ mongodb-core@2.1.11: bson "~1.0.4" require_optional "~1.0.0" -mongodb@2.2.27, "mongodb@>= 1.2.0 <3.0.0", mongodb@^2.2.27: +mongodb-core@2.1.12: + version "2.1.12" + resolved "https://registry.yarnpkg.com/mongodb-core/-/mongodb-core-2.1.12.tgz#1531192511bc16ef160ac6ae0cc46776ffd8451d" + dependencies: + bson "~1.0.4" + require_optional "~1.0.0" + +mongodb@2.2.27: version "2.2.27" resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-2.2.27.tgz#34122034db66d983bcf6ab5adb26a24a70fef6e6" dependencies: @@ -4483,6 +4490,14 @@ mongodb@2.2.27, "mongodb@>= 1.2.0 <3.0.0", mongodb@^2.2.27: mongodb-core "2.1.11" readable-stream "2.2.7" +"mongodb@>= 1.2.0 <3.0.0", mongodb@^2.2.28: + version "2.2.28" + resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-2.2.28.tgz#d8ff45754366e03973fa259bf4f11447858da657" + dependencies: + es6-promise "3.2.1" + mongodb-core "2.1.12" + readable-stream "2.2.7" + mongoose@*, mongoose@^4.10.4: version "4.10.4" resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-4.10.4.tgz#b9a0a033725e5c29efd9eefb4687d1371956c7b6" @@ -5494,15 +5509,15 @@ pug-error@^1.3.0, pug-error@^1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/pug-error/-/pug-error-1.3.2.tgz#53ae7d9d29bb03cf564493a026109f54c47f5f26" -pug-filters@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/pug-filters/-/pug-filters-2.1.2.tgz#3590b41adb34749f71d3f1f1a9f745011119117b" +pug-filters@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/pug-filters/-/pug-filters-2.1.3.tgz#d59767a220de797dd755489f66834cf9aa83aa54" dependencies: clean-css "^3.3.0" constantinople "^3.0.1" jstransformer "1.0.0" pug-error "^1.3.2" - pug-walk "^1.1.2" + pug-walk "^1.1.3" resolve "^1.1.6" uglify-js "^2.6.1" @@ -5522,12 +5537,12 @@ pug-lexer@^3.1.0: is-expression "^3.0.0" pug-error "^1.3.2" -pug-linker@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pug-linker/-/pug-linker-3.0.0.tgz#2416f06aaa1a9720e3b3261d1e8ca72f6f5123d2" +pug-linker@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/pug-linker/-/pug-linker-3.0.1.tgz#ba3f8ff213ca8f3a304859b44fed13ca7b9dfa19" dependencies: pug-error "^1.3.2" - pug-walk "^1.1.2" + pug-walk "^1.1.3" pug-lint@^2.4.0: version "2.4.0" @@ -5547,16 +5562,16 @@ pug-lint@^2.4.0: strip-json-comments "^2.0.1" void-elements "^2.0.1" -pug-load@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/pug-load/-/pug-load-2.0.6.tgz#86da4b31c4f76fd9a471982b9b3d00e6c8a3f945" +pug-load@^2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/pug-load/-/pug-load-2.0.7.tgz#531d0c6e11546010e984630d03df406367d2de77" dependencies: object-assign "^4.1.0" - pug-walk "^1.1.2" + pug-walk "^1.1.3" -pug-parser@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/pug-parser/-/pug-parser-2.0.2.tgz#53a680cfd05039dcb0c27d029094bc4a792689b0" +pug-parser@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pug-parser/-/pug-parser-3.0.0.tgz#37c619dd800f642187ce4d6ce1a164cdd75487a3" dependencies: pug-error "^1.3.2" token-stream "0.0.1" @@ -5571,20 +5586,20 @@ pug-strip-comments@^1.0.2: dependencies: pug-error "^1.3.2" -pug-walk@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/pug-walk/-/pug-walk-1.1.2.tgz#debb24c070a95d5fc2aebf3589261833d2332e3b" +pug-walk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/pug-walk/-/pug-walk-1.1.3.tgz#d7cd5b23db3ca87c636c86a0973f9cd8e030436c" -pug@^2.0.0-rc.1: - version "2.0.0-rc.1" - resolved "https://registry.yarnpkg.com/pug/-/pug-2.0.0-rc.1.tgz#723c08b3349bb9b96865b9ed7d3e379e247cd984" +pug@^2.0.0-rc.2: + version "2.0.0-rc.2" + resolved "https://registry.yarnpkg.com/pug/-/pug-2.0.0-rc.2.tgz#07845527790ab2c6be67dcf5eb1f31804081f04a" dependencies: pug-code-gen "^1.1.1" - pug-filters "^2.1.2" + pug-filters "^2.1.3" pug-lexer "^3.1.0" - pug-linker "^3.0.0" - pug-load "^2.0.6" - pug-parser "^2.0.2" + pug-linker "^3.0.1" + pug-load "^2.0.7" + pug-parser "^3.0.0" pug-runtime "^2.0.3" pug-strip-comments "^1.0.2" @@ -5915,7 +5930,7 @@ resolve@1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" -resolve@^1.1.6, resolve@^1.1.7, resolve@^1.3.2: +resolve@^1.1.6, resolve@^1.1.7, resolve@^1.3.2, resolve@^1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.3.3.tgz#655907c3469a8680dc2de3a275a8fdd69691f0e5" dependencies: @@ -6637,9 +6652,9 @@ tar@^2.0.0, tar@^2.2.1: fstream "^1.0.2" inherits "2" -tar@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/tar/-/tar-3.1.3.tgz#b4a04aafb5375a969a9fb7cc08e48a8ac3514277" +tar@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/tar/-/tar-3.1.5.tgz#4981e97ab7bad4cb1d5da9232047c9047a681aef" dependencies: minipass "^2.0.2" minizlib "^1.0.3"