fix(settings): allow removing the default project via settings
This commit is contained in:
parent
8992caadf9
commit
aeed4b3a3b
@ -9,9 +9,9 @@
|
|||||||
<div class="control" :class="{'is-loading': loading || localLoading}">
|
<div class="control" :class="{'is-loading': loading || localLoading}">
|
||||||
<div
|
<div
|
||||||
class="input-wrapper input"
|
class="input-wrapper input"
|
||||||
:class="{'has-multiple': hasMultiple}"
|
:class="{'has-multiple': hasMultiple, 'has-removal-button': removalAvailable}"
|
||||||
>
|
>
|
||||||
<slot
|
<slot
|
||||||
v-if="Array.isArray(internalValue)"
|
v-if="Array.isArray(internalValue)"
|
||||||
name="items"
|
name="items"
|
||||||
:items="internalValue"
|
:items="internalValue"
|
||||||
@ -19,14 +19,14 @@
|
|||||||
>
|
>
|
||||||
<template v-for="(item, key) in internalValue">
|
<template v-for="(item, key) in internalValue">
|
||||||
<slot name="tag" :item="item">
|
<slot name="tag" :item="item">
|
||||||
<span :key="`item${key}`" class="tag ml-2 mt-2">
|
<span :key="`item${key}`" class="tag ml-2 mt-2">
|
||||||
{{ label !== '' ? item[label] : item }}
|
{{ label !== '' ? item[label] : item }}
|
||||||
<BaseButton @click="() => remove(item)" class="delete is-small"></BaseButton>
|
<BaseButton @click="() => remove(item)" class="delete is-small"></BaseButton>
|
||||||
</span>
|
</span>
|
||||||
</slot>
|
</slot>
|
||||||
</template>
|
</template>
|
||||||
</slot>
|
</slot>
|
||||||
|
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
class="input"
|
class="input"
|
||||||
@ -40,6 +40,13 @@
|
|||||||
:autocomplete="autocompleteEnabled ? undefined : 'off'"
|
:autocomplete="autocompleteEnabled ? undefined : 'off'"
|
||||||
:spellcheck="autocompleteEnabled ? undefined : 'false'"
|
:spellcheck="autocompleteEnabled ? undefined : 'false'"
|
||||||
/>
|
/>
|
||||||
|
<BaseButton
|
||||||
|
v-if="removalAvailable"
|
||||||
|
class="removal-button"
|
||||||
|
@click="resetSelectedValue"
|
||||||
|
>
|
||||||
|
<icon icon="times"/>
|
||||||
|
</BaseButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -159,7 +166,7 @@ const props = defineProps({
|
|||||||
createPlaceholder: {
|
createPlaceholder: {
|
||||||
type: String,
|
type: String,
|
||||||
default() {
|
default() {
|
||||||
const {t} = useI18n({useScope: 'global'})
|
const {t} = useI18n({useScope: 'global'})
|
||||||
return t('input.multiselect.createPlaceholder')
|
return t('input.multiselect.createPlaceholder')
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -169,7 +176,7 @@ const props = defineProps({
|
|||||||
selectPlaceholder: {
|
selectPlaceholder: {
|
||||||
type: String,
|
type: String,
|
||||||
default() {
|
default() {
|
||||||
const {t} = useI18n({useScope: 'global'})
|
const {t} = useI18n({useScope: 'global'})
|
||||||
return t('input.multiselect.selectPlaceholder')
|
return t('input.multiselect.selectPlaceholder')
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -215,23 +222,23 @@ const props = defineProps({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'update:modelValue', value: null): void
|
(e: 'update:modelValue', value: null): void
|
||||||
/**
|
/**
|
||||||
* Triggered every time the search query input changes
|
* Triggered every time the search query input changes
|
||||||
*/
|
*/
|
||||||
(e: 'search', query: string): void
|
(e: 'search', query: string): void
|
||||||
/**
|
/**
|
||||||
* Triggered every time an option from the search results is selected. Also triggers a change in v-model.
|
* Triggered every time an option from the search results is selected. Also triggers a change in v-model.
|
||||||
*/
|
*/
|
||||||
(e: 'select', value: {[key: string]: any}): void
|
(e: 'select', value: {[key: string]: any}): void
|
||||||
/**
|
/**
|
||||||
* If nothing or no exact match was found and `creatable` is true, this event is triggered with the current value of the search query.
|
* If nothing or no exact match was found and `creatable` is true, this event is triggered with the current value of the search query.
|
||||||
*/
|
*/
|
||||||
(e: 'create', query: string): void
|
(e: 'create', query: string): void
|
||||||
/**
|
/**
|
||||||
* If `multiple` is enabled, this will be fired every time an item is removed from the array of selected items.
|
* If `multiple` is enabled, this will be fired every time an item is removed from the array of selected items.
|
||||||
*/
|
*/
|
||||||
(e: 'remove', value: null): void
|
(e: 'remove', value: null): void
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const query = ref<string | {[key: string]: any}>('')
|
const query = ref<string | {[key: string]: any}>('')
|
||||||
@ -269,8 +276,8 @@ const creatableAvailable = computed(() => {
|
|||||||
const hasResult = filteredSearchResults.value.some((elem: any) => elementInResults(elem, props.label, query.value))
|
const hasResult = filteredSearchResults.value.some((elem: any) => elementInResults(elem, props.label, query.value))
|
||||||
const hasQueryAlreadyAdded = Array.isArray(internalValue.value) && internalValue.value.some(elem => elementInResults(elem, props.label, query.value))
|
const hasQueryAlreadyAdded = Array.isArray(internalValue.value) && internalValue.value.some(elem => elementInResults(elem, props.label, query.value))
|
||||||
|
|
||||||
return props.creatable
|
return props.creatable
|
||||||
&& query.value !== ''
|
&& query.value !== ''
|
||||||
&& !(hasResult || hasQueryAlreadyAdded)
|
&& !(hasResult || hasQueryAlreadyAdded)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -287,7 +294,13 @@ const hasMultiple = computed(() => {
|
|||||||
return props.multiple && Array.isArray(internalValue.value) && internalValue.value.length > 0
|
return props.multiple && Array.isArray(internalValue.value) && internalValue.value.length > 0
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const removalAvailable = computed(() => !props.multiple && internalValue.value !== null && query.value !== '')
|
||||||
|
function resetSelectedValue() {
|
||||||
|
select(null)
|
||||||
|
}
|
||||||
|
|
||||||
const searchInput = ref<HTMLInputElement | null>(null)
|
const searchInput = ref<HTMLInputElement | null>(null)
|
||||||
|
|
||||||
// Searching will be triggered with a 200ms delay to avoid searching on every keyup event.
|
// Searching will be triggered with a 200ms delay to avoid searching on every keyup event.
|
||||||
function search() {
|
function search() {
|
||||||
|
|
||||||
@ -312,6 +325,7 @@ function search() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const multiselectRoot = ref<HTMLElement | null>(null)
|
const multiselectRoot = ref<HTMLElement | null>(null)
|
||||||
|
|
||||||
function hideSearchResultsHandler(e: MouseEvent) {
|
function hideSearchResultsHandler(e: MouseEvent) {
|
||||||
closeWhenClickedOutside(e, multiselectRoot.value, closeSearchResults)
|
closeWhenClickedOutside(e, multiselectRoot.value, closeSearchResults)
|
||||||
}
|
}
|
||||||
@ -328,7 +342,7 @@ function handleFocus() {
|
|||||||
}, 10)
|
}, 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
function select(object: {[key: string]: any}) {
|
function select(object: {[key: string]: any} | null) {
|
||||||
if (props.multiple) {
|
if (props.multiple) {
|
||||||
if (internalValue.value === null) {
|
if (internalValue.value === null) {
|
||||||
internalValue.value = []
|
internalValue.value = []
|
||||||
@ -370,6 +384,7 @@ function setSelectedObject(object: string | {[id: string]: any} | null, resetOnl
|
|||||||
}
|
}
|
||||||
|
|
||||||
const results = ref<(Element | ComponentPublicInstance)[]>([])
|
const results = ref<(Element | ComponentPublicInstance)[]>([])
|
||||||
|
|
||||||
function setResult(el: Element | ComponentPublicInstance | null, index: number) {
|
function setResult(el: Element | ComponentPublicInstance | null, index: number) {
|
||||||
if (el === null) {
|
if (el === null) {
|
||||||
delete results.value[index]
|
delete results.value[index]
|
||||||
@ -416,7 +431,7 @@ function createOrSelectOnEnter() {
|
|||||||
if (!creatableAvailable.value) {
|
if (!creatableAvailable.value) {
|
||||||
// Check if there's an exact match for our search term
|
// Check if there's an exact match for our search term
|
||||||
const exactMatch = filteredSearchResults.value.find((elem: any) => elementInResults(elem, props.label, query.value))
|
const exactMatch = filteredSearchResults.value.find((elem: any) => elementInResults(elem, props.label, query.value))
|
||||||
if(exactMatch) {
|
if (exactMatch) {
|
||||||
select(exactMatch)
|
select(exactMatch)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -572,4 +587,14 @@ function focus() {
|
|||||||
transition: color $transition;
|
transition: color $transition;
|
||||||
padding-left: .5rem;
|
padding-left: .5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.has-removal-button {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.removal-button {
|
||||||
|
position: absolute;
|
||||||
|
right: .5rem;
|
||||||
|
color: var(--danger);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
@ -70,11 +70,11 @@ function findProjects(query: string) {
|
|||||||
foundProjects.value = projectStore.searchProject(query)
|
foundProjects.value = projectStore.searchProject(query)
|
||||||
}
|
}
|
||||||
|
|
||||||
function select(l: IProject | null) {
|
function select(p: IProject | null) {
|
||||||
if (l === null) {
|
if (p === null) {
|
||||||
return
|
Object.assign(project, {id: 0})
|
||||||
}
|
}
|
||||||
Object.assign(project, l)
|
Object.assign(project, p)
|
||||||
emit('update:modelValue', project)
|
emit('update:modelValue', project)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user