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.
Files changed (38) hide show
  1. package/dist/index.js +6 -0
  2. package/dist/modules/styles.js +7 -6
  3. package/dist/plugins/ForeignInlineListPlugin/index.js +32 -1
  4. package/dist/plugins/base.js +4 -0
  5. package/dist/spa/spa/src/App.vue +2 -2
  6. package/dist/spa/spa/src/components/BreadcrumbsWithButtons.vue +1 -1
  7. package/dist/spa/spa/src/components/Filters.vue +19 -15
  8. package/dist/spa/spa/src/components/ResourceForm.vue +15 -15
  9. package/dist/spa/spa/src/components/ResourceListTable.vue +36 -16
  10. package/dist/spa/spa/src/composables/useStores.ts +64 -3
  11. package/dist/spa/spa/src/stores/core.ts +17 -11
  12. package/dist/spa/spa/src/stores/filters.ts +22 -0
  13. package/dist/spa/spa/src/stores/modal.ts +0 -1
  14. package/dist/spa/spa/src/views/CreateView.vue +24 -10
  15. package/dist/spa/spa/src/views/EditView.vue +5 -5
  16. package/dist/spa/spa/src/views/ListView.vue +25 -23
  17. package/dist/spa/spa/src/views/ShowView.vue +5 -5
  18. package/index.ts +10 -0
  19. package/modules/styles.ts +7 -6
  20. package/package.json +1 -1
  21. package/plugins/ForeignInlineListPlugin/custom/InlineList.vue +138 -14
  22. package/plugins/ForeignInlineListPlugin/index.ts +32 -5
  23. package/plugins/base.ts +7 -0
  24. package/spa/src/App.vue +2 -2
  25. package/spa/src/components/BreadcrumbsWithButtons.vue +1 -1
  26. package/spa/src/components/Filters.vue +19 -15
  27. package/spa/src/components/ResourceForm.vue +15 -15
  28. package/spa/src/components/ResourceListTable.vue +36 -16
  29. package/spa/src/composables/useStores.ts +64 -3
  30. package/spa/src/stores/core.ts +17 -11
  31. package/spa/src/stores/filters.ts +22 -0
  32. package/spa/src/stores/modal.ts +0 -1
  33. package/spa/src/views/CreateView.vue +24 -10
  34. package/spa/src/views/EditView.vue +5 -5
  35. package/spa/src/views/ListView.vue +25 -23
  36. package/spa/src/views/ShowView.vue +5 -5
  37. package/types/AdminForthConfig.ts +32 -1
  38. 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 mb-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"
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 mb-2 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"
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
- :resourceColumns="coreStore.resourceColumns"
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.resourceColumns.reduce((acc, column) => {
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
- router.push({ name: 'resource-show', params: {
134
- resourceId: route.params.resourceId,
135
- primaryKey: response.newRecordId
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 mb-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"
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 mb-2 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
+ 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.resourceColumns) {
98
+ if (!coreStore.resource) {
99
99
  return {};
100
100
  }
101
- coreStore.resourceColumns.forEach(column => {
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.resourceColumns.reduce((acc, column) => {
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.resourceColumns"
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 mb-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"
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 mb-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"
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 mb-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"
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 mb-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"
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 = ref([]);
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([filters], async () => {
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.value,
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.resourceColumns.find(c => c.primaryKey).name];
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
- filters.value = [];
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 me-2 mb-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"
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 mb-2 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"
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.resourceColumns?.filter(c => c.showIn.includes('show'))" :key="column.name"
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.resourceColumns.reduce((acc, column) => {
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: string,
483
+ icon?: string,
454
484
  action: Function,
455
485
  id?: string,
486
+ confirm?: string,
456
487
  }>,
457
488
  allowedActions?: AllowedActions,
458
489
 
@@ -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