Fixed Additional options in backend edit page.
This commit is contained in:
@@ -37,8 +37,8 @@
|
||||
</div>
|
||||
|
||||
<div class="column is-12" v-if="isLoading">
|
||||
<Message message_class="is-background-info-90 has-text-dark" title="Loading"
|
||||
icon="fas fa-spinner fa-spin" message="Loading backend settings. Please wait..."/>
|
||||
<Message message_class="is-background-info-90 has-text-dark" title="Loading" icon="fas fa-spinner fa-spin"
|
||||
message="Loading backend settings. Please wait..." />
|
||||
</div>
|
||||
|
||||
<div v-else class="column is-12">
|
||||
@@ -293,24 +293,23 @@
|
||||
</label>
|
||||
<template v-if="showOptions">
|
||||
<div class="columns is-multiline is-mobile">
|
||||
<template v-for="(val, key) in backend?.options" :key="'bo-'+key">
|
||||
<template v-for="_option in flatOptionPaths" :key="'bo-'+_option">
|
||||
<div class="column is-5">
|
||||
<input type="text" class="input" :value="key" readonly disabled>
|
||||
<input type="text" class="input" :value="_option" readonly disabled>
|
||||
<p class="help is-unselectable">
|
||||
<span class="icon has-text-info">
|
||||
<i class="fas fa-info-circle" :class="{'fa-bounce': newOptions[key]}"></i>
|
||||
<i class="fas fa-info-circle" :class="{ 'fa-bounce': newOptions[_option] }"></i>
|
||||
</span>
|
||||
{{ optionsList.find(v => v.key === key)?.description }}
|
||||
{{ option_describe(_option) }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="column is-6">
|
||||
<input type="text" class="input" v-model="backend.options[key]" required>
|
||||
<input type="text" class="input" :value="option_get(_option)"
|
||||
@input="e => option_set(_option, e.target.value)" required>
|
||||
</div>
|
||||
<div class="column is-1">
|
||||
<button class="button is-danger" @click.prevent="removeOption(key)">
|
||||
<span class="icon">
|
||||
<i class="fas fa-trash"></i>
|
||||
</span>
|
||||
<button class="button is-danger" @click.prevent="removeOption(_option)">
|
||||
<span class="icon"><i class="fas fa-trash" /></span>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
@@ -326,8 +325,8 @@
|
||||
<div class="select is-fullwidth">
|
||||
<select v-model="selectedOption">
|
||||
<option value="">Select Option</option>
|
||||
<option v-for="option in filteredOptions(optionsList)"
|
||||
:key="'opt-'+option.key" :value="option.key">
|
||||
<option v-for="option in filteredOptions(optionsList)" :key="'opt-' + option.key"
|
||||
:value="option.key">
|
||||
{{ option.key }}
|
||||
</option>
|
||||
</select>
|
||||
@@ -431,13 +430,20 @@ const loadContent = async () => {
|
||||
}
|
||||
|
||||
const saveContent = async () => {
|
||||
const json_text = toRaw(backend.value)
|
||||
|
||||
const flat = {}
|
||||
flatOptionPaths.value.forEach(path => flat[path] = option_get(path))
|
||||
|
||||
if (Object.keys(flat).length > 0) {
|
||||
json_text.options = flat
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await request(`/backend/${id}`, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(backend.value)
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(json_text)
|
||||
})
|
||||
|
||||
const json = await response.json()
|
||||
@@ -461,9 +467,10 @@ const removeOption = async (key) => {
|
||||
return
|
||||
}
|
||||
|
||||
if (!confirm(`Are you sure you want to remove this option [${key}]?`)) {
|
||||
if (!confirm(`Are you sure you want to remove this option '${key}'?`)) {
|
||||
return
|
||||
}
|
||||
|
||||
const response = await request(`/backend/${id}/option/options.${key}`, { method: 'DELETE' })
|
||||
|
||||
if (!response.ok) {
|
||||
@@ -475,6 +482,7 @@ const removeOption = async (key) => {
|
||||
notification('success', 'Information', `Option [${key}] removed successfully.`)
|
||||
delete backend.value.options[key]
|
||||
}
|
||||
|
||||
const addOption = async () => {
|
||||
if (!selectedOption.value) {
|
||||
notification('error', 'Error', 'Please select an option to add.')
|
||||
@@ -482,17 +490,11 @@ const addOption = async () => {
|
||||
}
|
||||
|
||||
backend.value.options = backend.value.options || {}
|
||||
if (backend.value.options.length < 1) {
|
||||
backend.value.options = {[selectedOption.value]: ''}
|
||||
} else {
|
||||
backend.value.options[selectedOption.value] = ''
|
||||
}
|
||||
|
||||
option_set(selectedOption.value, '')
|
||||
newOptions.value[selectedOption.value] = true
|
||||
selectedOption.value = ''
|
||||
}
|
||||
|
||||
|
||||
const getUUid = async () => {
|
||||
const required_values = ['type', 'token', 'url'];
|
||||
|
||||
@@ -570,7 +572,7 @@ const getUsers = async (showAlert = true) => {
|
||||
users.value = json
|
||||
}
|
||||
|
||||
watch(showOptions, async (value) => {
|
||||
watch(showOptions, async value => {
|
||||
if (!value) {
|
||||
return
|
||||
}
|
||||
@@ -589,14 +591,13 @@ watch(showOptions, async (value) => {
|
||||
})
|
||||
});
|
||||
|
||||
const filteredOptions = (options) => {
|
||||
const filteredOptions = options => {
|
||||
if (!options) {
|
||||
return []
|
||||
}
|
||||
return options.filter(v => !backend.value.options[v.key] && !newOptions.value[v.key])
|
||||
}
|
||||
|
||||
|
||||
const getServers = async () => {
|
||||
if ('plex' !== backend.value.type || servers.value.length > 0) {
|
||||
return
|
||||
@@ -674,6 +675,56 @@ watch(() => backend.value.user, async () => {
|
||||
})
|
||||
})
|
||||
|
||||
const flattenOptions = (obj, prefix = '') => {
|
||||
const out = []
|
||||
|
||||
for (const [key, val] of Object.entries(obj)) {
|
||||
const path = prefix ? `${prefix}.${key}` : key
|
||||
|
||||
if (Array.isArray(val)) {
|
||||
if (val.length === 0) {
|
||||
continue
|
||||
}
|
||||
out.push(path)
|
||||
continue
|
||||
}
|
||||
|
||||
if (val !== null && typeof val === 'object') {
|
||||
if (Object.keys(val).length === 0) {
|
||||
continue
|
||||
}
|
||||
out.push(...flattenOptions(val, path))
|
||||
continue
|
||||
}
|
||||
|
||||
out.push(path)
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
const flatOptionPaths = computed(() => flattenOptions(backend.value.options))
|
||||
|
||||
const option_get = path => path.split('.').reduce((o, k) => (o == null ? undefined : o[k]), backend.value.options)
|
||||
const option_set = (path, value) => {
|
||||
const keys = path.split('.')
|
||||
const last = keys.pop()
|
||||
let target = backend.value.options
|
||||
for (const k of keys) {
|
||||
if (target[k] == null || typeof target[k] !== 'object' || Array.isArray(target[k])) {
|
||||
target[k] = {}
|
||||
}
|
||||
target = target[k]
|
||||
}
|
||||
|
||||
target[last] = value
|
||||
}
|
||||
|
||||
const option_describe = path => {
|
||||
const item = optionsList.value.find((v) => v.key === path)
|
||||
return item ? item.description : ''
|
||||
}
|
||||
|
||||
onMounted(async () => await loadContent())
|
||||
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user