merge multicheckbox and list inputs

This commit is contained in:
Henry Jameson 2025-12-02 20:44:14 +02:00
commit b7a97b8603
8 changed files with 138 additions and 162 deletions

View file

@ -4,17 +4,10 @@ import IntegerSetting from '../helpers/integer_setting.vue'
import StringSetting from '../helpers/string_setting.vue' import StringSetting from '../helpers/string_setting.vue'
import GroupSetting from '../helpers/group_setting.vue' import GroupSetting from '../helpers/group_setting.vue'
import AttachmentSetting from '../helpers/attachment_setting.vue' import AttachmentSetting from '../helpers/attachment_setting.vue'
import MultiCheckboxSetting from '../helpers/multicheckbox_setting.vue' import ListSetting from '../helpers/list_setting.vue'
import SharedComputedObject from '../helpers/shared_computed_object.js' import SharedComputedObject from '../helpers/shared_computed_object.js'
import { library } from '@fortawesome/fontawesome-svg-core' import { get } from 'lodash'
import {
faGlobe
} from '@fortawesome/free-solid-svg-icons'
library.add(
faGlobe
)
const InstanceTab = { const InstanceTab = {
provide () { provide () {
@ -29,11 +22,18 @@ const InstanceTab = {
IntegerSetting, IntegerSetting,
StringSetting, StringSetting,
AttachmentSetting, AttachmentSetting,
MultiCheckboxSetting, ListSetting,
GroupSetting GroupSetting
}, },
computed: { computed: {
...SharedComputedObject() ...SharedComputedObject(),
providersOptions () {
const desc = get(this.$store.state.adminSettings.descriptions, [':pleroma', 'Pleroma.Web.Metadata', ':providers'])
return new Set(desc.suggestions.map(option => ({
label: option.replace('Pleroma.Web.Metadata.Providers.', ''),
value: option
})))
},
} }
} }

View file

@ -134,7 +134,8 @@
<h3>{{ $t('admin_dash.instance.rich_metadata') }}</h3> <h3>{{ $t('admin_dash.instance.rich_metadata') }}</h3>
<ul class="setting-list"> <ul class="setting-list">
<li> <li>
<MultiCheckboxSetting <ListSetting
:override-available-options="providersOptions"
:path="[':pleroma','Pleroma.Web.Metadata', ':providers']" :path="[':pleroma','Pleroma.Web.Metadata', ':providers']"
/> />
</li> </li>

View file

@ -5,7 +5,6 @@ import StringSetting from '../helpers/string_setting.vue'
import GroupSetting from '../helpers/group_setting.vue' import GroupSetting from '../helpers/group_setting.vue'
import AttachmentSetting from '../helpers/attachment_setting.vue' import AttachmentSetting from '../helpers/attachment_setting.vue'
import ListSetting from '../helpers/list_setting.vue' import ListSetting from '../helpers/list_setting.vue'
import MultiCheckboxSetting from '../helpers/multicheckbox_setting.vue'
import SharedComputedObject from '../helpers/shared_computed_object.js' import SharedComputedObject from '../helpers/shared_computed_object.js'
import { get } from 'lodash' import { get } from 'lodash'
@ -24,13 +23,12 @@ const MediaProxyTab = {
StringSetting, StringSetting,
AttachmentSetting, AttachmentSetting,
GroupSetting, GroupSetting,
ListSetting, ListSetting
MultiCheckboxSetting
}, },
computed: { computed: {
ttlSettersOptions () { ttlSettersOptions () {
const desc = get(this.$store.state.adminSettings.descriptions, ':pleroma.:rich_media.:ttl_setters') const desc = get(this.$store.state.adminSettings.descriptions, ':pleroma.:rich_media.:ttl_setters')
return new Set([...desc.suggestions, 'Pleroma.Web.RichMedia.Parser.TTL.Opengraph'].map(option => ({ return new Set(desc.suggestions.map(option => ({
label: option.replace('Pleroma.Web.RichMedia.Parser.TTL.', ''), label: option.replace('Pleroma.Web.RichMedia.Parser.TTL.', ''),
value: option value: option
}))) })))

View file

@ -7,7 +7,7 @@
<BooleanSetting path=":pleroma.:rich_media.:enabled" /> <BooleanSetting path=":pleroma.:rich_media.:enabled" />
</li> </li>
<li> <li>
<MultiCheckboxSetting <ListSetting
:override-available-options="parsersOptions" :override-available-options="parsersOptions"
path=":pleroma.:rich_media.:parsers" path=":pleroma.:rich_media.:parsers"
/> />
@ -18,13 +18,16 @@
/> />
</li> </li>
<li> <li>
<MultiCheckboxSetting <ListSetting
:override-available-options="ttlSettersOptions" :override-available-options="ttlSettersOptions"
path=":pleroma.:rich_media.:ttl_setters" path=":pleroma.:rich_media.:ttl_setters"
/> />
</li> </li>
<li> <li>
<ListSetting path=":pleroma.:rich_media.:ignore_tld" /> <ListSetting
path=":pleroma.:rich_media.:ignore_tld"
ignore-suggestions
/>
</li> </li>
<li> <li>
<ListSetting path=":pleroma.:rich_media.:ignore_hosts" /> <ListSetting path=":pleroma.:rich_media.:ignore_hosts" />

View file

@ -1,41 +1,100 @@
import Checkbox from 'src/components/checkbox/checkbox.vue'
import Setting from './setting.js' import Setting from './setting.js'
export default { export default {
...Setting, ...Setting,
data () { data () {
return { return {
newValue: '' newValue: '',
} }
}, },
components: { components: {
...Setting.components ...Setting.components,
Checkbox
}, },
props: { props: {
...Setting.props ...Setting.props,
ignoreSuggestions: {
required: false,
type: Boolean
},
overrideAvailableOptions: {
required: false,
type: Set
},
allowNew: {
required: false,
type: Set,
default: true
}
}, },
computed: { computed: {
...Setting.computed ...Setting.computed,
valueSet () {
return new Set(this.visibleState)
},
suggestions () {
const suggestions = this.backendDescription?.suggestions
if (suggestions) {
return new Set(this.backendDescription.suggestions)
} else {
return new Set()
}
},
extraEntries () {
if (this.ignoreSuggestions) return [...this.valueSet.values()]
return [...this.valueSet.values()].filter((x) => {
return !this.suggestions.has(x)
})
},
builtinEntries () {
if (this.ignoreSuggestions) return []
if (this.overrideAvailableOptions) {
return [...this.overrideAvailableOptions]
}
const builtins = [...this.valueSet.values()].filter((x) => {
return this.suggestions.has(x)
})
return builtins.map((option) => ({
label: option,
value: option
}))
}
}, },
methods: { methods: {
...Setting.methods, ...Setting.methods,
addNew () { optionPresent (option) {
this.update({ newValue: this.newValue }) return this.valueSet.has(option)
}, },
getValue ({ event, index, newValue, remove }) { getValue ({ event, index, eventType }) {
if (newValue) { switch (eventType) {
this.newValue = '' case 'toggle': {
return [...this.visibleState, newValue] this.newValue = ''
} else if (remove) { return [...this.visibleState, event]
const pre = this.visibleState.slice(0, index) }
const post = this.visibleState.slice(index + 1)
return [...pre, ...post] case 'add': {
} else { const res = [...this.visibleState, this.newValue]
const pre = this.visibleState.slice(0, index) this.newValue = ''
const post = this.visibleState.slice(index + 1) return res
const string = event?.target?.value }
return [...pre, string, ...post] case 'remove': {
const pre = this.visibleState.slice(0, index)
const post = this.visibleState.slice(index + 1)
return [...pre, ...post]
}
case 'edit': {
const pre = this.visibleState.slice(0, index)
const post = this.visibleState.slice(index + 1)
const string = event?.target?.value
return [...pre, string, ...post]
}
} }
} }
} }

View file

@ -23,36 +23,46 @@
{{ backendDescriptionDescription + ' ' }} {{ backendDescriptionDescription + ' ' }}
</p> </p>
<ul class="setting-list"> <ul class="setting-list">
<li <li v-for="item in builtinEntries">
class="btn-group" <Checkbox
v-for="(item, index) in visibleState"
>
<input
class="input string-input"
:class="{ disabled: shouldBeDisabled }"
:value="item"
@change="e => update({event: e, index })"
>
<button
class="button-default"
@click="e => update({ remove: true, index })"
>
<FAIcon icon="times" />
</button>
</li>
<li class="btn-group">
<input
class="input string-input"
:class="{ disabled: shouldBeDisabled }"
:disabled="shouldBeDisabled" :disabled="shouldBeDisabled"
v-model="newValue" :model-value="optionPresent(item.value)"
@update:model-value="e => update({ event, eventType: 'toggle' })"
> >
<button {{ item.label }}
class="button-default" </Checkbox>
@click="addNew" </li>
> <li v-for="(item, index) in extraEntries">
<FAIcon icon="plus" /> <div class="btn-group">
</button> <input
class="input string-input"
:class="{ disabled: shouldBeDisabled }"
:value="item"
@change="e => update({ event: e, index, eventType: 'edit' })"
>
<button
class="button-default"
@click="e => update({ index, eventType: 'remove' })"
>
<FAIcon icon="times" />
</button>
</div>
</li>
<li v-if="allowNew">
<div class="btn-group">
<input
class="input string-input"
:class="{ disabled: shouldBeDisabled }"
:disabled="shouldBeDisabled"
v-model="newValue"
>
<button
class="button-default"
@click="e => update({ eventType: 'add' })"
>
<FAIcon icon="plus" />
</button>
</div>
</li> </li>
</ul> </ul>
<ModifiedIndicator <ModifiedIndicator
@ -66,7 +76,7 @@
<style lang="scss"> <style lang="scss">
.ListSetting { .ListSetting {
li.btn-group { .btn-group {
display: flex display: flex
} }
} }

View file

@ -1,47 +0,0 @@
import Checkbox from 'src/components/checkbox/checkbox.vue'
import Setting from './setting.js'
export default {
...Setting,
props: {
...Setting.props,
overrideAvailableOptions: {
required: false,
type: Set
}
},
components: {
...Setting.components,
Checkbox
},
computed: {
...Setting.computed,
availableOptions () {
if (this.overrideAvailableOptions) {
return new Set(this.overrideAvailableOptions)
}
return new Set(this.backendDescription?.suggestions.map((option) => ({
label: option,
value: option
})))
},
valueSet () {
return new Set(this.visibleState)
}
},
methods: {
...Setting.methods,
optionPresent (option) {
return this.valueSet.has(option)
},
getValue ({ event, option }) {
const set = new Set(this.visibleState)
if (event) {
set.add(option)
} else {
set.delete(option)
}
return [...set]
}
}
}

View file

@ -1,48 +0,0 @@
<template>
<label
v-if="matchesExpertLevel"
class="MultiCheckboxSetting"
>
<h5
:for="path"
class="setting-label"
:class="{ 'faint': shouldBeDisabled }"
>
<template v-if="backendDescriptionLabel">
{{ backendDescriptionLabel + ' ' }}
</template>
<template v-else-if="source === 'admin'">
MISSING LABEL FOR {{ path }}
</template>
<slot v-else />
</h5>
<p
v-if="backendDescriptionDescription"
class="setting-description"
:class="{ 'faint': shouldBeDisabled }"
>
{{ backendDescriptionDescription + ' ' }}
</p>
<ul class="setting-list">
<li v-for="option in availableOptions">
<Checkbox
:model-value="optionPresent(option.value)"
:disabled="shouldBeDisabled"
@update:model-value="e => update({event: e, option: option.value})"
>
{{ option.label }}
</Checkbox>
</li>
</ul>
<div>
<ModifiedIndicator
:changed="isChanged"
:onclick="reset"
/>
<ProfileSettingIndicator :is-profile="isProfileSetting" />
<DraftButtons />
</div>
</label>
</template>
<script src="./multicheckbox_setting.js"></script>