adminforth 1.13.0-next.33 → 1.13.0-next.35
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.
|
@@ -98,4 +98,17 @@ onUnmounted(() => {
|
|
|
98
98
|
modal.value?.destroy();
|
|
99
99
|
})
|
|
100
100
|
|
|
101
|
+
function open() {
|
|
102
|
+
modal.value?.show();
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function close() {
|
|
106
|
+
modal.value?.hide();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
defineExpose({
|
|
110
|
+
open: open,
|
|
111
|
+
close: close,
|
|
112
|
+
})
|
|
113
|
+
|
|
101
114
|
</script>
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
</div>
|
|
35
35
|
<teleport to="body" v-if="teleportToBody && showDropdown">
|
|
36
36
|
<div ref="dropdownEl" :style="getDropdownPosition" :class="{'shadow-none': isTop}"
|
|
37
|
-
class="fixed z-
|
|
37
|
+
class="fixed z-[5] w-full bg-white shadow-lg dark:shadow-black dark:bg-gray-700
|
|
38
38
|
dark:border-gray-600 rounded-md py-1 text-base ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm max-h-48">
|
|
39
39
|
<div
|
|
40
40
|
v-for="item in filteredItems"
|
|
@@ -202,6 +202,23 @@ watch(
|
|
|
202
202
|
}
|
|
203
203
|
);
|
|
204
204
|
|
|
205
|
+
const handleScroll = () => {
|
|
206
|
+
if (showDropdown.value && inputEl.value) {
|
|
207
|
+
const rect = inputEl.value.getBoundingClientRect();
|
|
208
|
+
const style = {
|
|
209
|
+
left: `${rect.left}px`,
|
|
210
|
+
top: isTop.value && dropdownHeight.value
|
|
211
|
+
? `${rect.top - dropdownHeight.value - 8}px`
|
|
212
|
+
: `${rect.bottom + 8}px`,
|
|
213
|
+
width: `${rect.width}px`
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
if (dropdownEl.value) {
|
|
217
|
+
Object.assign(dropdownEl.value.style, style);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
|
|
205
222
|
onMounted(() => {
|
|
206
223
|
updateFromProps();
|
|
207
224
|
|
|
@@ -214,7 +231,11 @@ onMounted(() => {
|
|
|
214
231
|
});
|
|
215
232
|
|
|
216
233
|
addClickListener();
|
|
217
|
-
|
|
234
|
+
|
|
235
|
+
// Add scroll listeners if teleportToBody is true
|
|
236
|
+
if (props.teleportToBody) {
|
|
237
|
+
window.addEventListener('scroll', handleScroll, true);
|
|
238
|
+
}
|
|
218
239
|
});
|
|
219
240
|
|
|
220
241
|
const filteredItems = computed(() => {
|
|
@@ -268,6 +289,10 @@ const toogleItem = (item) => {
|
|
|
268
289
|
|
|
269
290
|
onUnmounted(() => {
|
|
270
291
|
removeClickListener();
|
|
292
|
+
// Remove scroll listeners if teleportToBody is true
|
|
293
|
+
if (props.teleportToBody) {
|
|
294
|
+
window.removeEventListener('scroll', handleScroll, true);
|
|
295
|
+
}
|
|
271
296
|
});
|
|
272
297
|
|
|
273
298
|
const getDropdownPosition = computed(() => {
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
ref="input"
|
|
19
19
|
class="w-full"
|
|
20
20
|
:options="columnOptions[column.name] || []"
|
|
21
|
+
teleportToBody
|
|
21
22
|
:placeholder = "columnOptions[column.name]?.length ?$t('Select...'): $t('There are no options available')"
|
|
22
23
|
:modelValue="value"
|
|
23
24
|
:readonly="column.editReadonly && source === 'edit'"
|
|
@@ -28,6 +29,7 @@
|
|
|
28
29
|
ref="input"
|
|
29
30
|
class="w-full"
|
|
30
31
|
:options="column.enum"
|
|
32
|
+
teleportToBody
|
|
31
33
|
:modelValue="value"
|
|
32
34
|
:readonly="column.editReadonly && source === 'edit'"
|
|
33
35
|
@update:modelValue="$emit('update:modelValue', $event)"
|
|
@@ -37,6 +39,7 @@
|
|
|
37
39
|
ref="input"
|
|
38
40
|
class="w-full"
|
|
39
41
|
:options="getBooleanOptions(column)"
|
|
42
|
+
teleportToBody
|
|
40
43
|
:modelValue="value"
|
|
41
44
|
:readonly="column.editReadonly && source === 'edit'"
|
|
42
45
|
@update:modelValue="$emit('update:modelValue', $event)"
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<template v-if="column.isArray?.enabled">
|
|
3
|
+
<div class="flex flex-col">
|
|
4
|
+
<ColumnValueInput
|
|
5
|
+
v-for="(arrayItemValue, arrayItemIndex) in currentValues[column.name]"
|
|
6
|
+
:key="`${column.name}-${arrayItemIndex}`"
|
|
7
|
+
ref="arrayItemRefs"
|
|
8
|
+
:class="{'mt-2': arrayItemIndex}"
|
|
9
|
+
:source="source"
|
|
10
|
+
:column="column"
|
|
11
|
+
:type="column.isArray.itemType"
|
|
12
|
+
:value="arrayItemValue"
|
|
13
|
+
:currentValues="currentValues"
|
|
14
|
+
:mode="mode"
|
|
15
|
+
:columnOptions="columnOptions"
|
|
16
|
+
:deletable="!column.editReadonly"
|
|
17
|
+
@update:modelValue="setCurrentValue(column.name, $event, arrayItemIndex)"
|
|
18
|
+
@update:unmasked="$emit('update:unmasked', column.name)"
|
|
19
|
+
@update:inValidity="$emit('update:inValidity', { name: column.name, value: $event })"
|
|
20
|
+
@update:emptiness="$emit('update:emptiness', { name: column.name, value: $event })"
|
|
21
|
+
@delete="setCurrentValue(column.name, currentValues[column.name].filter((_, index) => index !== arrayItemIndex))"
|
|
22
|
+
/>
|
|
23
|
+
</div>
|
|
24
|
+
<button
|
|
25
|
+
v-if="!column.editReadonly"
|
|
26
|
+
type="button"
|
|
27
|
+
@click="addArrayItem"
|
|
28
|
+
class="flex items-center py-1 px-3 me-2 text-sm font-medium rounded-default text-gray-900 focus:outline-none bg-white rounded border border-gray-300 hover:bg-gray-100 hover:text-lightPrimary focus:z-10 focus:ring-4 focus:ring-gray-100 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700"
|
|
29
|
+
:class="{'mt-2': currentValues[column.name].length}"
|
|
30
|
+
>
|
|
31
|
+
<IconPlusOutline class="w-4 h-4 me-2"/>
|
|
32
|
+
{{ $t('Add') }}
|
|
33
|
+
</button>
|
|
34
|
+
</template>
|
|
35
|
+
<ColumnValueInput
|
|
36
|
+
v-else
|
|
37
|
+
:source="source"
|
|
38
|
+
:column="column"
|
|
39
|
+
:value="currentValues[column.name]"
|
|
40
|
+
:currentValues="currentValues"
|
|
41
|
+
:mode="mode"
|
|
42
|
+
:columnOptions="columnOptions"
|
|
43
|
+
:unmasked="unmasked"
|
|
44
|
+
@update:modelValue="setCurrentValue(column.name, $event)"
|
|
45
|
+
@update:unmasked="$emit('update:unmasked', column.name)"
|
|
46
|
+
@update:inValidity="$emit('update:inValidity', { name: column.name, value: $event })"
|
|
47
|
+
@update:emptiness="$emit('update:emptiness', { name: column.name, value: $event })"
|
|
48
|
+
/>
|
|
49
|
+
</template>
|
|
50
|
+
|
|
51
|
+
<script setup lang="ts">
|
|
52
|
+
import { IconPlusOutline } from '@iconify-prerendered/vue-flowbite';
|
|
53
|
+
import ColumnValueInput from "./ColumnValueInput.vue";
|
|
54
|
+
import { ref, nextTick } from 'vue';
|
|
55
|
+
|
|
56
|
+
const props = defineProps<{
|
|
57
|
+
source: 'create' | 'edit',
|
|
58
|
+
column: any,
|
|
59
|
+
currentValues: any,
|
|
60
|
+
mode: string,
|
|
61
|
+
columnOptions: any,
|
|
62
|
+
unmasked: any,
|
|
63
|
+
setCurrentValue: Function
|
|
64
|
+
}>();
|
|
65
|
+
|
|
66
|
+
const emit = defineEmits(['update:unmasked', 'update:inValidity', 'update:emptiness', 'focus-last-input']);
|
|
67
|
+
|
|
68
|
+
const arrayItemRefs = ref([]);
|
|
69
|
+
|
|
70
|
+
async function addArrayItem() {
|
|
71
|
+
props.setCurrentValue(props.column.name, props.currentValues[props.column.name], props.currentValues[props.column.name].length);
|
|
72
|
+
await nextTick();
|
|
73
|
+
arrayItemRefs.value[arrayItemRefs.value.length - 1].focus();
|
|
74
|
+
}
|
|
75
|
+
</script>
|
|
@@ -42,50 +42,17 @@
|
|
|
42
42
|
class="px-6 py-4 whitespace-pre-wrap relative block md:table-cell"
|
|
43
43
|
:class="{'rounded-br-lg': i === group.columns.length - 1}"
|
|
44
44
|
>
|
|
45
|
-
<
|
|
46
|
-
<ColumnValueInput
|
|
47
|
-
v-for="(arrayItemValue, arrayItemIndex) in currentValues[column.name]"
|
|
48
|
-
:key="`${column.name}-${arrayItemIndex}`"
|
|
49
|
-
ref="arrayItemRefs"
|
|
50
|
-
:class="{'mt-2': arrayItemIndex}"
|
|
51
|
-
:source="source"
|
|
52
|
-
:column="column"
|
|
53
|
-
:type="column.isArray.itemType"
|
|
54
|
-
:value="arrayItemValue"
|
|
55
|
-
:currentValues="currentValues"
|
|
56
|
-
:mode="mode"
|
|
57
|
-
:columnOptions="columnOptions"
|
|
58
|
-
:deletable="!column.editReadonly"
|
|
59
|
-
@update:modelValue="setCurrentValue(column.name, $event, arrayItemIndex)"
|
|
60
|
-
@update:unmasked="unmasked[column.name] = !unmasked[column.name]"
|
|
61
|
-
@update:inValidity="customComponentsInValidity[column.name] = $event"
|
|
62
|
-
@update:emptiness="customComponentsEmptiness[column.name] = $event"
|
|
63
|
-
@delete="setCurrentValue(column.name, currentValues[column.name].filter((_, index) => index !== arrayItemIndex))"
|
|
64
|
-
/>
|
|
65
|
-
<button
|
|
66
|
-
v-if="!column.editReadonly"
|
|
67
|
-
type="button"
|
|
68
|
-
@click="setCurrentValue(column.name, currentValues[column.name], currentValues[column.name].length); focusOnLastInput(column.name)"
|
|
69
|
-
class="flex items-center py-1 px-3 me-2 text-sm font-medium rounded-default text-gray-900 focus:outline-none bg-white rounded border border-gray-300 hover:bg-gray-100 hover:text-lightPrimary focus:z-10 focus:ring-4 focus:ring-gray-100 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700"
|
|
70
|
-
:class="{'mt-2': currentValues[column.name].length}"
|
|
71
|
-
>
|
|
72
|
-
<IconPlusOutline class="w-4 h-4 me-2"/>
|
|
73
|
-
{{ $t('Add') }}
|
|
74
|
-
</button>
|
|
75
|
-
</template>
|
|
76
|
-
<ColumnValueInput
|
|
77
|
-
v-else
|
|
45
|
+
<ColumnValueInputWrapper
|
|
78
46
|
:source="source"
|
|
79
47
|
:column="column"
|
|
80
|
-
:value="currentValues[column.name]"
|
|
81
48
|
:currentValues="currentValues"
|
|
82
49
|
:mode="mode"
|
|
83
50
|
:columnOptions="columnOptions"
|
|
84
51
|
:unmasked="unmasked"
|
|
85
|
-
|
|
86
|
-
@update:unmasked="unmasked[
|
|
87
|
-
@update:inValidity="customComponentsInValidity[
|
|
88
|
-
@update:emptiness="customComponentsEmptiness[
|
|
52
|
+
:setCurrentValue="setCurrentValue"
|
|
53
|
+
@update:unmasked="unmasked[$event] = !unmasked[$event]"
|
|
54
|
+
@update:inValidity="customComponentsInValidity[$event.name] = $event.value"
|
|
55
|
+
@update:emptiness="customComponentsEmptiness[$event.name] = $event.value"
|
|
89
56
|
/>
|
|
90
57
|
<div v-if="columnError(column) && validating" class="mt-1 text-xs text-red-500 dark:text-red-400">{{ columnError(column) }}</div>
|
|
91
58
|
<div v-if="column.editingNote && column.editingNote[mode]" class="mt-1 text-xs text-gray-400 dark:text-gray-500">{{ column.editingNote[mode] }}</div>
|
|
@@ -98,10 +65,10 @@
|
|
|
98
65
|
|
|
99
66
|
<script setup lang="ts">
|
|
100
67
|
import { IconExclamationCircleSolid, IconPlusOutline } from '@iconify-prerendered/vue-flowbite';
|
|
101
|
-
import ColumnValueInput from "@/components/ColumnValueInput.vue";
|
|
102
68
|
import { Tooltip } from '@/afcl';
|
|
103
69
|
import { ref, computed, watch, nextTick, type Ref } from 'vue';
|
|
104
70
|
import { useI18n } from 'vue-i18n';
|
|
71
|
+
import ColumnValueInputWrapper from "@/components/ColumnValueInputWrapper.vue";
|
|
105
72
|
|
|
106
73
|
const { t } = useI18n();
|
|
107
74
|
|
|
@@ -117,8 +84,6 @@
|
|
|
117
84
|
columnOptions: any,
|
|
118
85
|
}>();
|
|
119
86
|
|
|
120
|
-
const arrayItemRefs = ref([]);
|
|
121
|
-
|
|
122
87
|
const customComponentsInValidity: Ref<Record<string, boolean>> = ref({});
|
|
123
88
|
const customComponentsEmptiness: Ref<Record<string, boolean>> = ref({});
|
|
124
89
|
const allColumnsHaveCustomComponent = computed(() => {
|
|
@@ -130,12 +95,6 @@
|
|
|
130
95
|
|
|
131
96
|
const emit = defineEmits(['update:customComponentsInValidity', 'update:customComponentsEmptiness']);
|
|
132
97
|
|
|
133
|
-
async function focusOnLastInput(column) {
|
|
134
|
-
// wait for element to register
|
|
135
|
-
await nextTick();
|
|
136
|
-
arrayItemRefs.value[arrayItemRefs.value.length - 1].focus();
|
|
137
|
-
}
|
|
138
|
-
|
|
139
98
|
watch(customComponentsInValidity.value, (newVal) => {
|
|
140
99
|
emit('update:customComponentsInValidity', newVal);
|
|
141
100
|
});
|
|
@@ -144,4 +103,4 @@
|
|
|
144
103
|
emit('update:customComponentsEmptiness', newVal);
|
|
145
104
|
});
|
|
146
105
|
|
|
147
|
-
</script>
|
|
106
|
+
</script>
|