diff options
| author | Zephyrrus <[email protected]> | 2021-01-11 12:51:45 +0200 |
|---|---|---|
| committer | Zephyrrus <[email protected]> | 2021-01-11 12:51:45 +0200 |
| commit | d69fcd856a47b04f964c658edfa2bed3e6f0abc1 (patch) | |
| tree | d8e578a2c4ca5969b5f24a6256fae95ae84ba9ef | |
| parent | feat: add dynamic settings page rendering based on the Joi object (diff) | |
| download | host.fuwn.me-d69fcd856a47b04f964c658edfa2bed3e6f0abc1.tar.xz host.fuwn.me-d69fcd856a47b04f964c658edfa2bed3e6f0abc1.zip | |
feat: add sections to settings object meta
| -rw-r--r-- | src/api/structures/Setting.js | 75 | ||||
| -rw-r--r-- | src/site/components/settings/JoiObject.vue | 3 | ||||
| -rw-r--r-- | src/site/pages/dashboard/admin/settings.vue | 28 |
3 files changed, 98 insertions, 8 deletions
diff --git a/src/api/structures/Setting.js b/src/api/structures/Setting.js index 7b2041d..ff98339 100644 --- a/src/api/structures/Setting.js +++ b/src/api/structures/Setting.js @@ -5,65 +5,113 @@ const { env } = process; const StatsGenerator = require('../utils/StatsGenerator'); +const Sections = Object.freeze({ + SERVICE: 'Service', + FILE: 'File', + USERS: 'Users', + SOCIAL_AND_SHARING: 'Social and sharing', + INSTANCE: 'Instance', + STATISTICS: 'Statistics', + SERVER: 'Server', + OTHER: 'Other' +}); + // use label to name them nicely // use meta to set custom rendering (render as radio instead of dropdown for example) and custom order // use description to add comments which will show up as a note somewhere next to the option const schema = Joi.object({ // Service settings serviceName: Joi.string().default('change-me') + // .meta({ section }) + .meta({ + section: Sections.SERVICE + }) .label('Service name') .description('Name of the service'), domain: Joi.string().default(`http://localhost:${env.SERVER_PORT}`) + .meta({ + section: Sections.SERVICE + }) .label('Domain') .description('Full domain this instance is gonna be running on'), // File related settings chunkSize: Joi.number().integer().greater(0) .default(90) + .meta({ + section: Sections.FILE + }) .label('Chunk size') .description('Maximum size of a chunk (files bigger than this limit will be split into multiple chunks)'), maxSize: Joi.number().integer().min(0) // setting it to 0 disabled the limit .default(5000) + .meta({ + section: Sections.FILE + }) .label('Maximum file size') .description('Maximum allowed upload file size in MB (0 to disable)'), generateZips: Joi.boolean().default(true) + .meta({ + section: Sections.FILE + }) .label('Generate zips') .description('Allows users to download entire albums in ZIP format'), generatedFileNameLength: Joi.number().integer().min(6) .default(12) + .meta({ + section: Sections.FILE + }) .label('Generated file name length') .description('How long should the automatically generated file name be'), generatedAlbumLength: Joi.number().integer().min(6) .default(6) + .meta({ + section: Sections.FILE + }) .label('Generated album name length') .description('How long should the automatically generated album identifier be'), maxLinksPerAlbum: Joi.number().integer().greater(0) .default(5) + .meta({ + section: Sections.FILE + }) .label('Maximum album links') .description('Maximum allowed number of a distinct links for an album'), uploadsFolder: Joi.string().default('uploads') + .meta({ + section: Sections.FILE + }) .label('Uploads folder') .description('Name of the folder where the uploads will be stored'), blockedExtensions: Joi.array() .items(Joi.string().pattern(/^(\.\w+)+$/, { name: 'file extension' })) .default(['.jar', '.exe', '.msi', '.com', '.bat', '.cmd', '.scr', '.ps1', '.sh']) + .meta({ + section: Sections.FILE + }) .label('Blocked extensions') .description('List of extensions which will be rejected by the server'), // User settings publicMode: Joi.boolean().default(true) + .meta({ + section: Sections.USERS + }) .label('Public mode') .description('Allows people to upload files without an account'), userAccount: Joi.boolean().default(true) + .meta({ + section: Sections.USERS + }) .label('User creation') .description('Allows people to create new accounts'), @@ -71,53 +119,76 @@ const schema = Joi.object({ metaThemeColor: Joi.string().hex().min(3) .max(6) .default('20222b') + .meta({ + section: Sections.SOCIAL_AND_SHARING + }) .label('Meta theme color') .description('Color that user agents should use to customize the display of the page/embeds'), metaDescription: Joi.string().default('Blazing fast file uploader and bunker written in node! 🚀') + .meta({ + section: Sections.SOCIAL_AND_SHARING + }) .label('Meta description') .description('Short and accurate summary of the content of the page'), metaKeyword: Joi.string().default('chibisafe,lolisafe,upload,uploader,file,vue,images,ssr,file uploader,free') + .meta({ + section: Sections.SOCIAL_AND_SHARING + }) .label('Meta keywords') .description('Words relevant to the page\'s content separated by commas'), metaTwitterHandle: Joi.string().pattern(/^@\w{1,15}$/, { name: 'twitter handle' }) + .meta({ + section: Sections.SOCIAL_AND_SHARING + }) .label('Twitter handle') .description('Your twitter handle'), // Instance settings backgroundImageURL: Joi.string().uri().default(p => `${p.domain}/assets/images/background.jpg`) + .meta({ + section: Sections.INSTANCE + }) .label('Background image link') .description('Background image that should be used instead of the default background'), logoURL: Joi.string().uri().default(p => `${p.domain}/assets/images/logo.jpg`) + .meta({ + section: Sections.INSTANCE + }) .label('Logo image link') .description('Logo image that should be used instead of the default logo'), // Statistics settings // TODO: Pattern fails for patterns like 0 1,2-7 * * * * because of the mixing of lists and ranges statisticsCron: Joi.string().pattern(/((((\d+,)+\d+|([\d\*]+(\/|-)\d+)|\d+|\*) ?){6})/, { name: 'cron' }).default('0 0 * * * *') + .meta({ + section: Sections.STATISTICS + }) .label('Statistics schedule') .description('Crontab like formated value which will be used to schedule generating and saving stats to the database'), enabledStatistics: Joi.array().items(Joi.string().valid(...Object.keys(StatsGenerator.statGenerators)).optional()) - .meta({ displayType: 'checkbox' }) + .meta({ section: Sections.STATISTICS, displayType: 'checkbox' }) .label('Enabled statistics') .description('Which statistics should be shown when opening the statistics page'), savedStatistics: Joi.array().items(Joi.string().valid(...Object.keys(StatsGenerator.statGenerators)).optional()) - .meta({ displayType: 'checkbox' }) + .meta({ section: Sections.STATISTICS, displayType: 'checkbox' }) .label('Cached statistics') .description('Which statistics should be saved to the database (refer to Statistics schedule for scheduling).') .note('If a statistics is enabled but not set to be saved, it will be generated every time the statistics page is opened'), // Server related settings rateLimitWindow: Joi.number().integer().default(2) + .meta({ section: Sections.SERVER }) .label('API rate limit window') .description('Timeframe for which requests are checked/remembered'), rateLimitMax: Joi.number().integer().default(5) + .meta({ section: Sections.SERVER }) .label('API maximum limit') .description('Max number of connections during windowMs milliseconds before sending a 429 response') }); diff --git a/src/site/components/settings/JoiObject.vue b/src/site/components/settings/JoiObject.vue index e842792..c91fd36 100644 --- a/src/site/components/settings/JoiObject.vue +++ b/src/site/components/settings/JoiObject.vue @@ -25,6 +25,7 @@ :rounded="false" :true-value="true" :false-value="false" /> + <!-- TODO: If array and has allowed items, limit input to those items only --> <b-taginput v-else-if="getDisplayType(field) === 'array' || getDisplayType(field) === 'tagInput'" v-model="settings.arr" @@ -76,7 +77,7 @@ export default { }; }, mounted() { - // TODO: Implement merging fields with values from the db (no endpoint to fetch settings yet) + }, methods: { getMin(field) { diff --git a/src/site/pages/dashboard/admin/settings.vue b/src/site/pages/dashboard/admin/settings.vue index bac9683..5a28dda 100644 --- a/src/site/pages/dashboard/admin/settings.vue +++ b/src/site/pages/dashboard/admin/settings.vue @@ -11,7 +11,8 @@ </h2> <hr> - <JoiObject :keys="settingsSchema.keys" :values="{}" /> + <!-- TODO: IMPLEMENT SECTIONS (v-for JoiObject for each section maybe?) --> + <JoiObject :keys="sectionedSettings" :values="{}" /> </div> </div> </div> @@ -31,16 +32,33 @@ export default { middleware: ['auth', 'admin', ({ store }) => { try { store.dispatch('admin/fetchSettings'); + // TODO: Implement merging fields with values from the db (no endpoint to fetch settings yet) store.dispatch('admin/getSettingsSchema'); } catch (e) { // eslint-disable-next-line no-console console.error(e); } }], - computed: mapState({ - settings: state => state.admin.settings, - settingsSchema: state => state.admin.settingsSchema - }), + computed: { + ...mapState({ + settings: state => state.admin.settings, + settingsSchema: state => state.admin.settingsSchema + }), + sectionedSettings() { + return Object.entries(this.settings).reduce((acc, { key, field }) => { + if (!field.meta) acc['Other'] = { ...acc['Other'], [key]: field }; + + const { sectionName } = field.metas.find(e => e.sectionName); + if (sectionName) { + acc[sectionName] = { ...acc[sectionName], [key]: field }; + } else { + acc['Other'] = { ...acc['Other'], [key]: field }; + } + + return acc; + }, {}); + } + }, methods: { promptRestartService() { this.$buefy.dialog.confirm({ |