Browse Source

feat: sideloading + locales nav menu

pull/901/head
Nick 5 years ago
parent
commit
28cf67cdaa
12 changed files with 151 additions and 23 deletions
  1. 30
      client/components/common/nav-header.vue
  2. 8
      config.sample.yml
  3. 2
      dev/templates/master.pug
  4. 4
      server/app/data.yml
  5. 1
      server/core/kernel.js
  6. 6
      server/core/scheduler.js
  7. 76
      server/core/sideloader.js
  8. 2
      server/core/telemetry.js
  9. 2
      server/graph/resolvers/localization.js
  10. 16
      server/master.js
  11. 25
      server/models/locales.js
  12. 2
      server/views/master.pug

30
client/components/common/nav-header.vue

@ -137,17 +137,17 @@
icon icon
) )
v-icon(color='grey') search v-icon(color='grey') search
//- v-menu(offset-y, left, transition='slide-y-transition')
//- v-tooltip(bottom, slot='activator')
//- v-btn(icon, slot='activator')
//- v-icon(color='grey') language
//- span Language
//- v-list.py-0
//- template(v-for='(lc, idx) of locales')
//- v-list-tile(@click='changeLocale(lc)')
//- v-list-tile-action: v-chip(:color='lc.code === $i18n.i18next.language ? `blue` : `grey`', small, label, dark) {{lc.code.toUpperCase()}}
//- v-list-tile-title {{lc.name}}
//- v-divider.my-0(v-if='idx < locales.length - 1')
v-menu(offset-y, left, transition='slide-y-transition', v-if='mode === `view` && locales.length > 0')
v-tooltip(bottom, slot='activator')
v-btn(icon, slot='activator')
v-icon(color='grey') language
span Language
v-list.py-0
template(v-for='(lc, idx) of locales')
v-list-tile(@click='changeLocale(lc)')
v-list-tile-action: v-chip(:color='lc.code === $i18n.i18next.language ? `blue` : `grey`', small, label, dark) {{lc.code.toUpperCase()}}
v-list-tile-title {{lc.name}}
v-divider.my-0(v-if='idx < locales.length - 1')
v-tooltip(bottom, v-if='isAuthenticated && isAdmin') v-tooltip(bottom, v-if='isAuthenticated && isAdmin')
v-btn.btn-animate-rotate(icon, href='/a', slot='activator') v-btn.btn-animate-rotate(icon, href='/a', slot='activator')
v-icon(color='grey') settings v-icon(color='grey') settings
@ -196,6 +196,8 @@ import { get, sync } from 'vuex-pathify'
import _ from 'lodash' import _ from 'lodash'
import Cookies from 'js-cookie' import Cookies from 'js-cookie'
/* global siteLangs */
export default { export default {
components: { components: {
PageDelete: () => import('./page-delete.vue') PageDelete: () => import('./page-delete.vue')
@ -217,11 +219,7 @@ export default {
searchAdvMenuShown: false, searchAdvMenuShown: false,
newPageModal: false, newPageModal: false,
deletePageModal: false, deletePageModal: false,
locales: [
{ code: 'en', name: 'English' },
{ code: 'fr', name: 'Français' },
{ code: 'es', name: 'Español' }
]
locales: siteLangs
} }
}, },
computed: { computed: {

8
config.sample.yml

@ -105,3 +105,11 @@ uploads:
maxFileSize: 5242880 maxFileSize: 5242880
# Maximum file uploads per request (default: 20) # Maximum file uploads per request (default: 20)
maxFiles: 10 maxFiles: 10
# ---------------------------------------------------------------------
# Offline Mode
# ---------------------------------------------------------------------
# If your server cannot access the internet. Set to true and manually
# download the offline files for sideloading.
offline: false

2
dev/templates/master.pug

@ -29,7 +29,7 @@ html
//- Site Properties //- Site Properties
script. script.
var siteConfig = !{JSON.stringify({ title: config.title, theme: config.theming.theme, darkMode: config.theming.darkMode, lang: config.lang.code, rtl: config.lang.rtl, company: config.company })}
var siteConfig = !{JSON.stringify(siteConfig)}; var siteLangs = !{JSON.stringify(langs)}
//- CSS //- CSS
<% for (var index in htmlWebpackPlugin.files.css) { %> <% for (var index in htmlWebpackPlugin.files.css) { %>

4
server/app/data.yml

@ -24,6 +24,7 @@ defaults:
uploads: uploads:
maxFileSize: 5242880 maxFileSize: 5242880
maxFiles: 10 maxFiles: 10
offline: false
# DB defaults # DB defaults
graphEndpoint: 'https://graph.requarks.io' graphEndpoint: 'https://graph.requarks.io'
lang: lang:
@ -63,12 +64,15 @@ jobs:
purgeUploads: purgeUploads:
onInit: true onInit: true
schedule: PT15M schedule: PT15M
offlineSkip: false
syncGraphLocales: syncGraphLocales:
onInit: true onInit: true
schedule: P1D schedule: P1D
offlineSkip: true
syncGraphUpdates: syncGraphUpdates:
onInit: true onInit: true
schedule: P1D schedule: P1D
offlineSkip: true
groups: groups:
defaultPermissions: defaultPermissions:
- 'read:pages' - 'read:pages'

1
server/core/kernel.js

@ -34,6 +34,7 @@ module.exports = {
await this.initTelemetry() await this.initTelemetry()
WIKI.cache = require('./cache').init() WIKI.cache = require('./cache').init()
WIKI.scheduler = require('./scheduler').init() WIKI.scheduler = require('./scheduler').init()
WIKI.sideloader = require('./sideloader').init()
WIKI.events = new EventEmitter() WIKI.events = new EventEmitter()
} catch (err) { } catch (err) {
WIKI.logger.error(err) WIKI.logger.error(err)

6
server/core/scheduler.js

@ -87,7 +87,6 @@ class Job {
} }
} }
module.exports = { module.exports = {
jobs: [], jobs: [],
init() { init() {
@ -95,6 +94,11 @@ module.exports = {
}, },
start() { start() {
_.forOwn(WIKI.data.jobs, (queueParams, queueName) => { _.forOwn(WIKI.data.jobs, (queueParams, queueName) => {
if (WIKI.config.offline && queueParams.offlineSkip) {
WIKI.logger.warn(`Skipping job ${queueName} because offline mode is enabled. [SKIPPED]`)
return
}
const schedule = (configHelper.isValidDurationString(queueParams.schedule)) ? queueParams.schedule : _.get(WIKI.config, queueParams.schedule) const schedule = (configHelper.isValidDurationString(queueParams.schedule)) ? queueParams.schedule : _.get(WIKI.config, queueParams.schedule)
this.registerJob({ this.registerJob({
name: _.kebabCase(queueName), name: _.kebabCase(queueName),

76
server/core/sideloader.js

@ -0,0 +1,76 @@
const fs = require('fs-extra')
const path = require('path')
const _ = require('lodash')
/* global WIKI */
module.exports = {
async init () {
if (!WIKI.config.offline) {
return
}
const sideloadExists = await fs.pathExists(path.join(WIKI.ROOTPATH, 'data/sideload'))
if (!sideloadExists) {
return
}
WIKI.logger.info('Sideload directory detected. Looking for packages...')
try {
await this.importLocales()
} catch (err) {
WIKI.logger.warn(err)
}
},
async importLocales() {
const localeExists = await fs.pathExists(path.join(WIKI.ROOTPATH, 'data/sideload/locales.json'))
if (localeExists) {
WIKI.logger.info('Found locales master file. Importing locale packages...')
let importedLocales = 0
const locales = await fs.readJson(path.join(WIKI.ROOTPATH, 'data/sideload/locales.json'))
if (locales && _.has(locales, 'data.localization.locales')) {
for (const locale of locales.data.localization.locales) {
try {
const localeData = await fs.readJson(path.join(WIKI.ROOTPATH, `data/sideload/${locale.code}.json`))
if (localeData) {
WIKI.logger.info(`Importing ${locale.name} locale package...`)
let lcObj = {}
_.forOwn(localeData, (value, key) => {
if (_.includes(key, '::')) { return }
if (_.isEmpty(value)) { value = key }
_.set(lcObj, key.replace(':', '.'), value)
})
const localeExists = await WIKI.models.locales.query().select('code').where('code', locale.code).first()
if (localeExists) {
await WIKI.models.locales.query().update({
code: locale.code,
strings: lcObj,
isRTL: locale.isRTL,
name: locale.name,
nativeName: locale.nativeName
}).where('code', locale.code)
} else {
await WIKI.models.locales.query().insert({
code: locale.code,
strings: lcObj,
isRTL: locale.isRTL,
name: locale.name,
nativeName: locale.nativeName
})
}
importedLocales++
}
} catch (err) {
// skip
}
}
WIKI.logger.info(`Imported ${importedLocales} locale packages: [COMPLETED]`)
}
}
}
}

2
server/core/telemetry.js

@ -28,7 +28,7 @@ module.exports = {
}) })
WIKI.telemetry = this WIKI.telemetry = this
if (_.get(WIKI.config, 'telemetry.isEnabled', false) === true) {
if (_.get(WIKI.config, 'telemetry.isEnabled', false) === true && WIKI.config.offline !== true) {
this.enabled = true this.enabled = true
this.sendOSInfo() this.sendOSInfo()
} }

2
server/graph/resolvers/localization.js

@ -66,6 +66,8 @@ module.exports = {
await WIKI.lang.setCurrentLocale(args.locale) await WIKI.lang.setCurrentLocale(args.locale)
await WIKI.lang.refreshNamespaces() await WIKI.lang.refreshNamespaces()
await WIKI.cache.del('nav:locales')
return { return {
responseResult: graphHelper.generateSuccess('Locale config updated') responseResult: graphHelper.generateSuccess('Locale config updated')
} }

16
server/master.js

@ -105,9 +105,6 @@ module.exports = async () => {
// ---------------------------------------- // ----------------------------------------
app.locals.basedir = WIKI.ROOTPATH app.locals.basedir = WIKI.ROOTPATH
app.locals._ = require('lodash')
app.locals.moment = require('moment')
app.locals.moment.locale(WIKI.config.lang.code)
app.locals.config = WIKI.config app.locals.config = WIKI.config
app.locals.pageMeta = { app.locals.pageMeta = {
title: '', title: '',
@ -146,6 +143,19 @@ module.exports = async () => {
// Routing // Routing
// ---------------------------------------- // ----------------------------------------
app.use(async (req, res, next) => {
res.locals.siteConfig = {
title: WIKI.config.title,
theme: WIKI.config.theming.theme,
darkMode: WIKI.config.theming.darkMode,
lang: WIKI.config.lang.code,
rtl: WIKI.config.lang.rtl,
company: WIKI.config.company
}
res.locals.langs = await WIKI.models.locales.getNavLocales({ cache: true })
next()
})
app.use('/', ctrl.auth) app.use('/', ctrl.auth)
app.use('/', ctrl.upload) app.use('/', ctrl.upload)
app.use('/', ctrl.common) app.use('/', ctrl.common)

25
server/models/locales.js

@ -1,5 +1,7 @@
const Model = require('objection').Model const Model = require('objection').Model
/* global WIKI */
/** /**
* Locales model * Locales model
*/ */
@ -34,4 +36,27 @@ module.exports = class Locale extends Model {
this.createdAt = new Date().toISOString() this.createdAt = new Date().toISOString()
this.updatedAt = new Date().toISOString() this.updatedAt = new Date().toISOString()
} }
static async getNavLocales({ cache = false } = {}) {
if (!WIKI.config.lang.namespacing) {
return []
}
if (cache) {
const navLocalesCached = await WIKI.cache.get('nav:locales')
if (navLocalesCached) {
return navLocalesCached
}
}
const navLocales = await WIKI.models.locales.query().select('code', 'nativeName AS name').whereIn('code', WIKI.config.lang.namespaces).orderBy('code')
if (navLocales) {
if (cache) {
await WIKI.cache.set('nav:locales', navLocales, 300)
}
return navLocales
} else {
WIKI.logger.warn('Site Locales for navigation are missing or corrupted.')
return []
}
}
} }

2
server/views/master.pug

@ -29,7 +29,7 @@ html
//- Site Properties //- Site Properties
script. script.
var siteConfig = !{JSON.stringify({ title: config.title, theme: config.theming.theme, darkMode: config.theming.darkMode, lang: config.lang.code, rtl: config.lang.rtl, company: config.company })}
var siteConfig = !{JSON.stringify(siteConfig)}; var siteLangs = !{JSON.stringify(langs)}
//- CSS //- CSS

Loading…
Cancel
Save