浏览代码

feat: page locale migration + deps update

Nick 5 年之前
父节点
当前提交
5689444a17

+ 47 - 4
client/components/admin/admin-theme.vue

@@ -69,7 +69,10 @@
                     :hint='$t(`admin:theme.cssOverrideHint`)'
                     auto-grow
                     )
-                  v-textarea.mt-2(
+                  i18next.caption.pl-2.ml-1(path='admin:theme.cssOverrideWarning', tag='div')
+                    strong.red--text(place='caution') {{$t('admin:theme.cssOverrideWarningCaution')}}
+                    code(place='cssClass') .contents
+                  v-textarea.mt-3(
                     v-model='config.injectHead'
                     :label='$t(`admin:theme.headHtmlInjection`)'
                     outline
@@ -96,7 +99,26 @@
                     .subheading {{$t('admin:theme.downloadThemes')}}
                   v-spacer
                   v-chip(label, color='white', small).teal--text coming soon
-                v-card-text.caption -- Coming soon --
+                v-data-table(
+                  :headers='headers',
+                  :items='themes',
+                  hide-actions,
+                  item-key='value',
+                  :rows-per-page-items='[-1]'
+                )
+                  template(v-slot:items='thm')
+                    td
+                      strong {{thm.item.text}}
+                    td
+                      span {{ thm.item.author }}
+                    td.text-xs-center
+                      v-progress-circular(v-if='thm.item.isDownloading', indeterminate, color='blue', size='20', :width='2')
+                      v-btn(v-else-if='thm.item.isInstalled && thm.item.installDate < thm.item.updatedAt', icon)
+                        v-icon.blue--text cached
+                      v-btn(v-else-if='thm.item.isInstalled', icon)
+                        v-icon.green--text check
+                      v-btn(v-else, icon)
+                        v-icon.grey--text cloud_download
 </template>
 
 <script>
@@ -111,7 +133,7 @@ export default {
     return {
       loading: false,
       themes: [
-        { text: 'Default', author: 'requarks.io', value: 'default' }
+        { text: 'Default', author: 'requarks.io', value: 'default', isInstalled: true, installDate: '', updatedAt: '' }
       ],
       iconsets: [
         { text: 'Material Icons (default)', value: 'md' },
@@ -131,7 +153,28 @@ export default {
     }
   },
   computed: {
-    darkMode: sync('site/dark')
+    darkMode: sync('site/dark'),
+    headers() {
+      return [
+        {
+          text: this.$t('admin:theme.downloadName'),
+          align: 'left',
+          value: 'text'
+        },
+        {
+          text: this.$t('admin:theme.downloadAuthor'),
+          align: 'left',
+          value: 'author'
+        },
+        {
+          text: this.$t('admin:theme.downloadDownload'),
+          align: 'center',
+          value: 'value',
+          sortable: false,
+          width: 100
+        }
+      ]
+    }
   },
   mounted() {
     this.darkModeInitial = this.darkMode

+ 20 - 0
client/components/admin/admin-utilities-cache.vue

@@ -15,6 +15,13 @@
       v-btn(outline, color='primary', @click='flushUploads', :disabled='loading').ml-0.mt-3
         v-icon(left) build
         span Proceed
+      v-divider.my-3
+      v-subheader.pl-0.primary--text Flush Client-Side Locale Cache
+      .body-1 Locale strings are cached in the browser local storage for 24h. You can delete your current cache in order to fetch the latest data during the next page load.
+      .body-1 Note that this affects only #[strong your own browser] and not everyone.
+      v-btn(outline, color='primary', @click='flushClientLocaleCache', :disabled='loading').ml-0.mt-3
+        v-icon(left) build
+        span Proceed
 </template>
 
 <script>
@@ -78,6 +85,19 @@ export default {
 
       this.$store.commit(`loadingStop`, 'admin-utilities-cache-flushUploads')
       this.loading = false
+    },
+    async flushClientLocaleCache () {
+      for (let i = 0; i < window.localStorage.length; i++) {
+        const lsKey = window.localStorage.key(i)
+        if (_.startsWith(lsKey, 'i18next_res')) {
+          window.localStorage.removeItem(lsKey)
+        }
+      }
+      this.$store.commit('showNotification', {
+        message: 'Locale Client-Side Cache flushed successfully.',
+        style: 'success',
+        icon: 'check'
+      })
     }
   }
 }

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

@@ -70,7 +70,7 @@ export default {
         const resp = _.get(respRaw, 'data.pages.migrateToLocale.responseResult', {})
         if (resp.succeeded) {
           this.$store.commit('showNotification', {
-            message: 'Migrated all content to target locale successfully.',
+            message: `Migrated ${_.get(respRaw, 'data.pages.migrateToLocale.count', 0)} page(s) to target locale successfully.`,
             style: 'success',
             icon: 'check'
           })

+ 1 - 0
client/graph/admin/utilities/utilities-mutation-content-migratelocale.gql

@@ -7,6 +7,7 @@ mutation($sourceLocale: String!, $targetLocale: String!) {
         slug
         message
       }
+      count
     }
   }
 }

+ 51 - 51
package.json

@@ -35,13 +35,13 @@
   },
   "dependencies": {
     "@aoberoi/passport-slack": "1.0.5",
-    "@bugsnag/js": "6.3.1",
+    "@bugsnag/js": "6.3.2",
     "algoliasearch": "3.33.0",
     "apollo-fetch": "0.7.0",
-    "apollo-server": "2.6.4",
-    "apollo-server-express": "2.6.4",
+    "apollo-server": "2.6.9",
+    "apollo-server-express": "2.6.9",
     "auto-load": "3.0.4",
-    "aws-sdk": "2.480.0",
+    "aws-sdk": "2.493.0",
     "axios": "0.19.0",
     "azure-search-client": "3.1.5",
     "bcryptjs-then": "1.0.1",
@@ -50,7 +50,7 @@
     "brute-knex": "4.0.0",
     "chalk": "2.4.2",
     "cheerio": "1.0.0-rc.3",
-    "chokidar": "3.0.1",
+    "chokidar": "3.0.2",
     "clean-css": "4.2.1",
     "compression": "1.7.4",
     "connect-session-knex": "1.4.0",
@@ -59,7 +59,7 @@
     "custom-error-instance": "2.1.1",
     "dependency-graph": "0.8.0",
     "diff": "4.0.1",
-    "diff2html": "2.10.0",
+    "diff2html": "2.11.2",
     "dotize": "0.3.0",
     "elasticsearch6": "npm:@elastic/elasticsearch@6",
     "elasticsearch7": "npm:@elastic/elasticsearch@7",
@@ -67,17 +67,17 @@
     "express": "4.17.1",
     "express-brute": "1.0.1",
     "express-session": "1.16.2",
-    "file-type": "12.0.0",
+    "file-type": "12.0.1",
     "filesize": "4.1.2",
-    "fs-extra": "8.0.1",
+    "fs-extra": "8.1.0",
     "getos": "3.1.1",
-    "graphql": "14.3.1",
+    "graphql": "14.4.2",
     "graphql-list-fields": "2.0.2",
     "graphql-rate-limit-directive": "1.1.0",
     "graphql-subscriptions": "1.1.0",
     "graphql-tools": "4.0.5",
     "highlight.js": "9.15.8",
-    "i18next": "17.0.4",
+    "i18next": "17.0.6",
     "i18next-express-middleware": "1.8.0",
     "i18next-node-fs-backend": "2.1.3",
     "image-size": "0.7.4",
@@ -86,16 +86,16 @@
     "js-yaml": "3.13.1",
     "jsonwebtoken": "8.5.1",
     "klaw": "3.0.0",
-    "knex": "0.17.6",
-    "lodash": "4.17.13",
-    "markdown-it": "8.4.2",
+    "knex": "0.19.0",
+    "lodash": "4.17.14",
+    "markdown-it": "9.0.1",
     "markdown-it-abbr": "1.0.4",
     "markdown-it-anchor": "5.2.4",
     "markdown-it-attrs": "2.4.1",
     "markdown-it-emoji": "1.4.0",
     "markdown-it-expand-tabs": "1.0.13",
     "markdown-it-external-links": "0.0.6",
-    "markdown-it-footnote": "3.0.1",
+    "markdown-it-footnote": "3.0.2",
     "markdown-it-imsize": "2.0.1",
     "markdown-it-mark": "2.0.0",
     "markdown-it-mathjax": "2.0.0",
@@ -105,7 +105,7 @@
     "mathjax-node": "2.1.1",
     "mime-types": "2.1.24",
     "moment": "2.24.0",
-    "moment-timezone": "0.5.25",
+    "moment-timezone": "0.5.26",
     "mongodb": "3.2.7",
     "mssql": "5.1.0",
     "multer": "1.4.1",
@@ -113,7 +113,7 @@
     "nanoid": "2.0.3",
     "node-2fa": "1.1.2",
     "node-cache": "4.2.0",
-    "nodemailer": "6.2.1",
+    "nodemailer": "6.3.0",
     "objection": "1.6.9",
     "passport": "0.4.0",
     "passport-auth0": "1.1.0",
@@ -138,7 +138,7 @@
     "pg": "7.11.0",
     "pg-hstore": "2.3.3",
     "pg-query-stream": "2.0.0",
-    "pg-tsquery": "8.0.4",
+    "pg-tsquery": "8.0.5",
     "pug": "2.0.4",
     "qr-image": "3.2.0",
     "raven": "2.6.4",
@@ -148,41 +148,41 @@
     "safe-regex": "2.0.2",
     "sanitize-filename": "1.6.1",
     "scim-query-filter-parser": "1.1.0",
-    "semver": "6.1.1",
+    "semver": "6.2.0",
     "serve-favicon": "2.5.0",
-    "simple-git": "1.116.0",
+    "simple-git": "1.121.0",
     "solr-node": "1.2.1",
     "sqlite3": "4.0.9",
     "striptags": "3.1.1",
     "subscriptions-transport-ws": "0.9.16",
     "tar-fs": "2.0.0",
-    "twemoji": "12.0.4",
+    "twemoji": "12.1.2",
     "uslug": "1.0.4",
     "uuid": "3.3.2",
     "validate.js": "0.13.1",
-    "validator": "11.0.0",
+    "validator": "11.1.0",
     "validator-as-promised": "1.0.2",
     "winston": "3.2.1",
     "yargs": "13.2.4"
   },
   "devDependencies": {
-    "@babel/cli": "^7.4.4",
-    "@babel/core": "^7.4.5",
-    "@babel/plugin-proposal-class-properties": "^7.4.4",
+    "@babel/cli": "^7.5.0",
+    "@babel/core": "^7.5.4",
+    "@babel/plugin-proposal-class-properties": "^7.5.0",
     "@babel/plugin-proposal-decorators": "^7.4.4",
-    "@babel/plugin-proposal-export-namespace-from": "^7.2.0",
-    "@babel/plugin-proposal-function-sent": "^7.2.0",
+    "@babel/plugin-proposal-export-namespace-from": "^7.5.2",
+    "@babel/plugin-proposal-function-sent": "^7.5.0",
     "@babel/plugin-proposal-json-strings": "^7.2.0",
     "@babel/plugin-proposal-numeric-separator": "^7.2.0",
     "@babel/plugin-proposal-throw-expressions": "^7.2.0",
     "@babel/plugin-syntax-dynamic-import": "^7.2.0",
     "@babel/plugin-syntax-import-meta": "^7.2.0",
     "@babel/polyfill": "^7.4.4",
-    "@babel/preset-env": "^7.4.5",
+    "@babel/preset-env": "^7.5.4",
     "@panter/vue-i18next": "0.15.1",
     "@vue/babel-preset-app": "3.9.2",
     "animate-sass": "0.8.2",
-    "animated-number-vue": "0.1.5",
+    "animated-number-vue": "1.0.0",
     "apollo-cache-inmemory": "1.6.2",
     "apollo-client": "2.6.3",
     "apollo-link": "1.2.12",
@@ -192,16 +192,16 @@
     "apollo-link-persisted-queries": "0.2.2",
     "apollo-link-ws": "1.0.18",
     "apollo-utilities": "1.3.2",
-    "autoprefixer": "9.6.0",
+    "autoprefixer": "9.6.1",
     "babel-eslint": "10.0.2",
     "babel-jest": "24.8.0",
     "babel-loader": "^8.0.6",
     "babel-plugin-graphql-tag": "2.4.0",
     "babel-plugin-lodash": "3.3.4",
     "babel-plugin-prismjs": "1.0.2",
-    "babel-plugin-transform-imports": "1.5.1",
+    "babel-plugin-transform-imports": "2.0.0",
     "brace": "0.11.1",
-    "cache-loader": "4.0.0",
+    "cache-loader": "4.0.1",
     "chart.js": "2.8.0",
     "clean-webpack-plugin": "3.0.0",
     "copy-webpack-plugin": "5.0.3",
@@ -210,16 +210,16 @@
     "cssnano": "4.1.10",
     "duplicate-package-checker-webpack-plugin": "3.0.0",
     "epic-spinners": "1.1.0",
-    "eslint": "6.0.0",
+    "eslint": "6.0.1",
     "eslint-config-requarks": "1.0.7",
-    "eslint-config-standard": "12.0.0",
-    "eslint-plugin-import": "2.17.3",
+    "eslint-config-standard": "13.0.1",
+    "eslint-plugin-import": "2.18.0",
     "eslint-plugin-node": "9.1.0",
-    "eslint-plugin-promise": "4.1.1",
+    "eslint-plugin-promise": "4.2.1",
     "eslint-plugin-standard": "4.0.0",
-    "eslint-plugin-vue": "5.2.2",
+    "eslint-plugin-vue": "5.2.3",
     "file-loader": "4.0.0",
-    "filepond": "4.4.9",
+    "filepond": "4.4.11",
     "filepond-plugin-file-validate-type": "1.2.4",
     "filesize.js": "1.0.2",
     "grapesjs": "0.14.62",
@@ -239,16 +239,16 @@
     "moment-duration-format": "2.3.2",
     "node-sass": "4.12.0",
     "offline-plugin": "5.0.7",
-    "optimize-css-assets-webpack-plugin": "5.0.1",
+    "optimize-css-assets-webpack-plugin": "5.0.3",
     "postcss-cssnext": "3.1.0",
     "postcss-flexbugs-fixes": "4.1.0",
     "postcss-flexibility": "2.0.0",
     "postcss-import": "12.0.1",
     "postcss-loader": "3.0.0",
-    "postcss-preset-env": "6.6.0",
+    "postcss-preset-env": "6.7.0",
     "postcss-selector-parser": "6.0.2",
     "prismjs": "1.16.0",
-    "pug-lint": "2.5.0",
+    "pug-lint": "2.6.0",
     "pug-loader": "2.4.0",
     "pug-plain-loader": "1.0.0",
     "raw-loader": "3.0.0",
@@ -257,15 +257,15 @@
     "resolve-url-loader": "3.1.0",
     "sass-loader": "7.1.0",
     "sass-resources-loader": "2.0.1",
-    "script-ext-html-webpack-plugin": "2.1.3",
+    "script-ext-html-webpack-plugin": "2.1.4",
     "simple-progress-webpack-plugin": "1.1.2",
     "style-loader": "0.23.1",
     "stylus": "0.54.5",
     "stylus-loader": "3.0.2",
-    "terser": "4.0.0",
+    "terser": "4.1.2",
     "twemoji-awesome": "1.0.6",
-    "url-loader": "2.0.0",
-    "vee-validate": "2.2.11",
+    "url-loader": "2.0.1",
+    "vee-validate": "2.2.12",
     "velocity-animate": "1.5.2",
     "viz.js": "2.1.2",
     "vue": "2.6.10",
@@ -276,30 +276,30 @@
     "vue-filepond": "5.1.1",
     "vue-hot-reload-api": "2.3.3",
     "vue-loader": "15.7.0",
-    "vue-material-design-icons": "3.2.0",
+    "vue-material-design-icons": "3.3.1",
     "vue-moment": "4.0.0",
-    "vue-router": "3.0.6",
+    "vue-router": "3.0.7",
     "vue-simple-breakpoints": "1.0.3",
     "vue-status-indicator": "1.1.1",
     "vue-template-compiler": "2.6.10",
     "vue-tour": "1.1.0",
     "vue2-animate": "2.1.0",
-    "vuedraggable": "2.22.0",
-    "vuescroll": "4.13.0",
+    "vuedraggable": "2.23.0",
+    "vuescroll": "4.13.1",
     "vuetify": "1.5.16",
     "vuex": "3.1.1",
     "vuex-pathify": "1.2.4",
     "vuex-persistedstate": "2.5.4",
-    "webpack": "4.35.0",
+    "webpack": "4.35.3",
     "webpack-bundle-analyzer": "3.3.2",
-    "webpack-cli": "3.3.4",
+    "webpack-cli": "3.3.6",
     "webpack-dev-middleware": "3.7.0",
     "webpack-hot-middleware": "2.25.0",
     "webpack-merge": "4.2.1",
     "webpack-subresource-integrity": "1.3.2",
     "whatwg-fetch": "3.0.0",
     "write-file-webpack-plugin": "4.5.0",
-    "xterm": "3.14.2",
+    "xterm": "3.14.5",
     "zxcvbn": "4.4.2"
   },
   "browserslist": [

+ 8 - 1
server/controllers/common.js

@@ -58,6 +58,13 @@ router.get(['/e', '/e/*'], async (req, res, next) => {
     userId: req.user.id,
     isPrivate: false
   })
+
+  const injectCode = {
+    css: WIKI.config.theming.injectCSS,
+    head: WIKI.config.theming.injectHead,
+    body: WIKI.config.theming.injectBody
+  }
+
   if (page) {
     if (!WIKI.auth.checkAccess(req.user, ['manage:pages'], pageArgs)) {
       _.set(res.locals, 'pageMeta.title', 'Unauthorized')
@@ -84,7 +91,7 @@ router.get(['/e', '/e/*'], async (req, res, next) => {
       content: null
     }
   }
-  res.render('editor', { page })
+  res.render('editor', { page, injectCode })
 })
 
 /**

+ 3 - 2
server/graph/resolvers/page.js

@@ -98,9 +98,10 @@ module.exports = {
     },
     async migrateToLocale(obj, args, context) {
       try {
-
+        const count = await WIKI.models.pages.migrateToLocale(args)
         return {
-          responseResult: graphHelper.generateSuccess('Migrated all content to target locale successfully.')
+          responseResult: graphHelper.generateSuccess('Migrated content to target locale successfully.'),
+          count
         }
       } catch (err) {
         return graphHelper.generateError(err)

+ 6 - 1
server/graph/schemas/page.graphql

@@ -77,7 +77,7 @@ type PageMutation {
   migrateToLocale(
     sourceLocale: String!
     targetLocale: String!
-  ): DefaultResponse @auth(requires: ["manage:system"])
+  ): PageMigrationResponse @auth(requires: ["manage:system"])
 }
 
 # -----------------------------------------------
@@ -89,6 +89,11 @@ type PageResponse {
   page: Page
 }
 
+type PageMigrationResponse {
+  responseResult: ResponseStatus!
+  count: Int
+}
+
 type Page {
   id: Int!
   path: String!

+ 13 - 0
server/models/pages.js

@@ -421,6 +421,19 @@ module.exports = class Page extends Model {
     return fs.emptyDir(path.join(process.cwd(), `data/cache`))
   }
 
+  static async migrateToLocale({ sourceLocale, targetLocale }) {
+    return WIKI.models.pages.query()
+      .patch({
+        localeCode: targetLocale
+      })
+      .where({
+        localeCode: sourceLocale
+      })
+      .whereNotExists(function() {
+        this.select('id').from('pages AS pagesm').where('pagesm.localeCode', targetLocale).andWhereRaw('pagesm.path = pages.path')
+      })
+  }
+
   static cleanHTML(rawHTML = '') {
     return striptags(rawHTML || '')
       .replace(emojiRegex(), '')

+ 4 - 0
server/views/editor.pug

@@ -1,5 +1,9 @@
 extends master.pug
 
+block head
+  if injectCode.css
+    style(type='text/css')!= injectCode.css
+
 block body
   #root
     editor(

文件差异内容过多而无法显示
+ 243 - 317
yarn.lock


部分文件因为文件数量过多而无法显示