adminforth 2.17.0-next.5 → 2.17.0-next.51

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 (112) hide show
  1. package/commands/callTsProxy.js +2 -1
  2. package/commands/createApp/templates/adminuser.ts.hbs +2 -1
  3. package/commands/createApp/templates/index.ts.hbs +3 -2
  4. package/commands/createCustomComponent/main.js +0 -3
  5. package/commands/createCustomComponent/templates/customCrud/afterBreadcrumbs.vue.hbs +4 -2
  6. package/commands/createCustomComponent/templates/customCrud/beforeActionButtons.vue.hbs +3 -2
  7. package/commands/createCustomComponent/templates/customCrud/beforeBreadcrumbs.vue.hbs +4 -2
  8. package/commands/createCustomComponent/templates/customCrud/bottom.vue.hbs +4 -2
  9. package/commands/createCustomComponent/templates/customCrud/threeDotsDropdownItems.vue.hbs +4 -2
  10. package/commands/createPlugin/templates/index.ts.hbs +4 -0
  11. package/dist/auth.d.ts +2 -2
  12. package/dist/auth.d.ts.map +1 -1
  13. package/dist/auth.js +17 -10
  14. package/dist/auth.js.map +1 -1
  15. package/dist/basePlugin.d.ts +1 -0
  16. package/dist/basePlugin.d.ts.map +1 -1
  17. package/dist/basePlugin.js +4 -2
  18. package/dist/basePlugin.js.map +1 -1
  19. package/dist/dataConnectors/baseConnector.d.ts +1 -0
  20. package/dist/dataConnectors/baseConnector.d.ts.map +1 -1
  21. package/dist/dataConnectors/baseConnector.js +100 -14
  22. package/dist/dataConnectors/baseConnector.js.map +1 -1
  23. package/dist/dataConnectors/clickhouse.d.ts +2 -0
  24. package/dist/dataConnectors/clickhouse.d.ts.map +1 -1
  25. package/dist/dataConnectors/clickhouse.js +15 -4
  26. package/dist/dataConnectors/clickhouse.js.map +1 -1
  27. package/dist/dataConnectors/mongo.d.ts +8 -1
  28. package/dist/dataConnectors/mongo.d.ts.map +1 -1
  29. package/dist/dataConnectors/mongo.js +72 -28
  30. package/dist/dataConnectors/mongo.js.map +1 -1
  31. package/dist/dataConnectors/mysql.d.ts +2 -0
  32. package/dist/dataConnectors/mysql.d.ts.map +1 -1
  33. package/dist/dataConnectors/mysql.js +22 -23
  34. package/dist/dataConnectors/mysql.js.map +1 -1
  35. package/dist/dataConnectors/postgres.d.ts +2 -0
  36. package/dist/dataConnectors/postgres.d.ts.map +1 -1
  37. package/dist/dataConnectors/postgres.js +23 -26
  38. package/dist/dataConnectors/postgres.js.map +1 -1
  39. package/dist/dataConnectors/sqlite.d.ts +2 -0
  40. package/dist/dataConnectors/sqlite.d.ts.map +1 -1
  41. package/dist/dataConnectors/sqlite.js +19 -19
  42. package/dist/dataConnectors/sqlite.js.map +1 -1
  43. package/dist/index.d.ts +10 -4
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +60 -54
  46. package/dist/index.js.map +1 -1
  47. package/dist/modules/codeInjector.d.ts.map +1 -1
  48. package/dist/modules/codeInjector.js +45 -63
  49. package/dist/modules/codeInjector.js.map +1 -1
  50. package/dist/modules/configValidator.d.ts.map +1 -1
  51. package/dist/modules/configValidator.js +14 -9
  52. package/dist/modules/configValidator.js.map +1 -1
  53. package/dist/modules/logger.d.ts +5 -0
  54. package/dist/modules/logger.d.ts.map +1 -0
  55. package/dist/modules/logger.js +16 -0
  56. package/dist/modules/logger.js.map +1 -0
  57. package/dist/modules/restApi.d.ts.map +1 -1
  58. package/dist/modules/restApi.js +21 -23
  59. package/dist/modules/restApi.js.map +1 -1
  60. package/dist/modules/socketBroker.d.ts.map +1 -1
  61. package/dist/modules/socketBroker.js +6 -5
  62. package/dist/modules/socketBroker.js.map +1 -1
  63. package/dist/modules/styles.js +1 -1
  64. package/dist/servers/express.d.ts.map +1 -1
  65. package/dist/servers/express.js +11 -11
  66. package/dist/servers/express.js.map +1 -1
  67. package/dist/spa/package-lock.json +0 -13
  68. package/dist/spa/package.json +0 -1
  69. package/dist/spa/src/App.vue +6 -3
  70. package/dist/spa/src/adminforth.ts +60 -1
  71. package/dist/spa/src/afcl/DatePicker.vue +0 -1
  72. package/dist/spa/src/afcl/Dropzone.vue +6 -4
  73. package/dist/spa/src/afcl/Tooltip.vue +38 -4
  74. package/dist/spa/src/components/ColumnValueInput.vue +14 -1
  75. package/dist/spa/src/components/CustomDateRangePicker.vue +0 -2
  76. package/dist/spa/src/components/CustomRangePicker.vue +9 -6
  77. package/dist/spa/src/components/Filters.vue +4 -4
  78. package/dist/spa/src/components/ListActionsThreeDots.vue +235 -0
  79. package/dist/spa/src/components/ResourceForm.vue +4 -4
  80. package/dist/spa/src/components/ResourceListTable.vue +30 -16
  81. package/dist/spa/src/components/ResourceListTableVirtual.vue +34 -18
  82. package/dist/spa/src/components/Sidebar.vue +4 -2
  83. package/dist/spa/src/components/ThreeDotsMenu.vue +35 -20
  84. package/dist/spa/src/composables/useFrontendApi.ts +8 -4
  85. package/dist/spa/src/renderers/CompactField.vue +3 -2
  86. package/dist/spa/src/renderers/CompactUUID.vue +3 -2
  87. package/dist/spa/src/renderers/RichText.vue +15 -0
  88. package/dist/spa/src/stores/core.ts +3 -2
  89. package/dist/spa/src/stores/filters.ts +1 -1
  90. package/dist/spa/src/stores/toast.ts +1 -2
  91. package/dist/spa/src/types/Back.ts +35 -12
  92. package/dist/spa/src/types/Common.ts +7 -14
  93. package/dist/spa/src/types/FrontendAPI.ts +25 -10
  94. package/dist/spa/src/utils.ts +1 -1
  95. package/dist/spa/src/views/CreateView.vue +23 -31
  96. package/dist/spa/src/views/EditView.vue +27 -31
  97. package/dist/spa/src/views/ListView.vue +20 -10
  98. package/dist/spa/src/views/SettingsView.vue +3 -2
  99. package/dist/spa/src/views/ShowView.vue +7 -6
  100. package/dist/types/Back.d.ts +28 -6
  101. package/dist/types/Back.d.ts.map +1 -1
  102. package/dist/types/Back.js +6 -0
  103. package/dist/types/Back.js.map +1 -1
  104. package/dist/types/Common.d.ts +8 -15
  105. package/dist/types/Common.d.ts.map +1 -1
  106. package/dist/types/Common.js +2 -0
  107. package/dist/types/Common.js.map +1 -1
  108. package/dist/types/FrontendAPI.d.ts +32 -10
  109. package/dist/types/FrontendAPI.d.ts.map +1 -1
  110. package/dist/types/FrontendAPI.js.map +1 -1
  111. package/package.json +4 -1
  112. package/commands/createCustomComponent/templates/customCrud/saveButton.vue.hbs +0 -28
@@ -119,8 +119,8 @@
119
119
  />
120
120
  </td>
121
121
  <td class=" items-center px-2 md:px-3 lg:px-6 py-4 cursor-default" @click="(e)=>{e.stopPropagation()}">
122
- <div class="flex text-lightPrimary dark:text-darkPrimary items-center">
123
- <Tooltip>
122
+ <div class="flex text-lightPrimary dark:text-darkPrimary items-center gap-2">
123
+ <Tooltip v-if="resource.options?.baseActionsAsQuickIcons && resource.options?.baseActionsAsQuickIcons.includes('show')">
124
124
  <RouterLink
125
125
  v-if="resource.options?.allowedActions?.show"
126
126
  :to="{
@@ -139,8 +139,7 @@
139
139
  {{ $t('Show item') }}
140
140
  </template>
141
141
  </Tooltip>
142
-
143
- <Tooltip>
142
+ <Tooltip v-if="resource.options?.baseActionsAsQuickIcons && resource.options?.baseActionsAsQuickIcons.includes('edit')" >
144
143
  <RouterLink
145
144
  v-if="resource.options?.allowedActions?.edit"
146
145
  :to="{
@@ -157,8 +156,7 @@
157
156
  {{ $t('Edit item') }}
158
157
  </template>
159
158
  </Tooltip>
160
-
161
- <Tooltip>
159
+ <Tooltip v-if="resource.options?.baseActionsAsQuickIcons && resource.options?.baseActionsAsQuickIcons.includes('delete')">
162
160
  <button
163
161
  v-if="resource.options?.allowedActions?.delete"
164
162
  @click="deleteRecord(row)"
@@ -170,7 +168,6 @@
170
168
  {{ $t('Delete item') }}
171
169
  </template>
172
170
  </Tooltip>
173
-
174
171
  <template v-if="customActionsInjection">
175
172
  <component
176
173
  v-for="c in customActionsInjection"
@@ -185,7 +182,7 @@
185
182
 
186
183
  <template v-if="resource.options?.actions">
187
184
  <Tooltip
188
- v-for="action in resource.options.actions.filter(a => a.showIn?.list)"
185
+ v-for="action in resource.options.actions.filter(a => a.showIn?.list || a.showIn?.listQuickIcon)"
189
186
  :key="action.id"
190
187
  >
191
188
  <component
@@ -198,12 +195,13 @@
198
195
  >
199
196
  <button
200
197
  type="button"
198
+ class="border border-gray-300 dark:border-gray-700 dark:border-opacity-0 border-opacity-0 hover:border-opacity-100 dark:hover:border-opacity-100 rounded-md hover:bg-gray-100 dark:hover:bg-gray-800 cursor-pointer"
201
199
  :disabled="rowActionLoadingStates?.[action.id]"
202
200
  >
203
201
  <component
204
202
  v-if="action.icon"
205
203
  :is="getIcon(action.icon)"
206
- class="w-5 h-5 mr-2 text-lightPrimary dark:text-darkPrimary"
204
+ class="w-6 h-6 text-lightPrimary dark:text-darkPrimary"
207
205
  />
208
206
  </button>
209
207
  </component>
@@ -213,6 +211,16 @@
213
211
  </template>
214
212
  </Tooltip>
215
213
  </template>
214
+ <ListActionsThreeDots
215
+ v-if="showListActionsThreeDots"
216
+ :resourceOptions="resource?.options"
217
+ :record="row"
218
+ :updateRecords="()=>emits('update:records', true)"
219
+ :deleteRecord="deleteRecord"
220
+ :resourceId="resource.resourceId"
221
+ :startCustomAction="startCustomAction"
222
+ :customActionIconsThreeDotsMenuItems="customActionIconsThreeDotsMenuItems"
223
+ />
216
224
  </div>
217
225
 
218
226
  </td>
@@ -323,24 +331,23 @@ import { useCoreStore } from '@/stores/core';
323
331
  import { showSuccesTost, showErrorTost } from '@/composables/useFrontendApi';
324
332
  import SkeleteLoader from '@/components/SkeleteLoader.vue';
325
333
  import { getIcon } from '@/utils';
326
- import {
327
- IconInboxOutline,
328
- } from '@iconify-prerendered/vue-flowbite';
329
-
330
334
  import {
331
335
  IconEyeSolid,
332
336
  IconPenSolid,
333
337
  IconTrashBinSolid,
338
+ IconInboxOutline
334
339
  } from '@iconify-prerendered/vue-flowbite';
335
340
  import router from '@/router';
336
341
  import { Tooltip } from '@/afcl';
337
342
  import type { AdminForthResourceCommon, AdminForthResourceColumnInputCommon, AdminForthResourceColumnCommon, AdminForthComponentDeclaration } from '@/types/Common';
338
- import adminforth from '@/adminforth';
343
+ import { useAdminforth } from '@/adminforth';
339
344
  import Checkbox from '@/afcl/Checkbox.vue';
345
+ import ListActionsThreeDots from '@/components/ListActionsThreeDots.vue';
340
346
  import CallActionWrapper from '@/components/CallActionWrapper.vue'
341
347
 
342
348
  const coreStore = useCoreStore();
343
349
  const { t } = useI18n();
350
+ const { alert, confirm } = useAdminforth();
344
351
  const props = defineProps<{
345
352
  page: number,
346
353
  resource: AdminForthResourceCommon | null,
@@ -352,6 +359,7 @@ const props = defineProps<{
352
359
  noRoundings?: boolean,
353
360
  customActionsInjection?: any[],
354
361
  tableBodyStartInjection?: any[],
362
+ customActionIconsThreeDotsMenuItems?: any[]
355
363
  tableRowReplaceInjection?: AdminForthComponentDeclaration,
356
364
  }>();
357
365
 
@@ -369,6 +377,12 @@ const pageInput = ref('1');
369
377
  const page = ref(1);
370
378
  const sort: Ref<Array<{field: string, direction: string}>> = ref([]);
371
379
 
380
+ const showListActionsThreeDots = computed(() => {
381
+ return props.resource?.options?.actions?.some(a => a.showIn?.listThreeDotsMenu) // show if any action is set to show in three dots menu
382
+ || (props.customActionIconsThreeDotsMenuItems && props.customActionIconsThreeDotsMenuItems.length > 0) // or if there are custom action icons for three dots menu
383
+ || !props.resource?.options.baseActionsAsQuickIcons // or if there is no baseActionsAsQuickIcons
384
+ || (props.resource?.options.baseActionsAsQuickIcons && props.resource?.options.baseActionsAsQuickIcons.length < 3) // if there all 3 base actions are shown as quick icons - hide three dots icon
385
+ })
372
386
 
373
387
  const from = computed(() => ((page.value || 1) - 1) * props.pageSize + 1);
374
388
  const to = computed(() => Math.min((page.value || 1) * props.pageSize, props.totalRows));
@@ -530,7 +544,7 @@ async function onClick(e: any, row: any) {
530
544
  }
531
545
 
532
546
  async function deleteRecord(row: any) {
533
- const data = await adminforth.confirm({
547
+ const data = await confirm({
534
548
  message: t('Are you sure you want to delete this item?'),
535
549
  yes: t('Delete'),
536
550
  no: t('Cancel'),
@@ -596,7 +610,7 @@ async function startCustomAction(actionId: string, row: any, extraData: Record<s
596
610
  emits('update:records', true);
597
611
 
598
612
  if (data.successMessage) {
599
- adminforth.alert({
613
+ alert({
600
614
  message: data.successMessage,
601
615
  variant: 'success'
602
616
  });
@@ -129,8 +129,8 @@
129
129
  />
130
130
  </td>
131
131
  <td class=" items-center px-2 md:px-3 lg:px-6 py-4 cursor-default" @click="(e)=>{e.stopPropagation()}">
132
- <div class="flex text-lightPrimary dark:text-darkPrimary items-center">
133
- <Tooltip>
132
+ <div class="flex text-lightPrimary dark:text-darkPrimary items-center gap-2">
133
+ <Tooltip v-if="resource.options?.baseActionsAsQuickIcons && resource.options?.baseActionsAsQuickIcons.includes('show')">
134
134
  <RouterLink
135
135
  v-if="resource.options?.allowedActions?.show"
136
136
  :to="{
@@ -142,15 +142,14 @@
142
142
  }"
143
143
 
144
144
  >
145
- <IconEyeSolid class="w-5 h-5 me-2"/>
145
+ <IconEyeSolid class="af-show-icon w-5 h-5 me-2"/>
146
146
  </RouterLink>
147
147
 
148
148
  <template v-slot:tooltip>
149
149
  {{ $t('Show item') }}
150
150
  </template>
151
151
  </Tooltip>
152
-
153
- <Tooltip>
152
+ <Tooltip v-if="resource.options?.baseActionsAsQuickIcons && resource.options?.baseActionsAsQuickIcons.includes('edit')" >
154
153
  <RouterLink
155
154
  v-if="resource.options?.allowedActions?.edit"
156
155
  :to="{
@@ -161,26 +160,24 @@
161
160
  }
162
161
  }"
163
162
  >
164
- <IconPenSolid class="w-5 h-5 me-2"/>
163
+ <IconPenSolid class="af-edit-icon w-5 h-5 me-2"/>
165
164
  </RouterLink>
166
165
  <template v-slot:tooltip>
167
166
  {{ $t('Edit item') }}
168
167
  </template>
169
168
  </Tooltip>
170
-
171
- <Tooltip>
169
+ <Tooltip v-if="resource.options?.baseActionsAsQuickIcons && resource.options?.baseActionsAsQuickIcons.includes('delete')">
172
170
  <button
173
171
  v-if="resource.options?.allowedActions?.delete"
174
172
  @click="deleteRecord(row)"
175
173
  >
176
- <IconTrashBinSolid class="w-5 h-5 me-2"/>
174
+ <IconTrashBinSolid class="af-delete-icon w-5 h-5 me-2"/>
177
175
  </button>
178
176
 
179
177
  <template v-slot:tooltip>
180
178
  {{ $t('Delete item') }}
181
179
  </template>
182
- </Tooltip>
183
-
180
+ </Tooltip>
184
181
  <template v-if="customActionsInjection">
185
182
  <component
186
183
  v-for="c in customActionsInjection"
@@ -192,10 +189,9 @@
192
189
  :updateRecords="()=>emits('update:records', true)"
193
190
  />
194
191
  </template>
195
-
196
- <template v-if="resource.options?.actions">
192
+ <template v-if="resource.options?.actions">
197
193
  <Tooltip
198
- v-for="action in resource.options.actions.filter(a => a.showIn?.list)"
194
+ v-for="action in resource.options.actions.filter(a => a.showIn?.list || a.showIn?.listQuickIcon)"
199
195
  :key="action.id"
200
196
  >
201
197
  <CallActionWrapper
@@ -212,12 +208,13 @@
212
208
  >
213
209
  <button
214
210
  type="button"
211
+ class="border border-gray-300 dark:border-gray-700 dark:border-opacity-0 border-opacity-0 hover:border-opacity-100 dark:hover:border-opacity-100 rounded-md hover:bg-gray-100 dark:hover:bg-gray-800 cursor-pointer"
215
212
  :disabled="rowActionLoadingStates?.[action.id]"
216
213
  >
217
214
  <component
218
215
  v-if="action.icon"
219
216
  :is="getIcon(action.icon)"
220
- class="w-5 h-5 mr-2 text-lightPrimary dark:text-darkPrimary"
217
+ class="w-6 h-6 text-lightPrimary dark:text-darkPrimary"
221
218
  />
222
219
  </button>
223
220
  </component>
@@ -228,6 +225,16 @@
228
225
  </template>
229
226
  </Tooltip>
230
227
  </template>
228
+ <ListActionsThreeDots
229
+ v-if="showListActionsThreeDots"
230
+ :resourceOptions="resource?.options"
231
+ :record="row"
232
+ :updateRecords="()=>emits('update:records', true)"
233
+ :deleteRecord="deleteRecord"
234
+ :resourceId="resource.resourceId"
235
+ :startCustomAction="startCustomAction"
236
+ :customActionIconsThreeDotsMenuItems="customActionIconsThreeDotsMenuItems"
237
+ />
231
238
  </div>
232
239
  </td>
233
240
  </component>
@@ -357,12 +364,14 @@ import {
357
364
  import router from '@/router';
358
365
  import { Tooltip } from '@/afcl';
359
366
  import type { AdminForthResourceCommon, AdminForthResourceColumnCommon, AdminForthComponentDeclaration } from '@/types/Common';
360
- import adminforth from '@/adminforth';
367
+ import { useAdminforth } from '@/adminforth';
361
368
  import Checkbox from '@/afcl/Checkbox.vue';
369
+ import ListActionsThreeDots from '@/components/ListActionsThreeDots.vue';
362
370
  import CallActionWrapper from '@/components/CallActionWrapper.vue'
363
371
 
364
372
  const coreStore = useCoreStore();
365
373
  const { t } = useI18n();
374
+ const { alert, confirm } = useAdminforth();
366
375
  const props = defineProps<{
367
376
  page: number,
368
377
  resource: AdminForthResourceCommon | null,
@@ -377,6 +386,7 @@ const props = defineProps<{
377
386
  containerHeight?: number,
378
387
  itemHeight?: number,
379
388
  bufferSize?: number,
389
+ customActionIconsThreeDotsMenuItems?: any[]
380
390
  tableRowReplaceInjection?: AdminForthComponentDeclaration
381
391
  }>();
382
392
 
@@ -394,6 +404,12 @@ const pageInput = ref('1');
394
404
  const page = ref(1);
395
405
  const sort: Ref<Array<{field: string, direction: string}>> = ref([]);
396
406
 
407
+ const showListActionsThreeDots = computed(() => {
408
+ return props.resource?.options?.actions?.some(a => a.showIn?.listThreeDotsMenu) // show if any action is set to show in three dots menu
409
+ || (props.customActionIconsThreeDotsMenuItems && props.customActionIconsThreeDotsMenuItems.length > 0) // or if there are custom action icons for three dots menu
410
+ || !props.resource?.options.baseActionsAsQuickIcons // or if there is no baseActionsAsQuickIcons
411
+ || (props.resource?.options.baseActionsAsQuickIcons && props.resource?.options.baseActionsAsQuickIcons.length < 3) // if there all 3 base actions are shown as quick icons - hide three dots icon
412
+ })
397
413
 
398
414
  const from = computed(() => ((page.value || 1) - 1) * props.pageSize + 1);
399
415
  const to = computed(() => Math.min((page.value || 1) * props.pageSize, props.totalRows));
@@ -555,7 +571,7 @@ async function onClick(e: any,row: any) {
555
571
  }
556
572
 
557
573
  async function deleteRecord(row: any) {
558
- const data = await adminforth.confirm({
574
+ const data = await confirm({
559
575
  message: t('Are you sure you want to delete this item?'),
560
576
  yes: t('Delete'),
561
577
  no: t('Cancel'),
@@ -620,7 +636,7 @@ async function startCustomAction(actionId: string, row: any, extraData: Record<s
620
636
  emits('update:records', true);
621
637
 
622
638
  if (data.successMessage) {
623
- adminforth.alert({
639
+ alert({
624
640
  message: data.successMessage,
625
641
  variant: 'success'
626
642
  });
@@ -299,7 +299,9 @@ import { IconCloseSidebarSolid, IconOpenSidebarSolid } from '@iconify-prerendere
299
299
  import { getIcon, verySimpleHash, loadFile, getCustomComponent } from '@/utils';
300
300
  import { Tooltip } from '@/afcl';
301
301
  import type { AnnouncementBadgeResponse } from '@/types/Common';
302
- import adminforth from '@/adminforth';
302
+ import { useAdminforth } from '@/adminforth';
303
+
304
+ const { menu } = useAdminforth();
303
305
 
304
306
  interface Props {
305
307
  sideBarOpen: boolean;
@@ -424,7 +426,7 @@ function closeCTA() {
424
426
  nextTick( async() => {
425
427
  emit('loadMenu');
426
428
  await coreStore.fetchMenuBadges();
427
- adminforth.menu.refreshMenuBadges();
429
+ menu.refreshMenuBadges();
428
430
  })
429
431
  }
430
432
 
@@ -13,27 +13,35 @@
13
13
  <!-- Dropdown menu -->
14
14
  <div
15
15
  ref="dropdownRef"
16
- :class="{'hidden': !showDropdown, 'block': showDropdown }"
17
- class="absolute z-30 right-0 mt-3 bg-lightThreeDotsMenuBodyBackground divide-y divide-gray-100 rounded-lg shadow w-44 dark:bg-darkThreeDotsMenuBodyBackground dark:divide-gray-600">
16
+ :class="{
17
+ 'block': showDropdown,
18
+ 'hidden': !showDropdown,
19
+ 'left-0 md:left-auto': checkboxes && checkboxes.length > 0
20
+ }"
21
+ class="absolute z-30 mt-3 bg-lightThreeDotsMenuBodyBackground divide-y divide-gray-100 rounded-lg shadow w-44 dark:bg-darkThreeDotsMenuBodyBackground dark:divide-gray-600 right-0">
18
22
  <ul class="py-2 text-sm text-lightThreeDotsMenuBodyText dark:text-darkThreeDotsMenuBodyText" aria-labelledby="dropdownMenuIconButton">
19
23
  <li v-for="(item, i) in threeDotsDropdownItems" :key="`dropdown-item-${i}`">
20
- <a href="#"
21
- class="block px-4 py-2 hover:bg-lightThreeDotsMenuBodyBackgroundHover hover:text-lightThreeDotsMenuBodyTextHover dark:hover:bg-darkThreeDotsMenuBodyBackgroundHover dark:hover:text-darkThreeDotsMenuBodyTextHover"
24
+ <div
25
+ class="block hover:bg-lightThreeDotsMenuBodyBackgroundHover hover:text-lightThreeDotsMenuBodyTextHover dark:hover:bg-darkThreeDotsMenuBodyBackgroundHover dark:hover:text-darkThreeDotsMenuBodyTextHover"
22
26
  :class="{
23
27
  'pointer-events-none': checkboxes && checkboxes.length === 0 && item.meta?.disabledWhenNoCheckboxes,
24
28
  'opacity-50': checkboxes && checkboxes.length === 0 && item.meta?.disabledWhenNoCheckboxes,
25
29
  'cursor-not-allowed': checkboxes && checkboxes.length === 0 && item.meta?.disabledWhenNoCheckboxes,
26
30
  }"
27
- @click="injectedComponentClick(i)">
28
- <component :ref="(el: any) => setComponentRef(el, i)" :is="getCustomComponent(item)"
29
- :meta="item.meta"
30
- :resource="coreStore.resource"
31
- :adminUser="coreStore.adminUser"
32
- :checkboxes="checkboxes"
33
- :updateList="props.updateList"
34
- :clearCheckboxes="clearCheckboxes"
35
- />
36
- </a>
31
+ @click="injectedComponentClick(i)"
32
+ >
33
+ <div class="wrapper">
34
+ <component
35
+ :ref="(el: any) => setComponentRef(el, i)" :is="getCustomComponent(item)"
36
+ :meta="item.meta"
37
+ :resource="coreStore.resource"
38
+ :adminUser="coreStore.adminUser"
39
+ :checkboxes="checkboxes"
40
+ :updateList="props.updateList"
41
+ :clearCheckboxes="clearCheckboxes"
42
+ />
43
+ </div>
44
+ </div>
37
45
  </li>
38
46
  <li v-for="action in customActions" :key="action.id">
39
47
  <component
@@ -80,7 +88,7 @@
80
88
  <script setup lang="ts">
81
89
  import { getCustomComponent, getIcon } from '@/utils';
82
90
  import { useCoreStore } from '@/stores/core';
83
- import adminforth from '@/adminforth';
91
+ import { useAdminforth } from '@/adminforth';
84
92
  import { callAdminForthApi } from '@/utils';
85
93
  import { useRoute, useRouter } from 'vue-router';
86
94
  import CallActionWrapper from '@/components/CallActionWrapper.vue'
@@ -88,7 +96,7 @@ import { ref, type ComponentPublicInstance, onMounted, onUnmounted } from 'vue';
88
96
  import type { AdminForthBulkActionCommon, AdminForthComponentDeclarationFull } from '@/types/Common';
89
97
  import type { AdminForthActionInput } from '@/types/Back';
90
98
 
91
-
99
+ const { list, alert} = useAdminforth();
92
100
  const route = useRoute();
93
101
  const coreStore = useCoreStore();
94
102
  const router = useRouter();
@@ -119,7 +127,7 @@ function setComponentRef(el: ComponentPublicInstance | null, index: number) {
119
127
  }
120
128
 
121
129
  async function handleActionClick(action: AdminForthActionInput, payload: any) {
122
- adminforth.list.closeThreeDotsDropdown();
130
+ list.closeThreeDotsDropdown();
123
131
 
124
132
  const actionId = action.id;
125
133
  const data = await callAdminForthApi({
@@ -156,7 +164,7 @@ async function handleActionClick(action: AdminForthActionInput, payload: any) {
156
164
  });
157
165
 
158
166
  if (data.successMessage) {
159
- adminforth.alert({
167
+ alert({
160
168
  message: data.successMessage,
161
169
  variant: 'success'
162
170
  });
@@ -164,7 +172,7 @@ async function handleActionClick(action: AdminForthActionInput, payload: any) {
164
172
  }
165
173
 
166
174
  if (data?.error) {
167
- adminforth.alert({
175
+ alert({
168
176
  message: data.error,
169
177
  variant: 'danger'
170
178
  });
@@ -172,7 +180,7 @@ async function handleActionClick(action: AdminForthActionInput, payload: any) {
172
180
  }
173
181
 
174
182
  function startBulkAction(actionId: string) {
175
- adminforth.list.closeThreeDotsDropdown();
183
+ list.closeThreeDotsDropdown();
176
184
  emit('startBulkAction', actionId);
177
185
  showDropdown.value = false;
178
186
  }
@@ -206,3 +214,10 @@ onUnmounted(() => {
206
214
  })
207
215
 
208
216
  </script>
217
+
218
+ <style lang="scss" scoped>
219
+ .wrapper > * {
220
+ @apply px-4 py-2;
221
+ }
222
+ </style>
223
+
@@ -1,17 +1,21 @@
1
- import adminforth from '@/adminforth';
1
+ import { useAdminforth } from '@/adminforth';
2
+
2
3
 
3
4
  export function showSuccesTost(message: string) {
4
- adminforth.alert({ message, variant: 'success' });
5
+ const { alert } = useAdminforth();
6
+ alert({ message, variant: 'success' });
5
7
  return message;
6
8
  }
7
9
 
8
10
  export function showWarningTost(message: string) {
9
- adminforth.alert({ message, variant: 'warning' });
11
+ const { alert } = useAdminforth();
12
+ alert({ message, variant: 'warning' });
10
13
  return message;
11
14
  }
12
15
 
13
16
  export function showErrorTost(message: string, timeout?: number) {
14
- adminforth.alert({ message, variant: 'danger', timeout: timeout || 30});
17
+ const { alert } = useAdminforth();
18
+ alert({ message, variant: 'danger', timeout: timeout || 30});
15
19
  return message;
16
20
  }
17
21
 
@@ -15,10 +15,11 @@
15
15
  import { computed, ref, onMounted, nextTick } from 'vue';
16
16
  import { IconFileCopyAltSolid } from '@iconify-prerendered/vue-flowbite';
17
17
  import Tooltip from '@/afcl/Tooltip.vue';
18
- import adminforth from '@/adminforth';
18
+ import { useAdminforth } from '@/adminforth';
19
19
  import { useI18n } from 'vue-i18n';
20
20
 
21
21
  const { t } = useI18n();
22
+ const { alert } = useAdminforth();
22
23
  const visualValue = computed(() => {
23
24
  // if lenght is more then 8, show only first 4 and last 4 characters, ... in the middle
24
25
  const val = props.record[props.column.name];
@@ -34,7 +35,7 @@ const id = ref();
34
35
 
35
36
  function copyToCB() {
36
37
  navigator.clipboard.writeText(props.record[props.column.name]);
37
- adminforth.alert({
38
+ alert({
38
39
  message: t('ID copied to clipboard'),
39
40
  variant: 'success',
40
41
  })
@@ -15,10 +15,11 @@
15
15
  import { computed, ref, onMounted, nextTick } from 'vue';
16
16
  import { IconFileCopyAltSolid } from '@iconify-prerendered/vue-flowbite';
17
17
  import Tooltip from '@/afcl/Tooltip.vue';
18
- import adminforth from '@/adminforth';
18
+ import { useAdminforth } from '@/adminforth';
19
19
  import { useI18n } from 'vue-i18n';
20
20
 
21
21
  const { t } = useI18n();
22
+ const { alert } = useAdminforth();
22
23
  const visualValue = computed(() => {
23
24
  // if lenght is more then 8, show only first 4 and last 4 characters, ... in the middle
24
25
  const val = props.record[props.column.name];
@@ -34,7 +35,7 @@ const id = ref();
34
35
 
35
36
  function copyToCB() {
36
37
  navigator.clipboard.writeText(props.record[props.column.name]);
37
- adminforth.alert({
38
+ alert({
38
39
  message: t('ID copied to clipboard'),
39
40
  variant: 'success',
40
41
  })
@@ -22,4 +22,19 @@ const htmlContent = protectAgainstXSS(props.record[props.column.name])
22
22
  /* You can add default styles here if needed */
23
23
  word-break: break-word;
24
24
  }
25
+ .rich-text :deep(table) {
26
+ border-collapse: collapse;
27
+ border: 1px solid #ddd;
28
+ }
29
+
30
+ .rich-text :deep(table th),
31
+ .rich-text :deep(table td) {
32
+ border: 1px solid #ddd;
33
+ padding: 8px;
34
+ }
35
+
36
+ .rich-text :deep(table th) {
37
+ background-color: #f5f5f5;
38
+ font-weight: 600;
39
+ }
25
40
  </style>
@@ -2,12 +2,13 @@ import { ref, computed } from 'vue'
2
2
  import { defineStore } from 'pinia'
3
3
  import { callAdminForthApi } from '@/utils';
4
4
  import websocket from '@/websocket';
5
- import adminforth from '@/adminforth';
5
+ import { useAdminforth } from '@/adminforth';
6
6
 
7
7
  import type { AdminForthResourceCommon, AdminForthResourceColumnCommon, GetBaseConfigResponse, ResourceVeryShort, AdminUser, UserData, AdminForthConfigMenuItem, AdminForthConfigForFrontend } from '@/types/Common';
8
8
  import type { Ref } from 'vue'
9
9
 
10
10
  export const useCoreStore = defineStore('core', () => {
11
+ const { alert } = useAdminforth();
11
12
  const resourceById: Ref<Record<string, ResourceVeryShort>> = ref({});
12
13
  const theme: Ref<'light'| 'dark'> = ref(window.localStorage.getItem('af__theme') as ('light'|'dark') || 'light');
13
14
 
@@ -157,7 +158,7 @@ export const useCoreStore = defineStore('core', () => {
157
158
  });
158
159
 
159
160
  if (respData.error) {
160
- adminforth.alert({
161
+ alert({
161
162
  message: respData.error,
162
163
  variant: 'danger',
163
164
  timeout: 30,
@@ -15,7 +15,7 @@ export const useFiltersStore = defineStore('filters', () => {
15
15
  }
16
16
  const setFilter = (filter: any) => {
17
17
  const index = filters.value.findIndex(f => f.field === filter.field);
18
- if (filters.value[index]) {
18
+ if (filters.value[index] && filters.value[index].operator === filter.value.operator) {
19
19
  filters.value[index] = filter;
20
20
  return;
21
21
  }
@@ -1,6 +1,5 @@
1
1
  import { ref, watch, type Ref } from 'vue'
2
2
  import { defineStore } from 'pinia'
3
- import { v1 as uuid } from 'uuid';
4
3
  import { useRoute } from 'vue-router';
5
4
 
6
5
 
@@ -23,7 +22,7 @@ export const useToastStore = defineStore('toast', () => {
23
22
  buttons?: { value: any; label: string }[];
24
23
  onResolve?: (value?: any) => void;
25
24
  }): string => {
26
- const toastId = uuid();
25
+ const toastId = crypto.randomUUID();
27
26
  toasts.value.push({
28
27
  ...toast,
29
28
  id: toastId,