adminforth 1.1.4 → 1.1.6
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 +6 -0
- package/dist/modules/styles.js +7 -6
- package/dist/plugins/ForeignInlineListPlugin/index.js +32 -1
- package/dist/plugins/base.js +4 -0
- package/dist/spa/spa/src/App.vue +2 -2
- package/dist/spa/spa/src/components/BreadcrumbsWithButtons.vue +1 -1
- package/dist/spa/spa/src/components/Filters.vue +19 -15
- package/dist/spa/spa/src/components/ResourceForm.vue +15 -15
- package/dist/spa/spa/src/components/ResourceListTable.vue +36 -16
- package/dist/spa/spa/src/composables/useStores.ts +64 -3
- package/dist/spa/spa/src/stores/core.ts +17 -11
- package/dist/spa/spa/src/stores/filters.ts +22 -0
- package/dist/spa/spa/src/stores/modal.ts +0 -1
- package/dist/spa/spa/src/views/CreateView.vue +24 -10
- package/dist/spa/spa/src/views/EditView.vue +5 -5
- package/dist/spa/spa/src/views/ListView.vue +25 -23
- package/dist/spa/spa/src/views/ShowView.vue +5 -5
- package/index.ts +10 -0
- package/modules/styles.ts +7 -6
- package/package.json +1 -1
- package/plugins/ForeignInlineListPlugin/custom/InlineList.vue +138 -14
- package/plugins/ForeignInlineListPlugin/index.ts +32 -5
- package/plugins/base.ts +7 -0
- package/spa/src/App.vue +2 -2
- package/spa/src/components/BreadcrumbsWithButtons.vue +1 -1
- package/spa/src/components/Filters.vue +19 -15
- package/spa/src/components/ResourceForm.vue +15 -15
- package/spa/src/components/ResourceListTable.vue +36 -16
- package/spa/src/composables/useStores.ts +64 -3
- package/spa/src/stores/core.ts +17 -11
- package/spa/src/stores/filters.ts +22 -0
- package/spa/src/stores/modal.ts +0 -1
- package/spa/src/views/CreateView.vue +24 -10
- package/spa/src/views/EditView.vue +5 -5
- package/spa/src/views/ListView.vue +25 -23
- package/spa/src/views/ShowView.vue +5 -5
- package/types/AdminForthConfig.ts +32 -1
- package/types/FrontendAPI.ts +47 -0
|
@@ -13,13 +13,13 @@
|
|
|
13
13
|
<BreadcrumbsWithButtons>
|
|
14
14
|
<!-- save and cancle -->
|
|
15
15
|
<button @click="$router.back()"
|
|
16
|
-
class="flex items-center py-1 px-3 me-2
|
|
16
|
+
class="flex items-center py-1 px-3 me-2 text-sm font-medium rounded-default text-gray-900 focus:outline-none bg-white rounded border border-gray-300 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-100 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700"
|
|
17
17
|
>
|
|
18
18
|
Cancel
|
|
19
19
|
</button>
|
|
20
20
|
|
|
21
21
|
<button @click="saveRecord"
|
|
22
|
-
class="flex items-center py-1 px-3
|
|
22
|
+
class="flex items-center py-1 px-3 text-sm font-medium rounded-default text-red-600 focus:outline-none bg-white rounded border border-gray-300 hover:bg-gray-100 hover:text-red-700 focus:z-10 focus:ring-4 focus:ring-gray-100 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-red-500 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700 disabled:opacity-50"
|
|
23
23
|
:disabled="saving || (validating && !isValid)"
|
|
24
24
|
>
|
|
25
25
|
<svg v-if="saving" x
|
|
@@ -45,8 +45,8 @@
|
|
|
45
45
|
|
|
46
46
|
<ResourceForm
|
|
47
47
|
v-else
|
|
48
|
-
:record="
|
|
49
|
-
:
|
|
48
|
+
:record="initalValues"
|
|
49
|
+
:resource="coreStore.resource"
|
|
50
50
|
@update:record="onUpdateRecord"
|
|
51
51
|
@update:isValid="isValid = $event"
|
|
52
52
|
:validating="validating"
|
|
@@ -77,6 +77,7 @@ import { callAdminForthApi, getCustomComponent,checkAcessByAllowedActions } from
|
|
|
77
77
|
import { IconFloppyDiskSolid } from '@iconify-prerendered/vue-flowbite';
|
|
78
78
|
import { onMounted, ref } from 'vue';
|
|
79
79
|
import { useRoute, useRouter } from 'vue-router';
|
|
80
|
+
import { computed } from 'vue';
|
|
80
81
|
|
|
81
82
|
|
|
82
83
|
const isValid = ref(false);
|
|
@@ -93,6 +94,13 @@ let createComponentsPerColumn = {};
|
|
|
93
94
|
|
|
94
95
|
const coreStore = useCoreStore();
|
|
95
96
|
|
|
97
|
+
const initalValues = computed(() => {
|
|
98
|
+
if (!route.query.values) {
|
|
99
|
+
return {};
|
|
100
|
+
}
|
|
101
|
+
return JSON.parse(decodeURIComponent(route.query.values));
|
|
102
|
+
});
|
|
103
|
+
|
|
96
104
|
async function onUpdateRecord(newRecord) {
|
|
97
105
|
console.log('newRecord', newRecord);
|
|
98
106
|
record.value = newRecord;
|
|
@@ -103,7 +111,7 @@ onMounted(async () => {
|
|
|
103
111
|
await coreStore.fetchResourceFull({
|
|
104
112
|
resourceId: route.params.resourceId
|
|
105
113
|
});
|
|
106
|
-
createComponentsPerColumn = coreStore.
|
|
114
|
+
createComponentsPerColumn = coreStore.resource.columns.reduce((acc, column) => {
|
|
107
115
|
if (column.components?.create) {
|
|
108
116
|
acc[column.name] = getCustomComponent(column.components.create);
|
|
109
117
|
}
|
|
@@ -130,11 +138,17 @@ async function saveRecord() {
|
|
|
130
138
|
},
|
|
131
139
|
});
|
|
132
140
|
saving.value = false;
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
141
|
+
if (route.query.returnTo) {
|
|
142
|
+
router.push(route.query.returnTo);
|
|
143
|
+
} else {
|
|
144
|
+
router.push({
|
|
145
|
+
name: 'resource-show',
|
|
146
|
+
params: {
|
|
147
|
+
resourceId: route.params.resourceId,
|
|
148
|
+
primaryKey: response.newRecordId
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
}
|
|
138
152
|
}
|
|
139
153
|
|
|
140
154
|
|
|
@@ -12,13 +12,13 @@
|
|
|
12
12
|
<BreadcrumbsWithButtons>
|
|
13
13
|
<!-- save and cancle -->
|
|
14
14
|
<button @click="$router.back()"
|
|
15
|
-
class="flex items-center py-1 px-3 me-2
|
|
15
|
+
class="flex items-center py-1 px-3 me-2 text-sm font-medium text-gray-900 rounded-default focus:outline-none bg-white rounded border border-gray-300 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-100 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700"
|
|
16
16
|
>
|
|
17
17
|
Cancel
|
|
18
18
|
</button>
|
|
19
19
|
|
|
20
20
|
<button @click="saveRecord"
|
|
21
|
-
class="flex items-center py-1 px-3
|
|
21
|
+
class="flex items-center py-1 px-3 text-sm font-medium rounded-default text-red-600 focus:outline-none bg-white rounded border border-gray-300 hover:bg-gray-100 hover:text-red-700 focus:z-10 focus:ring-4 focus:ring-gray-100 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-red-500 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700"
|
|
22
22
|
:disabled="saving || (validating && !isValid)"
|
|
23
23
|
>
|
|
24
24
|
<IconFloppyDiskSolid class="w-4 h-4" />
|
|
@@ -95,10 +95,10 @@ async function onUpdateRecord(newRecord) {
|
|
|
95
95
|
|
|
96
96
|
const editableRecord = computed(() => {
|
|
97
97
|
const newRecord = { ...coreStore.record };
|
|
98
|
-
if (!coreStore.
|
|
98
|
+
if (!coreStore.resource) {
|
|
99
99
|
return {};
|
|
100
100
|
}
|
|
101
|
-
coreStore.
|
|
101
|
+
coreStore.resource.columns.forEach(column => {
|
|
102
102
|
if (column.foreignResource) {
|
|
103
103
|
newRecord[column.name] = newRecord[column.name]?.pk
|
|
104
104
|
}
|
|
@@ -119,7 +119,7 @@ onMounted(async () => {
|
|
|
119
119
|
});
|
|
120
120
|
checkAcessByAllowedActions(coreStore.resourceOptions.allowedActions,'edit');
|
|
121
121
|
|
|
122
|
-
editComponentsPerColumn = coreStore.
|
|
122
|
+
editComponentsPerColumn = coreStore.resource.columns.reduce((acc, column) => {
|
|
123
123
|
if (column.components?.edit) {
|
|
124
124
|
acc[column.name] = getCustomComponent(column.components.edit);
|
|
125
125
|
}
|
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
<div class="relative">
|
|
3
3
|
<Teleport to="body">
|
|
4
4
|
<Filters
|
|
5
|
-
:columns="coreStore.
|
|
6
|
-
v-model:filters="filters"
|
|
5
|
+
:columns="coreStore.resource.columns"
|
|
7
6
|
:columnsMinMax="columnsMinMax" :show="filtersShow"
|
|
8
7
|
@hide="filtersShow = false"
|
|
9
8
|
/>
|
|
@@ -23,7 +22,7 @@
|
|
|
23
22
|
v-if="checkboxes.length"
|
|
24
23
|
data-tooltip-target="tooltip-remove-all"
|
|
25
24
|
data-tooltip-placement="bottom"
|
|
26
|
-
class="flex gap-1 items-center py-1 px-3 me-2
|
|
25
|
+
class="flex gap-1 items-center py-1 px-3 me-2 text-sm font-medium text-gray-900 focus:outline-none bg-white rounded border border-gray-300 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-100 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700"
|
|
27
26
|
>
|
|
28
27
|
<IconBanOutline class="w-5 h-5 "/>
|
|
29
28
|
|
|
@@ -39,7 +38,7 @@
|
|
|
39
38
|
v-for="(action,i) in coreStore.resource?.options?.bulkActions"
|
|
40
39
|
:key="action.id"
|
|
41
40
|
@click="startBulkAction(action.id)"
|
|
42
|
-
class="flex gap-1 items-center py-1 px-3
|
|
41
|
+
class="flex gap-1 items-center py-1 px-3 text-sm font-medium text-gray-900 focus:outline-none bg-white rounded border border-gray-300 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-100 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700"
|
|
43
42
|
:class="{'bg-red-100 text-red-800 border-red-400 dark:bg-red-700 dark:text-red-400 dark:border-red-400':action.state==='danger', 'bg-green-100 text-green-800 border-green-400 dark:bg-green-700 dark:text-green-400 dark:border-green-400':action.state==='success',
|
|
44
43
|
'bg-blue-100 text-blue-800 border-blue-400 dark:bg-blue-700 dark:text-blue-400 dark:border-blue-400':action.state==='active',
|
|
45
44
|
}"
|
|
@@ -52,24 +51,24 @@
|
|
|
52
51
|
{{ `${action.label} (${checkboxes.length})` }}
|
|
53
52
|
</button>
|
|
54
53
|
|
|
55
|
-
<RouterLink v-if="coreStore.resource?.options?.create"
|
|
54
|
+
<RouterLink v-if="coreStore.resource?.options?.allowedActions?.create"
|
|
56
55
|
:to="{ name: 'resource-create', params: { resourceId: $route.params.resourceId } }"
|
|
57
|
-
class="flex items-center py-1 px-3
|
|
56
|
+
class="flex items-center py-1 px-3 text-sm font-medium text-gray-900 focus:outline-none bg-white rounded border border-gray-300 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-100 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700 rounded-default"
|
|
58
57
|
>
|
|
59
58
|
<IconPlusOutline class="w-4 h-4 me-2"/>
|
|
60
59
|
Create
|
|
61
60
|
</RouterLink>
|
|
62
61
|
|
|
63
62
|
<button
|
|
64
|
-
class="flex gap-1 items-center py-1 px-3 me-2
|
|
63
|
+
class="flex gap-1 items-center py-1 px-3 me-2 text-sm font-medium text-gray-900 focus:outline-none bg-white rounded border border-gray-300 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-100 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700 rounded-default"
|
|
65
64
|
@click="()=>{filtersShow = !filtersShow}"
|
|
66
65
|
>
|
|
67
66
|
<IconFilterOutline class="w-4 h-4 me-2"/>
|
|
68
67
|
Filter
|
|
69
68
|
<span
|
|
70
69
|
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
|
-
v-if="filters.length">
|
|
72
|
-
{{ filters.length }}
|
|
70
|
+
v-if="filtersStore.filters.length">
|
|
71
|
+
{{ filtersStore.filters.length }}
|
|
73
72
|
</span>
|
|
74
73
|
</button>
|
|
75
74
|
</BreadcrumbsWithButtons>
|
|
@@ -90,6 +89,7 @@
|
|
|
90
89
|
@update:checkboxes="checkboxes = $event"
|
|
91
90
|
:pageSize="pageSize"
|
|
92
91
|
:totalRows="totalRows"
|
|
92
|
+
:checkboxes="checkboxes"
|
|
93
93
|
/>
|
|
94
94
|
|
|
95
95
|
<component
|
|
@@ -108,6 +108,7 @@ import BreadcrumbsWithButtons from '@/components/BreadcrumbsWithButtons.vue';
|
|
|
108
108
|
import ResourceListTable from '@/components/ResourceListTable.vue';
|
|
109
109
|
import { useCoreStore } from '@/stores/core';
|
|
110
110
|
import { useModalStore } from '@/stores/modal';
|
|
111
|
+
import { useFiltersStore } from '@/stores/filters';
|
|
111
112
|
import { callAdminForthApi, getIcon } from '@/utils';
|
|
112
113
|
import { initFlowbite } from 'flowbite';
|
|
113
114
|
import { computed, onMounted, ref, watch } from 'vue';
|
|
@@ -116,17 +117,15 @@ import { useRoute } from 'vue-router';
|
|
|
116
117
|
import ValueRenderer from '@/components/ValueRenderer.vue';
|
|
117
118
|
import { getCustomComponent } from '@/utils';
|
|
118
119
|
|
|
119
|
-
import {
|
|
120
|
-
IconInboxOutline,
|
|
121
|
-
IconPlusOutline
|
|
122
|
-
} from '@iconify-prerendered/vue-flowbite';
|
|
123
120
|
|
|
124
121
|
import {
|
|
125
|
-
IconBanOutline,
|
|
126
|
-
IconEyeSolid,
|
|
127
|
-
IconFilterOutline,
|
|
128
|
-
IconPenSolid,
|
|
129
|
-
IconTrashBinSolid
|
|
122
|
+
IconBanOutline,
|
|
123
|
+
IconEyeSolid,
|
|
124
|
+
IconFilterOutline,
|
|
125
|
+
IconPenSolid,
|
|
126
|
+
IconTrashBinSolid,
|
|
127
|
+
IconInboxOutline,
|
|
128
|
+
IconPlusOutline
|
|
130
129
|
} from '@iconify-prerendered/vue-flowbite';
|
|
131
130
|
|
|
132
131
|
import Filters from '@/components/Filters.vue';
|
|
@@ -135,11 +134,12 @@ const filtersShow = ref(false);
|
|
|
135
134
|
|
|
136
135
|
const coreStore = useCoreStore();
|
|
137
136
|
const modalStore = useModalStore();
|
|
137
|
+
const filtersStore = useFiltersStore();
|
|
138
138
|
|
|
139
139
|
const route = useRoute();
|
|
140
140
|
|
|
141
141
|
const page = ref(1);
|
|
142
|
-
const filters =
|
|
142
|
+
const filters = filtersStore.filters;
|
|
143
143
|
const columnsMinMax = ref({});
|
|
144
144
|
const sort = ref([]);
|
|
145
145
|
|
|
@@ -157,8 +157,10 @@ watch([page], async () => {
|
|
|
157
157
|
await getList();
|
|
158
158
|
});
|
|
159
159
|
|
|
160
|
-
watch(
|
|
160
|
+
watch(()=>filtersStore.filters, async () => {
|
|
161
161
|
page.value = 1;
|
|
162
|
+
checkboxes.value = [];
|
|
163
|
+
|
|
162
164
|
await getList();
|
|
163
165
|
}, {deep: true});
|
|
164
166
|
|
|
@@ -177,13 +179,13 @@ async function getList() {
|
|
|
177
179
|
resourceId: route.params.resourceId,
|
|
178
180
|
limit: pageSize.value,
|
|
179
181
|
offset: (page.value - 1) * pageSize.value,
|
|
180
|
-
filters: filters
|
|
182
|
+
filters: filtersStore.filters,
|
|
181
183
|
sort: sort.value,
|
|
182
184
|
}
|
|
183
185
|
});
|
|
184
186
|
|
|
185
187
|
rows.value = data.data?.map(row => {
|
|
186
|
-
row._primaryKeyValue = row[coreStore.
|
|
188
|
+
row._primaryKeyValue = row[coreStore.resource.columns.find(c => c.primaryKey).name];
|
|
187
189
|
return row;
|
|
188
190
|
});
|
|
189
191
|
totalRows.value = data.total;
|
|
@@ -265,7 +267,7 @@ onMounted(async () => {
|
|
|
265
267
|
|
|
266
268
|
// on route param change
|
|
267
269
|
watch(() => route.params.resourceId, async () => {
|
|
268
|
-
|
|
270
|
+
filtersStore.setFilters([]);
|
|
269
271
|
checkboxes.value = [];
|
|
270
272
|
sort.value = [];
|
|
271
273
|
await init();
|
|
@@ -10,14 +10,14 @@
|
|
|
10
10
|
/>
|
|
11
11
|
<BreadcrumbsWithButtons>
|
|
12
12
|
<RouterLink v-if="coreStore?.resourceOptions?.allowedActions?.edit" :to="{ name: 'resource-edit', params: { resourceId: $route.params.resourceId, primaryKey: $route.params.primaryKey } }"
|
|
13
|
-
class="flex items-center py-1 px-3
|
|
13
|
+
class="flex items-center py-1 px-3 text-sm font-medium text-gray-900 focus:outline-none bg-white rounded border border-gray-300 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-100 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700"
|
|
14
14
|
>
|
|
15
15
|
<IconPenSolid class="w-4 h-4" />
|
|
16
16
|
Edit
|
|
17
17
|
</RouterLink>
|
|
18
18
|
|
|
19
19
|
<button v-if="coreStore?.resourceOptions?.allowedActions?.delete" @click="showDeleteModal"
|
|
20
|
-
class="flex items-center py-1 px-3
|
|
20
|
+
class="flex items-center py-1 px-3 text-sm font-medium rounded-default text-red-600 focus:outline-none bg-white rounded border border-gray-300 hover:bg-gray-100 hover:text-red-700 focus:z-10 focus:ring-4 focus:ring-gray-100 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-red-500 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700"
|
|
21
21
|
>
|
|
22
22
|
<IconTrashBinSolid class="w-4 h-4" />
|
|
23
23
|
Delete
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
</tr>
|
|
59
59
|
</thead>
|
|
60
60
|
<tbody>
|
|
61
|
-
<tr v-for="column in coreStore.
|
|
61
|
+
<tr v-for="column in coreStore.resource?.columns.filter(c => c.showIn.includes('show'))" :key="column.name"
|
|
62
62
|
class="bg-form-view-bg odd:dark:bg-gray-900 even:dark:bg-gray-800 border-b dark:border-gray-700"
|
|
63
63
|
>
|
|
64
64
|
<component
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
:record="coreStore.record"
|
|
71
71
|
/>
|
|
72
72
|
<template v-else>
|
|
73
|
-
<td class="px-6 py-4 whitespace-nowrap">
|
|
73
|
+
<td class="px-6 py-4 whitespace-nowrap "> <!--align-top-->
|
|
74
74
|
{{ column.label }}
|
|
75
75
|
</td>
|
|
76
76
|
<td class="px-6 py-4 whitespace-nowrap whitespace-pre-wrap">
|
|
@@ -145,7 +145,7 @@ onMounted(async () => {
|
|
|
145
145
|
});
|
|
146
146
|
checkAcessByAllowedActions(coreStore.resourceOptions.allowedActions,'show');
|
|
147
147
|
|
|
148
|
-
showComponentsPerColumn = coreStore.
|
|
148
|
+
showComponentsPerColumn = coreStore.resource.columns.reduce((acc, column) => {
|
|
149
149
|
if (column.components?.show) {
|
|
150
150
|
acc[column.name] = getCustomComponent(column.components.show);
|
|
151
151
|
}
|
|
@@ -19,6 +19,17 @@ export interface GenericHttpServer {
|
|
|
19
19
|
*/
|
|
20
20
|
setupSpaServer(): void;
|
|
21
21
|
|
|
22
|
+
/**
|
|
23
|
+
* Method which should register endpoint in HTTP server.
|
|
24
|
+
*
|
|
25
|
+
* @param options : Object with method, path and handler properties.
|
|
26
|
+
*/
|
|
27
|
+
endpoint(options: {
|
|
28
|
+
method: string,
|
|
29
|
+
path: string,
|
|
30
|
+
handler: Function,
|
|
31
|
+
}): void;
|
|
32
|
+
|
|
22
33
|
}
|
|
23
34
|
|
|
24
35
|
export interface ExpressHttpServer extends GenericHttpServer {
|
|
@@ -53,6 +64,7 @@ export interface AdminForthClass {
|
|
|
53
64
|
codeInjector: CodeInjectorType;
|
|
54
65
|
express: GenericHttpServer;
|
|
55
66
|
|
|
67
|
+
|
|
56
68
|
auth: {
|
|
57
69
|
|
|
58
70
|
verify(jwt : string): any;
|
|
@@ -91,8 +103,26 @@ export interface AdminForthPluginType {
|
|
|
91
103
|
adminforth: AdminForthClass;
|
|
92
104
|
pluginDir: string;
|
|
93
105
|
customFolderName: string;
|
|
106
|
+
pluginInstanceId: string;
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* AdminForth plugins concept is based on modification of full AdminForth configuration
|
|
110
|
+
* to add some custom functionality. For example plugin might simply add custom field to resource by reusing
|
|
111
|
+
* {@link AdminForthResourceColumn.components} object, then add some hook which will modify record before getting or saving it to database.
|
|
112
|
+
*
|
|
113
|
+
* So this method is core of AdminForth plugins. It allows to modify full resource configuration.
|
|
114
|
+
* @param adminforth Instance of AdminForthClass
|
|
115
|
+
* @param resourceConfig Resource configuration object which will be modified by plugin
|
|
116
|
+
*/
|
|
94
117
|
modifyResourceConfig(adminforth: AdminForthClass, resourceConfig: AdminForthResource): void;
|
|
95
118
|
componentPath(componentFile: string): string;
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Here you can register custom endpoints for your plugin.
|
|
122
|
+
*
|
|
123
|
+
* @param server
|
|
124
|
+
*/
|
|
125
|
+
setupEndpoints(server: GenericHttpServer): void;
|
|
96
126
|
}
|
|
97
127
|
|
|
98
128
|
export enum AdminForthMenuTypes {
|
|
@@ -450,9 +480,10 @@ export type AdminForthResource = {
|
|
|
450
480
|
bulkActions?: Array<{
|
|
451
481
|
label: string,
|
|
452
482
|
state: string,
|
|
453
|
-
icon
|
|
483
|
+
icon?: string,
|
|
454
484
|
action: Function,
|
|
455
485
|
id?: string,
|
|
486
|
+
confirm?: string,
|
|
456
487
|
}>,
|
|
457
488
|
allowedActions?: AllowedActions,
|
|
458
489
|
|
package/types/FrontendAPI.ts
CHANGED
|
@@ -33,6 +33,35 @@ export interface FrontendAPIInterface {
|
|
|
33
33
|
* @param params - The parameters of the alert
|
|
34
34
|
*/
|
|
35
35
|
alert(params:AlertParams): void;
|
|
36
|
+
/**
|
|
37
|
+
* Add a filter to the list of filters
|
|
38
|
+
*
|
|
39
|
+
* Example:
|
|
40
|
+
*
|
|
41
|
+
* ```ts
|
|
42
|
+
* window.adminforth.updateListFilter({field: 'name', operator: 'ilike', value: 'john'})
|
|
43
|
+
* ```
|
|
44
|
+
*
|
|
45
|
+
* @param filter - The filter to add
|
|
46
|
+
*/
|
|
47
|
+
setListFilter(filter: any): void;
|
|
48
|
+
/**
|
|
49
|
+
* Update a filter in the list of filters
|
|
50
|
+
*
|
|
51
|
+
* Example:
|
|
52
|
+
*
|
|
53
|
+
* ```ts
|
|
54
|
+
* window.adminforth.updateListFilter({field: 'name', operator: 'ilike', value: 'john'})
|
|
55
|
+
* ```
|
|
56
|
+
*
|
|
57
|
+
* @param filter - The filter to update
|
|
58
|
+
*/
|
|
59
|
+
updateListFilter(filter: any): void;
|
|
60
|
+
/**
|
|
61
|
+
* Clear all filters from the list
|
|
62
|
+
*/
|
|
63
|
+
clearListFilters(): void;
|
|
64
|
+
|
|
36
65
|
}
|
|
37
66
|
|
|
38
67
|
export type ConfirmParams = {
|
|
@@ -62,12 +91,30 @@ export type AlertParams = {
|
|
|
62
91
|
variant?: AlertVariant;
|
|
63
92
|
}
|
|
64
93
|
|
|
94
|
+
export type FilterParams = {
|
|
95
|
+
/**
|
|
96
|
+
* Field of resource to filter
|
|
97
|
+
*/
|
|
98
|
+
field: string;
|
|
99
|
+
/**
|
|
100
|
+
* Operator of filter
|
|
101
|
+
*/
|
|
102
|
+
operator: Operator;
|
|
103
|
+
/**
|
|
104
|
+
* Value of filter
|
|
105
|
+
*/
|
|
106
|
+
value: string | number | boolean ;
|
|
107
|
+
}
|
|
108
|
+
|
|
65
109
|
export enum AlertVariant {
|
|
66
110
|
Danger = 'danger',
|
|
67
111
|
Success = 'success',
|
|
68
112
|
Warning = 'warning',
|
|
69
113
|
Info = 'info'
|
|
70
114
|
}
|
|
115
|
+
|
|
116
|
+
export type Operator = 'in' | 'ilike' | 'gte' | 'lte' ;
|
|
117
|
+
|
|
71
118
|
|
|
72
119
|
|
|
73
120
|
|