Browse Source

feat: edit shortcuts

NGPixel 2 years ago
parent
commit
8715cd69b2

+ 108 - 3
client/components/admin/admin-general.vue

@@ -144,7 +144,7 @@
                   //-   )
 
                   //- v-divider.mt-3
-                  v-switch(
+                  v-switch.mt-0(
                     inset
                     label='Comments'
                     color='indigo'
@@ -177,6 +177,76 @@
                     persistent-hint
                     )
 
+              v-card.mt-5.animated.fadeInUp.wait-p7s
+                v-toolbar(color='primary', dark, dense, flat)
+                  v-toolbar-title.subtitle-1 {{$t('admin:general.editShortcuts')}}
+                v-card-text
+                  v-switch.mt-0(
+                    inset
+                    :label='$t(`admin:general.editFab`)'
+                    color='primary'
+                    v-model='config.editFab'
+                    persistent-hint
+                    :hint='$t(`admin:general.editFabHint`)'
+                    )
+                v-divider
+                .overline.grey--text.pa-4 {{$t('admin:general.editMenuBar')}}
+                .px-3.pb-3
+                  v-switch.mt-0.ml-1(
+                    inset
+                    :label='$t(`admin:general.displayEditMenuBar`)'
+                    color='primary'
+                    v-model='config.editMenuBar'
+                    persistent-hint
+                    :hint='$t(`admin:general.displayEditMenuBarHint`)'
+                    )
+                  v-switch.mt-4.ml-1(
+                    v-if='config.editMenuBar'
+                    inset
+                    :label='$t(`admin:general.displayEditMenuBtn`)'
+                    color='primary'
+                    v-model='config.editMenuBtn'
+                    persistent-hint
+                    :hint='$t(`admin:general.displayEditMenuBtnHint`)'
+                    )
+                  v-switch.mt-4.ml-1(
+                    v-if='config.editMenuBar'
+                    inset
+                    :label='$t(`admin:general.displayEditMenuExternalBtn`)'
+                    color='primary'
+                    v-model='config.editMenuExternalBtn'
+                    persistent-hint
+                    :hint='$t(`admin:general.displayEditMenuExternalBtnHint`)'
+                    )
+                template(v-if='config.editMenuBar && config.editMenuExternalBtn')
+                  v-divider
+                  .overline.grey--text.pa-4 External Edit Button
+                  .px-3.pb-3
+                    v-text-field(
+                      outlined
+                      :label='$t(`admin:general.editMenuExternalName`)'
+                      v-model='config.editMenuExternalName'
+                      prepend-icon='mdi-format-title'
+                      :hint='$t(`admin:general.editMenuExternalNameHint`)'
+                      persistent-hint
+                      )
+                    v-text-field.mt-3(
+                      outlined
+                      :label='$t(`admin:general.editMenuExternalIcon`)'
+                      v-model='config.editMenuExternalIcon'
+                      prepend-icon='mdi-dice-5'
+                      :hint='$t(`admin:general.editMenuExternalIconHint`)'
+                      persistent-hint
+                      )
+                    v-text-field.mt-3(
+                      outlined
+                      :label='$t(`admin:general.editMenuExternalUrl`)'
+                      v-model='config.editMenuExternalUrl'
+                      prepend-icon='mdi-near-me'
+                      :hint='$t(`admin:general.editMenuExternalUrlHint`)'
+                      persistent-hint
+                      )
+
     component(:is='activeModal')
 
 </template>
@@ -216,7 +286,14 @@ export default {
         featurePageComments: false,
         featurePersonalWikis: false,
         featureTinyPNG: false,
-        pageExtensions: ''
+        pageExtensions: '',
+        editFab: false,
+        editMenuBar: false,
+        editMenuBtn: false,
+        editMenuExternalBtn: false,
+        editMenuExternalName: '',
+        editMenuExternalIcon: '',
+        editMenuExternalUrl: ''
       },
       metaRobots: [
         { text: 'Index', value: 'index' },
@@ -274,6 +351,13 @@ export default {
               $featurePageRatings: Boolean
               $featurePageComments: Boolean
               $featurePersonalWikis: Boolean
+              $editFab: Boolean
+              $editMenuBar: Boolean
+              $editMenuBtn: Boolean
+              $editMenuExternalBtn: Boolean
+              $editMenuExternalName: String
+              $editMenuExternalIcon: String
+              $editMenuExternalUrl: String
             ) {
               site {
                 updateConfig(
@@ -290,6 +374,13 @@ export default {
                   featurePageRatings: $featurePageRatings
                   featurePageComments: $featurePageComments
                   featurePersonalWikis: $featurePersonalWikis
+                  editFab: $editFab
+                  editMenuBar: $editMenuBar
+                  editMenuBtn: $editMenuBtn
+                  editMenuExternalBtn: $editMenuExternalBtn
+                  editMenuExternalName: $editMenuExternalName
+                  editMenuExternalIcon: $editMenuExternalIcon
+                  editMenuExternalUrl: $editMenuExternalUrl
                 ) {
                   responseResult {
                     succeeded
@@ -314,7 +405,14 @@ export default {
             pageExtensions: _.get(this.config, 'pageExtensions', ''),
             featurePageRatings: _.get(this.config, 'featurePageRatings', false),
             featurePageComments: _.get(this.config, 'featurePageComments', false),
-            featurePersonalWikis: _.get(this.config, 'featurePersonalWikis', false)
+            featurePersonalWikis: _.get(this.config, 'featurePersonalWikis', false),
+            editFab: _.get(this.config, 'editFab', false),
+            editMenuBar: _.get(this.config, 'editMenuBar', false),
+            editMenuBtn: _.get(this.config, 'editMenuBtn', false),
+            editMenuExternalBtn: _.get(this.config, 'editMenuExternalBtn', false),
+            editMenuExternalName: _.get(this.config, 'editMenuExternalName', ''),
+            editMenuExternalIcon: _.get(this.config, 'editMenuExternalIcon', ''),
+            editMenuExternalUrl: _.get(this.config, 'editMenuExternalUrl', '')
           },
           watchLoading (isLoading) {
             this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-site-update')
@@ -368,6 +466,13 @@ export default {
               featurePageRatings
               featurePageComments
               featurePersonalWikis
+              editFab
+              editMenuBar
+              editMenuBtn
+              editMenuExternalBtn
+              editMenuExternalName
+              editMenuExternalIcon
+              editMenuExternalUrl
             }
           }
         }

+ 10 - 1
client/store/page.js

@@ -41,7 +41,16 @@ const state = {
       manage: false
     }
   },
-  commentsCount: 0
+  commentsCount: 0,
+  editShortcuts: {
+    editFab: false,
+    editMenuBar: false,
+    editMenuBtn: false,
+    editMenuExternalBtn: false,
+    editMenuExternalName: '',
+    editMenuExternalIcon: '',
+    editMenuExternalUrl: ''
+  }
 }
 
 export default {

+ 79 - 3
client/themes/default/components/page.vue

@@ -49,10 +49,28 @@
             status-indicator.ml-3(negative, pulse)
         v-divider
       v-container.grey.pa-0(fluid, :class='$vuetify.theme.dark ? `darken-4-l3` : `lighten-4`')
-        v-row(no-gutters, align-content='center', style='height: 90px;')
+        v-row.page-header-section(no-gutters, align-content='center', style='height: 90px;')
           v-col.page-col-content.is-page-header(offset-xl='2', offset-lg='3', style='margin-top: auto; margin-bottom: auto;', :class='$vuetify.rtl ? `pr-4` : `pl-4`')
             .headline.grey--text(:class='$vuetify.theme.dark ? `text--lighten-2` : `text--darken-3`') {{title}}
             .caption.grey--text.text--darken-1 {{description}}
+            .page-edit-shortcuts(v-if='editShortcutsObj.editMenuBar')
+              v-btn(
+                v-if='editShortcutsObj.editMenuBtn'
+                @click='pageEdit'
+                depressed
+                small
+                )
+                v-icon.mr-2(small) mdi-pencil
+                span.text-none {{$t(`common:actions.edit`)}}
+              v-btn(
+                v-if='editShortcutsObj.editMenuExternalBtn'
+                :href='editMenuExternalUrl'
+                target='_blank'
+                depressed
+                small
+                )
+                v-icon.mr-2(small) {{ editShortcutsObj.editMenuExternalIcon }}
+                span.text-none {{$t(`common:page.editExternal`, { name: editShortcutsObj.editMenuExternalName })}}
       v-divider
       v-container.pl-5.pt-4(fluid, grid-list-xl)
         v-layout(row)
@@ -186,7 +204,7 @@
                 v-spacer
 
           v-flex.page-col-content(xs12, lg9, xl10)
-            v-tooltip(:right='$vuetify.rtl', :left='!$vuetify.rtl', v-if='hasAnyPagePermissions')
+            v-tooltip(:right='$vuetify.rtl', :left='!$vuetify.rtl', v-if='hasAnyPagePermissions && editShortcutsObj.editFab')
               template(v-slot:activator='{ on: onEditActivator }')
                 v-speed-dial(
                   v-model='pageEditFab'
@@ -440,6 +458,14 @@ export default {
     commentsExternal: {
       type: Boolean,
       default: false
+    },
+    editShortcuts: {
+      type: String,
+      default: ''
+    },
+    filename: {
+      type: String,
+      default: ''
     }
   },
   data() {
@@ -478,6 +504,7 @@ export default {
     isAuthenticated: get('user/authenticated'),
     commentsCount: get('page/commentsCount'),
     commentsPerms: get('page/effectivePermissions@comments'),
+    editShortcutsObj: get('page/editShortcuts'),
     rating: {
       get () {
         return 3.5
@@ -519,7 +546,14 @@ export default {
       return this.hasAdminPermission || this.hasWritePagesPermission || this.hasManagePagesPermission ||
         this.hasDeletePagesPermission || this.hasReadSourcePermission || this.hasReadHistoryPermission
     },
-    printView: sync('site/printView')
+    printView: sync('site/printView'),
+    editMenuExternalUrl () {
+      if (this.editShortcutsObj.editMenuBar && this.editShortcutsObj.editMenuExternalBtn) {
+        return this.editShortcutsObj.editMenuExternalUrl.replace('{filename}', this.filename)
+      } else {
+        return ''
+      }
+    }
   },
   created() {
     this.$store.set('page/authorId', this.authorId)
@@ -537,6 +571,9 @@ export default {
     if (this.effectivePermissions) {
       this.$store.set('page/effectivePermissions', JSON.parse(Buffer.from(this.effectivePermissions, 'base64').toString()))
     }
+    if (this.editShortcuts) {
+      this.$store.set('page/editShortcuts', JSON.parse(Buffer.from(this.editShortcuts, 'base64').toString()))
+    }
 
     this.$store.set('page/mode', 'view')
   },
@@ -676,4 +713,43 @@ export default {
   display: none;
 }
 
+.page-header-section {
+  position: relative;
+
+  .page-edit-shortcuts {
+    position: absolute;
+    bottom: -14px;
+    right: 10px;
+
+    .v-btn {
+      border-right: 1px solid #DDD !important;
+      border-bottom: 1px solid #DDD !important;
+      border-radius: 0;
+      color: #777;
+      background-color: #FFF !important;
+
+      @at-root .theme--dark & {
+        background-color: #222 !important;
+        border-right-color: #444 !important;
+        border-bottom-color: #444 !important;
+        color: #CCC;
+      }
+
+      .v-icon {
+        color: mc('blue', '700');
+      }
+
+      &:first-child {
+        border-top-left-radius: 5px;
+        border-bottom-left-radius: 5px;
+      }
+
+      &:last-child {
+        border-top-right-radius: 5px;
+        border-bottom-right-radius: 5px;
+      }
+    }
+  }
+}
+
 </style>

+ 4 - 0
client/themes/default/scss/app.scss

@@ -1036,4 +1036,8 @@
   .comments-container {
     display: none;
   }
+
+  .page-edit-shortcuts {
+    display: none;
+  }
 }

+ 8 - 0
server/app/data.yml

@@ -67,6 +67,14 @@ defaults:
       audience: 'urn:wiki.js'
       tokenExpiration: '30m'
       tokenRenewal: '14d'
+    editShortcuts:
+      editFab: true
+      editMenuBar: false
+      editMenuBtn: true
+      editMenuExternalBtn: true
+      editMenuExternalName: 'GitHub'
+      editMenuExternalIcon: 'mdi-github'
+      editMenuExternalUrl: 'https://github.com/org/repo/blob/main/{filename}'
     features:
       featurePageRatings: true
       featurePageComments: true

+ 6 - 1
server/controllers/common.js

@@ -542,13 +542,18 @@ router.get('/*', async (req, res, next) => {
             })
           }
 
+          // -> Page Filename (for edit on external repo button)
+          let pageFilename = WIKI.config.lang.namespacing ? `${pageArgs.locale}/${page.path}` : page.path
+          pageFilename += page.contentType === 'markdown' ? '.md' : '.html'
+
           // -> Render view
           res.render('page', {
             page,
             sidebar,
             injectCode,
             comments: commentTmpl,
-            effectivePermissions
+            effectivePermissions,
+            pageFilename
           })
         }
       } else if (pageArgs.path === 'home') {

+ 12 - 1
server/graph/resolvers/site.js

@@ -20,6 +20,7 @@ module.exports = {
         logoUrl: WIKI.config.logoUrl,
         pageExtensions: WIKI.config.pageExtensions.join(', '),
         ...WIKI.config.seo,
+        ...WIKI.config.editShortcuts,
         ...WIKI.config.features,
         ...WIKI.config.security,
         authAutoLogin: WIKI.config.auth.autoLogin,
@@ -84,6 +85,16 @@ module.exports = {
           tokenRenewal: _.get(args, 'authJwtRenewablePeriod', WIKI.config.auth.tokenRenewal)
         }
 
+        WIKI.config.editShortcuts = {
+          editFab: _.get(args, 'editFab', WIKI.config.editShortcuts.editFab),
+          editMenuBar: _.get(args, 'editMenuBar', WIKI.config.editShortcuts.editMenuBar),
+          editMenuBtn: _.get(args, 'editMenuBtn', WIKI.config.editShortcuts.editMenuBtn),
+          editMenuExternalBtn: _.get(args, 'editMenuExternalBtn', WIKI.config.editShortcuts.editMenuExternalBtn),
+          editMenuExternalName: _.get(args, 'editMenuExternalName', WIKI.config.editShortcuts.editMenuExternalName),
+          editMenuExternalIcon: _.get(args, 'editMenuExternalIcon', WIKI.config.editShortcuts.editMenuExternalIcon),
+          editMenuExternalUrl: _.get(args, 'editMenuExternalUrl', WIKI.config.editShortcuts.editMenuExternalUrl)
+        }
+
         WIKI.config.features = {
           featurePageRatings: _.get(args, 'featurePageRatings', WIKI.config.features.featurePageRatings),
           featurePageComments: _.get(args, 'featurePageComments', WIKI.config.features.featurePageComments),
@@ -109,7 +120,7 @@ module.exports = {
           forceDownload: _.get(args, 'uploadForceDownload', WIKI.config.uploads.forceDownload)
         }
 
-        await WIKI.configSvc.saveToDb(['host', 'title', 'company', 'contentLicense', 'seo', 'logoUrl', 'pageExtensions', 'auth', 'features', 'security', 'uploads'])
+        await WIKI.configSvc.saveToDb(['host', 'title', 'company', 'contentLicense', 'seo', 'logoUrl', 'pageExtensions', 'auth', 'editShortcuts', 'features', 'security', 'uploads'])
 
         if (WIKI.config.security.securityTrustProxy) {
           WIKI.app.enable('trust proxy')

+ 14 - 0
server/graph/schemas/site.graphql

@@ -41,6 +41,13 @@ type SiteMutation {
     authJwtAudience: String
     authJwtExpiration: String
     authJwtRenewablePeriod: String
+    editFab: Boolean
+    editMenuBar: Boolean
+    editMenuBtn: Boolean
+    editMenuExternalBtn: Boolean
+    editMenuExternalName: String
+    editMenuExternalIcon: String
+    editMenuExternalUrl: String
     featurePageRatings: Boolean
     featurePageComments: Boolean
     featurePersonalWikis: Boolean
@@ -83,6 +90,13 @@ type SiteConfig {
   authJwtAudience: String
   authJwtExpiration: String
   authJwtRenewablePeriod: String
+  editFab: Boolean
+  editMenuBar: Boolean
+  editMenuBtn: Boolean
+  editMenuExternalBtn: Boolean
+  editMenuExternalName: String
+  editMenuExternalIcon: String
+  editMenuExternalUrl: String
   featurePageRatings: Boolean
   featurePageComments: Boolean
   featurePersonalWikis: Boolean

+ 3 - 1
server/models/pages.js

@@ -148,6 +148,7 @@ module.exports = class Page extends Model {
       isPublished: 'boolean',
       publishEndDate: 'string',
       publishStartDate: 'string',
+      contentType: 'string',
       render: 'string',
       tags: [
         {
@@ -787,7 +788,7 @@ module.exports = class Page extends Model {
    * @returns {Promise} Promise with no value
    */
   static async deletePage(opts) {
-    const page = await WIKI.models.pages.getPageFromDb(_.has(opts, 'id') ? opts.id : opts);
+    const page = await WIKI.models.pages.getPageFromDb(_.has(opts, 'id') ? opts.id : opts)
     if (!page) {
       throw new WIKI.Error.PageNotFound()
     }
@@ -1067,6 +1068,7 @@ module.exports = class Page extends Model {
       isPublished: page.isPublished === 1 || page.isPublished === true,
       publishEndDate: page.publishEndDate,
       publishStartDate: page.publishStartDate,
+      contentType: page.contentType,
       render: page.render,
       tags: page.tags.map(t => _.pick(t, ['tag', 'title'])),
       title: page.title,

+ 2 - 0
server/views/page.pug

@@ -29,6 +29,8 @@ block body
       comments-enabled=config.features.featurePageComments
       effective-permissions=Buffer.from(JSON.stringify(effectivePermissions)).toString('base64')
       comments-external=comments.codeTemplate
+      edit-shortcuts=Buffer.from(JSON.stringify(config.editShortcuts)).toString('base64')
+      filename=pageFilename
       )
       template(slot='contents')
         div!= page.render