From 53ddb50b51536217a38eb9d5cc64d6a578f3a38a Mon Sep 17 00:00:00 2001 From: NGPixel Date: Sat, 20 Jun 2020 01:11:05 -0400 Subject: [PATCH] feat: save page scripts + styles --- client/components/editor.vue | 102 +++++++++++++++++- .../editor/editor-modal-properties.vue | 11 ++ client/graph/editor/create.gql | 16 --- client/graph/editor/update.gql | 15 --- server/graph/schemas/page.graphql | 34 +++--- server/models/pages.js | 63 ++++++++++- 6 files changed, 189 insertions(+), 52 deletions(-) delete mode 100644 client/graph/editor/create.gql delete mode 100644 client/graph/editor/update.gql diff --git a/client/components/editor.vue b/client/components/editor.vue index 36ae0937..b360437c 100644 --- a/client/components/editor.vue +++ b/client/components/editor.vue @@ -63,9 +63,6 @@ import { AtomSpinner } from 'epic-spinners' import { Base64 } from 'js-base64' import { StatusIndicator } from 'vue-status-indicator' -import createPageMutation from 'gql/editor/create.gql' -import updatePageMutation from 'gql/editor/update.gql' - import editorStore from '../store/editor' /* global WIKI */ @@ -262,7 +259,52 @@ export default { // -------------------------------------------- let resp = await this.$apollo.mutate({ - mutation: createPageMutation, + mutation: gql` + mutation ( + $content: String! + $description: String! + $editor: String! + $isPrivate: Boolean! + $isPublished: Boolean! + $locale: String! + $path: String! + $publishEndDate: Date + $publishStartDate: Date + $scriptCss: String + $scriptJs: String + $tags: [String]! + $title: String! + ) { + pages { + create( + content: $content + description: $description + editor: $editor + isPrivate: $isPrivate + isPublished: $isPublished + locale: $locale + path: $path + publishEndDate: $publishEndDate + publishStartDate: $publishStartDate + scriptCss: $scriptCss + scriptJs: $scriptJs + tags: $tags + title: $title + ) { + responseResult { + succeeded + errorCode + slug + message + } + page { + id + updatedAt + } + } + } + } + `, variables: { content: this.$store.get('editor/content'), description: this.$store.get('page/description'), @@ -273,6 +315,8 @@ export default { path: this.$store.get('page/path'), publishEndDate: this.$store.get('page/publishEndDate') || '', publishStartDate: this.$store.get('page/publishStartDate') || '', + scriptCss: this.$store.get('page/scriptCss'), + scriptJs: this.$store.get('page/scriptJs'), tags: this.$store.get('page/tags'), title: this.$store.get('page/title') } @@ -318,7 +362,53 @@ export default { } let resp = await this.$apollo.mutate({ - mutation: updatePageMutation, + mutation: gql` + mutation ( + $id: Int! + $content: String + $description: String + $editor: String + $isPrivate: Boolean + $isPublished: Boolean + $locale: String + $path: String + $publishEndDate: Date + $publishStartDate: Date + $scriptCss: String + $scriptJs: String + $tags: [String] + $title: String + ) { + pages { + update( + id: $id + content: $content + description: $description + editor: $editor + isPrivate: $isPrivate + isPublished: $isPublished + locale: $locale + path: $path + publishEndDate: $publishEndDate + publishStartDate: $publishStartDate + scriptCss: $scriptCss + scriptJs: $scriptJs + tags: $tags + title: $title + ) { + responseResult { + succeeded + errorCode + slug + message + } + page { + updatedAt + } + } + } + } + `, variables: { id: this.$store.get('page/id'), content: this.$store.get('editor/content'), @@ -330,6 +420,8 @@ export default { path: this.$store.get('page/path'), publishEndDate: this.$store.get('page/publishEndDate') || '', publishStartDate: this.$store.get('page/publishStartDate') || '', + scriptCss: this.$store.get('page/scriptCss'), + scriptJs: this.$store.get('page/scriptJs'), tags: this.$store.get('page/tags'), title: this.$store.get('page/title') } diff --git a/client/components/editor/editor-modal-properties.vue b/client/components/editor/editor-modal-properties.vue index cbc96a02..f3a00adf 100644 --- a/client/components/editor/editor-modal-properties.vue +++ b/client/components/editor/editor-modal-properties.vue @@ -188,6 +188,8 @@ ) {{$t('common:actions.ok')}} v-tab-item(:transition='false', :reverse-transition='false') + .editor-props-codeeditor-title + .overline {{$t('editor:props.js')}} .editor-props-codeeditor textarea(ref='codejs') .editor-props-codeeditor-hint @@ -231,6 +233,8 @@ ) v-tab-item(:transition='false', :reverse-transition='false') + .editor-props-codeeditor-title + .overline {{$t('editor:props.css')}} .editor-props-codeeditor textarea(ref='codecss') .editor-props-codeeditor-hint @@ -417,6 +421,13 @@ export default { visibility: hidden; } + &-title { + background-color: mc('grey', '900'); + border-bottom: 1px solid lighten(mc('grey', '900'), 10%); + color: #FFF; + padding: 10px; + } + &-hint { background-color: mc('grey', '900'); border-top: 1px solid lighten(mc('grey', '900'), 5%); diff --git a/client/graph/editor/create.gql b/client/graph/editor/create.gql deleted file mode 100644 index 90a5f5a2..00000000 --- a/client/graph/editor/create.gql +++ /dev/null @@ -1,16 +0,0 @@ -mutation ($content: String!, $description: String!, $editor: String!, $isPrivate: Boolean!, $isPublished: Boolean!, $locale: String!, $path: String!, $publishEndDate: Date, $publishStartDate: Date, $tags: [String]!, $title: String!) { - pages { - create(content: $content, description: $description, editor: $editor, isPrivate: $isPrivate, isPublished: $isPublished, locale: $locale, path: $path, publishEndDate: $publishEndDate, publishStartDate: $publishStartDate, tags: $tags, title: $title) { - responseResult { - succeeded - errorCode - slug - message - } - page { - id - updatedAt - } - } - } -} diff --git a/client/graph/editor/update.gql b/client/graph/editor/update.gql deleted file mode 100644 index 7d6f2c1c..00000000 --- a/client/graph/editor/update.gql +++ /dev/null @@ -1,15 +0,0 @@ -mutation ($id: Int!, $content: String, $description: String, $editor: String, $isPrivate: Boolean, $isPublished: Boolean, $locale: String, $path: String, $publishEndDate: Date, $publishStartDate: Date, $tags: [String], $title: String) { - pages { - update(id: $id, content: $content, description: $description, editor: $editor, isPrivate: $isPrivate, isPublished: $isPublished, locale: $locale, path: $path, publishEndDate: $publishEndDate, publishStartDate: $publishStartDate, tags: $tags, title: $title) { - responseResult { - succeeded - errorCode - slug - message - } - page { - updatedAt - } - } - } -} diff --git a/server/graph/schemas/page.graphql b/server/graph/schemas/page.graphql index 07cb9c69..f6f43f2a 100644 --- a/server/graph/schemas/page.graphql +++ b/server/graph/schemas/page.graphql @@ -44,7 +44,7 @@ type PageQuery { single( id: Int! - ): Page @auth(requires: ["manage:pages", "delete:pages", "manage:system"]) + ): Page @auth(requires: ["read:pages", "manage:system"]) tags: [PageTag]! @auth(requires: ["manage:system", "read:pages"]) @@ -89,6 +89,8 @@ type PageMutation { path: String! publishEndDate: Date publishStartDate: Date + scriptCss: String + scriptJs: String tags: [String]! title: String! ): PageResponse @auth(requires: ["write:pages", "manage:pages", "manage:system"]) @@ -104,6 +106,8 @@ type PageMutation { path: String publishEndDate: Date publishStartDate: Date + scriptCss: String + scriptJs: String tags: [String] title: String ): PageResponse @auth(requires: ["write:pages", "manage:pages", "manage:system"]) @@ -167,26 +171,28 @@ type Page { hash: String! title: String! description: String! - isPrivate: Boolean! - isPublished: Boolean! - privateNS: String - publishStartDate: Date! - publishEndDate: Date! + isPrivate: Boolean! @auth(requires: ["write:pages", "manage:system"]) + isPublished: Boolean! @auth(requires: ["write:pages", "manage:system"]) + privateNS: String @auth(requires: ["write:pages", "manage:system"]) + publishStartDate: Date! @auth(requires: ["write:pages", "manage:system"]) + publishEndDate: Date! @auth(requires: ["write:pages", "manage:system"]) tags: [PageTag]! - content: String! + content: String! @auth(requires: ["read:source", "write:pages", "manage:system"]) render: String toc: String contentType: String! createdAt: Date! updatedAt: Date! - editor: String! + editor: String! @auth(requires: ["write:pages", "manage:system"]) locale: String! - authorId: Int! - authorName: String! - authorEmail: String! - creatorId: Int! - creatorName: String! - creatorEmail: String! + scriptCss: String + scriptJs: String + authorId: Int! @auth(requires: ["write:pages", "manage:system"]) + authorName: String! @auth(requires: ["write:pages", "manage:system"]) + authorEmail: String! @auth(requires: ["write:pages", "manage:system"]) + creatorId: Int! @auth(requires: ["write:pages", "manage:system"]) + creatorName: String! @auth(requires: ["write:pages", "manage:system"]) + creatorEmail: String! @auth(requires: ["write:pages", "manage:system"]) } type PageTag { diff --git a/server/models/pages.js b/server/models/pages.js index b4a5fd1d..156821c0 100644 --- a/server/models/pages.js +++ b/server/models/pages.js @@ -8,6 +8,7 @@ const yaml = require('js-yaml') const striptags = require('striptags') const emojiRegex = require('emoji-regex') const he = require('he') +const CleanCSS = require('clean-css') /* global WIKI */ @@ -247,6 +248,28 @@ module.exports = class Page extends Model { throw new WIKI.Error.PageEmptyContent() } + // -> Format JS Scripts + let scriptCss = '' + if (WIKI.auth.checkAccess(opts.user, ['write:styles'], { + locale: opts.locale, + path: opts.path + })) { + if (!_.isEmpty(opts.scriptCss)) { + scriptCss = new CleanCSS({ inline: false }).minify(opts.scriptCss).styles + } else { + scriptCss = '' + } + } + + // -> Format JS Scripts + let scriptJs = '' + if (WIKI.auth.checkAccess(opts.user, ['write:scripts'], { + locale: opts.locale, + path: opts.path + })) { + scriptJs = opts.scriptJs || '' + } + // -> Create page await WIKI.models.pages.query().insert({ authorId: opts.user.id, @@ -263,7 +286,11 @@ module.exports = class Page extends Model { publishEndDate: opts.publishEndDate || '', publishStartDate: opts.publishStartDate || '', title: opts.title, - toc: '[]' + toc: '[]', + extra: JSON.stringify({ + js: scriptJs, + css: scriptCss + }) }) const page = await WIKI.models.pages.getPageFromDb({ path: opts.path, @@ -343,6 +370,33 @@ module.exports = class Page extends Model { versionDate: ogPage.updatedAt }) + // -> Format Extra Properties + if (!_.isPlainObject(ogPage.extra)) { + ogPage.extra = {} + } + + // -> Format JS Scripts + let scriptCss = _.get(ogPage, 'extra.css', '') + if (WIKI.auth.checkAccess(opts.user, ['write:styles'], { + locale: opts.locale, + path: opts.path + })) { + if (!_.isEmpty(opts.scriptCss)) { + scriptCss = new CleanCSS({ inline: false }).minify(opts.scriptCss).styles + } else { + scriptCss = '' + } + } + + // -> Format JS Scripts + let scriptJs = _.get(ogPage, 'extra.js', '') + if (WIKI.auth.checkAccess(opts.user, ['write:scripts'], { + locale: opts.locale, + path: opts.path + })) { + scriptJs = opts.scriptJs || '' + } + // -> Update page await WIKI.models.pages.query().patch({ authorId: opts.user.id, @@ -351,7 +405,12 @@ module.exports = class Page extends Model { isPublished: opts.isPublished === true || opts.isPublished === 1, publishEndDate: opts.publishEndDate || '', publishStartDate: opts.publishStartDate || '', - title: opts.title + title: opts.title, + extra: JSON.stringify({ + ...ogPage.extra, + js: scriptJs, + css: scriptCss + }) }).where('id', ogPage.id) let page = await WIKI.models.pages.getPageFromDb(ogPage.id)