@ramathibodi/nuxt-commons 0.1.71 → 0.1.73
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/module.json +1 -1
- package/dist/runtime/components/form/System.vue +27 -0
- package/dist/runtime/components/master/Autocomplete.vue +10 -0
- package/dist/runtime/components/master/Combobox.vue +11 -1
- package/dist/runtime/components/master/Select.vue +10 -1
- package/dist/runtime/components/master/label.vue +5 -1
- package/dist/runtime/components/model/Autocomplete.vue +11 -4
- package/dist/runtime/components/model/Combobox.vue +10 -4
- package/dist/runtime/components/model/Select.vue +12 -4
- package/dist/runtime/components/model/label.vue +7 -1
- package/dist/runtime/composables/lookupList.d.ts +12 -5
- package/dist/runtime/composables/lookupList.js +71 -21
- package/dist/runtime/composables/lookupListMaster.d.ts +4 -0
- package/dist/runtime/composables/lookupListMaster.js +9 -4
- package/package.json +1 -1
package/dist/module.json
CHANGED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import Pad from './Pad.vue'
|
|
3
|
+
import { watch } from 'vue'
|
|
4
|
+
import { useGraphQlOperation } from '../../composables/graphqlOperation'
|
|
5
|
+
|
|
6
|
+
interface Props extends /* @vue-ignore */ InstanceType<typeof Pad['$props']> {
|
|
7
|
+
templateId: string;
|
|
8
|
+
cache?: boolean | number
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const props = withDefaults(defineProps<Props>(),{
|
|
12
|
+
cache: false
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
const currentTemplate = ref<any>({})
|
|
16
|
+
|
|
17
|
+
watch(()=>props.templateId, (newValue) => {
|
|
18
|
+
useGraphQlOperation("Query","systemTemplateById",["template","templateScript"],{id: newValue},props.cache).then(result => {
|
|
19
|
+
currentTemplate.value = result
|
|
20
|
+
}).catch(_error => {
|
|
21
|
+
currentTemplate.value = {}
|
|
22
|
+
})
|
|
23
|
+
})
|
|
24
|
+
</script>
|
|
25
|
+
<template>
|
|
26
|
+
<FormPad v-bind="$attrs" :template="currentTemplate.template" :template-script="currentTemplate.templateScript" />
|
|
27
|
+
</template>
|
|
@@ -13,6 +13,11 @@ const props = withDefaults(defineProps<Props & MasterLikeProps>(), {
|
|
|
13
13
|
waitForFilter: false,
|
|
14
14
|
meilisearch: false,
|
|
15
15
|
cache: false,
|
|
16
|
+
|
|
17
|
+
statusField: 'statusCode',
|
|
18
|
+
activeValue: 'active',
|
|
19
|
+
hideInactiveInList: true,
|
|
20
|
+
preventSelectingInactive: true,
|
|
16
21
|
})
|
|
17
22
|
|
|
18
23
|
const {
|
|
@@ -43,6 +48,11 @@ const {
|
|
|
43
48
|
model-selected-item="masterItemByGroupKeyAndItemCodeIn"
|
|
44
49
|
:model-selected-item-by="computedModelSelectedItemBy"
|
|
45
50
|
model-selected-item-key="itemCodes"
|
|
51
|
+
|
|
52
|
+
:status-field="props.statusField"
|
|
53
|
+
:active-value="props.activeValue"
|
|
54
|
+
:hide-inactive-in-list="props.hideInactiveInList"
|
|
55
|
+
:prevent-selecting-inactive="props.preventSelectingInactive"
|
|
46
56
|
>
|
|
47
57
|
<!-- pass-through slots -->
|
|
48
58
|
<!-- @ts-ignore -->
|
|
@@ -13,6 +13,11 @@ const props = withDefaults(defineProps<Props & MasterLikeProps>(), {
|
|
|
13
13
|
waitForFilter: false,
|
|
14
14
|
meilisearch: false,
|
|
15
15
|
cache: false,
|
|
16
|
+
|
|
17
|
+
statusField: 'statusCode',
|
|
18
|
+
activeValue: 'active',
|
|
19
|
+
hideInactiveInList: true,
|
|
20
|
+
preventSelectingInactive: true,
|
|
16
21
|
})
|
|
17
22
|
|
|
18
23
|
const {
|
|
@@ -43,6 +48,11 @@ const {
|
|
|
43
48
|
model-selected-item="masterItemByGroupKeyAndItemCodeIn"
|
|
44
49
|
:model-selected-item-by="computedModelSelectedItemBy"
|
|
45
50
|
model-selected-item-key="itemCodes"
|
|
51
|
+
|
|
52
|
+
:status-field="props.statusField"
|
|
53
|
+
:active-value="props.activeValue"
|
|
54
|
+
:hide-inactive-in-list="props.hideInactiveInList"
|
|
55
|
+
:prevent-selecting-inactive="props.preventSelectingInactive"
|
|
46
56
|
>
|
|
47
57
|
<!-- pass-through slots -->
|
|
48
58
|
<!-- @ts-ignore -->
|
|
@@ -70,4 +80,4 @@ const {
|
|
|
70
80
|
|
|
71
81
|
<style>
|
|
72
82
|
.meilisearch-item em{font-weight:700}
|
|
73
|
-
</style>
|
|
83
|
+
</style>
|
|
@@ -12,6 +12,11 @@ const props = withDefaults(defineProps<Props & StaticMasterLikeProps>(), {
|
|
|
12
12
|
noDataText: 'ไม่พบข้อมูล',
|
|
13
13
|
waitForFilter: false,
|
|
14
14
|
cache: false,
|
|
15
|
+
|
|
16
|
+
statusField: 'statusCode',
|
|
17
|
+
activeValue: 'active',
|
|
18
|
+
hideInactiveInList: true,
|
|
19
|
+
preventSelectingInactive: true,
|
|
15
20
|
})
|
|
16
21
|
|
|
17
22
|
const {
|
|
@@ -36,6 +41,10 @@ const {
|
|
|
36
41
|
:no-data-text="computedNoDataText"
|
|
37
42
|
:show-code="props.showCode"
|
|
38
43
|
:cache="props.cache"
|
|
44
|
+
:status-field="props.statusField"
|
|
45
|
+
:active-value="props.activeValue"
|
|
46
|
+
:hide-inactive-in-list="props.hideInactiveInList"
|
|
47
|
+
:prevent-selecting-inactive="props.preventSelectingInactive"
|
|
39
48
|
>
|
|
40
49
|
<!-- pass-through slots -->
|
|
41
50
|
<!-- @ts-ignore -->
|
|
@@ -51,4 +60,4 @@ const {
|
|
|
51
60
|
{{ formatItemTitle(item) }}
|
|
52
61
|
</template>
|
|
53
62
|
</model-combobox>
|
|
54
|
-
</template>
|
|
63
|
+
</template>
|
|
@@ -39,5 +39,9 @@ const computedItemTitle = computed(()=>{
|
|
|
39
39
|
:not-found-text="computedNotFoundText"
|
|
40
40
|
:placeholder="computedPlaceholder"
|
|
41
41
|
:cache="props.cache"
|
|
42
|
-
|
|
42
|
+
>
|
|
43
|
+
<template v-for="(_, name, index) in ($slots as {})" :key="index" #[name]="slotData">
|
|
44
|
+
<slot :name="name" v-bind="((slotData || {}) as object)" />
|
|
45
|
+
</template>
|
|
46
|
+
</model-label>
|
|
43
47
|
</template>
|
|
@@ -10,11 +10,17 @@ const props = withDefaults(defineProps<Props & LookupProps & PersistSlimProps>()
|
|
|
10
10
|
fuzzy: false,
|
|
11
11
|
showCode: false,
|
|
12
12
|
cache: false,
|
|
13
|
+
|
|
13
14
|
serverSearch: false,
|
|
14
15
|
searchSearchSort: false,
|
|
15
16
|
serverSearchText: 'Type to search…',
|
|
16
17
|
serverSearchLoadingText: 'Searching…',
|
|
17
18
|
serverSearchDebounce: 500,
|
|
19
|
+
|
|
20
|
+
statusField: 'statusCode',
|
|
21
|
+
activeValue: 'active',
|
|
22
|
+
hideInactiveInList: false,
|
|
23
|
+
preventSelectingInactive: false,
|
|
18
24
|
})
|
|
19
25
|
|
|
20
26
|
const emit = defineEmits<{
|
|
@@ -22,8 +28,7 @@ const emit = defineEmits<{
|
|
|
22
28
|
}>()
|
|
23
29
|
|
|
24
30
|
const selectedItems = defineModel<any>()
|
|
25
|
-
|
|
26
|
-
useLocalStorageModel(selectedItems,props)
|
|
31
|
+
useLocalStorageModel(selectedItems, props)
|
|
27
32
|
|
|
28
33
|
const {
|
|
29
34
|
searchData,
|
|
@@ -33,12 +38,14 @@ const {
|
|
|
33
38
|
computedNoDataText,
|
|
34
39
|
isLoading,
|
|
35
40
|
isErrorLoading,
|
|
36
|
-
|
|
41
|
+
onUpdateModelValue, // ✅ moved into composable
|
|
42
|
+
} = useLookupList(props as any, emit, selectedItems)
|
|
37
43
|
</script>
|
|
38
44
|
|
|
39
45
|
<template>
|
|
40
46
|
<v-autocomplete
|
|
41
|
-
|
|
47
|
+
:model-value="selectedItems"
|
|
48
|
+
@update:model-value="onUpdateModelValue"
|
|
42
49
|
v-model:search="searchData"
|
|
43
50
|
v-bind="$attrs"
|
|
44
51
|
:items="computedItems"
|
|
@@ -15,6 +15,11 @@ const props = withDefaults(defineProps<Props & LookupProps & PersistSlimProps>()
|
|
|
15
15
|
serverSearchText: 'Type to search…',
|
|
16
16
|
serverSearchLoadingText: 'Searching…',
|
|
17
17
|
serverSearchDebounce: 500,
|
|
18
|
+
|
|
19
|
+
statusField: 'statusCode',
|
|
20
|
+
activeValue: 'active',
|
|
21
|
+
hideInactiveInList: false,
|
|
22
|
+
preventSelectingInactive: false,
|
|
18
23
|
})
|
|
19
24
|
|
|
20
25
|
const emit = defineEmits<{
|
|
@@ -22,8 +27,7 @@ const emit = defineEmits<{
|
|
|
22
27
|
}>()
|
|
23
28
|
|
|
24
29
|
const selectedItems = defineModel<any>()
|
|
25
|
-
|
|
26
|
-
useLocalStorageModel(selectedItems,props)
|
|
30
|
+
useLocalStorageModel(selectedItems, props)
|
|
27
31
|
|
|
28
32
|
const {
|
|
29
33
|
searchData,
|
|
@@ -33,12 +37,14 @@ const {
|
|
|
33
37
|
computedNoDataText,
|
|
34
38
|
isLoading,
|
|
35
39
|
isErrorLoading,
|
|
36
|
-
|
|
40
|
+
onUpdateModelValue, // ✅ from composable
|
|
41
|
+
} = useLookupList(props as any, emit, selectedItems)
|
|
37
42
|
</script>
|
|
38
43
|
|
|
39
44
|
<template>
|
|
40
45
|
<v-combobox
|
|
41
|
-
|
|
46
|
+
:model-value="selectedItems"
|
|
47
|
+
@update:model-value="onUpdateModelValue"
|
|
42
48
|
v-model:search="searchData"
|
|
43
49
|
v-bind="$attrs"
|
|
44
50
|
:items="computedItems"
|
|
@@ -10,6 +10,11 @@ const props = withDefaults(defineProps<Props & StaticLookupProps & PersistSlimPr
|
|
|
10
10
|
fuzzy: false,
|
|
11
11
|
showCode: false,
|
|
12
12
|
cache: false,
|
|
13
|
+
|
|
14
|
+
statusField: 'statusCode',
|
|
15
|
+
activeValue: 'active',
|
|
16
|
+
hideInactiveInList: false,
|
|
17
|
+
preventSelectingInactive: false,
|
|
13
18
|
})
|
|
14
19
|
|
|
15
20
|
const emit = defineEmits<{
|
|
@@ -17,8 +22,7 @@ const emit = defineEmits<{
|
|
|
17
22
|
}>()
|
|
18
23
|
|
|
19
24
|
const selectedItems = defineModel<any>()
|
|
20
|
-
|
|
21
|
-
useLocalStorageModel(selectedItems,props)
|
|
25
|
+
useLocalStorageModel(selectedItems, props)
|
|
22
26
|
|
|
23
27
|
const {
|
|
24
28
|
computedItems,
|
|
@@ -27,12 +31,16 @@ const {
|
|
|
27
31
|
computedNoDataText,
|
|
28
32
|
isLoading,
|
|
29
33
|
isErrorLoading,
|
|
30
|
-
|
|
34
|
+
searchData,
|
|
35
|
+
onUpdateModelValue, // ✅ from composable
|
|
36
|
+
} = useLookupList(props as any, emit, selectedItems)
|
|
31
37
|
</script>
|
|
32
38
|
|
|
33
39
|
<template>
|
|
34
40
|
<v-combobox
|
|
35
|
-
|
|
41
|
+
:model-value="selectedItems"
|
|
42
|
+
@update:model-value="onUpdateModelValue"
|
|
43
|
+
v-model:search="searchData"
|
|
36
44
|
v-bind="$attrs"
|
|
37
45
|
:items="computedItems"
|
|
38
46
|
:filter-keys="computedFilterKeys"
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { computedAsync } from '@vueuse/core'
|
|
3
3
|
import { useGraphQlOperation } from '../../composables/graphqlOperation'
|
|
4
4
|
import { concat } from "lodash-es";
|
|
5
|
+
import { ref } from 'vue'
|
|
5
6
|
|
|
6
7
|
interface Props {
|
|
7
8
|
modelName: string
|
|
@@ -18,6 +19,8 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
18
19
|
cache: false,
|
|
19
20
|
})
|
|
20
21
|
|
|
22
|
+
const modelItem = ref<Record<string, any>>({})
|
|
23
|
+
|
|
21
24
|
const modelItemValue = computedAsync<string>(async () => {
|
|
22
25
|
if (props.modelName && props.itemTitle) {
|
|
23
26
|
let fields: any[] = (typeof props.itemTitle === "string") ? [props.itemTitle] : []
|
|
@@ -28,6 +31,7 @@ const modelItemValue = computedAsync<string>(async () => {
|
|
|
28
31
|
|
|
29
32
|
try {
|
|
30
33
|
if (result) {
|
|
34
|
+
modelItem.value = result
|
|
31
35
|
if (typeof props.itemTitle === "string") return result[props.itemTitle]
|
|
32
36
|
else return props.itemTitle(result)
|
|
33
37
|
}
|
|
@@ -40,5 +44,7 @@ const modelItemValue = computedAsync<string>(async () => {
|
|
|
40
44
|
</script>
|
|
41
45
|
|
|
42
46
|
<template>
|
|
43
|
-
<
|
|
47
|
+
<slot name="default" :data="modelItem">
|
|
48
|
+
<span>{{ modelItemValue }}</span>
|
|
49
|
+
</slot>
|
|
44
50
|
</template>
|
|
@@ -13,6 +13,10 @@ export interface StaticLookupProps {
|
|
|
13
13
|
noDataText?: string;
|
|
14
14
|
placeholder?: string;
|
|
15
15
|
multiple?: boolean;
|
|
16
|
+
statusField?: string;
|
|
17
|
+
activeValue?: any;
|
|
18
|
+
hideInactiveInList?: boolean;
|
|
19
|
+
preventSelectingInactive?: boolean;
|
|
16
20
|
}
|
|
17
21
|
export interface LookupProps extends StaticLookupProps {
|
|
18
22
|
serverSearch?: boolean;
|
|
@@ -28,9 +32,9 @@ export interface LookupProps extends StaticLookupProps {
|
|
|
28
32
|
export interface LookupEmits {
|
|
29
33
|
(e: 'update:selectedObject', payload: any | any[]): void;
|
|
30
34
|
}
|
|
31
|
-
export declare function useLookupList(props: LookupProps, emit: LookupEmits, selectedItems: Ref<any>): {
|
|
32
|
-
modelItems:
|
|
33
|
-
items:
|
|
35
|
+
export declare function useLookupList<T extends Record<string, any>>(props: LookupProps, emit: LookupEmits, selectedItems: Ref<any>): {
|
|
36
|
+
modelItems: import("vue").ShallowRef<T[], T[]>;
|
|
37
|
+
items: import("vue").ShallowRef<T[], T[]>;
|
|
34
38
|
searchData: Ref<string, string>;
|
|
35
39
|
isLoading: Ref<boolean, boolean>;
|
|
36
40
|
isErrorLoading: Ref<boolean, boolean>;
|
|
@@ -38,9 +42,12 @@ export declare function useLookupList(props: LookupProps, emit: LookupEmits, sel
|
|
|
38
42
|
computedFilterKeys: import("vue").ComputedRef<string | string[]>;
|
|
39
43
|
computedPlaceholder: import("vue").ComputedRef<string | undefined>;
|
|
40
44
|
computedNoDataText: import("vue").ComputedRef<string | undefined>;
|
|
41
|
-
computedItems: import("vue").ComputedRef<
|
|
42
|
-
selectedItemsObject:
|
|
45
|
+
computedItems: import("vue").ComputedRef<T[]>;
|
|
46
|
+
selectedItemsObject: import("vue").ShallowRef<T[], T[]>;
|
|
43
47
|
syncSelectedFromModelValue: () => Promise<void>;
|
|
48
|
+
isSelectableValue: (value: any) => boolean;
|
|
49
|
+
setModelValueGuarded: (val: any) => void;
|
|
50
|
+
onUpdateModelValue: (val: any) => void;
|
|
44
51
|
loadItems: () => Promise<void>;
|
|
45
52
|
applyFuzzy: () => void;
|
|
46
53
|
};
|
|
@@ -1,17 +1,24 @@
|
|
|
1
|
-
import { computed, ref, watch } from "vue";
|
|
1
|
+
import { computed, ref, shallowRef, watch } from "vue";
|
|
2
2
|
import { watchDebounced } from "@vueuse/core";
|
|
3
3
|
import { union, isEmpty, isArray, sortBy, castArray } from "lodash-es";
|
|
4
4
|
import { useFuzzy } from "./utils/fuzzy.js";
|
|
5
5
|
import { useGraphQlOperation } from "./graphqlOperation.js";
|
|
6
6
|
export function useLookupList(props, emit, selectedItems) {
|
|
7
|
-
const modelItems =
|
|
8
|
-
const items =
|
|
7
|
+
const modelItems = shallowRef([]);
|
|
8
|
+
const items = shallowRef([]);
|
|
9
|
+
const selectedItemsObject = shallowRef([]);
|
|
9
10
|
const searchData = ref("");
|
|
10
11
|
const isLoading = ref(false);
|
|
11
12
|
const isErrorLoading = ref(false);
|
|
13
|
+
const statusField = computed(() => props.statusField ?? "statusCode");
|
|
14
|
+
const activeValue = computed(() => props.activeValue ?? "active");
|
|
15
|
+
const hideInactiveInList = computed(() => props.hideInactiveInList ?? false);
|
|
12
16
|
const queryFields = computed(() => {
|
|
13
17
|
let fieldsArray = [props.itemTitle, props.itemValue];
|
|
14
18
|
if (props.fields) fieldsArray = union(fieldsArray, props.fields);
|
|
19
|
+
if (hideInactiveInList.value && statusField.value) {
|
|
20
|
+
fieldsArray = union(fieldsArray, [statusField.value]);
|
|
21
|
+
}
|
|
15
22
|
return fieldsArray;
|
|
16
23
|
});
|
|
17
24
|
const computedFilterKeys = computed(() => {
|
|
@@ -59,7 +66,7 @@ export function useLookupList(props, emit, selectedItems) {
|
|
|
59
66
|
modelItems.value = [];
|
|
60
67
|
items.value = [];
|
|
61
68
|
}
|
|
62
|
-
} catch
|
|
69
|
+
} catch {
|
|
63
70
|
if (id !== requestId) return;
|
|
64
71
|
isErrorLoading.value = true;
|
|
65
72
|
modelItems.value = [];
|
|
@@ -84,7 +91,13 @@ export function useLookupList(props, emit, selectedItems) {
|
|
|
84
91
|
}
|
|
85
92
|
items.value = output;
|
|
86
93
|
}
|
|
87
|
-
const
|
|
94
|
+
const itemMap = computed(() => {
|
|
95
|
+
const m = /* @__PURE__ */ new Map();
|
|
96
|
+
for (const it of modelItems.value) {
|
|
97
|
+
m.set(it?.[props.itemValue], it);
|
|
98
|
+
}
|
|
99
|
+
return m;
|
|
100
|
+
});
|
|
88
101
|
async function syncSelectedFromModelValue() {
|
|
89
102
|
const modelValueData = selectedItems.value;
|
|
90
103
|
const values = castArray(modelValueData).filter(
|
|
@@ -95,24 +108,24 @@ export function useLookupList(props, emit, selectedItems) {
|
|
|
95
108
|
selectedItemsObject.value = [];
|
|
96
109
|
return;
|
|
97
110
|
}
|
|
98
|
-
|
|
99
|
-
const haveSet =
|
|
100
|
-
const missingValues = values.filter((
|
|
111
|
+
const alreadyInObject = selectedItemsObject.value?.filter((it) => values.includes(it?.[props.itemValue])) || [];
|
|
112
|
+
const haveSet = new Set(alreadyInObject.map((it) => it?.[props.itemValue]));
|
|
113
|
+
const missingValues = values.filter((v) => !haveSet.has(v));
|
|
101
114
|
const stillMissing = [];
|
|
102
|
-
for (const
|
|
103
|
-
const localHit =
|
|
115
|
+
for (const v of missingValues) {
|
|
116
|
+
const localHit = itemMap.value.get(v);
|
|
104
117
|
if (localHit) {
|
|
105
118
|
alreadyInObject.push(localHit);
|
|
106
|
-
haveSet.add(
|
|
119
|
+
haveSet.add(v);
|
|
107
120
|
} else {
|
|
108
|
-
stillMissing.push(
|
|
121
|
+
stillMissing.push(v);
|
|
109
122
|
}
|
|
110
123
|
}
|
|
111
124
|
if (stillMissing.length && props.modelSelectedItem) {
|
|
112
125
|
try {
|
|
113
126
|
const key = props.modelSelectedItemKey || "id";
|
|
114
127
|
const variables = { ...props.modelSelectedItemBy || {} };
|
|
115
|
-
variables[key] =
|
|
128
|
+
variables[key] = stillMissing;
|
|
116
129
|
const result = await useGraphQlOperation(
|
|
117
130
|
"Query",
|
|
118
131
|
props.modelSelectedItem,
|
|
@@ -120,13 +133,19 @@ export function useLookupList(props, emit, selectedItems) {
|
|
|
120
133
|
variables,
|
|
121
134
|
props.cache
|
|
122
135
|
);
|
|
123
|
-
|
|
136
|
+
const resolved = castArray(result);
|
|
137
|
+
for (const obj of resolved) {
|
|
138
|
+
const v = obj?.[props.itemValue];
|
|
139
|
+
if (!haveSet.has(v)) {
|
|
140
|
+
alreadyInObject.push(obj);
|
|
141
|
+
haveSet.add(v);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
124
144
|
} catch {
|
|
125
145
|
}
|
|
126
|
-
} else {
|
|
127
|
-
selectedItemsObject.value = alreadyInObject;
|
|
128
146
|
}
|
|
129
|
-
|
|
147
|
+
selectedItemsObject.value = alreadyInObject;
|
|
148
|
+
emit("update:selectedObject", props.multiple ? alreadyInObject : alreadyInObject[0]);
|
|
130
149
|
}
|
|
131
150
|
watchDebounced(
|
|
132
151
|
() => [
|
|
@@ -159,18 +178,44 @@ export function useLookupList(props, emit, selectedItems) {
|
|
|
159
178
|
() => {
|
|
160
179
|
syncSelectedFromModelValue();
|
|
161
180
|
},
|
|
162
|
-
{ immediate: true
|
|
181
|
+
{ immediate: true }
|
|
163
182
|
);
|
|
164
183
|
const computedItems = computed(() => {
|
|
165
184
|
const sortByField = !props.sortBy || typeof props.sortBy === "string" ? [props.sortBy || (props.showCode ? props.itemValue : props.itemTitle)] : props.sortBy;
|
|
166
|
-
const
|
|
185
|
+
const baseSource = (props.fuzzy || props.serverSearch && !props.searchSearchSort) && !isEmpty(searchData.value) ? items.value : sortBy(items.value, sortByField);
|
|
186
|
+
let baseItems = [...baseSource];
|
|
187
|
+
if (hideInactiveInList.value) {
|
|
188
|
+
baseItems = baseItems.filter((it) => it?.[statusField.value] === activeValue.value);
|
|
189
|
+
}
|
|
167
190
|
for (const selectedItem of selectedItemsObject.value || []) {
|
|
168
|
-
|
|
191
|
+
const v = selectedItem?.[props.itemValue];
|
|
192
|
+
if (!baseItems.find((x) => x?.[props.itemValue] === v)) {
|
|
169
193
|
baseItems.push(selectedItem);
|
|
170
194
|
}
|
|
171
195
|
}
|
|
172
196
|
return baseItems;
|
|
173
197
|
});
|
|
198
|
+
function isSelectableValue(value) {
|
|
199
|
+
if (!hideInactiveInList.value) return true;
|
|
200
|
+
const local = itemMap.value.get(value);
|
|
201
|
+
const obj = local ?? selectedItemsObject.value.find((it) => it?.[props.itemValue] === value) ?? modelItems.value.find((it) => it?.[props.itemValue] === value);
|
|
202
|
+
if (!obj) return true;
|
|
203
|
+
return obj?.[statusField.value] === activeValue.value;
|
|
204
|
+
}
|
|
205
|
+
function setModelValueGuarded(val) {
|
|
206
|
+
if (!(props.preventSelectingInactive ?? false)) {
|
|
207
|
+
selectedItems.value = val;
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
if (!props.multiple) {
|
|
211
|
+
if (val != null && !isSelectableValue(val)) return;
|
|
212
|
+
selectedItems.value = val;
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
const arr = Array.isArray(val) ? val : [];
|
|
216
|
+
selectedItems.value = arr.filter((v) => isSelectableValue(v));
|
|
217
|
+
}
|
|
218
|
+
const onUpdateModelValue = (val) => setModelValueGuarded(val);
|
|
174
219
|
return {
|
|
175
220
|
// state
|
|
176
221
|
modelItems,
|
|
@@ -187,7 +232,12 @@ export function useLookupList(props, emit, selectedItems) {
|
|
|
187
232
|
// selection
|
|
188
233
|
selectedItemsObject,
|
|
189
234
|
syncSelectedFromModelValue,
|
|
190
|
-
//
|
|
235
|
+
// selection policy helper
|
|
236
|
+
isSelectableValue,
|
|
237
|
+
// guarded setter for v-model updates
|
|
238
|
+
setModelValueGuarded,
|
|
239
|
+
onUpdateModelValue,
|
|
240
|
+
// actions
|
|
191
241
|
loadItems,
|
|
192
242
|
applyFuzzy
|
|
193
243
|
};
|
|
@@ -12,6 +12,10 @@ export interface StaticMasterLikeProps {
|
|
|
12
12
|
waitForFilter?: boolean;
|
|
13
13
|
waitForFilterText?: string;
|
|
14
14
|
cache?: boolean | number;
|
|
15
|
+
statusField?: string;
|
|
16
|
+
activeValue?: any;
|
|
17
|
+
hideInactiveInList?: boolean;
|
|
18
|
+
preventSelectingInactive?: boolean;
|
|
15
19
|
}
|
|
16
20
|
export interface MasterLikeProps extends StaticMasterLikeProps {
|
|
17
21
|
meilisearch?: boolean;
|
|
@@ -16,13 +16,20 @@ export function useLookupListMaster(props) {
|
|
|
16
16
|
return modelBy;
|
|
17
17
|
});
|
|
18
18
|
const computedModelSelectedItemBy = computed(() => ({ groupKey: props.groupKey }));
|
|
19
|
+
const itemTitleField = computed(() => props.lang === "TH" ? "itemValue" : "itemValueAlternative");
|
|
19
20
|
const computedFields = computed(() => {
|
|
20
21
|
const extra = [];
|
|
21
22
|
if (props.filterText) extra.push("filterText");
|
|
22
23
|
if (props.meilisearch) extra.push("_formatted");
|
|
23
|
-
|
|
24
|
+
const statusField = props.statusField ?? "statusCode";
|
|
25
|
+
const includeStatus = (props.hideInactiveInList ?? true) && statusField;
|
|
26
|
+
return union(
|
|
27
|
+
["itemCode", "itemValue", "itemValueAlternative"],
|
|
28
|
+
includeStatus ? [statusField] : [],
|
|
29
|
+
extra,
|
|
30
|
+
props.fields || []
|
|
31
|
+
);
|
|
24
32
|
});
|
|
25
|
-
const itemTitleField = computed(() => props.lang === "TH" ? "itemValue" : "itemValueAlternative");
|
|
26
33
|
const formatItemTitle = (item) => {
|
|
27
34
|
if (props.meilisearch) {
|
|
28
35
|
const raw = item.raw?._formatted ?? {};
|
|
@@ -47,7 +54,6 @@ export function useLookupListMaster(props) {
|
|
|
47
54
|
return [props.sortBy ?? "itemValue"];
|
|
48
55
|
});
|
|
49
56
|
return {
|
|
50
|
-
// for <model-*> props
|
|
51
57
|
computedModelName,
|
|
52
58
|
computedModelBy,
|
|
53
59
|
computedModelSelectedItemBy,
|
|
@@ -55,7 +61,6 @@ export function useLookupListMaster(props) {
|
|
|
55
61
|
itemTitleField,
|
|
56
62
|
computedNoDataText,
|
|
57
63
|
computedSortBy,
|
|
58
|
-
// helpers
|
|
59
64
|
formatItemTitle
|
|
60
65
|
};
|
|
61
66
|
}
|