adminforth 1.1.74 → 1.1.76
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/auth.ts +14 -0
- package/dataConnectors/postgres.ts +1 -1
- package/dist/auth.js +7 -0
- package/dist/index.js +117 -65
- package/dist/modules/codeInjector.js +29 -15
- package/dist/modules/utils.js +1 -1
- package/dist/plugins/AuditLogPlugin/index.js +2 -17
- package/dist/plugins/S3UploadPlugin/custom/s3uploader.vue +120 -0
- package/dist/plugins/S3UploadPlugin/index.js +103 -0
- package/dist/plugins/S3UploadPlugin/package-lock.json +431 -0
- package/dist/plugins/S3UploadPlugin/package.json +16 -0
- package/dist/plugins/TwoFactorsAuthPlugin/custom/TwoFactorsConfirmation.vue +152 -0
- package/dist/plugins/TwoFactorsAuthPlugin/custom/TwoFactorsOtp.vue +0 -0
- package/dist/plugins/TwoFactorsAuthPlugin/custom/TwoFactorsSetup.vue +188 -0
- package/dist/plugins/TwoFactorsAuthPlugin/index.js +150 -0
- package/dist/plugins/TwoFactorsAuthPlugin/node_modules/.package-lock.json +61 -0
- package/dist/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/LICENSE +21 -0
- package/dist/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/README.md +15 -0
- package/dist/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/package.json +217 -0
- package/dist/plugins/TwoFactorsAuthPlugin/node_modules/@types/notp/LICENSE +21 -0
- package/dist/plugins/TwoFactorsAuthPlugin/node_modules/@types/notp/README.md +15 -0
- package/dist/plugins/TwoFactorsAuthPlugin/node_modules/@types/notp/package.json +21 -0
- package/dist/plugins/TwoFactorsAuthPlugin/node_modules/node-2fa/LICENSE +201 -0
- package/dist/plugins/TwoFactorsAuthPlugin/node_modules/node-2fa/README.md +68 -0
- package/dist/plugins/TwoFactorsAuthPlugin/node_modules/node-2fa/dist/index.js +51 -0
- package/dist/plugins/TwoFactorsAuthPlugin/node_modules/node-2fa/dist/interfaces.js +2 -0
- package/dist/plugins/TwoFactorsAuthPlugin/node_modules/node-2fa/package.json +58 -0
- package/dist/plugins/TwoFactorsAuthPlugin/node_modules/notp/.travis.yml +6 -0
- package/dist/plugins/TwoFactorsAuthPlugin/node_modules/notp/LICENSE +22 -0
- package/dist/plugins/TwoFactorsAuthPlugin/node_modules/notp/Readme.md +135 -0
- package/dist/plugins/TwoFactorsAuthPlugin/node_modules/notp/examples/TOTP-verify.js +33 -0
- package/dist/plugins/TwoFactorsAuthPlugin/node_modules/notp/examples/TOTP.js +15 -0
- package/dist/plugins/TwoFactorsAuthPlugin/node_modules/notp/index.js +221 -0
- package/dist/plugins/TwoFactorsAuthPlugin/node_modules/notp/package.json +22 -0
- package/dist/plugins/TwoFactorsAuthPlugin/node_modules/notp/test/mocha.opts +1 -0
- package/dist/plugins/TwoFactorsAuthPlugin/node_modules/notp/test/notp.js +217 -0
- package/dist/plugins/TwoFactorsAuthPlugin/node_modules/thirty-two/LICENSE.txt +19 -0
- package/dist/plugins/TwoFactorsAuthPlugin/node_modules/thirty-two/Makefile +24 -0
- package/dist/plugins/TwoFactorsAuthPlugin/node_modules/thirty-two/README.md +15 -0
- package/dist/plugins/TwoFactorsAuthPlugin/node_modules/thirty-two/index.js +23 -0
- package/dist/plugins/TwoFactorsAuthPlugin/node_modules/thirty-two/lib/thirty-two/index.js +26 -0
- package/dist/plugins/TwoFactorsAuthPlugin/node_modules/thirty-two/lib/thirty-two/thirty-two.js +128 -0
- package/dist/plugins/TwoFactorsAuthPlugin/node_modules/thirty-two/package.json +15 -0
- package/dist/plugins/TwoFactorsAuthPlugin/node_modules/thirty-two/spec/thirty-two_spec.js +63 -0
- package/dist/plugins/TwoFactorsAuthPlugin/node_modules/tslib/CopyrightNotice.txt +15 -0
- package/dist/plugins/TwoFactorsAuthPlugin/node_modules/tslib/LICENSE.txt +12 -0
- package/dist/plugins/TwoFactorsAuthPlugin/node_modules/tslib/README.md +164 -0
- package/dist/plugins/TwoFactorsAuthPlugin/node_modules/tslib/SECURITY.md +41 -0
- package/dist/plugins/TwoFactorsAuthPlugin/node_modules/tslib/modules/index.js +68 -0
- package/dist/plugins/TwoFactorsAuthPlugin/node_modules/tslib/modules/package.json +3 -0
- package/dist/plugins/TwoFactorsAuthPlugin/node_modules/tslib/package.json +47 -0
- package/dist/plugins/TwoFactorsAuthPlugin/node_modules/tslib/tslib.es6.html +1 -0
- package/dist/plugins/TwoFactorsAuthPlugin/node_modules/tslib/tslib.es6.js +374 -0
- package/dist/plugins/TwoFactorsAuthPlugin/node_modules/tslib/tslib.es6.mjs +373 -0
- package/dist/plugins/TwoFactorsAuthPlugin/node_modules/tslib/tslib.html +1 -0
- package/dist/plugins/TwoFactorsAuthPlugin/node_modules/tslib/tslib.js +424 -0
- package/dist/plugins/TwoFactorsAuthPlugin/node_modules/undici-types/README.md +6 -0
- package/dist/plugins/TwoFactorsAuthPlugin/node_modules/undici-types/package.json +55 -0
- package/dist/plugins/TwoFactorsAuthPlugin/package-lock.json +69 -0
- package/dist/plugins/TwoFactorsAuthPlugin/package.json +15 -0
- package/dist/plugins/TwoFactorsAuthPlugin/types.js +1 -0
- package/dist/spa/index.html +1 -1
- package/dist/spa/package-lock.json +111 -0
- package/dist/spa/package.json +1 -0
- package/dist/spa/spa/src/App.vue +154 -121
- package/dist/spa/spa/src/components/ResourceForm.vue +91 -91
- package/dist/spa/spa/src/router/index.ts +0 -1
- package/dist/spa/spa/src/utils.ts +1 -1
- package/dist/spa/spa/src/views/CreateView.vue +0 -1
- package/dist/spa/spa/src/views/LoginView.vue +4 -1
- package/dist/spa/src/App.vue +178 -133
- package/dist/spa/src/components/MenuLink.vue +3 -3
- package/dist/spa/src/components/ResourceForm.vue +96 -96
- package/dist/spa/src/components/ResourceListTable.vue +69 -84
- package/dist/spa/src/components/SkeleteLoader.vue +23 -0
- package/dist/spa/src/components/ValueRenderer.vue +2 -3
- package/dist/spa/src/composables/useStores.ts +24 -11
- package/dist/spa/src/main.ts +1 -1
- package/dist/spa/src/router/index.ts +0 -1
- package/dist/spa/src/utils.ts +1 -1
- package/dist/spa/src/views/CreateView.vue +1 -9
- package/dist/spa/src/views/EditView.vue +1 -9
- package/dist/spa/src/views/ListView.vue +12 -3
- package/dist/spa/src/views/LoginView.vue +6 -1
- package/dist/spa/src/views/ResourceParent.vue +1 -2
- package/dist/spa/src/views/ShowView.vue +6 -14
- package/dist/spa/tailwind.config.js +3 -1
- package/index.ts +94 -35
- package/modules/codeInjector.ts +38 -27
- package/modules/utils.ts +1 -1
- package/package.json +1 -1
- package/plugins/AuditLogPlugin/index.ts +4 -20
- package/plugins/S3UploadPlugin/custom/s3uploader.vue +120 -0
- package/plugins/S3UploadPlugin/index.ts +112 -0
- package/plugins/S3UploadPlugin/package-lock.json +431 -0
- package/plugins/S3UploadPlugin/package.json +16 -0
- package/plugins/S3UploadPlugin/types.ts +76 -0
- package/plugins/TwoFactorsAuthPlugin/custom/TwoFactorsConfirmation.vue +152 -0
- package/plugins/TwoFactorsAuthPlugin/custom/TwoFactorsOtp.vue +0 -0
- package/plugins/TwoFactorsAuthPlugin/custom/TwoFactorsSetup.vue +188 -0
- package/plugins/TwoFactorsAuthPlugin/index.ts +150 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/.package-lock.json +61 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/LICENSE +21 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/README.md +15 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/assert/strict.d.ts +8 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/assert.d.ts +1040 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/async_hooks.d.ts +541 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/buffer.d.ts +2363 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/child_process.d.ts +1544 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/cluster.d.ts +578 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/console.d.ts +452 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/constants.d.ts +19 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/crypto.d.ts +4523 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/dgram.d.ts +596 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/diagnostics_channel.d.ts +554 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/dns/promises.d.ts +476 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/dns.d.ts +864 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/dom-events.d.ts +124 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/domain.d.ts +170 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/events.d.ts +931 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/fs/promises.d.ts +1245 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/fs.d.ts +4317 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/globals.d.ts +412 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/globals.global.d.ts +1 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/http.d.ts +1908 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/http2.d.ts +2418 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/https.d.ts +550 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/index.d.ts +89 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/inspector.d.ts +2746 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/module.d.ts +315 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/net.d.ts +999 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/os.d.ts +495 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/package.json +217 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/path.d.ts +191 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/perf_hooks.d.ts +905 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/process.d.ts +1754 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/punycode.d.ts +117 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/querystring.d.ts +153 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/readline/promises.d.ts +150 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/readline.d.ts +540 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/repl.d.ts +430 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/sea.d.ts +153 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/stream/consumers.d.ts +12 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/stream/promises.d.ts +83 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/stream/web.d.ts +367 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/stream.d.ts +1707 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/string_decoder.d.ts +67 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/test.d.ts +1718 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/timers/promises.d.ts +97 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/timers.d.ts +240 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/tls.d.ts +1217 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/trace_events.d.ts +197 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/tty.d.ts +208 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/url.d.ts +952 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/util.d.ts +2292 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/v8.d.ts +808 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/vm.d.ts +924 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/wasi.d.ts +181 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/worker_threads.d.ts +694 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/node/zlib.d.ts +530 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/notp/LICENSE +21 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/notp/README.md +15 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/notp/index.d.ts +127 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/@types/notp/package.json +21 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/node-2fa/LICENSE +201 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/node-2fa/README.md +68 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/node-2fa/dist/index.d.ts +11 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/node-2fa/dist/index.js +51 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/node-2fa/dist/interfaces.d.ts +4 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/node-2fa/dist/interfaces.js +2 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/node-2fa/package.json +58 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/notp/.travis.yml +6 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/notp/LICENSE +22 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/notp/Readme.md +135 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/notp/examples/TOTP-verify.js +33 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/notp/examples/TOTP.js +15 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/notp/index.js +221 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/notp/package.json +22 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/notp/test/mocha.opts +1 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/notp/test/notp.js +217 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/thirty-two/LICENSE.txt +19 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/thirty-two/Makefile +24 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/thirty-two/README.md +15 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/thirty-two/index.js +23 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/thirty-two/lib/thirty-two/index.js +26 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/thirty-two/lib/thirty-two/thirty-two.js +128 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/thirty-two/package.json +15 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/thirty-two/spec/thirty-two_spec.js +63 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/tslib/CopyrightNotice.txt +15 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/tslib/LICENSE.txt +12 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/tslib/README.md +164 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/tslib/SECURITY.md +41 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/tslib/modules/index.d.ts +37 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/tslib/modules/index.js +68 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/tslib/modules/package.json +3 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/tslib/package.json +47 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/tslib/tslib.d.ts +453 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/tslib/tslib.es6.html +1 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/tslib/tslib.es6.js +374 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/tslib/tslib.es6.mjs +373 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/tslib/tslib.html +1 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/tslib/tslib.js +424 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/undici-types/README.md +6 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/undici-types/agent.d.ts +31 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/undici-types/api.d.ts +43 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/undici-types/balanced-pool.d.ts +18 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/undici-types/cache.d.ts +36 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/undici-types/client.d.ts +97 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/undici-types/connector.d.ts +34 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/undici-types/content-type.d.ts +21 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/undici-types/cookies.d.ts +28 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/undici-types/diagnostics-channel.d.ts +67 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/undici-types/dispatcher.d.ts +241 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/undici-types/errors.d.ts +128 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/undici-types/fetch.d.ts +209 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/undici-types/file.d.ts +39 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/undici-types/filereader.d.ts +54 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/undici-types/formdata.d.ts +108 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/undici-types/global-dispatcher.d.ts +9 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/undici-types/global-origin.d.ts +7 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/undici-types/handlers.d.ts +9 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/undici-types/header.d.ts +4 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/undici-types/index.d.ts +63 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/undici-types/interceptors.d.ts +5 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/undici-types/mock-agent.d.ts +50 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/undici-types/mock-client.d.ts +25 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/undici-types/mock-errors.d.ts +12 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/undici-types/mock-interceptor.d.ts +93 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/undici-types/mock-pool.d.ts +25 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/undici-types/package.json +55 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/undici-types/patch.d.ts +71 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/undici-types/pool-stats.d.ts +19 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/undici-types/pool.d.ts +28 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/undici-types/proxy-agent.d.ts +30 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/undici-types/readable.d.ts +61 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/undici-types/webidl.d.ts +220 -0
- package/plugins/TwoFactorsAuthPlugin/node_modules/undici-types/websocket.d.ts +131 -0
- package/plugins/TwoFactorsAuthPlugin/package-lock.json +69 -0
- package/plugins/TwoFactorsAuthPlugin/package.json +15 -0
- package/plugins/TwoFactorsAuthPlugin/types.ts +10 -0
- package/servers/express.ts +1 -0
- package/spa/src/App.vue +154 -121
- package/spa/src/components/ResourceForm.vue +91 -91
- package/spa/src/router/index.ts +0 -1
- package/spa/src/utils.ts +1 -1
- package/spa/src/views/CreateView.vue +0 -1
- package/spa/src/views/LoginView.vue +4 -1
- package/types/AdminForthConfig.ts +24 -3
- package/dist/plugins/AuditLog/index.js +0 -13
- /package/dist/plugins/{AuditLog → S3UploadPlugin}/types.js +0 -0
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<RouterLink
|
|
3
3
|
:to="{name: item.resourceId ? 'resource-list' : item.path, params: item.resourceId ? { resourceId: item.resourceId }: {}}"
|
|
4
|
-
class="flex items-center py-2 text-
|
|
4
|
+
class="flex group items-center py-2 text-lightSidebarText dark:text-darkSidebarText rounded-default hover:bg-lightSidebarItemHover hover:text-lightSidebarTextHover dark:hover:bg-darkSidebarItemHover dark:hover:text-darkSidebarTextHover active:bg-lightSidebarActive dark:active:bg-darkSidebarHover" role="menuitem"
|
|
5
5
|
:class="{
|
|
6
6
|
'px-4': isChild,
|
|
7
7
|
'px-2': !isChild,
|
|
8
|
-
'bg-
|
|
8
|
+
'bg-sidebarActive dark:bg-gray-700': item.resourceId ?
|
|
9
9
|
($route.params.resourceId === item.resourceId && $route.name === 'resource-list') :
|
|
10
10
|
($route.name === item.path)
|
|
11
11
|
}"
|
|
12
12
|
>
|
|
13
|
-
<component v-if="item.icon" :is="getIcon(item.icon)" class="w-5 h-5 text-
|
|
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
15
|
</RouterLink>
|
|
16
16
|
</template>
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
<div class="rounded-default">
|
|
3
3
|
|
|
4
4
|
<div
|
|
5
|
-
class="relative shadow-
|
|
5
|
+
class="relative shadow-resourseFormShadow sm:rounded-lg dark:shadow-2xl dark:shadow-black rounded-default"
|
|
6
6
|
>
|
|
7
7
|
<form autocomplete="off" @submit.prevent>
|
|
8
8
|
<table class="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400 ">
|
|
9
|
-
<thead class="text-xs text-gray-700 uppercase bg-
|
|
9
|
+
<thead class="text-xs text-gray-700 uppercase bg-lightormHeading dark:bg-gray-700 dark:text-gray-400">
|
|
10
10
|
<tr>
|
|
11
11
|
<th scope="col" class="px-6 py-3">
|
|
12
12
|
Field
|
|
@@ -18,18 +18,8 @@
|
|
|
18
18
|
</thead>
|
|
19
19
|
<tbody>
|
|
20
20
|
<tr v-for="column, i in editableColumns" :key="column.name"
|
|
21
|
-
class="bg-
|
|
21
|
+
class="bg-ligftForm dark:bg-gray-800 border-b dark:border-gray-700"
|
|
22
22
|
>
|
|
23
|
-
<!-- if column is in customComponentsPerColumn, use this component. If not, use this code -->
|
|
24
|
-
<template v-if="customComponentsPerColumn[column.name]">
|
|
25
|
-
<component
|
|
26
|
-
:is="customComponentsPerColumn[column.name]"
|
|
27
|
-
:column="column"
|
|
28
|
-
:value="currentValues[column.name]"
|
|
29
|
-
@update:value="setCurrentValue(column.name, $event)"
|
|
30
|
-
/>
|
|
31
|
-
</template>
|
|
32
|
-
<template v-else>
|
|
33
23
|
<td class="px-6 py-4 whitespace-nowrap "> <!--align-top-->
|
|
34
24
|
{{ column.label }}
|
|
35
25
|
<span :data-tooltip-target="`tooltip-show-${i}`" class="relative inline-block">
|
|
@@ -44,88 +34,99 @@
|
|
|
44
34
|
</div>
|
|
45
35
|
</td>
|
|
46
36
|
<td class="px-6 py-4 whitespace-nowrap whitespace-pre-wrap relative">
|
|
47
|
-
<Dropdown
|
|
48
|
-
single
|
|
49
|
-
v-if="column.foreignResource"
|
|
50
|
-
:options="columnOptions[column.name] || []"
|
|
51
|
-
:placeholder = "columnOptions[column.name]?.length || 'There are no options available'"
|
|
52
|
-
:modelValue="currentValues[column.name]"
|
|
53
|
-
@update:modelValue="setCurrentValue(column.name, $event)"
|
|
54
|
-
></Dropdown>
|
|
55
|
-
<Dropdown
|
|
56
|
-
single
|
|
57
|
-
v-else-if="column.enum"
|
|
58
|
-
:options="column.enum"
|
|
59
|
-
:modelValue="currentValues[column.name]"
|
|
60
|
-
@update:modelValue="setCurrentValue(column.name, $event)"
|
|
61
|
-
/>
|
|
62
|
-
<Dropdown
|
|
63
|
-
single
|
|
64
|
-
v-else-if="column.type === 'boolean'"
|
|
65
|
-
:options="[{ label: 'Yes', value: true }, { label: 'No', value: false }, { label: 'Unset', value: null }]"
|
|
66
|
-
:modelValue="currentValues[column.name]"
|
|
67
|
-
@update:modelValue="setCurrentValue(column.name, $event)"
|
|
68
|
-
/>
|
|
69
|
-
<input
|
|
70
|
-
v-else-if="['integer'].includes(column.type)"
|
|
71
|
-
type="number"
|
|
72
|
-
step="1"
|
|
73
|
-
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-40 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
|
74
|
-
placeholder="0"
|
|
75
|
-
:value="currentValues[column.name]"
|
|
76
|
-
@input="setCurrentValue(column.name, $event.target.value)"
|
|
77
|
-
>
|
|
78
|
-
<CustomDatePicker
|
|
79
|
-
v-else-if="['datetime'].includes(column.type)"
|
|
80
|
-
:column="column"
|
|
81
|
-
:valueStart="currentValues[column.name]"
|
|
82
|
-
auto-hide
|
|
83
|
-
@update:valueStart="setCurrentValue(column.name, $event)"
|
|
84
|
-
/>
|
|
85
|
-
<input
|
|
86
|
-
v-else-if="['decimal', 'float'].includes(column.type)"
|
|
87
|
-
type="number"
|
|
88
|
-
step="0.1"
|
|
89
|
-
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-40 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
|
90
|
-
placeholder="0.0"
|
|
91
|
-
:value="currentValues[column.name]"
|
|
92
|
-
@input="setCurrentValue(column.name, $event.target.value)"
|
|
93
|
-
/>
|
|
94
|
-
<textarea
|
|
95
|
-
v-else-if="['text'].includes(column.type)"
|
|
96
|
-
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-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
|
97
|
-
placeholder="Text"
|
|
98
|
-
:value="currentValues[column.name]"
|
|
99
|
-
@input="setCurrentValue(column.name, $event.target.value)"
|
|
100
|
-
>
|
|
101
|
-
</textarea>
|
|
102
|
-
<input
|
|
103
|
-
v-else
|
|
104
|
-
:type="!column.masked || unmasked[column.name] ? 'text' : 'password'"
|
|
105
|
-
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-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
|
106
|
-
placeholder="Text"
|
|
107
|
-
:value="currentValues[column.name]"
|
|
108
|
-
@input="setCurrentValue(column.name, $event.target.value)"
|
|
109
|
-
autocomplete="false"
|
|
110
|
-
data-lpignore="true"
|
|
111
|
-
readonly
|
|
112
|
-
onfocus="this.removeAttribute('readonly');"
|
|
113
|
-
>
|
|
114
37
|
|
|
115
|
-
<
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
</
|
|
124
|
-
<
|
|
38
|
+
<template v-if="column?.components?.[props.source]?.file">
|
|
39
|
+
<component
|
|
40
|
+
:is="getCustomComponent(column.components[props.source])"
|
|
41
|
+
:column="column"
|
|
42
|
+
:value="currentValues[column.name]"
|
|
43
|
+
@update:value="setCurrentValue(column.name, $event)"
|
|
44
|
+
:meta="column.components[props.source].meta"
|
|
45
|
+
/>
|
|
46
|
+
</template>
|
|
47
|
+
<template v-else>
|
|
48
|
+
<Dropdown
|
|
49
|
+
single
|
|
50
|
+
v-if="column.foreignResource"
|
|
51
|
+
:options="columnOptions[column.name] || []"
|
|
52
|
+
:placeholder = "columnOptions[column.name]?.length ?'Select...': 'There are no options available'"
|
|
53
|
+
:modelValue="currentValues[column.name]"
|
|
54
|
+
@update:modelValue="setCurrentValue(column.name, $event)"
|
|
55
|
+
></Dropdown>
|
|
56
|
+
<Dropdown
|
|
57
|
+
single
|
|
58
|
+
v-else-if="column.enum"
|
|
59
|
+
:options="column.enum"
|
|
60
|
+
:modelValue="currentValues[column.name]"
|
|
61
|
+
@update:modelValue="setCurrentValue(column.name, $event)"
|
|
62
|
+
/>
|
|
63
|
+
<Dropdown
|
|
64
|
+
single
|
|
65
|
+
v-else-if="column.type === 'boolean'"
|
|
66
|
+
:options="[{ label: 'Yes', value: true }, { label: 'No', value: false }, { label: 'Unset', value: null }]"
|
|
67
|
+
:modelValue="currentValues[column.name]"
|
|
68
|
+
@update:modelValue="setCurrentValue(column.name, $event)"
|
|
69
|
+
/>
|
|
70
|
+
<input
|
|
71
|
+
v-else-if="['integer'].includes(column.type)"
|
|
72
|
+
type="number"
|
|
73
|
+
step="1"
|
|
74
|
+
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-40 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
|
75
|
+
placeholder="0"
|
|
76
|
+
:value="currentValues[column.name]"
|
|
77
|
+
@input="setCurrentValue(column.name, $event.target.value)"
|
|
78
|
+
>
|
|
79
|
+
<CustomDatePicker
|
|
80
|
+
v-else-if="['datetime'].includes(column.type)"
|
|
81
|
+
:column="column"
|
|
82
|
+
:valueStart="currentValues[column.name]"
|
|
83
|
+
auto-hide
|
|
84
|
+
@update:valueStart="setCurrentValue(column.name, $event)"
|
|
85
|
+
/>
|
|
86
|
+
<input
|
|
87
|
+
v-else-if="['decimal', 'float'].includes(column.type)"
|
|
88
|
+
type="number"
|
|
89
|
+
step="0.1"
|
|
90
|
+
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-40 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
|
91
|
+
placeholder="0.0"
|
|
92
|
+
:value="currentValues[column.name]"
|
|
93
|
+
@input="setCurrentValue(column.name, $event.target.value)"
|
|
94
|
+
/>
|
|
95
|
+
<textarea
|
|
96
|
+
v-else-if="['text'].includes(column.type)"
|
|
97
|
+
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-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
|
98
|
+
placeholder="Text"
|
|
99
|
+
:value="currentValues[column.name]"
|
|
100
|
+
@input="setCurrentValue(column.name, $event.target.value)"
|
|
101
|
+
>
|
|
102
|
+
</textarea>
|
|
103
|
+
<input
|
|
104
|
+
v-else
|
|
105
|
+
:type="!column.masked || unmasked[column.name] ? 'text' : 'password'"
|
|
106
|
+
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-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
|
107
|
+
placeholder="Text"
|
|
108
|
+
:value="currentValues[column.name]"
|
|
109
|
+
@input="setCurrentValue(column.name, $event.target.value)"
|
|
110
|
+
autocomplete="false"
|
|
111
|
+
data-lpignore="true"
|
|
112
|
+
readonly
|
|
113
|
+
onfocus="this.removeAttribute('readonly');"
|
|
114
|
+
>
|
|
125
115
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
116
|
+
<button
|
|
117
|
+
v-if="column.masked"
|
|
118
|
+
type="button"
|
|
119
|
+
@click="unmasked[column.name] = !unmasked[column.name]"
|
|
120
|
+
class="h-6 absolute inset-y-2 top-6 right-6 flex items-center pr-2 z-index-100 focus:outline-none"
|
|
121
|
+
>
|
|
122
|
+
<IconEyeSolid class="w-6 h-6 text-gray-400" v-if="!unmasked[column.name]" />
|
|
123
|
+
<IconEyeSlashSolid class="w-6 h-6 text-gray-400" v-else />
|
|
124
|
+
</button>
|
|
125
|
+
<div v-if="columnError(column) && validating" class="mt-1 text-xs text-red-500 dark:text-red-400">{{ columnError(column) }}</div>
|
|
126
|
+
|
|
127
|
+
<div v-if="column.editingNote && column.editingNote[mode]" class="mt-1 text-xs text-gray-400 dark:text-gray-500">{{ column.editingNote[mode] }}</div>
|
|
128
|
+
</template>
|
|
129
|
+
</td>
|
|
129
130
|
</tr>
|
|
130
131
|
|
|
131
132
|
</tbody>
|
|
@@ -141,7 +142,7 @@
|
|
|
141
142
|
import CustomDatePicker from "@/components/CustomDatePicker.vue";
|
|
142
143
|
import Dropdown from '@/components/Dropdown.vue';
|
|
143
144
|
import { useCoreStore } from '@/stores/core';
|
|
144
|
-
import { callAdminForthApi } from '@/utils';
|
|
145
|
+
import { callAdminForthApi, getCustomComponent } from '@/utils';
|
|
145
146
|
import { IconExclamationCircleSolid, IconEyeSlashSolid, IconEyeSolid } from '@iconify-prerendered/vue-flowbite';
|
|
146
147
|
import { computedAsync } from '@vueuse/core';
|
|
147
148
|
import { initFlowbite } from 'flowbite';
|
|
@@ -155,10 +156,9 @@ const props = defineProps({
|
|
|
155
156
|
resource: Object,
|
|
156
157
|
record: Object,
|
|
157
158
|
validating: Boolean,
|
|
158
|
-
|
|
159
|
+
source: String,
|
|
159
160
|
});
|
|
160
161
|
|
|
161
|
-
|
|
162
162
|
const unmasked = ref({});
|
|
163
163
|
|
|
164
164
|
const mode = computed(() => props.record && Object.keys(props.record).length ? 'edit' : 'create');
|
|
@@ -1,42 +1,29 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<!-- table -->
|
|
3
|
-
<div class="relative overflow-x-auto shadow-
|
|
3
|
+
<div class="relative overflow-x-auto shadow-listTableShadow dark:shadow-black overflow-y-hidden rounded-default">
|
|
4
4
|
|
|
5
5
|
<!-- skelet loader -->
|
|
6
6
|
<div role="status" v-if="!resource || !resource.columns"
|
|
7
7
|
class="max-w p-4 space-y-4 divide-y divide-gray-200 rounded shadow animate-pulse dark:divide-gray-700 md:p-6 dark:border-gray-700">
|
|
8
|
-
|
|
9
|
-
<div>
|
|
10
|
-
<div class="h-2.5 bg-gray-300 rounded-full dark:bg-gray-600 w-24 mb-2.5"></div>
|
|
11
|
-
<div class="w-32 h-2 bg-gray-200 rounded-full dark:bg-gray-700"></div>
|
|
12
|
-
</div>
|
|
13
|
-
<div class="h-2.5 bg-gray-300 rounded-full dark:bg-gray-700 w-12"></div>
|
|
14
|
-
</div>
|
|
15
|
-
|
|
16
|
-
<div class="flex items-center justify-between h-16 pt-4" v-for="i in new Array(10)">
|
|
17
|
-
<div>
|
|
18
|
-
<div class="h-2.5 bg-gray-300 rounded-full dark:bg-gray-600 w-24 mb-2.5"></div>
|
|
19
|
-
<div class="w-32 h-2 bg-gray-200 rounded-full dark:bg-gray-700"></div>
|
|
20
|
-
</div>
|
|
21
|
-
<div class="h-2.5 bg-gray-300 rounded-full dark:bg-gray-700 w-12"></div>
|
|
22
|
-
</div>
|
|
23
|
-
<span class="sr-only">Loading...</span>
|
|
8
|
+
|
|
24
9
|
</div>
|
|
25
10
|
|
|
26
11
|
<table v-else class="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400 rounded-default">
|
|
27
|
-
<thead class="text-xs text-view-table-heading-text bg-
|
|
12
|
+
<thead class="text-xs text-view-table-heading-text bg-lightListTableHeading dark:bg-darkListTableHeading dark:text-gray-400">
|
|
28
13
|
<tr>
|
|
29
14
|
<th scope="col" class="p-4">
|
|
30
15
|
<div v-if="rows && rows.length" class="flex items-center">
|
|
31
|
-
<input id="checkbox-all-search" type="checkbox" :checked="allFromThisPageChecked" @change="selectAll()"
|
|
32
|
-
class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 dark:focus:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600">
|
|
16
|
+
<input id="checkbox-all-search" type="checkbox" :checked="allFromThisPageChecked" @change="selectAll()"
|
|
17
|
+
class="w-4 h-4 cursor-pointer text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 dark:focus:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600">
|
|
33
18
|
<label for="checkbox-all-search" class="sr-only">checkbox</label>
|
|
34
19
|
</div>
|
|
35
20
|
</th>
|
|
36
21
|
|
|
37
22
|
<th v-for="c in columnsListed" scope="col" class="px-6 py-3">
|
|
23
|
+
|
|
38
24
|
<div @click="() => c.sortable && onSortButtonClick(c.name)" class="flex items-center " :class="{'cursor-pointer':c.sortable}">
|
|
39
25
|
{{ c.label }}
|
|
26
|
+
|
|
40
27
|
|
|
41
28
|
<div v-if="c.sortable"
|
|
42
29
|
:style="{ 'color':ascArr.includes(c.name)?'green':descArr.includes(c.name)?'red':'currentColor'}">
|
|
@@ -52,6 +39,12 @@
|
|
|
52
39
|
d="M8.574 11.024h6.852a2.075 2.075 0 0 0 1.847-1.086 1.9 1.9 0 0 0-.11-1.986L13.736 2.9a2.122 2.122 0 0 0-3.472 0L6.837 7.952a1.9 1.9 0 0 0-.11 1.986 2.074 2.074 0 0 0 1.847 1.086Zm6.852 1.952H8.574a2.072 2.072 0 0 0-1.847 1.087 1.9 1.9 0 0 0 .11 1.985l3.426 5.05a2.123 2.123 0 0 0 3.472 0l3.427-5.05a1.9 1.9 0 0 0 .11-1.985 2.074 2.074 0 0 0-1.846-1.087Z"/>
|
|
53
40
|
</svg>
|
|
54
41
|
</div>
|
|
42
|
+
<span
|
|
43
|
+
class="bg-red-100 text-red-800 text-xs font-medium me-1 px-1 py-0.5 rounded dark:bg-gray-700 dark:text-red-400 border border-red-400"
|
|
44
|
+
v-if="sort.findIndex((s) => s.field === c.name) !== -1">
|
|
45
|
+
{{ sort.findIndex((s) => s.field === c.name) + 1 }}
|
|
46
|
+
</span>
|
|
47
|
+
|
|
55
48
|
</div>
|
|
56
49
|
</th>
|
|
57
50
|
|
|
@@ -61,51 +54,8 @@
|
|
|
61
54
|
</tr>
|
|
62
55
|
</thead>
|
|
63
56
|
<tbody>
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
<div role="status"
|
|
68
|
-
class="max-w p-4 space-y-4 divide-y divide-gray-200 rounded animate-pulse dark:divide-gray-700 md:p-6 dark:border-gray-700">
|
|
69
|
-
<div class="flex items-center justify-between">
|
|
70
|
-
<div>
|
|
71
|
-
<div class="h-2.5 bg-gray-300 rounded-full dark:bg-gray-600 w-24 mb-2.5"></div>
|
|
72
|
-
<div class="w-32 h-2 bg-gray-200 rounded-full dark:bg-gray-700"></div>
|
|
73
|
-
</div>
|
|
74
|
-
<div class="h-2.5 bg-gray-300 rounded-full dark:bg-gray-700 w-12"></div>
|
|
75
|
-
</div>
|
|
76
|
-
<div class="flex items-center justify-between pt-4">
|
|
77
|
-
<div>
|
|
78
|
-
<div class="h-2.5 bg-gray-300 rounded-full dark:bg-gray-600 w-24 mb-2.5"></div>
|
|
79
|
-
<div class="w-32 h-2 bg-gray-200 rounded-full dark:bg-gray-700"></div>
|
|
80
|
-
</div>
|
|
81
|
-
<div class="h-2.5 bg-gray-300 rounded-full dark:bg-gray-700 w-12"></div>
|
|
82
|
-
</div>
|
|
83
|
-
<div class="flex items-center justify-between pt-4">
|
|
84
|
-
<div>
|
|
85
|
-
<div class="h-2.5 bg-gray-300 rounded-full dark:bg-gray-600 w-24 mb-2.5"></div>
|
|
86
|
-
<div class="w-32 h-2 bg-gray-200 rounded-full dark:bg-gray-700"></div>
|
|
87
|
-
</div>
|
|
88
|
-
<div class="h-2.5 bg-gray-300 rounded-full dark:bg-gray-700 w-12"></div>
|
|
89
|
-
</div>
|
|
90
|
-
<div class="flex items-center justify-between pt-4">
|
|
91
|
-
<div>
|
|
92
|
-
<div class="h-2.5 bg-gray-300 rounded-full dark:bg-gray-600 w-24 mb-2.5"></div>
|
|
93
|
-
<div class="w-32 h-2 bg-gray-200 rounded-full dark:bg-gray-700"></div>
|
|
94
|
-
</div>
|
|
95
|
-
<div class="h-2.5 bg-gray-300 rounded-full dark:bg-gray-700 w-12"></div>
|
|
96
|
-
</div>
|
|
97
|
-
<div class="flex items-center justify-between pt-4">
|
|
98
|
-
<div>
|
|
99
|
-
<div class="h-2.5 bg-gray-300 rounded-full dark:bg-gray-600 w-24 mb-2.5"></div>
|
|
100
|
-
<div class="w-32 h-2 bg-gray-200 rounded-full dark:bg-gray-700"></div>
|
|
101
|
-
</div>
|
|
102
|
-
<div class="h-2.5 bg-gray-300 rounded-full dark:bg-gray-700 w-12"></div>
|
|
103
|
-
</div>
|
|
104
|
-
<span class="sr-only">Loading...</span>
|
|
105
|
-
</div>
|
|
106
|
-
</td>
|
|
107
|
-
</tr>
|
|
108
|
-
<tr v-else-if="rows.length === 0" class="bg-list-view-table-bg border-b dark:bg-gray-800 dark:border-gray-700">
|
|
57
|
+
<SkeleteLoader v-if="!rows" :columns="3" :rows="resource?.columns.length + 2"/>
|
|
58
|
+
<tr v-else-if="rows.length === 0" class="bg-lightListTable border-b dark:bg-darkListTable dark:border-darkListTableBorder">
|
|
109
59
|
<td :colspan="resource?.columns.length + 2">
|
|
110
60
|
|
|
111
61
|
<div id="toast-simple"
|
|
@@ -118,16 +68,17 @@
|
|
|
118
68
|
</td>
|
|
119
69
|
</tr>
|
|
120
70
|
|
|
121
|
-
<tr v-else v-for="(row, rowI) in rows" :key="row.id"
|
|
122
|
-
class="bg-
|
|
123
|
-
<td class="w-4 p-4">
|
|
124
|
-
<div class="flex items center">
|
|
71
|
+
<tr @click="onClick($event,row)" v-else v-for="(row, rowI) in rows" :key="row.id"
|
|
72
|
+
class="bg-lightListTable border-b dark:bg-darkListTable border-lightListBorder dark:border-gray-700 hover:bg-lightListTableRowHover dark:hover:bg-darkListTableRowHover cursor-pointer">
|
|
73
|
+
<td class="w-4 p-4 cursor-default" @click="(e)=>{e.stopPropagation()}">
|
|
74
|
+
<div class="flex items center ">
|
|
125
75
|
<input
|
|
76
|
+
@click="(e)=>{e.stopPropagation()}"
|
|
126
77
|
id="checkbox-table-search-1"
|
|
127
78
|
type="checkbox"
|
|
128
79
|
:checked="checkboxesInternal.includes(row.id)"
|
|
129
80
|
@change="(e)=>{addToCheckedValues(row.id)}"
|
|
130
|
-
class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 dark:focus:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600">
|
|
81
|
+
class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 dark:focus:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600 cursor-pointer">
|
|
131
82
|
<label for="checkbox-table-search-1" class="sr-only">checkbox</label>
|
|
132
83
|
</div>
|
|
133
84
|
</td>
|
|
@@ -135,14 +86,14 @@
|
|
|
135
86
|
<!-- if c.name in listComponentsPerColumn, render it. If not, render ValueRenderer -->
|
|
136
87
|
<component
|
|
137
88
|
:is="c?.components?.list ? getCustomComponent(c.components.list) : ValueRenderer"
|
|
138
|
-
:meta="c?.components?.list
|
|
89
|
+
:meta="c?.components?.list?.meta"
|
|
139
90
|
:column="c"
|
|
140
91
|
:record="row"
|
|
141
92
|
:adminUser="coreStore.adminUser"
|
|
142
93
|
:resource="resource"
|
|
143
94
|
/>
|
|
144
95
|
</td>
|
|
145
|
-
<td class=" items-center px-6 py-4">
|
|
96
|
+
<td class=" items-center px-6 py-4 cursor-default" @click="(e)=>{e.stopPropagation()}">
|
|
146
97
|
<div class="flex">
|
|
147
98
|
<RouterLink
|
|
148
99
|
v-if="resource.options?.allowedActions.show"
|
|
@@ -278,6 +229,7 @@ import ValueRenderer from '@/components/ValueRenderer.vue';
|
|
|
278
229
|
import { getCustomComponent } from '@/utils';
|
|
279
230
|
import { useCoreStore } from '@/stores/core';
|
|
280
231
|
import { showSuccesTost } from '@/composables/useFrontendApi';
|
|
232
|
+
import SkeleteLoader from '@/components/SkeleteLoader.vue';
|
|
281
233
|
|
|
282
234
|
import {
|
|
283
235
|
IconInboxOutline,
|
|
@@ -291,6 +243,7 @@ IconFilterOutline,
|
|
|
291
243
|
IconPenSolid,
|
|
292
244
|
IconTrashBinSolid
|
|
293
245
|
} from '@iconify-prerendered/vue-flowbite';
|
|
246
|
+
import router from '@/router';
|
|
294
247
|
|
|
295
248
|
const coreStore = useCoreStore();
|
|
296
249
|
|
|
@@ -299,7 +252,8 @@ const props = defineProps([
|
|
|
299
252
|
'rows',
|
|
300
253
|
'totalRows',
|
|
301
254
|
'pageSize',
|
|
302
|
-
'checkboxes'
|
|
255
|
+
'checkboxes',
|
|
256
|
+
'sort'
|
|
303
257
|
])
|
|
304
258
|
|
|
305
259
|
// emits, update page
|
|
@@ -335,6 +289,10 @@ watch(() => props.checkboxes, (newCheckboxes) => {
|
|
|
335
289
|
checkboxesInternal.value = newCheckboxes;
|
|
336
290
|
});
|
|
337
291
|
|
|
292
|
+
watch(() => props.sort, (newSort) => {
|
|
293
|
+
sort.value = newSort;
|
|
294
|
+
});
|
|
295
|
+
|
|
338
296
|
function addToCheckedValues(id) {
|
|
339
297
|
if (checkboxesInternal.value.includes(id)) {
|
|
340
298
|
checkboxesInternal.value = checkboxesInternal.value.filter((item) => item !== id);
|
|
@@ -347,15 +305,18 @@ function addToCheckedValues(id) {
|
|
|
347
305
|
const columnsListed = computed(() => props.resource?.columns?.filter(c => c.showIn.includes('list')));
|
|
348
306
|
|
|
349
307
|
async function selectAll(value) {
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
checkboxesInternal.value.
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
|
|
308
|
+
if (!allFromThisPageChecked.value) {
|
|
309
|
+
props.rows.forEach((r) => {
|
|
310
|
+
if (!checkboxesInternal.value.includes(r.id)) {
|
|
311
|
+
checkboxesInternal.value.push(r.id)
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
else {
|
|
316
|
+
props.rows.forEach((r) => {
|
|
317
|
+
checkboxesInternal.value = checkboxesInternal.value.filter((item) => item !== r.id);
|
|
318
|
+
});
|
|
319
|
+
}
|
|
359
320
|
}
|
|
360
321
|
|
|
361
322
|
const totalPages = computed(() => Math.ceil(props.totalRows / props.pageSize));
|
|
@@ -365,7 +326,7 @@ const totalPages = computed(() => Math.ceil(props.totalRows / props.pageSize));
|
|
|
365
326
|
|
|
366
327
|
const allFromThisPageChecked = computed(() => {
|
|
367
328
|
if (!props.rows) return false;
|
|
368
|
-
return props.rows.every((r) =>
|
|
329
|
+
return props.rows.every((r) => checkboxesInternal.value.includes(r.id));
|
|
369
330
|
});
|
|
370
331
|
const ascArr = computed(() => sort.value.filter((s) => s.direction === 'asc').map((s) => s.field));
|
|
371
332
|
const descArr = computed(() => sort.value.filter((s) => s.direction === 'desc').map((s) => s.field));
|
|
@@ -374,7 +335,7 @@ const descArr = computed(() => sort.value.filter((s) => s.direction === 'desc').
|
|
|
374
335
|
function onSortButtonClick(field) {
|
|
375
336
|
const sortIndex = sort.value.findIndex((s) => s.field === field);
|
|
376
337
|
if (sortIndex === -1) {
|
|
377
|
-
sort.value = [{field, direction: 'asc'}
|
|
338
|
+
sort.value = [...sort.value,{field, direction: 'asc'}];
|
|
378
339
|
} else {
|
|
379
340
|
const sortField = sort.value[sortIndex];
|
|
380
341
|
if (sortField.direction === 'asc') {
|
|
@@ -385,6 +346,30 @@ function onSortButtonClick(field) {
|
|
|
385
346
|
}
|
|
386
347
|
}
|
|
387
348
|
|
|
349
|
+
|
|
350
|
+
const clickTarget = ref(null);
|
|
351
|
+
async function onClick(e,row) {
|
|
352
|
+
if(clickTarget.value === e.target) return;
|
|
353
|
+
clickTarget.value = e.target;
|
|
354
|
+
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
355
|
+
if (window.getSelection().toString()) return;
|
|
356
|
+
else {router.push({
|
|
357
|
+
name: 'resource-show',
|
|
358
|
+
params: {
|
|
359
|
+
resourceId: props.resource.resourceId,
|
|
360
|
+
primaryKey: row._primaryKeyValue,
|
|
361
|
+
},
|
|
362
|
+
})}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
|
|
388
373
|
async function deleteRecord(row) {
|
|
389
374
|
const data = await window.adminforth.confirm({
|
|
390
375
|
message: 'Are you sure you want to delete this item?',
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<tr v-for="c in new Array(props.columns)" class="bg-lightListTable border-b dark:bg-darkListTable dark:border-darkListBorder">
|
|
3
|
+
<td v-for="r in new Array(props.rows)" class="items-center px-6 py-8 cursor-default" >
|
|
4
|
+
<div role="status" class="max-w-sm animate-pulse">
|
|
5
|
+
<div class="h-2 bg-gray-200 rounded-full dark:bg-gray-700 max-w-[360px]"></div>
|
|
6
|
+
</div>
|
|
7
|
+
</td>
|
|
8
|
+
</tr>
|
|
9
|
+
</template>
|
|
10
|
+
|
|
11
|
+
<script setup>
|
|
12
|
+
|
|
13
|
+
const props = defineProps({
|
|
14
|
+
columns:Number,
|
|
15
|
+
rows:Number
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<style lang="scss" scoped>
|
|
22
|
+
|
|
23
|
+
</style>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div>
|
|
3
3
|
|
|
4
|
-
<span v-if="column.foreignResource">
|
|
4
|
+
<span @click="(e)=>{e.stopPropagation()}" v-if="column.foreignResource">
|
|
5
5
|
<RouterLink v-if="record[column.name]" class="font-medium text-blue-600 dark:text-blue-500 hover:brightness-110"
|
|
6
6
|
:to="{ name: 'resource-show', params: { resourceId: column.foreignResource.resourceId, primaryKey: record[column.name].pk } }">
|
|
7
7
|
{{ record[column.name].label }}
|
|
@@ -18,9 +18,8 @@
|
|
|
18
18
|
<span v-else-if="column.enum">
|
|
19
19
|
{{ checkEmptyValues(column.enum.find(e => e.value === record[column.name])?.label,route.meta.type) }}
|
|
20
20
|
</span>
|
|
21
|
-
<span v-else-if="column.type === 'datetime'">
|
|
21
|
+
<span v-else-if="column.type === 'datetime'" class="whitespace-nowrap">
|
|
22
22
|
{{ checkEmptyValues(formatDate(record[column.name]),route.meta.type) }}
|
|
23
|
-
|
|
24
23
|
</span>
|
|
25
24
|
<span v-else>
|
|
26
25
|
{{ checkEmptyValues(record[column.name],route.meta.type) }}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { FrontendAPIInterface, ConfirmParams, AlertParams,
|
|
1
|
+
import type { FrontendAPIInterface, ConfirmParams, AlertParams, } from '../types/FrontendAPI';
|
|
2
|
+
import type { AdminForthFilterOperators } from '@/types/AdminForthConfig';
|
|
2
3
|
import { useToastStore } from '../stores/toast';
|
|
3
4
|
import { useModalStore } from '../stores/modal';
|
|
4
5
|
import { useCoreStore } from '@/stores/core';
|
|
@@ -6,9 +7,20 @@ import { useFiltersStore } from '@/stores/filters';
|
|
|
6
7
|
import router from '@/router'
|
|
7
8
|
import type { AdminForthResourceColumn } from '@/types/AdminForthConfig';
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
type FilterParams = {
|
|
11
|
+
/**
|
|
12
|
+
* Field of resource to filter
|
|
13
|
+
*/
|
|
14
|
+
field: string;
|
|
15
|
+
/**
|
|
16
|
+
* Operator of filter
|
|
17
|
+
*/
|
|
18
|
+
operator: AdminForthFilterOperators;
|
|
19
|
+
/**
|
|
20
|
+
* Value of filter
|
|
21
|
+
*/
|
|
22
|
+
value: string | number | boolean ;
|
|
23
|
+
}
|
|
12
24
|
|
|
13
25
|
declare global {
|
|
14
26
|
interface Window {
|
|
@@ -23,7 +35,6 @@ declare global {
|
|
|
23
35
|
}
|
|
24
36
|
|
|
25
37
|
export class FrontendAPI implements FrontendAPIInterface {
|
|
26
|
-
private validOperators: Operator[] = ['lte', 'gte', 'in','ilike'];
|
|
27
38
|
private toastStore:any
|
|
28
39
|
private modalStore:any
|
|
29
40
|
private filtersStore:any
|
|
@@ -70,12 +81,8 @@ export class FrontendAPI implements FrontendAPIInterface {
|
|
|
70
81
|
const filterField = this.coreStore.resourceColumnsWithFilters.find((col: AdminForthResourceColumn) => col.name === filter.field)
|
|
71
82
|
if(!filterField){
|
|
72
83
|
throw new Error(`Field ${filter.field} is not available for filtering`)
|
|
73
|
-
}
|
|
74
|
-
if(filterField) {
|
|
75
|
-
if(!this.validOperators.includes(filter.operator)){
|
|
76
|
-
throw new Error(`Operator ${filter.operator} is not valid`)
|
|
77
|
-
}
|
|
78
84
|
}
|
|
85
|
+
|
|
79
86
|
}
|
|
80
87
|
return true
|
|
81
88
|
}
|
|
@@ -103,7 +110,13 @@ export class FrontendAPI implements FrontendAPIInterface {
|
|
|
103
110
|
if(index === -1) {
|
|
104
111
|
this.filtersStore.setFilter(filter)
|
|
105
112
|
} else {
|
|
106
|
-
|
|
113
|
+
const filters = [...this.filtersStore.filters];
|
|
114
|
+
if (filter.value === undefined) {
|
|
115
|
+
filters.splice(index, 1);
|
|
116
|
+
} else {
|
|
117
|
+
filters[index] = filter;
|
|
118
|
+
}
|
|
119
|
+
this.filtersStore.setFilters(filters);
|
|
107
120
|
}
|
|
108
121
|
}
|
|
109
122
|
}
|
package/dist/spa/src/main.ts
CHANGED
|
@@ -12,7 +12,6 @@ const router = createRouter({
|
|
|
12
12
|
component: () => import('@/views/LoginView.vue'),
|
|
13
13
|
meta: { title: 'login' },
|
|
14
14
|
beforeEnter: async (to, from, next) => {
|
|
15
|
-
const userStore = useUserStore()
|
|
16
15
|
if(localStorage.getItem('isAuthorized') === 'true'){
|
|
17
16
|
next({name: 'home'})
|
|
18
17
|
} else {
|