adminforth 2.4.0-next.21 → 2.4.0-next.210
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/commands/callTsProxy.js +14 -4
- package/commands/cli.js +10 -3
- package/commands/createApp/templates/custom/tsconfig.json.hbs +2 -3
- package/commands/createApp/templates/index.ts.hbs +10 -2
- package/commands/createApp/templates/package.json.hbs +1 -1
- package/commands/createApp/utils.js +27 -2
- package/commands/createCustomComponent/configLoader.js +3 -0
- package/commands/createCustomComponent/main.js +1 -0
- package/commands/createCustomComponent/templates/customCrud/beforeActionButtons.vue.hbs +38 -0
- package/commands/createPlugin/templates/custom/tsconfig.json.hbs +2 -5
- package/commands/createPlugin/templates/package.json.hbs +1 -1
- package/dist/auth.d.ts +9 -1
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +15 -2
- package/dist/auth.js.map +1 -1
- package/dist/dataConnectors/baseConnector.d.ts.map +1 -1
- package/dist/dataConnectors/baseConnector.js +46 -15
- package/dist/dataConnectors/baseConnector.js.map +1 -1
- package/dist/dataConnectors/clickhouse.d.ts.map +1 -1
- package/dist/dataConnectors/clickhouse.js +15 -0
- package/dist/dataConnectors/clickhouse.js.map +1 -1
- package/dist/dataConnectors/mongo.d.ts.map +1 -1
- package/dist/dataConnectors/mongo.js +44 -15
- package/dist/dataConnectors/mongo.js.map +1 -1
- 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.map +1 -1
- package/dist/dataConnectors/postgres.js +11 -0
- package/dist/dataConnectors/postgres.js.map +1 -1
- 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 +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +20 -9
- package/dist/index.js.map +1 -1
- package/dist/modules/codeInjector.d.ts +2 -0
- package/dist/modules/codeInjector.d.ts.map +1 -1
- package/dist/modules/codeInjector.js +52 -8
- package/dist/modules/codeInjector.js.map +1 -1
- package/dist/modules/configValidator.d.ts.map +1 -1
- package/dist/modules/configValidator.js +74 -7
- package/dist/modules/configValidator.js.map +1 -1
- package/dist/modules/restApi.d.ts.map +1 -1
- package/dist/modules/restApi.js +154 -26
- package/dist/modules/restApi.js.map +1 -1
- package/dist/modules/styles.d.ts +503 -13
- package/dist/modules/styles.d.ts.map +1 -1
- package/dist/modules/styles.js +559 -31
- package/dist/modules/styles.js.map +1 -1
- package/dist/modules/utils.d.ts +2 -0
- package/dist/modules/utils.d.ts.map +1 -1
- package/dist/modules/utils.js +16 -0
- package/dist/modules/utils.js.map +1 -1
- package/dist/servers/express.d.ts.map +1 -1
- package/dist/servers/express.js +14 -0
- package/dist/servers/express.js.map +1 -1
- package/dist/spa/index.html +1 -1
- package/dist/spa/package-lock.json +5 -4
- package/dist/spa/package.json +1 -1
- package/dist/spa/src/App.vue +54 -169
- package/dist/spa/src/adminforth.ts +42 -18
- package/dist/spa/src/afcl/BarChart.vue +2 -2
- package/dist/spa/src/afcl/Button.vue +6 -6
- package/dist/spa/src/afcl/ButtonGroup.vue +91 -0
- package/dist/spa/src/afcl/Card.vue +25 -0
- package/dist/spa/src/afcl/Checkbox.vue +21 -13
- package/dist/spa/src/afcl/CountryFlag.vue +4 -1
- package/dist/spa/src/{components/CustomDatePicker.vue → afcl/DatePicker.vue} +95 -9
- package/dist/spa/src/afcl/Dialog.vue +44 -27
- package/dist/spa/src/afcl/Dropzone.vue +12 -12
- package/dist/spa/src/afcl/Input.vue +6 -6
- package/dist/spa/src/afcl/JsonViewer.vue +25 -0
- package/dist/spa/src/afcl/LinkButton.vue +3 -3
- package/dist/spa/src/afcl/PieChart.vue +5 -5
- package/dist/spa/src/afcl/ProgressBar.vue +7 -7
- package/dist/spa/src/afcl/Select.vue +68 -34
- package/dist/spa/src/afcl/Skeleton.vue +6 -6
- package/dist/spa/src/afcl/Table.vue +213 -74
- package/dist/spa/src/afcl/Textarea.vue +31 -0
- package/dist/spa/src/afcl/Toggle.vue +32 -0
- package/dist/spa/src/afcl/Tooltip.vue +1 -2
- package/dist/spa/src/afcl/VerticalTabs.vue +16 -7
- package/dist/spa/src/afcl/index.ts +6 -3
- package/dist/spa/src/components/AcceptModal.vue +7 -7
- package/dist/spa/src/components/Breadcrumbs.vue +5 -5
- package/dist/spa/src/components/ColumnValueInput.vue +38 -18
- package/dist/spa/src/components/ColumnValueInputWrapper.vue +4 -3
- package/dist/spa/src/components/CustomDateRangePicker.vue +9 -8
- package/dist/spa/src/components/CustomRangePicker.vue +37 -8
- package/dist/spa/src/components/ErrorMessage.vue +21 -0
- package/dist/spa/src/components/Filters.vue +85 -39
- package/dist/spa/src/components/GroupsTable.vue +9 -8
- package/dist/spa/src/components/MenuLink.vue +90 -23
- package/dist/spa/src/components/ResourceForm.vue +94 -51
- package/dist/spa/src/components/ResourceListTable.vue +78 -80
- package/dist/spa/src/components/ResourceListTableVirtual.vue +71 -73
- package/dist/spa/src/components/ShowTable.vue +17 -12
- package/dist/spa/src/components/Sidebar.vue +448 -0
- package/dist/spa/src/components/SingleSkeletLoader.vue +6 -6
- package/dist/spa/src/components/SkeleteLoader.vue +3 -3
- package/dist/spa/src/components/ThreeDotsMenu.vue +73 -14
- package/dist/spa/src/components/Toast.vue +27 -9
- package/dist/spa/src/components/UserMenuSettingsButton.vue +70 -0
- package/dist/spa/src/components/ValueRenderer.vue +43 -16
- package/dist/spa/src/controls/BoolToggle.vue +34 -0
- package/dist/spa/src/i18n.ts +1 -1
- package/dist/spa/src/renderers/CompactField.vue +1 -1
- package/dist/spa/src/renderers/CompactUUID.vue +1 -1
- package/dist/spa/src/router/index.ts +8 -0
- package/dist/spa/src/shims-vue.d.ts +5 -0
- package/dist/spa/src/spa_types/core.ts +13 -1
- package/dist/spa/src/stores/core.ts +1 -1
- package/dist/spa/src/stores/filters.ts +29 -2
- package/dist/spa/src/stores/modal.ts +6 -1
- package/dist/spa/src/stores/toast.ts +22 -3
- package/dist/spa/src/types/Back.ts +137 -22
- package/dist/spa/src/types/Common.ts +67 -32
- package/dist/spa/src/types/FrontendAPI.ts +31 -5
- package/dist/spa/src/types/adapters/CaptchaAdapter.ts +34 -0
- package/dist/spa/src/types/adapters/CompletionAdapter.ts +25 -0
- package/dist/spa/src/types/adapters/EmailAdapter.ts +27 -0
- package/dist/spa/src/types/adapters/ImageGenerationAdapter.ts +50 -0
- package/dist/spa/src/types/adapters/ImageVisionAdapter.ts +30 -0
- package/dist/spa/src/types/adapters/KeyValueAdapter.ts +16 -0
- package/dist/spa/src/types/adapters/OAuth2Adapter.ts +34 -0
- package/dist/spa/src/types/adapters/StorageAdapter.ts +73 -0
- package/dist/spa/src/types/adapters/index.ts +8 -0
- package/dist/spa/src/utils.ts +219 -8
- package/dist/spa/src/views/CreateView.vue +18 -19
- package/dist/spa/src/views/EditView.vue +25 -19
- package/dist/spa/src/views/ListView.vue +139 -86
- package/dist/spa/src/views/LoginView.vue +31 -37
- package/dist/spa/src/views/ResourceParent.vue +2 -2
- package/dist/spa/src/views/SettingsView.vue +121 -0
- package/dist/spa/src/views/ShowView.vue +59 -39
- package/dist/spa/src/websocket.ts +6 -1
- package/dist/spa/tsconfig.app.json +1 -1
- package/dist/spa/vite.config.ts +45 -2
- package/dist/types/Back.d.ts +115 -14
- package/dist/types/Back.d.ts.map +1 -1
- package/dist/types/Back.js +15 -0
- package/dist/types/Back.js.map +1 -1
- package/dist/types/Common.d.ts +59 -29
- package/dist/types/Common.d.ts.map +1 -1
- package/dist/types/Common.js.map +1 -1
- package/dist/types/FrontendAPI.d.ts +31 -3
- package/dist/types/FrontendAPI.d.ts.map +1 -1
- package/dist/types/FrontendAPI.js.map +1 -1
- package/dist/types/adapters/CaptchaAdapter.d.ts +30 -0
- package/dist/types/adapters/CaptchaAdapter.d.ts.map +1 -0
- package/dist/types/adapters/CaptchaAdapter.js +5 -0
- package/dist/types/adapters/CaptchaAdapter.js.map +1 -0
- package/dist/types/adapters/CompletionAdapter.d.ts +20 -0
- package/dist/types/adapters/CompletionAdapter.d.ts.map +1 -0
- package/dist/types/adapters/CompletionAdapter.js +2 -0
- package/dist/types/adapters/CompletionAdapter.js.map +1 -0
- package/dist/types/adapters/EmailAdapter.d.ts +20 -0
- package/dist/types/adapters/EmailAdapter.d.ts.map +1 -0
- package/dist/types/adapters/EmailAdapter.js +2 -0
- package/dist/types/adapters/EmailAdapter.js.map +1 -0
- package/dist/types/adapters/ImageGenerationAdapter.d.ts +37 -0
- package/dist/types/adapters/ImageGenerationAdapter.d.ts.map +1 -0
- package/dist/types/adapters/ImageGenerationAdapter.js +2 -0
- package/dist/types/adapters/ImageGenerationAdapter.js.map +1 -0
- package/dist/types/adapters/ImageVisionAdapter.d.ts +25 -0
- package/dist/types/adapters/ImageVisionAdapter.d.ts.map +1 -0
- package/dist/types/adapters/ImageVisionAdapter.js +2 -0
- package/dist/types/adapters/ImageVisionAdapter.js.map +1 -0
- package/dist/types/adapters/KeyValueAdapter.d.ts +10 -0
- package/dist/types/adapters/KeyValueAdapter.d.ts.map +1 -0
- package/dist/types/adapters/KeyValueAdapter.js +2 -0
- package/dist/types/adapters/KeyValueAdapter.js.map +1 -0
- package/dist/types/adapters/OAuth2Adapter.d.ts +32 -0
- package/dist/types/adapters/OAuth2Adapter.d.ts.map +1 -0
- package/dist/types/adapters/OAuth2Adapter.js +2 -0
- package/dist/types/adapters/OAuth2Adapter.js.map +1 -0
- package/dist/types/adapters/StorageAdapter.d.ts +63 -0
- package/dist/types/adapters/StorageAdapter.d.ts.map +1 -0
- package/dist/types/adapters/StorageAdapter.js +2 -0
- package/dist/types/adapters/StorageAdapter.js.map +1 -0
- package/dist/types/adapters/index.d.ts +9 -0
- package/dist/types/adapters/index.d.ts.map +1 -0
- package/dist/types/adapters/index.js +2 -0
- package/dist/types/adapters/index.js.map +1 -0
- package/package.json +3 -2
- package/dist/spa/src/types/Adapters.ts +0 -213
- package/dist/types/Adapters.d.ts +0 -168
- package/dist/types/Adapters.d.ts.map +0 -1
- package/dist/types/Adapters.js +0 -2
- package/dist/types/Adapters.js.map +0 -1
|
@@ -6,24 +6,23 @@
|
|
|
6
6
|
<!-- skelet loader -->
|
|
7
7
|
<div role="status" v-if="!resource || !resource.columns"
|
|
8
8
|
class="max-w p-4 space-y-4 divide-y divide-gray-200 rounded shadow animate-pulse dark:divide-gray-700 md:p-6 dark:border-gray-700">
|
|
9
|
-
|
|
10
9
|
<div role="status" class="max-w-sm animate-pulse">
|
|
11
|
-
<div class="h-2 bg-
|
|
10
|
+
<div class="h-2 bg-lightListSkeletLoader rounded-full dark:bg-darkListSkeletLoader max-w-[360px]"></div>
|
|
12
11
|
</div>
|
|
13
12
|
</div>
|
|
14
|
-
<table v-else class=" w-full text-sm text-left rtl:text-right text-
|
|
13
|
+
<table v-else class=" w-full text-sm text-left rtl:text-right text-lightListTableText dark:text-darkListTableText rounded-default">
|
|
15
14
|
|
|
16
15
|
<tbody>
|
|
17
16
|
<!-- table header -->
|
|
18
|
-
<tr class="t-header sticky z-10 top-0 text-xs
|
|
17
|
+
<tr class="t-header sticky z-10 top-0 text-xs text-lightListTableHeadingText bg-lightListTableHeading dark:bg-darkListTableHeading dark:text-darkListTableHeadingText">
|
|
19
18
|
<td scope="col" class="p-4">
|
|
20
|
-
<
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
<
|
|
26
|
-
</
|
|
19
|
+
<Checkbox
|
|
20
|
+
:modelValue="allFromThisPageChecked"
|
|
21
|
+
:disabled="!rows || !rows.length"
|
|
22
|
+
@update:modelValue="selectAll"
|
|
23
|
+
>
|
|
24
|
+
<span class="sr-only">{{ $t('checkbox') }}</span>
|
|
25
|
+
</Checkbox>
|
|
27
26
|
</td>
|
|
28
27
|
|
|
29
28
|
<td v-for="c in columnsListed" ref="headerRefs" scope="col" class="px-2 md:px-3 lg:px-6 py-3">
|
|
@@ -48,8 +47,8 @@
|
|
|
48
47
|
</div>
|
|
49
48
|
<span
|
|
50
49
|
class="bg-red-100 text-red-800 text-xs font-medium me-1 px-1 py-0.5 rounded dark:bg-gray-700 dark:text-red-400 border border-red-400"
|
|
51
|
-
v-if="sort.findIndex((s) => s.field === c.name) !== -1 && sort?.length > 1">
|
|
52
|
-
{{ sort.findIndex((s) => s.field === c.name) + 1 }}
|
|
50
|
+
v-if="sort.findIndex((s: any) => s.field === c.name) !== -1 && sort?.length > 1">
|
|
51
|
+
{{ sort.findIndex((s: any) => s.field === c.name) + 1 }}
|
|
53
52
|
</span>
|
|
54
53
|
|
|
55
54
|
</div>
|
|
@@ -65,7 +64,7 @@
|
|
|
65
64
|
<!-- table header end -->
|
|
66
65
|
<SkeleteLoader
|
|
67
66
|
v-if="!rows"
|
|
68
|
-
:columns="resource?.columns.filter(c => c.showIn
|
|
67
|
+
:columns="resource?.columns.filter((c: AdminForthResourceColumnInputCommon) => c.showIn?.list).length + 2"
|
|
69
68
|
:rows="rowHeights.length || 3"
|
|
70
69
|
:row-heights="rowHeights"
|
|
71
70
|
:column-widths="columnWidths"
|
|
@@ -91,23 +90,21 @@
|
|
|
91
90
|
|
|
92
91
|
:class="{'border-b': rowI !== rows.length - 1, 'cursor-pointer': row._clickUrl !== null}"
|
|
93
92
|
>
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
</div>
|
|
105
|
-
</td>
|
|
93
|
+
<td class="w-4 p-4 cursor-default" @click="(e)=>e.stopPropagation()">
|
|
94
|
+
<Checkbox
|
|
95
|
+
:model-value="checkboxesInternal.includes(row._primaryKeyValue)"
|
|
96
|
+
@change="(e: any)=>{addToCheckedValues(row._primaryKeyValue)}"
|
|
97
|
+
@click="(e: any)=>e.stopPropagation()"
|
|
98
|
+
>
|
|
99
|
+
<span class="sr-only">{{ $t('checkbox') }}</span>
|
|
100
|
+
</Checkbox>
|
|
101
|
+
</td>
|
|
102
|
+
|
|
106
103
|
<td v-for="c in columnsListed" class="px-2 md:px-3 lg:px-6 py-4">
|
|
107
104
|
<!-- if c.name in listComponentsPerColumn, render it. If not, render ValueRenderer -->
|
|
108
105
|
<component
|
|
109
|
-
:is="c?.components?.list ? getCustomComponent(c.components.list) : ValueRenderer"
|
|
110
|
-
:meta="c?.components?.list
|
|
106
|
+
:is="c?.components?.list ? getCustomComponent(typeof c.components.list === 'string' ? { file: c.components.list } : c.components.list) : ValueRenderer"
|
|
107
|
+
:meta="typeof c?.components?.list === 'object' ? c.components.list.meta : undefined"
|
|
111
108
|
:column="c"
|
|
112
109
|
:record="row"
|
|
113
110
|
:adminUser="coreStore.adminUser"
|
|
@@ -118,7 +115,7 @@
|
|
|
118
115
|
<div class="flex text-lightPrimary dark:text-darkPrimary items-center">
|
|
119
116
|
<Tooltip>
|
|
120
117
|
<RouterLink
|
|
121
|
-
v-if="resource.options?.allowedActions
|
|
118
|
+
v-if="resource.options?.allowedActions?.show"
|
|
122
119
|
:to="{
|
|
123
120
|
name: 'resource-show',
|
|
124
121
|
params: {
|
|
@@ -128,7 +125,7 @@
|
|
|
128
125
|
}"
|
|
129
126
|
|
|
130
127
|
>
|
|
131
|
-
<IconEyeSolid class="w-5 h-5 me-2"/>
|
|
128
|
+
<IconEyeSolid class="af-show-icon w-5 h-5 me-2"/>
|
|
132
129
|
</RouterLink>
|
|
133
130
|
|
|
134
131
|
<template v-slot:tooltip>
|
|
@@ -138,7 +135,7 @@
|
|
|
138
135
|
|
|
139
136
|
<Tooltip>
|
|
140
137
|
<RouterLink
|
|
141
|
-
v-if="resource.options?.allowedActions
|
|
138
|
+
v-if="resource.options?.allowedActions?.edit"
|
|
142
139
|
:to="{
|
|
143
140
|
name: 'resource-edit',
|
|
144
141
|
params: {
|
|
@@ -147,7 +144,7 @@
|
|
|
147
144
|
}
|
|
148
145
|
}"
|
|
149
146
|
>
|
|
150
|
-
<IconPenSolid class="w-5 h-5 me-2"/>
|
|
147
|
+
<IconPenSolid class="af-edit-icon w-5 h-5 me-2"/>
|
|
151
148
|
</RouterLink>
|
|
152
149
|
<template v-slot:tooltip>
|
|
153
150
|
{{ $t('Edit item') }}
|
|
@@ -156,10 +153,10 @@
|
|
|
156
153
|
|
|
157
154
|
<Tooltip>
|
|
158
155
|
<button
|
|
159
|
-
v-if="resource.options?.allowedActions
|
|
156
|
+
v-if="resource.options?.allowedActions?.delete"
|
|
160
157
|
@click="deleteRecord(row)"
|
|
161
158
|
>
|
|
162
|
-
<IconTrashBinSolid class="w-5 h-5 me-2"/>
|
|
159
|
+
<IconTrashBinSolid class="af-delete-icon w-5 h-5 me-2"/>
|
|
163
160
|
</button>
|
|
164
161
|
|
|
165
162
|
<template v-slot:tooltip>
|
|
@@ -199,14 +196,14 @@
|
|
|
199
196
|
<!-- pagination
|
|
200
197
|
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)
|
|
201
198
|
-->
|
|
202
|
-
<div class="flex flex-row items-center mt-4 xs:flex-row xs:justify-between xs:items-center gap-3"
|
|
203
|
-
v-if="(rows || totalRows) && totalRows >= pageSize && totalRows > 0"
|
|
204
|
-
>
|
|
199
|
+
<div class="af-pagination-container flex flex-row items-center mt-4 xs:flex-row xs:justify-between xs:items-center gap-3">
|
|
205
200
|
|
|
206
|
-
<div class="inline-flex "
|
|
201
|
+
<div class="af-pagination-buttons-container inline-flex "
|
|
202
|
+
v-if="(rows || totalRows) && totalRows >= pageSize && totalRows > 0"
|
|
203
|
+
>
|
|
207
204
|
<!-- Buttons -->
|
|
208
205
|
<button
|
|
209
|
-
class="flex items-center py-1 px-3 gap-1 text-sm font-medium text-
|
|
206
|
+
class="af-pagination-prev-button flex items-center py-1 px-3 gap-1 text-sm font-medium text-lightListTablePaginationText focus:outline-none bg-lightListTablePaginationBackgoround border-r-0 rounded-s 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-darkListTablePaginationTextHover dark:hover:bg-darkListTablePaginationBackgoroundHover disabled:opacity-50"
|
|
210
207
|
@click="page--; pageInput = page.toString();" :disabled="page <= 1">
|
|
211
208
|
<svg class="w-3.5 h-3.5 rtl:rotate-180" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none"
|
|
212
209
|
viewBox="0 0 14 10">
|
|
@@ -218,14 +215,14 @@
|
|
|
218
215
|
</span>
|
|
219
216
|
</button>
|
|
220
217
|
<button
|
|
221
|
-
class="flex items-center py-1 px-3 text-sm font-medium text-
|
|
218
|
+
class="af-pagination-first-page-button flex items-center py-1 px-3 text-sm font-medium text-lightListTablePaginationText focus:outline-none bg-lightListTablePaginationBackgoround border-r-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-darkListTablePaginationTextHover dark:hover:bg-darkListTablePaginationBackgoroundHover disabled:opacity-50"
|
|
222
219
|
@click="page = 1; pageInput = page.toString();" :disabled="page <= 1">
|
|
223
220
|
<!-- <IconChevronDoubleLeftOutline class="w-4 h-4" /> -->
|
|
224
221
|
1
|
|
225
222
|
</button>
|
|
226
223
|
<div
|
|
227
224
|
contenteditable="true"
|
|
228
|
-
class="min-w-10 outline-none inline-block w-auto
|
|
225
|
+
class="af-pagination-input min-w-10 outline-none inline-block w-auto 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"
|
|
229
226
|
@keydown="onPageKeydown($event)"
|
|
230
227
|
@input="onPageInput($event)"
|
|
231
228
|
@blur="validatePageInput()"
|
|
@@ -234,14 +231,14 @@
|
|
|
234
231
|
</div>
|
|
235
232
|
|
|
236
233
|
<button
|
|
237
|
-
class="flex items-center py-1 px-3 text-sm font-medium text-
|
|
234
|
+
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"
|
|
238
235
|
@click="page = totalPages; pageInput = page.toString();" :disabled="page >= totalPages">
|
|
239
236
|
{{ totalPages }}
|
|
240
237
|
|
|
241
238
|
<!-- <IconChevronDoubleRightOutline class="w-4 h-4" /> -->
|
|
242
239
|
</button>
|
|
243
240
|
<button
|
|
244
|
-
class="flex items-center py-1 px-3 gap-1 text-sm font-medium text-
|
|
241
|
+
class="af-pagination-next-button flex items-center py-1 px-3 gap-1 text-sm font-medium text-lightListTablePaginationText focus:outline-none bg-lightListTablePaginationBackgoround border-l-0 rounded-e 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"
|
|
245
242
|
@click="page++; pageInput = page.toString();" :disabled="page >= totalPages">
|
|
246
243
|
<span class="hidden sm:inline">{{ $t('Next') }}</span>
|
|
247
244
|
<svg class="w-3.5 h-3.5 rtl:rotate-180" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none"
|
|
@@ -253,11 +250,11 @@
|
|
|
253
250
|
</div>
|
|
254
251
|
|
|
255
252
|
<!-- Help text -->
|
|
256
|
-
<span class="text-sm text-
|
|
257
|
-
<span v-if="((page || 1) - 1) * pageSize + 1 > totalRows">{{ $t('Wrong Page') }} </span>
|
|
258
|
-
<template v-else>
|
|
253
|
+
<span class="text-sm text-lightListTablePaginationHelpText dark:text-darkListTablePaginationHelpText">
|
|
254
|
+
<span v-if="((((page || 1) - 1) * pageSize + 1 > totalRows) && totalRows > 0)">{{ $t('Wrong Page') }} </span>
|
|
255
|
+
<template v-else-if="resource && totalRows > 0">
|
|
259
256
|
|
|
260
|
-
<span class="hidden sm:inline">
|
|
257
|
+
<span class="af-pagination-info hidden sm:inline">
|
|
261
258
|
<i18n-t keypath="Showing {from} to {to} of {total} Entries" tag="p" >
|
|
262
259
|
<template v-slot:from>
|
|
263
260
|
<strong>{{ from }}</strong>
|
|
@@ -307,12 +304,13 @@ import {
|
|
|
307
304
|
import {
|
|
308
305
|
IconEyeSolid,
|
|
309
306
|
IconPenSolid,
|
|
310
|
-
IconTrashBinSolid
|
|
307
|
+
IconTrashBinSolid,
|
|
311
308
|
} from '@iconify-prerendered/vue-flowbite';
|
|
312
309
|
import router from '@/router';
|
|
313
310
|
import { Tooltip } from '@/afcl';
|
|
314
|
-
import type { AdminForthResourceCommon } from '@/types/Common';
|
|
311
|
+
import type { AdminForthResourceCommon, AdminForthResourceColumnInputCommon, AdminForthResourceColumnCommon } from '@/types/Common';
|
|
315
312
|
import adminforth from '@/adminforth';
|
|
313
|
+
import Checkbox from '@/afcl/Checkbox.vue';
|
|
316
314
|
|
|
317
315
|
const coreStore = useCoreStore();
|
|
318
316
|
const { t } = useI18n();
|
|
@@ -341,7 +339,7 @@ const emits = defineEmits([
|
|
|
341
339
|
const checkboxesInternal: Ref<any[]> = ref([]);
|
|
342
340
|
const pageInput = ref('1');
|
|
343
341
|
const page = ref(1);
|
|
344
|
-
const sort = ref([]);
|
|
342
|
+
const sort: Ref<Array<{field: string, direction: string}>> = ref([]);
|
|
345
343
|
|
|
346
344
|
|
|
347
345
|
const from = computed(() => ((page.value || 1) - 1) * props.pageSize + 1);
|
|
@@ -350,11 +348,11 @@ const to = computed(() => Math.min((page.value || 1) * props.pageSize, props.tot
|
|
|
350
348
|
watch(() => page.value, (newPage) => {
|
|
351
349
|
emits('update:page', newPage);
|
|
352
350
|
});
|
|
353
|
-
async function onPageKeydown(event) {
|
|
351
|
+
async function onPageKeydown(event: any) {
|
|
354
352
|
// page input should accept only numbers, arrow keys and backspace
|
|
355
353
|
if (['Enter', 'Space'].includes(event.code) ||
|
|
356
354
|
(!['Backspace', 'ArrowRight', 'ArrowLeft'].includes(event.code)
|
|
357
|
-
&& isNaN(String.fromCharCode(event.keyCode)))) {
|
|
355
|
+
&& isNaN(Number(String.fromCharCode(event.keyCode || 0))))) {
|
|
358
356
|
event.preventDefault();
|
|
359
357
|
if (event.code === 'Enter') {
|
|
360
358
|
validatePageInput();
|
|
@@ -375,7 +373,7 @@ watch(() => props.checkboxes, (newCheckboxes) => {
|
|
|
375
373
|
checkboxesInternal.value = newCheckboxes;
|
|
376
374
|
});
|
|
377
375
|
|
|
378
|
-
watch(() => props.sort, (newSort) => {
|
|
376
|
+
watch(() => props.sort, (newSort: any) => {
|
|
379
377
|
sort.value = newSort;
|
|
380
378
|
});
|
|
381
379
|
|
|
@@ -386,17 +384,17 @@ watch(() => props.page, (newPage) => {
|
|
|
386
384
|
page.value = newPage;
|
|
387
385
|
});
|
|
388
386
|
|
|
389
|
-
const rowRefs = useTemplateRef('rowRefs');
|
|
390
|
-
const headerRefs = useTemplateRef('headerRefs');
|
|
391
|
-
const rowHeights = ref([]);
|
|
392
|
-
const columnWidths = ref([]);
|
|
387
|
+
const rowRefs = useTemplateRef<HTMLElement[]>('rowRefs');
|
|
388
|
+
const headerRefs = useTemplateRef<HTMLElement[]>('headerRefs');
|
|
389
|
+
const rowHeights = ref<number[]>([]);
|
|
390
|
+
const columnWidths = ref<number[]>([]);
|
|
393
391
|
watch(() => props.rows, (newRows) => {
|
|
394
392
|
// rows are set to null when new records are loading
|
|
395
|
-
rowHeights.value = newRows || !rowRefs.value ? [] : rowRefs.value.map((el) => el.offsetHeight);
|
|
396
|
-
columnWidths.value = newRows || !headerRefs.value ? [] : [48, ...headerRefs.value.map((el) => el.offsetWidth)];
|
|
393
|
+
rowHeights.value = newRows || !rowRefs.value ? [] : rowRefs.value.map((el: HTMLElement) => el.offsetHeight);
|
|
394
|
+
columnWidths.value = newRows || !headerRefs.value ? [] : [48, ...headerRefs.value.map((el: HTMLElement) => el.offsetWidth)];
|
|
397
395
|
});
|
|
398
396
|
|
|
399
|
-
function addToCheckedValues(id) {
|
|
397
|
+
function addToCheckedValues(id: string) {
|
|
400
398
|
if (checkboxesInternal.value.includes(id)) {
|
|
401
399
|
checkboxesInternal.value = checkboxesInternal.value.filter((item) => item !== id);
|
|
402
400
|
} else {
|
|
@@ -405,17 +403,17 @@ function addToCheckedValues(id) {
|
|
|
405
403
|
checkboxesInternal.value = [ ...checkboxesInternal.value ]
|
|
406
404
|
}
|
|
407
405
|
|
|
408
|
-
const columnsListed = computed(() => props.resource?.columns?.filter(c => c.showIn
|
|
406
|
+
const columnsListed = computed(() => props.resource?.columns?.filter((c: AdminForthResourceColumnCommon) => c.showIn?.list));
|
|
409
407
|
|
|
410
|
-
async function selectAll(
|
|
408
|
+
async function selectAll() {
|
|
411
409
|
if (!allFromThisPageChecked.value) {
|
|
412
|
-
props.rows
|
|
410
|
+
props.rows?.forEach((r) => {
|
|
413
411
|
if (!checkboxesInternal.value.includes(r._primaryKeyValue)) {
|
|
414
412
|
checkboxesInternal.value.push(r._primaryKeyValue)
|
|
415
413
|
}
|
|
416
414
|
});
|
|
417
415
|
} else {
|
|
418
|
-
props.rows
|
|
416
|
+
props.rows?.forEach((r) => {
|
|
419
417
|
checkboxesInternal.value = checkboxesInternal.value.filter((item) => item !== r._primaryKeyValue);
|
|
420
418
|
});
|
|
421
419
|
}
|
|
@@ -428,15 +426,15 @@ const allFromThisPageChecked = computed(() => {
|
|
|
428
426
|
if (!props.rows || !props.rows.length) return false;
|
|
429
427
|
return props.rows.every((r) => checkboxesInternal.value.includes(r._primaryKeyValue));
|
|
430
428
|
});
|
|
431
|
-
const ascArr = computed(() => sort.value.filter((s) => s.direction === 'asc').map((s) => s.field));
|
|
432
|
-
const descArr = computed(() => sort.value.filter((s) => s.direction === 'desc').map((s) => s.field));
|
|
429
|
+
const ascArr = computed(() => sort.value.filter((s:any) => s.direction === 'asc').map((s: any) => s.field));
|
|
430
|
+
const descArr = computed(() => sort.value.filter((s: any) => s.direction === 'desc').map((s: any) => s.field));
|
|
433
431
|
|
|
434
432
|
|
|
435
|
-
function onSortButtonClick(event, field) {
|
|
433
|
+
function onSortButtonClick(event: any, field: string) {
|
|
436
434
|
// if ctrl key is pressed, add to sort otherwise sort by this field
|
|
437
435
|
// in any case if field is already in sort, toggle direction
|
|
438
436
|
|
|
439
|
-
const sortIndex = sort.value.findIndex((s) => s.field === field);
|
|
437
|
+
const sortIndex = sort.value.findIndex((s: any) => s.field === field);
|
|
440
438
|
if (sortIndex === -1) {
|
|
441
439
|
// field is not in sort, add it
|
|
442
440
|
if (event.ctrlKey) {
|
|
@@ -447,9 +445,9 @@ function onSortButtonClick(event, field) {
|
|
|
447
445
|
} else {
|
|
448
446
|
const sortField = sort.value[sortIndex];
|
|
449
447
|
if (sortField.direction === 'asc') {
|
|
450
|
-
sort.value = sort.value.map((s) => s.field === field ? {field, direction: 'desc'} : s);
|
|
448
|
+
sort.value = sort.value.map((s: any) => s.field === field ? {field, direction: 'desc'} : s);
|
|
451
449
|
} else {
|
|
452
|
-
sort.value = sort.value.filter((s) => s.field !== field);
|
|
450
|
+
sort.value = sort.value.filter((s: any) => s.field !== field);
|
|
453
451
|
}
|
|
454
452
|
}
|
|
455
453
|
}
|
|
@@ -457,11 +455,11 @@ function onSortButtonClick(event, field) {
|
|
|
457
455
|
|
|
458
456
|
const clickTarget = ref(null);
|
|
459
457
|
|
|
460
|
-
async function onClick(e,row) {
|
|
458
|
+
async function onClick(e: any, row: any) {
|
|
461
459
|
if(clickTarget.value === e.target) return;
|
|
462
460
|
clickTarget.value = e.target;
|
|
463
461
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
464
|
-
if (window.getSelection()
|
|
462
|
+
if (window.getSelection()?.toString()) return;
|
|
465
463
|
else {
|
|
466
464
|
if (row._clickUrl === null) {
|
|
467
465
|
// user asked to nothing on click
|
|
@@ -476,7 +474,7 @@ async function onClick(e,row) {
|
|
|
476
474
|
router.resolve({
|
|
477
475
|
name: 'resource-show',
|
|
478
476
|
params: {
|
|
479
|
-
resourceId: props.resource
|
|
477
|
+
resourceId: props.resource?.resourceId,
|
|
480
478
|
primaryKey: row._primaryKeyValue,
|
|
481
479
|
},
|
|
482
480
|
}).href,
|
|
@@ -494,7 +492,7 @@ async function onClick(e,row) {
|
|
|
494
492
|
router.push({
|
|
495
493
|
name: 'resource-show',
|
|
496
494
|
params: {
|
|
497
|
-
resourceId: props.resource
|
|
495
|
+
resourceId: props.resource?.resourceId,
|
|
498
496
|
primaryKey: row._primaryKeyValue,
|
|
499
497
|
},
|
|
500
498
|
});
|
|
@@ -503,7 +501,7 @@ async function onClick(e,row) {
|
|
|
503
501
|
}
|
|
504
502
|
}
|
|
505
503
|
|
|
506
|
-
async function deleteRecord(row) {
|
|
504
|
+
async function deleteRecord(row: any) {
|
|
507
505
|
const data = await adminforth.confirm({
|
|
508
506
|
message: t('Are you sure you want to delete this item?'),
|
|
509
507
|
yes: t('Delete'),
|
|
@@ -515,7 +513,7 @@ async function deleteRecord(row) {
|
|
|
515
513
|
path: '/delete_record',
|
|
516
514
|
method: 'POST',
|
|
517
515
|
body: {
|
|
518
|
-
resourceId: props.resource
|
|
516
|
+
resourceId: props.resource?.resourceId,
|
|
519
517
|
primaryKey: row._primaryKeyValue,
|
|
520
518
|
}
|
|
521
519
|
});
|
|
@@ -533,16 +531,16 @@ async function deleteRecord(row) {
|
|
|
533
531
|
}
|
|
534
532
|
}
|
|
535
533
|
|
|
536
|
-
const actionLoadingStates = ref({});
|
|
534
|
+
const actionLoadingStates = ref<Record<string | number, boolean>>({});
|
|
537
535
|
|
|
538
|
-
async function startCustomAction(actionId, row) {
|
|
536
|
+
async function startCustomAction(actionId: string, row: any) {
|
|
539
537
|
actionLoadingStates.value[actionId] = true;
|
|
540
538
|
|
|
541
539
|
const data = await callAdminForthApi({
|
|
542
540
|
path: '/start_custom_action',
|
|
543
541
|
method: 'POST',
|
|
544
542
|
body: {
|
|
545
|
-
resourceId: props.resource
|
|
543
|
+
resourceId: props.resource?.resourceId,
|
|
546
544
|
actionId: actionId,
|
|
547
545
|
recordId: row._primaryKeyValue
|
|
548
546
|
}
|
|
@@ -580,7 +578,7 @@ async function startCustomAction(actionId, row) {
|
|
|
580
578
|
}
|
|
581
579
|
}
|
|
582
580
|
|
|
583
|
-
function onPageInput(event) {
|
|
581
|
+
function onPageInput(event: any) {
|
|
584
582
|
pageInput.value = event.target.innerText;
|
|
585
583
|
}
|
|
586
584
|
|