adminforth 2.26.0-test.3 → 2.26.0-test.5
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/dataConnectors/baseConnector.d.ts.map +1 -1
- package/dist/dataConnectors/baseConnector.js +3 -0
- package/dist/dataConnectors/baseConnector.js.map +1 -1
- package/dist/dataConnectors/clickhouse.d.ts +4 -0
- package/dist/dataConnectors/clickhouse.d.ts.map +1 -1
- package/dist/dataConnectors/clickhouse.js +14 -0
- package/dist/dataConnectors/clickhouse.js.map +1 -1
- package/dist/dataConnectors/mongo.d.ts +4 -0
- package/dist/dataConnectors/mongo.d.ts.map +1 -1
- package/dist/dataConnectors/mongo.js +9 -0
- package/dist/dataConnectors/mongo.js.map +1 -1
- package/dist/dataConnectors/mysql.d.ts +4 -0
- package/dist/dataConnectors/mysql.d.ts.map +1 -1
- package/dist/dataConnectors/mysql.js +11 -0
- package/dist/dataConnectors/mysql.js.map +1 -1
- package/dist/dataConnectors/postgres.d.ts +4 -0
- package/dist/dataConnectors/postgres.d.ts.map +1 -1
- package/dist/dataConnectors/postgres.js +11 -0
- package/dist/dataConnectors/postgres.js.map +1 -1
- package/dist/dataConnectors/qdrant.d.ts +65 -0
- package/dist/dataConnectors/qdrant.d.ts.map +1 -0
- package/dist/dataConnectors/qdrant.js +495 -0
- package/dist/dataConnectors/qdrant.js.map +1 -0
- package/dist/dataConnectors/sqlite.d.ts +4 -0
- package/dist/dataConnectors/sqlite.d.ts.map +1 -1
- package/dist/dataConnectors/sqlite.js +11 -0
- package/dist/dataConnectors/sqlite.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/modules/codeInjector.js +42 -42
- package/dist/modules/codeInjector.js.map +1 -1
- package/dist/modules/configValidator.d.ts.map +1 -1
- package/dist/modules/configValidator.js +3 -2
- package/dist/modules/configValidator.js.map +1 -1
- package/dist/spa/package-lock.json +13 -0
- package/dist/spa/package.json +1 -0
- package/dist/spa/pnpm-lock.yaml +12 -0
- package/dist/spa/src/afcl/Modal.vue +6 -2
- package/dist/spa/src/components/AcceptModal.vue +31 -53
- package/dist/spa/src/components/BreadcrumbsWithButtons.vue +4 -5
- package/dist/spa/src/components/ResourceListTable.vue +11 -11
- package/dist/spa/src/components/ResourceListTableVirtual.vue +21 -26
- package/dist/spa/src/components/Sidebar.vue +5 -1
- package/dist/spa/src/renderers/CountryFlag.vue +2 -2
- package/dist/spa/src/types/Back.ts +17 -2
- package/dist/spa/src/types/Common.ts +20 -0
- package/dist/spa/src/views/PageNotFound.vue +5 -1
- package/dist/types/Back.d.ts +19 -2
- package/dist/types/Back.d.ts.map +1 -1
- package/dist/types/Back.js.map +1 -1
- package/dist/types/Common.d.ts +5 -0
- package/dist/types/Common.d.ts.map +1 -1
- package/dist/types/Common.js.map +1 -1
- package/package.json +2 -1
|
@@ -1,41 +1,40 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<Teleport to="body">
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
3
|
+
<Modal
|
|
4
|
+
ref="modalRef"
|
|
5
|
+
:beforeCloseFunction="()=>{modalStore.onAcceptFunction(false);modalStore.isOpened=false}"
|
|
6
|
+
>
|
|
7
|
+
<div class="relative p-4 w-full max-w-md max-h-full" >
|
|
8
|
+
<button type="button" @click="modalStore.togleModal()" class="absolute top-3 end-2.5 text-lightAcceptModalCloseIcon bg-transparent hover:bg-lightAcceptModalCloseIconHoverBackground hover:text-lightAcceptModalCloseIconHover rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center dark:text-darkAcceptModalCloseIcon dark:hover:bg-darkAcceptModalCloseIconHoverBackground dark:hover:text-darkAcceptModalCloseIconHover" >
|
|
9
|
+
<svg class="w-3 h-3" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14">
|
|
10
|
+
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6"/>
|
|
11
|
+
</svg>
|
|
12
|
+
<span class="sr-only">{{ $t('Close modal') }}</span>
|
|
13
|
+
</button>
|
|
14
|
+
<div class="p-4 md:p-5 text-center">
|
|
15
|
+
<svg class="mx-auto mb-4 text-lightAcceptModalWarningIcon w-12 h-12 dark:text-darkAcceptModalWarningIcon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 20">
|
|
16
|
+
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 11V6m0 8h.01M19 10a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"/>
|
|
17
|
+
</svg>
|
|
18
|
+
<h3 class="afcl-confirmation-title mb-5 text-lg font-normal text-lightAcceptModalText dark:text-darkAcceptModalText">{{ modalStore?.modalContent?.content }}</h3>
|
|
19
|
+
<h3 class=" afcl-confirmation-title mb-5 text-lg font-normal text-lightAcceptModalText dark:text-darkAcceptModalText" v-html="modalStore?.modalContent?.contentHTML"></h3>
|
|
20
|
+
|
|
21
|
+
<button @click="()=>{ modalStore.onAcceptFunction(true);modalStore.togleModal()}" type="button" class="afcl-confirmation-accept-button text-lightAcceptModalConfirmButtonText bg-lightAcceptModalConfirmButtonBackground hover:bg-lightAcceptModalConfirmButtonBackgroundHover focus:ring-4 focus:outline-none focus:ring-lightAcceptModalConfirmButtonFocus font-medium rounded-lg text-sm inline-flex items-center px-5 py-2.5 text-center dark:text-darkAcceptModalConfirmButtonText dark:bg-darkAcceptModalConfirmButtonBackground dark:hover:bg-darkAcceptModalConfirmButtonBackgroundHover dark:focus:ring-darkAcceptModalConfirmButtonFocus">
|
|
22
|
+
{{ modalStore?.modalContent?.acceptText }}
|
|
23
|
+
</button>
|
|
24
|
+
<button @click="()=>{modalStore.onAcceptFunction(false);modalStore.togleModal()}" type="button" class="afcl-confirmation-cancel-button py-2.5 px-5 ms-3 text-sm font-medium text-lightAcceptModalCancelButtonText focus:outline-none bg-lightAcceptModalCancelButtonBackground rounded-lg border border-lightAcceptModalCancelButtonBorder hover:bg-lightAcceptModalCancelButtonBackgroundHover hover:text-lightPrimary focus:z-10 focus:ring-4 focus:ring-lightAcceptModalCancelButtonFocus dark:focus:ring-darkAcceptModalCancelButtonFocus dark:bg-darkAcceptModalCancelButtonBackground dark:text-darkAcceptModalCancelButtonText dark:border-darkAcceptModalCancelButtonBorder dark:hover:text-darkAcceptModalCancelButtonTextHover dark:hover:bg-darkAcceptModalCancelButtonBackgroundHover">{{ modalStore?.modalContent?.cancelText }}</button>
|
|
25
25
|
</div>
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
</Teleport>
|
|
26
|
+
</div>
|
|
27
|
+
</Modal>
|
|
28
|
+
</Teleport>
|
|
29
29
|
</template>
|
|
30
30
|
|
|
31
31
|
<script setup lang="ts">
|
|
32
32
|
import { watch, onMounted, nextTick, ref } from 'vue';
|
|
33
33
|
import { useModalStore } from '@/stores/modal';
|
|
34
|
-
import { Modal } from '
|
|
34
|
+
import { Modal } from '@/afcl';
|
|
35
35
|
|
|
36
|
+
const modalRef = ref();
|
|
36
37
|
const modalStore = useModalStore();
|
|
37
|
-
const modalEl = ref(null);
|
|
38
|
-
const modal = ref(null);
|
|
39
38
|
|
|
40
39
|
watch( () => modalStore.isOpened, (newVal) => {
|
|
41
40
|
if (newVal) {
|
|
@@ -46,35 +45,14 @@ watch( () => modalStore.isOpened, (newVal) => {
|
|
|
46
45
|
}
|
|
47
46
|
);
|
|
48
47
|
|
|
49
|
-
|
|
50
|
-
await nextTick();
|
|
51
|
-
modal.value = new Modal(
|
|
52
|
-
modalEl.value,
|
|
53
|
-
{
|
|
54
|
-
closable: true,
|
|
55
|
-
backdrop: 'static',
|
|
56
|
-
backdropClasses: "bg-gray-900/50 dark:bg-gray-900/80 fixed inset-0 z-[100]"
|
|
57
|
-
}
|
|
58
|
-
);
|
|
59
|
-
})
|
|
48
|
+
|
|
60
49
|
|
|
61
50
|
function open() {
|
|
62
|
-
|
|
51
|
+
modalRef.value.open();
|
|
63
52
|
}
|
|
64
53
|
|
|
65
54
|
function close() {
|
|
66
|
-
|
|
55
|
+
modalRef.value.close();
|
|
67
56
|
}
|
|
68
57
|
|
|
69
|
-
</script>
|
|
70
|
-
|
|
71
|
-
<style scoped>
|
|
72
|
-
.modal {
|
|
73
|
-
position: fixed;
|
|
74
|
-
z-index: 999;
|
|
75
|
-
top: 20%;
|
|
76
|
-
left: 50%;
|
|
77
|
-
width: 300px;
|
|
78
|
-
margin-left: -150px;
|
|
79
|
-
}
|
|
80
|
-
</style>
|
|
58
|
+
</script>
|
|
@@ -6,17 +6,16 @@
|
|
|
6
6
|
<slot></slot>
|
|
7
7
|
</div>
|
|
8
8
|
</div>
|
|
9
|
-
<div
|
|
10
|
-
<
|
|
11
|
-
<span class="font-medium">{{ $t('Error!')}}</span> {{ coreStore.resourceColumnsError }}
|
|
12
|
-
</div>
|
|
9
|
+
<div v-if="coreStore.resourceColumnsError" >
|
|
10
|
+
<PageNotFound :errorMessage="coreStore.resourceColumnsError" />
|
|
13
11
|
</div>
|
|
14
12
|
</div>
|
|
15
13
|
|
|
16
14
|
</template>
|
|
17
15
|
|
|
18
16
|
<script setup>
|
|
19
|
-
import Breadcrumbs from '@/components/Breadcrumbs.vue';
|
|
17
|
+
import Breadcrumbs from '@/components/Breadcrumbs.vue';
|
|
18
|
+
import PageNotFound from '@/views/PageNotFound.vue';
|
|
20
19
|
|
|
21
20
|
import { useCoreStore } from '@/stores/core';
|
|
22
21
|
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
<div class="h-2 bg-lightListSkeletLoader rounded-full dark:bg-darkListSkeletLoader max-w-[360px]"></div>
|
|
11
11
|
</div>
|
|
12
12
|
</div>
|
|
13
|
-
<table v-else class="
|
|
13
|
+
<table v-else class="w-full text-sm text-left rtl:text-right text-lightListTableText dark:text-darkListTableText rounded-default">
|
|
14
14
|
|
|
15
15
|
<tbody>
|
|
16
16
|
<!-- table header -->
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
<!-- table header end -->
|
|
65
65
|
<SkeleteLoader
|
|
66
66
|
v-if="!rows"
|
|
67
|
-
:columns="resource?.columns.filter((c:
|
|
67
|
+
:columns="resource?.columns.filter((c: AdminForthResourceColumnCommon) => c.showIn?.list).length + 2"
|
|
68
68
|
:rows="rowHeights.length || 3"
|
|
69
69
|
:row-heights="rowHeights"
|
|
70
70
|
:column-widths="columnWidths"
|
|
@@ -182,7 +182,7 @@
|
|
|
182
182
|
|
|
183
183
|
<template v-if="resource.options?.actions">
|
|
184
184
|
<Tooltip
|
|
185
|
-
v-for="action in resource.options.actions.filter(a => a.showIn?.list
|
|
185
|
+
v-for="action in resource.options.actions.filter(a => a.showIn?.list)"
|
|
186
186
|
:key="action.id"
|
|
187
187
|
>
|
|
188
188
|
<component
|
|
@@ -339,7 +339,7 @@ import {
|
|
|
339
339
|
} from '@iconify-prerendered/vue-flowbite';
|
|
340
340
|
import router from '@/router';
|
|
341
341
|
import { Tooltip } from '@/afcl';
|
|
342
|
-
import type { AdminForthResourceCommon,
|
|
342
|
+
import type { AdminForthResourceCommon, AdminForthResourceColumnCommon, AdminForthComponentDeclarationFull } from '@/types/Common';
|
|
343
343
|
import { useAdminforth } from '@/adminforth';
|
|
344
344
|
import Checkbox from '@/afcl/Checkbox.vue';
|
|
345
345
|
import ListActionsThreeDots from '@/components/ListActionsThreeDots.vue';
|
|
@@ -360,7 +360,7 @@ const props = defineProps<{
|
|
|
360
360
|
customActionsInjection?: any[],
|
|
361
361
|
tableBodyStartInjection?: any[],
|
|
362
362
|
customActionIconsThreeDotsMenuItems?: any[]
|
|
363
|
-
tableRowReplaceInjection?:
|
|
363
|
+
tableRowReplaceInjection?: AdminForthComponentDeclarationFull,
|
|
364
364
|
}>();
|
|
365
365
|
|
|
366
366
|
// emits, update page
|
|
@@ -436,7 +436,7 @@ watch(() => props.rows, (newRows) => {
|
|
|
436
436
|
columnWidths.value = newRows || !headerRefs.value ? [] : [48, ...headerRefs.value.map((el: HTMLElement) => el.offsetWidth)];
|
|
437
437
|
});
|
|
438
438
|
|
|
439
|
-
function addToCheckedValues(id: string) {
|
|
439
|
+
function addToCheckedValues(id: string | number) {
|
|
440
440
|
if (checkboxesInternal.value.includes(id)) {
|
|
441
441
|
checkboxesInternal.value = checkboxesInternal.value.filter((item) => item !== id);
|
|
442
442
|
} else {
|
|
@@ -468,7 +468,7 @@ const allFromThisPageChecked = computed(() => {
|
|
|
468
468
|
if (!props.rows || !props.rows.length) return false;
|
|
469
469
|
return props.rows.every((r) => checkboxesInternal.value.includes(r._primaryKeyValue));
|
|
470
470
|
});
|
|
471
|
-
const ascArr = computed(() => sort.value.filter((s:any) => s.direction === 'asc').map((s: any) => s.field));
|
|
471
|
+
const ascArr = computed(() => sort.value.filter((s: any) => s.direction === 'asc').map((s: any) => s.field));
|
|
472
472
|
const descArr = computed(() => sort.value.filter((s: any) => s.direction === 'desc').map((s: any) => s.field));
|
|
473
473
|
|
|
474
474
|
|
|
@@ -487,9 +487,9 @@ function onSortButtonClick(event: any, field: string) {
|
|
|
487
487
|
} else {
|
|
488
488
|
const sortField = sort.value[sortIndex];
|
|
489
489
|
if (sortField.direction === 'asc') {
|
|
490
|
-
sort.value = sort.value.map((s
|
|
490
|
+
sort.value = sort.value.map((s) => s.field === field ? {field, direction: 'desc'} : s);
|
|
491
491
|
} else {
|
|
492
|
-
sort.value = sort.value.filter((s
|
|
492
|
+
sort.value = sort.value.filter((s) => s.field !== field);
|
|
493
493
|
}
|
|
494
494
|
}
|
|
495
495
|
}
|
|
@@ -576,7 +576,7 @@ async function deleteRecord(row: any) {
|
|
|
576
576
|
const actionLoadingStates = ref<Record<string | number, boolean>>({});
|
|
577
577
|
|
|
578
578
|
async function startCustomAction(actionId: string, row: any, extraData: Record<string, any> = {}) {
|
|
579
|
-
|
|
579
|
+
|
|
580
580
|
actionLoadingStates.value[actionId] = true;
|
|
581
581
|
|
|
582
582
|
const data = await callAdminForthApi({
|
|
@@ -586,7 +586,7 @@ async function startCustomAction(actionId: string, row: any, extraData: Record<s
|
|
|
586
586
|
resourceId: props.resource?.resourceId,
|
|
587
587
|
actionId: actionId,
|
|
588
588
|
recordId: row._primaryKeyValue,
|
|
589
|
-
extra: extraData
|
|
589
|
+
extra: extraData
|
|
590
590
|
}
|
|
591
591
|
});
|
|
592
592
|
|
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
|
|
19
19
|
<tbody>
|
|
20
20
|
<!-- table header -->
|
|
21
|
-
<tr class="t-header sticky z-20 top-0 text-xs
|
|
22
|
-
<td scope="col" class="list-table-header-cell
|
|
21
|
+
<tr class="t-header sticky z-20 top-0 text-xs text-lightListTableHeadingText bg-lightListTableHeading dark:bg-darkListTableHeading dark:text-darkListTableHeadingText">
|
|
22
|
+
<td scope="col" class="list-table-header-cell p-4 sticky-column bg-lightListTableHeading dark:bg-darkListTableHeading">
|
|
23
23
|
<Checkbox
|
|
24
24
|
:modelValue="allFromThisPageChecked"
|
|
25
25
|
:disabled="!rows || !rows.length"
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
</Checkbox>
|
|
30
30
|
</td>
|
|
31
31
|
|
|
32
|
-
<td v-for="c in columnsListed" ref="headerRefs" scope="col" class="list-table-header-cell
|
|
32
|
+
<td v-for="c in columnsListed" ref="headerRefs" scope="col" class="list-table-header-cell px-2 md:px-3 lg:px-6 py-3" :class="{'sticky-column bg-lightListTableHeading dark:bg-darkListTableHeading': c.listSticky}">
|
|
33
33
|
|
|
34
34
|
<div @click="(evt) => c.sortable && onSortButtonClick(evt, c.name)"
|
|
35
35
|
class="flex items-center " :class="{'cursor-pointer':c.sortable}">
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
<SkeleteLoader
|
|
70
70
|
v-if="!rows"
|
|
71
71
|
:columns="resource?.columns.filter((c: AdminForthResourceColumnCommon) => c.showIn?.list).length + 2"
|
|
72
|
-
:rows="rowHeights.length ||
|
|
72
|
+
:rows="rowHeights.length || 3"
|
|
73
73
|
:row-heights="rowHeights"
|
|
74
74
|
:column-widths="columnWidths"
|
|
75
75
|
/>
|
|
@@ -94,7 +94,6 @@
|
|
|
94
94
|
|
|
95
95
|
<!-- Visible rows -->
|
|
96
96
|
<component
|
|
97
|
-
v-else
|
|
98
97
|
v-for="(row, rowI) in visibleRows"
|
|
99
98
|
:is="tableRowReplaceInjection ? getCustomComponent(tableRowReplaceInjection) : 'tr'"
|
|
100
99
|
:key="`row_${row._primaryKeyValue}`"
|
|
@@ -108,7 +107,7 @@
|
|
|
108
107
|
:class="{'border-b': rowI !== visibleRows.length - 1, 'cursor-pointer': row._clickUrl !== null}"
|
|
109
108
|
@mounted="(el: any) => updateRowHeight(`row_${row._primaryKeyValue}`, el.offsetHeight)"
|
|
110
109
|
>
|
|
111
|
-
<td class="w-4 p-4 cursor-default sticky-column bg-
|
|
110
|
+
<td class="w-4 p-4 cursor-default sticky-column bg-lightListTable dark:bg-darkListTable" @click="(e)=>e.stopPropagation()">
|
|
112
111
|
<Checkbox
|
|
113
112
|
:model-value="checkboxesInternal.includes(row._primaryKeyValue)"
|
|
114
113
|
@change="(e: any)=>{addToCheckedValues(row._primaryKeyValue)}"
|
|
@@ -116,7 +115,7 @@
|
|
|
116
115
|
>
|
|
117
116
|
<span class="sr-only">{{ $t('checkbox') }}</span>
|
|
118
117
|
</Checkbox>
|
|
119
|
-
|
|
118
|
+
</td>
|
|
120
119
|
<td v-for="c in columnsListed" class="px-2 md:px-3 lg:px-6 py-4" :class="{'sticky-column bg-lightListTable dark:bg-darkListTable': c.listSticky}">
|
|
121
120
|
<!-- if c.name in listComponentsPerColumn, render it. If not, render ValueRenderer -->
|
|
122
121
|
<component
|
|
@@ -177,7 +176,7 @@
|
|
|
177
176
|
<template v-slot:tooltip>
|
|
178
177
|
{{ $t('Delete item') }}
|
|
179
178
|
</template>
|
|
180
|
-
</Tooltip>
|
|
179
|
+
</Tooltip>
|
|
181
180
|
<template v-if="customActionsInjection">
|
|
182
181
|
<component
|
|
183
182
|
v-for="c in customActionsInjection"
|
|
@@ -191,7 +190,7 @@
|
|
|
191
190
|
</template>
|
|
192
191
|
<template v-if="resource.options?.actions">
|
|
193
192
|
<Tooltip
|
|
194
|
-
v-for="action in resource.options.actions.filter(a => a.showIn?.list
|
|
193
|
+
v-for="action in resource.options.actions.filter(a => a.showIn?.list)"
|
|
195
194
|
:key="action.id"
|
|
196
195
|
>
|
|
197
196
|
<CallActionWrapper
|
|
@@ -251,9 +250,9 @@
|
|
|
251
250
|
<!-- pagination
|
|
252
251
|
totalRows in v-if is used to not hide page input during loading when user puts cursor into it and edit directly (rows gets null there during edit)
|
|
253
252
|
-->
|
|
254
|
-
<div class="flex flex-row items-center mt-4 xs:flex-row xs:justify-between xs:items-center gap-3">
|
|
253
|
+
<div class="af-pagination-container flex flex-row items-center mt-4 xs:flex-row xs:justify-between xs:items-center gap-3">
|
|
255
254
|
|
|
256
|
-
<div class="inline-flex "
|
|
255
|
+
<div class="af-pagination-buttons-container inline-flex "
|
|
257
256
|
v-if="(rows || totalRows) && totalRows >= pageSize && totalRows > 0"
|
|
258
257
|
>
|
|
259
258
|
<!-- Buttons -->
|
|
@@ -279,11 +278,10 @@
|
|
|
279
278
|
type="text"
|
|
280
279
|
v-model="pageInput"
|
|
281
280
|
:style="{ width: `${Math.max(1, pageInput.length+4)}ch` }"
|
|
282
|
-
class="af-pagination-input min-w-10 outline-none inline-block
|
|
281
|
+
class="af-pagination-input min-w-10 outline-none inline-block py-1.5 px-3 text-sm text-center text-lightListTablePaginationCurrentPageText border border-lightListTablePaginationBorder dark:border-darkListTablePaginationBorder dark:text-darkListTablePaginationCurrentPageText dark:bg-darkListTablePaginationBackgoround z-10"
|
|
283
282
|
@keydown="onPageKeydown($event)"
|
|
284
283
|
@blur="validatePageInput()"
|
|
285
|
-
|
|
286
|
-
</input>
|
|
284
|
+
/>
|
|
287
285
|
|
|
288
286
|
<button
|
|
289
287
|
class="af-pagination-last-page-button flex items-center py-1 px-3 text-sm font-medium text-lightListTablePaginationText focus:outline-none bg-lightListTablePaginationBackgoround border-l-0 border border-lightListTablePaginationBorder hover:bg-lightListTablePaginationBackgoroundHover hover:text-lightListTablePaginationTextHover focus:z-10 focus:ring-4 focus:ring-lightListTablePaginationFocusRing dark:focus:ring-darkListTablePaginationFocusRing dark:bg-darkListTablePaginationBackgoround dark:text-darkListTablePaginationText dark:border-darkListTablePaginationBorder dark:hover:text-white dark:hover:bg-darkListTablePaginationBackgoroundHover disabled:opacity-50"
|
|
@@ -309,7 +307,7 @@
|
|
|
309
307
|
<span v-if="((((page || 1) - 1) * pageSize + 1 > totalRows) && totalRows > 0)">{{ $t('Wrong Page') }} </span>
|
|
310
308
|
<template v-else-if="resource && totalRows > 0">
|
|
311
309
|
|
|
312
|
-
<span class="hidden sm:inline">
|
|
310
|
+
<span class="af-pagination-info hidden sm:inline">
|
|
313
311
|
<i18n-t keypath="Showing {from} to {to} of {total} Entries" tag="p" >
|
|
314
312
|
<template v-slot:from>
|
|
315
313
|
<strong>{{ from }}</strong>
|
|
@@ -343,7 +341,7 @@
|
|
|
343
341
|
<script setup lang="ts">
|
|
344
342
|
|
|
345
343
|
|
|
346
|
-
import { computed, onMounted, ref, watch, useTemplateRef, nextTick, type Ref
|
|
344
|
+
import { computed, onMounted, ref, watch, useTemplateRef, nextTick, type Ref } from 'vue';
|
|
347
345
|
import { callAdminForthApi } from '@/utils';
|
|
348
346
|
import { useI18n } from 'vue-i18n';
|
|
349
347
|
import ValueRenderer from '@/components/ValueRenderer.vue';
|
|
@@ -352,18 +350,15 @@ import { useCoreStore } from '@/stores/core';
|
|
|
352
350
|
import { showSuccesTost, showErrorTost } from '@/composables/useFrontendApi';
|
|
353
351
|
import SkeleteLoader from '@/components/SkeleteLoader.vue';
|
|
354
352
|
import { getIcon } from '@/utils';
|
|
355
|
-
import {
|
|
356
|
-
IconInboxOutline,
|
|
357
|
-
} from '@iconify-prerendered/vue-flowbite';
|
|
358
|
-
|
|
359
353
|
import {
|
|
360
354
|
IconEyeSolid,
|
|
361
355
|
IconPenSolid,
|
|
362
|
-
IconTrashBinSolid
|
|
356
|
+
IconTrashBinSolid,
|
|
357
|
+
IconInboxOutline
|
|
363
358
|
} from '@iconify-prerendered/vue-flowbite';
|
|
364
359
|
import router from '@/router';
|
|
365
360
|
import { Tooltip } from '@/afcl';
|
|
366
|
-
import type { AdminForthResourceCommon, AdminForthResourceColumnCommon,
|
|
361
|
+
import type { AdminForthResourceCommon, AdminForthResourceColumnCommon, AdminForthComponentDeclarationFull } from '@/types/Common';
|
|
367
362
|
import { useAdminforth } from '@/adminforth';
|
|
368
363
|
import Checkbox from '@/afcl/Checkbox.vue';
|
|
369
364
|
import ListActionsThreeDots from '@/components/ListActionsThreeDots.vue';
|
|
@@ -387,7 +382,7 @@ const props = defineProps<{
|
|
|
387
382
|
itemHeight?: number,
|
|
388
383
|
bufferSize?: number,
|
|
389
384
|
customActionIconsThreeDotsMenuItems?: any[]
|
|
390
|
-
tableRowReplaceInjection?:
|
|
385
|
+
tableRowReplaceInjection?: AdminForthComponentDeclarationFull
|
|
391
386
|
}>();
|
|
392
387
|
|
|
393
388
|
// emits, update page
|
|
@@ -463,7 +458,7 @@ watch(() => props.rows, (newRows) => {
|
|
|
463
458
|
columnWidths.value = newRows || !headerRefs.value ? [] : [48, ...headerRefs.value.map((el: HTMLElement) => el.offsetWidth)];
|
|
464
459
|
});
|
|
465
460
|
|
|
466
|
-
function addToCheckedValues(id:
|
|
461
|
+
function addToCheckedValues(id: string | number) {
|
|
467
462
|
if (checkboxesInternal.value.includes(id)) {
|
|
468
463
|
checkboxesInternal.value = checkboxesInternal.value.filter((item) => item !== id);
|
|
469
464
|
} else {
|
|
@@ -499,7 +494,7 @@ const ascArr = computed(() => sort.value.filter((s: any) => s.direction === 'asc
|
|
|
499
494
|
const descArr = computed(() => sort.value.filter((s: any) => s.direction === 'desc').map((s: any) => s.field));
|
|
500
495
|
|
|
501
496
|
|
|
502
|
-
function onSortButtonClick(event: any, field:
|
|
497
|
+
function onSortButtonClick(event: any, field: string) {
|
|
503
498
|
// if ctrl key is pressed, add to sort otherwise sort by this field
|
|
504
499
|
// in any case if field is already in sort, toggle direction
|
|
505
500
|
|
|
@@ -524,7 +519,7 @@ function onSortButtonClick(event: any, field: any) {
|
|
|
524
519
|
|
|
525
520
|
const clickTarget = ref(null);
|
|
526
521
|
|
|
527
|
-
async function onClick(e: any,row: any) {
|
|
522
|
+
async function onClick(e: any, row: any) {
|
|
528
523
|
if(clickTarget.value === e.target) return;
|
|
529
524
|
clickTarget.value = e.target;
|
|
530
525
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
'-translate-x-full': !sideBarOpen,
|
|
10
10
|
'transform-none': sideBarOpen,
|
|
11
11
|
'sidebar-collapsed': iconOnlySidebarEnabled && isSidebarIconOnly && !isSidebarHovering,
|
|
12
|
-
'sidebar-expanded': !iconOnlySidebarEnabled || !isSidebarIconOnly || (isSidebarIconOnly && isSidebarHovering)
|
|
12
|
+
'sidebar-expanded': !iconOnlySidebarEnabled || !isSidebarIconOnly || (isSidebarIconOnly && isSidebarHovering),
|
|
13
|
+
'sidebar-floating': isSidebarIconOnly && isSidebarHovering
|
|
13
14
|
}"
|
|
14
15
|
aria-label="Sidebar"
|
|
15
16
|
>
|
|
@@ -217,6 +218,9 @@
|
|
|
217
218
|
|
|
218
219
|
.sidebar-expanded {
|
|
219
220
|
width: v-bind(expandedWidth); /* Expanded width (w-64) */
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
.sidebar-floating {
|
|
220
224
|
box-shadow: 3px 0px 12px -2px rgba(0, 0, 0, 0.15);
|
|
221
225
|
}
|
|
222
226
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<Tooltip>
|
|
2
|
+
<component :is="shouldShowTooltip ? Tooltip : 'span'">
|
|
3
3
|
<span class="flex items-center">
|
|
4
4
|
<CountryFlag class="w-[1.6rem] h-[1.2rem]" :countryCode="countryIsoLow" />
|
|
5
5
|
<span v-if="meta.showCountryName" class="ms-2">{{ countryName }}</span>
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
<template v-if="shouldShowTooltip" #tooltip>
|
|
9
9
|
{{ countryName }}
|
|
10
10
|
</template>
|
|
11
|
-
</
|
|
11
|
+
</component>
|
|
12
12
|
</template>
|
|
13
13
|
|
|
14
14
|
<script setup>
|
|
@@ -183,9 +183,23 @@ export interface IAdminForthDataSourceConnector {
|
|
|
183
183
|
* For string fields:
|
|
184
184
|
* - {@link AdminForthResourceColumn.maxLength}
|
|
185
185
|
* For numbers:
|
|
186
|
+
* // min/max are used inside getMinMaxForColumns from base connector
|
|
186
187
|
* - {@link AdminForthResourceColumn.min}
|
|
187
188
|
* - {@link AdminForthResourceColumn.max}
|
|
188
|
-
* - {@link AdminForthResourceColumn.minValue},
|
|
189
|
+
* - {@link AdminForthResourceColumn.minValue},
|
|
190
|
+
* - {@link AdminForthResourceColumn.maxValue},
|
|
191
|
+
* - {@link AdminForthResourceColumn.enum},
|
|
192
|
+
* - {@link AdminForthResourceColumn.foreignResource},
|
|
193
|
+
* - {@link AdminForthResourceColumn.sortable},
|
|
194
|
+
* - {@link AdminForthResourceColumn.backendOnly},
|
|
195
|
+
* - {@link AdminForthResourceColumn.masked},
|
|
196
|
+
* - {@link AdminForthResourceColumn.virtual},
|
|
197
|
+
* - {@link AdminForthResourceColumn.components},
|
|
198
|
+
* - {@link AdminForthResourceColumn.allowMinMaxQuery},
|
|
199
|
+
* - {@link AdminForthResourceColumn.editingNote},
|
|
200
|
+
* - {@link AdminForthResourceColumn.showIn},
|
|
201
|
+
* - {@link AdminForthResourceColumn.isUnique},
|
|
202
|
+
* - {@link AdminForthResourceColumn.validation})
|
|
189
203
|
* Also you can additionally save original column type to {@link AdminForthResourceColumn._underlineType}. This might be later used
|
|
190
204
|
* in {@link IAdminForthDataSourceConnector.getFieldValue} and {@link IAdminForthDataSourceConnector.setFieldValue} methods.
|
|
191
205
|
*
|
|
@@ -292,6 +306,8 @@ export interface IAdminForthDataSourceConnectorBase extends IAdminForthDataSourc
|
|
|
292
306
|
}): Promise<{ok: boolean, error?: string}>;
|
|
293
307
|
|
|
294
308
|
getMinMaxForColumns({ resource, columns }: { resource: AdminForthResource, columns: AdminForthResourceColumn[] }): Promise<{ [key: string]: { min: any, max: any } }>;
|
|
309
|
+
|
|
310
|
+
deleteMany?({resource, recordIds}:{resource: AdminForthResource, recordIds: any[]}): Promise<number>;
|
|
295
311
|
}
|
|
296
312
|
|
|
297
313
|
|
|
@@ -1811,7 +1827,6 @@ export type AllowedActions = {
|
|
|
1811
1827
|
*/
|
|
1812
1828
|
export interface ResourceOptionsInput extends Omit<NonNullable<AdminForthResourceInputCommon['options']>, 'allowedActions' | 'bulkActions'> {
|
|
1813
1829
|
|
|
1814
|
-
baseActionsAsQuickIcons?: ('show' | 'edit' | 'delete')[],
|
|
1815
1830
|
/**
|
|
1816
1831
|
* Custom bulk actions list. Bulk actions available in list view when user selects multiple records by
|
|
1817
1832
|
* using checkboxes.
|
|
@@ -371,6 +371,14 @@ export interface AdminForthResourceInputCommon {
|
|
|
371
371
|
* General options for resource.
|
|
372
372
|
*/
|
|
373
373
|
options?: {
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Show quick action icons for base actions (show, edit, delete) in list view.
|
|
378
|
+
* By default, they are inside three dots dropdown menu.
|
|
379
|
+
*/
|
|
380
|
+
baseActionsAsQuickIcons?: ('show' | 'edit' | 'delete')[],
|
|
381
|
+
|
|
374
382
|
|
|
375
383
|
/**
|
|
376
384
|
* Default sort for list view.
|
|
@@ -956,6 +964,18 @@ export interface AdminForthResourceColumnCommon extends AdminForthResourceColumn
|
|
|
956
964
|
|
|
957
965
|
editingNote?: { create?: string, edit?: string },
|
|
958
966
|
|
|
967
|
+
/*
|
|
968
|
+
______________________________________________
|
|
969
|
+
| |
|
|
970
|
+
| Min and max values are used |
|
|
971
|
+
| in getMinMaxForColumns from base connector |
|
|
972
|
+
|_____________________________________________|
|
|
973
|
+
|
|
|
974
|
+
|
|
|
975
|
+
|
|
|
976
|
+
|
|
|
977
|
+
V
|
|
978
|
+
*/
|
|
959
979
|
/**
|
|
960
980
|
* Minimal value stored in this field.
|
|
961
981
|
*/
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<div class="mx-auto max-w-screen-sm text-center">
|
|
5
5
|
<h1 class="mb-4 text-7xl tracking-tight font-extrabold lg:text-9xl text-lightPrimary dark:text-darkPrimary">404</h1>
|
|
6
6
|
<p class="mb-4 text-3xl tracking-tight font-bold text-gray-900 md:text-4xl dark:text-white">{{ $t("Something's missing.") }}</p>
|
|
7
|
-
<p class="mb-4 text-lg font-light text-gray-500 dark:text-gray-400">{{ $t("Sorry, we can't find that page. You'll find lots to explore on the home page.") }} </p>
|
|
7
|
+
<p class="mb-4 text-lg font-light text-gray-500 dark:text-gray-400">{{ props.errorMessage ? $t(props.errorMessage) : $t("Sorry, we can't find that page. You'll find lots to explore on the home page.") }} </p>
|
|
8
8
|
<div class="flex justify-center">
|
|
9
9
|
<LinkButton to="/">{{ $t('Go back home') }}</LinkButton>
|
|
10
10
|
</div>
|
|
@@ -17,4 +17,8 @@
|
|
|
17
17
|
|
|
18
18
|
import { LinkButton } from '@/afcl';
|
|
19
19
|
|
|
20
|
+
const props = defineProps<{
|
|
21
|
+
errorMessage?: string
|
|
22
|
+
}>();
|
|
23
|
+
|
|
20
24
|
</script>
|
package/dist/types/Back.d.ts
CHANGED
|
@@ -138,9 +138,23 @@ export interface IAdminForthDataSourceConnector {
|
|
|
138
138
|
* For string fields:
|
|
139
139
|
* - {@link AdminForthResourceColumn.maxLength}
|
|
140
140
|
* For numbers:
|
|
141
|
+
* // min/max are used inside getMinMaxForColumns from base connector
|
|
141
142
|
* - {@link AdminForthResourceColumn.min}
|
|
142
143
|
* - {@link AdminForthResourceColumn.max}
|
|
143
|
-
* - {@link AdminForthResourceColumn.minValue},
|
|
144
|
+
* - {@link AdminForthResourceColumn.minValue},
|
|
145
|
+
* - {@link AdminForthResourceColumn.maxValue},
|
|
146
|
+
* - {@link AdminForthResourceColumn.enum},
|
|
147
|
+
* - {@link AdminForthResourceColumn.foreignResource},
|
|
148
|
+
* - {@link AdminForthResourceColumn.sortable},
|
|
149
|
+
* - {@link AdminForthResourceColumn.backendOnly},
|
|
150
|
+
* - {@link AdminForthResourceColumn.masked},
|
|
151
|
+
* - {@link AdminForthResourceColumn.virtual},
|
|
152
|
+
* - {@link AdminForthResourceColumn.components},
|
|
153
|
+
* - {@link AdminForthResourceColumn.allowMinMaxQuery},
|
|
154
|
+
* - {@link AdminForthResourceColumn.editingNote},
|
|
155
|
+
* - {@link AdminForthResourceColumn.showIn},
|
|
156
|
+
* - {@link AdminForthResourceColumn.isUnique},
|
|
157
|
+
* - {@link AdminForthResourceColumn.validation})
|
|
144
158
|
* Also you can additionally save original column type to {@link AdminForthResourceColumn._underlineType}. This might be later used
|
|
145
159
|
* in {@link IAdminForthDataSourceConnector.getFieldValue} and {@link IAdminForthDataSourceConnector.setFieldValue} methods.
|
|
146
160
|
*
|
|
@@ -266,6 +280,10 @@ export interface IAdminForthDataSourceConnectorBase extends IAdminForthDataSourc
|
|
|
266
280
|
max: any;
|
|
267
281
|
};
|
|
268
282
|
}>;
|
|
283
|
+
deleteMany?({ resource, recordIds }: {
|
|
284
|
+
resource: AdminForthResource;
|
|
285
|
+
recordIds: any[];
|
|
286
|
+
}): Promise<number>;
|
|
269
287
|
}
|
|
270
288
|
export interface IAdminForthDataSourceConnectorConstructor {
|
|
271
289
|
new (): IAdminForthDataSourceConnectorBase;
|
|
@@ -1573,7 +1591,6 @@ export type AllowedActions = {
|
|
|
1573
1591
|
* General options for resource.
|
|
1574
1592
|
*/
|
|
1575
1593
|
export interface ResourceOptionsInput extends Omit<NonNullable<AdminForthResourceInputCommon['options']>, 'allowedActions' | 'bulkActions'> {
|
|
1576
|
-
baseActionsAsQuickIcons?: ('show' | 'edit' | 'delete')[];
|
|
1577
1594
|
/**
|
|
1578
1595
|
* Custom bulk actions list. Bulk actions available in list view when user selects multiple records by
|
|
1579
1596
|
* using checkboxes.
|