mirror of
https://github.com/TandoorRecipes/recipes.git
synced 2026-01-01 20:28:46 -05:00
157 lines
4.4 KiB
Vue
157 lines
4.4 KiB
Vue
<template>
|
|
<v-input>
|
|
<!--TODO Problems: 1. behind other cards when those are underneath the element, making card overflow visible breaks cards -->
|
|
<VueMultiselect
|
|
:id="id"
|
|
v-model="selected_items"
|
|
:options="items"
|
|
:close-on-select="true"
|
|
:clear-on-select="true"
|
|
:hide-selected="multiple"
|
|
:preserve-search="true"
|
|
:internal-search="false"
|
|
:limit="limit"
|
|
:placeholder="model"
|
|
:label="label"
|
|
track-by="id"
|
|
:multiple="multiple"
|
|
:taggable="allowCreate"
|
|
tag-placeholder="TODO CREATE PLACEHOLDER"
|
|
:loading="search_loading"
|
|
@search-change="debouncedSearchFunction"
|
|
@input="selectionChanged"
|
|
@tag="addItem"
|
|
@open="search('')"
|
|
:disabled="disabled"
|
|
>
|
|
</VueMultiselect>
|
|
</v-input>
|
|
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import {computed, onMounted, ref, Ref,} from 'vue'
|
|
import {ApiApi} from "@/openapi/index.js";
|
|
import {useDebounceFn} from "@vueuse/core";
|
|
import {GenericModel, getModelFromStr} from "@/types/Models";
|
|
import VueMultiselect from 'vue-multiselect'
|
|
|
|
const props = defineProps(
|
|
{
|
|
model: {type: String, required: true},
|
|
multiple: {type: Boolean, default: true},
|
|
limit: {type: Number, default: 25},
|
|
allowCreate: {type: Boolean, default: false},
|
|
|
|
id: {type: String, required: false, default: Math.random().toString()},
|
|
|
|
// not verified
|
|
search_on_load: {type: Boolean, default: false},
|
|
|
|
|
|
clearable: {type: Boolean, default: false,},
|
|
chips: {type: Boolean, default: undefined,},
|
|
|
|
itemName: {type: String, default: 'name'},
|
|
itemValue: {type: String, default: 'id'},
|
|
|
|
|
|
placeholder: {type: String, default: undefined},
|
|
label: {type: String, default: "name"},
|
|
parent_variable: {type: String, default: undefined},
|
|
|
|
sticky_options: {
|
|
type: Array,
|
|
default() {
|
|
return []
|
|
},
|
|
},
|
|
initial_selection: {
|
|
type: Array,
|
|
default() {
|
|
return []
|
|
},
|
|
},
|
|
initial_single_selection: {
|
|
type: Object,
|
|
default: undefined,
|
|
},
|
|
|
|
|
|
disabled: {type: Boolean, default: false,},
|
|
}
|
|
)
|
|
|
|
const model_class = ref({} as GenericModel<any>)
|
|
const items: Ref<Array<any>> = ref([])
|
|
const selected_items: Ref<Array<any> | any> = ref(undefined)
|
|
const search_query = ref('')
|
|
const search_loading = ref(false)
|
|
|
|
|
|
onMounted(() => {
|
|
model_class.value = getModelFromStr(props.model)
|
|
if (props.search_on_load) {
|
|
debouncedSearchFunction('')
|
|
}
|
|
})
|
|
|
|
/**
|
|
* debounced search function bound to search input changing
|
|
*/
|
|
const debouncedSearchFunction = useDebounceFn((query: string) => {
|
|
search(query)
|
|
}, 300)
|
|
|
|
/**
|
|
* performs the API request to search for the selected input
|
|
* @param query input to search for on the API
|
|
*/
|
|
function search(query: string) {
|
|
|
|
search_loading.value = true
|
|
model_class.value.list(query).then(r => {
|
|
items.value = r
|
|
if (props.allowCreate && search_query.value != '') {
|
|
// TODO check if search_query is already in items
|
|
items.value.unshift({id: null, name: `Create "${search_query.value}"`})
|
|
}
|
|
|
|
}).catch(err => {
|
|
//useMessageStore().addMessage(MessageType.ERROR, err, 8000)
|
|
}).finally(() => {
|
|
search_loading.value = false
|
|
})
|
|
}
|
|
|
|
function addItem(item: string) {
|
|
console.log("CREATEING NEW with -> ", item)
|
|
const api = new ApiApi()
|
|
api.apiKeywordList()
|
|
|
|
model_class.value.create(item).then(createdObj => {
|
|
//StandardToasts.makeStandardToast(this, StandardToasts.SUCCESS_CREATE)
|
|
if (selected_items.value instanceof Array) {
|
|
selected_items.value.push(createdObj)
|
|
} else {
|
|
selected_items.value = createdObj
|
|
}
|
|
items.value.push(createdObj)
|
|
selectionChanged()
|
|
}).catch((err) => {
|
|
//StandardToasts.makeStandardToast(this, StandardToasts.FAIL_CREATE)
|
|
}).finally(() => {
|
|
search_loading.value = false
|
|
})
|
|
}
|
|
|
|
function selectionChanged() {
|
|
//this.$emit("change", { var: this.parent_variable, val: this.selected_objects })
|
|
}
|
|
|
|
</script>
|
|
|
|
<style src="vue-multiselect/dist/vue-multiselect.css"></style>
|
|
<style scoped>
|
|
|
|
</style> |