adminforth 1.1.43 → 1.1.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +39 -41
- package/dist/spa/spa/src/components/ResourceForm.vue +5 -5
- package/dist/spa/spa/src/components/ResourceListTable.vue +10 -2
- package/dist/spa/spa/src/views/CreateView.vue +1 -8
- package/dist/spa/spa/src/views/EditView.vue +1 -9
- package/dist/spa/spa/src/views/ListView.vue +1 -1
- package/dist/spa/spa/src/views/ShowView.vue +2 -10
- package/index.ts +23 -26
- package/package.json +1 -1
- package/spa/src/components/ResourceForm.vue +5 -5
- package/spa/src/components/ResourceListTable.vue +10 -2
- package/spa/src/views/CreateView.vue +1 -8
- package/spa/src/views/EditView.vue +1 -9
- package/spa/src/views/ListView.vue +1 -1
- package/spa/src/views/ShowView.vue +2 -10
- package/types/FrontendAPI.ts +3 -1
package/dist/index.js
CHANGED
|
@@ -244,49 +244,47 @@ class AdminForth {
|
|
|
244
244
|
}
|
|
245
245
|
}
|
|
246
246
|
//check if resource has bulkActions
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
yield
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
})
|
|
264
|
-
});
|
|
265
|
-
}
|
|
266
|
-
const newBulkActions = bulkActions.map((action) => {
|
|
267
|
-
return Object.assign(action, { id: uuid() });
|
|
247
|
+
let bulkActions = ((_b = res === null || res === void 0 ? void 0 : res.options) === null || _b === void 0 ? void 0 : _b.bulkActions) || [];
|
|
248
|
+
if (!Array.isArray(bulkActions)) {
|
|
249
|
+
errors.push(`Resource "${res.resourceId}" bulkActions must be an array`);
|
|
250
|
+
bulkActions = [];
|
|
251
|
+
}
|
|
252
|
+
if (((_d = (_c = res.options) === null || _c === void 0 ? void 0 : _c.allowedActions) === null || _d === void 0 ? void 0 : _d.delete) && !bulkActions.find((action) => action.label === 'Delete checked')) {
|
|
253
|
+
bulkActions.push({
|
|
254
|
+
label: `Delete checked`,
|
|
255
|
+
state: 'danger',
|
|
256
|
+
icon: 'flowbite:trash-bin-outline',
|
|
257
|
+
action: (_e) => __awaiter(this, [_e], void 0, function* ({ selectedIds }) {
|
|
258
|
+
const connector = this.connectors[res.dataSource];
|
|
259
|
+
yield Promise.all(selectedIds.map((recordId) => __awaiter(this, void 0, void 0, function* () {
|
|
260
|
+
yield connector.deleteRecord({ resource: res, recordId });
|
|
261
|
+
})));
|
|
262
|
+
})
|
|
268
263
|
});
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
}
|
|
284
|
-
else {
|
|
285
|
-
errors.push(`Resource "${res.resourceId}" has invalid pageInjection key "${injection}", Supported keys are ${possibleInjections.join(', ')}`);
|
|
264
|
+
}
|
|
265
|
+
const newBulkActions = bulkActions.map((action) => {
|
|
266
|
+
return Object.assign(action, { id: uuid() });
|
|
267
|
+
});
|
|
268
|
+
res.options.bulkActions = newBulkActions;
|
|
269
|
+
// if pageInjection is a string, make array with one element. Also check file exists
|
|
270
|
+
const possibleInjections = ['beforeBreadcrumbs', 'afterBreadcrumbs', 'bottom'];
|
|
271
|
+
if (res.options.pageInjections) {
|
|
272
|
+
Object.entries(res.options.pageInjections).map(([key, value]) => {
|
|
273
|
+
Object.entries(value).map(([injection, target]) => {
|
|
274
|
+
if (possibleInjections.includes(injection)) {
|
|
275
|
+
if (!Array.isArray(res.options.pageInjections[key][injection])) {
|
|
276
|
+
// not array
|
|
277
|
+
res.options.pageInjections[key][injection] = [target];
|
|
286
278
|
}
|
|
287
|
-
|
|
279
|
+
res.options.pageInjections[key][injection].forEach((target, i) => {
|
|
280
|
+
res.options.pageInjections[key][injection][i] = this.validateComponent(target, errors);
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
284
|
+
errors.push(`Resource "${res.resourceId}" has invalid pageInjection key "${injection}", Supported keys are ${possibleInjections.join(', ')}`);
|
|
285
|
+
}
|
|
288
286
|
});
|
|
289
|
-
}
|
|
287
|
+
});
|
|
290
288
|
}
|
|
291
289
|
// transform all hooks Functions to array of functions
|
|
292
290
|
if (res.hooks) {
|
|
@@ -454,7 +452,7 @@ class AdminForth {
|
|
|
454
452
|
}
|
|
455
453
|
bundleNow(_b) {
|
|
456
454
|
return __awaiter(this, arguments, void 0, function* ({ hotReload = false, verbose = false }) {
|
|
457
|
-
this.codeInjector.bundleNow({ hotReload, verbose });
|
|
455
|
+
yield this.codeInjector.bundleNow({ hotReload, verbose });
|
|
458
456
|
});
|
|
459
457
|
}
|
|
460
458
|
getUserByPk(pk) {
|
|
@@ -21,12 +21,13 @@
|
|
|
21
21
|
class="bg-form-view-bg dark:bg-gray-800 border-b dark:border-gray-700"
|
|
22
22
|
>
|
|
23
23
|
<!-- if column is in customComponentsPerColumn, use this component. If not, use this code -->
|
|
24
|
-
<template v-if="
|
|
24
|
+
<template v-if="column?.components?.[props.source].file">
|
|
25
25
|
<component
|
|
26
|
-
:is="
|
|
26
|
+
:is="getCustomComponent(column.components[props.source])"
|
|
27
27
|
:column="column"
|
|
28
28
|
:value="currentValues[column.name]"
|
|
29
29
|
@update:value="setCurrentValue(column.name, $event)"
|
|
30
|
+
:meta="column.components[props.source].meta"
|
|
30
31
|
/>
|
|
31
32
|
</template>
|
|
32
33
|
<template v-else>
|
|
@@ -141,7 +142,7 @@
|
|
|
141
142
|
import CustomDatePicker from "@/components/CustomDatePicker.vue";
|
|
142
143
|
import Dropdown from '@/components/Dropdown.vue';
|
|
143
144
|
import { useCoreStore } from '@/stores/core';
|
|
144
|
-
import { callAdminForthApi } from '@/utils';
|
|
145
|
+
import { callAdminForthApi, getCustomComponent } from '@/utils';
|
|
145
146
|
import { IconExclamationCircleSolid, IconEyeSlashSolid, IconEyeSolid } from '@iconify-prerendered/vue-flowbite';
|
|
146
147
|
import { computedAsync } from '@vueuse/core';
|
|
147
148
|
import { initFlowbite } from 'flowbite';
|
|
@@ -155,10 +156,9 @@ const props = defineProps({
|
|
|
155
156
|
resource: Object,
|
|
156
157
|
record: Object,
|
|
157
158
|
validating: Boolean,
|
|
158
|
-
|
|
159
|
+
source: String,
|
|
159
160
|
});
|
|
160
161
|
|
|
161
|
-
|
|
162
162
|
const unmasked = ref({});
|
|
163
163
|
|
|
164
164
|
const mode = computed(() => props.record && Object.keys(props.record).length ? 'edit' : 'create');
|
|
@@ -35,8 +35,10 @@
|
|
|
35
35
|
</th>
|
|
36
36
|
|
|
37
37
|
<th v-for="c in columnsListed" scope="col" class="px-6 py-3">
|
|
38
|
+
|
|
38
39
|
<div @click="() => c.sortable && onSortButtonClick(c.name)" class="flex items-center " :class="{'cursor-pointer':c.sortable}">
|
|
39
40
|
{{ c.label }}
|
|
41
|
+
|
|
40
42
|
|
|
41
43
|
<div v-if="c.sortable"
|
|
42
44
|
:style="{ 'color':ascArr.includes(c.name)?'green':descArr.includes(c.name)?'red':'currentColor'}">
|
|
@@ -52,6 +54,12 @@
|
|
|
52
54
|
d="M8.574 11.024h6.852a2.075 2.075 0 0 0 1.847-1.086 1.9 1.9 0 0 0-.11-1.986L13.736 2.9a2.122 2.122 0 0 0-3.472 0L6.837 7.952a1.9 1.9 0 0 0-.11 1.986 2.074 2.074 0 0 0 1.847 1.086Zm6.852 1.952H8.574a2.072 2.072 0 0 0-1.847 1.087 1.9 1.9 0 0 0 .11 1.985l3.426 5.05a2.123 2.123 0 0 0 3.472 0l3.427-5.05a1.9 1.9 0 0 0 .11-1.985 2.074 2.074 0 0 0-1.846-1.087Z"/>
|
|
53
55
|
</svg>
|
|
54
56
|
</div>
|
|
57
|
+
<span
|
|
58
|
+
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"
|
|
59
|
+
v-if="sort.findIndex((s) => s.field === c.name) !== -1">
|
|
60
|
+
{{ sort.findIndex((s) => s.field === c.name) + 1 }}
|
|
61
|
+
</span>
|
|
62
|
+
|
|
55
63
|
</div>
|
|
56
64
|
</th>
|
|
57
65
|
|
|
@@ -136,7 +144,7 @@
|
|
|
136
144
|
<!-- if c.name in listComponentsPerColumn, render it. If not, render ValueRenderer -->
|
|
137
145
|
<component
|
|
138
146
|
:is="c?.components?.list ? getCustomComponent(c.components.list) : ValueRenderer"
|
|
139
|
-
:meta="c?.components?.list
|
|
147
|
+
:meta="c?.components?.list?.meta"
|
|
140
148
|
:column="c"
|
|
141
149
|
:record="row"
|
|
142
150
|
:adminUser="coreStore.adminUser"
|
|
@@ -376,7 +384,7 @@ const descArr = computed(() => sort.value.filter((s) => s.direction === 'desc').
|
|
|
376
384
|
function onSortButtonClick(field) {
|
|
377
385
|
const sortIndex = sort.value.findIndex((s) => s.field === field);
|
|
378
386
|
if (sortIndex === -1) {
|
|
379
|
-
sort.value = [{field, direction: 'asc'}
|
|
387
|
+
sort.value = [...sort.value,{field, direction: 'asc'}];
|
|
380
388
|
} else {
|
|
381
389
|
const sortField = sort.value[sortIndex];
|
|
382
390
|
if (sortField.direction === 'asc') {
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
@update:record="onUpdateRecord"
|
|
51
51
|
@update:isValid="isValid = $event"
|
|
52
52
|
:validating="validating"
|
|
53
|
-
:
|
|
53
|
+
:source="'create'"
|
|
54
54
|
>
|
|
55
55
|
</ResourceForm>
|
|
56
56
|
|
|
@@ -91,7 +91,6 @@ const route = useRoute();
|
|
|
91
91
|
const router = useRouter();
|
|
92
92
|
|
|
93
93
|
const record = ref({});
|
|
94
|
-
let createComponentsPerColumn = {};
|
|
95
94
|
|
|
96
95
|
const coreStore = useCoreStore();
|
|
97
96
|
|
|
@@ -115,12 +114,6 @@ onMounted(async () => {
|
|
|
115
114
|
await coreStore.fetchResourceFull({
|
|
116
115
|
resourceId: route.params.resourceId
|
|
117
116
|
});
|
|
118
|
-
createComponentsPerColumn = coreStore.resource.columns.reduce((acc, column) => {
|
|
119
|
-
if (column.components?.create) {
|
|
120
|
-
acc[column.name] = getCustomComponent(column.components.create);
|
|
121
|
-
}
|
|
122
|
-
return acc;
|
|
123
|
-
}, {});
|
|
124
117
|
loading.value = false;
|
|
125
118
|
checkAcessByAllowedActions(coreStore.resourceOptions.allowedActions,'create');
|
|
126
119
|
});
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
@update:record="onUpdateRecord"
|
|
47
47
|
@update:isValid="isValid = $event"
|
|
48
48
|
:validating="validating"
|
|
49
|
-
:
|
|
49
|
+
:source="'edit'"
|
|
50
50
|
>
|
|
51
51
|
</ResourceForm>
|
|
52
52
|
|
|
@@ -88,7 +88,6 @@ const loading = ref(false);
|
|
|
88
88
|
const saving = ref(false);
|
|
89
89
|
|
|
90
90
|
const record = ref({});
|
|
91
|
-
let editComponentsPerColumn = {};
|
|
92
91
|
|
|
93
92
|
async function onUpdateRecord(newRecord) {
|
|
94
93
|
record.value = newRecord;
|
|
@@ -119,13 +118,6 @@ onMounted(async () => {
|
|
|
119
118
|
primaryKey: route.params.primaryKey,
|
|
120
119
|
});
|
|
121
120
|
checkAcessByAllowedActions(coreStore.resourceOptions.allowedActions,'edit');
|
|
122
|
-
|
|
123
|
-
editComponentsPerColumn = coreStore.resource.columns.reduce((acc, column) => {
|
|
124
|
-
if (column.components?.edit) {
|
|
125
|
-
acc[column.name] = getCustomComponent(column.components.edit);
|
|
126
|
-
}
|
|
127
|
-
return acc;
|
|
128
|
-
}, {});
|
|
129
121
|
loading.value = false;
|
|
130
122
|
});
|
|
131
123
|
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
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"
|
|
71
71
|
v-if="filtersStore.filters.length">
|
|
72
72
|
{{ filtersStore.filters.length }}
|
|
73
|
-
|
|
73
|
+
</span>
|
|
74
74
|
</button>
|
|
75
75
|
</BreadcrumbsWithButtons>
|
|
76
76
|
|
|
@@ -75,8 +75,8 @@
|
|
|
75
75
|
</td>
|
|
76
76
|
<td class="px-6 py-4 whitespace-nowrap whitespace-pre-wrap">
|
|
77
77
|
<component
|
|
78
|
-
v-if="
|
|
79
|
-
:is="
|
|
78
|
+
v-if="column?.components?.show"
|
|
79
|
+
:is="getCustomComponent(column?.components?.show)"
|
|
80
80
|
:resource="coreStore.resource"
|
|
81
81
|
:meta="column.components.show.meta"
|
|
82
82
|
:column="column"
|
|
@@ -127,7 +127,6 @@ const item = ref(null);
|
|
|
127
127
|
const route = useRoute();
|
|
128
128
|
const router = useRouter();
|
|
129
129
|
const loading = ref(false);
|
|
130
|
-
let showComponentsPerColumn = {};
|
|
131
130
|
|
|
132
131
|
console.log(route.params,'showWiev');
|
|
133
132
|
|
|
@@ -145,13 +144,6 @@ onMounted(async () => {
|
|
|
145
144
|
primaryKey: route.params.primaryKey,
|
|
146
145
|
});
|
|
147
146
|
checkAcessByAllowedActions(coreStore.resourceOptions.allowedActions,'show');
|
|
148
|
-
|
|
149
|
-
showComponentsPerColumn = coreStore.resource.columns.reduce((acc, column) => {
|
|
150
|
-
if (column.components?.show) {
|
|
151
|
-
acc[column.name] = getCustomComponent(column.components.show);
|
|
152
|
-
}
|
|
153
|
-
return acc;
|
|
154
|
-
}, {});
|
|
155
147
|
loading.value = false;
|
|
156
148
|
});
|
|
157
149
|
|
package/index.ts
CHANGED
|
@@ -293,13 +293,13 @@ class AdminForth implements AdminForthClass {
|
|
|
293
293
|
|
|
294
294
|
|
|
295
295
|
//check if resource has bulkActions
|
|
296
|
-
|
|
297
|
-
let bulkActions = res.options.bulkActions;
|
|
296
|
+
let bulkActions = res?.options?.bulkActions || [];
|
|
298
297
|
|
|
299
298
|
if (!Array.isArray(bulkActions)) {
|
|
300
299
|
errors.push(`Resource "${res.resourceId}" bulkActions must be an array`);
|
|
301
300
|
bulkActions = [];
|
|
302
301
|
}
|
|
302
|
+
|
|
303
303
|
if(res.options?.allowedActions?.delete && !bulkActions.find((action) => action.label === 'Delete checked')){
|
|
304
304
|
bulkActions.push({
|
|
305
305
|
label: `Delete checked`,
|
|
@@ -317,32 +317,29 @@ class AdminForth implements AdminForthClass {
|
|
|
317
317
|
const newBulkActions = bulkActions.map((action) => {
|
|
318
318
|
return Object.assign(action, {id: uuid()});
|
|
319
319
|
});
|
|
320
|
-
bulkActions = newBulkActions;
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
}
|
|
332
|
-
res.options.pageInjections[key][injection].forEach((target, i) => {
|
|
333
|
-
res.options.pageInjections[key][injection][i] = this.validateComponent(target, errors);
|
|
334
|
-
});
|
|
335
|
-
} else {
|
|
336
|
-
errors.push(`Resource "${res.resourceId}" has invalid pageInjection key "${injection}", Supported keys are ${possibleInjections.join(', ')}`);
|
|
320
|
+
res.options.bulkActions = newBulkActions;
|
|
321
|
+
|
|
322
|
+
// if pageInjection is a string, make array with one element. Also check file exists
|
|
323
|
+
const possibleInjections = ['beforeBreadcrumbs', 'afterBreadcrumbs', 'bottom'];
|
|
324
|
+
if(res.options.pageInjections) {
|
|
325
|
+
Object.entries(res.options.pageInjections).map(([key, value]) => {
|
|
326
|
+
Object.entries(value).map(([injection, target]) => {
|
|
327
|
+
if (possibleInjections.includes(injection)) {
|
|
328
|
+
if (!Array.isArray(res.options.pageInjections[key][injection])) {
|
|
329
|
+
// not array
|
|
330
|
+
res.options.pageInjections[key][injection] = [target];
|
|
337
331
|
}
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
332
|
+
res.options.pageInjections[key][injection].forEach((target, i) => {
|
|
333
|
+
res.options.pageInjections[key][injection][i] = this.validateComponent(target, errors);
|
|
334
|
+
});
|
|
335
|
+
} else {
|
|
336
|
+
errors.push(`Resource "${res.resourceId}" has invalid pageInjection key "${injection}", Supported keys are ${possibleInjections.join(', ')}`);
|
|
337
|
+
}
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
})
|
|
343
341
|
}
|
|
344
342
|
|
|
345
|
-
|
|
346
343
|
// transform all hooks Functions to array of functions
|
|
347
344
|
if (res.hooks) {
|
|
348
345
|
for (const value of [res.hooks.show, res.hooks.list]) {
|
|
@@ -538,7 +535,7 @@ class AdminForth implements AdminForthClass {
|
|
|
538
535
|
}
|
|
539
536
|
|
|
540
537
|
async bundleNow({ hotReload=false, verbose=false }) {
|
|
541
|
-
this.codeInjector.bundleNow({ hotReload, verbose });
|
|
538
|
+
await this.codeInjector.bundleNow({ hotReload, verbose });
|
|
542
539
|
}
|
|
543
540
|
|
|
544
541
|
async getUserByPk(pk: string) {
|
package/package.json
CHANGED
|
@@ -21,12 +21,13 @@
|
|
|
21
21
|
class="bg-form-view-bg dark:bg-gray-800 border-b dark:border-gray-700"
|
|
22
22
|
>
|
|
23
23
|
<!-- if column is in customComponentsPerColumn, use this component. If not, use this code -->
|
|
24
|
-
<template v-if="
|
|
24
|
+
<template v-if="column?.components?.[props.source].file">
|
|
25
25
|
<component
|
|
26
|
-
:is="
|
|
26
|
+
:is="getCustomComponent(column.components[props.source])"
|
|
27
27
|
:column="column"
|
|
28
28
|
:value="currentValues[column.name]"
|
|
29
29
|
@update:value="setCurrentValue(column.name, $event)"
|
|
30
|
+
:meta="column.components[props.source].meta"
|
|
30
31
|
/>
|
|
31
32
|
</template>
|
|
32
33
|
<template v-else>
|
|
@@ -141,7 +142,7 @@
|
|
|
141
142
|
import CustomDatePicker from "@/components/CustomDatePicker.vue";
|
|
142
143
|
import Dropdown from '@/components/Dropdown.vue';
|
|
143
144
|
import { useCoreStore } from '@/stores/core';
|
|
144
|
-
import { callAdminForthApi } from '@/utils';
|
|
145
|
+
import { callAdminForthApi, getCustomComponent } from '@/utils';
|
|
145
146
|
import { IconExclamationCircleSolid, IconEyeSlashSolid, IconEyeSolid } from '@iconify-prerendered/vue-flowbite';
|
|
146
147
|
import { computedAsync } from '@vueuse/core';
|
|
147
148
|
import { initFlowbite } from 'flowbite';
|
|
@@ -155,10 +156,9 @@ const props = defineProps({
|
|
|
155
156
|
resource: Object,
|
|
156
157
|
record: Object,
|
|
157
158
|
validating: Boolean,
|
|
158
|
-
|
|
159
|
+
source: String,
|
|
159
160
|
});
|
|
160
161
|
|
|
161
|
-
|
|
162
162
|
const unmasked = ref({});
|
|
163
163
|
|
|
164
164
|
const mode = computed(() => props.record && Object.keys(props.record).length ? 'edit' : 'create');
|
|
@@ -35,8 +35,10 @@
|
|
|
35
35
|
</th>
|
|
36
36
|
|
|
37
37
|
<th v-for="c in columnsListed" scope="col" class="px-6 py-3">
|
|
38
|
+
|
|
38
39
|
<div @click="() => c.sortable && onSortButtonClick(c.name)" class="flex items-center " :class="{'cursor-pointer':c.sortable}">
|
|
39
40
|
{{ c.label }}
|
|
41
|
+
|
|
40
42
|
|
|
41
43
|
<div v-if="c.sortable"
|
|
42
44
|
:style="{ 'color':ascArr.includes(c.name)?'green':descArr.includes(c.name)?'red':'currentColor'}">
|
|
@@ -52,6 +54,12 @@
|
|
|
52
54
|
d="M8.574 11.024h6.852a2.075 2.075 0 0 0 1.847-1.086 1.9 1.9 0 0 0-.11-1.986L13.736 2.9a2.122 2.122 0 0 0-3.472 0L6.837 7.952a1.9 1.9 0 0 0-.11 1.986 2.074 2.074 0 0 0 1.847 1.086Zm6.852 1.952H8.574a2.072 2.072 0 0 0-1.847 1.087 1.9 1.9 0 0 0 .11 1.985l3.426 5.05a2.123 2.123 0 0 0 3.472 0l3.427-5.05a1.9 1.9 0 0 0 .11-1.985 2.074 2.074 0 0 0-1.846-1.087Z"/>
|
|
53
55
|
</svg>
|
|
54
56
|
</div>
|
|
57
|
+
<span
|
|
58
|
+
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"
|
|
59
|
+
v-if="sort.findIndex((s) => s.field === c.name) !== -1">
|
|
60
|
+
{{ sort.findIndex((s) => s.field === c.name) + 1 }}
|
|
61
|
+
</span>
|
|
62
|
+
|
|
55
63
|
</div>
|
|
56
64
|
</th>
|
|
57
65
|
|
|
@@ -136,7 +144,7 @@
|
|
|
136
144
|
<!-- if c.name in listComponentsPerColumn, render it. If not, render ValueRenderer -->
|
|
137
145
|
<component
|
|
138
146
|
:is="c?.components?.list ? getCustomComponent(c.components.list) : ValueRenderer"
|
|
139
|
-
:meta="c?.components?.list
|
|
147
|
+
:meta="c?.components?.list?.meta"
|
|
140
148
|
:column="c"
|
|
141
149
|
:record="row"
|
|
142
150
|
:adminUser="coreStore.adminUser"
|
|
@@ -376,7 +384,7 @@ const descArr = computed(() => sort.value.filter((s) => s.direction === 'desc').
|
|
|
376
384
|
function onSortButtonClick(field) {
|
|
377
385
|
const sortIndex = sort.value.findIndex((s) => s.field === field);
|
|
378
386
|
if (sortIndex === -1) {
|
|
379
|
-
sort.value = [{field, direction: 'asc'}
|
|
387
|
+
sort.value = [...sort.value,{field, direction: 'asc'}];
|
|
380
388
|
} else {
|
|
381
389
|
const sortField = sort.value[sortIndex];
|
|
382
390
|
if (sortField.direction === 'asc') {
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
@update:record="onUpdateRecord"
|
|
51
51
|
@update:isValid="isValid = $event"
|
|
52
52
|
:validating="validating"
|
|
53
|
-
:
|
|
53
|
+
:source="'create'"
|
|
54
54
|
>
|
|
55
55
|
</ResourceForm>
|
|
56
56
|
|
|
@@ -91,7 +91,6 @@ const route = useRoute();
|
|
|
91
91
|
const router = useRouter();
|
|
92
92
|
|
|
93
93
|
const record = ref({});
|
|
94
|
-
let createComponentsPerColumn = {};
|
|
95
94
|
|
|
96
95
|
const coreStore = useCoreStore();
|
|
97
96
|
|
|
@@ -115,12 +114,6 @@ onMounted(async () => {
|
|
|
115
114
|
await coreStore.fetchResourceFull({
|
|
116
115
|
resourceId: route.params.resourceId
|
|
117
116
|
});
|
|
118
|
-
createComponentsPerColumn = coreStore.resource.columns.reduce((acc, column) => {
|
|
119
|
-
if (column.components?.create) {
|
|
120
|
-
acc[column.name] = getCustomComponent(column.components.create);
|
|
121
|
-
}
|
|
122
|
-
return acc;
|
|
123
|
-
}, {});
|
|
124
117
|
loading.value = false;
|
|
125
118
|
checkAcessByAllowedActions(coreStore.resourceOptions.allowedActions,'create');
|
|
126
119
|
});
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
@update:record="onUpdateRecord"
|
|
47
47
|
@update:isValid="isValid = $event"
|
|
48
48
|
:validating="validating"
|
|
49
|
-
:
|
|
49
|
+
:source="'edit'"
|
|
50
50
|
>
|
|
51
51
|
</ResourceForm>
|
|
52
52
|
|
|
@@ -88,7 +88,6 @@ const loading = ref(false);
|
|
|
88
88
|
const saving = ref(false);
|
|
89
89
|
|
|
90
90
|
const record = ref({});
|
|
91
|
-
let editComponentsPerColumn = {};
|
|
92
91
|
|
|
93
92
|
async function onUpdateRecord(newRecord) {
|
|
94
93
|
record.value = newRecord;
|
|
@@ -119,13 +118,6 @@ onMounted(async () => {
|
|
|
119
118
|
primaryKey: route.params.primaryKey,
|
|
120
119
|
});
|
|
121
120
|
checkAcessByAllowedActions(coreStore.resourceOptions.allowedActions,'edit');
|
|
122
|
-
|
|
123
|
-
editComponentsPerColumn = coreStore.resource.columns.reduce((acc, column) => {
|
|
124
|
-
if (column.components?.edit) {
|
|
125
|
-
acc[column.name] = getCustomComponent(column.components.edit);
|
|
126
|
-
}
|
|
127
|
-
return acc;
|
|
128
|
-
}, {});
|
|
129
121
|
loading.value = false;
|
|
130
122
|
});
|
|
131
123
|
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
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"
|
|
71
71
|
v-if="filtersStore.filters.length">
|
|
72
72
|
{{ filtersStore.filters.length }}
|
|
73
|
-
|
|
73
|
+
</span>
|
|
74
74
|
</button>
|
|
75
75
|
</BreadcrumbsWithButtons>
|
|
76
76
|
|
|
@@ -75,8 +75,8 @@
|
|
|
75
75
|
</td>
|
|
76
76
|
<td class="px-6 py-4 whitespace-nowrap whitespace-pre-wrap">
|
|
77
77
|
<component
|
|
78
|
-
v-if="
|
|
79
|
-
:is="
|
|
78
|
+
v-if="column?.components?.show"
|
|
79
|
+
:is="getCustomComponent(column?.components?.show)"
|
|
80
80
|
:resource="coreStore.resource"
|
|
81
81
|
:meta="column.components.show.meta"
|
|
82
82
|
:column="column"
|
|
@@ -127,7 +127,6 @@ const item = ref(null);
|
|
|
127
127
|
const route = useRoute();
|
|
128
128
|
const router = useRouter();
|
|
129
129
|
const loading = ref(false);
|
|
130
|
-
let showComponentsPerColumn = {};
|
|
131
130
|
|
|
132
131
|
console.log(route.params,'showWiev');
|
|
133
132
|
|
|
@@ -145,13 +144,6 @@ onMounted(async () => {
|
|
|
145
144
|
primaryKey: route.params.primaryKey,
|
|
146
145
|
});
|
|
147
146
|
checkAcessByAllowedActions(coreStore.resourceOptions.allowedActions,'show');
|
|
148
|
-
|
|
149
|
-
showComponentsPerColumn = coreStore.resource.columns.reduce((acc, column) => {
|
|
150
|
-
if (column.components?.show) {
|
|
151
|
-
acc[column.name] = getCustomComponent(column.components.show);
|
|
152
|
-
}
|
|
153
|
-
return acc;
|
|
154
|
-
}, {});
|
|
155
147
|
loading.value = false;
|
|
156
148
|
});
|
|
157
149
|
|
package/types/FrontendAPI.ts
CHANGED
|
@@ -34,7 +34,9 @@ export interface FrontendAPIInterface {
|
|
|
34
34
|
*/
|
|
35
35
|
alert(params:AlertParams): void;
|
|
36
36
|
/**
|
|
37
|
-
* Add a filter to the list of filters
|
|
37
|
+
* Add a filter to the list of filters.
|
|
38
|
+
* Works only when user located on the list page.
|
|
39
|
+
* Can be used to set filter from charts or other components in pageInjections.
|
|
38
40
|
*
|
|
39
41
|
* Example:
|
|
40
42
|
*
|