models, messages and multiselects

This commit is contained in:
vabene1111
2024-05-01 10:04:19 +02:00
parent 32b75250dc
commit 569b7e78fe
13 changed files with 607 additions and 226 deletions

View File

@@ -1,98 +1,117 @@
<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>
<!-- &lt;!&ndash;TODO Problems: 1. behind other cards when those are underneath the element, making card overflow visible breaks cards &ndash;&gt;-->
<!-- <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"-->
<!-- class="material-multiselect"-->
<!-- >-->
<!-- </VueMultiselect>-->
<Multiselect
class="material-multiselect z-max"
v-model="model"
:options="search"
:delay="300"
:object="true"
valueProp="id"
:label="label"
:searchable="true"
:strict="false"
:disabled="disabled"
/>
</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'
import {computed, onMounted, PropType, ref, Ref} from "vue"
import {ApiApi} from "@/openapi/index.js"
import {useDebounceFn} from "@vueuse/core"
import {GenericModel, getModelFromStr} from "@/types/Models"
import Multiselect from '@vueform/multiselect'
const props = defineProps(
{
model: {type: String, required: true},
multiple: {type: Boolean, default: true},
limit: {type: Number, default: 25},
allowCreate: {type: Boolean, default: false},
const emit = defineEmits(['update:modelValue'])
id: {type: String, required: false, default: Math.random().toString()},
const props = defineProps({
model: {type: String, required: true},
// not verified
search_on_load: {type: Boolean, default: false},
id: {type: String, required: false, default: Math.random().toString()},
// not verified
clearable: {type: Boolean, default: false,},
chips: {type: Boolean, default: undefined,},
multiple: {type: Boolean, default: true},
limit: {type: Number, default: 25},
allowCreate: {type: Boolean, default: false},
itemName: {type: String, default: 'name'},
itemValue: {type: String, default: 'id'},
search_on_load: {type: Boolean, default: false},
clearable: {type: Boolean, default: false},
chips: {type: Boolean, default: undefined},
placeholder: {type: String, default: undefined},
label: {type: String, default: "name"},
parent_variable: {type: String, default: undefined},
itemName: {type: String, default: "name"},
itemValue: {type: String, default: "id"},
sticky_options: {
type: Array,
default() {
return []
},
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,
},
initial_selection: {
type: Array,
default() {
return []
},
},
initial_single_selection: {
type: Object,
default: undefined,
},
disabled: {type: Boolean, default: false},
})
disabled: {type: Boolean, default: false,},
}
)
const model = defineModel()
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_query = ref("")
const search_loading = ref(false)
const elementId = ref((Math.random() * 100000).toString())
onMounted(() => {
model_class.value = getModelFromStr(props.model)
if (props.search_on_load) {
debouncedSearchFunction('')
debouncedSearchFunction("")
}
})
@@ -108,16 +127,9 @@ const debouncedSearchFunction = useDebounceFn((query: string) => {
* @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 => {
return model_class.value.list(query).then((r) => {
return r
}).catch((err) => {
//useMessageStore().addMessage(MessageType.ERROR, err, 8000)
}).finally(() => {
search_loading.value = false
@@ -129,7 +141,7 @@ function addItem(item: string) {
const api = new ApiApi()
api.apiKeywordList()
model_class.value.create(item).then(createdObj => {
model_class.value.create(item).then((createdObj) => {
//StandardToasts.makeStandardToast(this, StandardToasts.SUCCESS_CREATE)
if (selected_items.value instanceof Array) {
selected_items.value.push(createdObj)
@@ -146,12 +158,19 @@ function addItem(item: string) {
}
function selectionChanged() {
//this.$emit("change", { var: this.parent_variable, val: this.selected_objects })
emit('update:modelValue', selected_items)
}
</script>
<style src="vue-multiselect/dist/vue-multiselect.css"></style>
<style src="@vueform/multiselect/themes/default.css"></style>
<style scoped>
</style>
.material-multiselect {
--ms-line-height: 2.5;
--ms-bg: rgba(235, 235, 235, 0.75);
--ms-border-color: 0;
--ms-border-color-active: 0;
border-bottom: 4px #0f0f0f;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
</style>