adminforth 2.4.0-next.3 → 2.4.0-next.300
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/commands/callTsProxy.js +14 -4
- package/commands/cli.js +12 -4
- package/commands/createApp/templates/api.ts.hbs +10 -0
- package/commands/createApp/templates/custom/tsconfig.json.hbs +2 -3
- package/commands/createApp/templates/index.ts.hbs +13 -5
- package/commands/createApp/templates/package.json.hbs +1 -1
- package/commands/createApp/utils.js +45 -7
- package/commands/createCustomComponent/configLoader.js +17 -4
- package/commands/createCustomComponent/configUpdater.js +25 -21
- package/commands/createCustomComponent/fileGenerator.js +1 -1
- package/commands/createCustomComponent/main.js +15 -8
- package/commands/createCustomComponent/templates/customCrud/beforeActionButtons.vue.hbs +38 -0
- package/commands/createCustomComponent/templates/customCrud/saveButton.vue.hbs +28 -0
- package/commands/createCustomComponent/templates/login/beforeLogin.vue.hbs +18 -0
- package/commands/createPlugin/templates/custom/tsconfig.json.hbs +2 -5
- package/commands/createPlugin/templates/package.json.hbs +1 -1
- package/commands/generateModels.js +30 -22
- package/dist/auth.d.ts +9 -1
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +21 -2
- package/dist/auth.js.map +1 -1
- package/dist/dataConnectors/baseConnector.d.ts +1 -1
- package/dist/dataConnectors/baseConnector.d.ts.map +1 -1
- package/dist/dataConnectors/baseConnector.js +69 -17
- package/dist/dataConnectors/baseConnector.js.map +1 -1
- package/dist/dataConnectors/clickhouse.d.ts.map +1 -1
- package/dist/dataConnectors/clickhouse.js +15 -0
- package/dist/dataConnectors/clickhouse.js.map +1 -1
- package/dist/dataConnectors/mongo.d.ts.map +1 -1
- package/dist/dataConnectors/mongo.js +50 -15
- package/dist/dataConnectors/mongo.js.map +1 -1
- package/dist/dataConnectors/mysql.d.ts.map +1 -1
- package/dist/dataConnectors/mysql.js +11 -0
- package/dist/dataConnectors/mysql.js.map +1 -1
- package/dist/dataConnectors/postgres.d.ts.map +1 -1
- package/dist/dataConnectors/postgres.js +43 -14
- package/dist/dataConnectors/postgres.js.map +1 -1
- package/dist/dataConnectors/sqlite.d.ts.map +1 -1
- package/dist/dataConnectors/sqlite.js +11 -0
- package/dist/dataConnectors/sqlite.js.map +1 -1
- package/dist/index.d.ts +12 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +42 -21
- package/dist/index.js.map +1 -1
- package/dist/modules/codeInjector.d.ts +2 -0
- package/dist/modules/codeInjector.d.ts.map +1 -1
- package/dist/modules/codeInjector.js +67 -12
- package/dist/modules/codeInjector.js.map +1 -1
- package/dist/modules/configValidator.d.ts +6 -0
- package/dist/modules/configValidator.d.ts.map +1 -1
- package/dist/modules/configValidator.js +203 -25
- package/dist/modules/configValidator.js.map +1 -1
- package/dist/modules/restApi.d.ts +1 -1
- package/dist/modules/restApi.d.ts.map +1 -1
- package/dist/modules/restApi.js +172 -31
- package/dist/modules/restApi.js.map +1 -1
- package/dist/modules/styles.d.ts +499 -13
- package/dist/modules/styles.d.ts.map +1 -1
- package/dist/modules/styles.js +555 -31
- package/dist/modules/styles.js.map +1 -1
- package/dist/modules/utils.d.ts +7 -15
- package/dist/modules/utils.d.ts.map +1 -1
- package/dist/modules/utils.js +45 -68
- package/dist/modules/utils.js.map +1 -1
- package/dist/servers/express.d.ts +5 -0
- package/dist/servers/express.d.ts.map +1 -1
- package/dist/servers/express.js +40 -1
- package/dist/servers/express.js.map +1 -1
- package/dist/spa/index.html +1 -1
- package/dist/spa/package-lock.json +1208 -708
- package/dist/spa/package.json +34 -34
- package/dist/spa/src/App.vue +58 -173
- package/dist/spa/src/adminforth.ts +42 -18
- package/dist/spa/src/afcl/AreaChart.vue +0 -1
- package/dist/spa/src/afcl/BarChart.vue +2 -2
- package/dist/spa/src/afcl/Button.vue +6 -6
- package/dist/spa/src/afcl/ButtonGroup.vue +91 -0
- package/dist/spa/src/afcl/Card.vue +25 -0
- package/dist/spa/src/afcl/Checkbox.vue +21 -13
- package/dist/spa/src/afcl/CountryFlag.vue +4 -1
- package/dist/spa/src/{components/CustomDatePicker.vue → afcl/DatePicker.vue} +95 -9
- package/dist/spa/src/afcl/Dialog.vue +47 -27
- package/dist/spa/src/afcl/Dropzone.vue +103 -44
- package/dist/spa/src/afcl/Input.vue +18 -8
- package/dist/spa/src/afcl/JsonViewer.vue +25 -0
- package/dist/spa/src/afcl/Link.vue +1 -1
- package/dist/spa/src/afcl/LinkButton.vue +3 -3
- package/dist/spa/src/afcl/PieChart.vue +5 -5
- package/dist/spa/src/afcl/ProgressBar.vue +7 -7
- package/dist/spa/src/afcl/Select.vue +82 -34
- package/dist/spa/src/afcl/Skeleton.vue +6 -6
- package/dist/spa/src/afcl/Table.vue +309 -73
- package/dist/spa/src/afcl/Textarea.vue +31 -0
- package/dist/spa/src/afcl/Toggle.vue +32 -0
- package/dist/spa/src/afcl/Tooltip.vue +28 -18
- package/dist/spa/src/afcl/VerticalTabs.vue +16 -7
- package/dist/spa/src/afcl/index.ts +6 -3
- package/dist/spa/src/components/AcceptModal.vue +48 -14
- package/dist/spa/src/components/Breadcrumbs.vue +5 -5
- package/dist/spa/src/components/CallActionWrapper.vue +15 -0
- package/dist/spa/src/components/ColumnValueInput.vue +38 -18
- package/dist/spa/src/components/ColumnValueInputWrapper.vue +4 -3
- package/dist/spa/src/components/CustomDateRangePicker.vue +9 -8
- package/dist/spa/src/components/CustomRangePicker.vue +37 -21
- package/dist/spa/src/components/ErrorMessage.vue +21 -0
- package/dist/spa/src/components/Filters.vue +194 -131
- package/dist/spa/src/components/GroupsTable.vue +9 -8
- package/dist/spa/src/components/MenuLink.vue +90 -23
- package/dist/spa/src/components/ResourceForm.vue +94 -51
- package/dist/spa/src/components/ResourceListTable.vue +120 -90
- package/dist/spa/src/components/ResourceListTableVirtual.vue +118 -84
- package/dist/spa/src/components/ShowTable.vue +21 -15
- package/dist/spa/src/components/Sidebar.vue +470 -0
- package/dist/spa/src/components/SingleSkeletLoader.vue +6 -6
- package/dist/spa/src/components/SkeleteLoader.vue +3 -3
- package/dist/spa/src/components/ThreeDotsMenu.vue +84 -15
- package/dist/spa/src/components/Toast.vue +40 -29
- package/dist/spa/src/components/UserMenuSettingsButton.vue +69 -0
- package/dist/spa/src/components/ValueRenderer.vue +44 -17
- package/dist/spa/src/controls/BoolToggle.vue +34 -0
- package/dist/spa/src/i18n.ts +5 -3
- package/dist/spa/src/main.ts +1 -1
- package/dist/spa/src/renderers/CompactField.vue +1 -1
- package/dist/spa/src/renderers/CompactUUID.vue +1 -1
- package/dist/spa/src/router/index.ts +8 -0
- package/dist/spa/src/shims-vue.d.ts +5 -0
- package/dist/spa/src/spa_types/core.ts +13 -1
- package/dist/spa/src/stores/core.ts +13 -1
- package/dist/spa/src/stores/filters.ts +33 -2
- package/dist/spa/src/stores/modal.ts +6 -1
- package/dist/spa/src/stores/toast.ts +22 -3
- package/dist/spa/src/types/Back.ts +164 -23
- package/dist/spa/src/types/Common.ts +92 -32
- package/dist/spa/src/types/FrontendAPI.ts +31 -5
- package/dist/spa/src/types/adapters/CaptchaAdapter.ts +34 -0
- package/dist/spa/src/types/adapters/CompletionAdapter.ts +25 -0
- package/dist/spa/src/types/adapters/EmailAdapter.ts +27 -0
- package/dist/spa/src/types/adapters/ImageGenerationAdapter.ts +50 -0
- package/dist/spa/src/types/adapters/ImageVisionAdapter.ts +30 -0
- package/dist/spa/src/types/adapters/KeyValueAdapter.ts +16 -0
- package/dist/spa/src/types/adapters/OAuth2Adapter.ts +34 -0
- package/dist/spa/src/types/adapters/StorageAdapter.ts +73 -0
- package/dist/spa/src/types/adapters/index.ts +8 -0
- package/dist/spa/src/utils.ts +291 -11
- package/dist/spa/src/views/CreateView.vue +63 -21
- package/dist/spa/src/views/EditView.vue +55 -22
- package/dist/spa/src/views/ListView.vue +144 -87
- package/dist/spa/src/views/LoginView.vue +60 -55
- package/dist/spa/src/views/ResourceParent.vue +2 -2
- package/dist/spa/src/views/SettingsView.vue +121 -0
- package/dist/spa/src/views/ShowView.vue +83 -53
- package/dist/spa/src/websocket.ts +6 -1
- package/dist/spa/tsconfig.app.json +1 -1
- package/dist/spa/vite.config.ts +45 -2
- package/dist/types/Back.d.ts +147 -14
- package/dist/types/Back.d.ts.map +1 -1
- package/dist/types/Back.js +15 -0
- package/dist/types/Back.js.map +1 -1
- package/dist/types/Common.d.ts +107 -29
- package/dist/types/Common.d.ts.map +1 -1
- package/dist/types/Common.js.map +1 -1
- package/dist/types/FrontendAPI.d.ts +31 -3
- package/dist/types/FrontendAPI.d.ts.map +1 -1
- package/dist/types/FrontendAPI.js.map +1 -1
- package/dist/types/adapters/CaptchaAdapter.d.ts +30 -0
- package/dist/types/adapters/CaptchaAdapter.d.ts.map +1 -0
- package/dist/types/adapters/CaptchaAdapter.js +5 -0
- package/dist/types/adapters/CaptchaAdapter.js.map +1 -0
- package/dist/types/adapters/CompletionAdapter.d.ts +20 -0
- package/dist/types/adapters/CompletionAdapter.d.ts.map +1 -0
- package/dist/types/adapters/CompletionAdapter.js +2 -0
- package/dist/types/adapters/CompletionAdapter.js.map +1 -0
- package/dist/types/adapters/EmailAdapter.d.ts +20 -0
- package/dist/types/adapters/EmailAdapter.d.ts.map +1 -0
- package/dist/types/adapters/EmailAdapter.js +2 -0
- package/dist/types/adapters/EmailAdapter.js.map +1 -0
- package/dist/types/adapters/ImageGenerationAdapter.d.ts +37 -0
- package/dist/types/adapters/ImageGenerationAdapter.d.ts.map +1 -0
- package/dist/types/adapters/ImageGenerationAdapter.js +2 -0
- package/dist/types/adapters/ImageGenerationAdapter.js.map +1 -0
- package/dist/types/adapters/ImageVisionAdapter.d.ts +25 -0
- package/dist/types/adapters/ImageVisionAdapter.d.ts.map +1 -0
- package/dist/types/adapters/ImageVisionAdapter.js +2 -0
- package/dist/types/adapters/ImageVisionAdapter.js.map +1 -0
- package/dist/types/adapters/KeyValueAdapter.d.ts +10 -0
- package/dist/types/adapters/KeyValueAdapter.d.ts.map +1 -0
- package/dist/types/adapters/KeyValueAdapter.js +2 -0
- package/dist/types/adapters/KeyValueAdapter.js.map +1 -0
- package/dist/types/adapters/OAuth2Adapter.d.ts +32 -0
- package/dist/types/adapters/OAuth2Adapter.d.ts.map +1 -0
- package/dist/types/adapters/OAuth2Adapter.js +2 -0
- package/dist/types/adapters/OAuth2Adapter.js.map +1 -0
- package/dist/types/adapters/StorageAdapter.d.ts +63 -0
- package/dist/types/adapters/StorageAdapter.d.ts.map +1 -0
- package/dist/types/adapters/StorageAdapter.js +2 -0
- package/dist/types/adapters/StorageAdapter.js.map +1 -0
- package/dist/types/adapters/index.d.ts +9 -0
- package/dist/types/adapters/index.d.ts.map +1 -0
- package/dist/types/adapters/index.js +2 -0
- package/dist/types/adapters/index.js.map +1 -0
- package/package.json +4 -2
- package/dist/spa/src/types/Adapters.ts +0 -213
- package/dist/types/Adapters.d.ts +0 -168
- package/dist/types/Adapters.d.ts.map +0 -1
- package/dist/types/Adapters.js +0 -2
- package/dist/types/Adapters.js.map +0 -1
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="relative flex items-center justify-center min-h-screen bg-
|
|
2
|
+
<div class="relative flex items-center justify-center min-h-screen bg-lightHtml dark:bg-darkHtml w-screen h-screen"
|
|
3
3
|
:style="coreStore.config?.loginBackgroundImage && backgroundPosition === 'over' ? {
|
|
4
4
|
'background-image': 'url(' + loadFile(coreStore.config?.loginBackgroundImage) + ')',
|
|
5
5
|
'background-size': 'cover',
|
|
6
6
|
'background-position': 'center',
|
|
7
|
-
'background-blend-mode': 'darken'
|
|
7
|
+
'background-blend-mode': coreStore.config?.removeBackgroundBlendMode ? 'normal' : 'darken'
|
|
8
8
|
}: {}"
|
|
9
9
|
>
|
|
10
10
|
|
|
@@ -23,44 +23,57 @@
|
|
|
23
23
|
|
|
24
24
|
<!-- Main modal -->
|
|
25
25
|
<div id="authentication-modal" tabindex="-1"
|
|
26
|
-
class="overflow-y-auto flex flex-grow
|
|
26
|
+
class="af-login-modal overflow-y-auto flex flex-grow
|
|
27
27
|
overflow-x-hidden z-50 min-w-[350px] justify-center items-center md:inset-0 h-[calc(100%-1rem)] max-h-full">
|
|
28
28
|
<div class="relative p-4 w-full max-h-full max-w-[400px]">
|
|
29
29
|
<!-- Modal content -->
|
|
30
|
-
<div class="relative bg-
|
|
30
|
+
<div class="af-login-popup af-login-modal-content relative bg-lightLoginViewBackground rounded-lg shadow dark:bg-darkLoginViewBackground dark:shadow-black" :class=" { 'rounded-b-none overflow-hidden': error } ">
|
|
31
31
|
<!-- Modal header -->
|
|
32
|
-
<div class="flex items-center justify-between p-4 md:p-5 border-b rounded-t dark:border-gray-600">
|
|
33
|
-
|
|
32
|
+
<div class="af-login-modal-header flex items-center justify-between flex-col p-4 md:p-5 border-b rounded-t dark:border-gray-600">
|
|
33
|
+
|
|
34
|
+
<template v-if="coreStore?.config?.loginPageInjections?.panelHeader.length > 0">
|
|
35
|
+
<component
|
|
36
|
+
v-for="(c, index) in coreStore?.config?.loginPageInjections?.panelHeader || []"
|
|
37
|
+
:key="index"
|
|
38
|
+
:is="getCustomComponent(c)"
|
|
39
|
+
:meta="c.meta"
|
|
40
|
+
/>
|
|
41
|
+
</template>
|
|
42
|
+
<h3 v-else class="text-xl font-semibold text-lightLoginViewText dark:text-darkLoginViewTextColor">
|
|
34
43
|
{{ $t('Sign in to') }} {{ coreStore.config?.brandName }}
|
|
35
44
|
</h3>
|
|
36
45
|
</div>
|
|
37
46
|
<!-- Modal body -->
|
|
38
|
-
<div class="p-4 md:p-5">
|
|
47
|
+
<div class="af-login-modal-body p-4 md:p-5">
|
|
39
48
|
<form class="space-y-4" @submit.prevent>
|
|
40
49
|
<div>
|
|
41
|
-
<label for="username" class="block mb-2 text-sm font-medium text-
|
|
42
|
-
<
|
|
50
|
+
<label for="username" class="block mb-2 text-sm font-medium text-lightLoginViewText dark:text-darkLoginViewTextColor">{{ $t('Your') }} {{ coreStore.config?.usernameFieldName?.toLowerCase() }}</label>
|
|
51
|
+
<Input
|
|
52
|
+
v-model="username"
|
|
43
53
|
autocomplete="username"
|
|
44
54
|
type="username"
|
|
45
55
|
name="username"
|
|
46
56
|
id="username"
|
|
47
57
|
ref="usernameInput"
|
|
48
|
-
oninput="setCustomValidity('')"
|
|
49
58
|
@keydown.enter="passwordInput.focus()"
|
|
50
|
-
class="
|
|
59
|
+
class="w-full"
|
|
60
|
+
placeholder="name@company.com" required />
|
|
51
61
|
</div>
|
|
52
|
-
<div class="
|
|
53
|
-
<label for="password" class="block mb-2 text-sm font-medium text-
|
|
54
|
-
<
|
|
62
|
+
<div class="">
|
|
63
|
+
<label for="password" class="block mb-2 text-sm font-medium text-lightLoginViewText dark:text-darkLoginViewTextColor">{{ $t('Your password') }}</label>
|
|
64
|
+
<Input
|
|
65
|
+
v-model="password"
|
|
55
66
|
ref="passwordInput"
|
|
56
67
|
autocomplete="current-password"
|
|
57
|
-
oninput="setCustomValidity('')"
|
|
58
68
|
@keydown.enter="login"
|
|
59
|
-
:type="!showPw ? 'password': 'text'" name="password" id="password" placeholder="••••••••" class="
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
69
|
+
:type="!showPw ? 'password': 'text'" name="password" id="password" placeholder="••••••••" class="w-full" required>
|
|
70
|
+
<template #rightIcon>
|
|
71
|
+
<button type="button" @click="showPw = !showPw" class="text-lightLoginViewSubTextColor dark:text-darkLoginViewSubTextColor">
|
|
72
|
+
<IconEyeSolid class="w-5 h-5" v-if="!showPw" />
|
|
73
|
+
<IconEyeSlashSolid class="w-5 h-5" v-else />
|
|
74
|
+
</button>
|
|
75
|
+
</template>
|
|
76
|
+
</Input>
|
|
64
77
|
</div>
|
|
65
78
|
|
|
66
79
|
<div v-if="coreStore.config.rememberMeDays"
|
|
@@ -77,20 +90,11 @@
|
|
|
77
90
|
v-for="c in coreStore?.config?.loginPageInjections?.underInputs || []"
|
|
78
91
|
:is="getCustomComponent(c)"
|
|
79
92
|
:meta="c.meta"
|
|
93
|
+
@update:disableLoginButton="setDisableLoginButton($event)"
|
|
80
94
|
/>
|
|
81
|
-
|
|
82
|
-
<div v-if="error" class="flex items-center p-4 mb-4 text-sm text-red-800 rounded-lg bg-red-50 dark:bg-gray-800 dark:text-red-400" role="alert">
|
|
83
|
-
<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">
|
|
84
|
-
<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"/>
|
|
85
|
-
</svg>
|
|
86
|
-
<span class="sr-only">{{ $t('Info') }}</span>
|
|
87
|
-
<div>
|
|
88
|
-
{{ error }}
|
|
89
|
-
</div>
|
|
90
|
-
</div>
|
|
91
|
-
|
|
95
|
+
|
|
92
96
|
<div v-if="coreStore.config?.loginPromptHTML"
|
|
93
|
-
class="flex items-center p-4 mb-4 text-sm text-
|
|
97
|
+
class="flex items-center p-4 mb-4 text-sm text-lightLoginViewPromptText rounded-lg bg-lightLoginViewPromptBackground dark:bg-darkLoginViewPromptBackground dark:text-darkLoginViewPromptText" role="alert"
|
|
94
98
|
>
|
|
95
99
|
<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">
|
|
96
100
|
<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"/>
|
|
@@ -98,13 +102,19 @@
|
|
|
98
102
|
<span class="sr-only">{{ $t('Info') }}</span>
|
|
99
103
|
<div v-html="coreStore.config?.loginPromptHTML"></div>
|
|
100
104
|
</div>
|
|
101
|
-
<Button @click="login" :loader="inProgress" :disabled="inProgress" class="w-full">
|
|
105
|
+
<Button @click="login" :loader="inProgress" :disabled="inProgress || disableLoginButton" class="w-full">
|
|
102
106
|
{{ $t('Login to your account') }}
|
|
103
107
|
</Button>
|
|
108
|
+
<component
|
|
109
|
+
v-for="c in coreStore?.config?.loginPageInjections?.underLoginButton || []"
|
|
110
|
+
:is="getCustomComponent(c)"
|
|
111
|
+
:meta="c.meta"
|
|
112
|
+
@update:disableLoginButton="setDisableLoginButton($event)"
|
|
113
|
+
/>
|
|
104
114
|
</form>
|
|
105
|
-
|
|
106
115
|
</div>
|
|
107
116
|
</div>
|
|
117
|
+
<ErrorMessage v-if="error" :error="error" class="absolute left-4 right-4 rounded-t-none mb-0 shadow px-9" />
|
|
108
118
|
</div>
|
|
109
119
|
</div>
|
|
110
120
|
|
|
@@ -112,7 +122,7 @@
|
|
|
112
122
|
</template>
|
|
113
123
|
|
|
114
124
|
|
|
115
|
-
<script setup>
|
|
125
|
+
<script setup lang="ts">
|
|
116
126
|
|
|
117
127
|
import { getCustomComponent } from '@/utils';
|
|
118
128
|
import { onBeforeMount, onMounted, ref, computed } from 'vue';
|
|
@@ -121,30 +131,34 @@ import { useUserStore } from '@/stores/user';
|
|
|
121
131
|
import { IconEyeSolid, IconEyeSlashSolid } from '@iconify-prerendered/vue-flowbite';
|
|
122
132
|
import { callAdminForthApi, loadFile } from '@/utils';
|
|
123
133
|
import { useRoute, useRouter } from 'vue-router';
|
|
124
|
-
import { Button, Checkbox } from '@/afcl';
|
|
134
|
+
import { Button, Checkbox, Input } from '@/afcl';
|
|
125
135
|
import { useI18n } from 'vue-i18n';
|
|
136
|
+
import ErrorMessage from '@/components/ErrorMessage.vue';
|
|
126
137
|
|
|
127
138
|
const { t } = useI18n();
|
|
128
139
|
|
|
129
140
|
const passwordInput = ref(null);
|
|
130
141
|
const usernameInput = ref(null);
|
|
131
142
|
const rememberMeValue= ref(false);
|
|
143
|
+
const username = ref('');
|
|
144
|
+
const password = ref('');
|
|
132
145
|
|
|
133
146
|
const route = useRoute();
|
|
134
147
|
const router = useRouter();
|
|
135
148
|
const inProgress = ref(false);
|
|
136
|
-
|
|
137
149
|
const coreStore = useCoreStore();
|
|
138
150
|
const user = useUserStore();
|
|
139
151
|
|
|
140
152
|
const showPw = ref(false);
|
|
141
153
|
|
|
142
154
|
const error = ref(null);
|
|
155
|
+
const disableLoginButton = ref(false);
|
|
143
156
|
|
|
144
157
|
const backgroundPosition = computed(() => {
|
|
145
158
|
return coreStore.config?.loginBackgroundPosition || '1/2';
|
|
146
159
|
});
|
|
147
160
|
|
|
161
|
+
|
|
148
162
|
onBeforeMount(() => {
|
|
149
163
|
if (localStorage.getItem('isAuthorized') === 'true') {
|
|
150
164
|
// if route has next param, redirect
|
|
@@ -158,29 +172,17 @@ onBeforeMount(() => {
|
|
|
158
172
|
})
|
|
159
173
|
|
|
160
174
|
onMounted(async () => {
|
|
175
|
+
coreStore.getLoginFormConfig();
|
|
161
176
|
if (coreStore.config?.demoCredentials) {
|
|
162
|
-
const [
|
|
163
|
-
|
|
164
|
-
|
|
177
|
+
const [demoUsername, demoPassword] = coreStore.config.demoCredentials.split(':');
|
|
178
|
+
username.value = demoUsername;
|
|
179
|
+
password.value = demoPassword;
|
|
165
180
|
}
|
|
166
181
|
usernameInput.value.focus();
|
|
167
182
|
});
|
|
168
183
|
|
|
169
184
|
|
|
170
185
|
async function login() {
|
|
171
|
-
|
|
172
|
-
const username = usernameInput.value.value;
|
|
173
|
-
const password = passwordInput.value.value;
|
|
174
|
-
|
|
175
|
-
if (!username) {
|
|
176
|
-
usernameInput.value.setCustomValidity(t('Please fill out this field.'));
|
|
177
|
-
return;
|
|
178
|
-
}
|
|
179
|
-
if (!password) {
|
|
180
|
-
passwordInput.value.setCustomValidity(t('Please fill out this field.'));
|
|
181
|
-
return;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
186
|
if (inProgress.value) {
|
|
185
187
|
return;
|
|
186
188
|
}
|
|
@@ -189,8 +191,8 @@ async function login() {
|
|
|
189
191
|
path: '/login',
|
|
190
192
|
method: 'POST',
|
|
191
193
|
body: {
|
|
192
|
-
username,
|
|
193
|
-
password,
|
|
194
|
+
username: username.value,
|
|
195
|
+
password: password.value,
|
|
194
196
|
rememberMe: rememberMeValue.value,
|
|
195
197
|
}
|
|
196
198
|
});
|
|
@@ -206,5 +208,8 @@ async function login() {
|
|
|
206
208
|
|
|
207
209
|
}
|
|
208
210
|
|
|
211
|
+
function setDisableLoginButton(value: boolean) {
|
|
212
|
+
disableLoginButton.value = value;
|
|
213
|
+
}
|
|
209
214
|
|
|
210
215
|
</script>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div :key="`${$route?.params.resourceId}---${$route?.params.primaryKey}`" class="p-4 flex"
|
|
2
|
+
<div :key="`${$route?.params.resourceId}---${$route?.params.primaryKey}`" class="af-resource-parent p-4 flex"
|
|
3
3
|
:class="limitHeightToPage ? 'h-[calc(100dvh-3.5rem)]': undefined"
|
|
4
4
|
>
|
|
5
5
|
<RouterView/>
|
|
@@ -33,7 +33,7 @@ const limitHeightToPage = computed(() => {
|
|
|
33
33
|
}
|
|
34
34
|
const listPageInjects = coreStore.resource.options.pageInjections.list;
|
|
35
35
|
|
|
36
|
-
for (const pi of [listPageInjects.beforeBreadcrumbs, listPageInjects.afterBreadcrumbs, listPageInjects.bottom]) {
|
|
36
|
+
for (const pi of [listPageInjects.beforeBreadcrumbs, listPageInjects.beforeActionButtons, listPageInjects.afterBreadcrumbs, listPageInjects.bottom]) {
|
|
37
37
|
if (pi) {
|
|
38
38
|
for (const piItem of pi) {
|
|
39
39
|
if (!piItem.meta?.thinEnoughToShrinkTable) {
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="mt-20 h-full w-full" :class="{ 'hidden': initialTabSet === false }">
|
|
3
|
+
<div v-if="!coreStore?.config?.settingPages || coreStore?.config?.settingPages.length === 0">
|
|
4
|
+
<p>{{ $t('No setting pages configured or still loading...') }}</p>
|
|
5
|
+
</div>
|
|
6
|
+
<VerticalTabs v-else ref="VerticalTabsRef" v-model:active-tab="activeTab" @update:active-tab="setURL({slug: $event, pageLabel: ''})">
|
|
7
|
+
<template v-for="(c,i) in coreStore?.config?.settingPages" :key="`tab:${settingPageSlotName(c,i)}`" v-slot:['tab:'+c.slug]>
|
|
8
|
+
<div class="flex items-center justify-center whitespace-nowrap w-full px-4 gap-2" @click="setURL(c)">
|
|
9
|
+
<component v-if="c.icon" :is="getIcon(c.icon)" class="w-5 h-5 group-hover:text-lightSidebarIconsHover transition duration-75 dark:group-hover:text-darkSidebarIconsHover dark:text-darkSidebarIcons" ></component>
|
|
10
|
+
{{ c.pageLabel }}
|
|
11
|
+
</div>
|
|
12
|
+
</template>
|
|
13
|
+
|
|
14
|
+
<template v-for="(c,i) in coreStore?.config?.settingPages" :key="`${settingPageSlotName(c,i)}-content`" v-slot:[c.slug]>
|
|
15
|
+
<component
|
|
16
|
+
:is="getCustomComponent({file: c.component || ''})"
|
|
17
|
+
:resource="coreStore.resource"
|
|
18
|
+
:adminUser="coreStore.adminUser"
|
|
19
|
+
/>
|
|
20
|
+
</template>
|
|
21
|
+
</VerticalTabs>
|
|
22
|
+
</div>
|
|
23
|
+
</template>
|
|
24
|
+
|
|
25
|
+
<script setup lang="ts">
|
|
26
|
+
import { ref, onMounted, watch } from 'vue';
|
|
27
|
+
import { useRouter } from 'vue-router';
|
|
28
|
+
import { useCoreStore } from '@/stores/core';
|
|
29
|
+
import { getCustomComponent, getIcon } from '@/utils';
|
|
30
|
+
import { Dropdown } from 'flowbite';
|
|
31
|
+
import adminforth from '@/adminforth';
|
|
32
|
+
import { VerticalTabs } from '@/afcl'
|
|
33
|
+
import { useRoute } from 'vue-router'
|
|
34
|
+
|
|
35
|
+
const route = useRoute()
|
|
36
|
+
const coreStore = useCoreStore();
|
|
37
|
+
const router = useRouter();
|
|
38
|
+
|
|
39
|
+
const routerIsReady = ref(false);
|
|
40
|
+
const loginRedirectCheckIsReady = ref(false);
|
|
41
|
+
const dropdownUserButton = ref<HTMLElement | null>(null);
|
|
42
|
+
const VerticalTabsRef = ref();
|
|
43
|
+
const activeTab = ref('');
|
|
44
|
+
const initialTabSet = ref(false);
|
|
45
|
+
|
|
46
|
+
watch(() => route?.params?.page, (val) => {
|
|
47
|
+
handleURLChange(val as string | null);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
async function initRouter() {
|
|
51
|
+
await router.isReady();
|
|
52
|
+
routerIsReady.value = true;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
watch(dropdownUserButton, (el) => {
|
|
56
|
+
if (el) {
|
|
57
|
+
const dd = new Dropdown(
|
|
58
|
+
document.querySelector('#dropdown-user') as HTMLElement,
|
|
59
|
+
document.querySelector('[data-dropdown-toggle="dropdown-user"]') as HTMLElement,
|
|
60
|
+
);
|
|
61
|
+
adminforth.closeUserMenuDropdown = () => dd.hide();
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
onMounted(async () => {
|
|
66
|
+
if (coreStore.adminUser) {
|
|
67
|
+
await loadMenu();
|
|
68
|
+
loginRedirectCheckIsReady.value = true;
|
|
69
|
+
const routeParamsPage = route?.params?.page;
|
|
70
|
+
if (!routeParamsPage) {
|
|
71
|
+
if (coreStore.config?.settingPages?.[0]) {
|
|
72
|
+
setURL(coreStore.config.settingPages[0]);
|
|
73
|
+
}
|
|
74
|
+
} else {
|
|
75
|
+
handleURLChange(routeParamsPage as string | null);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
async function loadMenu() {
|
|
81
|
+
await initRouter();
|
|
82
|
+
await coreStore.fetchMenuAndResource();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function slugifyString(str: string): string {
|
|
86
|
+
return str
|
|
87
|
+
.toString()
|
|
88
|
+
.toLowerCase()
|
|
89
|
+
.replace(/\s+/g, '-')
|
|
90
|
+
.replace(/[^a-z0-9-_]/g, '-');
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function setURL(item: {
|
|
94
|
+
pageLabel: string;
|
|
95
|
+
slug?: string | undefined;
|
|
96
|
+
}) {
|
|
97
|
+
router.replace({
|
|
98
|
+
name: 'settings',
|
|
99
|
+
params: { page: item?.slug }
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function handleURLChange(val: string | null) {
|
|
104
|
+
let isParamInTabs;
|
|
105
|
+
for (const c of coreStore?.config?.settingPages || []) {
|
|
106
|
+
if (c.slug ? c.slug === val : slugifyString(c.pageLabel) === val) {
|
|
107
|
+
isParamInTabs = true;
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
if (isParamInTabs) {
|
|
112
|
+
VerticalTabsRef.value.setActiveTab(val);
|
|
113
|
+
activeTab.value = val as string;
|
|
114
|
+
if (!initialTabSet.value) initialTabSet.value = true;
|
|
115
|
+
} else {
|
|
116
|
+
if (coreStore.config?.settingPages?.[0]) {
|
|
117
|
+
setURL(coreStore.config.settingPages[0]);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
</script>
|
|
@@ -4,52 +4,60 @@
|
|
|
4
4
|
v-if="!loading"
|
|
5
5
|
v-for="c in coreStore?.resourceOptions?.pageInjections?.show?.beforeBreadcrumbs || []"
|
|
6
6
|
:is="getCustomComponent(c)"
|
|
7
|
-
:meta="c.meta"
|
|
7
|
+
:meta="(c as AdminForthComponentDeclarationFull).meta"
|
|
8
8
|
:record="coreStore.record"
|
|
9
9
|
:resource="coreStore.resource"
|
|
10
10
|
:adminUser="coreStore.adminUser"
|
|
11
11
|
/>
|
|
12
12
|
<BreadcrumbsWithButtons>
|
|
13
13
|
<template v-if="coreStore.resource?.options?.actions">
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
14
|
+
|
|
15
|
+
<template v-for="action in coreStore.resource.options.actions.filter(a => a.showIn?.showButton)" :key="action.id">
|
|
16
|
+
<component
|
|
17
|
+
:is="action?.customComponent ? getCustomComponent(action.customComponent) : CallActionWrapper"
|
|
18
|
+
:meta="action.customComponent?.meta"
|
|
19
|
+
@callAction="(payload?) => startCustomAction(action.id, payload)"
|
|
20
|
+
:disabled="actionLoadingStates[action.id]"
|
|
21
|
+
>
|
|
22
|
+
<button
|
|
23
|
+
:key="action.id"
|
|
24
|
+
:disabled="actionLoadingStates[action.id!]"
|
|
25
|
+
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-lightPrimary 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
|
+
<component
|
|
28
|
+
v-if="action.icon"
|
|
29
|
+
:is="getIcon(action.icon)"
|
|
30
|
+
class="w-4 h-4 me-2 text-lightPrimary dark:text-darkPrimary"
|
|
31
|
+
/>
|
|
32
|
+
{{ action.name }}
|
|
33
|
+
</button>
|
|
34
|
+
</component>
|
|
35
|
+
</template>
|
|
28
36
|
</template>
|
|
29
37
|
<RouterLink v-if="coreStore.resource?.options?.allowedActions?.create"
|
|
30
38
|
:to="{ name: 'resource-create', params: { resourceId: $route.params.resourceId } }"
|
|
31
|
-
class="flex items-center py-1 px-3 text-sm font-medium text-
|
|
39
|
+
class="af-add-new-button flex items-center py-1 px-3 text-sm font-medium text-lightShowViewButtonText focus:outline-none bg-lightShowViewButtonBackground rounded border border-lightShowViewButtonBorder hover:bg-lightShowViewButtonBackgroundHover hover:text-lightShowViewButtonTextHover focus:z-10 focus:ring-4 focus:ring-lightShowViewButtonFocusRing dark:focus:ring-darkShowViewButtonFocusRing dark:bg-darkShowViewButtonBackground dark:text-darkShowViewButtonText dark:border-darkShowViewButtonBorder dark:hover:text-darkShowViewButtonTextHover dark:hover:bg-darkShowViewButtonBackgroundHover rounded-default gap-1"
|
|
32
40
|
>
|
|
33
|
-
<IconPlusOutline class="w-4 h-4
|
|
41
|
+
<IconPlusOutline class="w-4 h-4"/>
|
|
34
42
|
{{ $t('Add new') }}
|
|
35
43
|
</RouterLink>
|
|
36
44
|
|
|
37
45
|
<RouterLink v-if="coreStore?.resourceOptions?.allowedActions?.edit" :to="{ name: 'resource-edit', params: { resourceId: $route.params.resourceId, primaryKey: $route.params.primaryKey } }"
|
|
38
|
-
class="flex items-center py-1 px-3 text-sm font-medium text-
|
|
46
|
+
class="flex items-center af-edit-button py-1 px-3 text-sm font-medium text-lightShowViewButtonText focus:outline-none bg-lightShowViewButtonBackground rounded-default border border-lightShowViewButtonBorder hover:bg-lightShowViewButtonBackgroundHover hover:text-lightShowViewButtonTextHover focus:z-10 focus:ring-4 focus:ring-lightShowViewButtonFocusRing dark:focus:ring-darkShowViewButtonFocusRing dark:bg-darkShowViewButtonBackground dark:text-darkShowViewButtonText dark:border-darkShowViewButtonBorder dark:hover:text-darkShowViewButtonTextHover dark:hover:bg-darkShowViewButtonBackgroundHover gap-1"
|
|
39
47
|
>
|
|
40
48
|
<IconPenSolid class="w-4 h-4" />
|
|
41
49
|
{{ $t('Edit') }}
|
|
42
50
|
</RouterLink>
|
|
43
51
|
|
|
44
52
|
<button v-if="coreStore?.resourceOptions?.allowedActions?.delete" @click="deleteRecord"
|
|
45
|
-
class="flex items-center py-1 px-3 text-sm font-medium rounded-default text-red-600 focus:outline-none bg-
|
|
53
|
+
class="flex items-center af-delete-button py-1 px-3 text-sm font-medium rounded-default text-red-600 focus:outline-none bg-lightShowViewButtonBackground border border-lightShowViewButtonBorder hover:bg-lightShowViewButtonBackgroundHover hover:text-red-700 focus:z-10 focus:ring-4 focus:ring-lightShowViewButtonFocusRing dark:focus:ring-darkShowViewButtonFocusRing dark:bg-darkShowViewButtonBackground dark:text-red-500 dark:border-darkShowViewButtonBorder dark:hover:text-darkShowViewButtonTextHover dark:hover:bg-darkShowViewButtonBackgroundHover gap-1"
|
|
46
54
|
>
|
|
47
55
|
<IconTrashBinSolid class="w-4 h-4" />
|
|
48
56
|
{{ $t('Delete') }}
|
|
49
57
|
</button>
|
|
50
58
|
|
|
51
59
|
<ThreeDotsMenu
|
|
52
|
-
:threeDotsDropdownItems="coreStore.resourceOptions?.pageInjections?.show?.threeDotsDropdownItems"
|
|
60
|
+
:threeDotsDropdownItems="(coreStore.resourceOptions?.pageInjections?.show?.threeDotsDropdownItems as [])"
|
|
53
61
|
:customActions="customActions"
|
|
54
62
|
></ThreeDotsMenu>
|
|
55
63
|
</BreadcrumbsWithButtons>
|
|
@@ -57,7 +65,7 @@
|
|
|
57
65
|
<component
|
|
58
66
|
v-for="c in coreStore?.resourceOptions?.pageInjections?.show?.afterBreadcrumbs || []"
|
|
59
67
|
:is="getCustomComponent(c)"
|
|
60
|
-
:meta="c.meta"
|
|
68
|
+
:meta="(c as AdminForthComponentDeclarationFull).meta"
|
|
61
69
|
:record="coreStore.record"
|
|
62
70
|
:resource="coreStore.resource"
|
|
63
71
|
:adminUser="coreStore.adminUser"
|
|
@@ -76,11 +84,11 @@
|
|
|
76
84
|
v-else-if="coreStore.record"
|
|
77
85
|
class="relative w-full flex flex-col gap-4"
|
|
78
86
|
>
|
|
79
|
-
<div v-if="!groups.length && allColumns
|
|
87
|
+
<div v-if="!groups.length && allColumns?.length">
|
|
80
88
|
<ShowTable
|
|
81
|
-
:columns="allColumns"
|
|
82
89
|
:resource="coreStore.resource"
|
|
83
90
|
:record="coreStore.record"
|
|
91
|
+
:columns="allColumns as Array<{ name: string; label?: string; components?: any }>"
|
|
84
92
|
/>
|
|
85
93
|
</div>
|
|
86
94
|
<template v-else>
|
|
@@ -93,12 +101,12 @@
|
|
|
93
101
|
:record="coreStore.record"
|
|
94
102
|
/>
|
|
95
103
|
</template>
|
|
96
|
-
<template v-if="otherColumns.length > 0">
|
|
104
|
+
<template v-if="otherColumns && otherColumns.length > 0">
|
|
97
105
|
<ShowTable
|
|
98
|
-
:columns="otherColumns"
|
|
99
106
|
groupName="Other Fields"
|
|
100
107
|
:resource="coreStore.resource"
|
|
101
108
|
:record="coreStore.record"
|
|
109
|
+
:columns="otherColumns as Array<{ name: string; label?: string; components?: any }>"
|
|
102
110
|
/>
|
|
103
111
|
</template>
|
|
104
112
|
</template>
|
|
@@ -112,8 +120,7 @@
|
|
|
112
120
|
v-if="!loading"
|
|
113
121
|
v-for="c in coreStore?.resourceOptions?.pageInjections?.show?.bottom || []"
|
|
114
122
|
:is="getCustomComponent(c)"
|
|
115
|
-
:meta="c.meta"
|
|
116
|
-
:column="column"
|
|
123
|
+
:meta="(c as AdminForthComponentDeclarationFull).meta"
|
|
117
124
|
:record="coreStore.record"
|
|
118
125
|
:resource="coreStore.resource"
|
|
119
126
|
:adminUser="coreStore.adminUser"
|
|
@@ -140,6 +147,8 @@ import ShowTable from '@/components/ShowTable.vue';
|
|
|
140
147
|
import adminforth from "@/adminforth";
|
|
141
148
|
import { useI18n } from 'vue-i18n';
|
|
142
149
|
import { getIcon } from '@/utils';
|
|
150
|
+
import { type AdminForthComponentDeclarationFull } from '@/types/Common.js';
|
|
151
|
+
import CallActionWrapper from '@/components/CallActionWrapper.vue'
|
|
143
152
|
|
|
144
153
|
const route = useRoute();
|
|
145
154
|
const router = useRouter();
|
|
@@ -147,62 +156,65 @@ const loading = ref(true);
|
|
|
147
156
|
const { t } = useI18n();
|
|
148
157
|
const coreStore = useCoreStore();
|
|
149
158
|
|
|
150
|
-
const actionLoadingStates = ref({});
|
|
159
|
+
const actionLoadingStates = ref<Record<string, boolean>>({});
|
|
151
160
|
|
|
152
161
|
const customActions = computed(() => {
|
|
153
|
-
return coreStore.resource?.options?.actions?.filter(a => a.showIn?.showThreeDotsMenu) || [];
|
|
162
|
+
return coreStore.resource?.options?.actions?.filter((a: any) => a.showIn?.showThreeDotsMenu) || [];
|
|
154
163
|
});
|
|
155
164
|
|
|
156
165
|
onMounted(async () => {
|
|
157
166
|
loading.value = true;
|
|
158
167
|
await coreStore.fetchResourceFull({
|
|
159
|
-
resourceId: route.params.resourceId
|
|
168
|
+
resourceId: route.params.resourceId as string,
|
|
160
169
|
});
|
|
161
170
|
initThreeDotsDropdown();
|
|
162
171
|
await coreStore.fetchRecord({
|
|
163
|
-
resourceId: route.params.resourceId,
|
|
164
|
-
primaryKey: route.params.primaryKey,
|
|
172
|
+
resourceId: route.params.resourceId as string,
|
|
173
|
+
primaryKey: route.params.primaryKey as string,
|
|
165
174
|
source: 'show',
|
|
166
175
|
});
|
|
167
|
-
|
|
176
|
+
if(coreStore.resourceOptions){
|
|
177
|
+
checkAcessByAllowedActions(coreStore.resourceOptions.allowedActions,'show');
|
|
178
|
+
}
|
|
168
179
|
loading.value = false;
|
|
169
180
|
});
|
|
170
181
|
|
|
171
182
|
const groups = computed(() => {
|
|
172
183
|
let fieldGroupType;
|
|
173
|
-
if (coreStore.resource
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
184
|
+
if (coreStore.resource) {
|
|
185
|
+
if (coreStore.resource.options?.showFieldGroups) {
|
|
186
|
+
fieldGroupType = coreStore.resource.options.showFieldGroups;
|
|
187
|
+
} else if (coreStore.resource.options?.showFieldGroups === null) {
|
|
188
|
+
fieldGroupType = [];
|
|
189
|
+
} else {
|
|
190
|
+
fieldGroupType = coreStore.resource.options?.fieldGroups;
|
|
191
|
+
}
|
|
179
192
|
}
|
|
193
|
+
const activeGroups: typeof fieldGroupType | [] = fieldGroupType ?? [];
|
|
180
194
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
return activeGroups.map(group => ({
|
|
195
|
+
return activeGroups.map((group: FieldGroup) => ({
|
|
184
196
|
...group,
|
|
185
|
-
columns: coreStore.resource
|
|
186
|
-
col => group.columns.includes(col.name) && col.showIn
|
|
197
|
+
columns: coreStore.resource?.columns.filter(
|
|
198
|
+
col => group.columns.includes(col.name) && col.showIn?.show
|
|
187
199
|
),
|
|
188
200
|
}));
|
|
189
201
|
});
|
|
190
202
|
|
|
191
203
|
const allColumns = computed(() => {
|
|
192
|
-
return coreStore.resource
|
|
204
|
+
return coreStore.resource?.columns.filter(col => col.showIn?.show);
|
|
193
205
|
});
|
|
194
206
|
|
|
195
207
|
const otherColumns = computed(() => {
|
|
196
208
|
const groupedColumnNames = new Set(
|
|
197
|
-
groups.value.flatMap(group => group.columns.map(col => col.name))
|
|
209
|
+
groups.value.flatMap(group => group.columns.map((col: AdminForthResourceColumnCommon) => col.name))
|
|
198
210
|
);
|
|
199
211
|
|
|
200
|
-
return coreStore.resource
|
|
201
|
-
col => !groupedColumnNames.has(col.name) && col.showIn
|
|
212
|
+
return coreStore.resource?.columns.filter(
|
|
213
|
+
col => !groupedColumnNames.has(col.name) && col.showIn?.show
|
|
202
214
|
);
|
|
203
215
|
});
|
|
204
216
|
|
|
205
|
-
async function deleteRecord(
|
|
217
|
+
async function deleteRecord() {
|
|
206
218
|
const data = await adminforth.confirm({
|
|
207
219
|
message: t('Are you sure you want to delete this item?'),
|
|
208
220
|
yes: t('Delete'),
|
|
@@ -231,7 +243,7 @@ async function deleteRecord(row) {
|
|
|
231
243
|
|
|
232
244
|
}
|
|
233
245
|
|
|
234
|
-
async function startCustomAction(actionId) {
|
|
246
|
+
async function startCustomAction(actionId: string, extra: any) {
|
|
235
247
|
actionLoadingStates.value[actionId] = true;
|
|
236
248
|
|
|
237
249
|
const data = await callAdminForthApi({
|
|
@@ -240,7 +252,8 @@ async function startCustomAction(actionId) {
|
|
|
240
252
|
body: {
|
|
241
253
|
resourceId: route.params.resourceId,
|
|
242
254
|
actionId: actionId,
|
|
243
|
-
recordId: route.params.primaryKey
|
|
255
|
+
recordId: route.params.primaryKey,
|
|
256
|
+
extra: extra,
|
|
244
257
|
}
|
|
245
258
|
});
|
|
246
259
|
|
|
@@ -263,8 +276,8 @@ async function startCustomAction(actionId) {
|
|
|
263
276
|
|
|
264
277
|
if (data?.ok) {
|
|
265
278
|
await coreStore.fetchRecord({
|
|
266
|
-
resourceId: route.params.resourceId,
|
|
267
|
-
primaryKey: route.params.primaryKey,
|
|
279
|
+
resourceId: route.params.resourceId as string,
|
|
280
|
+
primaryKey: route.params.primaryKey as string,
|
|
268
281
|
source: 'show',
|
|
269
282
|
});
|
|
270
283
|
|
|
@@ -281,4 +294,21 @@ async function startCustomAction(actionId) {
|
|
|
281
294
|
}
|
|
282
295
|
}
|
|
283
296
|
|
|
297
|
+
adminforth.show.refresh = () => {
|
|
298
|
+
(async () => {
|
|
299
|
+
try {
|
|
300
|
+
loading.value = true;
|
|
301
|
+
await coreStore.fetchRecord({
|
|
302
|
+
resourceId: String(route.params.resourceId),
|
|
303
|
+
primaryKey: String(route.params.primaryKey),
|
|
304
|
+
source: 'show',
|
|
305
|
+
});
|
|
306
|
+
} catch (e) {
|
|
307
|
+
showErrorTost((e as Error).message);
|
|
308
|
+
} finally {
|
|
309
|
+
loading.value = false;
|
|
310
|
+
}
|
|
311
|
+
})();
|
|
312
|
+
}
|
|
313
|
+
|
|
284
314
|
</script>
|