Преглед изворни кода

misc: admin vuetify 2.0 UI + arabic display improvements

Nick пре 5 година
родитељ
комит
577a061033
52 измењених фајлова са 239 додато и 202 уклоњено
  1. 1 1
      client/components/admin/admin-auth.vue
  2. 1 0
      client/components/admin/admin-contribute.vue
  3. 2 2
      client/components/admin/admin-dashboard.vue
  4. 1 1
      client/components/admin/admin-general.vue
  5. 2 2
      client/components/admin/admin-groups-edit-permissions.vue
  6. 10 10
      client/components/admin/admin-groups-edit-rules.vue
  7. 1 1
      client/components/admin/admin-groups-edit-users.vue
  8. 1 1
      client/components/admin/admin-groups-edit.vue
  9. 5 1
      client/components/admin/admin-locale.vue
  10. 54 53
      client/components/admin/admin-pages-edit.vue
  11. 10 14
      client/components/admin/admin-pages.vue
  12. 3 3
      client/components/admin/admin-storage.vue
  13. 1 1
      client/components/admin/admin-system.vue
  14. 1 1
      client/components/admin/admin-theme.vue
  15. 1 1
      client/components/admin/admin-users.vue
  16. 1 1
      client/components/common/duration-picker.vue
  17. 9 9
      client/components/common/nav-header.vue
  18. 1 1
      client/components/common/user-search.vue
  19. 24 24
      client/components/editor/editor-modal-media.vue
  20. 10 0
      client/index-app.js
  21. 0 3
      client/scss/app.scss
  22. 0 55
      client/scss/base/fonts.scss
  23. 43 0
      client/scss/fonts/arabic.scss
  24. 55 0
      client/scss/fonts/default.scss
  25. 0 1
      client/scss/legacy.scss
  26. BIN
      client/static/fonts/MaterialIcons-Regular.woff
  27. BIN
      client/static/fonts/MaterialIcons-Regular.woff2
  28. BIN
      client/static/fonts/arabic/BalooBhaijaan-Regular.woff
  29. BIN
      client/static/fonts/arabic/BalooBhaijaan-Regular.woff2
  30. BIN
      client/static/fonts/arabic/Tajawal-Bold.woff
  31. BIN
      client/static/fonts/arabic/Tajawal-Bold.woff2
  32. BIN
      client/static/fonts/arabic/Tajawal-Medium.woff
  33. BIN
      client/static/fonts/arabic/Tajawal-Medium.woff2
  34. BIN
      client/static/fonts/arabic/Tajawal-Regular.woff
  35. BIN
      client/static/fonts/arabic/Tajawal-Regular.woff2
  36. 0 0
      client/static/fonts/default/Roboto-Bold.woff
  37. 0 0
      client/static/fonts/default/Roboto-Bold.woff2
  38. 0 0
      client/static/fonts/default/Roboto-BoldItalic.woff
  39. 0 0
      client/static/fonts/default/Roboto-BoldItalic.woff2
  40. 0 0
      client/static/fonts/default/Roboto-Italic.woff
  41. 0 0
      client/static/fonts/default/Roboto-Italic.woff2
  42. 0 0
      client/static/fonts/default/Roboto-Medium.woff
  43. 0 0
      client/static/fonts/default/Roboto-Medium.woff2
  44. 0 0
      client/static/fonts/default/Roboto-MediumItalic.woff
  45. 0 0
      client/static/fonts/default/Roboto-MediumItalic.woff2
  46. 0 0
      client/static/fonts/default/Roboto-Regular.woff
  47. 0 0
      client/static/fonts/default/Roboto-Regular.woff2
  48. 0 0
      client/static/fonts/default/RobotoMono-Regular.woff
  49. 0 0
      client/static/fonts/default/RobotoMono-Regular.woff2
  50. 1 1
      dev/templates/master.pug
  51. 0 7
      server/views/legacy/master.pug
  52. 1 8
      server/views/master.pug

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

@@ -198,7 +198,7 @@
               i18next(path='admin:auth.siteUrlNotSetup', tag='span')
                 strong(place='siteUrl') {{$t('admin:general.siteUrl')}}
                 strong(place='general') {{$t('admin:general.title')}}
-            .pa-3.mt-3.radius-7.grey(v-else, :class='$vuetify.dark ? `darken-3-d5` : `lighten-3`')
+            .pa-3.mt-3.radius-7.grey(v-else, :class='$vuetify.theme.dark ? `darken-3-d5` : `lighten-3`')
               .body-2: strong {{$t('admin:auth.allowedWebOrigins')}}
               .body-2 {{host}}
               v-divider.my-3

+ 1 - 0
client/components/admin/admin-contribute.vue

@@ -252,6 +252,7 @@ export default {
     margin-bottom: 12px;
     border-radius: 7px;
     background-color: mc('grey', '100');
+    color: mc('grey', '700');
     padding: 12px;
 
     strong {

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

@@ -45,7 +45,7 @@
           :class='isLatestVersion ? "teal lighten-2" : "red lighten-2"'
           dark
           )
-          v-btn.btn-animate-wrench(fab, absolute, right, top, small, light, to='system', v-if='hasPermission(`manage:system`)')
+          v-btn.btn-animate-wrench(fab, absolute, :right='!$vuetify.rtl', :left='$vuetify.rtl', top, small, light, to='system', v-if='hasPermission(`manage:system`)')
             v-icon(:color='isLatestVersion ? `teal` : `red darken-4`', small) mdi-wrench
           v-card-text
             v-icon.dashboard-icon mdi-blur
@@ -95,7 +95,7 @@
               .subtitle-1 {{$t('admin:contribute.title')}}
               .body-2.mt-3: strong {{$t('admin:dashboard.contributeSubtitle')}}
               .body-2 {{$t('admin:dashboard.contributeHelp')}}
-              v-btn.mx-0.mt-4(:color='$vuetify.dark ? `indigo lighten-3` : `indigo`', outlined, small, to='/contribute')
+              v-btn.mx-0.mt-4(:color='$vuetify.theme.dark ? `indigo lighten-3` : `indigo`', outlined, small, to='/contribute')
                 .caption: strong {{$t('admin:dashboard.contributeLearnMore')}}
 
 </template>

+ 1 - 1
client/components/admin/admin-general.vue

@@ -44,7 +44,7 @@
                   .overline.grey--text.pa-4 {{$t('admin:general.logo')}} #[v-chip.ml-2(label, color='grey', small, outlined) coming soon]
                   v-card-text.pb-4.pl-5
                     v-layout.px-3(row, align-center)
-                      v-avatar(size='100', :color='$vuetify.dark ? `grey darken-2` : `grey lighten-3`', :tile='config.logoIsSquare')
+                      v-avatar(size='100', :color='$vuetify.theme.dark ? `grey darken-2` : `grey lighten-3`', :tile='config.logoIsSquare')
                       .ml-4
                         v-btn.mr-3(color='teal', depressed, disabled)
                           v-icon(left) mdi-cloud-upload

+ 2 - 2
client/components/admin/admin-groups-edit-permissions.vue

@@ -12,7 +12,7 @@
       v-alert.radius-7(
         v-if='group.isSystem'
         color='orange darken-2'
-        :class='$vuetify.dark ? "grey darken-4" : "orange lighten-5"'
+        :class='$vuetify.theme.dark ? "grey darken-4" : "orange lighten-5"'
         outline
         :value='true'
         icon='lock_outline'
@@ -20,7 +20,7 @@
     v-container.px-3.pb-3.pt-0(fluid, grid-list-md)
       v-layout(row, wrap)
         v-flex(xs12, md6, lg4, v-for='pmGroup in permissions', :key='pmGroup.category')
-          v-card.md2(flat, :class='$vuetify.dark ? "grey darken-3-d5" : "white"')
+          v-card.md2(flat, :class='$vuetify.theme.dark ? "grey darken-3-d5" : "white"')
             v-subheader {{pmGroup.category}}
             v-card-text.pt-0
               template(v-for='(pm, idx) in pmGroup.items')

+ 10 - 10
client/components/admin/admin-groups-edit-rules.vue

@@ -2,16 +2,16 @@
   v-card.wiki-form
     v-card-text(v-if='group.id === 1')
       v-alert.radius-7(
-        :class='$vuetify.dark ? "grey darken-4" : "orange lighten-5"'
+        :class='$vuetify.theme.dark ? "grey darken-4" : "orange lighten-5"'
         color='orange darken-2'
         outline
         :value='true'
         icon='lock_outline'
         ) This group has access to everything.
     template(v-else)
-      v-card-title(:class='$vuetify.dark ? `grey darken-3-d5` : `grey lighten-5`')
+      v-card-title(:class='$vuetify.theme.dark ? `grey darken-3-d5` : `grey lighten-5`')
         v-alert.radius-7(
-          :class='$vuetify.dark ? `grey darken-3-d3` : `white`'
+          :class='$vuetify.theme.dark ? `grey darken-3-d3` : `white`'
           :value='true'
           color='grey'
           outline
@@ -48,10 +48,10 @@
               v-list-item-avatar
                 v-icon cloud_download
               v-list-item-title Export Rules
-      v-card-text(:class='$vuetify.dark ? `grey darken-4-l5` : `white`')
+      v-card-text(:class='$vuetify.theme.dark ? `grey darken-4-l5` : `white`')
         .rules
           .caption(v-if='group.pageRules.length === 0')
-            em(:class='$vuetify.dark ? `grey--text` : `blue-grey--text`') This group has no page rules yet.
+            em(:class='$vuetify.theme.dark ? `grey--text` : `blue-grey--text`') This group has no page rules yet.
           .rule(v-for='rule of group.pageRules', :key='rule.id')
             v-btn.ma-0.rule-deny-btn(
               solo
@@ -90,7 +90,7 @@
                 v-icon.mr-2(:color='rule.deny ? `red` : `green`') {{props.item.icon}}
                 v-list-item-content
                   v-list-item-title.body-2 {{props.item.text}}
-                v-chip.mr-2.grey--text(label, small, :color='$vuetify.dark ? `grey darken-4` : `grey lighten-4`').caption {{props.item.value}}
+                v-chip.mr-2.grey--text(label, small, :color='$vuetify.theme.dark ? `grey darken-4` : `grey lighten-4`').caption {{props.item.value}}
 
             //- Match
             v-select.ml-1.mr-1(
@@ -111,7 +111,7 @@
                   v-list-item-title(v-html='data.item.text')
             //- Locales
             v-select.mr-1(
-              :background-color='$vuetify.dark ? `grey darken-3-d5` : `blue-grey lighten-5`'
+              :background-color='$vuetify.theme.dark ? `grey darken-3-d5` : `blue-grey lighten-5`'
               solo
               :items='locales'
               v-model='rule.locales'
@@ -147,7 +147,7 @@
                 v-icon.mr-2(:color='rule.deny ? `red` : `green`') language
                 v-list-item-content
                   v-list-item-title.body-2 {{props.item.text}}
-                v-chip.mr-2.grey--text(label, small, :color='$vuetify.dark ? `grey darken-4` : `grey lighten-4`').caption {{props.item.value.toUpperCase()}}
+                v-chip.mr-2.grey--text(label, small, :color='$vuetify.theme.dark ? `grey darken-4` : `grey lighten-4`').caption {{props.item.value.toUpperCase()}}
 
             //- Path
             v-text-field(
@@ -158,11 +158,11 @@
               :placeholder='rule.match === `REGEX` ? `Regular Expression` : `Path`'
               :suffix='rule.match === `REGEX` ? `/` : null'
               hide-details
-              :color='$vuetify.dark ? `grey` : `blue-grey`'
+              :color='$vuetify.theme.dark ? `grey` : `blue-grey`'
               )
 
             v-btn(icon, @click='removeRule(rule.id)')
-              v-icon(:color='$vuetify.dark ? `grey` : `blue-grey`') clear
+              v-icon(:color='$vuetify.theme.dark ? `grey` : `blue-grey`') clear
 
         v-divider.mt-3
         v-subheader.pl-0 Rules Order

+ 1 - 1
client/components/admin/admin-groups-edit-users.vue

@@ -1,6 +1,6 @@
 <template lang="pug">
   v-card.wiki-form
-    v-card-title(:class='$vuetify.dark ? `grey darken-3-d3` : `grey lighten-5`')
+    v-card-title(:class='$vuetify.theme.dark ? `grey darken-3-d3` : `grey lighten-5`')
       v-text-field(
         outline
         flat

+ 1 - 1
client/components/admin/admin-groups-edit.vue

@@ -26,7 +26,7 @@
             v-icon(left) check
             span Update Group
         v-card.mt-3
-          v-tabs(v-model='tab', :color='$vuetify.dark ? "primary" : "grey darken-2"', fixed-tabs, slider-color='white', show-arrows, dark)
+          v-tabs(v-model='tab', :color='$vuetify.theme.dark ? "primary" : "grey darken-2"', fixed-tabs, slider-color='white', show-arrows, dark)
             v-tab(key='permissions') Permissions
             v-tab(key='rules') Page Rules
             v-tab(key='users') Users

+ 5 - 1
client/components/admin/admin-locale.vue

@@ -37,7 +37,7 @@
                           v-avatar.blue.white--text(tile, size='40', v-html='data.item.code.toUpperCase()')
                         v-list-item-content
                           v-list-item-title(v-html='data.item.name')
-                          v-list-item-sub-title(v-html='data.item.nativeName')
+                          v-list-item-subtitle(v-html='data.item.nativeName')
                   v-divider.mt-3
                   v-switch(
                     v-model='autoUpdate'
@@ -254,6 +254,10 @@ export default {
           style: 'success',
           icon: 'check'
         })
+
+        _.delay(() => {
+          window.location.reload(true)
+        }, 1500)
       } else {
         this.$store.commit('showNotification', {
           message: `Error: ${resp.message}`,

+ 54 - 53
client/components/admin/admin-pages-edit.vue

@@ -23,15 +23,16 @@
             status-indicator.mr-3.ml-4(active, pulse)
             .caption.blue--text {{$t('common:page.global')}}
           v-spacer
-          v-btn.animated.fadeInRight.wait-p4s(color='grey', large, outline, to='/pages')
-            v-icon arrow_back
-          v-divider.animated.fadeInRight.wait-p3s.mx-3(vertical)
+          v-btn.mx-1.animated.fadeInRight.wait-p4s(color='grey', large, outlined, to='/pages')
+            v-icon mdi-arrow-left
+          v-divider.mx-1.animated.fadeInRight.wait-p3s.mx-1(vertical)
           v-dialog(v-model='deletePageDialog', max-width='500')
-            v-btn.animated.fadeInDown.wait-p1s(color='red', large, outline, slot='activator')
-              v-icon(color='red') delete
+            template(v-slot:activator='{ on }')
+              v-btn.mx-1.animated.fadeInDown.wait-p1s(color='red', large, outlined, v-on='on')
+                v-icon(color='red') mdi-trash-can-outline
             v-card.wiki-form
               .dialog-header.is-short.is-red
-                v-icon.mr-2(color='white') highlight_off
+                v-icon.mr-2(color='white') mdi-file-document-box-remove-outline
                 span {{$t('common:page.delete')}}
               v-card-text
                 i18next.body-2(path='common:page.deleteTitle', tag='div')
@@ -45,67 +46,67 @@
                 v-spacer
                 v-btn(flat, @click='deletePageDialog = false', :disabled='loading') {{$t('common:actions.cancel')}}
                 v-btn(color='red darken-2', @click='deletePage', :loading='loading').white--text {{$t('common:actions.delete')}}
-          v-btn.animated.fadeInDown(color='teal', large, outline, @click='rerenderPage')
-            v-icon(left) system_update_alt
+          v-btn.ml-1.animated.fadeInDown(color='teal', large, outlined, @click='rerenderPage')
+            v-icon(left) mdi-cube-scan
             span Re-render
       v-flex(xs12, lg6)
         v-card.animated.fadeInUp
           v-toolbar(color='primary', dense, dark, flat)
-            v-icon.mr-2 subject
+            v-icon.mr-2 mdi-text-subject
             span Properties
           v-list.py-0(two-line, dense)
             v-list-item
               v-list-item-content
-                v-list-item-title.caption.grey--text Title
-                v-list-item-sub-title.body-2.grey--text.text--darken-3 {{ page.title }}
+                v-list-item-title: .overline.grey--text Title
+                v-list-item-subtitle.body-2.grey--text.text--darken-3 {{ page.title }}
             v-divider
             v-list-item
               v-list-item-content
-                v-list-item-title.caption.grey--text Description
-                v-list-item-sub-title.body-2.grey--text.text--darken-3 {{ page.description || '-' }}
+                v-list-item-title: .overline.grey--text Description
+                v-list-item-subtitle.body-2.grey--text.text--darken-3 {{ page.description || '-' }}
             v-divider
             v-list-item
               v-list-item-content
-                v-list-item-title.caption.grey--text Locale
-                v-list-item-sub-title.body-2.grey--text.text--darken-3 {{ page.locale }}
+                v-list-item-title: .overline.grey--text Locale
+                v-list-item-subtitle.body-2.grey--text.text--darken-3 {{ page.locale }}
               v-list-item-action
-                v-btn(icon)
-                  v-icon(color='grey') edit
+                v-btn(icon, x-small)
+                  v-icon(color='grey') mdi-pencil
             v-divider
             v-list-item
               v-list-item-content
-                v-list-item-title.caption.grey--text Path
-                v-list-item-sub-title.body-2.grey--text.text--darken-3 {{ page.path }}
+                v-list-item-title: .overline.grey--text Path
+                v-list-item-subtitle.body-2.grey--text.text--darken-3 {{ page.path }}
               v-list-item-action
-                v-btn(icon)
-                  v-icon(color='grey') edit
+                v-btn(icon, x-small)
+                  v-icon(color='grey') mdi-pencil
             v-divider
             v-list-item
               v-list-item-content
-                v-list-item-title.caption.grey--text Editor
-                v-list-item-sub-title.body-2.grey--text.text--darken-3 {{ page.editor || '?' }}
+                v-list-item-title: .overline.grey--text Editor
+                v-list-item-subtitle.body-2.grey--text.text--darken-3 {{ page.editor || '?' }}
             v-divider
             v-list-item
               v-list-item-content
-                v-list-item-title.caption.grey--text Content Type
-                v-list-item-sub-title.body-2.grey--text.text--darken-3 {{ page.contentType || '?' }}
+                v-list-item-title: .overline.grey--text Content Type
+                v-list-item-subtitle.body-2.grey--text.text--darken-3 {{ page.contentType || '?' }}
 
         v-toolbar.elevation-2.mt-3.animated.fadeInUp.wait-p4s(color='white', dense)
           v-spacer
-          v-btn(color='primary', flat, :href='`/` + page.locale + `/` + page.path')
-            v-icon(left) subject
+          v-btn(color='primary', text, :href='`/` + page.locale + `/` + page.path')
+            v-icon(left) mdi-text-subject
             span View
-          v-divider(vertical)
-          v-btn(color='primary', flat, :href='`/e/` + page.locale + `/` + page.path')
-            v-icon(left) edit
+          v-divider.mx-2(vertical)
+          v-btn(color='primary', text, :href='`/e/` + page.locale + `/` + page.path')
+            v-icon(left) mdi-pencil
             span Edit
-          v-divider(vertical)
-          v-btn(color='primary', flat, :href='`/s/` + page.locale + `/` + page.path')
-            v-icon(left) code
+          v-divider.mx-2(vertical)
+          v-btn(color='primary', text, :href='`/s/` + page.locale + `/` + page.path')
+            v-icon(left) mdi-code-tags
             span Source
-          v-divider(vertical)
-          v-btn(color='primary', flat, :href='`/h/` + page.locale + `/` + page.path')
-            v-icon(left) history
+          v-divider.mx-2(vertical)
+          v-btn(color='primary', text, :href='`/h/` + page.locale + `/` + page.path')
+            v-icon(left) mdi-history
             span History
           v-spacer
 
@@ -114,47 +115,47 @@
       v-flex(xs12, lg6)
         v-card.animated.fadeInUp.wait-p2s
           v-toolbar(color='primary', dense, dark, flat)
-            v-icon.mr-2 people
+            v-icon.mr-2 mdi-account-multiple
             span Users
           v-list.py-0(two-line, dense)
             v-list-item
-              v-list-item-avatar
+              v-list-item-avatar(size='24')
                 v-btn(icon, :to='`/users/` + page.creatorId')
-                  v-icon(color='grey') person
+                  v-icon(color='grey') mdi-account
               v-list-item-content
-                v-list-item-title.caption.grey--text Creator
-                v-list-item-sub-title.body-2.grey--text.text--darken-3 {{ page.creatorName }} #[em.caption ({{ page.creatorEmail }})]
+                v-list-item-title: .overline.grey--text Creator
+                v-list-item-subtitle.body-2.grey--text.text--darken-3 {{ page.creatorName }} #[em.caption ({{ page.creatorEmail }})]
               v-list-item-action
                 v-list-item-action-text {{ page.createdAt | moment('calendar') }}
             v-divider
             v-list-item
-              v-list-item-avatar
+              v-list-item-avatar(size='24')
                 v-btn(icon, :to='`/users/` + page.authorId')
-                  v-icon(color='grey') person
+                  v-icon(color='grey') mdi-account
               v-list-item-content
-                v-list-item-title.caption.grey--text Last Editor
-                v-list-item-sub-title.body-2.grey--text.text--darken-3 {{ page.authorName }} #[em.caption ({{ page.authorEmail }})]
+                v-list-item-title: .overline.grey--text Last Editor
+                v-list-item-subtitle.body-2.grey--text.text--darken-3 {{ page.authorName }} #[em.caption ({{ page.authorEmail }})]
               v-list-item-action
                 v-list-item-action-text {{ page.updatedAt | moment('calendar') }}
         v-card.mt-3.animated.fadeInUp.wait-p4s
           v-toolbar(color='primary', dense, dark, flat)
-            v-icon.mr-2 history
+            v-icon.mr-2 mdi-history
             span Recent History
             v-spacer
             v-chip(label, color='white', small).primary--text coming soon
           v-timeline.mx-3(dense, clipped)
             v-timeline-item(color='teal', small, v-if='page.createdAt !== page.updatedAt')
               v-layout(justify-space-between)
-                v-flex(xs7) Page Modified by #[strong {{ page.authorName }}] #[em.caption ({{ page.authorEmail }})]
-                v-flex.text-xs-right(xs5).caption.grey--text.text-darken-2 {{ page.updatedAt | moment('calendar') }}
+                v-flex(xs7).body-2 Page Modified by #[strong {{ page.authorName }}] #[em.caption ({{ page.authorEmail }})]
+                v-flex.text-right(xs5).caption.grey--text.text-darken-2 {{ page.updatedAt | moment('calendar') }}
             v-timeline-item(hide-dot, small)
-              .body-1 ...
-              v-btn.mx-0(outline, color='grey', :href='`/h/` + page.locale + `/` + page.path') View Full History
-              .body-1 ...
+              .body-2 ...
+              v-btn.mx-0.mt-1(outlined, color='grey', :href='`/h/` + page.locale + `/` + page.path') View Full History
+              .body-2 ...
             v-timeline-item(color='pink', small)
               v-layout(justify-space-between)
-                v-flex(xs7) Page created by #[strong {{ page.creatorName }}] #[em.caption ({{ page.creatorEmail }})]
-                v-flex.text-xs-right(xs5).caption.grey--text.text-darken-2 {{ page.createdAt | moment('calendar') }}
+                v-flex(xs7).body-2 Page created by #[strong {{ page.creatorName }}] #[em.caption ({{ page.creatorEmail }})]
+                v-flex.text-right(xs5).caption.grey--text.text-darken-2 {{ page.createdAt | moment('calendar') }}
 
     v-layout(row, align-center, v-else)
       v-progress-circular(indeterminate, width='2', color='grey')

+ 10 - 14
client/components/admin/admin-pages.vue

@@ -17,7 +17,7 @@
             v-icon(left) mdi-plus
             span New Page
         v-card.wiki-form.mt-3.animated.fadeInUp
-          v-toolbar(flat, :color='$vuetify.dark ? `grey darken-3-d5` : `grey lighten-5`', height='80')
+          v-toolbar(flat, :color='$vuetify.theme.dark ? `grey darken-3-d5` : `grey lighten-5`', height='80')
             v-spacer
             v-text-field(
               outlined
@@ -46,27 +46,27 @@
             :items='filteredPages'
             :headers='headers'
             :search='search'
-            :pagination.sync='pagination'
-            :rows-per-page-items='[15]'
+            :page.sync='pagination'
+            :items-per-page='15'
             :loading='loading'
             must-sort,
-            hide-actions
+            hide-default-footer
           )
-            template(slot='items', slot-scope='props')
+            template(slot='item', slot-scope='props')
               tr.is-clickable(:active='props.selected', @click='$router.push(`/pages/` + props.item.id)')
                 td.text-xs-right {{ props.item.id }}
                 td
                   .body-2 {{ props.item.title }}
                   .caption {{ props.item.description }}
                 td.admin-pages-path
-                  v-chip(label, small, :color='$vuetify.dark ? `grey darken-4` : `grey lighten-4`') {{ props.item.locale }}
-                  span.ml-2.grey--text(:class='$vuetify.dark ? `text--lighten-1` : `text--darken-2`') {{ props.item.path }}
+                  v-chip(label, small, :color='$vuetify.theme.dark ? `grey darken-4` : `grey lighten-4`') {{ props.item.locale }}
+                  span.ml-2.grey--text(:class='$vuetify.theme.dark ? `text--lighten-1` : `text--darken-2`') {{ props.item.path }}
                 td {{ props.item.createdAt | moment('calendar') }}
                 td {{ props.item.updatedAt | moment('calendar') }}
             template(slot='no-data')
               v-alert.ma-3(icon='warning', :value='true', outline) No pages to display.
           .text-xs-center.py-2.animated.fadeInDown(v-if='this.pageTotal > 1')
-            v-pagination(v-model='pagination.page', :length='pageTotal')
+            v-pagination(v-model='pagination', :length='pageTotal')
 </template>
 
 <script>
@@ -77,7 +77,7 @@ export default {
   data() {
     return {
       selectedPage: {},
-      pagination: {},
+      pagination: 1,
       pages: [],
       headers: [
         { text: 'ID', value: 'id', width: 50, align: 'right' },
@@ -99,11 +99,7 @@ export default {
   },
   computed: {
     pageTotal () {
-      if (this.pagination.rowsPerPage == null || this.pagination.totalItems == null) {
-        return 0
-      }
-
-      return Math.ceil(this.filteredPages.length / this.pagination.rowsPerPage)
+      return Math.ceil(this.filteredPages.length / 15)
     },
     filteredPages () {
       return _.filter(this.pages, pg => {

+ 3 - 3
client/components/admin/admin-storage.vue

@@ -33,7 +33,7 @@
               v-divider(v-if='idx < targets.length - 1')
 
         v-card.mt-3.animated.fadeInUp.wait-p2s
-          v-toolbar(flat, :color='$vuetify.dark ? `grey darken-3-l5` : `grey darken-3`', dark, dense)
+          v-toolbar(flat, :color='$vuetify.theme.dark ? `grey darken-3-l5` : `grey darken-3`', dark, dense)
             .subtitle-1 {{$t('admin:storage.status')}}
             v-spacer
             looping-rhombuses-spinner(
@@ -182,14 +182,14 @@
                 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.radius-7.grey(flat, :class='$vuetify.theme.dark ? `darken-3-d5` : `lighten-3`', height='100%')
                         v-card-text
                           .subtitle-1(v-html='act.label')
                           .body-2.mt-4(v-html='act.hint')
                           v-btn.mx-0.mt-5(
                             @click='executeAction(target.key, act.handler)'
                             outlined
-                            :color='$vuetify.dark ? `blue` : `primary`'
+                            :color='$vuetify.theme.dark ? `blue` : `primary`'
                             :disabled='runningAction'
                             :loading='runningActionHandler === act.handler'
                             ) {{$t('admin:storage.actionRun')}}

+ 1 - 1
client/components/admin/admin-system.vue

@@ -10,7 +10,7 @@
         v-layout.mt-3(row wrap)
           v-flex(lg6 xs12)
             v-card.animated.fadeInUp
-              v-btn.animated.fadeInLeft.wait-p2s.btn-animate-rotate(fab, absolute, right, top, small, light, @click='refresh'): v-icon(color='grey') mdi-refresh
+              v-btn.animated.fadeInLeft.wait-p2s.btn-animate-rotate(fab, absolute, :right='!$vuetify.rtl', :left='$vuetify.rtl', top, small, light, @click='refresh'): v-icon(color='grey') mdi-refresh
               v-subheader Wiki.js
               v-list(two-line, dense)
                 v-list-item(avatar)

+ 1 - 1
client/components/admin/admin-theme.vue

@@ -29,7 +29,7 @@
                     )
                     template(slot='item', slot-scope='data')
                       v-list-item-avatar
-                        v-icon.blue--text(dark) filter_frames
+                        v-icon.blue--text(dark) mdi-image-filter-frames
                       v-list-item-content
                         v-list-item-title(v-html='data.item.text')
                         v-list-item-sub-title(v-html='data.item.author')

+ 1 - 1
client/components/admin/admin-users.vue

@@ -14,7 +14,7 @@
             v-icon(left) mdi-plus
             span New User
         v-card.wiki-form.mt-3.animated.fadeInUp
-          v-toolbar(flat, :color='$vuetify.dark ? `grey darken-3-d5` : `grey lighten-5`', height='80')
+          v-toolbar(flat, :color='$vuetify.theme.dark ? `grey darken-3-d5` : `grey lighten-5`', height='80')
             v-spacer
             v-text-field(
               outlined

+ 1 - 1
client/components/common/duration-picker.vue

@@ -1,5 +1,5 @@
 <template lang='pug'>
-  v-toolbar.radius-7(flat, :color='$vuetify.dark ? "grey darken-4-l3" : "grey lighten-3"')
+  v-toolbar.radius-7(flat, :color='$vuetify.theme.dark ? "grey darken-4-l3" : "grey lighten-3"')
     .body-2.mr-3 {{$t('common:duration.every')}}
     v-text-field(
       solo

+ 9 - 9
client/components/common/nav-header.vue

@@ -1,5 +1,5 @@
 <template lang='pug'>
-  v-app-bar.nav-header(color='black', dark, app, clipped-left, fixed, flat, :extended='searchIsShown && $vuetify.breakpoint.smAndDown')
+  v-app-bar.nav-header(color='black', dark, app, :clipped-left='!$vuetify.rtl', :clipped-right='$vuetify.rtl', fixed, flat, :extended='searchIsShown && $vuetify.breakpoint.smAndDown')
     v-toolbar(color='deep-purple', flat, slot='extension', v-if='searchIsShown && $vuetify.breakpoint.smAndDown')
       v-text-field(
         ref='searchFieldMobile'
@@ -21,9 +21,9 @@
         v-toolbar.nav-header-inner.pl-3(color='black', dark, flat)
           v-menu(open-on-hover, offset-y, bottom, left, min-width='250', transition='slide-y-transition')
             template(v-slot:activator='{ on }')
-              v-app-bar-nav-icon.btn-animate-app(v-on='on')
+              v-app-bar-nav-icon.btn-animate-app(v-on='on', :class='$vuetify.rtl ? `mx-0` : ``')
                 v-icon mdi-menu-open
-            v-list(nav, :light='!$vuetify.dark', :dark='$vuetify.dark', :class='$vuetify.dark ? `grey darken-4` : ``')
+            v-list(nav, :light='!$vuetify.theme.dark', :dark='$vuetify.theme.dark', :class='$vuetify.theme.dark ? `grey darken-4` : ``')
               v-list-item.pl-4(href='/')
                 v-list-item-avatar(size='24'): v-icon(color='blue') mdi-home
                 v-list-item-title.body-2 {{$t('common:header.home')}}
@@ -43,7 +43,7 @@
                   v-list-item-avatar(size='24'): v-icon(color='indigo') mdi-history
                   v-list-item-title.body-2 {{$t('common:header.history')}}
                 v-list-item.pl-4(@click='pageSource', v-if='mode !== `source`')
-                  v-list-item-avatar(size='24'): v-icon(color='indigo') mdi-code-braces
+                  v-list-item-avatar(size='24'): v-icon(color='indigo') mdi-code-tags
                   v-list-item-title.body-2 {{$t('common:header.viewSource')}}
                 v-list-item.pl-4(@click='pageMove', v-if='isAuthenticated')
                   v-list-item-avatar(size='24'): v-icon(color='grey lighten-2') mdi-content-save-move-outline
@@ -141,7 +141,7 @@
             template(v-slot:activator='{ on: menu }')
               v-tooltip(bottom)
                 template(v-slot:activator='{ on: tooltip }')
-                  v-btn(icon, v-on='{ ...menu, ...tooltip }')
+                  v-btn(icon, v-on='{ ...menu, ...tooltip }', :class='$vuetify.rtl ? `ml-3` : ``')
                     v-icon(color='grey') mdi-web
                 span {{$t('common:header.language')}}
             v-list.py-0
@@ -152,20 +152,20 @@
                 v-divider.my-0(v-if='idx < locales.length - 1')
           v-tooltip(bottom, v-if='isAuthenticated && isAdmin')
             template(v-slot:activator='{ on }')
-              v-btn.btn-animate-rotate(icon, href='/a', v-on='on')
+              v-btn.btn-animate-rotate(icon, href='/a', v-on='on', :class='$vuetify.rtl ? `ml-3` : ``')
                 v-icon(color='grey') mdi-settings
             span {{$t('common:header.admin')}}
           v-menu(v-if='isAuthenticated', offset-y, min-width='300', left, transition='slide-y-transition')
             template(v-slot:activator='{ on: menu }')
               v-tooltip(bottom)
                 template(v-slot:activator='{ on: tooltip }')
-                  v-btn(icon, v-on='{ ...menu, ...tooltip }')
+                  v-btn(icon, v-on='{ ...menu, ...tooltip }', :class='$vuetify.rtl ? `ml-0` : ``')
                     v-icon(v-if='picture.kind === `initials`', color='grey') mdi-account-circle
                     v-avatar(v-else-if='picture.kind === `image`', :size='29')
                       v-img(:src='picture.url')
                 span {{$t('common:header.account')}}
             v-list.py-0
-              v-list-item.py-3.grey(avatar, :class='$vuetify.dark ? `darken-4-l5` : `lighten-5`')
+              v-list-item.py-3.grey(avatar, :class='$vuetify.theme.dark ? `darken-4-l5` : `lighten-5`')
                 v-list-item-avatar
                   v-avatar.blue(v-if='picture.kind === `initials`', :size='40')
                     span.white--text.subheading {{picture.initials}}
@@ -189,7 +189,7 @@
 
           v-tooltip(v-else, left)
             template(v-slot:activator='{ on }')
-              v-btn(icon, v-on='on', outline, color='grey darken-3', href='/login')
+              v-btn(icon, v-on='on', outlined, color='grey darken-3', href='/login')
                 v-icon(color='grey') mdi-account-circle
             span {{$t('common:header.login')}}
 

+ 1 - 1
client/components/common/user-search.vue

@@ -25,7 +25,7 @@
           hide-details
           )
         v-list.grey.mt-3.py-0.radius-7(
-          :class='$vuetify.dark ? `darken-3-d5` : `lighten-3`'
+          :class='$vuetify.theme.dark ? `darken-3-d5` : `lighten-3`'
           two-line
           dense
           )

+ 24 - 24
client/components/editor/editor-modal-media.vue

@@ -3,19 +3,19 @@
     v-container.pa-3(grid-list-lg, fluid)
       v-layout(row, wrap)
         v-flex(xs12, lg9)
-          v-card.radius-7.animated.fadeInLeft.wait-p1s(:light='!$vuetify.dark', :dark='$vuetify.dark')
+          v-card.radius-7.animated.fadeInLeft.wait-p1s(:light='!$vuetify.theme.dark', :dark='$vuetify.theme.dark')
             v-card-text
               .d-flex
-                v-toolbar.radius-7(:color='$vuetify.dark ? `teal` : `teal lighten-5`', dense, flat, height='44')
-                  .body-2(:class='$vuetify.dark ? `white--text` : `teal--text`') {{$t('editor:assets.title')}}
+                v-toolbar.radius-7(:color='$vuetify.theme.dark ? `teal` : `teal lighten-5`', dense, flat, height='44')
+                  .body-2(:class='$vuetify.theme.dark ? `white--text` : `teal--text`') {{$t('editor:assets.title')}}
                   v-spacer
                   v-btn(flat, icon, @click='refresh', tile, small)
-                    v-icon(:color='$vuetify.dark ? `white` : `teal`') mdi-refresh
+                    v-icon(:color='$vuetify.theme.dark ? `white` : `teal`') mdi-refresh
                 v-dialog(v-model='newFolderDialog', max-width='550')
                   template(v-slot:activator='{ on }')
                     v-btn.ml-3.my-0.mr-0.radius-7(outlined, large, color='teal', :icon='$vuetify.breakpoint.xsOnly', v-on='on')
                       v-icon(:left='$vuetify.breakpoint.mdAndUp') mdi-plus
-                      span.hidden-sm-and-down(:class='$vuetify.dark ? `teal--text text--lighten-3` : ``') {{$t('editor:assets.newFolder')}}
+                      span.hidden-sm-and-down(:class='$vuetify.theme.dark ? `teal--text text--lighten-3` : ``') {{$t('editor:assets.newFolder')}}
                   v-card
                     .dialog-header.is-short.subtitle-1 {{$t('editor:assets.newFolder')}}
                     v-card-text
@@ -35,7 +35,7 @@
                       v-spacer
                       v-btn(text, @click='newFolderDialog = false') {{$t('common:actions.cancel')}}
                       v-btn.px-3(color='primary', @click='createFolder', :disabled='!isFolderNameValid', :loading='newFolderLoading') {{$t('common:actions.create')}}
-              v-toolbar(flat, dense, :color='$vuetify.dark ? `grey darken-3` : `white`')
+              v-toolbar(flat, dense, :color='$vuetify.theme.dark ? `grey darken-3` : `white`')
                 template(v-if='folderTree.length > 0')
                   .body-2
                     span.mr-1 /
@@ -44,7 +44,7 @@
                       span.mx-1 /
                 .body-2(v-else) / #[em root]
               template(v-if='folders.length > 0 || currentFolderId > 0')
-                v-btn.is-icon.mx-1(:color='$vuetify.dark ? `grey lighten-1` : `grey darken-2`', outlined, :dark='currentFolderId > 0', @click='upFolder()', :disabled='currentFolderId === 0')
+                v-btn.is-icon.mx-1(:color='$vuetify.theme.dark ? `grey lighten-1` : `grey darken-2`', outlined, :dark='currentFolderId > 0', @click='upFolder()', :disabled='currentFolderId === 0')
                   v-icon mdi-folder-upload
                 v-btn.btn-normalcase.mx-1(v-for='folder of folders', :key='folder.id', depressed,  color='grey darken-2', dark, @click='downFolder(folder)')
                   v-icon(left) mdi-folder
@@ -64,14 +64,14 @@
                   tr.is-clickable(
                     @click.left='currentFileId = props.item.id'
                     @click.right.prevent=''
-                    :class='currentFileId === props.item.id ? ($vuetify.dark ? `grey darken-3-d5` : `teal lighten-5`) : ``'
+                    :class='currentFileId === props.item.id ? ($vuetify.theme.dark ? `grey darken-3-d5` : `teal lighten-5`) : ``'
                     )
                     td.text-xs-right(v-if='$vuetify.breakpoint.smAndUp') {{ props.item.id }}
                     td
                       .body-2(:class='currentFileId === props.item.id ? `teal--text` : ``') {{ props.item.filename }}
                       .caption.grey--text {{ props.item.description }}
                     td.text-xs-center(v-if='$vuetify.breakpoint.lgAndUp')
-                      v-chip.ma-0(small, :color='$vuetify.dark ? `grey darken-4` : `grey lighten-4`')
+                      v-chip.ma-0(small, :color='$vuetify.theme.dark ? `grey darken-4` : `grey lighten-4`')
                         .caption {{props.item.ext.toUpperCase().substring(1)}}
                     td(v-if='$vuetify.breakpoint.mdAndUp') {{ props.item.fileSize | prettyBytes }}
                     td(v-if='$vuetify.breakpoint.mdAndUp') {{ props.item.createdAt | moment('from') }}
@@ -115,22 +115,22 @@
               .text-xs-center.py-2(v-if='this.pageTotal > 1')
                 v-pagination(v-model='pagination', :length='pageTotal', color='teal')
               .d-flex.mt-3
-                v-toolbar.radius-7(flat, :color='$vuetify.dark ? `grey darken-2` : `grey lighten-4`', dense, height='44')
-                  .body-2(:class='$vuetify.dark ? `grey--text text--lighten-1` : `grey--text text--darken-1`') {{$t('editor:assets.fileCount', { count: assets.length })}}
+                v-toolbar.radius-7(flat, :color='$vuetify.theme.dark ? `grey darken-2` : `grey lighten-4`', dense, height='44')
+                  .body-2(:class='$vuetify.theme.dark ? `grey--text text--lighten-1` : `grey--text text--darken-1`') {{$t('editor:assets.fileCount', { count: assets.length })}}
                 v-btn.ml-3.mr-0.my-0.radius-7(color='teal', large, @click='insert', :disabled='!currentFileId', :dark='currentFileId !== null')
                   v-icon(left) mdi-playlist-plus
                   span {{$t('common:actions.insert')}}
 
         v-flex(xs12, lg3)
-          v-card.radius-7.animated.fadeInRight.wait-p3s(:light='!$vuetify.dark', :dark='$vuetify.dark')
+          v-card.radius-7.animated.fadeInRight.wait-p3s(:light='!$vuetify.theme.dark', :dark='$vuetify.theme.dark')
             v-card-text
               .d-flex
-                v-toolbar.radius-7(:color='$vuetify.dark ? `teal` : `teal lighten-5`', dense, flat, height='44')
-                  v-icon.mr-3(:color='$vuetify.dark ? `white` : `teal`') mdi-cloud-upload
-                  .body-2(:class='$vuetify.dark ? `white--text` : `teal--text`') {{$t('editor:assets.uploadAssets')}}
+                v-toolbar.radius-7(:color='$vuetify.theme.dark ? `teal` : `teal lighten-5`', dense, flat, height='44')
+                  v-icon.mr-3(:color='$vuetify.theme.dark ? `white` : `teal`') mdi-cloud-upload
+                  .body-2(:class='$vuetify.theme.dark ? `white--text` : `teal--text`') {{$t('editor:assets.uploadAssets')}}
                 v-btn.my-0.ml-3.mr-0.radius-7(outlined, large, color='teal', @click='browse', v-if='$vuetify.breakpoint.mdAndUp')
                   v-icon(left) mdi-library-plus
-                  span(:class='$vuetify.dark ? `teal--text text--lighten-3` : ``') {{$t('common:actions.browse')}}
+                  span(:class='$vuetify.theme.dark ? `teal--text text--lighten-3` : ``') {{$t('common:actions.browse')}}
               file-pond.mt-3(
                 name='mediaUpload'
                 ref='pond'
@@ -149,11 +149,11 @@
               v-spacer
               v-btn.px-4(color='teal', dark, @click='upload') {{$t('common:actions.upload')}}
 
-          v-card.mt-3.radius-7.animated.fadeInRight.wait-p4s(:light='!$vuetify.dark', :dark='$vuetify.dark')
+          v-card.mt-3.radius-7.animated.fadeInRight.wait-p4s(:light='!$vuetify.theme.dark', :dark='$vuetify.theme.dark')
             v-card-text.pb-0
-              v-toolbar.radius-7(:color='$vuetify.dark ? `teal` : `teal lighten-5`', dense, flat)
-                v-icon.mr-3(:color='$vuetify.dark ? `white` : `teal`') mdi-cloud-download
-                .body-2(:class='$vuetify.dark ? `white--text` : `teal--text`') {{$t('editor:assets.fetchImage')}}
+              v-toolbar.radius-7(:color='$vuetify.theme.dark ? `teal` : `teal lighten-5`', dense, flat)
+                v-icon.mr-3(:color='$vuetify.theme.dark ? `white` : `teal`') mdi-cloud-download
+                .body-2(:class='$vuetify.theme.dark ? `white--text` : `teal--text`') {{$t('editor:assets.fetchImage')}}
                 v-spacer
                 v-chip(label, color='white', small).teal--text coming soon
               v-text-field.mt-3(
@@ -169,11 +169,11 @@
               v-spacer
               v-btn.px-4(color='teal', disabled) {{$t('common:actions.fetch')}}
 
-          v-card.mt-3.radius-7.animated.fadeInRight.wait-p4s(:light='!$vuetify.dark', :dark='$vuetify.dark')
+          v-card.mt-3.radius-7.animated.fadeInRight.wait-p4s(:light='!$vuetify.theme.dark', :dark='$vuetify.theme.dark')
             v-card-text.pb-0
-              v-toolbar.radius-7(:color='$vuetify.dark ? `teal` : `teal lighten-5`', dense, flat)
-                v-icon.mr-3(:color='$vuetify.dark ? `white` : `teal`') mdi-format-align-top
-                .body-2(:class='$vuetify.dark ? `white--text` : `teal--text`') {{$t('editor:assets.imageAlign')}}
+              v-toolbar.radius-7(:color='$vuetify.theme.dark ? `teal` : `teal lighten-5`', dense, flat)
+                v-icon.mr-3(:color='$vuetify.theme.dark ? `white` : `teal`') mdi-format-align-top
+                .body-2(:class='$vuetify.theme.dark ? `white--text` : `teal--text`') {{$t('editor:assets.imageAlign')}}
               v-select.mt-3(
                 v-model='imageAlignment'
                 :items='imageAlignments'

+ 10 - 0
client/index-app.js

@@ -1,6 +1,16 @@
 require('core-js/stable')
 require('regenerator-runtime/runtime')
 
+switch (window.document.documentElement.lang) {
+  case 'ar':
+  case 'fa':
+    require('./scss/fonts/arabic.scss')
+    break
+  default:
+    require('./scss/fonts/default.scss')
+    break
+}
+
 require('./scss/app.scss')
 require('./themes/' + process.env.CURRENT_THEME + '/scss/app.scss')
 

+ 0 - 3
client/scss/app.scss

@@ -1,12 +1,9 @@
 @import "global";
 
 @import "base/base";
-@import "base/fonts";
 @import "base/icons";
 @import "base/animation";
 
-// @import "../libs/animate/animate";
-// @import '~vue2-animate/src/sass/vue2-animate';
 @import '~vuescroll/dist/vuescroll.css';
 @import '~diff2html/dist/diff2html.min.css';
 

+ 0 - 55
client/scss/base/fonts.scss

@@ -1,55 +0,0 @@
-@font-face {
-  font-family: 'Roboto';
-  src: url('/fonts/Roboto-MediumItalic.woff2') format('woff2'),
-      url('/fonts/Roboto-MediumItalic.woff') format('woff');
-  font-weight: 500;
-  font-style: italic;
-}
-
-@font-face {
-  font-family: 'Roboto';
-  src: url('/fonts/Roboto-Italic.woff2') format('woff2'),
-      url('/fonts/Roboto-Italic.woff') format('woff');
-  font-weight: normal;
-  font-style: italic;
-}
-
-@font-face {
-  font-family: 'Roboto';
-  src: url('/fonts/Roboto-Bold.woff2') format('woff2'),
-      url('/fonts/Roboto-Bold.woff') format('woff');
-  font-weight: bold;
-  font-style: normal;
-}
-
-@font-face {
-  font-family: 'Roboto';
-  src: url('/fonts/Roboto-Regular.woff2') format('woff2'),
-      url('/fonts/Roboto-Regular.woff') format('woff');
-  font-weight: normal;
-  font-style: normal;
-}
-
-@font-face {
-  font-family: 'Roboto';
-  src: url('/fonts/Roboto-BoldItalic.woff2') format('woff2'),
-      url('/fonts/Roboto-BoldItalic.woff') format('woff');
-  font-weight: bold;
-  font-style: italic;
-}
-
-@font-face {
-  font-family: 'Roboto';
-  src: url('/fonts/Roboto-Medium.woff2') format('woff2'),
-      url('/fonts/Roboto-Medium.woff') format('woff');
-  font-weight: 500;
-  font-style: normal;
-}
-
-@font-face {
-  font-family: 'Roboto Mono';
-  src: url('/fonts/RobotoMono-Regular.woff2') format('woff2'),
-      url('/fonts/RobotoMono-Regular.woff') format('woff');
-  font-weight: normal;
-  font-style: normal;
-}

+ 43 - 0
client/scss/fonts/arabic.scss

@@ -0,0 +1,43 @@
+@font-face {
+  font-family: 'Tajawal';
+  src: url('/fonts/arabic/Tajawal-Bold.woff2') format('woff2'),
+      url('/fonts/arabic/Tajawal-Bold.woff') format('woff');
+  font-weight: bold;
+  font-style: normal;
+}
+
+@font-face {
+  font-family: 'Tajawal';
+  src: url('/fonts/arabic/Tajawal-Regular.woff2') format('woff2'),
+      url('/fonts/arabic/Tajawal-Regular.woff') format('woff');
+  font-weight: normal;
+  font-style: normal;
+}
+
+@font-face {
+  font-family: 'Tajawal';
+  src: url('/fonts/arabic/Tajawal-Medium.woff2') format('woff2'),
+      url('/fonts/arabic/Tajawal-Medium.woff') format('woff');
+  font-weight: 500;
+  font-style: normal;
+}
+
+@font-face {
+  font-family: 'Roboto Mono';
+  src: url('/fonts/arabic/RobotoMono-Regular.woff2') format('woff2'),
+      url('/fonts/arabic/RobotoMono-Regular.woff') format('woff');
+  font-weight: normal;
+  font-style: normal;
+}
+
+html:lang(ar), html:lang(fa) {
+  font-family: Tajawal, sans-serif;
+
+  .v-application {
+    font-family: Tajawal, sans-serif;
+
+    & .headline, & .title {
+      font-family: Tajawal, sans-serif !important;
+    }
+  }
+}

+ 55 - 0
client/scss/fonts/default.scss

@@ -0,0 +1,55 @@
+@font-face {
+  font-family: 'Roboto';
+  src: url('/fonts/default/Roboto-MediumItalic.woff2') format('woff2'),
+      url('/fonts/default/Roboto-MediumItalic.woff') format('woff');
+  font-weight: 500;
+  font-style: italic;
+}
+
+@font-face {
+  font-family: 'Roboto';
+  src: url('/fonts/default/Roboto-Italic.woff2') format('woff2'),
+      url('/fonts/default/Roboto-Italic.woff') format('woff');
+  font-weight: normal;
+  font-style: italic;
+}
+
+@font-face {
+  font-family: 'Roboto';
+  src: url('/fonts/default/Roboto-Bold.woff2') format('woff2'),
+      url('/fonts/default/Roboto-Bold.woff') format('woff');
+  font-weight: bold;
+  font-style: normal;
+}
+
+@font-face {
+  font-family: 'Roboto';
+  src: url('/fonts/default/Roboto-Regular.woff2') format('woff2'),
+      url('/fonts/default/Roboto-Regular.woff') format('woff');
+  font-weight: normal;
+  font-style: normal;
+}
+
+@font-face {
+  font-family: 'Roboto';
+  src: url('/fonts/default/Roboto-BoldItalic.woff2') format('woff2'),
+      url('/fonts/default/Roboto-BoldItalic.woff') format('woff');
+  font-weight: bold;
+  font-style: italic;
+}
+
+@font-face {
+  font-family: 'Roboto';
+  src: url('/fonts/default/Roboto-Medium.woff2') format('woff2'),
+      url('/fonts/default/Roboto-Medium.woff') format('woff');
+  font-weight: 500;
+  font-style: normal;
+}
+
+@font-face {
+  font-family: 'Roboto Mono';
+  src: url('/fonts/default/RobotoMono-Regular.woff2') format('woff2'),
+      url('/fonts/default/RobotoMono-Regular.woff') format('woff');
+  font-weight: normal;
+  font-style: normal;
+}

+ 0 - 1
client/scss/legacy.scss

@@ -1,6 +1,5 @@
 @import "global";
 
-@import "./base/fonts.scss";
 @import "./base/icons.scss";
 
 html {

BIN
client/static/fonts/MaterialIcons-Regular.woff


BIN
client/static/fonts/MaterialIcons-Regular.woff2


BIN
client/static/fonts/arabic/BalooBhaijaan-Regular.woff


BIN
client/static/fonts/arabic/BalooBhaijaan-Regular.woff2


BIN
client/static/fonts/arabic/Tajawal-Bold.woff


BIN
client/static/fonts/arabic/Tajawal-Bold.woff2


BIN
client/static/fonts/arabic/Tajawal-Medium.woff


BIN
client/static/fonts/arabic/Tajawal-Medium.woff2


BIN
client/static/fonts/arabic/Tajawal-Regular.woff


BIN
client/static/fonts/arabic/Tajawal-Regular.woff2


+ 0 - 0
client/static/fonts/Roboto-Bold.woff → client/static/fonts/default/Roboto-Bold.woff


+ 0 - 0
client/static/fonts/Roboto-Bold.woff2 → client/static/fonts/default/Roboto-Bold.woff2


+ 0 - 0
client/static/fonts/Roboto-BoldItalic.woff → client/static/fonts/default/Roboto-BoldItalic.woff


+ 0 - 0
client/static/fonts/Roboto-BoldItalic.woff2 → client/static/fonts/default/Roboto-BoldItalic.woff2


+ 0 - 0
client/static/fonts/Roboto-Italic.woff → client/static/fonts/default/Roboto-Italic.woff


+ 0 - 0
client/static/fonts/Roboto-Italic.woff2 → client/static/fonts/default/Roboto-Italic.woff2


+ 0 - 0
client/static/fonts/Roboto-Medium.woff → client/static/fonts/default/Roboto-Medium.woff


+ 0 - 0
client/static/fonts/Roboto-Medium.woff2 → client/static/fonts/default/Roboto-Medium.woff2


+ 0 - 0
client/static/fonts/Roboto-MediumItalic.woff → client/static/fonts/default/Roboto-MediumItalic.woff


+ 0 - 0
client/static/fonts/Roboto-MediumItalic.woff2 → client/static/fonts/default/Roboto-MediumItalic.woff2


+ 0 - 0
client/static/fonts/Roboto-Regular.woff → client/static/fonts/default/Roboto-Regular.woff


+ 0 - 0
client/static/fonts/Roboto-Regular.woff2 → client/static/fonts/default/Roboto-Regular.woff2


+ 0 - 0
client/static/fonts/RobotoMono-Regular.woff → client/static/fonts/default/RobotoMono-Regular.woff


+ 0 - 0
client/static/fonts/RobotoMono-Regular.woff2 → client/static/fonts/default/RobotoMono-Regular.woff2


+ 1 - 1
dev/templates/master.pug

@@ -1,5 +1,5 @@
 doctype html
-html
+html(lang=siteConfig.lang)
   head
     meta(http-equiv='X-UA-Compatible', content='IE=edge')
     meta(charset='UTF-8')

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

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

+ 1 - 8
server/views/master.pug

@@ -1,5 +1,5 @@
 doctype html
-html
+html(lang=siteConfig.lang)
   head
     meta(http-equiv='X-UA-Compatible', content='IE=edge')
     meta(charset='UTF-8')
@@ -64,13 +64,6 @@ html
       )
       
     
-      
-    script(
-      type='text/javascript'
-      src='/app.35e1a512a39dbf80760e.hot-update.js'
-      )
-      
-    
 
     != analyticsCode.head