adminforth 1.2.96 → 1.2.98
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/index.js +2 -1
- package/dist/modules/restApi.js +22 -23
- package/dist/spa/index.html +4 -4
- package/dist/spa/package-lock.json +421 -6
- package/dist/spa/package.json +10 -2
- package/dist/spa/src/App.vue +236 -94
- package/dist/spa/src/assets/base.css +2 -0
- package/dist/spa/src/assets/logo.svg +19 -1
- package/dist/spa/src/components/AcceptModal.vue +3 -10
- package/dist/spa/src/components/Breadcrumbs.vue +3 -2
- package/dist/spa/src/components/BreadcrumbsWithButtons.vue +1 -1
- package/dist/spa/src/components/CustomDatePicker.vue +25 -10
- package/dist/spa/src/components/CustomDateRangePicker.vue +14 -5
- package/dist/spa/src/components/Dropdown.vue +19 -5
- package/dist/spa/src/components/Filters.vue +103 -38
- package/dist/spa/src/components/MenuLink.vue +3 -3
- package/dist/spa/src/components/ResourceForm.vue +205 -116
- package/dist/spa/{spa/src → src}/components/ResourceListTable.vue +6 -3
- package/dist/spa/{spa/src → src}/components/Toast.vue +9 -3
- package/dist/spa/src/components/ValueRenderer.vue +30 -8
- package/dist/spa/src/index.scss +2 -1
- package/dist/spa/src/main.ts +2 -2
- package/dist/spa/src/router/index.ts +29 -19
- package/dist/spa/src/stores/core.ts +65 -59
- package/dist/spa/src/stores/modal.ts +13 -3
- package/dist/spa/src/types/AdminForthConfig.ts +1477 -0
- package/dist/spa/src/types/FrontendAPI.ts +121 -0
- package/dist/spa/src/utils.ts +69 -10
- package/dist/spa/src/views/CreateView.vue +69 -16
- package/dist/spa/src/views/EditView.vue +68 -14
- package/dist/spa/src/views/ListView.vue +100 -371
- package/dist/spa/src/views/LoginView.vue +67 -29
- package/dist/spa/src/views/ResourceParent.vue +1 -2
- package/dist/spa/src/views/ShowView.vue +116 -25
- package/dist/spa/tailwind.config.js +8 -3
- package/dist/spa/vite.config.ts +13 -0
- package/index.ts +2 -1
- package/modules/restApi.ts +27 -26
- package/package.json +1 -1
- package/dist/spa/.vscode/extensions.json +0 -6
- package/dist/spa/public/favicon.ico +0 -0
- package/dist/spa/spa/.eslintrc.cjs +0 -14
- package/dist/spa/spa/.vscode/extensions.json +0 -6
- package/dist/spa/spa/README.md +0 -39
- package/dist/spa/spa/env.d.ts +0 -1
- package/dist/spa/spa/index.html +0 -23
- package/dist/spa/spa/package-lock.json +0 -4573
- package/dist/spa/spa/package.json +0 -49
- package/dist/spa/spa/postcss.config.js +0 -6
- package/dist/spa/spa/public/favicon.ico +0 -0
- package/dist/spa/spa/src/App.vue +0 -314
- package/dist/spa/spa/src/assets/base.css +0 -0
- package/dist/spa/spa/src/assets/logo.svg +0 -19
- package/dist/spa/spa/src/components/AcceptModal.vue +0 -45
- package/dist/spa/spa/src/components/Breadcrumbs.vue +0 -40
- package/dist/spa/spa/src/components/BreadcrumbsWithButtons.vue +0 -26
- package/dist/spa/spa/src/components/CustomDatePicker.vue +0 -174
- package/dist/spa/spa/src/components/CustomDateRangePicker.vue +0 -218
- package/dist/spa/spa/src/components/Dropdown.vue +0 -168
- package/dist/spa/spa/src/components/Filters.vue +0 -222
- package/dist/spa/spa/src/components/HelloWorld.vue +0 -17
- package/dist/spa/spa/src/components/MenuLink.vue +0 -24
- package/dist/spa/spa/src/components/ResourceForm.vue +0 -289
- package/dist/spa/spa/src/components/SingleSkeletLoader.vue +0 -13
- package/dist/spa/spa/src/components/ValueRenderer.vue +0 -66
- package/dist/spa/spa/src/components/icons/IconCalendar.vue +0 -5
- package/dist/spa/spa/src/components/icons/IconCommunity.vue +0 -7
- package/dist/spa/spa/src/components/icons/IconDocumentation.vue +0 -7
- package/dist/spa/spa/src/components/icons/IconEcosystem.vue +0 -7
- package/dist/spa/spa/src/components/icons/IconSupport.vue +0 -7
- package/dist/spa/spa/src/components/icons/IconTime.vue +0 -5
- package/dist/spa/spa/src/components/icons/IconTooling.vue +0 -19
- package/dist/spa/spa/src/index.scss +0 -27
- package/dist/spa/spa/src/main.ts +0 -18
- package/dist/spa/spa/src/router/index.ts +0 -63
- package/dist/spa/spa/src/stores/core.ts +0 -144
- package/dist/spa/spa/src/stores/modal.ts +0 -48
- package/dist/spa/spa/src/utils.ts +0 -103
- package/dist/spa/spa/src/views/CreateView.vue +0 -156
- package/dist/spa/spa/src/views/EditView.vue +0 -157
- package/dist/spa/spa/src/views/HomeView.vue +0 -8
- package/dist/spa/spa/src/views/ListView.vue +0 -258
- package/dist/spa/spa/src/views/LoginView.vue +0 -143
- package/dist/spa/spa/src/views/ResourceParent.vue +0 -17
- package/dist/spa/spa/src/views/ShowView.vue +0 -184
- package/dist/spa/spa/tailwind.config.js +0 -17
- package/dist/spa/spa/tsconfig.app.json +0 -14
- package/dist/spa/spa/tsconfig.json +0 -11
- package/dist/spa/spa/tsconfig.node.json +0 -19
- package/dist/spa/spa/vite.config.ts +0 -56
- package/dist/spa/src/views/HomeView.vue +0 -8
- package/dist/types.js +0 -30
- /package/dist/spa/{spa/public → public}/assets/favicon.png +0 -0
- /package/dist/spa/{spa/src → src}/components/CustomRangePicker.vue +0 -0
- /package/dist/spa/{spa/src → src}/components/SkeleteLoader.vue +0 -0
- /package/dist/spa/{spa/src → src}/composables/useFrontendApi.ts +0 -0
- /package/dist/spa/{spa/src → src}/composables/useStores.ts +0 -0
- /package/dist/spa/{spa/src → src}/spa_types/core.ts +0 -0
- /package/dist/spa/{spa/src → src}/stores/filters.ts +0 -0
- /package/dist/spa/{spa/src → src}/stores/toast.ts +0 -0
- /package/dist/spa/{spa/src → src}/stores/user.ts +0 -0
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
<div class="mx-auto grid grid-cols-2 gap-4 mb-2" :class="{hidden: !showTimeInputs}">
|
|
27
27
|
<div>
|
|
28
28
|
<div class="relative">
|
|
29
|
-
<div class="absolute inset-y-0 end-0 top-0 flex items-center pe-3.5">
|
|
29
|
+
<div class="absolute inset-y-0 end-0 top-0 flex items-center pe-3.5 pointer-events-none">
|
|
30
30
|
<IconTime class="w-4 h-4 text-gray-500 dark:text-gray-400 bg-white dark:bg-gray-700"/>
|
|
31
31
|
</div>
|
|
32
32
|
|
|
@@ -101,6 +101,9 @@ const endDate = ref('');
|
|
|
101
101
|
const startTime = ref('');
|
|
102
102
|
const endTime = ref('');
|
|
103
103
|
|
|
104
|
+
const datepickerStartObject = ref('')
|
|
105
|
+
const datepickerEndObject = ref('')
|
|
106
|
+
|
|
104
107
|
const start = computed(() => {
|
|
105
108
|
if (!startDate.value) {
|
|
106
109
|
return;
|
|
@@ -132,11 +135,11 @@ const end = computed(() => {
|
|
|
132
135
|
})
|
|
133
136
|
|
|
134
137
|
function updateFromProps() {
|
|
135
|
-
if (props.valueStart
|
|
138
|
+
if (!props.valueStart) {
|
|
136
139
|
datepickerStartEl.value.value = '';
|
|
137
140
|
startTime.value = '';
|
|
138
141
|
}
|
|
139
|
-
if (props.valueEnd
|
|
142
|
+
if (!props.valueEnd) {
|
|
140
143
|
datepickerEndEl.value.value = '';
|
|
141
144
|
endTime.value = '';
|
|
142
145
|
}
|
|
@@ -162,9 +165,9 @@ watch(end, () => {
|
|
|
162
165
|
|
|
163
166
|
function initDatepickers() {
|
|
164
167
|
|
|
165
|
-
new Datepicker(datepickerStartEl.value, {format: 'dd M yyyy'});
|
|
168
|
+
datepickerStartObject.value = new Datepicker(datepickerStartEl.value, {format: 'dd M yyyy'});
|
|
166
169
|
|
|
167
|
-
new Datepicker(datepickerEndEl.value, {format: 'dd M yyyy'});
|
|
170
|
+
datepickerEndObject.value = new Datepicker(datepickerEndEl.value, {format: 'dd M yyyy'});
|
|
168
171
|
addChangeDateListener();
|
|
169
172
|
}
|
|
170
173
|
|
|
@@ -178,6 +181,11 @@ function removeChangeDateListener() {
|
|
|
178
181
|
datepickerEndEl.value.removeEventListener('changeDate', setEndDate);
|
|
179
182
|
}
|
|
180
183
|
|
|
184
|
+
function destroyDatepickerElement() {
|
|
185
|
+
datepickerStartObject.value.destroy();
|
|
186
|
+
datepickerEndObject.value.destroy();
|
|
187
|
+
}
|
|
188
|
+
|
|
181
189
|
function setStartDate(event) {
|
|
182
190
|
startDate.value = event.detail.date
|
|
183
191
|
}
|
|
@@ -205,5 +213,6 @@ onMounted(() => {
|
|
|
205
213
|
|
|
206
214
|
onBeforeUnmount(() => {
|
|
207
215
|
removeChangeDateListener();
|
|
216
|
+
destroyDatepickerElement();
|
|
208
217
|
})
|
|
209
218
|
</script>
|
|
@@ -6,10 +6,11 @@
|
|
|
6
6
|
v-model="search"
|
|
7
7
|
@focus="showDropdown = true"
|
|
8
8
|
class="block w-full pl-3 pr-10 py-2 border border-gray-300 rounded-md leading-5 bg-white placeholder-gray-500 focus:outline-none focus:shadow-outline-blue focus:border-blue-300 sm:text-sm transition duration-150 ease-in-out dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
|
9
|
-
:placeholder="selectedItems.length ? '' : 'Select...'"
|
|
9
|
+
:placeholder="selectedItems.length ? '' : placeholder || 'Select...'"
|
|
10
10
|
/>
|
|
11
11
|
<div class="absolute inset-y-0 left-2 flex items-center pr-2 flex-wrap">
|
|
12
|
-
|
|
12
|
+
{{ }}
|
|
13
|
+
<div v-for="item in selectedItems" :key="item?.name" class="bg-blue-100 text-blue-800 text-xs font-medium me-2 px-2.5 py-0.5 rounded dark:bg-blue-900 dark:text-blue-300">
|
|
13
14
|
<span>{{ item.label }}</span>
|
|
14
15
|
<button
|
|
15
16
|
type="button"
|
|
@@ -34,7 +35,7 @@
|
|
|
34
35
|
<IconCaretUpSolid v-else class="h-5 w-5 text-gray-400" />
|
|
35
36
|
</div>
|
|
36
37
|
</div>
|
|
37
|
-
<div v-if="showDropdown" class="absolute z-10 mt-1 w-full bg-white shadow-lg rounded-md py-1 text-base ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm">
|
|
38
|
+
<div v-if="showDropdown" class="absolute z-10 mt-1 w-full bg-white shadow-lg dark:shadow-black rounded-md py-1 text-base ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm">
|
|
38
39
|
<div
|
|
39
40
|
v-for="item in filteredItems"
|
|
40
41
|
:key="item.value"
|
|
@@ -66,6 +67,11 @@ const props = defineProps({
|
|
|
66
67
|
type: Boolean,
|
|
67
68
|
default: false,
|
|
68
69
|
},
|
|
70
|
+
placeholder: {
|
|
71
|
+
type: String,
|
|
72
|
+
default: '',
|
|
73
|
+
|
|
74
|
+
},
|
|
69
75
|
});
|
|
70
76
|
|
|
71
77
|
const emit = defineEmits(['update:modelValue']);
|
|
@@ -76,10 +82,14 @@ const showDropdown = ref(false);
|
|
|
76
82
|
const selectedItems = ref([]);
|
|
77
83
|
|
|
78
84
|
function updateFromProps() {
|
|
79
|
-
console.log('⚡ updateFromProps', props.modelValue)
|
|
80
85
|
if (props.modelValue !== undefined) {
|
|
81
86
|
if (props.single) {
|
|
82
|
-
|
|
87
|
+
const el = props.options.find(item => item.value === props.modelValue);
|
|
88
|
+
if (el) {
|
|
89
|
+
selectedItems.value = [el];
|
|
90
|
+
} else {
|
|
91
|
+
selectedItems.value = [];
|
|
92
|
+
}
|
|
83
93
|
} else {
|
|
84
94
|
selectedItems.value = props.options.filter(item => props.modelValue.includes(item.value));
|
|
85
95
|
}
|
|
@@ -93,6 +103,10 @@ onMounted(() => {
|
|
|
93
103
|
updateFromProps();
|
|
94
104
|
});
|
|
95
105
|
|
|
106
|
+
watch(() => props.options, () => {
|
|
107
|
+
updateFromProps();
|
|
108
|
+
});
|
|
109
|
+
|
|
96
110
|
addClickListener();
|
|
97
111
|
|
|
98
112
|
});
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
<!-- drawer component -->
|
|
3
3
|
<div id="drawer-navigation"
|
|
4
4
|
|
|
5
|
-
class="fixed
|
|
5
|
+
class="fixed right-0 z-50 p-4 overflow-y-auto transition-transform translate-x-full bg-white w-80 dark:bg-gray-800 shadow-xl dark:shadow-gray-900"
|
|
6
6
|
|
|
7
7
|
:class="show ? 'top-0 transform-none' : ''"
|
|
8
8
|
tabindex="-1" aria-labelledby="drawer-navigation-label"
|
|
9
|
-
:style="{ height: `calc(100vh
|
|
9
|
+
:style="{ height: `calc(100vh ` }"
|
|
10
10
|
>
|
|
11
11
|
<h5 id="drawer-navigation-label" class="text-base font-semibold text-gray-500 uppercase dark:text-gray-400">
|
|
12
12
|
Filters
|
|
@@ -22,11 +22,17 @@
|
|
|
22
22
|
<li v-for="c in columnsWithFilter" :key="c">
|
|
23
23
|
<p class="dark:text-gray-400">{{ c.label }}</p>
|
|
24
24
|
|
|
25
|
-
<Dropdown
|
|
26
|
-
v-if="c.
|
|
25
|
+
<Dropdown
|
|
26
|
+
v-if="c.foreignResource"
|
|
27
|
+
:options="columnOptions[c.name] || []"
|
|
28
|
+
@update:modelValue="setFilterItem({ column: c, operator: 'in', value: $event })"
|
|
29
|
+
:modelValue="filtersStore.filters.find(f => f.field === c.name && f.operator === 'in')?.value || []"
|
|
30
|
+
/>
|
|
31
|
+
<Dropdown
|
|
32
|
+
v-else-if="c.type === 'boolean'"
|
|
27
33
|
:options="[{ label: 'Yes', value: true }, { label: 'No', value: false }, { label: 'Unset', value: null }]"
|
|
28
34
|
@update:modelValue="setFilterItem({ column: c, operator: 'in', value: $event })"
|
|
29
|
-
:modelValue="filters.find(f => f.field === c.name && f.operator === 'in')?.value || []"
|
|
35
|
+
:modelValue="filtersStore.filters.find(f => f.field === c.name && f.operator === 'in')?.value || []"
|
|
30
36
|
/>
|
|
31
37
|
|
|
32
38
|
<Dropdown
|
|
@@ -34,7 +40,7 @@
|
|
|
34
40
|
:options="c.enum"
|
|
35
41
|
:allowCustom="c.allowCustom"
|
|
36
42
|
@update:modelValue="setFilterItem({ column: c, operator: 'in', value: $event })"
|
|
37
|
-
:modelValue="filters.find(f => f.field === c.name && f.operator === 'in')?.value || []"
|
|
43
|
+
:modelValue="filtersStore.filters.find(f => f.field === c.name && f.operator === 'in')?.value || []"
|
|
38
44
|
/>
|
|
39
45
|
|
|
40
46
|
<input
|
|
@@ -48,9 +54,9 @@
|
|
|
48
54
|
<CustomDateRangePicker
|
|
49
55
|
v-else-if="['datetime'].includes(c.type)"
|
|
50
56
|
:column="c"
|
|
51
|
-
:valueStart="filters.find(f => f.field === c.name && f.operator === 'gte')?.value || undefined"
|
|
57
|
+
:valueStart="filtersStore.filters.find(f => f.field === c.name && f.operator === 'gte')?.value || undefined"
|
|
52
58
|
@update:valueStart="setFilterItem({ column: c, operator: 'gte', value: $event || undefined })"
|
|
53
|
-
:valueEnd="filters.find(f => f.field === c.name && f.operator === 'lte')?.value || undefined"
|
|
59
|
+
:valueEnd="filtersStore.filters.find(f => f.field === c.name && f.operator === 'lte')?.value || undefined"
|
|
54
60
|
@update:valueEnd="setFilterItem({ column: c, operator: 'lte', value: $event || undefined })"
|
|
55
61
|
/>
|
|
56
62
|
|
|
@@ -62,22 +68,32 @@
|
|
|
62
68
|
:value="getFilterItem({ column: c, operator: 'ilike' })"
|
|
63
69
|
>
|
|
64
70
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
71
|
+
<CustomRangePicker
|
|
72
|
+
v-else-if="['integer', 'decimal', 'float'].includes(c.type) && c.allowMinMaxQuery"
|
|
73
|
+
:min="getFilterMinValue(c.name)"
|
|
74
|
+
:max="getFilterMaxValue(c.name)"
|
|
75
|
+
:valueStart="getFilterItem({ column: c, operator: 'gte' })"
|
|
76
|
+
@update:valueStart="setFilterItem({ column: c, operator: 'gte', value: $event || undefined })"
|
|
77
|
+
:valueEnd="getFilterItem({ column: c, operator: 'lte' })"
|
|
78
|
+
@update:valueEnd="setFilterItem({ column: c, operator: 'lte', value: $event || undefined })"
|
|
79
|
+
/>
|
|
80
|
+
|
|
81
|
+
<div v-else-if="['integer', 'decimal', 'float'].includes(c.type)" class="flex gap-2">
|
|
82
|
+
<input
|
|
83
|
+
type="number" aria-describedby="helper-text-explanation"
|
|
84
|
+
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-20 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
|
85
|
+
placeholder="From"
|
|
86
|
+
@input="setFilterItem({ column: c, operator: 'gte', value: $event.target.value || undefined })"
|
|
87
|
+
:value="getFilterItem({ column: c, operator: 'gte' })"
|
|
88
|
+
>
|
|
89
|
+
<input
|
|
90
|
+
type="number" aria-describedby="helper-text-explanation"
|
|
91
|
+
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-20 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
|
92
|
+
placeholder="To"
|
|
93
|
+
@input="setFilterItem({ column: c, operator: 'lte', value: $event.target.value || undefined})"
|
|
94
|
+
:value="getFilterItem({ column: c, operator: 'lte' })"
|
|
95
|
+
>
|
|
96
|
+
</div>
|
|
81
97
|
|
|
82
98
|
</li>
|
|
83
99
|
</ul>
|
|
@@ -85,33 +101,71 @@
|
|
|
85
101
|
|
|
86
102
|
<div class="flex justify-end gap-2">
|
|
87
103
|
<button
|
|
88
|
-
:disabled="!filters.length"
|
|
104
|
+
:disabled="!filtersStore.filters.length"
|
|
89
105
|
type="button"
|
|
90
|
-
class="flex items-center py-1 px-3
|
|
106
|
+
class="flex items-center py-1 px-3 text-sm font-medium text-gray-900 focus:outline-none bg-white rounded border border-gray-300 hover:bg-gray-100 hover:text-blue-700 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 disabled:opacity-50 disabled:cursor-not-allowed"
|
|
91
107
|
@click="clear">Clear all</button>
|
|
92
108
|
|
|
93
109
|
</div>
|
|
94
110
|
</div>
|
|
95
111
|
|
|
96
|
-
<div v-if="show"
|
|
112
|
+
<div v-if="show" class="bg-gray-900/50 dark:bg-gray-900/80 fixed inset-0 z-30"
|
|
97
113
|
@click="$emit('hide')">
|
|
98
114
|
</div>
|
|
99
115
|
</template>
|
|
100
116
|
|
|
101
117
|
<script setup>
|
|
102
|
-
import { watch, computed } from 'vue'
|
|
118
|
+
import { watch, computed, ref, onMounted } from 'vue'
|
|
103
119
|
import Dropdown from '@/components/Dropdown.vue';
|
|
104
120
|
import CustomDateRangePicker from '@/components/CustomDateRangePicker.vue';
|
|
121
|
+
import { callAdminForthApi } from '@/utils';
|
|
122
|
+
import { useRouter } from 'vue-router';
|
|
123
|
+
import { computedAsync } from '@vueuse/core'
|
|
124
|
+
import CustomRangePicker from "@/components/CustomRangePicker.vue";
|
|
125
|
+
import { useFiltersStore } from '@/stores/filters';
|
|
126
|
+
|
|
127
|
+
const filtersStore = useFiltersStore();
|
|
128
|
+
|
|
105
129
|
|
|
106
130
|
// props: columns
|
|
107
131
|
// add support for v-model:filers
|
|
108
132
|
const props = defineProps(['columns', 'filters', 'show', 'columnsMinMax']);
|
|
109
133
|
const emits = defineEmits(['update:filters', 'hide']);
|
|
110
134
|
|
|
111
|
-
const
|
|
135
|
+
const router = useRouter();
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
const columnsWithFilter = computed(
|
|
112
139
|
() => props.columns?.filter(column => column.showIn.includes('filter')) || []
|
|
113
140
|
);
|
|
114
141
|
|
|
142
|
+
const columnOptions = computedAsync(async () => {
|
|
143
|
+
const ret = {};
|
|
144
|
+
if (!props.columns) {
|
|
145
|
+
return ret;
|
|
146
|
+
}
|
|
147
|
+
await Promise.all(
|
|
148
|
+
Object.values(props.columns).map(async (column) => {
|
|
149
|
+
if (column.foreignResource) {
|
|
150
|
+
const list = await callAdminForthApi({
|
|
151
|
+
method: 'POST',
|
|
152
|
+
path: `/get_resource_foreign_data`,
|
|
153
|
+
body: {
|
|
154
|
+
resourceId: router.currentRoute.value.params.resourceId,
|
|
155
|
+
column: column.name,
|
|
156
|
+
limit: 1000,
|
|
157
|
+
offset: 0,
|
|
158
|
+
},
|
|
159
|
+
});
|
|
160
|
+
ret[column.name] = list.items;
|
|
161
|
+
}
|
|
162
|
+
})
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
return ret;
|
|
166
|
+
}, {});
|
|
167
|
+
|
|
168
|
+
|
|
115
169
|
// sync 'body' class 'overflow-hidden' with show prop show
|
|
116
170
|
watch(() => props.show, (show) => {
|
|
117
171
|
if (show) {
|
|
@@ -130,28 +184,39 @@ watch(() => props.show, (show) => {
|
|
|
130
184
|
|
|
131
185
|
function setFilterItem({ column, operator, value }) {
|
|
132
186
|
|
|
133
|
-
const index =
|
|
187
|
+
const index = filtersStore.filters.findIndex(f => f.field === column.name && f.operator === operator);
|
|
134
188
|
if (value === undefined) {
|
|
135
189
|
if (index !== -1) {
|
|
136
|
-
|
|
190
|
+
filtersStore.filters.splice(index, 1);
|
|
137
191
|
}
|
|
138
|
-
emits('update:filters', [...props.filters]);
|
|
139
|
-
return;
|
|
140
192
|
} else {
|
|
141
193
|
if (index === -1) {
|
|
142
|
-
|
|
194
|
+
filtersStore.setFilter({ field: column.name, value, operator });
|
|
143
195
|
} else {
|
|
144
|
-
|
|
196
|
+
filtersStore.setFilters([...filtersStore.filters.slice(0, index), { field: column.name, value, operator }, ...filtersStore.filters.slice(index + 1)])
|
|
145
197
|
}
|
|
146
198
|
}
|
|
147
|
-
emits('update:filters', [...
|
|
199
|
+
emits('update:filters', [...filtersStore.filters]);
|
|
148
200
|
}
|
|
149
201
|
|
|
150
202
|
function getFilterItem({ column, operator }) {
|
|
151
|
-
return
|
|
203
|
+
return filtersStore.filters.find(f => f.field === column.name && f.operator === operator)?.value || '';
|
|
152
204
|
}
|
|
153
205
|
|
|
154
206
|
async function clear() {
|
|
155
|
-
|
|
207
|
+
filtersStore.clearFilters();
|
|
208
|
+
emits('update:filters', [...filtersStore.filters]);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function getFilterMinValue(columnName) {
|
|
212
|
+
if(props.columnsMinMax && props.columnsMinMax[columnName]) {
|
|
213
|
+
return props.columnsMinMax[columnName]?.min
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function getFilterMaxValue(columnName) {
|
|
218
|
+
if(props.columnsMinMax && props.columnsMinMax[columnName]) {
|
|
219
|
+
return props.columnsMinMax[columnName]?.max
|
|
220
|
+
}
|
|
156
221
|
}
|
|
157
222
|
</script>
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<RouterLink
|
|
3
3
|
:to="{name: item.resourceId ? 'resource-list' : item.path, params: item.resourceId ? { resourceId: item.resourceId }: {}}"
|
|
4
|
-
class="flex items-center py-2 text-
|
|
4
|
+
class="flex group items-center py-2 text-lightSidebarText dark:text-darkSidebarText rounded-default hover:bg-lightSidebarItemHover hover:text-lightSidebarTextHover dark:hover:bg-darkSidebarItemHover dark:hover:text-darkSidebarTextHover active:bg-lightSidebarActive dark:active:bg-darkSidebarHover" role="menuitem"
|
|
5
5
|
:class="{
|
|
6
6
|
'px-4': isChild,
|
|
7
7
|
'px-2': !isChild,
|
|
8
|
-
'bg-
|
|
8
|
+
'bg-lightSidebarItemActive dark:bg-darkSidebarItemActive': item.resourceId ?
|
|
9
9
|
($route.params.resourceId === item.resourceId && $route.name === 'resource-list') :
|
|
10
10
|
($route.name === item.path)
|
|
11
11
|
}"
|
|
12
12
|
>
|
|
13
|
-
<component v-if="item.icon" :is="getIcon(item.icon)" class="w-5 h-5 text-
|
|
13
|
+
<component v-if="item.icon" :is="getIcon(item.icon)" class="w-5 h-5 text-lightSidebarIcons dark:text-darkSidebarIcons transition duration-75 group-hover:text-lightSidebarIconsHover dark:group-hover:text-darkSidebarIconsHover" ></component>
|
|
14
14
|
<span class="ms-3">{{ item.label }}</span>
|
|
15
15
|
</RouterLink>
|
|
16
16
|
</template>
|