aboutsummaryrefslogtreecommitdiff
path: root/src/site/components/settings
diff options
context:
space:
mode:
authorKana <[email protected]>2021-06-19 02:03:57 +0900
committerGitHub <[email protected]>2021-06-19 02:03:57 +0900
commit065c5221a0250838f1d1f9bb7a7922ff4f55e038 (patch)
tree8a69a81f00e6bff2752f4f7c59dcbbf21f893b20 /src/site/components/settings
parentchore: docs update (diff)
parentfix: potentially fix the blocked extensions array splitting (diff)
downloadhost.fuwn.me-065c5221a0250838f1d1f9bb7a7922ff4f55e038.tar.xz
host.fuwn.me-065c5221a0250838f1d1f9bb7a7922ff4f55e038.zip
Merge pull request #278 from Zephyrrus/Zephyrrus-feature/database_based_settings
Zephyrrus feature/database based settings
Diffstat (limited to 'src/site/components/settings')
-rw-r--r--src/site/components/settings/JoiObject.vue151
1 files changed, 151 insertions, 0 deletions
diff --git a/src/site/components/settings/JoiObject.vue b/src/site/components/settings/JoiObject.vue
new file mode 100644
index 0000000..8d3a803
--- /dev/null
+++ b/src/site/components/settings/JoiObject.vue
@@ -0,0 +1,151 @@
+<template>
+ <div v-if="settings">
+ <div v-for="[key, field] in Object.entries(settings)" :key="key">
+ <b-field
+ :label="field.flags.label"
+ :message="getErrorMessage(key) || field.flags.description"
+ :type="getValidationType(key)"
+ class="field"
+ horizontal>
+ <b-input
+ v-if="getDisplayType(field) === 'string'"
+ v-model="values[key]"
+ class="chibisafe-input"
+ expanded />
+ <b-input
+ v-else-if="getDisplayType(field) === 'number'"
+ v-model="values[key]"
+ type="number"
+ class="chibisafe-input"
+ :min="getMin(field)"
+ :max="getMax(field)"
+ expanded />
+ <b-switch
+ v-else-if="getDisplayType(field) === 'boolean'"
+ v-model="values[key]"
+ :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="values[key]"
+ ellipsis
+ icon="label"
+ :placeholder="field.flags.label"
+ class="taginp" />
+ <div v-else-if="getDisplayType(field) === 'checkbox'">
+ <b-checkbox v-for="item in getAllowedItems(field)" :key="item"
+ v-model="values[key]"
+ :native-value="item">
+ {{ item }}
+ </b-checkbox>
+ </div>
+ </b-field>
+ <!--
+ TODO: Add asterisk to required fields
+ -->
+ </div>
+ </div>
+</template>
+
+
+<script>
+export default {
+ name: 'JoiObject',
+ props: {
+ settings: {
+ type: Object,
+ required: true
+ },
+ errors: {
+ 'type': Object,
+ 'default': () => ({})
+ }
+ },
+ data() {
+ return {
+ values: {}
+ };
+ },
+ created() {
+ for (const [k, v] of Object.entries(this.settings)) {
+ this.$set(this.values, k, v.value);
+ }
+ },
+ methods: {
+ getMin(field) {
+ if (field.type !== 'number') return;
+
+ for (const rule of field.rules) {
+ if (rule.name === 'greater') return rule.args.limit + 1;
+ if (rule.name === 'min') return rule.args.limit;
+ }
+ },
+ getMax(field) {
+ if (field.type !== 'number') return;
+
+ for (const rule of field.rules) {
+ if (rule.name === 'less') return rule.args.limit - 1;
+ if (rule.name === 'max') return rule.args.limit;
+ }
+ },
+ getDisplayType(field) {
+ if (!field.metas) return field.type;
+
+ const foundMeta = field.metas.find(e => e.displayType);
+
+ if (foundMeta) return foundMeta.displayType;
+
+ return field.type;
+ },
+ getAllowedItems(field) {
+ if (!field.items) return [];
+
+ return field.items.reduce((acc, item) => {
+ if (!item.allow) return acc;
+
+ return [...acc, ...item.allow];
+ }, []);
+ },
+ getValidationType(fieldName) {
+ if (Array.isArray(this.errors[fieldName])) return 'is-danger';
+ return null;
+ },
+ getErrorMessage(fieldName) {
+ if (Array.isArray(this.errors[fieldName])) return this.errors[fieldName].join('\n');
+ return null;
+ },
+ getValues() {
+ return this.values;
+ }
+ }
+};
+</script>
+<style lang="scss" scoped>
+ @import '~/assets/styles/_colors.scss';
+
+ .field {
+ margin-bottom: 1em;
+
+ ::v-deep .help.is-danger {
+ white-space: pre-line;
+ }
+ }
+
+ .taginp {
+ ::v-deep {
+ .taginput-container {
+ border-color: #585858;
+ }
+
+ .input::placeholder {
+ color: $textColor;
+ }
+
+ .taginput-container, .control, .input {
+ background-color: transparent;
+ }
+ }
+ }
+</style>