diff --git a/src/store/modules/normalizers.js b/src/store/modules/normalizers.js index 4fbfecae9b52658668980cdb1d275a6715789f32..c9dbc85075e09b19a1b45fde05db06ff2ac95f42 100644 --- a/src/store/modules/normalizers.js +++ b/src/store/modules/normalizers.js @@ -12,6 +12,10 @@ export const parseTuples = (tuples, key) => { accum[item.tuple[0]] = item.tuple[1] } else if (key === ':mascots') { accum[item.tuple[0]] = { ...item.tuple[1], id: `f${(~~(Math.random() * 1e8)).toString(16)}` } + } else if (item.tuple[0] === ':groups') { + accum[item.tuple[0]] = item.tuple[1].reduce((acc, group) => { + return [...acc, { [group.tuple[0]]: { value: group.tuple[1], id: `f${(~~(Math.random() * 1e8)).toString(16)}` }}] + }, []) } else if ((item.tuple[0] === ':sslopts' && item.tuple[1].length === 0) || // should be removed (item.tuple[0] === ':tlsopts' && item.tuple[1].length === 0)) { accum[item.tuple[0]] = {} diff --git a/src/views/settings/components/Inputs.vue b/src/views/settings/components/Inputs.vue index b1624e5dac813d045938239cc2df3adfd7431030..024b4b7adc628487de82ceac190ff093a1e9bca6 100644 --- a/src/views/settings/components/Inputs.vue +++ b/src/views/settings/components/Inputs.vue @@ -55,30 +55,6 @@ @input="update($event, settingGroup.group, settingGroup.key, settingParent, setting.key, setting.type, nested)"> <template slot="prepend">:</template> </el-input> - <div v-if="editableKeywordWithInput(setting.key)"> - <div v-for="([key, value], index) in editableKeywordData(data)" :key="index" class="setting-input"> - <el-input :value="key" placeholder="pattern" class="name-input" @input="parseEditableKeyword($event, 'key', index)"/> : - <el-input :value="value" placeholder="replacement" class="value-input" @input="parseEditableKeyword($event, 'value', index)"/> - <el-button icon="el-icon-minus" circle @click="deleteEditableKeywordRow(index)"/> - </div> - <el-button icon="el-icon-plus" circle @click="addRowToEditableKeyword"/> - </div> - <div v-if="editableKeywordWithSelect(setting.type)"> - <div v-for="([key, value], index) in editableKeywordData(data)" :key="index" class="setting-input"> - <el-input :value="key" placeholder="key" class="name-input" @input="parseEditableKeyword($event, 'key', index)"/> : - <el-select :value="value" multiple filterable allow-create class="value-input" @change="parseEditableKeyword($event, 'value', index)"/> - <el-button icon="el-icon-minus" circle @click="deleteEditableKeywordRow(index)"/> - </div> - <el-button icon="el-icon-plus" circle @click="addRowToEditableKeyword"/> - </div> - <div v-if="editableKeywordWithInteger(setting.type)"> - <div v-for="([key, value], index) in editableKeywordData(data)" :key="index" class="setting-input"> - <el-input :value="key" placeholder="key" class="name-input" @input="parseEditableKeyword($event, 'key', index)"/> : - <el-input-number :value="value" :min="0" size="large" class="value-input" @change="parseEditableKeyword($event, 'value', index)"/> - <el-button icon="el-icon-minus" circle @click="deleteEditableKeywordRow(index)"/> - </div> - <el-button icon="el-icon-plus" circle @click="addRowToEditableKeyword"/> - </div> <div v-if="setting.key === ':prune'"> <el-radio-group v-model="prune"> <el-radio label=":disabled">Disabled</el-radio> @@ -137,8 +113,9 @@ @input="updateSetting($event, settingGroup.group, settingGroup.key, setting.key)"/> </div> <!-- special inputs --> - <auto-linker-input v-if="settingGroup.group === ':auto_linker'" :setting-group="settingGroup" :setting="setting" :data="data"/> - <mascots-input v-if="setting.key === ':mascots'" :setting-group="settingGroup" :setting="setting" :data="data"/> + <auto-linker-input v-if="settingGroup.group === ':auto_linker'" :data="data" :setting-group="settingGroup" :setting="setting"/> + <mascots-input v-if="setting.key === ':mascots'" :data="data" :setting-group="settingGroup" :setting="setting"/> + <editable-keyword v-if="editableKeyword(setting.key, setting.type)" :data="data" :setting-group="settingGroup" :setting="setting"/> <!--------------------> <div v-if="setting.key === ':icons'"> <div v-for="(icon, index) in iconsValue" :key="index" class="mascot-container"> @@ -165,13 +142,14 @@ import AceEditor from 'vue2-ace-editor' import 'brace/mode/elixir' import 'default-passive-events' -import { AutoLinkerInput, MascotsInput } from './inputComponents' +import { AutoLinkerInput, EditableKeyword, MascotsInput } from './inputComponents' export default { name: 'Inputs', components: { editor: AceEditor, AutoLinkerInput, + EditableKeyword, MascotsInput }, props: { @@ -183,7 +161,7 @@ export default { required: false }, data: { - type: Object || Array, + type: [Object, Array], default: function() { return {} } @@ -287,43 +265,12 @@ export default { methods: { addIconToIcons() {}, addValueToIcons() {}, - addRowToEditableKeyword() { - const updatedValue = this.editableKeywordData(this.data).reduce((acc, el, i) => { - return { ...acc, [el[0]]: el[1] } - }, {}) - this.updateSetting({ ...updatedValue, '': [] }, this.settingGroup.group, this.settingGroup.key, this.setting.key) - }, - deleteEditableKeywordRow(index) { - const filteredValues = this.editableKeywordData(this.data).filter((el, i) => index !== i) - const updatedValue = filteredValues.reduce((acc, el, i) => { - return { ...acc, [el[0]]: el[1] } - }, {}) - this.updateSetting(updatedValue, this.settingGroup.group, this.settingGroup.key, this.setting.key) - }, deleteIcondRow(index) {}, - editableKeywordWithInput(key) { - return key === ':replace' - }, - editableKeywordWithInteger(type) { - return Array.isArray(type) - ? type.includes('keyword') && type.includes('integer') - : false - }, - editableKeywordWithSelect(type) { - return type === 'map' || - (Array.isArray(type) && type.includes('keyword') && type.findIndex(el => el.includes('list') && el.includes('string')) !== -1) - }, - editableKeywordData(data) { - return Object.keys(data).map(key => [key, data[key]]) - }, - parseEditableKeyword(value, inputType, index) { - const updatedValue = this.editableKeywordData(this.data).reduce((acc, el, i) => { - if (index === i) { - return inputType === 'key' ? { ...acc, [value]: el[1] } : { ...acc, [el[0]]: value } - } - return { ...acc, [el[0]]: el[1] } - }, {}) - this.updateSetting(updatedValue, this.settingGroup.group, this.settingGroup.key, this.setting.key) + editableKeyword(key, type) { + return key === ':replace' || + (Array.isArray(type) && type.includes('keyword') && type.includes('integer')) || + type === 'map' || + (Array.isArray(type) && type.includes('keyword') && type.findIndex(el => el.includes('list') && el.includes('string')) !== -1) }, parseIcons(value, inputType, index) {}, parseRateLimiter(value, input, typeOfInput, typeOfLimit, currentValue) { diff --git a/src/views/settings/components/inputComponents/EditableKeyword.vue b/src/views/settings/components/inputComponents/EditableKeyword.vue new file mode 100644 index 0000000000000000000000000000000000000000..f1f106cd862ea2cc1f98014725821f62da88da77 --- /dev/null +++ b/src/views/settings/components/inputComponents/EditableKeyword.vue @@ -0,0 +1,109 @@ +<template> + <div> + <div v-if="setting.key === ':replace'"> + <div v-for="element in data" :key="getId(element)" class="setting-input"> + <el-input :value="getKey(element)" placeholder="pattern" class="name-input" @input="parseEditableKeyword($event, 'key', element)"/> : + <el-input :value="getValue(element)" placeholder="replacement" class="value-input" @input="parseEditableKeyword($event, 'value', element)"/> + <el-button icon="el-icon-minus" circle @click="deleteEditableKeywordRow(element)"/> + </div> + <el-button icon="el-icon-plus" circle @click="addRowToEditableKeyword"/> + </div> + <div v-else-if="editableKeywordWithInteger"> + <div v-for="element in data" :key="getId(element)" class="setting-input"> + <el-input :value="getKey(element)" placeholder="key" class="name-input" @input="parseEditableKeyword($event, 'key', element)"/> : + <el-input-number :value="getValue(element)" :min="0" size="large" class="value-input" @change="parseEditableKeyword($event, 'value', element)"/> + <el-button icon="el-icon-minus" circle @click="deleteEditableKeywordRow(element)"/> + </div> + <el-button icon="el-icon-plus" circle @click="addRowToEditableKeyword"/> + </div> + <div v-else> + <div v-for="element in data" :key="getId(element)" class="setting-input"> + <el-input :value="getKey(element)" placeholder="key" class="name-input" @input="parseEditableKeyword($event, 'key', element)"/> : + <el-select :value="getValue(element)" multiple filterable allow-create class="value-input" @change="parseEditableKeyword($event, 'value', element)"/> + <el-button icon="el-icon-minus" circle @click="deleteEditableKeywordRow(element)"/> + </div> + <el-button icon="el-icon-plus" circle @click="addRowToEditableKeyword"/> + </div> + </div> +</template> + +<script> +export default { + name: 'EditableKeyword', + props: { + data: { + type: [Object, Array], + default: function() { + return {} + } + }, + setting: { + type: Object, + default: function() { + return {} + } + }, + settingGroup: { + type: Object, + default: function() { + return {} + } + } + }, + computed: { + editableKeywordWithInteger() { + return Array.isArray(this.setting.type) && this.setting.type.includes('keyword') && this.setting.type.includes('integer') + } + }, + methods: { + addRowToEditableKeyword() { + const updatedValue = [...this.data, { '': { value: '', id: this.generateID() }}] + this.updateSetting(updatedValue, this.settingGroup.group, this.settingGroup.key, this.setting.key) + }, + deleteEditableKeywordRow(element) { + const deletedId = this.getId(element) + const filteredValues = this.data.filter(element => Object.values(element)[0].id !== deletedId) + this.updateSetting(filteredValues, this.settingGroup.group, this.settingGroup.key, this.setting.key) + }, + generateID() { + return `f${(~~(Math.random() * 1e8)).toString(16)}` + }, + getKey(element) { + return Object.keys(element)[0] + }, + getId(element) { + const { id } = Object.values(element)[0] + return id + }, + getValue(element) { + const { value } = Object.values(element)[0] + return value + }, + parseEditableKeyword(value, inputType, element) { + const updatedId = this.getId(element) + const updatedValue = this.data.map((element, index) => { + if (Object.values(element)[0].id === updatedId) { + return inputType === 'key' + ? { [value]: Object.values(this.data[index])[0] } + : { [Object.keys(element)[0]]: { ...Object.values(this.data[index])[0], value }} + } + return element + }) + + this.updateSetting(updatedValue, this.settingGroup.group, this.settingGroup.key, this.setting.key, this.setting.type) + }, + updateSetting(value, group, key, input, type) { + const updatedSettings = value.reduce((acc, element) => { + return { ...acc, [Object.keys(element)[0]]: [['list', 'string'], Object.values(element)[0].value] } + }, {}) + this.$store.dispatch('UpdateSettings', { group, key, input, value: updatedSettings, type }) + this.$store.dispatch('UpdateState', { group, key, input, value }) + } + } +} +</script> + +<style rel='stylesheet/scss' lang='scss'> +@import '../../styles/main'; +@include settings +</style> diff --git a/src/views/settings/components/inputComponents/index.js b/src/views/settings/components/inputComponents/index.js index eb2d7b8364ad5486930bfb92a34dd468df619a8d..922dea1b592f2e5edaea9f1fee4650e7e2dc00b8 100644 --- a/src/views/settings/components/inputComponents/index.js +++ b/src/views/settings/components/inputComponents/index.js @@ -1,2 +1,3 @@ export { default as AutoLinkerInput } from './AutoLinkerInput' export { default as MascotsInput } from './MascotsInput' +export { default as EditableKeyword } from './EditableKeyword'