mirror of
https://github.com/requarks/wiki.git
synced 2026-08-26 21:27:10 -05:00
refactor: admin editors + flags page to comp api, server cleanup
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "ux"
|
||||
},
|
||||
{
|
||||
"path": "server"
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
"i18n-ally.localesPaths": [
|
||||
"src/i18n",
|
||||
"src/i18n/locales"
|
||||
]
|
||||
}
|
||||
}
|
||||
+23
-32
@@ -34,32 +34,32 @@
|
||||
"node": ">=16.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@azure/storage-blob": "12.2.1",
|
||||
"@azure/storage-blob": "12.9.0",
|
||||
"@exlinc/keycloak-passport": "1.0.2",
|
||||
"@graphql-tools/schema": "8.3.7",
|
||||
"@graphql-tools/utils": "8.6.6",
|
||||
"@joplin/turndown-plugin-gfm": "1.0.43",
|
||||
"@root/csr": "0.8.1",
|
||||
"@root/keypairs": "0.10.3",
|
||||
"@root/pem": "1.0.4",
|
||||
"acme": "3.0.3",
|
||||
"akismet-api": "5.2.1",
|
||||
"algoliasearch": "4.5.1",
|
||||
"akismet-api": "5.3.0",
|
||||
"apollo-fetch": "0.7.0",
|
||||
"apollo-server": "2.25.2",
|
||||
"apollo-server-express": "2.25.2",
|
||||
"apollo-server": "3.6.7",
|
||||
"apollo-server-express": "3.6.7",
|
||||
"auto-load": "3.0.4",
|
||||
"aws-sdk": "2.1111.0",
|
||||
"azure-search-client": "3.1.5",
|
||||
"bcryptjs-then": "1.0.1",
|
||||
"bluebird": "3.7.2",
|
||||
"body-parser": "1.19.1",
|
||||
"chalk": "4.1.0",
|
||||
"body-parser": "1.20.0",
|
||||
"chalk": "4.1.2",
|
||||
"cheerio": "1.0.0-rc.5",
|
||||
"chokidar": "3.5.3",
|
||||
"chromium-pickle-js": "0.2.0",
|
||||
"clean-css": "4.2.3",
|
||||
"command-exists": "1.2.9",
|
||||
"compression": "1.7.4",
|
||||
"connect-session-knex": "2.0.0",
|
||||
"connect-session-knex": "2.1.1",
|
||||
"cookie-parser": "1.4.6",
|
||||
"cors": "2.8.5",
|
||||
"cuint": "0.2.2",
|
||||
@@ -69,8 +69,6 @@
|
||||
"diff2html": "3.1.14",
|
||||
"dompurify": "2.2.7",
|
||||
"dotize": "0.3.0",
|
||||
"elasticsearch6": "npm:@elastic/elasticsearch@6",
|
||||
"elasticsearch7": "npm:@elastic/elasticsearch@7",
|
||||
"emoji-regex": "9.2.2",
|
||||
"eventemitter2": "6.4.5",
|
||||
"express": "4.17.3",
|
||||
@@ -80,11 +78,11 @@
|
||||
"filesize": "6.1.0",
|
||||
"fs-extra": "9.0.1",
|
||||
"getos": "3.2.1",
|
||||
"graphql": "15.3.0",
|
||||
"graphql": "16.3.0",
|
||||
"graphql-list-fields": "2.0.2",
|
||||
"graphql-rate-limit-directive": "1.2.1",
|
||||
"graphql-subscriptions": "1.1.0",
|
||||
"graphql-tools": "7.0.0",
|
||||
"graphql-rate-limit-directive": "2.0.2",
|
||||
"graphql-tools": "8.2.5",
|
||||
"graphql-upload": "13.0.0",
|
||||
"he": "1.2.0",
|
||||
"highlight.js": "10.3.1",
|
||||
"i18next": "19.8.3",
|
||||
@@ -93,14 +91,14 @@
|
||||
"image-size": "0.9.2",
|
||||
"js-base64": "3.7.2",
|
||||
"js-binary": "1.2.0",
|
||||
"js-yaml": "3.14.0",
|
||||
"js-yaml": "4.1.0",
|
||||
"jsdom": "16.4.0",
|
||||
"jsonwebtoken": "8.5.1",
|
||||
"katex": "0.12.0",
|
||||
"klaw": "3.0.0",
|
||||
"klaw": "4.0.1",
|
||||
"knex": "1.0.5",
|
||||
"lodash": "4.17.21",
|
||||
"luxon": "1.25.0",
|
||||
"luxon": "2.3.1",
|
||||
"markdown-it": "11.0.1",
|
||||
"markdown-it-abbr": "1.0.4",
|
||||
"markdown-it-attrs": "3.0.3",
|
||||
@@ -116,15 +114,15 @@
|
||||
"markdown-it-sup": "1.0.0",
|
||||
"markdown-it-task-lists": "2.1.1",
|
||||
"mathjax": "3.1.2",
|
||||
"mime-types": "2.1.34",
|
||||
"moment": "2.29.1",
|
||||
"mime-types": "2.1.35",
|
||||
"moment": "2.29.2",
|
||||
"moment-timezone": "0.5.31",
|
||||
"ms": "2.1.3",
|
||||
"multer": "1.4.4",
|
||||
"nanoid": "3.2.0",
|
||||
"node-2fa": "1.1.2",
|
||||
"node-cache": "5.1.2",
|
||||
"nodemailer": "6.7.2",
|
||||
"nodemailer": "6.7.3",
|
||||
"objection": "3.0.1",
|
||||
"passport": "0.4.1",
|
||||
"passport-auth0": "1.4.2",
|
||||
@@ -155,7 +153,7 @@
|
||||
"pug": "3.0.2",
|
||||
"punycode": "2.1.1",
|
||||
"qr-image": "3.2.0",
|
||||
"raven": "2.6.4",
|
||||
"rate-limiter-flexible": "2.3.6",
|
||||
"remove-markdown": "0.3.0",
|
||||
"request": "2.88.2",
|
||||
"request-promise": "4.2.6",
|
||||
@@ -165,18 +163,15 @@
|
||||
"semver": "7.3.6",
|
||||
"serve-favicon": "2.5.0",
|
||||
"simple-git": "2.21.0",
|
||||
"solr-node": "1.2.1",
|
||||
"ssh2": "1.5.0",
|
||||
"ssh2": "1.9.0",
|
||||
"ssh2-promise": "1.0.2",
|
||||
"striptags": "3.2.0",
|
||||
"subscriptions-transport-ws": "0.9.18",
|
||||
"tar-fs": "2.1.1",
|
||||
"turndown": "7.1.1",
|
||||
"twemoji": "13.1.0",
|
||||
"uslug": "1.0.4",
|
||||
"uuid": "8.3.2",
|
||||
"validate.js": "0.13.1",
|
||||
"winston": "3.7.2",
|
||||
"xss": "1.0.11",
|
||||
"yargs": "16.1.0"
|
||||
},
|
||||
@@ -219,10 +214,10 @@
|
||||
"babel-plugin-transform-imports": "2.0.0",
|
||||
"cache-loader": "4.1.0",
|
||||
"canvas-confetti": "1.3.1",
|
||||
"cash-dom": "8.1.0",
|
||||
"cash-dom": "8.1.1",
|
||||
"chart.js": "2.9.4",
|
||||
"clean-webpack-plugin": "3.0.0",
|
||||
"clipboard": "2.0.8",
|
||||
"clipboard": "2.0.10",
|
||||
"codemirror": "5.58.2",
|
||||
"copy-webpack-plugin": "6.2.1",
|
||||
"core-js": "3.6.5",
|
||||
@@ -321,10 +316,6 @@
|
||||
"xterm": "4.9.0",
|
||||
"zxcvbn": "4.4.2"
|
||||
},
|
||||
"resolutions": {
|
||||
"apollo-server-express/**/graphql-tools": "4.0.8",
|
||||
"graphql": "15.3.0"
|
||||
},
|
||||
"browserslist": [
|
||||
"> 1%",
|
||||
"last 2 major versions",
|
||||
|
||||
@@ -32,12 +32,12 @@ module.exports = {
|
||||
let appdata = {}
|
||||
|
||||
try {
|
||||
appconfig = yaml.safeLoad(
|
||||
appconfig = yaml.load(
|
||||
cfgHelper.parseConfigValue(
|
||||
fs.readFileSync(confPaths.config, 'utf8')
|
||||
)
|
||||
)
|
||||
appdata = yaml.safeLoad(fs.readFileSync(confPaths.data, 'utf8'))
|
||||
appdata = yaml.load(fs.readFileSync(confPaths.data, 'utf8'))
|
||||
appdata.regex = require(confPaths.dataRegex)
|
||||
console.info(chalk.green.bold(`OK`))
|
||||
} catch (err) {
|
||||
|
||||
@@ -128,6 +128,8 @@ module.exports = {
|
||||
},
|
||||
// -> Migrate DB Schemas
|
||||
async syncSchemas () {
|
||||
WIKI.logger.info('Ensuring DB schema exists...')
|
||||
await self.knex.raw(`CREATE SCHEMA IF NOT EXISTS ${WIKI.config.db.schemas.wiki}`)
|
||||
WIKI.logger.info('Ensuring DB migrations have been applied...')
|
||||
return self.knex.migrate.latest({
|
||||
tableName: 'migrations',
|
||||
|
||||
+3
-11
@@ -52,14 +52,9 @@ module.exports = {
|
||||
*/
|
||||
async bootMaster() {
|
||||
try {
|
||||
if (WIKI.config.setup) {
|
||||
WIKI.logger.info('Starting setup wizard...')
|
||||
require('../setup')()
|
||||
} else {
|
||||
await this.preBootMaster()
|
||||
await require('../master')()
|
||||
this.postBootMaster()
|
||||
}
|
||||
await this.preBootMaster()
|
||||
await require('../master')()
|
||||
this.postBootMaster()
|
||||
} catch (err) {
|
||||
WIKI.logger.error(err)
|
||||
process.exit(1)
|
||||
@@ -73,16 +68,13 @@ module.exports = {
|
||||
await WIKI.models.authentication.refreshStrategiesFromDisk()
|
||||
await WIKI.models.commentProviders.refreshProvidersFromDisk()
|
||||
await WIKI.models.editors.refreshEditorsFromDisk()
|
||||
await WIKI.models.loggers.refreshLoggersFromDisk()
|
||||
await WIKI.models.renderers.refreshRenderersFromDisk()
|
||||
await WIKI.models.searchEngines.refreshSearchEnginesFromDisk()
|
||||
await WIKI.models.storage.refreshTargetsFromDisk()
|
||||
|
||||
await WIKI.extensions.init()
|
||||
|
||||
await WIKI.auth.activateStrategies()
|
||||
await WIKI.models.commentProviders.initProvider()
|
||||
await WIKI.models.searchEngines.initEngine()
|
||||
await WIKI.models.storage.initTargets()
|
||||
WIKI.scheduler.start()
|
||||
|
||||
|
||||
+46
-37
@@ -1,44 +1,53 @@
|
||||
// const _ = require('lodash')
|
||||
const winston = require('winston')
|
||||
const chalk = require('chalk')
|
||||
const EventEmitter = require('events')
|
||||
|
||||
/* global WIKI */
|
||||
|
||||
const LEVELS = ['error', 'warn', 'info', 'debug']
|
||||
const LEVELSIGNORED = ['verbose', 'silly']
|
||||
const LEVELCOLORS = {
|
||||
error: 'red',
|
||||
warn: 'yellow',
|
||||
info: 'green',
|
||||
debug: 'cyan'
|
||||
}
|
||||
|
||||
class Logger extends EventEmitter {}
|
||||
const primaryLogger = new Logger()
|
||||
|
||||
let ignoreNextLevels = false
|
||||
|
||||
LEVELS.forEach(lvl => {
|
||||
primaryLogger[lvl] = (...args) => {
|
||||
primaryLogger.emit(lvl, ...args)
|
||||
}
|
||||
|
||||
if (!ignoreNextLevels) {
|
||||
primaryLogger.on(lvl, (msg) => {
|
||||
if (WIKI.config.logFormat === 'json') {
|
||||
console.log(JSON.stringify({
|
||||
timestamp: new Date().toISOString(),
|
||||
instance: WIKI.INSTANCE_ID,
|
||||
level: lvl,
|
||||
message: msg
|
||||
}))
|
||||
} else {
|
||||
console.log(chalk`${new Date().toISOString()} {dim [${WIKI.INSTANCE_ID}]} {${LEVELCOLORS[lvl]}.bold ${lvl}}: ${msg}`)
|
||||
}
|
||||
})
|
||||
}
|
||||
if (lvl === WIKI.config.logLevel) {
|
||||
ignoreNextLevels = true
|
||||
}
|
||||
})
|
||||
|
||||
LEVELSIGNORED.forEach(lvl => {
|
||||
primaryLogger[lvl] = () => {}
|
||||
})
|
||||
|
||||
module.exports = {
|
||||
loggers: {},
|
||||
init(uid) {
|
||||
const loggerFormats = [
|
||||
winston.format.label({ label: uid }),
|
||||
winston.format.timestamp()
|
||||
]
|
||||
|
||||
if (WIKI.config.logFormat === 'json') {
|
||||
loggerFormats.push(winston.format.json())
|
||||
} else {
|
||||
loggerFormats.push(winston.format.colorize())
|
||||
loggerFormats.push(winston.format.printf(info => `${info.timestamp} [${info.label}] ${info.level}: ${info.message}`))
|
||||
}
|
||||
|
||||
const logger = winston.createLogger({
|
||||
level: WIKI.config.logLevel,
|
||||
format: winston.format.combine(...loggerFormats)
|
||||
})
|
||||
|
||||
// Init Console (default)
|
||||
|
||||
logger.add(new winston.transports.Console({
|
||||
level: WIKI.config.logLevel,
|
||||
prettyPrint: true,
|
||||
colorize: true,
|
||||
silent: false,
|
||||
timestamp: true
|
||||
}))
|
||||
|
||||
// _.forOwn(_.omitBy(WIKI.config.logging.loggers, s => s.enabled === false), (loggerConfig, loggerKey) => {
|
||||
// let loggerModule = require(`../modules/logging/${loggerKey}`)
|
||||
// loggerModule.init(logger, loggerConfig)
|
||||
// this.loggers[logger.key] = loggerModule
|
||||
// })
|
||||
|
||||
return logger
|
||||
init () {
|
||||
return primaryLogger
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ module.exports = {
|
||||
async startHTTP () {
|
||||
WIKI.logger.info(`HTTP Server on port: [ ${WIKI.config.port} ]`)
|
||||
this.servers.http = http.createServer(WIKI.app)
|
||||
this.servers.graph.installSubscriptionHandlers(this.servers.http)
|
||||
|
||||
this.servers.http.listen(WIKI.config.port, WIKI.config.bindIP)
|
||||
this.servers.http.on('error', (error) => {
|
||||
@@ -83,7 +82,6 @@ module.exports = {
|
||||
return process.exit(1)
|
||||
}
|
||||
this.servers.https = https.createServer(tlsOpts, WIKI.app)
|
||||
this.servers.graph.installSubscriptionHandlers(this.servers.https)
|
||||
|
||||
this.servers.https.listen(WIKI.config.ssl.port, WIKI.config.bindIP)
|
||||
this.servers.https.on('error', (error) => {
|
||||
@@ -121,15 +119,15 @@ module.exports = {
|
||||
async startGraphQL () {
|
||||
const graphqlSchema = require('../graph')
|
||||
this.servers.graph = new ApolloServer({
|
||||
...graphqlSchema,
|
||||
schema: graphqlSchema,
|
||||
uploads: false,
|
||||
context: ({ req, res }) => ({ req, res }),
|
||||
subscriptions: {
|
||||
onConnect: (connectionParams, webSocket) => {
|
||||
|
||||
},
|
||||
path: '/graphql-subscriptions'
|
||||
}
|
||||
plugins: [
|
||||
// ApolloServerPluginDrainHttpServer({ httpServer: this.servers.http })
|
||||
// ...(this.servers.https && ApolloServerPluginDrainHttpServer({ httpServer: this.servers.https }))
|
||||
]
|
||||
})
|
||||
await this.servers.graph.start()
|
||||
this.servers.graph.applyMiddleware({ app: WIKI.app, cors: false })
|
||||
},
|
||||
/**
|
||||
|
||||
@@ -327,12 +327,6 @@ exports.up = async knex => {
|
||||
// -> SYSTEM CONFIG
|
||||
|
||||
await knex('settings').insert([
|
||||
{
|
||||
key: 'update',
|
||||
value: {
|
||||
locales: true
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'mail',
|
||||
value: {
|
||||
@@ -372,6 +366,18 @@ exports.up = async knex => {
|
||||
uploadMaxFiles: 20,
|
||||
uploadScanSVG: true
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'system',
|
||||
value: {
|
||||
sessionSecret: crypto.randomBytes(32).toString('hex')
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'update',
|
||||
value: {
|
||||
locales: true
|
||||
}
|
||||
}
|
||||
])
|
||||
|
||||
|
||||
+16
-45
@@ -1,26 +1,22 @@
|
||||
const _ = require('lodash')
|
||||
const fs = require('fs')
|
||||
// const gqlTools = require('graphql-tools')
|
||||
const path = require('path')
|
||||
const autoload = require('auto-load')
|
||||
const PubSub = require('graphql-subscriptions').PubSub
|
||||
const { LEVEL, MESSAGE } = require('triple-beam')
|
||||
const Transport = require('winston-transport')
|
||||
const { createRateLimitTypeDef } = require('graphql-rate-limit-directive')
|
||||
// const { GraphQLUpload } = require('graphql-upload')
|
||||
const { makeExecutableSchema } = require('@graphql-tools/schema')
|
||||
const { rateLimitDirective } = require('graphql-rate-limit-directive')
|
||||
const { GraphQLUpload } = require('graphql-upload')
|
||||
const { rateLimitDirectiveTypeDefs, rateLimitDirectiveTransformer } = rateLimitDirective()
|
||||
|
||||
/* global WIKI */
|
||||
|
||||
WIKI.logger.info(`Loading GraphQL Schema...`)
|
||||
|
||||
// Init Subscription PubSub
|
||||
|
||||
WIKI.GQLEmitter = new PubSub()
|
||||
|
||||
// Schemas
|
||||
|
||||
let typeDefs = [createRateLimitTypeDef()]
|
||||
let schemas = fs.readdirSync(path.join(WIKI.SERVERPATH, 'graph/schemas'))
|
||||
const typeDefs = [
|
||||
rateLimitDirectiveTypeDefs
|
||||
]
|
||||
const schemas = fs.readdirSync(path.join(WIKI.SERVERPATH, 'graph/schemas'))
|
||||
schemas.forEach(schema => {
|
||||
typeDefs.push(fs.readFileSync(path.join(WIKI.SERVERPATH, `graph/schemas/${schema}`), 'utf8'))
|
||||
})
|
||||
@@ -28,47 +24,22 @@ schemas.forEach(schema => {
|
||||
// Resolvers
|
||||
|
||||
let resolvers = {
|
||||
// Upload: GraphQLUpload
|
||||
Upload: GraphQLUpload
|
||||
}
|
||||
const resolversObj = _.values(autoload(path.join(WIKI.SERVERPATH, 'graph/resolvers')))
|
||||
resolversObj.forEach(resolver => {
|
||||
_.merge(resolvers, resolver)
|
||||
})
|
||||
|
||||
// Directives
|
||||
// Make executable schema
|
||||
|
||||
let schemaDirectives = {
|
||||
...autoload(path.join(WIKI.SERVERPATH, 'graph/directives'))
|
||||
}
|
||||
let schema = makeExecutableSchema({
|
||||
typeDefs,
|
||||
resolvers
|
||||
})
|
||||
|
||||
// Live Trail Logger (admin)
|
||||
|
||||
class LiveTrailLogger extends Transport {
|
||||
constructor(opts) {
|
||||
super(opts)
|
||||
|
||||
this.name = 'liveTrailLogger'
|
||||
this.level = 'debug'
|
||||
}
|
||||
|
||||
log (info, callback = () => {}) {
|
||||
WIKI.GQLEmitter.publish('livetrail', {
|
||||
loggingLiveTrail: {
|
||||
timestamp: new Date(),
|
||||
level: info[LEVEL],
|
||||
output: info[MESSAGE]
|
||||
}
|
||||
})
|
||||
callback(null, true)
|
||||
}
|
||||
}
|
||||
|
||||
WIKI.logger.add(new LiveTrailLogger({}))
|
||||
schema = rateLimitDirectiveTransformer(schema)
|
||||
|
||||
WIKI.logger.info(`GraphQL Schema: [ OK ]`)
|
||||
|
||||
module.exports = {
|
||||
typeDefs,
|
||||
resolvers,
|
||||
schemaDirectives
|
||||
}
|
||||
module.exports = schema
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
const _ = require('lodash')
|
||||
const graphHelper = require('../../helpers/graph')
|
||||
|
||||
/* global WIKI */
|
||||
|
||||
module.exports = {
|
||||
Query: {
|
||||
async logging() { return {} }
|
||||
},
|
||||
Mutation: {
|
||||
async logging() { return {} }
|
||||
},
|
||||
Subscription: {
|
||||
loggingLiveTrail: {
|
||||
subscribe: () => WIKI.GQLEmitter.asyncIterator('livetrail')
|
||||
}
|
||||
},
|
||||
LoggingQuery: {
|
||||
async loggers(obj, args, context, info) {
|
||||
let loggers = await WIKI.models.loggers.getLoggers()
|
||||
loggers = loggers.map(logger => {
|
||||
const loggerInfo = _.find(WIKI.data.loggers, ['key', logger.key]) || {}
|
||||
return {
|
||||
...loggerInfo,
|
||||
...logger,
|
||||
config: _.sortBy(_.transform(logger.config, (res, value, key) => {
|
||||
const configData = _.get(loggerInfo.props, key, {})
|
||||
res.push({
|
||||
key,
|
||||
value: JSON.stringify({
|
||||
...configData,
|
||||
value
|
||||
})
|
||||
})
|
||||
}, []), 'key')
|
||||
}
|
||||
})
|
||||
// if (args.filter) { loggers = graphHelper.filter(loggers, args.filter) }
|
||||
if (args.orderBy) { loggers = _.sortBy(loggers, [args.orderBy]) }
|
||||
return loggers
|
||||
}
|
||||
},
|
||||
LoggingMutation: {
|
||||
async updateLoggers(obj, args, context) {
|
||||
try {
|
||||
for (let logger of args.loggers) {
|
||||
await WIKI.models.loggers.query().patch({
|
||||
isEnabled: logger.isEnabled,
|
||||
level: logger.level,
|
||||
config: _.reduce(logger.config, (result, value, key) => {
|
||||
_.set(result, `${value.key}`, value.value)
|
||||
return result
|
||||
}, {})
|
||||
}).where('key', logger.key)
|
||||
}
|
||||
return {
|
||||
responseResult: graphHelper.generateSuccess('Loggers updated successfully')
|
||||
}
|
||||
} catch (err) {
|
||||
return graphHelper.generateError(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,5 +2,5 @@
|
||||
|
||||
scalar Date
|
||||
scalar JSON
|
||||
# scalar Upload
|
||||
scalar Upload
|
||||
scalar UUID
|
||||
|
||||
+7
-1
@@ -6,6 +6,12 @@
|
||||
const path = require('path')
|
||||
const { nanoid } = require('nanoid')
|
||||
const { DateTime } = require('luxon')
|
||||
const semver = require('semver')
|
||||
|
||||
if (!semver.satisfies(process.version, '>=16')) {
|
||||
console.error('ERROR: Node.js 16.x or later required!')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
let WIKI = {
|
||||
IS_DEBUG: process.env.NODE_ENV === 'development',
|
||||
@@ -26,7 +32,7 @@ WIKI.configSvc.init()
|
||||
// Init Logger
|
||||
// ----------------------------------------
|
||||
|
||||
WIKI.logger = require('./core/logger').init('MASTER')
|
||||
WIKI.logger = require('./core/logger').init()
|
||||
|
||||
// ----------------------------------------
|
||||
// Start Kernel
|
||||
|
||||
+1
-1
@@ -77,7 +77,7 @@ module.exports = async () => {
|
||||
|
||||
app.use(cookieParser())
|
||||
app.use(session({
|
||||
secret: WIKI.config.sessionSecret,
|
||||
secret: WIKI.config.system.sessionSecret,
|
||||
resave: false,
|
||||
saveUninitialized: false,
|
||||
store: new KnexSessionStore({
|
||||
|
||||
+13
-50
@@ -17,11 +17,12 @@ module.exports = class Analytics extends Model {
|
||||
static get jsonSchema () {
|
||||
return {
|
||||
type: 'object',
|
||||
required: ['key', 'isEnabled'],
|
||||
required: ['module', 'isEnabled'],
|
||||
|
||||
properties: {
|
||||
key: {type: 'string'},
|
||||
isEnabled: {type: 'boolean'}
|
||||
id: { type: 'string' },
|
||||
module: { type: 'string' },
|
||||
isEnabled: { type: 'boolean', default: false }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,65 +33,27 @@ module.exports = class Analytics extends Model {
|
||||
|
||||
static async getProviders(isEnabled) {
|
||||
const providers = await WIKI.models.analytics.query().where(_.isBoolean(isEnabled) ? { isEnabled } : {})
|
||||
return _.sortBy(providers, ['key'])
|
||||
return _.sortBy(providers, ['module'])
|
||||
}
|
||||
|
||||
static async refreshProvidersFromDisk() {
|
||||
let trx
|
||||
try {
|
||||
const dbProviders = await WIKI.models.analytics.query()
|
||||
|
||||
// -> Fetch definitions from disk
|
||||
const analyticsDirs = await fs.readdir(path.join(WIKI.SERVERPATH, 'modules/analytics'))
|
||||
let diskProviders = []
|
||||
for (let dir of analyticsDirs) {
|
||||
WIKI.data.analytics = []
|
||||
for (const dir of analyticsDirs) {
|
||||
const def = await fs.readFile(path.join(WIKI.SERVERPATH, 'modules/analytics', dir, 'definition.yml'), 'utf8')
|
||||
diskProviders.push(yaml.safeLoad(def))
|
||||
const defParsed = yaml.load(def)
|
||||
defParsed.key = dir
|
||||
defParsed.props = commonHelper.parseModuleProps(defParsed.props)
|
||||
WIKI.data.analytics.push(defParsed)
|
||||
WIKI.logger.debug(`Loaded analytics module definition ${dir}: [ OK ]`)
|
||||
}
|
||||
WIKI.data.analytics = diskProviders.map(provider => ({
|
||||
...provider,
|
||||
props: commonHelper.parseModuleProps(provider.props)
|
||||
}))
|
||||
|
||||
let newProviders = []
|
||||
for (let provider of WIKI.data.analytics) {
|
||||
if (!_.some(dbProviders, ['key', provider.key])) {
|
||||
newProviders.push({
|
||||
key: provider.key,
|
||||
isEnabled: false,
|
||||
config: _.transform(provider.props, (result, value, key) => {
|
||||
_.set(result, key, value.default)
|
||||
return result
|
||||
}, {})
|
||||
})
|
||||
} else {
|
||||
const providerConfig = _.get(_.find(dbProviders, ['key', provider.key]), 'config', {})
|
||||
await WIKI.models.analytics.query().patch({
|
||||
config: _.transform(provider.props, (result, value, key) => {
|
||||
if (!_.has(result, key)) {
|
||||
_.set(result, key, value.default)
|
||||
}
|
||||
return result
|
||||
}, providerConfig)
|
||||
}).where('key', provider.key)
|
||||
}
|
||||
}
|
||||
if (newProviders.length > 0) {
|
||||
trx = await WIKI.models.Objection.transaction.start(WIKI.models.knex)
|
||||
for (let provider of newProviders) {
|
||||
await WIKI.models.analytics.query(trx).insert(provider)
|
||||
}
|
||||
await trx.commit()
|
||||
WIKI.logger.info(`Loaded ${newProviders.length} new analytics providers: [ OK ]`)
|
||||
} else {
|
||||
WIKI.logger.info(`No new analytics providers found: [ SKIPPED ]`)
|
||||
}
|
||||
WIKI.logger.info(`Loaded ${WIKI.data.analytics.length} analytics module definitions: [ OK ]`)
|
||||
} catch (err) {
|
||||
WIKI.logger.error(`Failed to scan or load new analytics providers: [ FAILED ]`)
|
||||
WIKI.logger.error(err)
|
||||
if (trx) {
|
||||
trx.rollback()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,113 +0,0 @@
|
||||
const Model = require('objection').Model
|
||||
const path = require('path')
|
||||
const fs = require('fs-extra')
|
||||
const _ = require('lodash')
|
||||
const yaml = require('js-yaml')
|
||||
const commonHelper = require('../helpers/common')
|
||||
|
||||
/* global WIKI */
|
||||
|
||||
/**
|
||||
* Logger model
|
||||
*/
|
||||
module.exports = class Logger extends Model {
|
||||
static get tableName() { return 'loggers' }
|
||||
static get idColumn() { return 'key' }
|
||||
|
||||
static get jsonSchema () {
|
||||
return {
|
||||
type: 'object',
|
||||
required: ['key', 'isEnabled'],
|
||||
|
||||
properties: {
|
||||
key: {type: 'string'},
|
||||
isEnabled: {type: 'boolean'},
|
||||
level: {type: 'string'}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static get jsonAttributes() {
|
||||
return ['config']
|
||||
}
|
||||
|
||||
static async getLoggers() {
|
||||
return WIKI.models.loggers.query()
|
||||
}
|
||||
|
||||
static async refreshLoggersFromDisk() {
|
||||
let trx
|
||||
try {
|
||||
const dbLoggers = await WIKI.models.loggers.query()
|
||||
|
||||
// -> Fetch definitions from disk
|
||||
const loggersDirs = await fs.readdir(path.join(WIKI.SERVERPATH, 'modules/logging'))
|
||||
let diskLoggers = []
|
||||
for (let dir of loggersDirs) {
|
||||
const def = await fs.readFile(path.join(WIKI.SERVERPATH, 'modules/logging', dir, 'definition.yml'), 'utf8')
|
||||
diskLoggers.push(yaml.safeLoad(def))
|
||||
}
|
||||
WIKI.data.loggers = diskLoggers.map(logger => ({
|
||||
...logger,
|
||||
props: commonHelper.parseModuleProps(logger.props)
|
||||
}))
|
||||
|
||||
// -> Insert new loggers
|
||||
let newLoggers = []
|
||||
for (let logger of WIKI.data.loggers) {
|
||||
if (!_.some(dbLoggers, ['key', logger.key])) {
|
||||
newLoggers.push({
|
||||
key: logger.key,
|
||||
isEnabled: (logger.key === 'console'),
|
||||
level: logger.defaultLevel,
|
||||
config: _.transform(logger.props, (result, value, key) => {
|
||||
_.set(result, key, value.default)
|
||||
return result
|
||||
}, {})
|
||||
})
|
||||
} else {
|
||||
const loggerConfig = _.get(_.find(dbLoggers, ['key', logger.key]), 'config', {})
|
||||
await WIKI.models.loggers.query().patch({
|
||||
config: _.transform(logger.props, (result, value, key) => {
|
||||
if (!_.has(result, key)) {
|
||||
_.set(result, key, value.default)
|
||||
}
|
||||
return result
|
||||
}, loggerConfig)
|
||||
}).where('key', logger.key)
|
||||
}
|
||||
}
|
||||
if (newLoggers.length > 0) {
|
||||
trx = await WIKI.models.Objection.transaction.start(WIKI.models.knex)
|
||||
for (let logger of newLoggers) {
|
||||
await WIKI.models.loggers.query(trx).insert(logger)
|
||||
}
|
||||
await trx.commit()
|
||||
WIKI.logger.info(`Loaded ${newLoggers.length} new loggers: [ OK ]`)
|
||||
} else {
|
||||
WIKI.logger.info(`No new loggers found: [ SKIPPED ]`)
|
||||
}
|
||||
} catch (err) {
|
||||
WIKI.logger.error(`Failed to scan or load new loggers: [ FAILED ]`)
|
||||
WIKI.logger.error(err)
|
||||
if (trx) {
|
||||
trx.rollback()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static async pageEvent({ event, page }) {
|
||||
const loggers = await WIKI.models.storage.query().where('isEnabled', true)
|
||||
if (loggers && loggers.length > 0) {
|
||||
_.forEach(loggers, logger => {
|
||||
WIKI.queue.job.syncStorage.add({
|
||||
event,
|
||||
logger,
|
||||
page
|
||||
}, {
|
||||
removeOnComplete: true
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
const Model = require('objection').Model
|
||||
const path = require('path')
|
||||
const fs = require('fs-extra')
|
||||
const _ = require('lodash')
|
||||
const yaml = require('js-yaml')
|
||||
const commonHelper = require('../helpers/common')
|
||||
|
||||
/* global WIKI */
|
||||
|
||||
/**
|
||||
* SearchEngine model
|
||||
*/
|
||||
module.exports = class SearchEngine extends Model {
|
||||
static get tableName() { return 'searchEngines' }
|
||||
static get idColumn() { return 'key' }
|
||||
|
||||
static get jsonSchema () {
|
||||
return {
|
||||
type: 'object',
|
||||
required: ['key', 'isEnabled'],
|
||||
|
||||
properties: {
|
||||
key: {type: 'string'},
|
||||
isEnabled: {type: 'boolean'},
|
||||
level: {type: 'string'}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static get jsonAttributes() {
|
||||
return ['config']
|
||||
}
|
||||
|
||||
static async getSearchEngines() {
|
||||
return WIKI.models.searchEngines.query()
|
||||
}
|
||||
|
||||
static async refreshSearchEnginesFromDisk() {
|
||||
let trx
|
||||
try {
|
||||
const dbSearchEngines = await WIKI.models.searchEngines.query()
|
||||
|
||||
// -> Fetch definitions from disk
|
||||
const searchEnginesDirs = await fs.readdir(path.join(WIKI.SERVERPATH, 'modules/search'))
|
||||
let diskSearchEngines = []
|
||||
for (let dir of searchEnginesDirs) {
|
||||
const def = await fs.readFile(path.join(WIKI.SERVERPATH, 'modules/search', dir, 'definition.yml'), 'utf8')
|
||||
diskSearchEngines.push(yaml.safeLoad(def))
|
||||
}
|
||||
WIKI.data.searchEngines = diskSearchEngines.map(searchEngine => ({
|
||||
...searchEngine,
|
||||
props: commonHelper.parseModuleProps(searchEngine.props)
|
||||
}))
|
||||
|
||||
// -> Insert new searchEngines
|
||||
let newSearchEngines = []
|
||||
for (let searchEngine of WIKI.data.searchEngines) {
|
||||
if (!_.some(dbSearchEngines, ['key', searchEngine.key])) {
|
||||
newSearchEngines.push({
|
||||
key: searchEngine.key,
|
||||
isEnabled: false,
|
||||
config: _.transform(searchEngine.props, (result, value, key) => {
|
||||
_.set(result, key, value.default)
|
||||
return result
|
||||
}, {})
|
||||
})
|
||||
} else {
|
||||
const searchEngineConfig = _.get(_.find(dbSearchEngines, ['key', searchEngine.key]), 'config', {})
|
||||
await WIKI.models.searchEngines.query().patch({
|
||||
config: _.transform(searchEngine.props, (result, value, key) => {
|
||||
if (!_.has(result, key)) {
|
||||
_.set(result, key, value.default)
|
||||
}
|
||||
return result
|
||||
}, searchEngineConfig)
|
||||
}).where('key', searchEngine.key)
|
||||
}
|
||||
}
|
||||
if (newSearchEngines.length > 0) {
|
||||
trx = await WIKI.models.Objection.transaction.start(WIKI.models.knex)
|
||||
for (let searchEngine of newSearchEngines) {
|
||||
await WIKI.models.searchEngines.query(trx).insert(searchEngine)
|
||||
}
|
||||
await trx.commit()
|
||||
WIKI.logger.info(`Loaded ${newSearchEngines.length} new search engines: [ OK ]`)
|
||||
} else {
|
||||
WIKI.logger.info(`No new search engines found: [ SKIPPED ]`)
|
||||
}
|
||||
} catch (err) {
|
||||
WIKI.logger.error(`Failed to scan or load new search engines: [ FAILED ]`)
|
||||
WIKI.logger.error(err)
|
||||
if (trx) {
|
||||
trx.rollback()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static async initEngine({ activate = false } = {}) {
|
||||
const searchEngine = await WIKI.models.searchEngines.query().findOne('isEnabled', true)
|
||||
if (searchEngine) {
|
||||
WIKI.data.searchEngine = require(`../modules/search/${searchEngine.key}/engine`)
|
||||
WIKI.data.searchEngine.key = searchEngine.key
|
||||
WIKI.data.searchEngine.config = searchEngine.config
|
||||
if (activate) {
|
||||
try {
|
||||
await WIKI.data.searchEngine.activate()
|
||||
} catch (err) {
|
||||
// -> Revert to basic engine
|
||||
if (err instanceof WIKI.Error.SearchActivationFailed) {
|
||||
await WIKI.models.searchEngines.query().patch({ isEnabled: false }).where('key', searchEngine.key)
|
||||
await WIKI.models.searchEngines.query().patch({ isEnabled: true }).where('key', 'db')
|
||||
await WIKI.models.searchEngines.initEngine()
|
||||
}
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
await WIKI.data.searchEngine.init()
|
||||
} catch (err) {
|
||||
WIKI.logger.warn(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,7 @@ module.exports = configure(function (/* ctx */) {
|
||||
// https://v2.quasar.dev/quasar-cli/boot-files
|
||||
boot: [
|
||||
'apollo',
|
||||
'components',
|
||||
'i18n'
|
||||
],
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import { boot } from 'quasar/wrappers'
|
||||
|
||||
import BlueprintIcon from '../components/BlueprintIcon.vue'
|
||||
|
||||
export default boot(({ app }) => {
|
||||
app.component('BlueprintIcon', BlueprintIcon)
|
||||
})
|
||||
@@ -98,6 +98,17 @@ body::-webkit-scrollbar-thumb {
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ICONS SIZE FIX
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
.q-btn .q-icon {
|
||||
&.fa-solid,
|
||||
&.fa-regular {
|
||||
font-size: 1.3em;
|
||||
}
|
||||
}
|
||||
|
||||
.q-select__dropdown-icon {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,11 @@ q-layout.admin(view='hHh Lpr lff')
|
||||
q-toolbar-title.text-h6.font-poppins Wiki.js
|
||||
q-toolbar.gt-sm.justify-center(style='height: 64px;', dark)
|
||||
.text-overline.text-uppercase.text-grey {{t('admin.adminArea')}}
|
||||
q-badge.q-ml-sm(
|
||||
label='v3 Preview'
|
||||
color='pink'
|
||||
outline
|
||||
)
|
||||
q-toolbar(style='height: 64px;', dark)
|
||||
q-space
|
||||
q-spinner-tail(
|
||||
|
||||
@@ -4,8 +4,8 @@ q-page.admin-flags
|
||||
.col-auto
|
||||
img.admin-icon.animated.fadeInLeft(src='/_assets/icons/fluent-cashbook.svg')
|
||||
.col.q-pl-md
|
||||
.text-h5.text-primary.animated.fadeInLeft {{ $t('admin.editors.title') }}
|
||||
.text-subtitle1.text-grey.animated.fadeInLeft.wait-p2s {{ $t('admin.editors.subtitle') }}
|
||||
.text-h5.text-primary.animated.fadeInLeft {{ t('admin.editors.title') }}
|
||||
.text-subtitle1.text-grey.animated.fadeInLeft.wait-p2s {{ t('admin.editors.subtitle') }}
|
||||
.col-auto
|
||||
q-btn.q-mr-sm.acrylic-btn(
|
||||
icon='las la-question-circle'
|
||||
@@ -16,7 +16,7 @@ q-page.admin-flags
|
||||
type='a'
|
||||
)
|
||||
q-btn.q-mr-sm.acrylic-btn(
|
||||
icon='las la-redo-alt'
|
||||
icon='fa-solid fa-rotate'
|
||||
flat
|
||||
color='secondary'
|
||||
:loading='loading > 0'
|
||||
@@ -24,8 +24,8 @@ q-page.admin-flags
|
||||
)
|
||||
q-btn(
|
||||
unelevated
|
||||
icon='mdi-check'
|
||||
:label='$t(`common.actions.apply`)'
|
||||
icon='fa-solid fa-check'
|
||||
:label='t(`common.actions.apply`)'
|
||||
color='secondary'
|
||||
@click='save'
|
||||
:disabled='loading > 0'
|
||||
@@ -37,16 +37,16 @@ q-page.admin-flags
|
||||
q-item(v-for='editor of editors', :key='editor.id')
|
||||
blueprint-icon(:icon='editor.icon')
|
||||
q-item-section
|
||||
q-item-label: strong {{$t(`admin.editors.` + editor.id + `Name`)}}
|
||||
q-item-label: strong {{t(`admin.editors.` + editor.id + `Name`)}}
|
||||
q-item-label.flex.items-center(caption)
|
||||
span {{$t(`admin.editors.` + editor.id + `Description`)}}
|
||||
span {{t(`admin.editors.` + editor.id + `Description`)}}
|
||||
template(v-if='editor.config')
|
||||
q-item-section(
|
||||
side
|
||||
)
|
||||
q-btn(
|
||||
icon='las la-cog'
|
||||
:label='$t(`admin.editors.configuration`)'
|
||||
:label='t(`admin.editors.configuration`)'
|
||||
:color='$q.dark.isActive ? `blue-grey-3` : `blue-grey-8`'
|
||||
outline
|
||||
no-caps
|
||||
@@ -59,69 +59,67 @@ q-page.admin-flags
|
||||
:color='editor.isDisabled ? `grey` : `primary`'
|
||||
checked-icon='las la-check'
|
||||
unchecked-icon='las la-times'
|
||||
:label='$t(`admin.sites.isActive`)'
|
||||
:aria-label='$t(`admin.sites.isActive`)'
|
||||
:label='t(`admin.sites.isActive`)'
|
||||
:aria-label='t(`admin.sites.isActive`)'
|
||||
:disabled='editor.isDisabled'
|
||||
)
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { createMetaMixin } from 'quasar'
|
||||
<script setup>
|
||||
import { useMeta } from 'quasar'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { defineAsyncComponent, onMounted, reactive, ref, watch } from 'vue'
|
||||
|
||||
export default {
|
||||
mixins: [
|
||||
createMetaMixin(function () {
|
||||
return {
|
||||
title: this.$t('admin.editors.title')
|
||||
}
|
||||
})
|
||||
],
|
||||
data () {
|
||||
return {
|
||||
loading: false,
|
||||
editors: [
|
||||
{
|
||||
id: 'wysiwyg',
|
||||
icon: 'google-presentation',
|
||||
isActive: true
|
||||
},
|
||||
{
|
||||
id: 'markdown',
|
||||
icon: 'markdown',
|
||||
config: {},
|
||||
isActive: true
|
||||
},
|
||||
{
|
||||
id: 'channel',
|
||||
icon: 'chat',
|
||||
isActive: true
|
||||
},
|
||||
{
|
||||
id: 'blog',
|
||||
icon: 'typewriter-with-paper',
|
||||
isActive: true,
|
||||
isDisabled: true
|
||||
},
|
||||
{
|
||||
id: 'api',
|
||||
icon: 'api',
|
||||
isActive: true,
|
||||
isDisabled: true
|
||||
},
|
||||
{
|
||||
id: 'redirect',
|
||||
icon: 'advance',
|
||||
isActive: true
|
||||
}
|
||||
]
|
||||
}
|
||||
// STORES / ROUTERS / i18n
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
// META
|
||||
|
||||
useMeta({
|
||||
title: t('admin.editors.title')
|
||||
})
|
||||
|
||||
const loading = ref(false)
|
||||
const editors = reactive([
|
||||
{
|
||||
id: 'wysiwyg',
|
||||
icon: 'google-presentation',
|
||||
isActive: true
|
||||
},
|
||||
methods: {
|
||||
async load () {},
|
||||
save () {},
|
||||
refresh () {}
|
||||
{
|
||||
id: 'markdown',
|
||||
icon: 'markdown',
|
||||
config: {},
|
||||
isActive: true
|
||||
},
|
||||
{
|
||||
id: 'channel',
|
||||
icon: 'chat',
|
||||
isActive: true
|
||||
},
|
||||
{
|
||||
id: 'blog',
|
||||
icon: 'typewriter-with-paper',
|
||||
isActive: true,
|
||||
isDisabled: true
|
||||
},
|
||||
{
|
||||
id: 'api',
|
||||
icon: 'api',
|
||||
isActive: true,
|
||||
isDisabled: true
|
||||
},
|
||||
{
|
||||
id: 'redirect',
|
||||
icon: 'advance',
|
||||
isActive: true
|
||||
}
|
||||
}
|
||||
])
|
||||
|
||||
const load = async () => {}
|
||||
const save = () => {}
|
||||
const refresh = () => {}
|
||||
</script>
|
||||
|
||||
<style lang='scss'>
|
||||
|
||||
+89
-85
@@ -4,8 +4,8 @@ q-page.admin-flags
|
||||
.col-auto
|
||||
img.admin-icon.animated.fadeInLeft(src='/_assets/icons/fluent-windsock.svg')
|
||||
.col.q-pl-md
|
||||
.text-h5.text-primary.animated.fadeInLeft {{ $t('admin.flags.title') }}
|
||||
.text-subtitle1.text-grey.animated.fadeInLeft.wait-p2s {{ $t('admin.flags.subtitle') }}
|
||||
.text-h5.text-primary.animated.fadeInLeft {{ t('admin.flags.title') }}
|
||||
.text-subtitle1.text-grey.animated.fadeInLeft.wait-p2s {{ t('admin.flags.subtitle') }}
|
||||
.col-auto
|
||||
q-btn.q-mr-sm.acrylic-btn(
|
||||
icon='las la-question-circle'
|
||||
@@ -17,8 +17,8 @@ q-page.admin-flags
|
||||
)
|
||||
q-btn(
|
||||
unelevated
|
||||
icon='mdi-check'
|
||||
:label='$t(`common.actions.apply`)'
|
||||
icon='fa-solid fa-check'
|
||||
:label='t(`common.actions.apply`)'
|
||||
color='secondary'
|
||||
@click='save'
|
||||
:loading='loading'
|
||||
@@ -34,125 +34,129 @@ q-page.admin-flags
|
||||
q-card-section.col-auto.q-pr-none
|
||||
q-icon(name='las la-exclamation-triangle', size='sm')
|
||||
q-card-section
|
||||
span {{ $t('admin.flags.warn.label') }}
|
||||
.text-caption.text-red-1 {{ $t('admin.flags.warn.hint') }}
|
||||
span {{ t('admin.flags.warn.label') }}
|
||||
.text-caption.text-red-1 {{ t('admin.flags.warn.hint') }}
|
||||
q-item(tag='label', v-ripple)
|
||||
blueprint-icon(icon='flag-filled')
|
||||
q-item-section
|
||||
q-item-label {{$t(`admin.flags.ldapdebug.label`)}}
|
||||
q-item-label(caption) {{$t(`admin.flags.ldapdebug.hint`)}}
|
||||
q-item-label {{t(`admin.flags.ldapdebug.label`)}}
|
||||
q-item-label(caption) {{t(`admin.flags.ldapdebug.hint`)}}
|
||||
q-item-section(avatar)
|
||||
q-toggle(
|
||||
v-model='flags.ldapdebug'
|
||||
color='primary'
|
||||
checked-icon='las la-check'
|
||||
unchecked-icon='las la-times'
|
||||
:aria-label='$t(`admin.flags.ldapdebug.label`)'
|
||||
:aria-label='t(`admin.flags.ldapdebug.label`)'
|
||||
)
|
||||
q-separator.q-my-sm(inset)
|
||||
q-item(tag='label', v-ripple)
|
||||
blueprint-icon(icon='flag-filled')
|
||||
q-item-section
|
||||
q-item-label {{$t(`admin.flags.sqllog.label`)}}
|
||||
q-item-label(caption) {{$t(`admin.flags.sqllog.hint`)}}
|
||||
q-item-label {{t(`admin.flags.sqllog.label`)}}
|
||||
q-item-label(caption) {{t(`admin.flags.sqllog.hint`)}}
|
||||
q-item-section(avatar)
|
||||
q-toggle(
|
||||
v-model='flags.sqllog'
|
||||
color='primary'
|
||||
checked-icon='las la-check'
|
||||
unchecked-icon='las la-times'
|
||||
:aria-label='$t(`admin.flags.sqllog.label`)'
|
||||
:aria-label='t(`admin.flags.sqllog.label`)'
|
||||
)
|
||||
q-card.shadow-1.q-py-sm.q-mt-md
|
||||
q-item(tag='label', v-ripple)
|
||||
blueprint-icon(icon='heart-outline')
|
||||
q-item-section
|
||||
q-item-label {{$t(`admin.flags.hidedonatebtn.label`)}}
|
||||
q-item-label(caption) {{$t(`admin.flags.hidedonatebtn.hint`)}}
|
||||
q-item-label {{t(`admin.flags.hidedonatebtn.label`)}}
|
||||
q-item-label(caption) {{t(`admin.flags.hidedonatebtn.hint`)}}
|
||||
q-item-section(avatar)
|
||||
q-toggle(
|
||||
v-model='flags.hidedonatebtn'
|
||||
color='primary'
|
||||
checked-icon='las la-check'
|
||||
unchecked-icon='las la-times'
|
||||
:aria-label='$t(`admin.flags.hidedonatebtn.label`)'
|
||||
:aria-label='t(`admin.flags.hidedonatebtn.label`)'
|
||||
)
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import gql from 'graphql-tag'
|
||||
import { defineAsyncComponent, onMounted, reactive, ref, watch } from 'vue'
|
||||
import _transform from 'lodash/transform'
|
||||
import { createMetaMixin } from 'quasar'
|
||||
import { useMeta } from 'quasar'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
// STORES / ROUTERS / i18n
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
// META
|
||||
|
||||
useMeta({
|
||||
title: t('admin.flags.title')
|
||||
})
|
||||
|
||||
const loading = ref(false)
|
||||
const flags = reactive({
|
||||
ldapdebug: false,
|
||||
sqllog: false,
|
||||
hidedonatebtn: false
|
||||
})
|
||||
|
||||
const save = async () => {
|
||||
|
||||
export default {
|
||||
mixins: [
|
||||
createMetaMixin(function () {
|
||||
return {
|
||||
title: this.$t('admin.flags.title')
|
||||
}
|
||||
})
|
||||
],
|
||||
data () {
|
||||
return {
|
||||
loading: false,
|
||||
flags: {
|
||||
ldapdebug: false,
|
||||
sqllog: false,
|
||||
hidedonatebtn: false
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async save () {
|
||||
try {
|
||||
await this.$apollo.mutate({
|
||||
mutation: gql`
|
||||
mutation updateFlags (
|
||||
$flags: [SystemFlagInput]!
|
||||
) {
|
||||
updateSystemFlags(
|
||||
flags: $flags
|
||||
) {
|
||||
status {
|
||||
succeeded
|
||||
slug
|
||||
message
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
variables: {
|
||||
flags: _transform(this.flags, (result, value, key) => {
|
||||
result.push({ key, value })
|
||||
}, [])
|
||||
},
|
||||
watchLoading (isLoading) {
|
||||
this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-flags-update')
|
||||
}
|
||||
})
|
||||
this.$store.commit('showNotification', {
|
||||
style: 'success',
|
||||
message: 'Flags applied successfully.',
|
||||
icon: 'check'
|
||||
})
|
||||
} catch (err) {
|
||||
this.$store.commit('pushGraphError', err)
|
||||
}
|
||||
}
|
||||
}
|
||||
// apollo: {
|
||||
// flags: {
|
||||
// query: gql``,
|
||||
// fetchPolicy: 'network-only',
|
||||
// update: (data) => _transform(data.system.flags, (result, row) => {
|
||||
// _set(result, row.key, row.value)
|
||||
// }, {}),
|
||||
// watchLoading (isLoading) {
|
||||
// this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-flags-refresh')
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
// methods: {
|
||||
// async save () {
|
||||
// try {
|
||||
// await this.$apollo.mutate({
|
||||
// mutation: gql`
|
||||
// mutation updateFlags (
|
||||
// $flags: [SystemFlagInput]!
|
||||
// ) {
|
||||
// updateSystemFlags(
|
||||
// flags: $flags
|
||||
// ) {
|
||||
// status {
|
||||
// succeeded
|
||||
// slug
|
||||
// message
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// `,
|
||||
// variables: {
|
||||
// flags: _transform(this.flags, (result, value, key) => {
|
||||
// result.push({ key, value })
|
||||
// }, [])
|
||||
// },
|
||||
// watchLoading (isLoading) {
|
||||
// this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-flags-update')
|
||||
// }
|
||||
// })
|
||||
// this.$store.commit('showNotification', {
|
||||
// style: 'success',
|
||||
// message: 'Flags applied successfully.',
|
||||
// icon: 'check'
|
||||
// })
|
||||
// } catch (err) {
|
||||
// this.$store.commit('pushGraphError', err)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// apollo: {
|
||||
// flags: {
|
||||
// query: gql``,
|
||||
// fetchPolicy: 'network-only',
|
||||
// update: (data) => _transform(data.system.flags, (result, row) => {
|
||||
// _set(result, row.key, row.value)
|
||||
// }, {}),
|
||||
// watchLoading (isLoading) {
|
||||
// this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-flags-refresh')
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
</script>
|
||||
|
||||
<style lang='scss'>
|
||||
|
||||
@@ -28,11 +28,11 @@ const routes = [
|
||||
component: () => import('../layouts/AdminLayout.vue'),
|
||||
children: [
|
||||
{ path: '', redirect: '/_admin/dashboard' },
|
||||
{ path: 'dashboard', component: () => import('../pages/AdminDashboard.vue') }
|
||||
{ path: 'dashboard', component: () => import('../pages/AdminDashboard.vue') },
|
||||
// { path: 'sites', component: () => import('../pages/AdminSites.vue') },
|
||||
// // -> Site
|
||||
// { path: ':siteid/general', component: () => import('../pages/AdminGeneral.vue') },
|
||||
// { path: ':siteid/editors', component: () => import('../pages/AdminEditors.vue') },
|
||||
{ path: ':siteid/editors', component: () => import('../pages/AdminEditors.vue') },
|
||||
// { path: ':siteid/locale', component: () => import('../pages/AdminLocale.vue') },
|
||||
// { path: ':siteid/login', component: () => import('../pages/AdminLogin.vue') },
|
||||
// { path: ':siteid/navigation', component: () => import('../pages/AdminNavigation.vue') },
|
||||
@@ -51,7 +51,7 @@ const routes = [
|
||||
// { path: 'system', component: () => import('../pages/AdminSystem.vue') },
|
||||
// { path: 'utilities', component: () => import('../pages/AdminUtilities.vue') },
|
||||
// { path: 'webhooks', component: () => import('../pages/AdminWebhooks.vue') },
|
||||
// { path: 'flags', component: () => import('../pages/AdminFlags.vue') }
|
||||
{ path: 'flags', component: () => import('../pages/AdminFlags.vue') }
|
||||
]
|
||||
},
|
||||
// {
|
||||
|
||||
Reference in New Issue
Block a user