mirror of
https://github.com/YunoHost/yunohost-admin.git
synced 2024-09-03 20:06:15 +02:00
refactor: rework TagsSelectizeItem with multiple choices types
This commit is contained in:
parent
cba781d809
commit
837e92789a
2 changed files with 44 additions and 30 deletions
|
@ -3,17 +3,14 @@ import type { BDropdown, BFormInput } from 'bootstrap-vue-next'
|
||||||
import { computed, ref } from 'vue'
|
import { computed, ref } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
|
import { fromEntries } from '@/helpers/commons'
|
||||||
import type {
|
import type {
|
||||||
BaseItemComputedProps,
|
BaseItemComputedProps,
|
||||||
|
Choice,
|
||||||
|
TagUpdateArgs,
|
||||||
TagsSelectizeItemProps,
|
TagsSelectizeItemProps,
|
||||||
} from '@/types/form'
|
} from '@/types/form'
|
||||||
|
|
||||||
type TagUpdateArgs = {
|
|
||||||
action: 'add' | 'remove'
|
|
||||||
option: string
|
|
||||||
applyFn: (tag: string) => void
|
|
||||||
}
|
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
inheritAttrs: false,
|
inheritAttrs: false,
|
||||||
})
|
})
|
||||||
|
@ -55,19 +52,26 @@ const criteria = computed(() => {
|
||||||
return search.value.trim().toLowerCase()
|
return search.value.trim().toLowerCase()
|
||||||
})
|
})
|
||||||
const availableOptions = computed(() => {
|
const availableOptions = computed(() => {
|
||||||
const options = props.options.filter((opt) => {
|
return props.options.filter((opt) => {
|
||||||
return (
|
const tag = typeof opt === 'string' ? opt : opt.value
|
||||||
props.modelValue?.indexOf(opt) === -1 &&
|
let filterIn =
|
||||||
props.disabledItems?.includes(opt)
|
model.value?.indexOf(tag) === -1 &&
|
||||||
)
|
!(props.disabledItems?.includes(tag) ?? false)
|
||||||
})
|
if (filterIn && criteria.value) {
|
||||||
if (criteria.value) {
|
filterIn = tag.toLowerCase().indexOf(criteria.value) > -1
|
||||||
return options.filter(
|
|
||||||
(opt) => opt.toLowerCase().indexOf(criteria.value) > -1,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
return options
|
return filterIn
|
||||||
})
|
})
|
||||||
|
})
|
||||||
|
const texts = computed(() =>
|
||||||
|
fromEntries(
|
||||||
|
props.options.map((opt) => {
|
||||||
|
const tag = typeof opt === 'string' ? opt : opt.value
|
||||||
|
const text = typeof opt === 'string' ? opt : opt.text
|
||||||
|
return [tag, text]
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
)
|
||||||
const searchI18n = computed(() => {
|
const searchI18n = computed(() => {
|
||||||
const params = { items: t('items.' + props.itemsName, 0) }
|
const params = { items: t('items.' + props.itemsName, 0) }
|
||||||
return {
|
return {
|
||||||
|
@ -80,18 +84,20 @@ const searchState = computed(() => {
|
||||||
return criteria.value && availableOptions.value.length === 0 ? false : null
|
return criteria.value && availableOptions.value.length === 0 ? false : null
|
||||||
})
|
})
|
||||||
|
|
||||||
function onAddTag(option: string, applyFn: TagUpdateArgs['applyFn']) {
|
function onAddTag(option: Choice, applyFn: TagUpdateArgs['applyFn']) {
|
||||||
emit('tag-update', { action: 'add', option, applyFn })
|
const tag = typeof option === 'string' ? option : option.value
|
||||||
|
emit('tag-update', { action: 'add', tag, applyFn })
|
||||||
search.value = ''
|
search.value = ''
|
||||||
if (props.auto) {
|
if (props.auto) {
|
||||||
applyFn(option)
|
applyFn(tag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onRemoveTag(option: string, applyFn: TagUpdateArgs['applyFn']) {
|
function onRemoveTag(option: Choice, applyFn: TagUpdateArgs['applyFn']) {
|
||||||
emit('tag-update', { action: 'remove', option, applyFn })
|
const tag = typeof option === 'string' ? option : option.value
|
||||||
|
emit('tag-update', { action: 'remove', tag, applyFn })
|
||||||
if (props.auto) {
|
if (props.auto) {
|
||||||
applyFn(option)
|
applyFn(tag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,11 +140,11 @@ function onDropdownKeydown(e: KeyboardEvent) {
|
||||||
>
|
>
|
||||||
<BFormTag
|
<BFormTag
|
||||||
:title="tag"
|
:title="tag"
|
||||||
:disabled="disabled || disabledItems?.includes(tag)"
|
:disabled="disabled || (disabledItems?.includes(tag) ?? false)"
|
||||||
class="border border-dark mb-2"
|
class="border border-dark mb-2"
|
||||||
@remove="onRemoveTag(tag, removeTag)"
|
@remove="onRemoveTag(tag, removeTag)"
|
||||||
>
|
>
|
||||||
<YIcon v-if="tagIcon" :iname="tagIcon" /> {{ tag }}
|
<YIcon v-if="tagIcon" :iname="tagIcon" /> {{ texts[tag] }}
|
||||||
</BFormTag>
|
</BFormTag>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -173,6 +179,7 @@ function onDropdownKeydown(e: KeyboardEvent) {
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
size="sm"
|
size="sm"
|
||||||
type="search"
|
type="search"
|
||||||
|
@click.stop
|
||||||
/>
|
/>
|
||||||
</BFormGroup>
|
</BFormGroup>
|
||||||
</BDropdownForm>
|
</BDropdownForm>
|
||||||
|
@ -180,11 +187,11 @@ function onDropdownKeydown(e: KeyboardEvent) {
|
||||||
</BDropdownGroup>
|
</BDropdownGroup>
|
||||||
|
|
||||||
<BDropdownItemButton
|
<BDropdownItemButton
|
||||||
v-for="option in availableOptions"
|
v-for="(option, i) in availableOptions"
|
||||||
:key="option"
|
:key="i"
|
||||||
@click="onAddTag(option, addTag)"
|
@click="onAddTag(option, addTag)"
|
||||||
>
|
>
|
||||||
{{ option }}
|
{{ typeof option === 'string' ? option : option.text }}
|
||||||
</BDropdownItemButton>
|
</BDropdownItemButton>
|
||||||
<BDropdownText v-if="!criteria && availableOptions.length === 0">
|
<BDropdownText v-if="!criteria && availableOptions.length === 0">
|
||||||
<YIcon iname="exclamation-triangle" />
|
<YIcon iname="exclamation-triangle" />
|
||||||
|
|
|
@ -10,7 +10,14 @@ import { isObjectLiteral } from '@/helpers/commons'
|
||||||
import type { ArrInnerType, Cols, Obj, StateVariant } from '@/types/commons'
|
import type { ArrInnerType, Cols, Obj, StateVariant } from '@/types/commons'
|
||||||
|
|
||||||
type StateValidation = false | null
|
type StateValidation = false | null
|
||||||
type Choices = string[] | { text: string; value: string }[]
|
export type Choice = string | { text: string; value: string }
|
||||||
|
type Choices = Choice[]
|
||||||
|
|
||||||
|
export type TagUpdateArgs = {
|
||||||
|
action: 'add' | 'remove'
|
||||||
|
tag: string
|
||||||
|
applyFn: (tag: string) => void
|
||||||
|
}
|
||||||
|
|
||||||
// DISPLAY
|
// DISPLAY
|
||||||
|
|
||||||
|
@ -121,7 +128,7 @@ export type TagsItemProps = BaseWritableItemProps & {
|
||||||
|
|
||||||
export type TagsSelectizeItemProps = BaseWritableItemProps & {
|
export type TagsSelectizeItemProps = BaseWritableItemProps & {
|
||||||
itemsName: string
|
itemsName: string
|
||||||
options: string[]
|
options: Choices
|
||||||
auto?: boolean
|
auto?: boolean
|
||||||
disabledItems?: string[]
|
disabledItems?: string[]
|
||||||
label: string
|
label: string
|
||||||
|
|
Loading…
Reference in a new issue