adminforth 1.1.75 → 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/dist/modules/utils.js +1 -1
- package/dist/plugins/S3UploadPlugin/package.json +1 -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/spa/spa/.eslintrc.cjs +14 -0
- package/dist/spa/spa/.vscode/extensions.json +6 -0
- package/dist/spa/spa/README.md +39 -0
- package/dist/spa/spa/env.d.ts +1 -0
- package/dist/spa/spa/index.html +23 -0
- package/dist/spa/spa/package-lock.json +4470 -0
- package/dist/spa/spa/package.json +48 -0
- package/dist/spa/spa/postcss.config.js +6 -0
- package/dist/spa/spa/public/assets/favicon.png +0 -0
- package/dist/spa/spa/src/App.vue +316 -0
- package/dist/spa/spa/src/assets/base.css +0 -0
- package/dist/spa/spa/src/assets/logo.svg +19 -0
- package/dist/spa/spa/src/components/AcceptModal.vue +45 -0
- package/dist/spa/spa/src/components/Breadcrumbs.vue +40 -0
- package/dist/spa/spa/src/components/BreadcrumbsWithButtons.vue +26 -0
- package/dist/spa/spa/src/components/CustomDatePicker.vue +174 -0
- package/dist/spa/spa/src/components/CustomDateRangePicker.vue +218 -0
- package/dist/spa/spa/src/components/CustomRangePicker.vue +148 -0
- package/dist/spa/spa/src/components/Dropdown.vue +168 -0
- package/dist/spa/spa/src/components/Filters.vue +211 -0
- package/dist/spa/spa/src/components/HelloWorld.vue +17 -0
- package/dist/spa/spa/src/components/MenuLink.vue +24 -0
- package/dist/spa/spa/src/components/ResourceForm.vue +265 -0
- package/dist/spa/spa/src/components/ResourceListTable.vue +404 -0
- package/dist/spa/spa/src/components/SingleSkeletLoader.vue +13 -0
- package/dist/spa/spa/src/components/SkeleteLoader.vue +23 -0
- package/dist/spa/spa/src/components/Toast.vue +66 -0
- package/dist/spa/spa/src/components/ValueRenderer.vue +59 -0
- package/dist/spa/spa/src/components/icons/IconCalendar.vue +5 -0
- package/dist/spa/spa/src/components/icons/IconCommunity.vue +7 -0
- package/dist/spa/spa/src/components/icons/IconDocumentation.vue +7 -0
- package/dist/spa/spa/src/components/icons/IconEcosystem.vue +7 -0
- package/dist/spa/spa/src/components/icons/IconSupport.vue +7 -0
- package/dist/spa/spa/src/components/icons/IconTime.vue +5 -0
- package/dist/spa/spa/src/components/icons/IconTooling.vue +19 -0
- package/dist/spa/spa/src/composables/useFrontendApi.ts +26 -0
- package/dist/spa/spa/src/composables/useStores.ts +126 -0
- package/dist/spa/spa/src/index.scss +26 -0
- package/dist/spa/spa/src/main.ts +18 -0
- package/dist/spa/spa/src/router/index.ts +63 -0
- package/dist/spa/spa/src/spa_types/core.ts +51 -0
- package/dist/spa/spa/src/stores/core.ts +144 -0
- package/dist/spa/spa/src/stores/filters.ts +22 -0
- package/dist/spa/spa/src/stores/modal.ts +48 -0
- package/dist/spa/spa/src/stores/toast.ts +15 -0
- package/dist/spa/spa/src/stores/user.ts +54 -0
- package/dist/spa/spa/src/utils.ts +101 -0
- package/dist/spa/spa/src/views/CreateView.vue +155 -0
- package/dist/spa/spa/src/views/EditView.vue +157 -0
- package/dist/spa/spa/src/views/ListView.vue +266 -0
- package/dist/spa/spa/src/views/LoginView.vue +139 -0
- package/dist/spa/spa/src/views/ResourceParent.vue +17 -0
- package/dist/spa/spa/src/views/ShowView.vue +180 -0
- package/dist/spa/spa/tailwind.config.js +17 -0
- package/dist/spa/spa/tsconfig.app.json +14 -0
- package/dist/spa/spa/tsconfig.json +11 -0
- package/dist/spa/spa/tsconfig.node.json +19 -0
- package/dist/spa/spa/vite.config.ts +49 -0
- package/modules/utils.ts +1 -1
- package/package.json +1 -2
- package/plugins/S3UploadPlugin/package.json +1 -0
- package/plugins/S3UploadPlugin/types.ts +1 -1
- 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
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<!-- drawer component -->
|
|
3
|
+
<div id="drawer-navigation"
|
|
4
|
+
|
|
5
|
+
class="fixed right-0 z-50 p-4 overflow-y-auto transition-transform translate-x-full bg-white w-80 dark:bg-gray-800 shadow-xl dark:shadow-black"
|
|
6
|
+
|
|
7
|
+
:class="show ? 'top-0 transform-none' : ''"
|
|
8
|
+
tabindex="-1" aria-labelledby="drawer-navigation-label"
|
|
9
|
+
:style="{ height: `calc(100vh ` }"
|
|
10
|
+
>
|
|
11
|
+
<h5 id="drawer-navigation-label" class="text-base font-semibold text-gray-500 uppercase dark:text-gray-400">
|
|
12
|
+
Filters
|
|
13
|
+
|
|
14
|
+
<button type="button" @click="$emit('hide')" class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm p-1.5 absolute end-2.5 inline-flex items-center dark:hover:bg-gray-600 dark:hover:text-white" >
|
|
15
|
+
<svg aria-hidden="true" class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path></svg>
|
|
16
|
+
<span class="sr-only">Close menu</span>
|
|
17
|
+
</button>
|
|
18
|
+
</h5>
|
|
19
|
+
|
|
20
|
+
<div class="py-4 ">
|
|
21
|
+
<ul class="space-y-3 font-medium">
|
|
22
|
+
<li v-for="c in columnsWithFilter" :key="c">
|
|
23
|
+
<p class="dark:text-gray-400">{{ c.label }}</p>
|
|
24
|
+
|
|
25
|
+
<Dropdown
|
|
26
|
+
v-if="c.foreignResource"
|
|
27
|
+
:options="columnOptions[c.name] || []"
|
|
28
|
+
@update:modelValue="setFilterItem({ column: c, operator: 'in', value: $event })"
|
|
29
|
+
:modelValue="filtersStore.filters.find(f => f.field === c.name && f.operator === 'in')?.value || []"
|
|
30
|
+
/>
|
|
31
|
+
<Dropdown
|
|
32
|
+
v-else-if="c.type === 'boolean'"
|
|
33
|
+
:options="[{ label: 'Yes', value: true }, { label: 'No', value: false }, { label: 'Unset', value: null }]"
|
|
34
|
+
@update:modelValue="setFilterItem({ column: c, operator: 'in', value: $event })"
|
|
35
|
+
:modelValue="filtersStore.filters.find(f => f.field === c.name && f.operator === 'in')?.value || []"
|
|
36
|
+
/>
|
|
37
|
+
|
|
38
|
+
<Dropdown
|
|
39
|
+
v-else-if="c.enum"
|
|
40
|
+
:options="c.enum"
|
|
41
|
+
:allowCustom="c.allowCustom"
|
|
42
|
+
@update:modelValue="setFilterItem({ column: c, operator: 'in', value: $event })"
|
|
43
|
+
:modelValue="filtersStore.filters.find(f => f.field === c.name && f.operator === 'in')?.value || []"
|
|
44
|
+
/>
|
|
45
|
+
|
|
46
|
+
<input
|
|
47
|
+
v-else-if="[ 'string', 'text' ].includes(c.type)"
|
|
48
|
+
type="text" class="w-full py-1 px-2 border border-gray-300 rounded-md 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"
|
|
49
|
+
placeholder="Search"
|
|
50
|
+
@input="setFilterItem({ column: c, operator: 'ilike', value: $event.target.value || undefined })"
|
|
51
|
+
:value="getFilterItem({ column: c, operator: 'ilike' })"
|
|
52
|
+
>
|
|
53
|
+
|
|
54
|
+
<CustomDateRangePicker
|
|
55
|
+
v-else-if="['datetime'].includes(c.type)"
|
|
56
|
+
:column="c"
|
|
57
|
+
:valueStart="filtersStore.filters.find(f => f.field === c.name && f.operator === 'gte')?.value || undefined"
|
|
58
|
+
@update:valueStart="setFilterItem({ column: c, operator: 'gte', value: $event || undefined })"
|
|
59
|
+
:valueEnd="filtersStore.filters.find(f => f.field === c.name && f.operator === 'lte')?.value || undefined"
|
|
60
|
+
@update:valueEnd="setFilterItem({ column: c, operator: 'lte', value: $event || undefined })"
|
|
61
|
+
/>
|
|
62
|
+
|
|
63
|
+
<input
|
|
64
|
+
v-else-if="[ 'date', 'time' ].includes(c.type)"
|
|
65
|
+
type="text" class="w-full py-1 px-2 border border-gray-300 rounded-md"
|
|
66
|
+
placeholder="Search datetime"
|
|
67
|
+
@input="setFilterItem({ column: c, operator: 'ilike', value: $event.target.value || undefined })"
|
|
68
|
+
:value="getFilterItem({ column: c, operator: 'ilike' })"
|
|
69
|
+
>
|
|
70
|
+
|
|
71
|
+
<CustomRangePicker
|
|
72
|
+
v-else-if="['integer', 'decimal', 'float'].includes(c.type) && c.allowMinMaxQuery"
|
|
73
|
+
:min="c.min"
|
|
74
|
+
:max="c.max"
|
|
75
|
+
:valueStart="getFilterItem({ column: c, operator: 'gte' })"
|
|
76
|
+
@update:valueStart="setFilterItem({ column: c, operator: 'gte', value: $event || undefined })"
|
|
77
|
+
:valueEnd="getFilterItem({ column: c, operator: 'lte' })"
|
|
78
|
+
@update:valueEnd="setFilterItem({ column: c, operator: 'lte', value: $event || undefined })"
|
|
79
|
+
/>
|
|
80
|
+
|
|
81
|
+
<div v-else-if="['integer', 'decimal', 'float'].includes(c.type)" class="flex gap-2">
|
|
82
|
+
<input
|
|
83
|
+
type="number" aria-describedby="helper-text-explanation"
|
|
84
|
+
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-20 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"
|
|
85
|
+
placeholder="From"
|
|
86
|
+
@input="setFilterItem({ column: c, operator: 'gte', value: $event.target.value || undefined })"
|
|
87
|
+
:value="getFilterItem({ column: c, operator: 'gte' })"
|
|
88
|
+
>
|
|
89
|
+
<input
|
|
90
|
+
type="number" aria-describedby="helper-text-explanation"
|
|
91
|
+
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-20 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"
|
|
92
|
+
placeholder="To"
|
|
93
|
+
@input="setFilterItem({ column: c, operator: 'lte', value: $event.target.value || undefined})"
|
|
94
|
+
:value="getFilterItem({ column: c, operator: 'lte' })"
|
|
95
|
+
>
|
|
96
|
+
</div>
|
|
97
|
+
|
|
98
|
+
</li>
|
|
99
|
+
</ul>
|
|
100
|
+
</div>
|
|
101
|
+
|
|
102
|
+
<div class="flex justify-end gap-2">
|
|
103
|
+
<button
|
|
104
|
+
:disabled="!filtersStore.filters.length"
|
|
105
|
+
type="button"
|
|
106
|
+
class="flex items-center py-1 px-3 text-sm font-medium text-gray-900 focus:outline-none bg-white rounded border border-gray-300 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-100 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700 disabled:opacity-50 disabled:cursor-not-allowed"
|
|
107
|
+
@click="clear">Clear all</button>
|
|
108
|
+
|
|
109
|
+
</div>
|
|
110
|
+
</div>
|
|
111
|
+
|
|
112
|
+
<div v-if="show" class="bg-gray-900/50 dark:bg-gray-900/80 fixed inset-0 z-30"
|
|
113
|
+
@click="$emit('hide')">
|
|
114
|
+
</div>
|
|
115
|
+
</template>
|
|
116
|
+
|
|
117
|
+
<script setup>
|
|
118
|
+
import { watch, computed, ref, onMounted } from 'vue'
|
|
119
|
+
import Dropdown from '@/components/Dropdown.vue';
|
|
120
|
+
import CustomDateRangePicker from '@/components/CustomDateRangePicker.vue';
|
|
121
|
+
import { callAdminForthApi } from '@/utils';
|
|
122
|
+
import { useRouter } from 'vue-router';
|
|
123
|
+
import { computedAsync } from '@vueuse/core'
|
|
124
|
+
import CustomRangePicker from "@/components/CustomRangePicker.vue";
|
|
125
|
+
import { useFiltersStore } from '@/stores/filters';
|
|
126
|
+
|
|
127
|
+
const filtersStore = useFiltersStore();
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
// props: columns
|
|
131
|
+
// add support for v-model:filers
|
|
132
|
+
const props = defineProps(['columns', 'filters', 'show', 'columnsMinMax']);
|
|
133
|
+
const emits = defineEmits(['update:filters', 'hide']);
|
|
134
|
+
|
|
135
|
+
const router = useRouter();
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
const columnsWithFilter = computed(
|
|
139
|
+
() => props.columns?.filter(column => column.showIn.includes('filter')) || []
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
const columnOptions = computedAsync(async () => {
|
|
143
|
+
const ret = {};
|
|
144
|
+
if (!props.columns) {
|
|
145
|
+
return ret;
|
|
146
|
+
}
|
|
147
|
+
await Promise.all(
|
|
148
|
+
Object.values(props.columns).map(async (column) => {
|
|
149
|
+
if (column.foreignResource) {
|
|
150
|
+
const list = await callAdminForthApi({
|
|
151
|
+
method: 'POST',
|
|
152
|
+
path: `/get_resource_foreign_data`,
|
|
153
|
+
body: {
|
|
154
|
+
resourceId: router.currentRoute.value.params.resourceId,
|
|
155
|
+
column: column.name,
|
|
156
|
+
limit: 1000,
|
|
157
|
+
offset: 0,
|
|
158
|
+
},
|
|
159
|
+
});
|
|
160
|
+
ret[column.name] = list.items;
|
|
161
|
+
}
|
|
162
|
+
})
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
return ret;
|
|
166
|
+
}, {});
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
// sync 'body' class 'overflow-hidden' with show prop show
|
|
170
|
+
watch(() => props.show, (show) => {
|
|
171
|
+
if (show) {
|
|
172
|
+
document.body.classList.add('overflow-hidden');
|
|
173
|
+
} else {
|
|
174
|
+
document.body.classList.remove('overflow-hidden');
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
// filters is a array of objects
|
|
179
|
+
// {
|
|
180
|
+
// field: 'name',
|
|
181
|
+
// value: 'John',
|
|
182
|
+
// operator: 'like'
|
|
183
|
+
// }
|
|
184
|
+
|
|
185
|
+
function setFilterItem({ column, operator, value }) {
|
|
186
|
+
|
|
187
|
+
const index = filtersStore.filters.findIndex(f => f.field === column.name && f.operator === operator);
|
|
188
|
+
if (value === undefined) {
|
|
189
|
+
if (index !== -1) {
|
|
190
|
+
filtersStore.filters.splice(index, 1);
|
|
191
|
+
}
|
|
192
|
+
emits('update:filters', [...filtersStore.filters]);
|
|
193
|
+
return;
|
|
194
|
+
} else {
|
|
195
|
+
if (index === -1) {
|
|
196
|
+
filtersStore.setFilter({ field: column.name, value, operator });
|
|
197
|
+
} else {
|
|
198
|
+
filtersStore.setFilters([...filtersStore.filters.slice(0, index), { field: column.name, value, operator }, ...filtersStore.filters.slice(index + 1)])
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
emits('update:filters', [...filtersStore.filters]);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function getFilterItem({ column, operator }) {
|
|
205
|
+
return filtersStore.filters.find(f => f.field === column.name && f.operator === operator)?.value || '';
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
async function clear() {
|
|
209
|
+
filtersStore.clearFilters();
|
|
210
|
+
}
|
|
211
|
+
</script>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
defineProps<{
|
|
3
|
+
msg: string
|
|
4
|
+
}>()
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<template>
|
|
8
|
+
<div class="greetings">
|
|
9
|
+
<h1 class="green">{{ msg }}</h1>
|
|
10
|
+
<h3>
|
|
11
|
+
You’ve successfully created a project with
|
|
12
|
+
</h3>
|
|
13
|
+
</div>
|
|
14
|
+
</template>
|
|
15
|
+
|
|
16
|
+
<style scoped>
|
|
17
|
+
</style>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<RouterLink
|
|
3
|
+
:to="{name: item.resourceId ? 'resource-list' : item.path, params: item.resourceId ? { resourceId: item.resourceId }: {}}"
|
|
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
|
+
:class="{
|
|
6
|
+
'px-4': isChild,
|
|
7
|
+
'px-2': !isChild,
|
|
8
|
+
'bg-sidebarActive dark:bg-gray-700': item.resourceId ?
|
|
9
|
+
($route.params.resourceId === item.resourceId && $route.name === 'resource-list') :
|
|
10
|
+
($route.name === item.path)
|
|
11
|
+
}"
|
|
12
|
+
>
|
|
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
|
+
<span class="ms-3">{{ item.label }}</span>
|
|
15
|
+
</RouterLink>
|
|
16
|
+
</template>
|
|
17
|
+
|
|
18
|
+
<script setup lang="ts">
|
|
19
|
+
import { getIcon } from '@/utils';
|
|
20
|
+
|
|
21
|
+
const props = defineProps(['item', 'isChild']);
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
</script>
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="rounded-default">
|
|
3
|
+
|
|
4
|
+
<div
|
|
5
|
+
class="relative shadow-resourseFormShadow sm:rounded-lg dark:shadow-2xl dark:shadow-black rounded-default"
|
|
6
|
+
>
|
|
7
|
+
<form autocomplete="off" @submit.prevent>
|
|
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-lightormHeading dark:bg-gray-700 dark:text-gray-400">
|
|
10
|
+
<tr>
|
|
11
|
+
<th scope="col" class="px-6 py-3">
|
|
12
|
+
Field
|
|
13
|
+
</th>
|
|
14
|
+
<th scope="col" class="px-6 py-3 w-4/6">
|
|
15
|
+
Value
|
|
16
|
+
</th>
|
|
17
|
+
</tr>
|
|
18
|
+
</thead>
|
|
19
|
+
<tbody>
|
|
20
|
+
<tr v-for="column, i in editableColumns" :key="column.name"
|
|
21
|
+
class="bg-ligftForm dark:bg-gray-800 border-b dark:border-gray-700"
|
|
22
|
+
>
|
|
23
|
+
<td class="px-6 py-4 whitespace-nowrap "> <!--align-top-->
|
|
24
|
+
{{ column.label }}
|
|
25
|
+
<span :data-tooltip-target="`tooltip-show-${i}`" class="relative inline-block">
|
|
26
|
+
<IconExclamationCircleSolid v-if="column.required[mode]" class="w-4 h-4"
|
|
27
|
+
:class="(columnError(column) && validating) ? 'text-red-500 dark:text-red-400' : 'text-gray-400 dark:text-gray-500'"
|
|
28
|
+
/>
|
|
29
|
+
</span>
|
|
30
|
+
<div :id="`tooltip-show-${i}`"
|
|
31
|
+
role="tooltip" class="absolute z-10 invisible inline-block px-3 py-2 text-sm font-medium text-white transition-opacity duration-300 bg-gray-900 rounded-lg shadow-sm opacity-0 tooltip dark:bg-gray-700">
|
|
32
|
+
Required field
|
|
33
|
+
<div class="tooltip-arrow" data-popper-arrow></div>
|
|
34
|
+
</div>
|
|
35
|
+
</td>
|
|
36
|
+
<td class="px-6 py-4 whitespace-nowrap whitespace-pre-wrap relative">
|
|
37
|
+
|
|
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
|
+
>
|
|
115
|
+
|
|
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>
|
|
130
|
+
</tr>
|
|
131
|
+
|
|
132
|
+
</tbody>
|
|
133
|
+
</table>
|
|
134
|
+
</form>
|
|
135
|
+
</div>
|
|
136
|
+
</div>
|
|
137
|
+
|
|
138
|
+
</template>
|
|
139
|
+
|
|
140
|
+
<script setup>
|
|
141
|
+
|
|
142
|
+
import CustomDatePicker from "@/components/CustomDatePicker.vue";
|
|
143
|
+
import Dropdown from '@/components/Dropdown.vue';
|
|
144
|
+
import { useCoreStore } from '@/stores/core';
|
|
145
|
+
import { callAdminForthApi, getCustomComponent } from '@/utils';
|
|
146
|
+
import { IconExclamationCircleSolid, IconEyeSlashSolid, IconEyeSolid } from '@iconify-prerendered/vue-flowbite';
|
|
147
|
+
import { computedAsync } from '@vueuse/core';
|
|
148
|
+
import { initFlowbite } from 'flowbite';
|
|
149
|
+
import { computed, onMounted, ref, watch } from 'vue';
|
|
150
|
+
import { useRouter } from 'vue-router';
|
|
151
|
+
|
|
152
|
+
const router = useRouter();
|
|
153
|
+
|
|
154
|
+
const props = defineProps({
|
|
155
|
+
loading: Boolean,
|
|
156
|
+
resource: Object,
|
|
157
|
+
record: Object,
|
|
158
|
+
validating: Boolean,
|
|
159
|
+
source: String,
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
const unmasked = ref({});
|
|
163
|
+
|
|
164
|
+
const mode = computed(() => props.record && Object.keys(props.record).length ? 'edit' : 'create');
|
|
165
|
+
|
|
166
|
+
const emit = defineEmits(['update:record', 'update:isValid']);
|
|
167
|
+
|
|
168
|
+
const currentValues = ref({});
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
const columnError = (column) => {
|
|
172
|
+
const val = computed(() => {
|
|
173
|
+
if ( column.required[mode.value] && (currentValues.value[column.name] === undefined || currentValues.value[column.name] === null || currentValues.value[column.name] === '') ) {
|
|
174
|
+
return 'This field is required';
|
|
175
|
+
}
|
|
176
|
+
if ( column.type === 'string' || column.type === 'text' ) {
|
|
177
|
+
if ( column.maxLength && currentValues.value[column.name]?.length > column.maxLength ) {
|
|
178
|
+
return `This field must be shorter than ${column.maxLength} characters`;
|
|
179
|
+
}
|
|
180
|
+
if ( column.minLength && currentValues.value[column.name]?.length < column.minLength ) {
|
|
181
|
+
return `This field must be longer than ${column.minLength} characters`;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
if ( ['integer', 'decimal', 'float'].includes(column.type) ) {
|
|
185
|
+
if ( column.minValue !== undefined && currentValues.value[column.name] < column.minValue ) {
|
|
186
|
+
return `This field must be greater than ${column.minValue}`;
|
|
187
|
+
}
|
|
188
|
+
if ( column.maxValue !== undefined && currentValues.value[column.name] > column.maxValue ) {
|
|
189
|
+
return `This field must be less than ${column.maxValue}`;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
if ( column.validation && column.validation.length ){
|
|
193
|
+
const validationArray = column.validation;
|
|
194
|
+
for (let i = 0; i < validationArray.length; i++) {
|
|
195
|
+
if (validationArray[i].regExp) {
|
|
196
|
+
const regExp = new RegExp(validationArray[i].regExp);
|
|
197
|
+
let value = currentValues.value[column.name];
|
|
198
|
+
if (value === undefined || value === null) {
|
|
199
|
+
value = '';
|
|
200
|
+
}
|
|
201
|
+
if (!regExp.test(value)) {
|
|
202
|
+
return validationArray[i].message;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
}
|
|
208
|
+
return null;
|
|
209
|
+
});
|
|
210
|
+
return val.value;
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
const setCurrentValue = (key, value) => {
|
|
215
|
+
currentValues.value[key] = value;
|
|
216
|
+
|
|
217
|
+
emit('update:record', currentValues.value);
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
onMounted(() => {
|
|
221
|
+
Object.keys(props.record).forEach((key) => {
|
|
222
|
+
currentValues.value[key] = props.record[key];
|
|
223
|
+
});
|
|
224
|
+
initFlowbite();
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
const columnOptions = computedAsync(async () => {
|
|
230
|
+
return (await Promise.all(
|
|
231
|
+
Object.values(props.resource.columns).map(async (column) => {
|
|
232
|
+
if (column.foreignResource) {
|
|
233
|
+
const list = await callAdminForthApi({
|
|
234
|
+
method: 'POST',
|
|
235
|
+
path: `/get_resource_foreign_data`,
|
|
236
|
+
body: {
|
|
237
|
+
resourceId: router.currentRoute.value.params.resourceId,
|
|
238
|
+
column: column.name,
|
|
239
|
+
limit: 1000,
|
|
240
|
+
offset: 0,
|
|
241
|
+
},
|
|
242
|
+
});
|
|
243
|
+
return { [column.name]: list.items };
|
|
244
|
+
}
|
|
245
|
+
})
|
|
246
|
+
)).reduce((acc, val) => Object.assign(acc, val), {})
|
|
247
|
+
|
|
248
|
+
}, {});
|
|
249
|
+
|
|
250
|
+
const coreStore = useCoreStore();
|
|
251
|
+
|
|
252
|
+
const editableColumns = computed(() => {
|
|
253
|
+
const mode = props.record ? 'edit' : 'create';
|
|
254
|
+
return props.resource?.columns?.filter(column => column.showIn.includes(mode));
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
const isValid = computed(() => {
|
|
258
|
+
return editableColumns.value?.every(column => !columnError(column));
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
watch(() => isValid.value, (value) => {
|
|
262
|
+
emit('update:isValid', value);
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
</script>
|