Selaa lähdekoodia

feat: save page scripts + styles

NGPixel 5 vuotta sitten
vanhempi
sitoutus
53ddb50b51

+ 97 - 5
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')
             }

+ 11 - 0
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%);

+ 0 - 16
client/graph/editor/create.gql

@@ -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
-      }
-    }
-  }
-}

+ 0 - 15
client/graph/editor/update.gql

@@ -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
-      }
-    }
-  }
-}

+ 20 - 14
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 {

+ 61 - 2
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)