adminforth 2.7.18 → 2.8.0
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/createApp/templates/index.ts.hbs +2 -1
- 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/dist/dataConnectors/baseConnector.d.ts.map +1 -1
- package/dist/dataConnectors/baseConnector.js +33 -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 +30 -1
- 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/modules/codeInjector.d.ts +1 -0
- package/dist/modules/codeInjector.d.ts.map +1 -1
- package/dist/modules/codeInjector.js +4 -0
- package/dist/modules/codeInjector.js.map +1 -1
- package/dist/modules/configValidator.d.ts.map +1 -1
- package/dist/modules/configValidator.js +6 -2
- package/dist/modules/configValidator.js.map +1 -1
- package/dist/modules/restApi.d.ts.map +1 -1
- package/dist/modules/restApi.js +2 -0
- package/dist/modules/restApi.js.map +1 -1
- package/dist/modules/styles.d.ts +8 -1
- package/dist/modules/styles.d.ts.map +1 -1
- package/dist/modules/styles.js +9 -2
- package/dist/modules/styles.js.map +1 -1
- package/dist/spa/src/App.vue +12 -4
- package/dist/spa/src/adminforth.ts +31 -11
- package/dist/spa/src/afcl/BarChart.vue +2 -2
- package/dist/spa/src/afcl/Checkbox.vue +2 -2
- package/dist/spa/src/afcl/Dialog.vue +38 -21
- package/dist/spa/src/afcl/Dropzone.vue +2 -2
- package/dist/spa/src/afcl/Input.vue +1 -1
- package/dist/spa/src/afcl/LinkButton.vue +1 -1
- package/dist/spa/src/afcl/PieChart.vue +5 -5
- package/dist/spa/src/afcl/Select.vue +17 -12
- package/dist/spa/src/afcl/Table.vue +202 -72
- package/dist/spa/src/afcl/Textarea.vue +31 -0
- package/dist/spa/src/afcl/Toggle.vue +2 -2
- package/dist/spa/src/afcl/Tooltip.vue +0 -1
- package/dist/spa/src/afcl/index.ts +1 -1
- package/dist/spa/src/components/AcceptModal.vue +1 -1
- package/dist/spa/src/components/ColumnValueInput.vue +11 -11
- package/dist/spa/src/components/ColumnValueInputWrapper.vue +2 -2
- package/dist/spa/src/components/CustomRangePicker.vue +5 -5
- package/dist/spa/src/components/ErrorMessage.vue +21 -0
- package/dist/spa/src/components/Filters.vue +7 -6
- package/dist/spa/src/components/GroupsTable.vue +2 -1
- package/dist/spa/src/components/MenuLink.vue +3 -3
- package/dist/spa/src/components/ResourceForm.vue +35 -27
- package/dist/spa/src/components/ResourceListTable.vue +42 -42
- package/dist/spa/src/components/ResourceListTableVirtual.vue +41 -41
- package/dist/spa/src/components/ShowTable.vue +3 -3
- package/dist/spa/src/components/SkeleteLoader.vue +2 -2
- package/dist/spa/src/components/ThreeDotsMenu.vue +69 -10
- package/dist/spa/src/components/Toast.vue +25 -2
- package/dist/spa/src/components/ValueRenderer.vue +39 -12
- package/dist/spa/src/i18n.ts +1 -1
- package/dist/spa/src/shims-vue.d.ts +5 -0
- package/dist/spa/src/spa_types/core.ts +1 -1
- 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 +31 -6
- package/dist/spa/src/types/Common.ts +33 -24
- package/dist/spa/src/types/FrontendAPI.ts +21 -5
- package/dist/spa/src/types/adapters/EmailAdapter.ts +2 -4
- package/dist/spa/src/types/adapters/ImageVisionAdapter.ts +30 -0
- package/dist/spa/src/types/adapters/index.ts +1 -0
- package/dist/spa/src/utils.ts +8 -7
- package/dist/spa/src/views/CreateView.vue +15 -16
- package/dist/spa/src/views/EditView.vue +23 -17
- package/dist/spa/src/views/ListView.vue +116 -66
- package/dist/spa/src/views/LoginView.vue +2 -9
- package/dist/spa/src/views/ResourceParent.vue +1 -1
- 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 +16 -1
- 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 +27 -22
- package/dist/types/Common.d.ts.map +1 -1
- package/dist/types/Common.js.map +1 -1
- package/dist/types/FrontendAPI.d.ts +21 -3
- package/dist/types/FrontendAPI.d.ts.map +1 -1
- package/dist/types/FrontendAPI.js.map +1 -1
- package/dist/types/adapters/EmailAdapter.d.ts +2 -3
- package/dist/types/adapters/EmailAdapter.d.ts.map +1 -1
- 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/index.d.ts +1 -0
- package/dist/types/adapters/index.d.ts.map +1 -1
- package/package.json +2 -1
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
<Teleport to="body">
|
|
4
4
|
<Filters
|
|
5
5
|
:columns="coreStore.resource?.columns"
|
|
6
|
-
:columnsMinMax="columnsMinMax"
|
|
6
|
+
:columnsMinMax="columnsMinMax"
|
|
7
|
+
:show="filtersShow"
|
|
7
8
|
@hide="filtersShow = false"
|
|
8
9
|
/>
|
|
9
10
|
</Teleport>
|
|
@@ -11,12 +12,19 @@
|
|
|
11
12
|
<component
|
|
12
13
|
v-for="c in coreStore?.resourceOptions?.pageInjections?.list?.beforeBreadcrumbs || []"
|
|
13
14
|
:is="getCustomComponent(c)"
|
|
14
|
-
:meta="c.meta"
|
|
15
|
+
:meta="(c as AdminForthComponentDeclarationFull).meta"
|
|
15
16
|
:resource="coreStore.resource"
|
|
16
17
|
:adminUser="coreStore.adminUser"
|
|
17
18
|
/>
|
|
18
19
|
|
|
19
20
|
<BreadcrumbsWithButtons>
|
|
21
|
+
<component
|
|
22
|
+
v-for="c in coreStore?.resourceOptions?.pageInjections?.list?.beforeActionButtons || []"
|
|
23
|
+
:is="getCustomComponent(c)"
|
|
24
|
+
:meta="(c as AdminForthComponentDeclarationFull).meta"
|
|
25
|
+
:resource="coreStore.resource"
|
|
26
|
+
:adminUser="coreStore.adminUser"
|
|
27
|
+
/>
|
|
20
28
|
<button
|
|
21
29
|
@click="()=>{checkboxes = []}"
|
|
22
30
|
v-if="checkboxes.length"
|
|
@@ -31,47 +39,47 @@
|
|
|
31
39
|
</Tooltip>
|
|
32
40
|
</button>
|
|
33
41
|
|
|
34
|
-
|
|
35
|
-
v-if="checkboxes.length"
|
|
42
|
+
<div
|
|
43
|
+
v-if="checkboxes.length"
|
|
36
44
|
v-for="(action,i) in coreStore.resource?.options?.bulkActions"
|
|
37
|
-
:key="action.id"
|
|
38
|
-
@click="startBulkAction(action.id)"
|
|
39
|
-
class="flex gap-1 items-center py-1 px-3 text-sm font-medium text-lightListViewButtonText focus:outline-none bg-lightListViewButtonBackground rounded-default border border-lightListViewButtonBorder hover:bg-lightListViewButtonBackgroundHover hover:text-lightListViewButtonTextHover focus:z-10 focus:ring-4 focus:ring-lightListViewButtonFocusRing dark:focus:ring-darkListViewButtonFocusRing dark:bg-darkListViewButtonBackground dark:text-darkListViewButtonText dark:border-darkListViewButtonBorder dark:hover:text-darkListViewButtonTextHover dark:hover:bg-darkListViewButtonBackgroundHover"
|
|
40
|
-
:class="action.buttonCustomCssClass || ''"
|
|
41
45
|
>
|
|
42
|
-
<
|
|
43
|
-
v-if="
|
|
44
|
-
:
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
{{ action.
|
|
67
|
-
|
|
68
|
-
|
|
46
|
+
<button
|
|
47
|
+
v-if="!action.showInThreeDotsDropdown"
|
|
48
|
+
:key="action.id"
|
|
49
|
+
@click="startBulkAction(action.id!)"
|
|
50
|
+
class="flex gap-1 items-center py-1 px-3 text-sm font-medium text-lightListViewButtonText focus:outline-none bg-lightListViewButtonBackground rounded-default border border-lightListViewButtonBorder hover:bg-lightListViewButtonBackgroundHover hover:text-lightListViewButtonTextHover focus:z-10 focus:ring-4 focus:ring-lightListViewButtonFocusRing dark:focus:ring-darkListViewButtonFocusRing dark:bg-darkListViewButtonBackground dark:text-darkListViewButtonText dark:border-darkListViewButtonBorder dark:hover:text-darkListViewButtonTextHover dark:hover:bg-darkListViewButtonBackgroundHover"
|
|
51
|
+
:class="action.buttonCustomCssClass || ''"
|
|
52
|
+
>
|
|
53
|
+
<component
|
|
54
|
+
v-if="action.icon && !bulkActionLoadingStates[action.id!]"
|
|
55
|
+
:is="getIcon(action.icon)"
|
|
56
|
+
class="w-5 h-5 transition duration-75 group-hover:text-gray-900 dark:group-hover:text-white"></component>
|
|
57
|
+
<div v-if="bulkActionLoadingStates[action.id!]">
|
|
58
|
+
<svg
|
|
59
|
+
aria-hidden="true"
|
|
60
|
+
class="w-5 h-5 animate-spin text-gray-200 dark:text-gray-500 fill-gray-500 dark:fill-gray-300"
|
|
61
|
+
viewBox="0 0 100 101"
|
|
62
|
+
fill="none"
|
|
63
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
64
|
+
>
|
|
65
|
+
<path d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z" fill="currentColor"/>
|
|
66
|
+
<path d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z" fill="currentFill"/>
|
|
67
|
+
</svg>
|
|
68
|
+
<span class="sr-only">Loading...</span>
|
|
69
|
+
</div>
|
|
70
|
+
{{ `${action.label} (${checkboxes.length})` }}
|
|
71
|
+
<div v-if="action.badge" class="text-white bg-gradient-to-r from-purple-500 via-purple-600 to-purple-700 hover:bg-gradient-to-br focus:ring-4 focus:outline-none focus:ring-purple-300 dark:focus:ring-purple-800
|
|
72
|
+
font-medium rounded-sm text-xs px-1 ml-1 text-center ">
|
|
73
|
+
{{ action.badge }}
|
|
74
|
+
</div>
|
|
75
|
+
</button>
|
|
76
|
+
</div>
|
|
69
77
|
|
|
70
78
|
<RouterLink v-if="coreStore.resource?.options?.allowedActions?.create"
|
|
71
79
|
:to="{ name: 'resource-create', params: { resourceId: $route.params.resourceId } }"
|
|
72
|
-
class="af-create-button flex items-center py-1 px-3 text-sm font-medium text-lightListViewButtonText focus:outline-none bg-lightListViewButtonBackground rounded border border-lightListViewButtonBorder hover:bg-lightListViewButtonBackgroundHover hover:text-lightListViewButtonTextHover focus:z-10 focus:ring-4 focus:ring-lightListViewButtonFocusRing dark:focus:ring-darkListViewButtonFocusRing dark:bg-darkListViewButtonBackground dark:text-darkListViewButtonText dark:border-darkListViewButtonBorder dark:hover:text-darkListViewButtonTextHover dark:hover:bg-darkListViewButtonBackgroundHover rounded-default"
|
|
80
|
+
class="af-create-button flex items-center py-1 px-3 text-sm font-medium text-lightListViewButtonText focus:outline-none bg-lightListViewButtonBackground rounded border border-lightListViewButtonBorder hover:bg-lightListViewButtonBackgroundHover hover:text-lightListViewButtonTextHover focus:z-10 focus:ring-4 focus:ring-lightListViewButtonFocusRing dark:focus:ring-darkListViewButtonFocusRing dark:bg-darkListViewButtonBackground dark:text-darkListViewButtonText dark:border-darkListViewButtonBorder dark:hover:text-darkListViewButtonTextHover dark:hover:bg-darkListViewButtonBackgroundHover rounded-default gap-1"
|
|
73
81
|
>
|
|
74
|
-
<IconPlusOutline class="w-4 h-4
|
|
82
|
+
<IconPlusOutline class="w-4 h-4"/>
|
|
75
83
|
{{ $t('Create') }}
|
|
76
84
|
</RouterLink>
|
|
77
85
|
|
|
@@ -80,7 +88,7 @@
|
|
|
80
88
|
@click="()=>{filtersShow = !filtersShow}"
|
|
81
89
|
v-if="coreStore.resource?.options?.allowedActions?.filter"
|
|
82
90
|
>
|
|
83
|
-
<IconFilterOutline class="w-4 h-4
|
|
91
|
+
<IconFilterOutline class="w-4 h-4"/>
|
|
84
92
|
{{ $t('Filter') }}
|
|
85
93
|
<span
|
|
86
94
|
class="bg-red-100 text-red-800 text-xs font-medium me-2 px-2.5 py-0.5 rounded dark:bg-gray-700 dark:text-red-400 border border-red-400"
|
|
@@ -90,14 +98,19 @@
|
|
|
90
98
|
</button>
|
|
91
99
|
|
|
92
100
|
<ThreeDotsMenu
|
|
93
|
-
:threeDotsDropdownItems="coreStore.resourceOptions?.pageInjections?.list?.threeDotsDropdownItems"
|
|
94
|
-
|
|
101
|
+
:threeDotsDropdownItems="(coreStore.resourceOptions?.pageInjections?.list?.threeDotsDropdownItems as [])"
|
|
102
|
+
:bulkActions="coreStore.resource?.options?.bulkActions"
|
|
103
|
+
:checkboxes="checkboxes"
|
|
104
|
+
@startBulkAction="startBulkAction"
|
|
105
|
+
:updateList="getList"
|
|
106
|
+
:clearCheckboxes="clearCheckboxes"
|
|
107
|
+
></ThreeDotsMenu>
|
|
95
108
|
</BreadcrumbsWithButtons>
|
|
96
109
|
|
|
97
110
|
<component
|
|
98
111
|
v-for="c in coreStore?.resourceOptions?.pageInjections?.list?.afterBreadcrumbs || []"
|
|
99
112
|
:is="getCustomComponent(c)"
|
|
100
|
-
:meta="c.meta"
|
|
113
|
+
:meta="(c as AdminForthComponentDeclarationFull).meta"
|
|
101
114
|
:resource="coreStore.resource"
|
|
102
115
|
:adminUser="coreStore.adminUser"
|
|
103
116
|
/>
|
|
@@ -114,12 +127,23 @@
|
|
|
114
127
|
:pageSize="pageSize"
|
|
115
128
|
:totalRows="totalRows"
|
|
116
129
|
:checkboxes="checkboxes"
|
|
117
|
-
:customActionsInjection="coreStore.resourceOptions?.pageInjections?.list?.customActionIcons
|
|
118
|
-
|
|
130
|
+
:customActionsInjection="Array.isArray(coreStore.resourceOptions?.pageInjections?.list?.customActionIcons)
|
|
131
|
+
? coreStore.resourceOptions.pageInjections.list.customActionIcons
|
|
132
|
+
: coreStore.resourceOptions?.pageInjections?.list?.customActionIcons
|
|
133
|
+
? [coreStore.resourceOptions.pageInjections.list.customActionIcons]
|
|
134
|
+
: []
|
|
135
|
+
"
|
|
136
|
+
:tableBodyStartInjection="Array.isArray(coreStore.resourceOptions?.pageInjections?.list?.tableBodyStart)
|
|
137
|
+
? coreStore.resourceOptions.pageInjections.list.tableBodyStart
|
|
138
|
+
: coreStore.resourceOptions?.pageInjections?.list?.tableBodyStart
|
|
139
|
+
? [coreStore.resourceOptions.pageInjections.list.tableBodyStart]
|
|
140
|
+
: []
|
|
141
|
+
"
|
|
119
142
|
:container-height="1100"
|
|
120
143
|
:item-height="52.5"
|
|
121
144
|
:buffer-size="listBufferSize"
|
|
122
145
|
/>
|
|
146
|
+
|
|
123
147
|
<ResourceListTable
|
|
124
148
|
v-else
|
|
125
149
|
:resource="coreStore.resource"
|
|
@@ -133,14 +157,24 @@
|
|
|
133
157
|
:pageSize="pageSize"
|
|
134
158
|
:totalRows="totalRows"
|
|
135
159
|
:checkboxes="checkboxes"
|
|
136
|
-
:customActionsInjection="coreStore.resourceOptions?.pageInjections?.list?.customActionIcons
|
|
137
|
-
|
|
160
|
+
:customActionsInjection="Array.isArray(coreStore.resourceOptions?.pageInjections?.list?.customActionIcons)
|
|
161
|
+
? coreStore.resourceOptions.pageInjections.list.customActionIcons
|
|
162
|
+
: coreStore.resourceOptions?.pageInjections?.list?.customActionIcons
|
|
163
|
+
? [coreStore.resourceOptions.pageInjections.list.customActionIcons]
|
|
164
|
+
: []
|
|
165
|
+
"
|
|
166
|
+
:tableBodyStartInjection="Array.isArray(coreStore.resourceOptions?.pageInjections?.list?.tableBodyStart)
|
|
167
|
+
? coreStore.resourceOptions.pageInjections.list.tableBodyStart
|
|
168
|
+
: coreStore.resourceOptions?.pageInjections?.list?.tableBodyStart
|
|
169
|
+
? [coreStore.resourceOptions.pageInjections.list.tableBodyStart]
|
|
170
|
+
: []
|
|
171
|
+
"
|
|
138
172
|
/>
|
|
139
173
|
|
|
140
174
|
<component
|
|
141
175
|
v-for="c in coreStore?.resourceOptions?.pageInjections?.list?.bottom || []"
|
|
142
176
|
:is="getCustomComponent(c)"
|
|
143
|
-
:meta="c.meta"
|
|
177
|
+
:meta="(c as AdminForthComponentDeclarationFull).meta"
|
|
144
178
|
:resource="coreStore.resource"
|
|
145
179
|
:adminUser="coreStore.adminUser"
|
|
146
180
|
/>
|
|
@@ -161,6 +195,8 @@ import { showErrorTost } from '@/composables/useFrontendApi'
|
|
|
161
195
|
import { getCustomComponent, initThreeDotsDropdown } from '@/utils';
|
|
162
196
|
import ThreeDotsMenu from '@/components/ThreeDotsMenu.vue';
|
|
163
197
|
import { Tooltip } from '@/afcl'
|
|
198
|
+
import type { AdminForthComponentDeclarationFull } from '@/types/Common';
|
|
199
|
+
|
|
164
200
|
|
|
165
201
|
import {
|
|
166
202
|
IconBanOutline,
|
|
@@ -180,7 +216,7 @@ const route = useRoute();
|
|
|
180
216
|
|
|
181
217
|
const page = ref(1);
|
|
182
218
|
const columnsMinMax = ref({});
|
|
183
|
-
const sort = ref(
|
|
219
|
+
const sort = ref();
|
|
184
220
|
|
|
185
221
|
watch(() => sort, async (to, from) => {
|
|
186
222
|
// in store sort might be needed for plugins
|
|
@@ -224,11 +260,11 @@ async function getList() {
|
|
|
224
260
|
totalRows.value = 0;
|
|
225
261
|
return {error: data.error};
|
|
226
262
|
}
|
|
227
|
-
rows.value = data.data?.map(row => {
|
|
228
|
-
if (coreStore.resource
|
|
229
|
-
row._primaryKeyValue = row[coreStore.resource.columns.find(c => c.primaryKey)
|
|
230
|
-
} else {
|
|
231
|
-
row._primaryKeyValue = row[coreStore.resource.columns.find(c => c.primaryKey)
|
|
263
|
+
rows.value = data.data?.map((row: any) => {
|
|
264
|
+
if (coreStore.resource?.columns?.find(c => c.primaryKey)?.foreignResource) {
|
|
265
|
+
row._primaryKeyValue = row[coreStore.resource.columns.find(c => c.primaryKey)!.name].pk;
|
|
266
|
+
} else if (coreStore.resource) {
|
|
267
|
+
row._primaryKeyValue = row[coreStore.resource.columns.find(c => c.primaryKey)!.name];
|
|
232
268
|
}
|
|
233
269
|
return row;
|
|
234
270
|
});
|
|
@@ -240,6 +276,10 @@ async function getList() {
|
|
|
240
276
|
return {}
|
|
241
277
|
}
|
|
242
278
|
|
|
279
|
+
function clearCheckboxes() {
|
|
280
|
+
checkboxes.value = [];
|
|
281
|
+
}
|
|
282
|
+
|
|
243
283
|
async function refreshExistingList(pk?: any) {
|
|
244
284
|
const currentData = rows.value;
|
|
245
285
|
if (!currentData) {
|
|
@@ -292,9 +332,9 @@ async function refreshExistingList(pk?: any) {
|
|
|
292
332
|
}
|
|
293
333
|
|
|
294
334
|
|
|
295
|
-
async function startBulkAction(actionId) {
|
|
296
|
-
const action = coreStore.resource
|
|
297
|
-
if (action
|
|
335
|
+
async function startBulkAction(actionId: string) {
|
|
336
|
+
const action = coreStore.resource?.options?.bulkActions?.find(a => a.id === actionId);
|
|
337
|
+
if (action?.confirm) {
|
|
298
338
|
const confirmed = await adminforth.confirm({
|
|
299
339
|
message: action.confirm,
|
|
300
340
|
});
|
|
@@ -334,10 +374,10 @@ async function startBulkAction(actionId) {
|
|
|
334
374
|
|
|
335
375
|
|
|
336
376
|
class SortQuerySerializer {
|
|
337
|
-
static serialize(sort) {
|
|
377
|
+
static serialize(sort: {field: string, direction: 'asc' | 'desc'}[]) {
|
|
338
378
|
return sort.map(s => `${s.field}__${s.direction}`).join(',');
|
|
339
379
|
}
|
|
340
|
-
static deserialize(str) {
|
|
380
|
+
static deserialize(str: string) {
|
|
341
381
|
return str.split(',').map(s => {
|
|
342
382
|
const [field, direction] = s.split('__');
|
|
343
383
|
return { field, direction };
|
|
@@ -350,7 +390,7 @@ let listAutorefresher: any = null;
|
|
|
350
390
|
async function init() {
|
|
351
391
|
|
|
352
392
|
await coreStore.fetchResourceFull({
|
|
353
|
-
resourceId: route.params.resourceId
|
|
393
|
+
resourceId: route.params.resourceId as string
|
|
354
394
|
});
|
|
355
395
|
isPageLoaded.value = true;
|
|
356
396
|
// !!! clear filters should be in same tick with sort assignment so that watch can catch it as one change
|
|
@@ -361,7 +401,7 @@ async function init() {
|
|
|
361
401
|
return {
|
|
362
402
|
field,
|
|
363
403
|
operator,
|
|
364
|
-
value: JSON.parse(decodeURIComponent(route.query[k]))
|
|
404
|
+
value: JSON.parse(decodeURIComponent(route.query[k] as string))
|
|
365
405
|
}
|
|
366
406
|
});
|
|
367
407
|
if (filters.length) {
|
|
@@ -371,8 +411,8 @@ async function init() {
|
|
|
371
411
|
}
|
|
372
412
|
|
|
373
413
|
if (route.query.sort) {
|
|
374
|
-
sort.value = SortQuerySerializer.deserialize(route.query.sort);
|
|
375
|
-
} else if (coreStore
|
|
414
|
+
sort.value = SortQuerySerializer.deserialize(route.query.sort as string);
|
|
415
|
+
} else if (coreStore?.resource?.options?.defaultSort) {
|
|
376
416
|
sort.value = [{
|
|
377
417
|
field: coreStore.resource.options.defaultSort.columnName,
|
|
378
418
|
direction: coreStore.resource.options.defaultSort.direction
|
|
@@ -382,7 +422,7 @@ async function init() {
|
|
|
382
422
|
}
|
|
383
423
|
// page init should be also in same tick
|
|
384
424
|
if (route.query.page) {
|
|
385
|
-
page.value = parseInt(route.query.page);
|
|
425
|
+
page.value = parseInt(route.query.page as string);
|
|
386
426
|
}
|
|
387
427
|
|
|
388
428
|
// getList(); - Not needed here, watch will trigger it
|
|
@@ -411,8 +451,18 @@ watch([page, sort, () => filtersStore.filters], async () => {
|
|
|
411
451
|
}, { deep: true });
|
|
412
452
|
|
|
413
453
|
adminforth.list.refresh = async () => {
|
|
414
|
-
|
|
415
|
-
|
|
454
|
+
const result = await getList();
|
|
455
|
+
|
|
456
|
+
if (!result) {
|
|
457
|
+
return {};
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
if ('error' in result && result.error != null) {
|
|
461
|
+
return { error: String(result.error) };
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
return {};
|
|
465
|
+
};
|
|
416
466
|
|
|
417
467
|
adminforth.list.silentRefresh = async () => {
|
|
418
468
|
return await refreshExistingList();
|
|
@@ -432,10 +482,10 @@ watch(() => filtersStore.filters, async (to, from) => {
|
|
|
432
482
|
page.value = 1;
|
|
433
483
|
checkboxes.value = []; // TODO: not sure absolutely needed here
|
|
434
484
|
// update query param for each filter as filter_<column_name>=value
|
|
435
|
-
const query = {};
|
|
485
|
+
const query: Record<string, string | undefined> = {};
|
|
436
486
|
const currentQ = currentQuery();
|
|
437
487
|
filtersStore.filters.forEach(f => {
|
|
438
|
-
if (f.value) {
|
|
488
|
+
if (f.value !== undefined && f.value !== null && f.value !== '') {
|
|
439
489
|
query[`filter__${f.field}__${f.operator}`] = encodeURIComponent(JSON.stringify(f.value));
|
|
440
490
|
}
|
|
441
491
|
});
|
|
@@ -92,15 +92,7 @@
|
|
|
92
92
|
:meta="c.meta"
|
|
93
93
|
/>
|
|
94
94
|
|
|
95
|
-
<
|
|
96
|
-
<svg class="flex-shrink-0 inline w-4 h-4 me-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20">
|
|
97
|
-
<path d="M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5ZM9.5 4a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3ZM12 15H8a1 1 0 0 1 0-2h1v-3H8a1 1 0 0 1 0-2h2a1 1 0 0 1 1 1v4h1a1 1 0 0 1 0 2Z"/>
|
|
98
|
-
</svg>
|
|
99
|
-
<span class="sr-only">{{ $t('Info') }}</span>
|
|
100
|
-
<div>
|
|
101
|
-
{{ error }}
|
|
102
|
-
</div>
|
|
103
|
-
</div>
|
|
95
|
+
<ErrorMessage :error="error" />
|
|
104
96
|
|
|
105
97
|
<div v-if="loginPromptHTML"
|
|
106
98
|
class="flex items-center p-4 mb-4 text-sm text-lightLoginViewPromptText rounded-lg bg-lightLoginViewPromptBackground dark:bg-darkLoginViewPromptBackground dark:text-darkLoginViewPromptText" role="alert"
|
|
@@ -136,6 +128,7 @@ import { callAdminForthApi, loadFile } from '@/utils';
|
|
|
136
128
|
import { useRoute, useRouter } from 'vue-router';
|
|
137
129
|
import { Button, Checkbox, Input } from '@/afcl';
|
|
138
130
|
import { useI18n } from 'vue-i18n';
|
|
131
|
+
import ErrorMessage from '@/components/ErrorMessage.vue';
|
|
139
132
|
|
|
140
133
|
const { t } = useI18n();
|
|
141
134
|
|
|
@@ -33,7 +33,7 @@ const limitHeightToPage = computed(() => {
|
|
|
33
33
|
}
|
|
34
34
|
const listPageInjects = coreStore.resource.options.pageInjections.list;
|
|
35
35
|
|
|
36
|
-
for (const pi of [listPageInjects.beforeBreadcrumbs, listPageInjects.afterBreadcrumbs, listPageInjects.bottom]) {
|
|
36
|
+
for (const pi of [listPageInjects.beforeBreadcrumbs, listPageInjects.beforeActionButtons, listPageInjects.afterBreadcrumbs, listPageInjects.bottom]) {
|
|
37
37
|
if (pi) {
|
|
38
38
|
for (const piItem of pi) {
|
|
39
39
|
if (!piItem.meta?.thinEnoughToShrinkTable) {
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
v-if="!loading"
|
|
5
5
|
v-for="c in coreStore?.resourceOptions?.pageInjections?.show?.beforeBreadcrumbs || []"
|
|
6
6
|
:is="getCustomComponent(c)"
|
|
7
|
-
:meta="c.meta"
|
|
7
|
+
:meta="(c as AdminForthComponentDeclarationFull).meta"
|
|
8
8
|
:record="coreStore.record"
|
|
9
9
|
:resource="coreStore.resource"
|
|
10
10
|
:adminUser="coreStore.adminUser"
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
v-for="action in coreStore.resource.options.actions.filter(a => a.showIn?.showButton)"
|
|
16
16
|
:key="action.id"
|
|
17
17
|
@click="startCustomAction(action.id)"
|
|
18
|
-
:disabled="actionLoadingStates[action.id]"
|
|
18
|
+
:disabled="actionLoadingStates[action.id!]"
|
|
19
19
|
class="flex items-center py-1 px-3 text-sm font-medium text-gray-900 focus:outline-none bg-white rounded-default 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"
|
|
20
20
|
>
|
|
21
21
|
<component
|
|
@@ -28,28 +28,28 @@
|
|
|
28
28
|
</template>
|
|
29
29
|
<RouterLink v-if="coreStore.resource?.options?.allowedActions?.create"
|
|
30
30
|
:to="{ name: 'resource-create', params: { resourceId: $route.params.resourceId } }"
|
|
31
|
-
class="af-add-new-button flex items-center py-1 px-3 text-sm font-medium text-lightShowViewButtonText focus:outline-none bg-lightShowViewButtonBackground rounded border border-lightShowViewButtonBorder hover:bg-lightShowViewButtonBackgroundHover hover:text-lightShowViewButtonTextHover focus:z-10 focus:ring-4 focus:ring-lightShowViewButtonFocusRing dark:focus:ring-darkShowViewButtonFocusRing dark:bg-darkShowViewButtonBackground dark:text-darkShowViewButtonText dark:border-darkShowViewButtonBorder dark:hover:text-darkShowViewButtonTextHover dark:hover:bg-darkShowViewButtonBackgroundHover rounded-default"
|
|
31
|
+
class="af-add-new-button flex items-center py-1 px-3 text-sm font-medium text-lightShowViewButtonText focus:outline-none bg-lightShowViewButtonBackground rounded border border-lightShowViewButtonBorder hover:bg-lightShowViewButtonBackgroundHover hover:text-lightShowViewButtonTextHover focus:z-10 focus:ring-4 focus:ring-lightShowViewButtonFocusRing dark:focus:ring-darkShowViewButtonFocusRing dark:bg-darkShowViewButtonBackground dark:text-darkShowViewButtonText dark:border-darkShowViewButtonBorder dark:hover:text-darkShowViewButtonTextHover dark:hover:bg-darkShowViewButtonBackgroundHover rounded-default gap-1"
|
|
32
32
|
>
|
|
33
|
-
<IconPlusOutline class="w-4 h-4
|
|
33
|
+
<IconPlusOutline class="w-4 h-4"/>
|
|
34
34
|
{{ $t('Add new') }}
|
|
35
35
|
</RouterLink>
|
|
36
36
|
|
|
37
37
|
<RouterLink v-if="coreStore?.resourceOptions?.allowedActions?.edit" :to="{ name: 'resource-edit', params: { resourceId: $route.params.resourceId, primaryKey: $route.params.primaryKey } }"
|
|
38
|
-
class="flex items-center af-edit-button py-1 px-3 text-sm font-medium text-lightShowViewButtonText focus:outline-none bg-lightShowViewButtonBackground rounded-default border border-lightShowViewButtonBorder hover:bg-lightShowViewButtonBackgroundHover hover:text-lightShowViewButtonTextHover focus:z-10 focus:ring-4 focus:ring-lightShowViewButtonFocusRing dark:focus:ring-darkShowViewButtonFocusRing dark:bg-darkShowViewButtonBackground dark:text-darkShowViewButtonText dark:border-darkShowViewButtonBorder dark:hover:text-darkShowViewButtonTextHover dark:hover:bg-darkShowViewButtonBackgroundHover"
|
|
38
|
+
class="flex items-center af-edit-button py-1 px-3 text-sm font-medium text-lightShowViewButtonText focus:outline-none bg-lightShowViewButtonBackground rounded-default border border-lightShowViewButtonBorder hover:bg-lightShowViewButtonBackgroundHover hover:text-lightShowViewButtonTextHover focus:z-10 focus:ring-4 focus:ring-lightShowViewButtonFocusRing dark:focus:ring-darkShowViewButtonFocusRing dark:bg-darkShowViewButtonBackground dark:text-darkShowViewButtonText dark:border-darkShowViewButtonBorder dark:hover:text-darkShowViewButtonTextHover dark:hover:bg-darkShowViewButtonBackgroundHover gap-1"
|
|
39
39
|
>
|
|
40
40
|
<IconPenSolid class="w-4 h-4" />
|
|
41
41
|
{{ $t('Edit') }}
|
|
42
42
|
</RouterLink>
|
|
43
43
|
|
|
44
44
|
<button v-if="coreStore?.resourceOptions?.allowedActions?.delete" @click="deleteRecord"
|
|
45
|
-
class="flex items-center af-delete-button py-1 px-3 text-sm font-medium rounded-default text-red-600 focus:outline-none bg-lightShowViewButtonBackground border border-lightShowViewButtonBorder hover:bg-lightShowViewButtonBackgroundHover hover:text-red-700 focus:z-10 focus:ring-4 focus:ring-lightShowViewButtonFocusRing dark:focus:ring-darkShowViewButtonFocusRing dark:bg-darkShowViewButtonBackground dark:text-red-500 dark:border-darkShowViewButtonBorder dark:hover:text-darkShowViewButtonTextHover dark:hover:bg-darkShowViewButtonBackgroundHover"
|
|
45
|
+
class="flex items-center af-delete-button py-1 px-3 text-sm font-medium rounded-default text-red-600 focus:outline-none bg-lightShowViewButtonBackground border border-lightShowViewButtonBorder hover:bg-lightShowViewButtonBackgroundHover hover:text-red-700 focus:z-10 focus:ring-4 focus:ring-lightShowViewButtonFocusRing dark:focus:ring-darkShowViewButtonFocusRing dark:bg-darkShowViewButtonBackground dark:text-red-500 dark:border-darkShowViewButtonBorder dark:hover:text-darkShowViewButtonTextHover dark:hover:bg-darkShowViewButtonBackgroundHover gap-1"
|
|
46
46
|
>
|
|
47
47
|
<IconTrashBinSolid class="w-4 h-4" />
|
|
48
48
|
{{ $t('Delete') }}
|
|
49
49
|
</button>
|
|
50
50
|
|
|
51
51
|
<ThreeDotsMenu
|
|
52
|
-
:threeDotsDropdownItems="coreStore.resourceOptions?.pageInjections?.show?.threeDotsDropdownItems"
|
|
52
|
+
:threeDotsDropdownItems="(coreStore.resourceOptions?.pageInjections?.show?.threeDotsDropdownItems as [])"
|
|
53
53
|
:customActions="customActions"
|
|
54
54
|
></ThreeDotsMenu>
|
|
55
55
|
</BreadcrumbsWithButtons>
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
<component
|
|
58
58
|
v-for="c in coreStore?.resourceOptions?.pageInjections?.show?.afterBreadcrumbs || []"
|
|
59
59
|
:is="getCustomComponent(c)"
|
|
60
|
-
:meta="c.meta"
|
|
60
|
+
:meta="(c as AdminForthComponentDeclarationFull).meta"
|
|
61
61
|
:record="coreStore.record"
|
|
62
62
|
:resource="coreStore.resource"
|
|
63
63
|
:adminUser="coreStore.adminUser"
|
|
@@ -76,11 +76,11 @@
|
|
|
76
76
|
v-else-if="coreStore.record"
|
|
77
77
|
class="relative w-full flex flex-col gap-4"
|
|
78
78
|
>
|
|
79
|
-
<div v-if="!groups.length && allColumns
|
|
79
|
+
<div v-if="!groups.length && allColumns?.length">
|
|
80
80
|
<ShowTable
|
|
81
|
-
:columns="allColumns"
|
|
82
81
|
:resource="coreStore.resource"
|
|
83
82
|
:record="coreStore.record"
|
|
83
|
+
:columns="allColumns as Array<{ name: string; label?: string; components?: any }>"
|
|
84
84
|
/>
|
|
85
85
|
</div>
|
|
86
86
|
<template v-else>
|
|
@@ -93,12 +93,12 @@
|
|
|
93
93
|
:record="coreStore.record"
|
|
94
94
|
/>
|
|
95
95
|
</template>
|
|
96
|
-
<template v-if="otherColumns.length > 0">
|
|
96
|
+
<template v-if="otherColumns && otherColumns.length > 0">
|
|
97
97
|
<ShowTable
|
|
98
|
-
:columns="otherColumns"
|
|
99
98
|
groupName="Other Fields"
|
|
100
99
|
:resource="coreStore.resource"
|
|
101
100
|
:record="coreStore.record"
|
|
101
|
+
:columns="otherColumns as Array<{ name: string; label?: string; components?: any }>"
|
|
102
102
|
/>
|
|
103
103
|
</template>
|
|
104
104
|
</template>
|
|
@@ -112,8 +112,7 @@
|
|
|
112
112
|
v-if="!loading"
|
|
113
113
|
v-for="c in coreStore?.resourceOptions?.pageInjections?.show?.bottom || []"
|
|
114
114
|
:is="getCustomComponent(c)"
|
|
115
|
-
:meta="c.meta"
|
|
116
|
-
:column="column"
|
|
115
|
+
:meta="(c as AdminForthComponentDeclarationFull).meta"
|
|
117
116
|
:record="coreStore.record"
|
|
118
117
|
:resource="coreStore.resource"
|
|
119
118
|
:adminUser="coreStore.adminUser"
|
|
@@ -140,6 +139,7 @@ import ShowTable from '@/components/ShowTable.vue';
|
|
|
140
139
|
import adminforth from "@/adminforth";
|
|
141
140
|
import { useI18n } from 'vue-i18n';
|
|
142
141
|
import { getIcon } from '@/utils';
|
|
142
|
+
import { type AdminForthComponentDeclarationFull, type AdminForthResourceColumnCommon, type FieldGroup } from '@/types/Common.js';
|
|
143
143
|
|
|
144
144
|
const route = useRoute();
|
|
145
145
|
const router = useRouter();
|
|
@@ -147,62 +147,65 @@ const loading = ref(true);
|
|
|
147
147
|
const { t } = useI18n();
|
|
148
148
|
const coreStore = useCoreStore();
|
|
149
149
|
|
|
150
|
-
const actionLoadingStates = ref({});
|
|
150
|
+
const actionLoadingStates = ref<Record<string, boolean>>({});
|
|
151
151
|
|
|
152
152
|
const customActions = computed(() => {
|
|
153
|
-
return coreStore.resource?.options?.actions?.filter(a => a.showIn?.showThreeDotsMenu) || [];
|
|
153
|
+
return coreStore.resource?.options?.actions?.filter((a: any) => a.showIn?.showThreeDotsMenu) || [];
|
|
154
154
|
});
|
|
155
155
|
|
|
156
156
|
onMounted(async () => {
|
|
157
157
|
loading.value = true;
|
|
158
158
|
await coreStore.fetchResourceFull({
|
|
159
|
-
resourceId: route.params.resourceId
|
|
159
|
+
resourceId: route.params.resourceId as string,
|
|
160
160
|
});
|
|
161
161
|
initThreeDotsDropdown();
|
|
162
162
|
await coreStore.fetchRecord({
|
|
163
|
-
resourceId: route.params.resourceId,
|
|
164
|
-
primaryKey: route.params.primaryKey,
|
|
163
|
+
resourceId: route.params.resourceId as string,
|
|
164
|
+
primaryKey: route.params.primaryKey as string,
|
|
165
165
|
source: 'show',
|
|
166
166
|
});
|
|
167
|
-
|
|
167
|
+
if(coreStore.resourceOptions){
|
|
168
|
+
checkAcessByAllowedActions(coreStore.resourceOptions.allowedActions,'show');
|
|
169
|
+
}
|
|
168
170
|
loading.value = false;
|
|
169
171
|
});
|
|
170
172
|
|
|
171
173
|
const groups = computed(() => {
|
|
172
174
|
let fieldGroupType;
|
|
173
|
-
if (coreStore.resource
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
175
|
+
if (coreStore.resource) {
|
|
176
|
+
if (coreStore.resource.options?.showFieldGroups) {
|
|
177
|
+
fieldGroupType = coreStore.resource.options.showFieldGroups;
|
|
178
|
+
} else if (coreStore.resource.options?.showFieldGroups === null) {
|
|
179
|
+
fieldGroupType = [];
|
|
180
|
+
} else {
|
|
181
|
+
fieldGroupType = coreStore.resource.options?.fieldGroups;
|
|
182
|
+
}
|
|
179
183
|
}
|
|
184
|
+
const activeGroups: typeof fieldGroupType | [] = fieldGroupType ?? [];
|
|
180
185
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
return activeGroups.map(group => ({
|
|
186
|
+
return activeGroups.map((group: FieldGroup) => ({
|
|
184
187
|
...group,
|
|
185
|
-
columns: coreStore.resource
|
|
186
|
-
col => group.columns.includes(col.name) && col.showIn
|
|
188
|
+
columns: coreStore.resource?.columns.filter(
|
|
189
|
+
col => group.columns.includes(col.name) && col.showIn?.show
|
|
187
190
|
),
|
|
188
191
|
}));
|
|
189
192
|
});
|
|
190
193
|
|
|
191
194
|
const allColumns = computed(() => {
|
|
192
|
-
return coreStore.resource
|
|
195
|
+
return coreStore.resource?.columns.filter(col => col.showIn?.show);
|
|
193
196
|
});
|
|
194
197
|
|
|
195
198
|
const otherColumns = computed(() => {
|
|
196
199
|
const groupedColumnNames = new Set(
|
|
197
|
-
groups.value.flatMap(group => group.columns.map(col => col.name))
|
|
200
|
+
groups.value.flatMap(group => group.columns.map((col: AdminForthResourceColumnCommon) => col.name))
|
|
198
201
|
);
|
|
199
202
|
|
|
200
|
-
return coreStore.resource
|
|
201
|
-
col => !groupedColumnNames.has(col.name) && col.showIn
|
|
203
|
+
return coreStore.resource?.columns.filter(
|
|
204
|
+
col => !groupedColumnNames.has(col.name) && col.showIn?.show
|
|
202
205
|
);
|
|
203
206
|
});
|
|
204
207
|
|
|
205
|
-
async function deleteRecord(
|
|
208
|
+
async function deleteRecord() {
|
|
206
209
|
const data = await adminforth.confirm({
|
|
207
210
|
message: t('Are you sure you want to delete this item?'),
|
|
208
211
|
yes: t('Delete'),
|
|
@@ -231,7 +234,7 @@ async function deleteRecord(row) {
|
|
|
231
234
|
|
|
232
235
|
}
|
|
233
236
|
|
|
234
|
-
async function startCustomAction(actionId) {
|
|
237
|
+
async function startCustomAction(actionId: string) {
|
|
235
238
|
actionLoadingStates.value[actionId] = true;
|
|
236
239
|
|
|
237
240
|
const data = await callAdminForthApi({
|
|
@@ -263,8 +266,8 @@ async function startCustomAction(actionId) {
|
|
|
263
266
|
|
|
264
267
|
if (data?.ok) {
|
|
265
268
|
await coreStore.fetchRecord({
|
|
266
|
-
resourceId: route.params.resourceId,
|
|
267
|
-
primaryKey: route.params.primaryKey,
|
|
269
|
+
resourceId: route.params.resourceId as string,
|
|
270
|
+
primaryKey: route.params.primaryKey as string,
|
|
268
271
|
source: 'show',
|
|
269
272
|
});
|
|
270
273
|
|
|
@@ -281,4 +284,21 @@ async function startCustomAction(actionId) {
|
|
|
281
284
|
}
|
|
282
285
|
}
|
|
283
286
|
|
|
287
|
+
adminforth.show.refresh = () => {
|
|
288
|
+
(async () => {
|
|
289
|
+
try {
|
|
290
|
+
loading.value = true;
|
|
291
|
+
await coreStore.fetchRecord({
|
|
292
|
+
resourceId: String(route.params.resourceId),
|
|
293
|
+
primaryKey: String(route.params.primaryKey),
|
|
294
|
+
source: 'show',
|
|
295
|
+
});
|
|
296
|
+
} catch (e) {
|
|
297
|
+
showErrorTost((e as Error).message);
|
|
298
|
+
} finally {
|
|
299
|
+
loading.value = false;
|
|
300
|
+
}
|
|
301
|
+
})();
|
|
302
|
+
}
|
|
303
|
+
|
|
284
304
|
</script>
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
|
|
2
2
|
const subscriptions: { [topic: string]: ((data: any) => void)[] } = {};
|
|
3
|
+
|
|
4
|
+
interface ExtendedWebSocket extends WebSocket {
|
|
5
|
+
connected?: boolean;
|
|
6
|
+
}
|
|
7
|
+
|
|
3
8
|
const state: {
|
|
4
9
|
status: 'connecting' | 'connected' | 'disconnected';
|
|
5
|
-
ws:
|
|
10
|
+
ws: ExtendedWebSocket | null;
|
|
6
11
|
} = {
|
|
7
12
|
status: 'connecting',
|
|
8
13
|
ws: null
|