adminforth 1.1.32 → 1.1.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +9 -0
- package/dist/modules/codeInjector.js +19 -7
- package/dist/modules/styles.js +2 -2
- package/dist/spa/index.html +2 -2
- package/dist/spa/package-lock.json +17 -4
- package/dist/spa/package.json +2 -1
- package/dist/spa/src/App.vue +125 -45
- package/dist/spa/src/assets/logo.svg +19 -1
- package/dist/spa/src/components/AcceptModal.vue +2 -9
- package/dist/spa/src/components/BreadcrumbsWithButtons.vue +1 -1
- package/dist/spa/src/components/CustomDatePicker.vue +16 -3
- package/dist/spa/src/components/CustomDateRangePicker.vue +11 -2
- package/dist/spa/src/components/Dropdown.vue +6 -1
- package/dist/spa/src/components/Filters.vue +40 -19
- package/dist/spa/src/components/ResourceForm.vue +26 -24
- package/dist/spa/src/components/ValueRenderer.vue +14 -8
- package/dist/spa/src/main.ts +1 -1
- package/dist/spa/src/router/index.ts +30 -20
- package/dist/spa/src/stores/core.ts +48 -31
- package/dist/spa/src/stores/modal.ts +13 -3
- package/dist/spa/src/utils.ts +62 -7
- package/dist/spa/src/views/CreateView.vue +67 -15
- package/dist/spa/src/views/EditView.vue +45 -11
- package/dist/spa/src/views/ListView.vue +82 -366
- package/dist/spa/src/views/LoginView.vue +16 -4
- package/dist/spa/src/views/ShowView.vue +105 -21
- package/dist/spa/tailwind.config.js +1 -1
- package/dist/spa/vite.config.ts +6 -0
- package/index.ts +11 -0
- package/modules/codeInjector.ts +19 -1
- package/modules/styles.ts +2 -2
- package/package.json +1 -1
- package/spa/index.html +1 -1
- package/spa/src/App.vue +2 -3
- package/types/AdminForthConfig.ts +15 -0
- package/dist/plugins/AccessControl/index.js +0 -66
- package/dist/plugins/AccessControl/types.js +0 -1
- package/dist/spa/public/favicon.ico +0 -0
- package/dist/spa/spa/.eslintrc.cjs +0 -14
- package/dist/spa/spa/.vscode/extensions.json +0 -6
- package/dist/spa/spa/README.md +0 -39
- package/dist/spa/spa/env.d.ts +0 -1
- package/dist/spa/spa/index.html +0 -23
- package/dist/spa/spa/package-lock.json +0 -4359
- package/dist/spa/spa/package.json +0 -47
- package/dist/spa/spa/postcss.config.js +0 -6
- package/dist/spa/spa/public/favicon.ico +0 -0
- package/dist/spa/spa/src/App.vue +0 -272
- package/dist/spa/spa/src/assets/base.css +0 -0
- package/dist/spa/spa/src/assets/logo.svg +0 -19
- package/dist/spa/spa/src/components/AcceptModal.vue +0 -45
- package/dist/spa/spa/src/components/Breadcrumbs.vue +0 -40
- package/dist/spa/spa/src/components/BreadcrumbsWithButtons.vue +0 -26
- package/dist/spa/spa/src/components/CustomDatePicker.vue +0 -174
- package/dist/spa/spa/src/components/CustomDateRangePicker.vue +0 -218
- package/dist/spa/spa/src/components/CustomRangePicker.vue +0 -148
- package/dist/spa/spa/src/components/Dropdown.vue +0 -168
- package/dist/spa/spa/src/components/Filters.vue +0 -211
- package/dist/spa/spa/src/components/HelloWorld.vue +0 -17
- package/dist/spa/spa/src/components/MenuLink.vue +0 -24
- package/dist/spa/spa/src/components/ResourceForm.vue +0 -265
- package/dist/spa/spa/src/components/SingleSkeletLoader.vue +0 -13
- package/dist/spa/spa/src/components/ValueRenderer.vue +0 -60
- package/dist/spa/spa/src/components/icons/IconCalendar.vue +0 -5
- package/dist/spa/spa/src/components/icons/IconCommunity.vue +0 -7
- package/dist/spa/spa/src/components/icons/IconDocumentation.vue +0 -7
- package/dist/spa/spa/src/components/icons/IconEcosystem.vue +0 -7
- package/dist/spa/spa/src/components/icons/IconSupport.vue +0 -7
- package/dist/spa/spa/src/components/icons/IconTime.vue +0 -5
- package/dist/spa/spa/src/components/icons/IconTooling.vue +0 -19
- package/dist/spa/spa/src/index.scss +0 -26
- package/dist/spa/spa/src/main.ts +0 -18
- package/dist/spa/spa/src/router/index.ts +0 -64
- package/dist/spa/spa/src/stores/core.ts +0 -144
- package/dist/spa/spa/src/stores/modal.ts +0 -48
- package/dist/spa/spa/src/utils.ts +0 -101
- package/dist/spa/spa/src/views/CreateView.vue +0 -163
- package/dist/spa/spa/src/views/EditView.vue +0 -165
- package/dist/spa/spa/src/views/ListView.vue +0 -257
- package/dist/spa/spa/src/views/LoginView.vue +0 -134
- package/dist/spa/spa/src/views/ResourceParent.vue +0 -18
- package/dist/spa/spa/src/views/ShowView.vue +0 -188
- package/dist/spa/spa/tailwind.config.js +0 -15
- package/dist/spa/spa/tsconfig.app.json +0 -14
- package/dist/spa/spa/tsconfig.json +0 -11
- package/dist/spa/spa/tsconfig.node.json +0 -19
- package/dist/spa/spa/vite.config.ts +0 -49
- package/dist/types.js +0 -30
- /package/dist/spa/{spa/public → public/assets}/favicon.png +0 -0
- /package/dist/spa/{spa/src → src}/components/ResourceListTable.vue +0 -0
- /package/dist/spa/{spa/src → src}/components/Toast.vue +0 -0
- /package/dist/spa/{spa/src → src}/composables/useFrontendApi.ts +0 -0
- /package/dist/spa/{spa/src → src}/composables/useStores.ts +0 -0
- /package/dist/spa/{spa/src → src}/spa_types/core.ts +0 -0
- /package/dist/spa/{spa/src → src}/stores/filters.ts +0 -0
- /package/dist/spa/{spa/src → src}/stores/toast.ts +0 -0
- /package/dist/spa/{spa/src → src}/stores/user.ts +0 -0
- /package/spa/public/{favicon.png → assets/favicon.png} +0 -0
|
@@ -1,21 +1,38 @@
|
|
|
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
|
+
/>
|
|
3
11
|
<BreadcrumbsWithButtons>
|
|
4
|
-
<RouterLink :to="{ name: 'resource-edit', params: { resourceId: $route.params.resourceId, primaryKey: $route.params.primaryKey } }"
|
|
5
|
-
class="flex items-center py-1 px-3
|
|
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"
|
|
6
14
|
>
|
|
7
15
|
<IconPenSolid class="w-4 h-4" />
|
|
8
16
|
Edit
|
|
9
17
|
</RouterLink>
|
|
10
18
|
|
|
11
|
-
<button @click="deleteRecord"
|
|
12
|
-
class="flex items-center py-1 px-3
|
|
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"
|
|
13
21
|
>
|
|
14
22
|
<IconTrashBinSolid class="w-4 h-4" />
|
|
15
23
|
Delete
|
|
16
24
|
</button>
|
|
17
25
|
</BreadcrumbsWithButtons>
|
|
18
26
|
|
|
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
|
+
|
|
19
36
|
<div v-if="loading" role="status" class="max-w-sm animate-pulse">
|
|
20
37
|
<div class="h-2.5 bg-gray-200 rounded-full dark:bg-gray-700 w-48 mb-4"></div>
|
|
21
38
|
<div class="h-2 bg-gray-200 rounded-full dark:bg-gray-700 max-w-[360px] mb-2.5"></div>
|
|
@@ -29,7 +46,7 @@
|
|
|
29
46
|
v-else
|
|
30
47
|
class="relative overflow-x-auto shadow-resourse-form-shadow "
|
|
31
48
|
>
|
|
32
|
-
<table class="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400">
|
|
49
|
+
<table class="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400 rounded-default">
|
|
33
50
|
<thead class="text-xs text-gray-700 uppercase bg-form-view-heading dark:bg-gray-700 dark:text-gray-400">
|
|
34
51
|
<tr>
|
|
35
52
|
<th scope="col" class="px-6 py-3">
|
|
@@ -41,23 +58,49 @@
|
|
|
41
58
|
</tr>
|
|
42
59
|
</thead>
|
|
43
60
|
<tbody>
|
|
44
|
-
<tr v-for="column in coreStore.
|
|
61
|
+
<tr v-for="column in coreStore.resource?.columns.filter(c => c.showIn.includes('show'))" :key="column.name"
|
|
45
62
|
class="bg-form-view-bg odd:dark:bg-gray-900 even:dark:bg-gray-800 border-b dark:border-gray-700"
|
|
46
63
|
>
|
|
47
|
-
|
|
48
|
-
|
|
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 }}
|
|
49
75
|
</td>
|
|
50
76
|
<td class="px-6 py-4 whitespace-nowrap whitespace-pre-wrap">
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
77
|
+
<component
|
|
78
|
+
v-if="showComponentsPerColumn[column.name]"
|
|
79
|
+
:is="showComponentsPerColumn[column.name]"
|
|
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
|
+
/>
|
|
56
89
|
</td>
|
|
90
|
+
</template>
|
|
57
91
|
</tr>
|
|
58
|
-
|
|
59
92
|
</tbody>
|
|
60
93
|
</table>
|
|
94
|
+
|
|
95
|
+
<component
|
|
96
|
+
v-for="c in coreStore?.resourceOptions?.pageInjections?.show?.bottom || []"
|
|
97
|
+
:is="getCustomComponent(c)"
|
|
98
|
+
:meta="c.meta"
|
|
99
|
+
:column="column"
|
|
100
|
+
:record="coreStore.record"
|
|
101
|
+
:resource="coreStore.resource"
|
|
102
|
+
:adminUser="coreStore.adminUser"
|
|
103
|
+
/>
|
|
61
104
|
</div>
|
|
62
105
|
|
|
63
106
|
|
|
@@ -68,37 +111,78 @@
|
|
|
68
111
|
<script setup>
|
|
69
112
|
|
|
70
113
|
import BreadcrumbsWithButtons from '@/components/BreadcrumbsWithButtons.vue';
|
|
114
|
+
|
|
71
115
|
import ValueRenderer from '@/components/ValueRenderer.vue';
|
|
72
116
|
import { useCoreStore } from '@/stores/core';
|
|
73
|
-
import {
|
|
117
|
+
import { useModalStore } from '@/stores/modal';
|
|
118
|
+
import { getCustomComponent, checkAcessByAllowedActions } from '@/utils';
|
|
74
119
|
import { IconPenSolid, IconTrashBinSolid } from '@iconify-prerendered/vue-flowbite';
|
|
75
120
|
import { onMounted, ref } from 'vue';
|
|
76
|
-
import { useRoute } from 'vue-router';
|
|
121
|
+
import { useRoute,useRouter } from 'vue-router';
|
|
122
|
+
import {callAdminForthApi} from '@/utils';
|
|
123
|
+
import {showSuccesTost} from '@/composables/useFrontendApi';
|
|
77
124
|
|
|
78
125
|
|
|
79
126
|
const item = ref(null);
|
|
80
127
|
const route = useRoute();
|
|
128
|
+
const router = useRouter();
|
|
81
129
|
const loading = ref(false);
|
|
82
130
|
let showComponentsPerColumn = {};
|
|
83
131
|
|
|
132
|
+
console.log(route.params,'showWiev');
|
|
133
|
+
|
|
134
|
+
|
|
84
135
|
const coreStore = useCoreStore();
|
|
136
|
+
const modalStore = useModalStore();
|
|
85
137
|
|
|
86
138
|
onMounted(async () => {
|
|
87
139
|
loading.value = true;
|
|
88
|
-
await coreStore.
|
|
140
|
+
await coreStore.fetchResourceFull({
|
|
89
141
|
resourceId: route.params.resourceId
|
|
90
142
|
});
|
|
91
143
|
await coreStore.fetchRecord({
|
|
92
144
|
resourceId: route.params.resourceId,
|
|
93
145
|
primaryKey: route.params.primaryKey,
|
|
94
146
|
});
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
147
|
+
checkAcessByAllowedActions(coreStore.resourceOptions.allowedActions,'show');
|
|
148
|
+
|
|
149
|
+
showComponentsPerColumn = coreStore.resource.columns.reduce((acc, column) => {
|
|
150
|
+
if (column.components?.show) {
|
|
151
|
+
acc[column.name] = getCustomComponent(column.components.show);
|
|
98
152
|
}
|
|
99
153
|
return acc;
|
|
100
|
-
|
|
154
|
+
}, {});
|
|
101
155
|
loading.value = false;
|
|
102
156
|
});
|
|
103
157
|
|
|
158
|
+
async function deleteRecord(row) {
|
|
159
|
+
const data = await window.adminforth.confirm({
|
|
160
|
+
message: 'Are you sure you want to delete this item?',
|
|
161
|
+
yes: 'Delete',
|
|
162
|
+
no: 'Cancel',
|
|
163
|
+
});
|
|
164
|
+
if (data) {
|
|
165
|
+
try {
|
|
166
|
+
const res = await callAdminForthApi({
|
|
167
|
+
path: '/delete_record',
|
|
168
|
+
method: 'POST',
|
|
169
|
+
body: {
|
|
170
|
+
resourceId: route.params.resourceId,
|
|
171
|
+
primaryKey: route.params.primaryKey,
|
|
172
|
+
}});
|
|
173
|
+
if (!res.error){
|
|
174
|
+
router.push({ name: 'resource-list', params: { resourceId: route.params.resourceId } });
|
|
175
|
+
showSuccesTost('Record deleted successfully')
|
|
176
|
+
} else {
|
|
177
|
+
console.error(res.error)
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
} catch (e) {
|
|
181
|
+
console.error(e);
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
}
|
|
187
|
+
|
|
104
188
|
</script>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** @type {import('tailwindcss').Config} */
|
|
2
2
|
export default {
|
|
3
|
-
content: ["./src/**/*.{vue, js}","./src/*.{vue, js}", "./index.html", "./node_modules/flowbite/**/*.js"],
|
|
3
|
+
content: ["./src/**/*.{vue, js, ts, tsx}","./src/*.{vue, js, ts, tsx}", "./index.html", "./node_modules/flowbite/**/*.js"],
|
|
4
4
|
theme: {
|
|
5
5
|
extend: {
|
|
6
6
|
/* IMPORTANT:ADMINFORTH TAILWIND STYLES */
|
package/dist/spa/vite.config.ts
CHANGED
package/index.ts
CHANGED
|
@@ -49,6 +49,8 @@ class AdminForth implements AdminForthClass {
|
|
|
49
49
|
runningHotReload: boolean;
|
|
50
50
|
activatedPlugins: Array<AdminForthPlugin>;
|
|
51
51
|
|
|
52
|
+
baseUrlSlashed: string;
|
|
53
|
+
|
|
52
54
|
statuses: {
|
|
53
55
|
dbDiscover?: 'running' | 'done',
|
|
54
56
|
}
|
|
@@ -159,6 +161,11 @@ class AdminForth implements AdminForthClass {
|
|
|
159
161
|
if (!this.config.baseUrl) {
|
|
160
162
|
this.config.baseUrl = '';
|
|
161
163
|
}
|
|
164
|
+
if (!this.config.baseUrl.endsWith('/')) {
|
|
165
|
+
this.baseUrlSlashed = this.config.baseUrl + '/';
|
|
166
|
+
} else {
|
|
167
|
+
this.baseUrlSlashed = this.config.baseUrl;
|
|
168
|
+
}
|
|
162
169
|
if (!this.config?.customization.brandName) {
|
|
163
170
|
this.config.customization.brandName = 'AdminForth';
|
|
164
171
|
}
|
|
@@ -166,6 +173,10 @@ class AdminForth implements AdminForthClass {
|
|
|
166
173
|
errors.push(...this.checkCustomFileExists(this.config.customization.brandLogo));
|
|
167
174
|
}
|
|
168
175
|
|
|
176
|
+
if (!this.config.customization.favicon) {
|
|
177
|
+
errors.push(...this.checkCustomFileExists(this.config.customization.favicon));
|
|
178
|
+
}
|
|
179
|
+
|
|
169
180
|
if (!this.config.customization.datesFormat) {
|
|
170
181
|
this.config.customization.datesFormat = 'MMM D, YYYY HH:mm:ss';
|
|
171
182
|
}
|
package/modules/codeInjector.ts
CHANGED
|
@@ -209,6 +209,18 @@ class CodeInjector implements CodeInjectorType {
|
|
|
209
209
|
this.srcFoldersToSync[this.adminforth.config.customization.customComponentsDir] = './'
|
|
210
210
|
}
|
|
211
211
|
|
|
212
|
+
// if this.adminforth.config.customization.favicon is set, copy it to assets
|
|
213
|
+
const customFav = this.adminforth.config.customization?.favicon;
|
|
214
|
+
if (customFav) {
|
|
215
|
+
|
|
216
|
+
const faviconPath = path.join(this.adminforth.config.customization?.customComponentsDir, customFav.replace('@@/', ''));
|
|
217
|
+
const dest = path.join(CodeInjector.SPA_TMP_PATH, 'public', 'assets', customFav.replace('@@/', ''));
|
|
218
|
+
// make sure all folders in dest exist
|
|
219
|
+
await fsExtra.ensureDir(path.dirname(dest));
|
|
220
|
+
|
|
221
|
+
await fsExtra.copy(faviconPath, dest);
|
|
222
|
+
}
|
|
223
|
+
|
|
212
224
|
for (const [src, dest] of Object.entries(this.srcFoldersToSync)) {
|
|
213
225
|
const to = path.join(CodeInjector.SPA_TMP_PATH, 'src', 'custom', dest);
|
|
214
226
|
if (process.env.HEAVY_DEBUG) {
|
|
@@ -343,7 +355,6 @@ class CodeInjector implements CodeInjectorType {
|
|
|
343
355
|
await fs.promises.writeFile(tailwindConfigPath, tailwindConfigContent);
|
|
344
356
|
}
|
|
345
357
|
|
|
346
|
-
|
|
347
358
|
const routerVuePath = path.join(CodeInjector.SPA_TMP_PATH, 'src', 'router', 'index.ts');
|
|
348
359
|
|
|
349
360
|
let routerVueContent = await fs.promises.readFile(routerVuePath, 'utf-8');
|
|
@@ -353,6 +364,13 @@ class CodeInjector implements CodeInjectorType {
|
|
|
353
364
|
const indexHtmlPath = path.join(CodeInjector.SPA_TMP_PATH, 'index.html');
|
|
354
365
|
let indexHtmlContent = await fs.promises.readFile(indexHtmlPath, 'utf-8');
|
|
355
366
|
indexHtmlContent = indexHtmlContent.replace('/* IMPORTANT:ADMINFORTH TITLE */', `${this.adminforth.config.customization.title || 'AdminForth'}`);
|
|
367
|
+
|
|
368
|
+
indexHtmlContent = indexHtmlContent.replace(
|
|
369
|
+
'/* IMPORTANT:ADMINFORTH FAVICON */',
|
|
370
|
+
this.adminforth.config.customization.favicon?.replace('@@/', `${this.adminforth.baseUrlSlashed}assets/`)
|
|
371
|
+
||
|
|
372
|
+
`${this.adminforth.baseUrlSlashed}assets/favicon.png`
|
|
373
|
+
);
|
|
356
374
|
await fs.promises.writeFile(indexHtmlPath, indexHtmlContent);
|
|
357
375
|
|
|
358
376
|
|
package/modules/styles.ts
CHANGED
|
@@ -27,10 +27,10 @@ export const styles = () => `
|
|
|
27
27
|
|
|
28
28
|
"list-view-bg": "#FFFFFF", // White background
|
|
29
29
|
"list-view-table-bg": "#FFFFFF", // White table background
|
|
30
|
-
"list-view-table-heading": "
|
|
30
|
+
"list-view-table-heading": "rgb(249 250 251)", // Very light grey heading
|
|
31
31
|
"list-view-table-heading-text": "#333333", // Dark grey heading text
|
|
32
32
|
"list-view-table-text": "#333333", // Dark grey text
|
|
33
|
-
"list-view-table-row-hover": "
|
|
33
|
+
"list-view-table-row-hover": "rgb(249 250 251)", // Very light grey row hover
|
|
34
34
|
"list-view-bread-crumbs-text": "#666666", // Medium grey bread crumbs
|
|
35
35
|
"list-view-border-color": "#DDDDDD", // Light grey border
|
|
36
36
|
|
package/package.json
CHANGED
package/spa/index.html
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<html lang="en">
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
|
-
<link rel="icon" href="
|
|
5
|
+
<link rel="icon" href="/* IMPORTANT:ADMINFORTH FAVICON */">
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
7
|
<title>/* IMPORTANT:ADMINFORTH TITLE */</title>
|
|
8
8
|
<!--
|
package/spa/src/App.vue
CHANGED
|
@@ -59,11 +59,11 @@
|
|
|
59
59
|
|
|
60
60
|
v-if="loggedIn && routerIsReady && loginRedirectCheckIsReady"
|
|
61
61
|
|
|
62
|
-
id="logo-sidebar" class="fixed border-none top-0 left-0 z-20 w-64 h-screen transition-transform
|
|
62
|
+
id="logo-sidebar" class="fixed border-none top-0 left-0 z-20 w-64 h-screen transition-transform border-r border-nav-menu-border sm:translate-x-0 dark:bg-gray-800 dark:border-gray-700"
|
|
63
63
|
:class="{ '-translate-x-full': !sideBarOpen, 'transform-none': sideBarOpen }"
|
|
64
64
|
aria-label="Sidebar"
|
|
65
65
|
>
|
|
66
|
-
<div class="h-full px-3 pb-4 overflow-y-auto bg-
|
|
66
|
+
<div class="h-full px-3 pb-4 overflow-y-auto bg-white dark:bg-gray-800 border-r">
|
|
67
67
|
<div class="flex ms-2 md:me-24 m-4 ">
|
|
68
68
|
<img :src="loadFile(coreStore.config?.brandLogo || '@/assets/logo.svg')" :alt="`${ coreStore.config?.brandName } Logo`" class="h-8 me-3" />
|
|
69
69
|
<span class="self-center text-header-text-size font-semibold sm:text-header-text-size whitespace-nowrap dark:text-header-text text-header-logo-color">
|
|
@@ -242,7 +242,6 @@ async function loadMenu() {
|
|
|
242
242
|
|
|
243
243
|
coreStore.menu.forEach((item, i) => {
|
|
244
244
|
if (item.open) {
|
|
245
|
-
console.log(item)
|
|
246
245
|
opened.value.push(i);
|
|
247
246
|
}
|
|
248
247
|
});
|
|
@@ -742,6 +742,21 @@ export type AdminForthConfig = {
|
|
|
742
742
|
*/
|
|
743
743
|
brandLogo?: string,
|
|
744
744
|
|
|
745
|
+
/**
|
|
746
|
+
* Path to your app favicon
|
|
747
|
+
*
|
|
748
|
+
* Example:
|
|
749
|
+
* Place file `favicon.png` to `./custom` folder and set this option:
|
|
750
|
+
*
|
|
751
|
+
* ```ts
|
|
752
|
+
* favicon: '@@/favicon.png',
|
|
753
|
+
* ```
|
|
754
|
+
*/
|
|
755
|
+
favicon?: string,
|
|
756
|
+
|
|
757
|
+
/**
|
|
758
|
+
favicon?: string,
|
|
759
|
+
|
|
745
760
|
/**
|
|
746
761
|
* DayJS format string for all dates in the app
|
|
747
762
|
*/
|
|
@@ -1,66 +0,0 @@
|
|
|
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
|
-
import AdminForthPlugin from "../base.js";
|
|
12
|
-
class AccessControlPlugin extends AdminForthPlugin {
|
|
13
|
-
constructor(options) {
|
|
14
|
-
super(options, import.meta.url);
|
|
15
|
-
this.options = options;
|
|
16
|
-
}
|
|
17
|
-
modifyResourceConfig(adminforth, resourceConfig) {
|
|
18
|
-
super.modifyResourceConfig(adminforth, resourceConfig);
|
|
19
|
-
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
|
-
}
|
|
64
|
-
}
|
|
65
|
-
AccessControlPlugin.defaultError = 'Sorry, you do not have access to this resource.';
|
|
66
|
-
export default AccessControlPlugin;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
Binary file
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/* eslint-env node */
|
|
2
|
-
require('@rushstack/eslint-patch/modern-module-resolution')
|
|
3
|
-
|
|
4
|
-
module.exports = {
|
|
5
|
-
root: true,
|
|
6
|
-
'extends': [
|
|
7
|
-
'plugin:vue/vue3-essential',
|
|
8
|
-
'eslint:recommended',
|
|
9
|
-
'@vue/eslint-config-typescript'
|
|
10
|
-
],
|
|
11
|
-
parserOptions: {
|
|
12
|
-
ecmaVersion: 'latest'
|
|
13
|
-
}
|
|
14
|
-
}
|
package/dist/spa/spa/README.md
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
# spa
|
|
2
|
-
|
|
3
|
-
This template should help get you started developing with Vue 3 in Vite.
|
|
4
|
-
|
|
5
|
-
## Recommended IDE Setup
|
|
6
|
-
|
|
7
|
-
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur).
|
|
8
|
-
|
|
9
|
-
## Type Support for `.vue` Imports in TS
|
|
10
|
-
|
|
11
|
-
TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) to make the TypeScript language service aware of `.vue` types.
|
|
12
|
-
|
|
13
|
-
## Customize configuration
|
|
14
|
-
|
|
15
|
-
See [Vite Configuration Reference](https://vitejs.dev/config/).
|
|
16
|
-
|
|
17
|
-
## Project Setup
|
|
18
|
-
|
|
19
|
-
```sh
|
|
20
|
-
npm install
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
### Compile and Hot-Reload for Development
|
|
24
|
-
|
|
25
|
-
```sh
|
|
26
|
-
npm run dev
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
### Type-Check, Compile and Minify for Production
|
|
30
|
-
|
|
31
|
-
```sh
|
|
32
|
-
npm run build
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
### Lint with [ESLint](https://eslint.org/)
|
|
36
|
-
|
|
37
|
-
```sh
|
|
38
|
-
npm run lint
|
|
39
|
-
```
|
package/dist/spa/spa/env.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
/// <reference types="vite/client" />
|
package/dist/spa/spa/index.html
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8">
|
|
5
|
-
<link rel="icon" href="/favicon.png">
|
|
6
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
|
-
<title>/* IMPORTANT:ADMINFORTH TITLE */</title>
|
|
8
|
-
<!--
|
|
9
|
-
<script>
|
|
10
|
-
// On page load or when changing themes, best to add inline in `head` to avoid FOUC
|
|
11
|
-
if (localStorage.getItem('color-theme') === 'dark' || (!('color-theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
|
12
|
-
document.documentElement.classList.add('dark');
|
|
13
|
-
} else {
|
|
14
|
-
document.documentElement.classList.remove('dark')
|
|
15
|
-
}
|
|
16
|
-
</script> -->
|
|
17
|
-
|
|
18
|
-
</head>
|
|
19
|
-
<body class=" ">
|
|
20
|
-
<div id="app" class="min-h-screen bg-html-bg dark:bg-gray-800"></div>
|
|
21
|
-
<script type="module" src="/src/main.ts"></script>
|
|
22
|
-
</body>
|
|
23
|
-
</html>
|