Browse Source

fix: admin rendering UI + dark mode

Nick 5 years ago
parent
commit
c4629419d3
35 changed files with 231 additions and 197 deletions
  1. 4 1
      client/client-app.js
  2. 1 1
      client/components/admin.vue
  3. 4 4
      client/components/admin/admin-auth.vue
  4. 2 2
      client/components/admin/admin-dashboard.vue
  5. 64 51
      client/components/admin/admin-rendering.vue
  6. 23 26
      client/components/admin/admin-search.vue
  7. 30 34
      client/components/admin/admin-storage.vue
  8. 6 0
      client/components/admin/admin-theme.vue
  9. 1 1
      client/components/admin/admin-utilities-content.vue
  10. 1 1
      client/components/common/v-card-chin.vue
  11. 42 41
      client/scss/base/base.scss
  12. 7 7
      client/themes/default/components/page.vue
  13. 8 8
      client/themes/default/scss/app.scss
  14. 1 1
      server/modules/rendering/html-asciinema/definition.yml
  15. 1 1
      server/modules/rendering/html-blockquotes/definition.yml
  16. 1 1
      server/modules/rendering/html-codehighlighter/definition.yml
  17. 1 1
      server/modules/rendering/html-core/definition.yml
  18. 1 1
      server/modules/rendering/html-mathjax/definition.yml
  19. 1 1
      server/modules/rendering/html-mediaplayers/definition.yml
  20. 1 1
      server/modules/rendering/html-mermaid/definition.yml
  21. 1 1
      server/modules/rendering/html-plantuml/definition.yml
  22. 1 1
      server/modules/rendering/html-security/definition.yml
  23. 1 1
      server/modules/rendering/html-twemoji/definition.yml
  24. 1 1
      server/modules/rendering/markdown-abbr/definition.yml
  25. 1 1
      server/modules/rendering/markdown-core/definition.yml
  26. 1 1
      server/modules/rendering/markdown-emoji/definition.yml
  27. 1 1
      server/modules/rendering/markdown-expandtabs/definition.yml
  28. 1 1
      server/modules/rendering/markdown-footnotes/definition.yml
  29. 1 1
      server/modules/rendering/markdown-imsize/definition.yml
  30. 1 1
      server/modules/rendering/markdown-mathjax/definition.yml
  31. 1 1
      server/modules/rendering/markdown-supsub/definition.yml
  32. 1 1
      server/modules/rendering/markdown-tasklists/definition.yml
  33. 5 1
      server/setup.js
  34. 7 0
      server/views/legacy/master.pug
  35. 7 0
      server/views/master.pug

+ 4 - 1
client/client-app.js

@@ -196,7 +196,10 @@ let bootstrap = () => {
     store,
     i18n,
     vuetify: new Vuetify({
-      rtl: siteConfig.rtl
+      rtl: siteConfig.rtl,
+      theme: {
+        dark: siteConfig.darkMode
+      }
     })
   })
 

+ 1 - 1
client/components/admin.vue

@@ -1,5 +1,5 @@
 <template lang='pug'>
-  v-app(:dark='darkMode').admin
+  v-app.admin
     nav-header(hide-search)
       template(slot='mid')
         v-spacer

+ 4 - 4
client/components/admin/admin-auth.vue

@@ -29,11 +29,11 @@
                 v-list-item-content
                   v-list-item-title.body-2(:class='!str.isAvailable ? `grey--text` : (selectedStrategy === str.key ? `primary--text` : ``)') {{ str.title }}
                   v-list-item-subtitle: .caption(:class='!str.isAvailable ? `grey--text text--lighten-1` : (selectedStrategy === str.key ? `blue--text ` : ``)') {{ str.description }}
-                v-list-item-avatar(v-if='selectedStrategy === str.key')
+                v-list-item-avatar(v-if='selectedStrategy === str.key', size='24')
                   v-icon.animated.fadeInLeft(color='primary', large) mdi-chevron-right
               v-divider(v-if='idx < strategies.length - 1')
 
-        v-card.wiki-form.mt-3.animated.fadeInUp.wait-p2s
+        v-card.mt-3.animated.fadeInUp.wait-p2s
           v-toolbar(flat, color='primary', dark, dense)
             .subtitle-1 {{$t('admin:auth.globalAdvSettings')}}
           v-card-text
@@ -64,7 +64,7 @@
 
       v-flex(xs12, lg9)
 
-        v-card.wiki-form.animated.fadeInUp.wait-p2s
+        v-card.animated.fadeInUp.wait-p2s
           v-toolbar(color='primary', dense, flat, dark)
             .subtitle-1 {{strategy.title}}
           v-card-text
@@ -194,7 +194,7 @@
             .subtitle-1 {{$t('admin:auth.configReference')}}
           v-card-text
             .body-2 {{$t('admin:auth.configReferenceSubtitle')}}
-            v-alert.mt-3.radius-7(v-if='host.length < 8', color='red', outline, :value='true', icon='warning')
+            v-alert.mt-3.radius-7(v-if='host.length < 8', color='red', outlined, :value='true', icon='mdi-alert')
               i18next(path='admin:auth.siteUrlNotSetup', tag='span')
                 strong(place='siteUrl') {{$t('admin:general.siteUrl')}}
                 strong(place='general') {{$t('admin:general.title')}}

+ 2 - 2
client/components/admin/admin-dashboard.vue

@@ -54,7 +54,7 @@
             .body-2(v-else) {{$t('admin:dashboard.versionNew', { version: info.latestVersion })}}
       v-flex(xs12, xl6)
         v-card.radius-7.animated.fadeInUp.wait-p2s
-          v-card-title.subtitle-1(:class='$vuetify.dark ? `grey darken-2` : `grey lighten-5`') Recent Pages
+          v-card-title.subtitle-1(:class='$vuetify.theme.dark ? `grey darken-2` : `grey lighten-5`') Recent Pages
           v-data-table.pb-2(
             :items='recentPages'
             hide-default-footer
@@ -71,7 +71,7 @@
                 .caption Created {{ props.item.createdAt | moment('calendar') }}
       v-flex(xs12, xl6)
         v-card.radius-7.animated.fadeInUp.wait-p4s
-          v-card-title.subtitle-1(:class='$vuetify.dark ? `grey darken-2` : `grey lighten-5`') Most Popular Pages
+          v-card-title.subtitle-1(:class='$vuetify.theme.dark ? `grey darken-2` : `grey lighten-5`') Most Popular Pages
           v-data-table.pb-2(
             :items='popularPages'
             hide-default-footer

+ 64 - 51
client/components/admin/admin-rendering.vue

@@ -8,10 +8,10 @@
             .headline.primary--text.animated.fadeInLeft Rendering
             .subtitle-1.grey--text.animated.fadeInLeft.wait-p4s Configure how content is rendered #[v-chip(label, color='primary', small).white--text coming soon]
           v-spacer
-          v-btn.animated.fadeInDown.wait-p2s(outline, color='grey', @click='refresh', large)
-            v-icon refresh
+          v-btn.mx-3.animated.fadeInDown.wait-p2s(outlined, color='grey', @click='refresh', large)
+            v-icon mdi-refresh
           v-btn.animated.fadeInDown(color='success', @click='save', depressed, large)
-            v-icon(left) check
+            v-icon(left) mdi-check
             span {{$t('common:actions.apply')}}
 
       v-flex.animated.fadeInUp(lg3, xs12)
@@ -21,43 +21,49 @@
           flat
           dark
           )
-          v-icon.mr-2 line_weight
+          v-icon.mr-2 mdi-creation
           .subtitle-1 Pipeline
-        v-expansion-panel.adm-rendering-pipeline(v-model='selectedCore')
-          v-expansion-panel-content(
-            hide-actions
+        v-expansion-panels.adm-rendering-pipeline(
+          v-model='selectedCore'
+          accordion
+          mandatory
+          )
+          v-expansion-panel(
             v-for='core in renderers'
             :key='core.key'
             )
-            v-toolbar(
-              slot='header'
-              color='blue'
-              dense
-              dark
-              flat
-              )
-              v-spacer
-              .body-2 {{core.input}}
-              v-icon.mx-2 arrow_forward
-              .caption {{core.output}}
-              v-spacer
-            v-list.py-0(two-line, dense)
-              template(v-for='(rdr, n) in core.children')
-                v-list-item(
-                  avatar
-                  :key='rdr.key'
-                  @click='selectRenderer(rdr.key)'
-                  :class='currentRenderer.key === rdr.key ? (darkMode ? `grey darken-4-l4` : `blue lighten-5`) : ``'
-                  )
-                  v-list-item-avatar
-                    v-icon(:color='currentRenderer.key === rdr.key ? "primary" : "grey"') {{rdr.icon}}
-                  v-list-item-content
-                    v-list-item-title {{rdr.title}}
-                    v-list-item-sub-title {{rdr.description}}
-                  v-list-item-avatar
-                    status-indicator(v-if='rdr.isEnabled', positive, pulse)
-                    status-indicator(v-else, negative, pulse)
-                v-divider.my-0(v-if='n < core.children.length - 1')
+            v-expansion-panel-header(
+              hide-actions
+              ripple
+            )
+              v-toolbar(
+                color='blue'
+                dense
+                dark
+                flat
+                )
+                v-spacer
+                .body-2 {{core.input}}
+                v-icon.mx-2 mdi-arrow-right-bold-hexagon-outline
+                .caption {{core.output}}
+                v-spacer
+            v-expansion-panel-content
+              v-list.py-0(two-line, dense)
+                template(v-for='(rdr, n) in core.children')
+                  v-list-item(
+                    :key='rdr.key'
+                    @click='selectRenderer(rdr.key)'
+                    :class='currentRenderer.key === rdr.key ? (darkMode ? `grey darken-4-l4` : `blue lighten-5`) : ``'
+                    )
+                    v-list-item-avatar(size='24')
+                      v-icon(:color='currentRenderer.key === rdr.key ? "primary" : "grey"') {{rdr.icon}}
+                    v-list-item-content
+                      v-list-item-title {{rdr.title}}
+                      v-list-item-subtitle: .caption {{rdr.description}}
+                    v-list-item-avatar(size='24')
+                      status-indicator(v-if='rdr.isEnabled', positive, pulse)
+                      status-indicator(v-else, negative, pulse)
+                  v-divider.my-0(v-if='n < core.children.length - 1')
 
       v-flex(lg9, xs12)
         v-card.wiki-form.animated.fadeInUp
@@ -70,20 +76,20 @@
             v-icon.mr-2 {{currentRenderer.icon}}
             .subtitle-1 {{currentRenderer.title}}
             v-spacer
-            .pt-3.mt-1
-              v-switch(
-                dark
-                color='white'
-                label='Enabled'
-                v-model='currentRenderer.isEnabled'
-                )
+            v-switch(
+              dark
+              color='white'
+              label='Enabled'
+              v-model='currentRenderer.isEnabled'
+              hide-details
+              )
           v-card-text.pb-4.pt-2.pl-4
-            v-subheader.pl-0 Rendering Module Configuration
-            .body-1.ml-3(v-if='!currentRenderer.config || currentRenderer.config.length < 1') This rendering module has no configuration options you can modify.
+            .overline.my-5 Rendering Module Configuration
+            .body-2.ml-3(v-if='!currentRenderer.config || currentRenderer.config.length < 1'): em This rendering module has no configuration options you can modify.
             template(v-else, v-for='(cfg, idx) in currentRenderer.config')
               v-select(
                 v-if='cfg.value.type === "string" && cfg.value.enum'
-                outline
+                outlined
                 :items='cfg.value.enum'
                 :key='cfg.key'
                 :label='cfg.value.title'
@@ -103,7 +109,7 @@
                 )
               v-text-field(
                 v-else
-                outline
+                outlined
                 :key='cfg.key'
                 :label='cfg.value.title'
                 v-model='cfg.value.value'
@@ -111,7 +117,7 @@
                 persistent-hint
                 :class='cfg.value.hint ? "mb-2" : ""'
                 )
-              v-divider.my-3(v-if='idx < currentRenderer.config.length - 1')
+              v-divider.my-5(v-if='idx < currentRenderer.config.length - 1')
           v-card-chin
             v-spacer
             .caption.pr-3.grey--text Module: {{ currentRenderer.key }}
@@ -211,10 +217,17 @@ export default {
 
 <style lang='scss'>
 .adm-rendering-pipeline {
-  border-top: 1px solid #FFF;
+  .v-expansion-panel--active .v-expansion-panel-header {
+    min-height: 0;
+  }
+
+  .v-expansion-panel-header {
+    padding: 0;
+    margin-top: 1px;
+  }
 
-  .v-expansion-panel__header {
-    padding: 0 0;
+  .v-expansion-panel-content__wrap {
+    padding: 0;
   }
 }
 </style>

+ 23 - 26
client/components/admin/admin-search.vue

@@ -8,13 +8,13 @@
             .headline.primary--text.animated.fadeInLeft {{$t('admin:search.title')}}
             .subtitle-1.grey--text.animated.fadeInLeft.wait-p2s {{$t('admin:search.subtitle')}}
           v-spacer
-          v-btn.animated.fadeInDown.wait-p2s(outline, color='grey', @click='refresh', large)
-            v-icon refresh
-          v-btn.animated.fadeInDown.wait-p1s(color='black', dark, large, depressed, @click='rebuild')
-            v-icon(left) cached
+          v-btn.mx-1.animated.fadeInDown.wait-p2s(outlined, color='grey', @click='refresh', large)
+            v-icon mdi-refresh
+          v-btn.mx-2.animated.fadeInDown.wait-p1s(color='black', dark, large, depressed, @click='rebuild')
+            v-icon(left) mdi-cached
             span {{$t('admin:search.rebuildIndex')}}
-          v-btn.animated.fadeInDown(color='success', @click='save', depressed, large)
-            v-icon(left) check
+          v-btn.ml-1.animated.fadeInDown(color='success', @click='save', depressed, large)
+            v-icon(left) mdi-check
             span {{$t('common:actions.apply')}}
 
       v-flex(lg3, xs12)
@@ -24,19 +24,19 @@
           v-list.py-0(two-line, dense)
             template(v-for='(eng, idx) in engines')
               v-list-item(:key='eng.key', @click='selectedEngine = eng.key', :disabled='!eng.isAvailable')
-                v-list-item-avatar
-                  v-icon(color='grey', v-if='!eng.isAvailable') cancel
-                  v-icon(color='primary', v-else-if='eng.key === selectedEngine') radio_button_checked
-                  v-icon(color='grey', v-else) radio_button_unchecked
+                v-list-item-avatar(size='24')
+                  v-icon(color='grey', v-if='!eng.isAvailable') mdi-minus-box-outline
+                  v-icon(color='primary', v-else-if='eng.key === selectedEngine') mdi-checkbox-marked-outline
+                  v-icon(color='grey', v-else) mdi-checkbox-blank-outline
                 v-list-item-content
                   v-list-item-title.body-2(:class='!eng.isAvailable ? `grey--text` : (selectedEngine === eng.key ? `primary--text` : ``)') {{ eng.title }}
-                  v-list-item-sub-title.caption(:class='!eng.isAvailable ? `grey--text text--lighten-1` : (selectedEngine === eng.key ? `blue--text ` : ``)') {{ eng.description }}
-                v-list-item-avatar(v-if='selectedEngine === eng.key')
-                  v-icon.animated.fadeInLeft(color='primary') arrow_forward_ios
+                  v-list-item-subtitle: .caption(:class='!eng.isAvailable ? `grey--text text--lighten-1` : (selectedEngine === eng.key ? `blue--text ` : ``)') {{ eng.description }}
+                v-list-item-avatar(v-if='selectedEngine === eng.key', size='24')
+                  v-icon.animated.fadeInLeft(color='primary', large) mdi-chevron-right
               v-divider(v-if='idx < engines.length - 1')
 
       v-flex(lg9, xs12)
-        v-card.wiki-form.animated.fadeInUp.wait-p2s
+        v-card.animated.fadeInUp.wait-p2s
           v-toolbar(color='primary', dense, flat, dark)
             .subtitle-1 {{engine.title}}
           v-card-text
@@ -45,18 +45,17 @@
             .caption.pt-3 {{engine.description}}
             .caption.pb-3: a(:href='engine.website') {{engine.website}}
             v-divider.mt-3
-            v-subheader.pl-0 {{$t('admin:search.engineConfig')}}
-            .body-1.ml-3(v-if='!engine.config || engine.config.length < 1') {{$t('admin:search.engineNoConfig')}}
+            .overline.my-5 {{$t('admin:search.engineConfig')}}
+            .body-2.ml-3(v-if='!engine.config || engine.config.length < 1'): em {{$t('admin:search.engineNoConfig')}}
             template(v-else, v-for='cfg in engine.config')
               v-select(
                 v-if='cfg.value.type === "string" && cfg.value.enum'
-                outline
-                background-color='grey lighten-2'
+                outlined
                 :items='cfg.value.enum'
                 :key='cfg.key'
                 :label='cfg.value.title'
                 v-model='cfg.value.value'
-                prepend-icon='settings_applications'
+                prepend-icon='mdi-settings-box'
                 :hint='cfg.value.hint ? cfg.value.hint : ""'
                 persistent-hint
                 :class='cfg.value.hint ? "mb-2" : ""'
@@ -67,30 +66,28 @@
                 :label='cfg.value.title'
                 v-model='cfg.value.value'
                 color='primary'
-                prepend-icon='settings_applications'
+                prepend-icon='mdi-settings-box'
                 :hint='cfg.value.hint ? cfg.value.hint : ""'
                 persistent-hint
                 )
               v-textarea(
                 v-else-if='cfg.value.type === "string" && cfg.value.multiline'
-                outline
-                background-color='grey lighten-2'
+                outlined
                 :key='cfg.key'
                 :label='cfg.value.title'
                 v-model='cfg.value.value'
-                prepend-icon='settings_applications'
+                prepend-icon='mdi-settings-box'
                 :hint='cfg.value.hint ? cfg.value.hint : ""'
                 persistent-hint
                 :class='cfg.value.hint ? "mb-2" : ""'
                 )
               v-text-field(
                 v-else
-                outline
-                background-color='grey lighten-2'
+                outlined
                 :key='cfg.key'
                 :label='cfg.value.title'
                 v-model='cfg.value.value'
-                prepend-icon='settings_applications'
+                prepend-icon='mdi-settings-box'
                 :hint='cfg.value.hint ? cfg.value.hint : ""'
                 persistent-hint
                 :class='cfg.value.hint ? "mb-2" : ""'

+ 30 - 34
client/components/admin/admin-storage.vue

@@ -8,10 +8,10 @@
             .headline.primary--text.animated.fadeInLeft {{$t('admin:storage.title')}}
             .subtitle-1.grey--text.animated.fadeInLeft.wait-p4s {{$t('admin:storage.subtitle')}}
           v-spacer
-          v-btn.animated.fadeInDown.wait-p2s(outline, color='grey', @click='refresh', large)
-            v-icon refresh
+          v-btn.mx-3.animated.fadeInDown.wait-p2s(outlined, color='grey', @click='refresh', large)
+            v-icon mdi-refresh
           v-btn.animated.fadeInDown(color='success', @click='save', depressed, large)
-            v-icon(left) check
+            v-icon(left) mdi-check
             span {{$t('common:actions.apply')}}
 
       v-flex(lg3, xs12)
@@ -21,15 +21,15 @@
           v-list(two-line, dense).py-0
             template(v-for='(tgt, idx) in targets')
               v-list-item(:key='tgt.key', @click='selectedTarget = tgt.key', :disabled='!tgt.isAvailable')
-                v-list-item-avatar
-                  v-icon(color='grey', v-if='!tgt.isAvailable') indeterminate_check_box
-                  v-icon(color='primary', v-else-if='tgt.isEnabled', v-ripple, @click='tgt.key !== `local` && (tgt.isEnabled = false)') check_box
-                  v-icon(color='grey', v-else, v-ripple, @click='tgt.isEnabled = true') check_box_outline_blank
+                v-list-item-avatar(size='24')
+                  v-icon(color='grey', v-if='!tgt.isAvailable') mdi-minus-box-outline
+                  v-icon(color='primary', v-else-if='tgt.isEnabled', v-ripple, @click='tgt.key !== `local` && (tgt.isEnabled = false)') mdi-checkbox-marked-outline
+                  v-icon(color='grey', v-else, v-ripple, @click='tgt.isEnabled = true') mdi-checkbox-blank-outline
                 v-list-item-content
                   v-list-item-title.body-2(:class='!tgt.isAvailable ? `grey--text` : (selectedTarget === tgt.key ? `primary--text` : ``)') {{ tgt.title }}
-                  v-list-item-sub-title.caption(:class='!tgt.isAvailable ? `grey--text text--lighten-1` : (selectedTarget === tgt.key ? `blue--text ` : ``)') {{ tgt.description }}
-                v-list-item-avatar(v-if='selectedTarget === tgt.key')
-                  v-icon.animated.fadeInLeft(color='primary') arrow_forward_ios
+                  v-list-item-subtitle: .caption(:class='!tgt.isAvailable ? `grey--text text--lighten-1` : (selectedTarget === tgt.key ? `blue--text ` : ``)') {{ tgt.description }}
+                v-list-item-avatar(v-if='selectedTarget === tgt.key', size='24')
+                  v-icon.animated.fadeInLeft(color='primary', large) mdi-chevron-right
               v-divider(v-if='idx < targets.length - 1')
 
         v-card.mt-3.animated.fadeInUp.wait-p2s
@@ -84,22 +84,20 @@
             v-form
               .targetlogo
                 img(:src='target.logo', :alt='target.title')
-              v-subheader.pl-0 {{target.title}}
-              .caption {{target.description}}
-              .caption: a(:href='target.website') {{target.website}}
+              .body-2.pt-3 {{target.description}}
+              .body-2.pt-3.pb-5: a(:href='target.website') {{target.website}}
               v-divider.mt-3
-              v-subheader.pl-0 {{$t('admin:storage.targetConfig')}}
-              .body-1.ml-3(v-if='!target.config || target.config.length < 1') {{$t('admin:storage.noConfigOption')}}
+              .overline.my-5 {{$t('admin:storage.targetConfig')}}
+              .body-2.ml-3(v-if='!target.config || target.config.length < 1'): em {{$t('admin:storage.noConfigOption')}}
               template(v-else, v-for='cfg in target.config')
                 v-select(
                   v-if='cfg.value.type === "string" && cfg.value.enum'
-                  outline
-                  background-color='grey lighten-2'
+                  outlined
                   :items='cfg.value.enum'
                   :key='cfg.key'
                   :label='cfg.value.title'
                   v-model='cfg.value.value'
-                  prepend-icon='settings_applications'
+                  prepend-icon='mdi-settings-box'
                   :hint='cfg.value.hint ? cfg.value.hint : ""'
                   persistent-hint
                   :class='cfg.value.hint ? "mb-2" : ""'
@@ -110,37 +108,35 @@
                   :label='cfg.value.title'
                   v-model='cfg.value.value'
                   color='primary'
-                  prepend-icon='settings_applications'
+                  prepend-icon='mdi-settings-box'
                   :hint='cfg.value.hint ? cfg.value.hint : ""'
                   persistent-hint
                   )
                 v-textarea(
                   v-else-if='cfg.value.type === "string" && cfg.value.multiline'
-                  outline
-                  background-color='grey lighten-2'
+                  outlined
                   :key='cfg.key'
                   :label='cfg.value.title'
                   v-model='cfg.value.value'
-                  prepend-icon='settings_applications'
+                  prepend-icon='mdi-settings-box'
                   :hint='cfg.value.hint ? cfg.value.hint : ""'
                   persistent-hint
                   :class='cfg.value.hint ? "mb-2" : ""'
                   )
                 v-text-field(
                   v-else
-                  outline
-                  background-color='grey lighten-2'
+                  outlined
                   :key='cfg.key'
                   :label='cfg.value.title'
                   v-model='cfg.value.value'
-                  prepend-icon='settings_applications'
+                  prepend-icon='mdi-settings-box'
                   :hint='cfg.value.hint ? cfg.value.hint : ""'
                   persistent-hint
                   :class='cfg.value.hint ? "mb-2" : ""'
                   )
               v-divider.mt-3
-              v-subheader.pl-0 {{$t('admin:storage.syncDirection')}}
-              .body-1.ml-3 {{$t('admin:storage.syncDirectionSubtitle')}}
+              .overline.my-5 {{$t('admin:storage.syncDirection')}}
+              .body-2.ml-3 {{$t('admin:storage.syncDirectionSubtitle')}}
               .pr-3.pt-3
                 v-radio-group.ml-3.py-0(v-model='target.mode')
                   v-radio(
@@ -161,7 +157,7 @@
                     value='pull'
                     :disabled='target.supportedModes.indexOf(`pull`) < 0'
                   )
-              .body-1.ml-3
+              .body-2.ml-3
                 strong {{$t('admin:storage.syncDirBi')}} #[em.red--text.text--lighten-2(v-if='target.supportedModes.indexOf(`sync`) < 0') {{$t('admin:storage.unsupported')}}]
                 .pb-3 {{$t('admin:storage.syncDirBiHint')}}
                 strong {{$t('admin:storage.syncDirPush')}} #[em.red--text.text--lighten-2(v-if='target.supportedModes.indexOf(`push`) < 0') {{$t('admin:storage.unsupported')}}]
@@ -171,8 +167,8 @@
 
               template(v-if='target.hasSchedule')
                 v-divider.mt-3
-                v-subheader.pl-0 {{$t('admin:storage.syncSchedule')}}
-                .body-1.ml-3 {{$t('admin:storage.syncScheduleHint')}}
+                .overline.my-5 {{$t('admin:storage.syncSchedule')}}
+                .body-2.ml-3 {{$t('admin:storage.syncScheduleHint')}}
                 .pa-3
                   duration-picker(v-model='target.syncInterval')
                   i18next.caption.mt-3(path='admin:storage.syncScheduleCurrent', tag='div')
@@ -182,17 +178,17 @@
 
               template(v-if='target.actions && target.actions.length > 0')
                 v-divider.mt-3
-                v-subheader.pl-0 {{$t('admin:storage.actions')}}
+                .overline.my-5 {{$t('admin:storage.actions')}}
                 v-container.pt-0(grid-list-xl, fluid)
                   v-layout(row, wrap, fill-height)
                     v-flex(xs12, lg6, xl4, v-for='act of target.actions', :key='act.handler')
                       v-card.radius-7.grey(flat, :class='$vuetify.dark ? `darken-3-d5` : `lighten-3`', height='100%')
                         v-card-text
                           .subtitle-1(v-html='act.label')
-                          .body-1.mt-2(v-html='act.hint')
-                          v-btn.mx-0.mt-3(
+                          .body-2.mt-4(v-html='act.hint')
+                          v-btn.mx-0.mt-5(
                             @click='executeAction(target.key, act.handler)'
-                            outline
+                            outlined
                             :color='$vuetify.dark ? `blue` : `primary`'
                             :disabled='runningAction'
                             :loading='runningActionHandler === act.handler'

+ 6 - 0
client/components/admin/admin-theme.vue

@@ -167,11 +167,17 @@ export default {
       ]
     }
   },
+  watch: {
+    'darkMode' (newValue, oldValue) {
+      this.$vuetify.theme.dark = newValue
+    }
+  },
   mounted() {
     this.darkModeInitial = this.darkMode
   },
   beforeDestroy() {
     this.darkMode = this.darkModeInitial
+    this.$vuetify.theme.dark = this.darkModeInitial
   },
   methods: {
     async save () {

+ 1 - 1
client/components/admin/admin-utilities-content.vue

@@ -6,7 +6,7 @@
       .subtitle-1.pb-3.pl-0.primary--text Migrate all pages to target locale
       .body-2 If you created content before selecting a different locale and activating the namespacing capabilities, you may want to transfer all content to the base locale.
       .body-2.red--text: strong This operation is destructive and cannot be reversed! Make sure you have proper backups!
-      v-toolbar.mt-5(flat, color='grey lighten-4', height='80')
+      v-toolbar.radius-7.mt-5(flat, :color='$vuetify.theme.dark ? `grey darken-3-d5` : `grey lighten-4`', height='80')
         v-select(
           label='Source Locale'
           outlined

+ 1 - 1
client/components/common/v-card-chin.vue

@@ -8,7 +8,7 @@
 <script>
 export default {
   computed: {
-    dark() { return this.$vuetify.dark }
+    dark() { return this.$vuetify.theme.dark }
   }
 }
 </script>

+ 42 - 41
client/scss/base/base.scss

@@ -19,59 +19,60 @@ html {
   }
 }
 
-.application--wrap {
+.v-application--wrap {
   transition: all 1.2s ease;
   transform-origin: 50% 50%;
-  background-color: #FFF;
+  // background-color: #FFF;
 
   @at-root .theme--dark & {
     background-color: mc('grey', '900');
   }
 }
 
-
-@for $i from 0 through 25 {
-  .radius-#{$i} {
-    border-radius: #{$i}px;
+.v-application {
+  @for $i from 0 through 25 {
+    .radius-#{$i} {
+      border-radius: #{$i}px;
+    }
   }
-}
 
-@for $i from 1 through 5 {
-  .grey.darken-2-d#{$i} {
-    background-color: darken(mc('grey', '700'), percentage($i/100)) !important;
-    border-color: darken(mc('grey', '700'), percentage($i/100)) !important;
-  }
-  .grey.darken-2-l#{$i} {
-    background-color: lighten(mc('grey', '700'), percentage($i/100)) !important;
-    border-color: lighten(mc('grey', '700'), percentage($i/100)) !important;
+  @for $i from 1 through 5 {
+    .grey.darken-2-d#{$i} {
+      background-color: darken(mc('grey', '700'), percentage($i/100)) !important;
+      border-color: darken(mc('grey', '700'), percentage($i/100)) !important;
+    }
+    .grey.darken-2-l#{$i} {
+      background-color: lighten(mc('grey', '700'), percentage($i/100)) !important;
+      border-color: lighten(mc('grey', '700'), percentage($i/100)) !important;
+    }
+    .grey.darken-3-d#{$i} {
+      background-color: darken(mc('grey', '800'), percentage($i/100)) !important;
+      border-color: darken(mc('grey', '800'), percentage($i/100)) !important;
+    }
+    .grey.darken-3-l#{$i} {
+      background-color: lighten(mc('grey', '800'), percentage($i/100)) !important;
+      border-color: lighten(mc('grey', '800'), percentage($i/100)) !important;
+    }
+    .grey.darken-4-d#{$i} {
+      background-color: darken(mc('grey', '900'), percentage($i/100)) !important;
+      border-color: darken(mc('grey', '900'), percentage($i/100)) !important;
+    }
+    .grey.darken-4-l#{$i} {
+      background-color: lighten(mc('grey', '900'), percentage($i/100)) !important;
+      border-color: lighten(mc('grey', '900'), percentage($i/100)) !important;
+    }
   }
-  .grey.darken-3-d#{$i} {
-    background-color: darken(mc('grey', '800'), percentage($i/100)) !important;
-    border-color: darken(mc('grey', '800'), percentage($i/100)) !important;
+  .grey.darken-5 {
+    background-color: #0C0C0C !important;
+    border-color: #0C0C0C !important;
   }
-  .grey.darken-3-l#{$i} {
-    background-color: lighten(mc('grey', '800'), percentage($i/100)) !important;
-    border-color: lighten(mc('grey', '800'), percentage($i/100)) !important;
-  }
-  .grey.darken-4-d#{$i} {
-    background-color: darken(mc('grey', '900'), percentage($i/100)) !important;
-    border-color: darken(mc('grey', '900'), percentage($i/100)) !important;
+
+  .blue.darken-5 {
+    background-color: darken(mc('blue', '900'), 20%) !important;
+    border-color: darken(mc('blue', '900'), 20%) !important;
   }
-  .grey.darken-4-l#{$i} {
-    background-color: lighten(mc('grey', '900'), percentage($i/100)) !important;
-    border-color: lighten(mc('grey', '900'), percentage($i/100)) !important;
+  .indigo.darken-5 {
+    background-color: darken(mc('indigo', '900'), 10%) !important;
+    border-color: darken(mc('indigo', '900'), 10%) !important;
   }
 }
-.grey.darken-5 {
-  background-color: #0C0C0C !important;
-  border-color: #0C0C0C !important;
-}
-
-.blue.darken-5 {
-  background-color: darken(mc('blue', '900'), 20%) !important;
-  border-color: darken(mc('blue', '900'), 20%) !important;
-}
-.indigo.darken-5 {
-  background-color: darken(mc('indigo', '900'), 10%) !important;
-  border-color: darken(mc('indigo', '900'), 10%) !important;
-}

+ 7 - 7
client/themes/default/components/page.vue

@@ -2,7 +2,7 @@
   v-app(v-scroll='upBtnScroll', :dark='darkMode')
     nav-header
     v-navigation-drawer(
-      :class='darkMode ? `grey darken-5` : `primary`'
+      :class='darkMode ? `grey darken-4-d4` : `primary`'
       dark
       app
       clipped
@@ -12,7 +12,7 @@
       :right='$vuetify.rtl'
       )
       vue-scroll(:ops='scrollStyle')
-        nav-sidebar(:color='darkMode ? `grey darken-5` : `primary`', :items='sidebar')
+        nav-sidebar(:color='darkMode ? `grey darken-4-d4` : `primary`', :items='sidebar')
 
     v-fab-transition
       v-btn(
@@ -57,7 +57,7 @@
         v-layout(row)
           v-flex.page-col-sd(lg3, xl2, fill-height, v-if='$vuetify.breakpoint.lgAndUp', style='margin-top: -90px;')
             v-card(v-if='toc.length')
-              .overline.pa-5.pb-0(:class='darkMode ? `indigo--text text--lighten-3` : `primary--text`') {{$t('common:page.toc')}}
+              .overline.pa-5.pb-0(:class='darkMode ? `blue--text text--lighten-2` : `primary--text`') {{$t('common:page.toc')}}
               v-list.pb-3(dense, nav, :class='darkMode ? `darken-3-d3` : ``')
                 template(v-for='(tocItem, tocIdx) in toc')
                   v-list-item(@click='$vuetify.goTo(tocItem.anchor, scrollOpts)')
@@ -67,12 +67,12 @@
                   template(v-for='tocSubItem in tocItem.children')
                     v-list-item(@click='$vuetify.goTo(tocSubItem.anchor, scrollOpts)')
                       v-icon.pl-3(color='grey lighten-1', small) mdi-chevron-right
-                      v-list-item-title.pl-3.caption.grey--text.text--darken-1 {{tocSubItem.title}}
+                      v-list-item-title.pl-3.caption.grey--text(:class='darkMode ? `text--lighten-1` : `text--darken-1`') {{tocSubItem.title}}
                     //- v-divider(inset, v-if='tocIdx < toc.length - 1')
 
             v-card.mt-5
               .pa-5.pt-3
-                .overline.indigo--text.d-flex.align-center
+                .overline.indigo--text.d-flex.align-center(:class='$vuetify.theme.dark ? `text--lighten-3` : ``')
                   span {{$t('common:page.lastEditedBy')}}
                   v-spacer
                   v-tooltip(top, v-if='isAuthenticated')
@@ -85,7 +85,7 @@
 
             v-card.mt-5(v-if='tags.length > 0 || true')
               .pa-5
-                .overline.teal--text.pb-2 Tags
+                .overline.teal--text.pb-2(:class='$vuetify.theme.dark ? `text--lighten-3` : ``') Tags
                 v-chip.mr-1(
                   label
                   color='teal lighten-5'
@@ -98,7 +98,7 @@
 
             v-card.mt-5
               .pa-5
-                .overline.pb-2.yellow--text.text--darken-4 Rating
+                .overline.pb-2.yellow--text(:class='$vuetify.theme.dark ? `text--darken-3` : `text--darken-4`') Rating
                 .text-center
                   v-rating(
                     v-model='rating'

+ 8 - 8
client/themes/default/scss/app.scss

@@ -10,11 +10,11 @@
   }
 
   @at-root .theme--dark & {
-    background-color: darken(mc('grey', '900'), 4%);
+    // background-color: darken(mc('grey', '900'), 4%);
     color: mc('grey', '300');
 
     a {
-      color: mc('indigo', '200');
+      color: mc('blue', '100');
     }
   }
 
@@ -57,7 +57,7 @@
     position: relative;
 
     @at-root .theme--dark & {
-      color: mc('teal', '100');
+      color: mc('grey', '300');
     }
 
     &::after {
@@ -71,7 +71,7 @@
       border-radius: 3px;
 
       @at-root .theme--dark & {
-        background: linear-gradient(to right, mc('teal', '300') 0%, mc('teal', '500') 10%, rgba(mc('teal', '900'), 0) 100%);
+        background: linear-gradient(to right, mc('blue', '300') 0%, mc('blue', '500') 10%, rgba(mc('blue', '900'), 0) 100%);
       }
 
       @at-root .application--is-rtl & {
@@ -227,7 +227,7 @@
 
       @at-root .theme--dark & {
         background-color: mc('grey', '900');
-        background-image: radial-gradient(ellipse at top, mc('blue', '900'), rgba(darken(mc('blue', '900'), 5%), .2));
+        background-image: radial-gradient(ellipse at top, rgba(mc('blue', '900'), .25), rgba(darken(mc('blue', '900'), 5%), .2));
         border-color: mc('blue', '500');
         box-shadow: 0 0 2px 0 mc('grey', '900');
       }
@@ -245,7 +245,7 @@
 
       @at-root .theme--dark & {
         background-color: mc('grey', '900');
-        background-image: radial-gradient(ellipse at top, mc('orange', '900'), rgba(darken(mc('orange', '900'), 5%), .2));
+        background-image: radial-gradient(ellipse at top, rgba(mc('orange', '900'), .25), rgba(darken(mc('orange', '900'), 5%), .2));
         border-color: mc('orange', '500');
         box-shadow: 0 0 2px 0 mc('grey', '900');
       }
@@ -263,7 +263,7 @@
 
       @at-root .theme--dark & {
         background-color: mc('grey', '900');
-        background-image: radial-gradient(ellipse at top, mc('red', '900'), rgba(darken(mc('red', '900'), 5%), .2));
+        background-image: radial-gradient(ellipse at top, rgba(mc('red', '900'), .1), rgba(darken(mc('red', '900'), 5%), .2));
         border-color: mc('red', '500');
         box-shadow: 0 0 2px 0 mc('grey', '900');
       }
@@ -281,7 +281,7 @@
 
       @at-root .theme--dark & {
         background-color: mc('grey', '900');
-        background-image: radial-gradient(ellipse at top, mc('green', '900'), rgba(darken(mc('green', '900'), 5%), .2));
+        background-image: radial-gradient(ellipse at top, rgba(mc('green', '900'), .4), rgba(darken(mc('green', '900'), 5%), .2));
         border-color: mc('green', '500');
         box-shadow: 0 0 2px 0 mc('grey', '900');
       }

+ 1 - 1
server/modules/rendering/html-asciinema/definition.yml

@@ -2,7 +2,7 @@ key: htmlAsciinema
 title: Asciinema
 description: Embed asciinema players from compatible links
 author: requarks.io
-icon: subtitles
+icon: mdi-theater
 enabledDefault: false
 dependsOn: htmlCore
 props: {}

+ 1 - 1
server/modules/rendering/html-blockquotes/definition.yml

@@ -2,7 +2,7 @@ key: htmlBlockquotes
 title: Blockquotes
 description: Parse blockquotes box styling
 author: requarks.io
-icon: insert_comment
+icon: mdi-alpha-t-box-outline
 enabledDefault: true
 dependsOn: htmlCore
 props: {}

+ 1 - 1
server/modules/rendering/html-codehighlighter/definition.yml

@@ -2,7 +2,7 @@ key: htmlCodehighlighter
 title: Code Highlighting Post-Processor
 description: Syntax detector for programming code
 author: requarks.io
-icon: palette
+icon: mdi-code-braces
 enabledDefault: true
 dependsOn: htmlCore
 props: {}

+ 1 - 1
server/modules/rendering/html-core/definition.yml

@@ -4,5 +4,5 @@ description: Basic HTML Parser
 author: requarks.io
 input: html
 output: html
-icon: crop_free
+icon: mdi-language-html5
 props: {}

+ 1 - 1
server/modules/rendering/html-mathjax/definition.yml

@@ -2,7 +2,7 @@ key: htmlMathjax
 title: Mathjax Processor
 description: TeX/MathML Math Equations Parser
 author: requarks.io
-icon: functions
+icon: mdi-function-variant
 enabledDefault: false
 dependsOn: htmlCore
 props: {}

+ 1 - 1
server/modules/rendering/html-mediaplayers/definition.yml

@@ -2,7 +2,7 @@ key: htmlMediaplayers
 title: Media Players
 description: Embed players such as Youtube, Vimeo, Soundcloud, etc.
 author: requarks.io
-icon: subscriptions
+icon: mdi-library-video
 enabledDefault: true
 dependsOn: htmlCore
 props: {}

+ 1 - 1
server/modules/rendering/html-mermaid/definition.yml

@@ -2,7 +2,7 @@ key: htmlMermaid
 title: Mermaid
 description: Generate flowcharts from Mermaid syntax
 author: requarks.io
-icon: merge_type
+icon: mdi-arrow-decision-outline
 enabledDefault: false
 dependsOn: htmlCore
 props: {}

+ 1 - 1
server/modules/rendering/html-plantuml/definition.yml

@@ -2,7 +2,7 @@ key: htmlPlantuml
 title: PlantUML
 description: Generate diagrams from PlantUML syntax
 author: requarks.io
-icon: multiline_chart
+icon: mdi-sitemap
 enabledDefault: false
 dependsOn: htmlCore
 props: {}

+ 1 - 1
server/modules/rendering/html-security/definition.yml

@@ -2,7 +2,7 @@ key: htmlSecurity
 title: Security
 description: Filter and strips potentially dangerous content
 author: requarks.io
-icon: whatshot
+icon: mdi-fire
 enabledDefault: true
 dependsOn: htmlCore
 props:

+ 1 - 1
server/modules/rendering/html-twemoji/definition.yml

@@ -2,7 +2,7 @@ key: htmlTwemoji
 title: Twemoji
 description: Apply Twitter Emojis to all Unicode emojis
 author: requarks.io
-icon: whatshot
+icon: mdi-emoticon-happy-outline
 enabledDefault: true
 dependsOn: htmlCore
 props: {}

+ 1 - 1
server/modules/rendering/markdown-abbr/definition.yml

@@ -2,7 +2,7 @@ key: markdownAbbr
 title: Abbreviations
 description: Parse abbreviations into abbr tags
 author: requarks.io
-icon: text_format
+icon: mdi-contain-start
 enabledDefault: true
 dependsOn: markdownCore
 props: {}

+ 1 - 1
server/modules/rendering/markdown-core/definition.yml

@@ -4,7 +4,7 @@ description: Basic Markdown Parser
 author: requarks.io
 input: markdown
 output: html
-icon: crop_free
+icon: mdi-markdown
 props:
   allowHTML:
     type: Boolean

+ 1 - 1
server/modules/rendering/markdown-emoji/definition.yml

@@ -2,7 +2,7 @@ key: markdownEmoji
 title: Emoji
 description: Convert tags to emojis
 author: requarks.io
-icon: tag_faces
+icon: mdi-sticker-emoji
 enabledDefault: true
 dependsOn: markdownCore
 props: {}

+ 1 - 1
server/modules/rendering/markdown-expandtabs/definition.yml

@@ -2,7 +2,7 @@ key: markdownExpandtabs
 title: Expand Tabs
 description: Replace tabs with spaces in code blocks
 author: requarks.io
-icon: space_bar
+icon: mdi-arrow-expand-horizontal
 enabledDefault: true
 dependsOn: markdownCore
 props:

+ 1 - 1
server/modules/rendering/markdown-footnotes/definition.yml

@@ -2,7 +2,7 @@ key: markdownFootnotes
 title: Footnotes
 description: Parse footnotes references
 author: requarks.io
-icon: low_priority
+icon: mdi-page-layout-footer
 enabledDefault: true
 dependsOn: markdownCore
 props: {}

+ 1 - 1
server/modules/rendering/markdown-imsize/definition.yml

@@ -2,7 +2,7 @@ key: markdownImsize
 title: Image Size
 description: Adds dimensions attributes to images
 author: requarks.io
-icon: insert_photo
+icon: mdi-image-size-select-large
 enabledDefault: true
 dependsOn: markdownCore
 props: {}

+ 1 - 1
server/modules/rendering/markdown-mathjax/definition.yml

@@ -2,7 +2,7 @@ key: markdownMathjax
 title: Mathjax Preprocessor
 description: Prepare TeX blocks for Mathjax
 author: requarks.io
-icon: functions
+icon: mdi-function-variant
 enabledDefault: false
 dependsOn: markdownCore
 props: {}

+ 1 - 1
server/modules/rendering/markdown-supsub/definition.yml

@@ -2,7 +2,7 @@ key: markdownSupsub
 title: Subscript/Superscript
 description: Parse subscript and superscript tags
 author: requarks.io
-icon: format_size
+icon: mdi-format-superscript
 enabledDefault: true
 dependsOn: markdownCore
 props:

+ 1 - 1
server/modules/rendering/markdown-tasklists/definition.yml

@@ -2,7 +2,7 @@ key: markdownTasklists
 title: Task Lists
 description: Parse task lists to checkboxes
 author: requarks.io
-icon: list
+icon: mdi-format-list-checks
 enabledDefault: true
 dependsOn: markdownCore
 props: {}

+ 5 - 1
server/setup.js

@@ -125,7 +125,11 @@ module.exports = () => {
       })
       _.set(WIKI.config, 'theming', {
         theme: 'default',
-        darkMode: false
+        darkMode: false,
+        iconset: 'mdi',
+        injectCSS: '',
+        injectHead: '',
+        injectBody: ''
       })
       _.set(WIKI.config, 'title', 'Wiki.js')
 

+ 7 - 0
server/views/legacy/master.pug

@@ -65,6 +65,13 @@ html
       )
       
     
+      
+    script(
+      type='text/javascript'
+      src='/legacy.35e1a512a39dbf80760e.hot-update.js'
+      )
+      
+    
 
     != analyticsCode.head
 

+ 7 - 0
server/views/master.pug

@@ -64,6 +64,13 @@ html
       )
       
     
+      
+    script(
+      type='text/javascript'
+      src='/app.35e1a512a39dbf80760e.hot-update.js'
+      )
+      
+    
 
     != analyticsCode.head