adminforth 1.1.29 → 1.1.31

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 (41) hide show
  1. package/dist/index.js +0 -1
  2. package/dist/plugins/AccessControl/index.js +3 -56
  3. package/dist/plugins/ForeignInlineListPlugin/custom/InlineList.vue +2 -2
  4. package/dist/plugins/ForeignInlineListPlugin/index.js +0 -1
  5. package/dist/plugins/plugins/ForeignInlineListPlugin/custom/InlineList.vue +248 -0
  6. package/dist/spa/index.html +2 -2
  7. package/dist/spa/package-lock.json +1 -189
  8. package/dist/spa/package.json +1 -6
  9. package/dist/spa/spa/src/components/ResourceListTable.vue +2 -2
  10. package/dist/spa/spa/src/components/ShowTableItem.vue +14 -0
  11. package/dist/spa/spa/src/views/HomeView.vue +8 -0
  12. package/dist/spa/spa/src/views/ListView.vue +2 -2
  13. package/dist/spa/spa/src/views/ShowView.vue +2 -2
  14. package/dist/spa/src/App.vue +57 -76
  15. package/dist/spa/src/components/AcceptModal.vue +1 -1
  16. package/dist/spa/src/components/CustomDatePicker.vue +3 -3
  17. package/dist/spa/src/components/CustomDateRangePicker.vue +3 -3
  18. package/dist/spa/src/components/Dropdown.vue +4 -13
  19. package/dist/spa/src/components/Filters.vue +22 -55
  20. package/dist/spa/src/components/MenuLink.vue +2 -2
  21. package/dist/spa/src/components/ResourceForm.vue +99 -157
  22. package/dist/spa/src/components/ValueRenderer.vue +1 -11
  23. package/dist/spa/src/router/index.ts +2 -3
  24. package/dist/spa/src/stores/core.ts +33 -22
  25. package/dist/spa/src/utils.ts +3 -5
  26. package/dist/spa/src/views/CreateView.vue +7 -15
  27. package/dist/spa/src/views/EditView.vue +8 -36
  28. package/dist/spa/src/views/HomeView.vue +8 -0
  29. package/dist/spa/src/views/ListView.vue +23 -35
  30. package/dist/spa/src/views/LoginView.vue +1 -1
  31. package/dist/spa/src/views/ResourceParent.vue +1 -1
  32. package/dist/spa/src/views/ShowView.vue +9 -20
  33. package/dist/spa/tailwind.config.js +2 -5
  34. package/index.ts +0 -1
  35. package/package.json +1 -1
  36. package/plugins/ForeignInlineListPlugin/custom/InlineList.vue +2 -2
  37. package/plugins/ForeignInlineListPlugin/index.ts +0 -1
  38. package/spa/src/components/ResourceListTable.vue +2 -2
  39. package/spa/src/views/ListView.vue +2 -2
  40. package/spa/src/views/ShowView.vue +2 -2
  41. package/dist/spa/src/components/CustomRangePicker.vue +0 -148
package/dist/index.js CHANGED
@@ -693,7 +693,6 @@ class AdminForth {
693
693
  }
694
694
  yield interpretResource(adminUser, resource, { requestBody: body }, ActionCheckSource.DisplayButtons);
695
695
  const { allowed, error } = checkAccess(source, resource);
696
- console.log('allowed', allowed, error);
697
696
  if (!allowed) {
698
697
  return { error };
699
698
  }
@@ -1,15 +1,5 @@
1
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
- return new (P || (P = Promise))(function (resolve, reject) {
4
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
- step((generator = generator.apply(thisArg, _arguments || [])).next());
8
- });
9
- };
10
- import { AllowedActionsEnum } from "../../types/AdminForthConfig.js";
11
1
  import AdminForthPlugin from "../base.js";
12
- class AccessControlPlugin extends AdminForthPlugin {
2
+ class AuditLogPlugin extends AdminForthPlugin {
13
3
  constructor(options) {
14
4
  super(options, import.meta.url);
15
5
  this.options = options;
@@ -17,50 +7,7 @@ class AccessControlPlugin extends AdminForthPlugin {
17
7
  modifyResourceConfig(adminforth, resourceConfig) {
18
8
  super.modifyResourceConfig(adminforth, resourceConfig);
19
9
  this.adminforth = adminforth;
20
- if (!resourceConfig.hooks) {
21
- resourceConfig.hooks = {};
22
- }
23
- const checkAccess = (adminUser, action, meta) => __awaiter(this, void 0, void 0, function* () {
24
- const hasAccessOrError = yield this.options.hasAccess(adminUser, action, meta);
25
- if (hasAccessOrError === true) {
26
- return { ok: true };
27
- }
28
- else {
29
- return { ok: false, error: hasAccessOrError || AccessControlPlugin.defaultError };
30
- }
31
- });
32
- const bindHookCheck = (action, hookName) => {
33
- if (!resourceConfig.hooks[action]) {
34
- resourceConfig.hooks[action] = {};
35
- }
36
- if (!resourceConfig.hooks[action][hookName]) {
37
- resourceConfig.hooks[action][hookName] = [];
38
- }
39
- if (hookName === 'beforeDatasourceRequest') {
40
- resourceConfig.hooks[action][hookName].unshift((_a) => __awaiter(this, [_a], void 0, function* ({ adminUser, query }) {
41
- return checkAccess(adminUser, action, { query });
42
- }));
43
- }
44
- else {
45
- resourceConfig.hooks[action][hookName].unshift((_b) => __awaiter(this, [_b], void 0, function* ({ adminUser, record }) {
46
- return checkAccess(adminUser, action, { record });
47
- }));
48
- }
49
- };
50
- // List check
51
- bindHookCheck(AllowedActionsEnum.list, 'beforeDatasourceRequest');
52
- // Show check
53
- bindHookCheck(AllowedActionsEnum.show, 'beforeDatasourceRequest');
54
- // Edit check
55
- bindHookCheck(AllowedActionsEnum.edit, 'beforeDatasourceRequest');
56
- // create check
57
- bindHookCheck(AllowedActionsEnum.create, 'beforeSave');
58
- // edit check
59
- bindHookCheck(AllowedActionsEnum.edit, 'beforeSave');
60
- // delete check
61
- bindHookCheck(AllowedActionsEnum.delete, 'beforeSave');
62
- console.log('resourceConfig', resourceConfig);
63
10
  }
64
11
  }
65
- AccessControlPlugin.defaultError = 'Sorry, you do not have access to this resource.';
66
- export default AccessControlPlugin;
12
+ AuditLogPlugin.defaultError = 'Sorry, you do not have access to this resource.';
13
+ export default AuditLogPlugin;
@@ -22,7 +22,7 @@
22
22
  v-if="checkboxes.length"
23
23
  data-tooltip-target="tooltip-remove-all"
24
24
  data-tooltip-placement="bottom"
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"
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-default 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"
26
26
  >
27
27
  <IconBanOutline class="w-5 h-5 "/>
28
28
  <div id="tooltip-remove-all" role="tooltip"
@@ -37,7 +37,7 @@
37
37
  v-for="(action,i) in listResource?.options?.bulkActions"
38
38
  :key="action.id"
39
39
  @click="startBulkAction(action.id)"
40
- 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"
40
+ class="flex gap-1 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-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
41
  :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',
42
42
  'bg-blue-100 text-blue-800 border-blue-400 dark:bg-blue-700 dark:text-blue-400 dark:border-blue-400':action.state==='active',
43
43
  }"
@@ -40,7 +40,6 @@ export default class ForeignInlineListPlugin extends AdminForthPlugin {
40
40
  if (!this.foreignResource) {
41
41
  throw new Error(`ForeignInlineListPlugin: Resource with ID "${this.options.foreignResourceId}" not found`);
42
42
  }
43
- console.log('🔌 ForeignInlineListPlugin', this.options);
44
43
  resourceConfig.columns.push({
45
44
  name: `foreignInlineList_${this.foreignResource.resourceId}`,
46
45
  label: 'Foreign Inline List',
@@ -0,0 +1,248 @@
1
+ <template>
2
+ <Teleport to="body">
3
+ <!-- todo exclude foreign column-->
4
+ <Filters
5
+ v-if="listResource"
6
+ :columns="listResource.columns.filter((c) => c.name !== listResourceRefColumn.name)"
7
+ v-model:filters="filters"
8
+ :columnsMinMax="columnsMinMax"
9
+ :show="filtersShow"
10
+ @hide="filtersShow = false"
11
+ />
12
+ </Teleport>
13
+
14
+ <td colspan="2">
15
+ <div class="flex items-center gap-1">
16
+ <h4 v-if="listResource"
17
+ class="px-6 py-4"
18
+ >{{ listResource.label }} inline records</h4>
19
+
20
+ <button
21
+ @click="()=>{checkboxes = []}"
22
+ v-if="checkboxes.length"
23
+ data-tooltip-target="tooltip-remove-all"
24
+ data-tooltip-placement="bottom"
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"
26
+ >
27
+ <IconBanOutline class="w-5 h-5 "/>
28
+ <div id="tooltip-remove-all" role="tooltip"
29
+ class="absolute z-10 invisible inline-block px-3 py-2 text-sm font-medium text-white transition-opacity duration-300 bg-gray-900 rounded-lg shadow-sm opacity-0 tooltip dark:bg-gray-700">
30
+ Remove selection
31
+ <div class="tooltip-arrow" data-popper-arrow></div>
32
+ </div>
33
+ </button>
34
+
35
+ <button
36
+ v-if="checkboxes.length"
37
+ v-for="(action,i) in listResource?.options?.bulkActions"
38
+ :key="action.id"
39
+ @click="startBulkAction(action.id)"
40
+ 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"
41
+ :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',
42
+ 'bg-blue-100 text-blue-800 border-blue-400 dark:bg-blue-700 dark:text-blue-400 dark:border-blue-400':action.state==='active',
43
+ }"
44
+ >
45
+ <component
46
+ v-if="action.icon"
47
+ :is="getIcon(action.icon)"
48
+ class="w-5 h-5 text-gray-500 transition duration-75 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white"></component>
49
+
50
+ {{ `${action.label} (${checkboxes.length})` }}
51
+ </button>
52
+
53
+ <RouterLink v-if="listResource?.options?.allowedActions?.create"
54
+ :to="{
55
+ name: 'resource-create',
56
+ params: { resourceId: listResource.resourceId },
57
+ query: {
58
+ values: encodeURIComponent(JSON.stringify({[listResourceRefColumn.name]: props.record[selfPrimaryKeyColumn.name]})),
59
+ returnTo: $route.fullPath,
60
+ },
61
+ }"
62
+ 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"
63
+ >
64
+ <IconPlusOutline class="w-4 h-4 me-2"/>
65
+ Create
66
+ </RouterLink>
67
+
68
+ <button
69
+ 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 rounded-default"
70
+ @click="()=>{filtersShow = !filtersShow}"
71
+ >
72
+ <IconFilterOutline class="w-4 h-4 me-2"/>
73
+ Filter
74
+ <span
75
+ class="bg-red-100 text-red-800 text-xs font-medium px-2.5 py-0.5 rounded dark:bg-gray-700 dark:text-red-400 border border-red-400"
76
+ v-if="filters.length">
77
+ {{ filters.length }}
78
+ </span>
79
+ </button>
80
+
81
+ </div>
82
+
83
+ <ResourceListTable
84
+ :resource="listResource"
85
+ :rows="rows"
86
+ @update:page="page = $event"
87
+ @update:sort="sort = $event"
88
+ @update:checkboxes="checkboxes = $event"
89
+ :pageSize="pageSize"
90
+ :totalRows="totalRows"
91
+ :checkboxes="checkboxes"
92
+ />
93
+
94
+ </td>
95
+ </template>
96
+
97
+ <script setup>
98
+ import { callAdminForthApi } from '@/utils';
99
+ import { ref, onMounted, watch, computed } from 'vue';
100
+ import ResourceListTable from '@/components/ResourceListTable.vue';
101
+ import Filters from '@/components/Filters.vue';
102
+ import {
103
+ IconBanOutline,
104
+ IconFilterOutline,
105
+ IconPlusOutline,
106
+ } from '@iconify-prerendered/vue-flowbite';
107
+
108
+ import { getIcon } from '@/utils';
109
+
110
+ const props = defineProps(['column', 'record', 'meta', 'resource', 'adminUser']);
111
+
112
+ const listResource = ref(null);
113
+ const loading = ref(true);
114
+
115
+ const page = ref(1);
116
+ const sort = ref([]);
117
+ const checkboxes = ref([]);
118
+ const pageSize = computed(() => listResource.value?.options?.listPageSize || 10);
119
+
120
+ const rows = ref(null);
121
+ const totalRows = ref(0);
122
+
123
+ const filters = ref([]);
124
+ const filtersShow = ref(false);
125
+ const columnsMinMax = ref(null);
126
+
127
+ const listResourceRefColumn = computed(() => {
128
+ if (!listResource.value) {
129
+ return null;
130
+ }
131
+ return listResource.value.columns.find(c => c.foreignResource?.resourceId === props.resource.resourceId);
132
+ });
133
+
134
+ const selfPrimaryKeyColumn = computed(() => {
135
+ return props.resource.columns.find(c => c.primaryKey);
136
+ });
137
+
138
+ const endFilters = computed(() => {
139
+ if (!listResource.value) {
140
+ return [];
141
+ }
142
+ // get name of the column that is foreign key
143
+ const refColumn = listResourceRefColumn.value;
144
+
145
+ const primaryKeyColumn = selfPrimaryKeyColumn.value;
146
+
147
+ if (!refColumn) {
148
+ window.adminforth.alert({
149
+ message: `Column with foreignResource.resourceId which is equal to '${props.resource.resourceId}' not found in resource which is specified as foreighResourceId '${listResource.value.resourceId}'`,
150
+ variant: 'danger',
151
+ });
152
+ return [];
153
+ }
154
+ return [
155
+ ...filters.value,
156
+ {
157
+ field: refColumn.name,
158
+ operator: 'eq',
159
+ value: props.record[primaryKeyColumn.name],
160
+ },
161
+ ];
162
+ });
163
+
164
+ watch([page], async () => {
165
+ await getList();
166
+ });
167
+
168
+ watch([sort], async () => {
169
+ await getList();
170
+ }, {deep: true});
171
+
172
+ watch([filters], async () => {
173
+ page.value = 1;
174
+ checkboxes.value = [];
175
+ await getList();
176
+ }, {deep: true});
177
+
178
+
179
+ async function startBulkAction(actionId) {
180
+ const data = await callAdminForthApi({
181
+ path: '/start_bulk_action',
182
+ method: 'POST',
183
+ body: {
184
+ resourceId: listResource.value.resourceId,
185
+ actionId: actionId,
186
+ recordIds: checkboxes.value
187
+ }
188
+ });
189
+ if (data?.status === 'success') {
190
+ checkboxes.value = [];
191
+ }
192
+ await getList();
193
+ }
194
+
195
+ async function getList() {
196
+ rows.value = null;
197
+ console.log('getList', listResource.value)
198
+ const data = await callAdminForthApi({
199
+ path: '/get_resource_data',
200
+ method: 'POST',
201
+ body: {
202
+ source: 'list',
203
+ resourceId: listResource.value.resourceId,
204
+ limit: pageSize.value,
205
+ offset: (page.value - 1) * pageSize.value,
206
+ filters: endFilters.value,
207
+ sort: sort.value,
208
+ }
209
+ });
210
+
211
+ if (data.error) {
212
+ window.adminforth.alert({
213
+ message: data.error,
214
+ variant: 'danger',
215
+ timeout: 'unlimited',
216
+ });
217
+ rows.value = [];
218
+ totalRows.value = 0;
219
+ return;
220
+ }
221
+
222
+ rows.value = data.data?.map(row => {
223
+ row._primaryKeyValue = row[listResource.value.columns.find(c => c.primaryKey).name];
224
+ return row;
225
+ });
226
+ totalRows.value = data.total;
227
+ }
228
+
229
+ onMounted( async () => {
230
+ loading.value = true;
231
+ const foreighResourceId = props.meta.foreignResourceId;
232
+ listResource.value = (await callAdminForthApi({
233
+ path: `/plugin/${props.meta.pluginInstanceId}/get_resource`,
234
+ method: 'POST',
235
+ body: {},
236
+ })).resource;
237
+ columnsMinMax.value = await callAdminForthApi({
238
+ path: '/get_min_max_for_columns',
239
+ method: 'POST',
240
+ body: {
241
+ resourceId: foreighResourceId,
242
+ }
243
+ });
244
+ loading.value = false;
245
+ await getList();
246
+ });
247
+
248
+ </script>
@@ -16,8 +16,8 @@
16
16
  </script> -->
17
17
 
18
18
  </head>
19
- <body class=" ">
20
- <div id="app" class="min-h-screen bg-html-bg dark:bg-gray-800"></div>
19
+ <body>
20
+ <div id="app" class="min-h-screen dark:bg-gray-800"></div>
21
21
  <script type="module" src="/src/main.ts"></script>
22
22
  </body>
23
23
  </html>
@@ -9,17 +9,12 @@
9
9
  "version": "0.0.0",
10
10
  "dependencies": {
11
11
  "@iconify-prerendered/vue-flowbite": "^0.23.1714023977",
12
- "@unhead/vue": "^1.9.12",
13
- "@vueuse/core": "^10.10.0",
14
12
  "dayjs": "^1.11.11",
15
- "debounce": "^2.1.0",
16
13
  "flowbite": "^2.3.0",
17
14
  "flowbite-datepicker": "^1.2.6",
18
15
  "pinia": "^2.1.7",
19
- "unhead": "^1.9.12",
20
16
  "vue": "^3.4.21",
21
- "vue-router": "^4.3.0",
22
- "vue-slider-component": "^4.1.0-beta.7"
17
+ "vue-router": "^4.3.0"
23
18
  },
24
19
  "devDependencies": {
25
20
  "@rushstack/eslint-patch": "^1.8.0",
@@ -955,11 +950,6 @@
955
950
  "undici-types": "~5.26.4"
956
951
  }
957
952
  },
958
- "node_modules/@types/web-bluetooth": {
959
- "version": "0.0.20",
960
- "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz",
961
- "integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow=="
962
- },
963
953
  "node_modules/@typescript-eslint/eslint-plugin": {
964
954
  "version": "7.9.0",
965
955
  "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.9.0.tgz",
@@ -1151,58 +1141,6 @@
1151
1141
  "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==",
1152
1142
  "dev": true
1153
1143
  },
1154
- "node_modules/@unhead/dom": {
1155
- "version": "1.9.12",
1156
- "resolved": "https://registry.npmjs.org/@unhead/dom/-/dom-1.9.12.tgz",
1157
- "integrity": "sha512-3MY1TbZmEjGNZapi3wvJW0vWNS2CLKHt7/m57sScDHCNvNBe1mTwrIOhtZFDgAndhml2EVQ68RMa0Vhum/M+cw==",
1158
- "dependencies": {
1159
- "@unhead/schema": "1.9.12",
1160
- "@unhead/shared": "1.9.12"
1161
- },
1162
- "funding": {
1163
- "url": "https://github.com/sponsors/harlan-zw"
1164
- }
1165
- },
1166
- "node_modules/@unhead/schema": {
1167
- "version": "1.9.12",
1168
- "resolved": "https://registry.npmjs.org/@unhead/schema/-/schema-1.9.12.tgz",
1169
- "integrity": "sha512-ue2FKyIZKsuZDpWJBMlBGwMm4s+vFeU3NUWsNt8Z+2JkOUIqO/VG43LxNgY1M595bOS71Gdxk+G9VtzfKJ5uEA==",
1170
- "dependencies": {
1171
- "hookable": "^5.5.3",
1172
- "zhead": "^2.2.4"
1173
- },
1174
- "funding": {
1175
- "url": "https://github.com/sponsors/harlan-zw"
1176
- }
1177
- },
1178
- "node_modules/@unhead/shared": {
1179
- "version": "1.9.12",
1180
- "resolved": "https://registry.npmjs.org/@unhead/shared/-/shared-1.9.12.tgz",
1181
- "integrity": "sha512-72wlLXG3FP3sXUrwd42Uv8jYpHSg4R6IFJcsl+QisRjKM89JnjOFSw1DqWO4IOftW5xOxS4J5v7SQyJ4NJo7Bw==",
1182
- "dependencies": {
1183
- "@unhead/schema": "1.9.12"
1184
- },
1185
- "funding": {
1186
- "url": "https://github.com/sponsors/harlan-zw"
1187
- }
1188
- },
1189
- "node_modules/@unhead/vue": {
1190
- "version": "1.9.12",
1191
- "resolved": "https://registry.npmjs.org/@unhead/vue/-/vue-1.9.12.tgz",
1192
- "integrity": "sha512-keE4EuswgzCqVU7zmZprU+ToMvNWc3s8NoLreH5AtJd2u0FgBygD8sxRVyEnZw1KwFYOJ2C7yD2TChSKZioPGQ==",
1193
- "dependencies": {
1194
- "@unhead/schema": "1.9.12",
1195
- "@unhead/shared": "1.9.12",
1196
- "hookable": "^5.5.3",
1197
- "unhead": "1.9.12"
1198
- },
1199
- "funding": {
1200
- "url": "https://github.com/sponsors/harlan-zw"
1201
- },
1202
- "peerDependencies": {
1203
- "vue": ">=2.7 || >=3"
1204
- }
1205
- },
1206
1144
  "node_modules/@vitejs/plugin-vue": {
1207
1145
  "version": "5.0.4",
1208
1146
  "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.0.4.tgz",
@@ -1392,89 +1330,6 @@
1392
1330
  "integrity": "sha512-VcZK7MvpjuTPx2w6blwnwZAu5/LgBUtejFOi3pPGQFXQN5Ela03FUtd2Qtg4yWGGissVL0dr6Ro1LfOFh+PCuQ==",
1393
1331
  "dev": true
1394
1332
  },
1395
- "node_modules/@vueuse/core": {
1396
- "version": "10.10.0",
1397
- "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.10.0.tgz",
1398
- "integrity": "sha512-vexJ/YXYs2S42B783rI95lMt3GzEwkxzC8Hb0Ndpd8rD+p+Lk/Za4bd797Ym7yq4jXqdSyj3JLChunF/vyYjUw==",
1399
- "dependencies": {
1400
- "@types/web-bluetooth": "^0.0.20",
1401
- "@vueuse/metadata": "10.10.0",
1402
- "@vueuse/shared": "10.10.0",
1403
- "vue-demi": ">=0.14.7"
1404
- },
1405
- "funding": {
1406
- "url": "https://github.com/sponsors/antfu"
1407
- }
1408
- },
1409
- "node_modules/@vueuse/core/node_modules/vue-demi": {
1410
- "version": "0.14.8",
1411
- "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.8.tgz",
1412
- "integrity": "sha512-Uuqnk9YE9SsWeReYqK2alDI5YzciATE0r2SkA6iMAtuXvNTMNACJLJEXNXaEy94ECuBe4Sk6RzRU80kjdbIo1Q==",
1413
- "hasInstallScript": true,
1414
- "bin": {
1415
- "vue-demi-fix": "bin/vue-demi-fix.js",
1416
- "vue-demi-switch": "bin/vue-demi-switch.js"
1417
- },
1418
- "engines": {
1419
- "node": ">=12"
1420
- },
1421
- "funding": {
1422
- "url": "https://github.com/sponsors/antfu"
1423
- },
1424
- "peerDependencies": {
1425
- "@vue/composition-api": "^1.0.0-rc.1",
1426
- "vue": "^3.0.0-0 || ^2.6.0"
1427
- },
1428
- "peerDependenciesMeta": {
1429
- "@vue/composition-api": {
1430
- "optional": true
1431
- }
1432
- }
1433
- },
1434
- "node_modules/@vueuse/metadata": {
1435
- "version": "10.10.0",
1436
- "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.10.0.tgz",
1437
- "integrity": "sha512-UNAo2sTCAW5ge6OErPEHb5z7NEAg3XcO9Cj7OK45aZXfLLH1QkexDcZD77HBi5zvEiLOm1An+p/4b5K3Worpug==",
1438
- "funding": {
1439
- "url": "https://github.com/sponsors/antfu"
1440
- }
1441
- },
1442
- "node_modules/@vueuse/shared": {
1443
- "version": "10.10.0",
1444
- "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.10.0.tgz",
1445
- "integrity": "sha512-2aW33Ac0Uk0U+9yo3Ypg9s5KcR42cuehRWl7vnUHadQyFvCktseyxxEPBi1Eiq4D2yBGACOnqLZpx1eMc7g5Og==",
1446
- "dependencies": {
1447
- "vue-demi": ">=0.14.7"
1448
- },
1449
- "funding": {
1450
- "url": "https://github.com/sponsors/antfu"
1451
- }
1452
- },
1453
- "node_modules/@vueuse/shared/node_modules/vue-demi": {
1454
- "version": "0.14.8",
1455
- "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.8.tgz",
1456
- "integrity": "sha512-Uuqnk9YE9SsWeReYqK2alDI5YzciATE0r2SkA6iMAtuXvNTMNACJLJEXNXaEy94ECuBe4Sk6RzRU80kjdbIo1Q==",
1457
- "hasInstallScript": true,
1458
- "bin": {
1459
- "vue-demi-fix": "bin/vue-demi-fix.js",
1460
- "vue-demi-switch": "bin/vue-demi-switch.js"
1461
- },
1462
- "engines": {
1463
- "node": ">=12"
1464
- },
1465
- "funding": {
1466
- "url": "https://github.com/sponsors/antfu"
1467
- },
1468
- "peerDependencies": {
1469
- "@vue/composition-api": "^1.0.0-rc.1",
1470
- "vue": "^3.0.0-0 || ^2.6.0"
1471
- },
1472
- "peerDependenciesMeta": {
1473
- "@vue/composition-api": {
1474
- "optional": true
1475
- }
1476
- }
1477
- },
1478
1333
  "node_modules/acorn": {
1479
1334
  "version": "8.11.3",
1480
1335
  "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
@@ -1861,17 +1716,6 @@
1861
1716
  "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==",
1862
1717
  "dev": true
1863
1718
  },
1864
- "node_modules/debounce": {
1865
- "version": "2.1.0",
1866
- "resolved": "https://registry.npmjs.org/debounce/-/debounce-2.1.0.tgz",
1867
- "integrity": "sha512-OkL3+0pPWCqoBc/nhO9u6TIQNTK44fnBnzuVtJAbp13Naxw9R6u21x+8tVTka87AhDZ3htqZ2pSSsZl9fqL2Wg==",
1868
- "engines": {
1869
- "node": ">=18"
1870
- },
1871
- "funding": {
1872
- "url": "https://github.com/sponsors/sindresorhus"
1873
- }
1874
- },
1875
1719
  "node_modules/debug": {
1876
1720
  "version": "4.3.4",
1877
1721
  "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@@ -2525,11 +2369,6 @@
2525
2369
  "he": "bin/he"
2526
2370
  }
2527
2371
  },
2528
- "node_modules/hookable": {
2529
- "version": "5.5.3",
2530
- "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz",
2531
- "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ=="
2532
- },
2533
2372
  "node_modules/ignore": {
2534
2373
  "version": "5.3.1",
2535
2374
  "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
@@ -3973,20 +3812,6 @@
3973
3812
  "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
3974
3813
  "dev": true
3975
3814
  },
3976
- "node_modules/unhead": {
3977
- "version": "1.9.12",
3978
- "resolved": "https://registry.npmjs.org/unhead/-/unhead-1.9.12.tgz",
3979
- "integrity": "sha512-s6VxcTV45hy8c/IioKQOonFnAO+kBOSpgDfqEHhnU0YVSQYaRPEp9pzW1qSPf0lx+bg9RKeOQyNNbSGGUP26aQ==",
3980
- "dependencies": {
3981
- "@unhead/dom": "1.9.12",
3982
- "@unhead/schema": "1.9.12",
3983
- "@unhead/shared": "1.9.12",
3984
- "hookable": "^5.5.3"
3985
- },
3986
- "funding": {
3987
- "url": "https://github.com/sponsors/harlan-zw"
3988
- }
3989
- },
3990
3815
  "node_modules/update-browserslist-db": {
3991
3816
  "version": "1.0.16",
3992
3817
  "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz",
@@ -4145,11 +3970,6 @@
4145
3970
  "vue": "^3.2.0"
4146
3971
  }
4147
3972
  },
4148
- "node_modules/vue-slider-component": {
4149
- "version": "4.1.0-beta.7",
4150
- "resolved": "https://registry.npmjs.org/vue-slider-component/-/vue-slider-component-4.1.0-beta.7.tgz",
4151
- "integrity": "sha512-Qb7K920ZG7PoQswoF6Ias+i3W2rd3k4fpk04JUl82kEUcN86Yg6et7bVSKWt/7VpQe8a5IT3BqCKSCOZ7AJgCA=="
4152
- },
4153
3973
  "node_modules/vue-template-compiler": {
4154
3974
  "version": "2.7.16",
4155
3975
  "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.16.tgz",
@@ -4333,14 +4153,6 @@
4333
4153
  "funding": {
4334
4154
  "url": "https://github.com/sponsors/sindresorhus"
4335
4155
  }
4336
- },
4337
- "node_modules/zhead": {
4338
- "version": "2.2.4",
4339
- "resolved": "https://registry.npmjs.org/zhead/-/zhead-2.2.4.tgz",
4340
- "integrity": "sha512-8F0OI5dpWIA5IGG5NHUg9staDwz/ZPxZtvGVf01j7vHqSyZ0raHY+78atOVxRqb73AotX22uV1pXt3gYSstGag==",
4341
- "funding": {
4342
- "url": "https://github.com/sponsors/harlan-zw"
4343
- }
4344
4156
  }
4345
4157
  }
4346
4158
  }
@@ -13,17 +13,12 @@
13
13
  },
14
14
  "dependencies": {
15
15
  "@iconify-prerendered/vue-flowbite": "^0.23.1714023977",
16
- "@unhead/vue": "^1.9.12",
17
- "@vueuse/core": "^10.10.0",
18
16
  "dayjs": "^1.11.11",
19
- "debounce": "^2.1.0",
20
17
  "flowbite": "^2.3.0",
21
18
  "flowbite-datepicker": "^1.2.6",
22
19
  "pinia": "^2.1.7",
23
- "unhead": "^1.9.12",
24
20
  "vue": "^3.4.21",
25
- "vue-router": "^4.3.0",
26
- "vue-slider-component": "^4.1.0-beta.7"
21
+ "vue-router": "^4.3.0"
27
22
  },
28
23
  "devDependencies": {
29
24
  "@rushstack/eslint-patch": "^1.8.0",
@@ -109,7 +109,7 @@
109
109
  <td :colspan="resource?.columns.length + 2">
110
110
 
111
111
  <div id="toast-simple"
112
- class=" mx-auto my-5 flex items-center w-full max-w-xs p-4 space-x-4 rtl:space-x-reverse text-gray-500 bg-white divide-x rtl:divide-x-reverse divide-gray-200 dark:text-gray-400 dark:divide-gray-700 space-x dark:bg-gray-800"
112
+ class=" mx-auto my-5 flex items-center w-full max-w-xs p-4 space-x-4 rtl:space-x-reverse text-gray-500 divide-x rtl:divide-x-reverse divide-gray-200 dark:text-gray-400 dark:divide-gray-700 space-x dark:bg-gray-800"
113
113
  role="alert">
114
114
  <IconInboxOutline class="w-6 h-6 text-gray-500 dark:text-gray-400"/>
115
115
  <div class="ps-4 text-sm font-normal">No items here yet</div>
@@ -208,7 +208,7 @@
208
208
  </table>
209
209
  </div>
210
210
  <!-- pagination -->
211
- <div class="flex flex-col items-center mt-4 xs:flex-row xs:justify-between xs:items-center"
211
+ <div class="flex flex-col items-center mt-4 mb-4 xs:flex-row xs:justify-between xs:items-center"
212
212
  v-if="rows && totalRows >= pageSize && totalRows > 0"
213
213
  >
214
214
  <!-- Help text -->