adminforth 1.2.87 → 1.2.89

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 (101) hide show
  1. package/dist/modules/restApi.js +9 -0
  2. package/dist/spa/.vscode/extensions.json +6 -0
  3. package/dist/spa/index.html +4 -4
  4. package/dist/spa/package-lock.json +6 -421
  5. package/dist/spa/package.json +2 -10
  6. package/dist/spa/public/favicon.ico +0 -0
  7. package/dist/spa/spa/.eslintrc.cjs +14 -0
  8. package/dist/spa/spa/.vscode/extensions.json +6 -0
  9. package/dist/spa/spa/README.md +39 -0
  10. package/dist/spa/spa/env.d.ts +1 -0
  11. package/dist/spa/spa/index.html +23 -0
  12. package/dist/spa/spa/package-lock.json +4573 -0
  13. package/dist/spa/spa/package.json +49 -0
  14. package/dist/spa/spa/postcss.config.js +6 -0
  15. package/dist/spa/spa/public/favicon.ico +0 -0
  16. package/dist/spa/spa/src/App.vue +314 -0
  17. package/dist/spa/spa/src/assets/base.css +0 -0
  18. package/dist/spa/spa/src/assets/logo.svg +19 -0
  19. package/dist/spa/spa/src/components/AcceptModal.vue +45 -0
  20. package/dist/spa/spa/src/components/Breadcrumbs.vue +40 -0
  21. package/dist/spa/spa/src/components/BreadcrumbsWithButtons.vue +26 -0
  22. package/dist/spa/spa/src/components/CustomDatePicker.vue +174 -0
  23. package/dist/spa/spa/src/components/CustomDateRangePicker.vue +218 -0
  24. package/dist/spa/spa/src/components/Dropdown.vue +168 -0
  25. package/dist/spa/spa/src/components/Filters.vue +222 -0
  26. package/dist/spa/spa/src/components/HelloWorld.vue +17 -0
  27. package/dist/spa/spa/src/components/MenuLink.vue +24 -0
  28. package/dist/spa/spa/src/components/ResourceForm.vue +289 -0
  29. package/dist/spa/{src → spa/src}/components/ResourceListTable.vue +3 -6
  30. package/dist/spa/spa/src/components/SingleSkeletLoader.vue +13 -0
  31. package/dist/spa/{src → spa/src}/components/Toast.vue +3 -9
  32. package/dist/spa/spa/src/components/ValueRenderer.vue +66 -0
  33. package/dist/spa/spa/src/components/icons/IconCalendar.vue +5 -0
  34. package/dist/spa/spa/src/components/icons/IconCommunity.vue +7 -0
  35. package/dist/spa/spa/src/components/icons/IconDocumentation.vue +7 -0
  36. package/dist/spa/spa/src/components/icons/IconEcosystem.vue +7 -0
  37. package/dist/spa/spa/src/components/icons/IconSupport.vue +7 -0
  38. package/dist/spa/spa/src/components/icons/IconTime.vue +5 -0
  39. package/dist/spa/spa/src/components/icons/IconTooling.vue +19 -0
  40. package/dist/spa/spa/src/index.scss +27 -0
  41. package/dist/spa/spa/src/main.ts +18 -0
  42. package/dist/spa/spa/src/router/index.ts +63 -0
  43. package/dist/spa/spa/src/stores/core.ts +144 -0
  44. package/dist/spa/spa/src/stores/modal.ts +48 -0
  45. package/dist/spa/spa/src/utils.ts +103 -0
  46. package/dist/spa/spa/src/views/CreateView.vue +156 -0
  47. package/dist/spa/spa/src/views/EditView.vue +157 -0
  48. package/dist/spa/spa/src/views/HomeView.vue +8 -0
  49. package/dist/spa/spa/src/views/ListView.vue +258 -0
  50. package/dist/spa/spa/src/views/LoginView.vue +143 -0
  51. package/dist/spa/spa/src/views/ResourceParent.vue +17 -0
  52. package/dist/spa/spa/src/views/ShowView.vue +184 -0
  53. package/dist/spa/spa/tailwind.config.js +17 -0
  54. package/dist/spa/spa/tsconfig.app.json +14 -0
  55. package/dist/spa/spa/tsconfig.json +11 -0
  56. package/dist/spa/spa/tsconfig.node.json +19 -0
  57. package/dist/spa/spa/vite.config.ts +56 -0
  58. package/dist/spa/src/App.vue +94 -236
  59. package/dist/spa/src/assets/base.css +0 -2
  60. package/dist/spa/src/assets/logo.svg +1 -19
  61. package/dist/spa/src/components/AcceptModal.vue +10 -3
  62. package/dist/spa/src/components/Breadcrumbs.vue +2 -3
  63. package/dist/spa/src/components/BreadcrumbsWithButtons.vue +1 -1
  64. package/dist/spa/src/components/CustomDatePicker.vue +10 -25
  65. package/dist/spa/src/components/CustomDateRangePicker.vue +5 -14
  66. package/dist/spa/src/components/Dropdown.vue +5 -19
  67. package/dist/spa/src/components/Filters.vue +38 -103
  68. package/dist/spa/src/components/MenuLink.vue +3 -3
  69. package/dist/spa/src/components/ResourceForm.vue +116 -205
  70. package/dist/spa/src/components/ValueRenderer.vue +8 -30
  71. package/dist/spa/src/index.scss +1 -2
  72. package/dist/spa/src/main.ts +2 -2
  73. package/dist/spa/src/router/index.ts +19 -29
  74. package/dist/spa/src/stores/core.ts +59 -65
  75. package/dist/spa/src/stores/modal.ts +3 -13
  76. package/dist/spa/src/utils.ts +10 -69
  77. package/dist/spa/src/views/CreateView.vue +16 -69
  78. package/dist/spa/src/views/EditView.vue +14 -68
  79. package/dist/spa/src/views/HomeView.vue +8 -0
  80. package/dist/spa/src/views/ListView.vue +371 -100
  81. package/dist/spa/src/views/LoginView.vue +29 -67
  82. package/dist/spa/src/views/ResourceParent.vue +2 -1
  83. package/dist/spa/src/views/ShowView.vue +25 -116
  84. package/dist/spa/tailwind.config.js +3 -8
  85. package/dist/spa/vite.config.ts +0 -13
  86. package/dist/types.js +30 -0
  87. package/modules/restApi.ts +14 -1
  88. package/package.json +1 -1
  89. package/spa/src/components/MenuLink.vue +3 -0
  90. package/types/AdminForthConfig.ts +6 -0
  91. package/dist/spa/src/types/AdminForthConfig.ts +0 -1477
  92. package/dist/spa/src/types/FrontendAPI.ts +0 -121
  93. /package/dist/spa/{public → spa/public}/assets/favicon.png +0 -0
  94. /package/dist/spa/{src → spa/src}/components/CustomRangePicker.vue +0 -0
  95. /package/dist/spa/{src → spa/src}/components/SkeleteLoader.vue +0 -0
  96. /package/dist/spa/{src → spa/src}/composables/useFrontendApi.ts +0 -0
  97. /package/dist/spa/{src → spa/src}/composables/useStores.ts +0 -0
  98. /package/dist/spa/{src → spa/src}/spa_types/core.ts +0 -0
  99. /package/dist/spa/{src → spa/src}/stores/filters.ts +0 -0
  100. /package/dist/spa/{src → spa/src}/stores/toast.ts +0 -0
  101. /package/dist/spa/{src → spa/src}/stores/user.ts +0 -0
@@ -1,18 +1,17 @@
1
1
  <template>
2
2
  <div class="relative flex items-center justify-center min-h-screen bg-gray-100 dark:bg-gray-800"
3
3
  :style="coreStore.config?.loginBackgroundImage ? {
4
- 'background-image': 'url(' + loadFile(coreStore.config?.loginBackgroundImage) + ')',
4
+ 'background-image': 'url(' + coreStore.config?.loginBackgroundImage + ')',
5
5
  'background-size': 'cover',
6
6
  'background-position': 'center',
7
7
  'background-blend-mode': 'darken'
8
8
  }: {}"
9
9
  >
10
-
11
- <!-- Main modal -->
10
+ <!-- Main modal -->
12
11
  <div id="authentication-modal" tabindex="-1" class=" overflow-y-auto overflow-x-hidden z-50 min-w-[400px] justify-center items-center md:inset-0 h-[calc(100%-1rem)] max-h-full">
13
12
  <div class="relative p-4 w-full max-w-md max-h-full">
14
13
  <!-- Modal content -->
15
- <div class="relative bg-white rounded-lg shadow dark:bg-gray-700 dark:shadow-black" >
14
+ <div class="relative bg-white rounded-lg shadow dark:bg-gray-700">
16
15
  <!-- Modal header -->
17
16
  <div class="flex items-center justify-between p-4 md:p-5 border-b rounded-t dark:border-gray-600">
18
17
  <h3 class="text-xl font-semibold text-gray-900 dark:text-white">
@@ -22,23 +21,17 @@
22
21
  </div>
23
22
  <!-- Modal body -->
24
23
  <div class="p-4 md:p-5">
25
- <form class="space-y-4" @submit.prevent>
24
+ <form class="space-y-4" @submit.prevent>
26
25
  <div>
27
26
  <label for="username" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Your {{ coreStore.config?.usernameFieldName?.toLowerCase() }}</label>
28
- <input type="username" name="username" id="username"
29
- ref="usernameInput"
30
- @keydown.enter="passwordInput.focus()"
31
- class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white" placeholder="name@company.com" required />
27
+ <input type="username" name="username" id="username" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white" placeholder="name@company.com" required />
32
28
  </div>
33
29
  <div class="relative">
34
30
  <label for="password" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Your password</label>
35
- <input
36
- ref="passwordInput"
37
- @keydown.enter="login"
38
- :type="!showPw ? 'password': 'text'" name="password" id="password" placeholder="••••••••" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white" required />
31
+ <input :type="!showPw ? 'password': 'text'" name="password" id="password" placeholder="••••••••" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white" required />
39
32
  <button type="button" @click="showPw = !showPw" class="absolute top-12 right-3 -translate-y-1/2 text-gray-400 dark:text-gray-300">
40
- <IconEyeSolid class="w-5 h-5" v-if="!showPw" />
41
- <IconEyeSlashSolid class="w-5 h-5" v-else />
33
+ <IconEyeSolid class="w-5 h-5" v-if="!showPw" />
34
+ <IconEyeSlashSolid class="w-5 h-5" v-else />
42
35
  </button>
43
36
  </div>
44
37
  <!-- <div class="flex justify-between">
@@ -61,17 +54,6 @@
61
54
  </div>
62
55
  </div>
63
56
 
64
-
65
- <div v-if="coreStore.config?.loginPromptHTML"
66
- class="flex items-center p-4 mb-4 text-sm text-gray-800 rounded-lg bg-gray-50 dark:bg-gray-800 dark:text-gray-400" role="alert"
67
- >
68
- <svg class="flex-shrink-0 inline w-4 h-4 me-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20">
69
- <path d="M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5ZM9.5 4a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3ZM12 15H8a1 1 0 0 1 0-2h1v-3H8a1 1 0 0 1 0-2h2a1 1 0 0 1 1 1v4h1a1 1 0 0 1 0 2Z"/>
70
- </svg>
71
- <span class="sr-only">Info</span>
72
- <div v-html="coreStore.config?.loginPromptHTML"></div>
73
- </div>
74
-
75
57
  <button
76
58
  @click="login"
77
59
  type="submit" class="flex items-center justify-center gap-1 w-full text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">
@@ -96,64 +78,44 @@
96
78
 
97
79
  <script setup>
98
80
 
99
- import { onMounted, ref, watchEffect } from 'vue';
81
+ import { onMounted, ref } from 'vue';
100
82
  import { useCoreStore } from '@/stores/core';
101
- import { useUserStore } from '@/stores/user';
102
83
  import { IconEyeSolid, IconEyeSlashSolid } from '@iconify-prerendered/vue-flowbite';
103
- import { callAdminForthApi, loadFile } from '@/utils';
84
+ import { callAdminForthApi } from '@/utils';
104
85
  import { useRouter } from 'vue-router';
105
86
 
106
- const passwordInput = ref(null);
107
- const usernameInput = ref(null);
108
-
109
87
  const router = useRouter();
110
88
  const inProgress = ref(false);
111
89
 
112
90
  const coreStore = useCoreStore();
113
- const user = useUserStore();
114
-
115
91
 
116
92
  const showPw = ref(false);
117
93
 
118
94
  const error = ref(null);
119
95
 
120
- onMounted(async () => {
121
- await coreStore.getPublicConfig();
122
- if (coreStore.config?.demoCredentials) {
123
- console.log('Setting demo credentials');
124
- const [username, password] = coreStore.config.demoCredentials.split(':');
125
- usernameInput.value.value = username;
126
- passwordInput.value.value = password;
127
- }
128
- usernameInput.value.focus();
96
+ onMounted(() => {
97
+ coreStore.getPublicConfig()
129
98
  });
130
99
 
131
-
132
100
  async function login() {
133
- const username = usernameInput.value.value;
134
- const password = passwordInput.value.value;
135
-
136
- if (!username || !password) {
137
- return;
138
- }
139
- inProgress.value = true;
140
- const resp = await callAdminForthApi({
141
- path: '/login',
142
- method: 'POST',
143
- body: {
144
- username,
145
- password,
101
+ inProgress.value = true;
102
+ const resp = await callAdminForthApi({
103
+ path: '/login',
104
+ method: 'POST',
105
+ body: {
106
+ username: document.getElementById('username').value,
107
+ password: document.getElementById('password').value,
108
+ }
109
+ });
110
+ inProgress.value = false;
111
+ if (resp.error) {
112
+ error.value = resp.error;
113
+ } else {
114
+ error.value = null;
115
+ router.push('/');
116
+ await coreStore.fetchMenuAndResource();
146
117
  }
147
- });
148
- inProgress.value = false;
149
- if (resp.error) {
150
- error.value = resp.error;
151
- } else if (resp.redirectTo) {
152
- router.push(resp.redirectTo);
153
- } else {
154
- error.value = null;
155
- await user.finishLogin();
156
- }
118
+
157
119
  }
158
120
 
159
121
 
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div :key="`${$route?.params.resourceId}---${$route?.params.primaryKey}`" class="p-4">
2
+ <div>
3
3
  <RouterView/>
4
4
  </div>
5
5
  </template>
@@ -11,6 +11,7 @@
11
11
 
12
12
 
13
13
  import { useCoreStore } from '@/stores/core';
14
+ import { onMounted } from 'vue';
14
15
 
15
16
  const coreStore = useCoreStore()
16
17
 
@@ -1,38 +1,21 @@
1
1
  <template>
2
2
  <div class="relative">
3
- <component
4
- v-for="c in coreStore?.resourceOptions?.pageInjections?.show?.beforeBreadcrumbs || []"
5
- :is="getCustomComponent(c)"
6
- :meta="c.meta"
7
- :record="coreStore.record"
8
- :resource="coreStore.resource"
9
- :adminUser="coreStore.adminUser"
10
- />
11
3
  <BreadcrumbsWithButtons>
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 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"
4
+ <RouterLink :to="{ name: 'resource-edit', params: { resourceId: $route.params.resourceId, primaryKey: $route.params.primaryKey } }"
5
+ 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"
14
6
  >
15
7
  <IconPenSolid class="w-4 h-4" />
16
8
  Edit
17
9
  </RouterLink>
18
10
 
19
- <button v-if="coreStore?.resourceOptions?.allowedActions?.delete" @click="deleteRecord"
20
- class="flex items-center py-1 px-3 text-sm font-medium rounded-default text-red-600 focus:outline-none bg-white 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"
11
+ <button @click="deleteRecord"
12
+ class="flex items-center py-1 px-3 mb-2 text-sm font-medium 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
13
  >
22
14
  <IconTrashBinSolid class="w-4 h-4" />
23
15
  Delete
24
16
  </button>
25
17
  </BreadcrumbsWithButtons>
26
18
 
27
- <component
28
- v-for="c in coreStore?.resourceOptions?.pageInjections?.show?.afterBreadcrumbs || []"
29
- :is="getCustomComponent(c)"
30
- :meta="c.meta"
31
- :record="coreStore.record"
32
- :resource="coreStore.resource"
33
- :adminUser="coreStore.adminUser"
34
- />
35
-
36
19
  <div v-if="loading" role="status" class="max-w-sm animate-pulse">
37
20
  <div class="h-2.5 bg-gray-200 rounded-full dark:bg-gray-700 w-48 mb-4"></div>
38
21
  <div class="h-2 bg-gray-200 rounded-full dark:bg-gray-700 max-w-[360px] mb-2.5"></div>
@@ -43,69 +26,35 @@
43
26
  <span class="sr-only">Loading...</span>
44
27
  </div>
45
28
  <div
46
- v-else-if="coreStore.record"
47
- class="relative overflow-x-auto rounded-default shadow-resourseFormShadow "
29
+ v-else
30
+ class="relative overflow-x-auto shadow-md sm:rounded-lg"
48
31
  >
49
- <table class="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400 rounded-default">
50
- <thead class="text-xs text-gray-700 uppercase bg-lightFormHeading dark:bg-gray-700 dark:text-gray-400">
32
+ <table class="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400">
33
+ <thead class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
51
34
  <tr>
52
35
  <th scope="col" class="px-6 py-3">
53
36
  Field
54
37
  </th>
55
- <th scope="col" class="px-6 py-3 w-5/6">
38
+ <th scope="col" class="px-6 py-3 w-4/6">
56
39
  Value
57
40
  </th>
58
41
  </tr>
59
42
  </thead>
60
43
  <tbody>
61
- <tr v-for="column in coreStore.resource?.columns.filter(c => c.showIn.includes('show'))" :key="column.name"
62
- class="bg-lightForm bg-darkForm odd:dark:bg-gray-900 even:dark:bg-gray-800 border-b dark:border-gray-700"
44
+ <tr v-for="column in coreStore.resourceColumns?.filter(c => c.showIn.includes('show'))" :key="column.name"
45
+ class="odd:bg-white odd:dark:bg-gray-900 even:bg-gray-50 even:dark:bg-gray-800 border-b dark:border-gray-700"
63
46
  >
64
- <component
65
- v-if="column.components?.showRow"
66
- :is="getCustomComponent(column.components.showRow)"
67
- :meta="column.components.showRow.meta"
68
- :column="column"
69
- :resource="coreStore.resource"
70
- :record="coreStore.record"
71
- />
72
- <template v-else>
73
- <td class="px-6 py-4 whitespace-nowrap "> <!--align-top-->
74
- {{ column.label }}
47
+ <td class="px-6 py-4 whitespace-nowrap">
48
+ {{ column.label }}
75
49
  </td>
76
50
  <td class="px-6 py-4 whitespace-nowrap whitespace-pre-wrap">
77
- <component
78
- v-if="column?.components?.show"
79
- :is="getCustomComponent(column?.components?.show)"
80
- :resource="coreStore.resource"
81
- :meta="column.components.show.meta"
82
- :column="column"
83
- :record="coreStore.record"
84
- />
85
- <ValueRenderer v-else
86
- :column="column"
87
- :record="coreStore.record"
88
- />
51
+ <ValueRenderer :column="column" :row="coreStore.record" />
89
52
  </td>
90
- </template>
91
53
  </tr>
54
+
92
55
  </tbody>
93
- </table>
94
- </div>
95
-
96
- <div v-else class="text-center text-gray-500 dark:text-gray-400 mt-10">
97
- Ooops. Record not found
98
- </div>
99
-
100
- <component
101
- v-for="c in coreStore?.resourceOptions?.pageInjections?.show?.bottom || []"
102
- :is="getCustomComponent(c)"
103
- :meta="c.meta"
104
- :column="column"
105
- :record="coreStore.record"
106
- :resource="coreStore.resource"
107
- :adminUser="coreStore.adminUser"
108
- />
56
+ </table>
57
+ </div>
109
58
 
110
59
 
111
60
  </div>
@@ -114,71 +63,31 @@
114
63
 
115
64
  <script setup>
116
65
 
66
+ import { ref, computed, onMounted } from 'vue';
67
+ import { useRoute } from 'vue-router';
68
+ import { callAdminForthApi } from '@/utils';
117
69
  import BreadcrumbsWithButtons from '@/components/BreadcrumbsWithButtons.vue';
118
-
119
- import ValueRenderer from '@/components/ValueRenderer.vue';
120
- import { useCoreStore } from '@/stores/core';
121
- import { useModalStore } from '@/stores/modal';
122
- import { getCustomComponent, checkAcessByAllowedActions } from '@/utils';
123
70
  import { IconPenSolid, IconTrashBinSolid } from '@iconify-prerendered/vue-flowbite';
124
- import { onMounted, ref } from 'vue';
125
- import { useRoute,useRouter } from 'vue-router';
126
- import {callAdminForthApi} from '@/utils';
127
- import { showSuccesTost, showErrorTost } from '@/composables/useFrontendApi';
71
+ import { useCoreStore } from '@/stores/core';
72
+ import ValueRenderer from '@/components/ValueRenderer.vue';
128
73
 
129
74
 
130
75
  const item = ref(null);
131
76
  const route = useRoute();
132
- const router = useRouter();
133
- const loading = ref(true);
134
-
135
- console.log(route.params,'showWiev');
136
-
77
+ const loading = ref(false);
137
78
 
138
79
  const coreStore = useCoreStore();
139
- const modalStore = useModalStore();
140
80
 
141
81
  onMounted(async () => {
142
82
  loading.value = true;
143
- await coreStore.fetchResourceFull({
83
+ await coreStore.fetchColumns({
144
84
  resourceId: route.params.resourceId
145
85
  });
146
86
  await coreStore.fetchRecord({
147
87
  resourceId: route.params.resourceId,
148
88
  primaryKey: route.params.primaryKey,
149
89
  });
150
- checkAcessByAllowedActions(coreStore.resourceOptions.allowedActions,'show');
151
90
  loading.value = false;
152
91
  });
153
92
 
154
- async function deleteRecord(row) {
155
- const data = await window.adminforth.confirm({
156
- message: 'Are you sure you want to delete this item?',
157
- yes: 'Delete',
158
- no: 'Cancel',
159
- });
160
- if (data) {
161
- try {
162
- const res = await callAdminForthApi({
163
- path: '/delete_record',
164
- method: 'POST',
165
- body: {
166
- resourceId: route.params.resourceId,
167
- primaryKey: route.params.primaryKey,
168
- }});
169
- if (!res.error){
170
- router.push({ name: 'resource-list', params: { resourceId: route.params.resourceId } });
171
- showSuccesTost('Record deleted successfully')
172
- } else {
173
- showErrorTost(res.error)
174
- }
175
-
176
- } catch (e) {
177
- console.error(e);
178
- };
179
- }
180
-
181
-
182
- }
183
-
184
- </script>
93
+ </script>
@@ -1,17 +1,12 @@
1
1
  /** @type {import('tailwindcss').Config} */
2
2
  export default {
3
- content: ["./src/**/*.{vue, js, ts, tsx}","./src/*.{vue, js, ts, tsx}", "./index.html", "./node_modules/flowbite/**/*.js"],
3
+ content: ["./src/**/*.{vue, js}", "./node_modules/flowbite/**/*.js"],
4
4
  theme: {
5
- extend: {
6
- /* IMPORTANT:ADMINFORTH TAILWIND STYLES */
7
- }
5
+ extend: {},
8
6
  },
9
-
10
7
  darkMode: 'class',
11
8
  plugins: [
12
- require('flowbite/plugin')({
13
- charts: true,
14
- }),
9
+ require('flowbite/plugin'),
15
10
  ],
16
11
  }
17
12
 
@@ -2,7 +2,6 @@ import { fileURLToPath, URL } from 'node:url'
2
2
 
3
3
  import { defineConfig } from 'vite'
4
4
  import vue from '@vitejs/plugin-vue'
5
- import { clear, error } from 'node:console';
6
5
 
7
6
 
8
7
  const customLogger = {
@@ -12,12 +11,6 @@ const customLogger = {
12
11
  console.log(msg);
13
12
  }
14
13
  },
15
- warnOnce(msg: string) {
16
- console.warn('warn once', msg);
17
- if (!this.hasWarned) {
18
- this.hasWarned = true;
19
- }
20
- },
21
14
  warn(msg: string) {
22
15
  console.warn(msg);
23
16
  },
@@ -27,13 +20,7 @@ const customLogger = {
27
20
  clear() {
28
21
  console.clear();
29
22
  },
30
- clearScreen() {
31
- console.clear();
32
- },
33
23
  hasWarned: false,
34
- hasErrorLogged: (error: any): boolean => {
35
- return false;
36
- }
37
24
  };
38
25
 
39
26
  // https://vitejs.dev/config/
package/dist/types.js ADDED
@@ -0,0 +1,30 @@
1
+ // typical types which AdminForth supports
2
+ //
3
+ export const AdminForthTypes = {
4
+ STRING: 'string',
5
+ INTEGER: 'integer',
6
+ FLOAT: 'float',
7
+ DECIMAL: 'decimal',
8
+ BOOLEAN: 'boolean',
9
+ DATE: 'date',
10
+ DATETIME: 'datetime',
11
+ TIME: 'time',
12
+ TEXT: 'text',
13
+ JSON: 'json',
14
+ };
15
+ export const AdminForthFilterOperators = {
16
+ EQ: 'eq',
17
+ NE: 'ne',
18
+ GT: 'gt',
19
+ LT: 'lt',
20
+ GTE: 'gte',
21
+ LTE: 'lte',
22
+ LIKE: 'like',
23
+ ILIKE: 'ilike',
24
+ IN: 'in',
25
+ NIN: 'nin',
26
+ };
27
+ export const AdminForthSortDirections = {
28
+ ASC: 'asc',
29
+ DESC: 'desc',
30
+ };
@@ -182,7 +182,18 @@ export default class AdminForthRestAPI {
182
182
  throw new Error(`'visible' function of ${menuItem.label || menuItem.type } must return boolean value`);
183
183
  }
184
184
  return toReturn;
185
- }}
185
+ }
186
+
187
+
188
+ }
189
+
190
+ function processMenuItem(menuItem) {
191
+ if (menuItem.badge) {
192
+ if (typeof menuItem.badge === 'function') {
193
+ menuItem.badge = menuItem.badge(adminUser);
194
+ }
195
+ }
196
+ }
186
197
  let newMenu = []
187
198
  for (let menuItem of this.adminforth.config.menu) {
188
199
  let newMenuItem = {...menuItem,}
@@ -200,10 +211,12 @@ export default class AdminForthRestAPI {
200
211
  continue
201
212
  }
202
213
  }
214
+ processMenuItem(newChild)
203
215
  newChildren.push(newChild)
204
216
  }
205
217
  newMenuItem = {...newMenuItem, children: newChildren}
206
218
  }
219
+ processMenuItem(newMenuItem)
207
220
  newMenu.push(newMenuItem)
208
221
  }
209
222
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "adminforth",
3
- "version": "1.2.87",
3
+ "version": "1.2.89",
4
4
  "description": "OpenSource Vue3 powered forth-generation admin panel",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -12,6 +12,9 @@
12
12
  >
13
13
  <component v-if="item.icon" :is="getIcon(item.icon)" class="w-5 h-5 text-lightSidebarIcons dark:text-darkSidebarIcons transition duration-75 group-hover:text-lightSidebarIconsHover dark:group-hover:text-darkSidebarIconsHover" ></component>
14
14
  <span class="ms-3">{{ item.label }}</span>
15
+ <span v-if="item.badge" class="inline-flex items-center justify-center w-3 h-3 p-3 ms-3 text-sm font-medium rounded-full bg-lightAnnouncementBG dark:bg-darkAnnouncementBG
16
+ fill-lightAnnouncementText dark:fill-darkAccent text-lightAnnouncementText dark:text-darkAccent">{{ item.badge }}</span>
17
+
15
18
  </RouterLink>
16
19
  </template>
17
20
 
@@ -469,6 +469,12 @@ export type AdminForthConfigMenuItem = {
469
469
  * You can use it to hide menu items depending on some user
470
470
  */
471
471
  visible?: (user: AdminUser) => boolean,
472
+
473
+ /**
474
+ * Optional callback which will be called before rendering the menu for each item.
475
+ * Result of callback if not null will be used as a small badge near the menu item.
476
+ */
477
+ badge?: string | ((user: AdminUser) => string),
472
478
  }
473
479
 
474
480