@vc-shell/create-vc-app 1.2.4-beta.8 → 2.0.0-alpha.1
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/README.md +44 -74
- package/dist/commands/add-module.d.ts +2 -0
- package/dist/commands/add-module.d.ts.map +1 -0
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/engine/codegen.d.ts +9 -0
- package/dist/engine/codegen.d.ts.map +1 -0
- package/dist/engine/helpers.d.ts +19 -0
- package/dist/engine/helpers.d.ts.map +1 -0
- package/dist/engine/template.d.ts +21 -0
- package/dist/engine/template.d.ts.map +1 -0
- package/dist/index.js +355 -526
- package/dist/output.d.ts +4 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/templates/dynamic-module/_gitignore +4 -0
- package/dist/templates/dynamic-module/_package.json.ejs +26 -0
- package/dist/templates/dynamic-module/src/modules/index.ts.ejs +5 -0
- package/dist/templates/dynamic-module/tsconfig.json +14 -0
- package/dist/templates/dynamic-module/vite.config.mts.ejs +3 -0
- package/dist/templates/{base/_env → host-app/_env.ejs} +1 -1
- package/dist/templates/{base/_package.json → host-app/_package.json.ejs} +7 -7
- package/dist/templates/{base/index.html → host-app/index.html.ejs} +1 -1
- package/dist/templates/{base/src/bootstrap.ts → host-app/src/bootstrap.ts.ejs} +6 -3
- package/dist/templates/{base/src/main.ts → host-app/src/main.ts.ejs} +7 -5
- package/dist/templates/{base/src/pages/App.vue → host-app/src/pages/App.vue.ejs} +1 -1
- package/dist/templates/host-app/src/pages/Platform.vue +19 -0
- package/dist/templates/host-app/src/router/routes.ts.ejs +107 -0
- package/dist/templates/host-app/vite.config.mts.ejs +7 -0
- package/dist/templates/module/composables/index.ts.ejs +2 -0
- package/dist/templates/module/composables/useDetails.ts.ejs +38 -0
- package/dist/templates/module/composables/useList.ts.ejs +43 -0
- package/dist/templates/module/locales/en.json.ejs +22 -0
- package/dist/templates/module/pages/details.vue.ejs +111 -0
- package/dist/templates/module/pages/index.ts.ejs +2 -0
- package/dist/templates/module/pages/list.vue.ejs +117 -0
- package/dist/templates/{sample/classic-module → sample-module}/pages/details.vue +2 -2
- package/dist/templates/{sample/classic-module → sample-module}/pages/list.vue +3 -3
- package/dist/templates/standalone/LICENSE +12 -0
- package/dist/templates/standalone/README.md +54 -0
- package/dist/templates/standalone/_browserslistrc +3 -0
- package/dist/templates/standalone/_commitlintrc.json +3 -0
- package/dist/templates/standalone/_editorconfig +22 -0
- package/dist/templates/standalone/_env.ejs +3 -0
- package/dist/templates/standalone/_env.local.ejs +1 -0
- package/dist/templates/standalone/_eslintignore +3 -0
- package/dist/templates/standalone/_eslintrc.js +41 -0
- package/dist/templates/standalone/_github/COMMIT_CONVENTION.md +91 -0
- package/dist/templates/standalone/_github/PULL_REQUEST_TEMPLATE.md +8 -0
- package/dist/templates/standalone/_gitignore +71 -0
- package/dist/templates/standalone/_package.json.ejs +0 -0
- package/dist/templates/standalone/_prettierignore +4 -0
- package/dist/templates/standalone/_prettierrc +4 -0
- package/dist/templates/standalone/_vscode/extensions.json +14 -0
- package/dist/templates/standalone/_vscode/settings.json +14 -0
- package/dist/templates/standalone/_yarn/releases/yarn-4.9.1.cjs +948 -0
- package/dist/templates/standalone/_yarnrc.yml +7 -0
- package/dist/templates/standalone/index.html.ejs +26 -0
- package/dist/templates/standalone/postcss.config.cjs +6 -0
- package/dist/templates/standalone/public/assets/1.jpeg +0 -0
- package/dist/templates/standalone/public/assets/2.jpg +0 -0
- package/dist/templates/standalone/public/assets/3.jpg +0 -0
- package/dist/templates/standalone/public/assets/app-select.svg +11 -0
- package/dist/templates/standalone/public/assets/avatar.jpg +0 -0
- package/dist/templates/standalone/public/assets/background.jpg +0 -0
- package/dist/templates/standalone/public/assets/empty.png +0 -0
- package/dist/templates/standalone/public/assets/logo-white.svg +21 -0
- package/dist/templates/standalone/public/assets/logo.svg +8 -0
- package/dist/templates/standalone/public/assets/welcome.png +0 -0
- package/dist/templates/standalone/public/img/icons/apple-touch-icon.png +0 -0
- package/dist/templates/standalone/public/img/icons/favicon-16x16.png +0 -0
- package/dist/templates/standalone/public/img/icons/favicon-32x32.png +0 -0
- package/dist/templates/standalone/public/img/icons/favicon.ico +0 -0
- package/dist/templates/standalone/public/img/icons/mstile-150x150.png +0 -0
- package/dist/templates/standalone/public/img/icons/safari-pinned-tab.svg +32 -0
- package/dist/templates/standalone/src/api_client/README.md +199 -0
- package/dist/templates/standalone/src/bootstrap.ts.ejs +26 -0
- package/dist/templates/standalone/src/components/dashboard-widgets/Welcome.vue +51 -0
- package/dist/templates/standalone/src/composables/index.ts +1 -0
- package/dist/templates/standalone/src/env.d.ts +9 -0
- package/dist/templates/standalone/src/locales/en.json +16 -0
- package/dist/templates/standalone/src/locales/index.ts +2 -0
- package/dist/templates/{sample/overrides/main.ts → standalone/src/main.ts.ejs} +22 -9
- package/dist/templates/standalone/src/pages/App.vue.ejs +38 -0
- package/dist/templates/standalone/src/pages/Dashboard.vue.ejs +7 -0
- package/dist/templates/standalone/src/router/index.ts +10 -0
- package/dist/templates/{base/src/router/routes.ts → standalone/src/router/routes.ts.ejs} +27 -7
- package/dist/templates/standalone/src/shims-vue.d.ts +27 -0
- package/dist/templates/standalone/src/styles/custom.scss +116 -0
- package/dist/templates/standalone/src/styles/index.scss +8 -0
- package/dist/templates/standalone/src/vue-i18n.d.ts +10 -0
- package/dist/templates/standalone/tailwind.config.ts +7 -0
- package/dist/templates/standalone/tsconfig.json +16 -0
- package/dist/templates/standalone/yarn.lock +0 -0
- package/dist/types.d.ts +23 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +7 -4
- package/dist/templates/modules/classic-module/composables/index.ts +0 -2
- package/dist/templates/modules/classic-module/composables/use{{ModuleNamePascalCase}}Details/index.ts +0 -24
- package/dist/templates/modules/classic-module/composables/use{{ModuleNamePascalCase}}List/index.ts +0 -47
- package/dist/templates/modules/classic-module/locales/en.json +0 -37
- package/dist/templates/modules/classic-module/pages/details.vue +0 -87
- package/dist/templates/modules/classic-module/pages/list.vue +0 -257
- package/dist/templates/sample/classic-module/pages/index.ts +0 -2
- /package/dist/templates/{base → host-app}/LICENSE +0 -0
- /package/dist/templates/{base → host-app}/README.md +0 -0
- /package/dist/templates/{base → host-app}/_browserslistrc +0 -0
- /package/dist/templates/{base → host-app}/_commitlintrc.json +0 -0
- /package/dist/templates/{base → host-app}/_editorconfig +0 -0
- /package/dist/templates/{base/_env.local → host-app/_env.local.ejs} +0 -0
- /package/dist/templates/{base → host-app}/_eslintignore +0 -0
- /package/dist/templates/{base → host-app}/_eslintrc.js +0 -0
- /package/dist/templates/{base → host-app}/_github/COMMIT_CONVENTION.md +0 -0
- /package/dist/templates/{base → host-app}/_github/PULL_REQUEST_TEMPLATE.md +0 -0
- /package/dist/templates/{base → host-app}/_gitignore +0 -0
- /package/dist/templates/{base → host-app}/_prettierignore +0 -0
- /package/dist/templates/{base → host-app}/_prettierrc +0 -0
- /package/dist/templates/{base → host-app}/_vscode/extensions.json +0 -0
- /package/dist/templates/{base → host-app}/_vscode/settings.json +0 -0
- /package/dist/templates/{base → host-app}/_yarn/releases/yarn-4.9.1.cjs +0 -0
- /package/dist/templates/{base → host-app}/_yarnrc.yml +0 -0
- /package/dist/templates/{base → host-app}/postcss.config.cjs +0 -0
- /package/dist/templates/{base → host-app}/public/assets/1.jpeg +0 -0
- /package/dist/templates/{base → host-app}/public/assets/2.jpg +0 -0
- /package/dist/templates/{base → host-app}/public/assets/3.jpg +0 -0
- /package/dist/templates/{base → host-app}/public/assets/app-select.svg +0 -0
- /package/dist/templates/{base → host-app}/public/assets/avatar.jpg +0 -0
- /package/dist/templates/{base → host-app}/public/assets/background.jpg +0 -0
- /package/dist/templates/{base → host-app}/public/assets/empty.png +0 -0
- /package/dist/templates/{base → host-app}/public/assets/logo-white.svg +0 -0
- /package/dist/templates/{base → host-app}/public/assets/logo.svg +0 -0
- /package/dist/templates/{base → host-app}/public/assets/welcome.png +0 -0
- /package/dist/templates/{base → host-app}/public/img/icons/apple-touch-icon.png +0 -0
- /package/dist/templates/{base → host-app}/public/img/icons/favicon-16x16.png +0 -0
- /package/dist/templates/{base → host-app}/public/img/icons/favicon-32x32.png +0 -0
- /package/dist/templates/{base → host-app}/public/img/icons/favicon.ico +0 -0
- /package/dist/templates/{base → host-app}/public/img/icons/mstile-150x150.png +0 -0
- /package/dist/templates/{base → host-app}/public/img/icons/safari-pinned-tab.svg +0 -0
- /package/dist/templates/{base → host-app}/src/api_client/README.md +0 -0
- /package/dist/templates/{base → host-app}/src/components/dashboard-widgets/Welcome.vue +0 -0
- /package/dist/templates/{base → host-app}/src/composables/index.ts +0 -0
- /package/dist/templates/{base → host-app}/src/env.d.ts +0 -0
- /package/dist/templates/{base → host-app}/src/locales/en.json +0 -0
- /package/dist/templates/{base → host-app}/src/locales/index.ts +0 -0
- /package/dist/templates/{base/src/pages/Dashboard.vue → host-app/src/pages/Dashboard.vue.ejs} +0 -0
- /package/dist/templates/{base → host-app}/src/router/index.ts +0 -0
- /package/dist/templates/{base → host-app}/src/shims-vue.d.ts +0 -0
- /package/dist/templates/{base → host-app}/src/styles/custom.scss +0 -0
- /package/dist/templates/{base → host-app}/src/styles/index.scss +0 -0
- /package/dist/templates/{base → host-app}/src/vue-i18n.d.ts +0 -0
- /package/dist/templates/{base → host-app}/tailwind.config.ts +0 -0
- /package/dist/templates/{base → host-app}/tsconfig.json +0 -0
- /package/dist/templates/{base → host-app}/yarn.lock +0 -0
- /package/dist/templates/{modules/classic-module/index.ts → module/index.ts.ejs} +0 -0
- /package/dist/templates/{modules/classic-module → module}/locales/index.ts +0 -0
- /package/dist/templates/{sample/classic-module → sample-module}/composables/index.ts +0 -0
- /package/dist/templates/{sample/classic-module → sample-module}/composables/useDetails/index.ts +0 -0
- /package/dist/templates/{sample/classic-module → sample-module}/composables/useList/index.ts +0 -0
- /package/dist/templates/{sample/classic-module → sample-module}/index.ts +0 -0
- /package/dist/templates/{sample/classic-module → sample-module}/locales/en.json +0 -0
- /package/dist/templates/{sample/classic-module → sample-module}/locales/index.ts +0 -0
- /package/dist/templates/{modules/classic-module → sample-module}/pages/index.ts +0 -0
- /package/dist/templates/{mocks → sample-module}/sample-data/constants.ts +0 -0
- /package/dist/templates/{mocks → sample-module}/sample-data/index.ts +0 -0
- /package/dist/templates/{mocks → sample-module}/sample-data/methods.ts +0 -0
- /package/dist/templates/{base/vite.config.mts → standalone/vite.config.mts.ejs} +0 -0
package/dist/output.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAQjD,wBAAgB,YAAY,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI,CAsB1D"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "<%- PackageName %>",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"scripts": {
|
|
6
|
+
"serve": "cross-env APP_ENV=development vite --force",
|
|
7
|
+
"build": "cross-env APP_ENV=production vite build",
|
|
8
|
+
"build:types": "vue-tsc --declaration --emitDeclarationOnly --outDir dist/types",
|
|
9
|
+
"type-check": "vue-tsc --noEmit"
|
|
10
|
+
},
|
|
11
|
+
"devDependencies": {
|
|
12
|
+
"@types/node": "^20.10.5",
|
|
13
|
+
"@vc-shell/ts-config": "^2.0.0-alpha.1",
|
|
14
|
+
"cross-env": "^7.0.3",
|
|
15
|
+
"sass": "^1.87.0",
|
|
16
|
+
"typescript": "^5.8.3",
|
|
17
|
+
"vite": "^6.3.3",
|
|
18
|
+
"vue-tsc": "^2.2.10"
|
|
19
|
+
},
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"@vc-shell/config-generator": "^2.0.0-alpha.1",
|
|
22
|
+
"@vc-shell/framework": "^2.0.0-alpha.1",
|
|
23
|
+
"vue": "^3.5.13",
|
|
24
|
+
"vue-router": "^4.2.5"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "
|
|
2
|
+
"name": "<%- PackageName %>",
|
|
3
3
|
"version": "0.0.0",
|
|
4
4
|
"private": true,
|
|
5
5
|
"scripts": {
|
|
@@ -22,14 +22,14 @@
|
|
|
22
22
|
"@types/node": "^20.10.5",
|
|
23
23
|
"@typescript-eslint/eslint-plugin": "^7.4.0",
|
|
24
24
|
"@typescript-eslint/parser": "^7.4.0",
|
|
25
|
-
"@vc-shell/api-client-generator": "^
|
|
26
|
-
"@vc-shell/release-config": "^
|
|
27
|
-
"@vc-shell/ts-config": "^
|
|
25
|
+
"@vc-shell/api-client-generator": "^2.0.0-alpha.1",
|
|
26
|
+
"@vc-shell/release-config": "^2.0.0-alpha.1",
|
|
27
|
+
"@vc-shell/ts-config": "^2.0.0-alpha.1",
|
|
28
28
|
"@vitejs/plugin-vue": "^5.2.3",
|
|
29
29
|
"@vue/eslint-config-prettier": "^9.0.0",
|
|
30
30
|
"@vue/eslint-config-typescript": "^13.0.0",
|
|
31
31
|
"autoprefixer": "^10.4.16",
|
|
32
|
-
"conventional-changelog-cli": "^
|
|
32
|
+
"conventional-changelog-cli": "^5.0.0",
|
|
33
33
|
"cross-env": "^7.0.3",
|
|
34
34
|
"eslint": "^8.57.0",
|
|
35
35
|
"eslint-import-resolver-typescript": "^3.6.1",
|
|
@@ -52,8 +52,8 @@
|
|
|
52
52
|
"vue-tsc": "^2.2.10"
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"@vc-shell/config-generator": "^
|
|
56
|
-
"@vc-shell/framework": "^
|
|
55
|
+
"@vc-shell/config-generator": "^2.0.0-alpha.1",
|
|
56
|
+
"@vc-shell/framework": "^2.0.0-alpha.1",
|
|
57
57
|
"@vueuse/core": "^10.7.1",
|
|
58
58
|
"@vueuse/integrations": "^10.7.1",
|
|
59
59
|
"cross-spawn": "^7.0.3",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
<link rel="icon" type="image/png" sizes="32x32" href="img/icons/favicon-32x32.png">
|
|
12
12
|
<link rel="icon" type="image/png" sizes="16x16" href="img/icons/favicon-16x16.png">
|
|
13
13
|
<meta name="theme-color" content="#ffffff">
|
|
14
|
-
<title
|
|
14
|
+
<title><%- AppNameSentenceCase %></title>
|
|
15
15
|
</head>
|
|
16
16
|
|
|
17
17
|
<body>
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
import { App } from "vue";
|
|
2
|
+
<% if (dashboard) { %>
|
|
1
3
|
import { addMenuItem, registerDashboardWidget } from "@vc-shell/framework";
|
|
2
|
-
import {
|
|
4
|
+
import { markRaw } from "vue";
|
|
3
5
|
import Welcome from "./components/dashboard-widgets/Welcome.vue";
|
|
6
|
+
<% } %>
|
|
4
7
|
|
|
5
8
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
6
9
|
export function bootstrap(app: App) {
|
|
7
|
-
|
|
10
|
+
<% if (dashboard) { %>
|
|
8
11
|
addMenuItem({
|
|
9
12
|
title: "SHELL.MENU.DASHBOARD",
|
|
10
13
|
icon: "lucide-home",
|
|
@@ -12,7 +15,6 @@ export function bootstrap(app: App) {
|
|
|
12
15
|
url: "/",
|
|
13
16
|
});
|
|
14
17
|
|
|
15
|
-
// Register Dashboard Welcome Widget
|
|
16
18
|
registerDashboardWidget({
|
|
17
19
|
id: "welcome-widget",
|
|
18
20
|
name: "Welcome",
|
|
@@ -20,4 +22,5 @@ export function bootstrap(app: App) {
|
|
|
20
22
|
size: { width: 6, height: 6 },
|
|
21
23
|
position: { x: 0, y: 0 },
|
|
22
24
|
});
|
|
25
|
+
<% } %>
|
|
23
26
|
}
|
|
@@ -3,16 +3,13 @@ import { createApp } from "vue";
|
|
|
3
3
|
import { router } from "./router";
|
|
4
4
|
import * as locales from "./locales";
|
|
5
5
|
import { RouterView } from "vue-router";
|
|
6
|
-
import {{ModuleNamePascalCase}} from "./modules/{{ModuleName}}";
|
|
7
6
|
import { bootstrap } from "./bootstrap";
|
|
8
7
|
|
|
9
|
-
// Load required CSS
|
|
10
8
|
import "@vc-shell/framework/dist/index.css";
|
|
11
9
|
|
|
12
10
|
async function startApp() {
|
|
13
11
|
const { loadUser } = useUser();
|
|
14
12
|
|
|
15
|
-
|
|
16
13
|
try {
|
|
17
14
|
await loadUser();
|
|
18
15
|
} catch (e) {
|
|
@@ -26,9 +23,14 @@ async function startApp() {
|
|
|
26
23
|
locale: import.meta.env.APP_I18N_LOCALE,
|
|
27
24
|
fallbackLocale: import.meta.env.APP_I18N_FALLBACK_LOCALE,
|
|
28
25
|
},
|
|
26
|
+
<% if (aiAgent) { %>
|
|
27
|
+
aiAgent: {
|
|
28
|
+
config: {
|
|
29
|
+
url: import.meta.env.APP_AI_AGENT_URL,
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
<% } %>
|
|
29
33
|
})
|
|
30
|
-
// {{ModuleNamePascalCase}} module initialization
|
|
31
|
-
.use({{ModuleNamePascalCase}}, { router })
|
|
32
34
|
.use(router);
|
|
33
35
|
|
|
34
36
|
const { currentLocale, setLocale } = app.runWithContext(() => useLanguages());
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="tw-w-full tw-h-full">
|
|
3
|
+
<iframe
|
|
4
|
+
v-if="url"
|
|
5
|
+
ref="iframeRef"
|
|
6
|
+
:src="url"
|
|
7
|
+
class="tw-w-full tw-h-full tw-border-0"
|
|
8
|
+
allow="clipboard-read; clipboard-write"
|
|
9
|
+
/>
|
|
10
|
+
</div>
|
|
11
|
+
</template>
|
|
12
|
+
|
|
13
|
+
<script setup lang="ts">
|
|
14
|
+
import { computed } from "vue";
|
|
15
|
+
import { useRoute } from "vue-router";
|
|
16
|
+
|
|
17
|
+
const route = useRoute();
|
|
18
|
+
const url = computed(() => route.query.url as string | undefined);
|
|
19
|
+
</script>
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { RouteRecordRaw } from "vue-router";
|
|
2
|
+
import App from "../pages/App.vue";
|
|
3
|
+
<% if (dashboard) { %>
|
|
4
|
+
import Dashboard from "../pages/Dashboard.vue";
|
|
5
|
+
<% } %>
|
|
6
|
+
import Platform from "../pages/Platform.vue";
|
|
7
|
+
import { Invite, Login, ResetPassword, ForgotPassword, ChangePasswordPage } from "@vc-shell/framework";
|
|
8
|
+
// eslint-disable-next-line import/no-unresolved
|
|
9
|
+
import whiteLogoImage from "/assets/logo-white.svg";
|
|
10
|
+
// eslint-disable-next-line import/no-unresolved
|
|
11
|
+
import bgImage from "/assets/background.jpg";
|
|
12
|
+
|
|
13
|
+
<% if (tenantRoutes) { %>
|
|
14
|
+
const tenantIdRegex = "[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}";
|
|
15
|
+
<% } %>
|
|
16
|
+
|
|
17
|
+
export const routes: RouteRecordRaw[] = [
|
|
18
|
+
{
|
|
19
|
+
<% if (tenantRoutes) { %>
|
|
20
|
+
path: `/:tenantId(${tenantIdRegex})?`,
|
|
21
|
+
<% } else { %>
|
|
22
|
+
path: "/",
|
|
23
|
+
<% } %>
|
|
24
|
+
component: App,
|
|
25
|
+
name: "App",
|
|
26
|
+
meta: {
|
|
27
|
+
root: true,
|
|
28
|
+
},
|
|
29
|
+
children: [
|
|
30
|
+
<% if (dashboard) { %>
|
|
31
|
+
{
|
|
32
|
+
name: "Dashboard",
|
|
33
|
+
path: "",
|
|
34
|
+
component: Dashboard,
|
|
35
|
+
},
|
|
36
|
+
<% } %>
|
|
37
|
+
{
|
|
38
|
+
name: "Platform",
|
|
39
|
+
path: "platform",
|
|
40
|
+
component: Platform,
|
|
41
|
+
props: (route) => ({
|
|
42
|
+
url: route.query.url,
|
|
43
|
+
}),
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
<% if (tenantRoutes) { %>
|
|
47
|
+
beforeEnter: (to) => {
|
|
48
|
+
const { tenantId } = to.params;
|
|
49
|
+
if (!tenantId || new RegExp(tenantIdRegex).test(tenantId as string)) {
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
return { path: "/" };
|
|
53
|
+
},
|
|
54
|
+
<% } %>
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
name: "Login",
|
|
58
|
+
path: "/login",
|
|
59
|
+
component: Login,
|
|
60
|
+
props: () => ({
|
|
61
|
+
logo: whiteLogoImage,
|
|
62
|
+
title: "<%- AppNameSentenceCase %>",
|
|
63
|
+
}),
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
name: "Invite",
|
|
67
|
+
path: "/invite",
|
|
68
|
+
component: Invite,
|
|
69
|
+
props: (_route) => ({
|
|
70
|
+
userId: _route.query.userId,
|
|
71
|
+
token: _route.query.token,
|
|
72
|
+
userName: _route.query.userName,
|
|
73
|
+
logo: whiteLogoImage,
|
|
74
|
+
}),
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
name: "ResetPassword",
|
|
78
|
+
path: "/resetpassword",
|
|
79
|
+
component: ResetPassword,
|
|
80
|
+
props: (_route) => ({
|
|
81
|
+
userId: _route.query.userId,
|
|
82
|
+
token: _route.query.token,
|
|
83
|
+
userName: _route.query.userName,
|
|
84
|
+
logo: whiteLogoImage,
|
|
85
|
+
}),
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
name: "ForgotPassword",
|
|
89
|
+
path: "/forgot-password",
|
|
90
|
+
component: ForgotPassword,
|
|
91
|
+
props: () => ({
|
|
92
|
+
logo: whiteLogoImage,
|
|
93
|
+
}),
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
name: "ChangePassword",
|
|
97
|
+
path: "/changepassword",
|
|
98
|
+
component: ChangePasswordPage,
|
|
99
|
+
meta: {
|
|
100
|
+
forced: true,
|
|
101
|
+
},
|
|
102
|
+
props: (_route) => ({
|
|
103
|
+
forced: _route.meta.forced,
|
|
104
|
+
logo: whiteLogoImage,
|
|
105
|
+
}),
|
|
106
|
+
},
|
|
107
|
+
];
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { ref } from "vue";
|
|
2
|
+
import { useAsync, useLoading } from "@vc-shell/framework";
|
|
3
|
+
|
|
4
|
+
export default function use<%- ModuleNamePascalCase %>Details() {
|
|
5
|
+
const item = ref<Record<string, unknown>>({});
|
|
6
|
+
|
|
7
|
+
const { loading: itemLoading, action: fetchItem } = useAsync(async (id?: string) => {
|
|
8
|
+
// TODO: Replace with real API call
|
|
9
|
+
// const result = await apiClient.getById(id);
|
|
10
|
+
// item.value = result;
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const { loading: saveLoading, action: saveAction } = useAsync(async () => {
|
|
14
|
+
// TODO: Replace with real API call
|
|
15
|
+
// if (item.value.id) {
|
|
16
|
+
// await apiClient.update(item.value);
|
|
17
|
+
// } else {
|
|
18
|
+
// await apiClient.create(item.value);
|
|
19
|
+
// }
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const loading = useLoading(itemLoading, saveLoading);
|
|
23
|
+
|
|
24
|
+
async function getItem(id: string) {
|
|
25
|
+
await fetchItem(id);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async function saveItem() {
|
|
29
|
+
await saveAction();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
item,
|
|
34
|
+
loading,
|
|
35
|
+
getItem,
|
|
36
|
+
saveItem,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { ref, type Ref } from "vue";
|
|
2
|
+
import { useAsync, useLoading } from "@vc-shell/framework";
|
|
3
|
+
|
|
4
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5
|
+
export default function use<%- ModuleNamePascalCase %>List() {
|
|
6
|
+
const data: Ref<Record<string, any>[]> = ref([]);
|
|
7
|
+
const totalCount = ref(0);
|
|
8
|
+
const currentPage = ref(1);
|
|
9
|
+
const searchQuery = ref("");
|
|
10
|
+
|
|
11
|
+
const { loading: itemsLoading, action: fetchItems } = useAsync(async () => {
|
|
12
|
+
// TODO: Replace with real API call
|
|
13
|
+
// const result = await apiClient.search({
|
|
14
|
+
// keyword: searchQuery.value,
|
|
15
|
+
// skip: (currentPage.value - 1) * 20,
|
|
16
|
+
// take: 20,
|
|
17
|
+
// });
|
|
18
|
+
// data.value = result.results ?? [];
|
|
19
|
+
// totalCount.value = result.totalCount ?? 0;
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const { loading: deleteLoading, action: removeItems } = useAsync(async (ids?: string[]) => {
|
|
23
|
+
// TODO: Replace with real API call
|
|
24
|
+
// await Promise.all((ids ?? []).map((id) => apiClient.delete(id)));
|
|
25
|
+
// await fetchItems();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const loading = useLoading(itemsLoading, deleteLoading);
|
|
29
|
+
|
|
30
|
+
async function getItems() {
|
|
31
|
+
await fetchItems();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
data,
|
|
36
|
+
loading,
|
|
37
|
+
totalCount,
|
|
38
|
+
currentPage,
|
|
39
|
+
searchQuery,
|
|
40
|
+
getItems,
|
|
41
|
+
removeItems,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"<%- ModuleNameScreamingSnake %>": {
|
|
3
|
+
"MENU": {
|
|
4
|
+
"TITLE": "<%- ModuleNameSentenceCase %>"
|
|
5
|
+
},
|
|
6
|
+
"PAGES": {
|
|
7
|
+
"LIST": {
|
|
8
|
+
"TITLE": "<%- ModuleNameSentenceCase %>",
|
|
9
|
+
"TOOLBAR": {
|
|
10
|
+
"REFRESH": "Refresh",
|
|
11
|
+
"ADD": "Add"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"DETAILS": {
|
|
15
|
+
"TITLE": "<%- ModuleNameSentenceCase %> Details"
|
|
16
|
+
},
|
|
17
|
+
"ALERTS": {
|
|
18
|
+
"CLOSE_CONFIRMATION": "You have unsaved changes. Close anyway?"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<VcBlade
|
|
3
|
+
:title="title"
|
|
4
|
+
:toolbar-items="bladeToolbar"
|
|
5
|
+
:loading="loading"
|
|
6
|
+
:expanded="expanded"
|
|
7
|
+
:closable="closable"
|
|
8
|
+
width="70%"
|
|
9
|
+
@close="$emit('close:blade')"
|
|
10
|
+
@expand="$emit('expand:blade')"
|
|
11
|
+
@collapse="$emit('collapse:blade')"
|
|
12
|
+
>
|
|
13
|
+
<VcContainer>
|
|
14
|
+
<VcForm>
|
|
15
|
+
<!-- Add your form fields here -->
|
|
16
|
+
<VcInput
|
|
17
|
+
v-model="item.name"
|
|
18
|
+
:label="'Name'"
|
|
19
|
+
required
|
|
20
|
+
/>
|
|
21
|
+
</VcForm>
|
|
22
|
+
</VcContainer>
|
|
23
|
+
</VcBlade>
|
|
24
|
+
</template>
|
|
25
|
+
|
|
26
|
+
<script setup lang="ts">
|
|
27
|
+
import {
|
|
28
|
+
VcBlade,
|
|
29
|
+
VcContainer,
|
|
30
|
+
VcForm,
|
|
31
|
+
VcInput,
|
|
32
|
+
useBladeNavigation,
|
|
33
|
+
useModificationTracker,
|
|
34
|
+
usePopup,
|
|
35
|
+
useBeforeUnload,
|
|
36
|
+
type IBladeToolbar,
|
|
37
|
+
type IParentCallArgs,
|
|
38
|
+
} from "@vc-shell/framework";
|
|
39
|
+
import { ref, computed, onMounted } from "vue";
|
|
40
|
+
import use<%- ModuleNamePascalCase %>Details from "../composables/useDetails";
|
|
41
|
+
|
|
42
|
+
export interface Props {
|
|
43
|
+
expanded?: boolean;
|
|
44
|
+
closable?: boolean;
|
|
45
|
+
param?: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface Emits {
|
|
49
|
+
(event: "parent:call", args: IParentCallArgs): void;
|
|
50
|
+
(event: "collapse:blade"): void;
|
|
51
|
+
(event: "expand:blade"): void;
|
|
52
|
+
(event: "close:blade"): void;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
defineOptions({
|
|
56
|
+
url: "/<%- ModuleName %>-details",
|
|
57
|
+
name: "<%- ModuleNamePascalCase %>Details",
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
61
|
+
expanded: true,
|
|
62
|
+
closable: true,
|
|
63
|
+
param: undefined,
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const emit = defineEmits<Emits>();
|
|
67
|
+
|
|
68
|
+
const { onBeforeClose } = useBladeNavigation();
|
|
69
|
+
const { showConfirmation } = usePopup();
|
|
70
|
+
|
|
71
|
+
const { item, loading, getItem, saveItem } = use<%- ModuleNamePascalCase %>Details();
|
|
72
|
+
const { isModified, resetModificationState } = useModificationTracker(item);
|
|
73
|
+
|
|
74
|
+
const title = computed(() => {
|
|
75
|
+
return props.param
|
|
76
|
+
? String(item.value?.name || "<%- ModuleNameSentenceCase %> Details")
|
|
77
|
+
: "New <%- ModuleNameSentenceCase %>";
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
const bladeToolbar = ref<IBladeToolbar[]>([
|
|
81
|
+
{
|
|
82
|
+
id: "save",
|
|
83
|
+
title: "Save",
|
|
84
|
+
icon: "lucide-save",
|
|
85
|
+
disabled: computed(() => !isModified.value),
|
|
86
|
+
async clickHandler() {
|
|
87
|
+
await saveItem();
|
|
88
|
+
resetModificationState();
|
|
89
|
+
emit("parent:call", { method: "reload" });
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
]);
|
|
93
|
+
|
|
94
|
+
onMounted(async () => {
|
|
95
|
+
if (props.param) {
|
|
96
|
+
await getItem(props.param);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
onBeforeClose(async () => {
|
|
101
|
+
if (isModified.value) {
|
|
102
|
+
return await showConfirmation("You have unsaved changes. Are you sure you want to close?");
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
useBeforeUnload(computed(() => isModified.value));
|
|
107
|
+
|
|
108
|
+
defineExpose({
|
|
109
|
+
title,
|
|
110
|
+
});
|
|
111
|
+
</script>
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<VcBlade
|
|
3
|
+
:title="$t('<%- ModuleNameScreamingSnake %>.PAGES.LIST.TITLE')"
|
|
4
|
+
:toolbar-items="bladeToolbar"
|
|
5
|
+
:loading="loading"
|
|
6
|
+
:expanded="expanded"
|
|
7
|
+
:closable="closable"
|
|
8
|
+
width="50%"
|
|
9
|
+
@close="$emit('close:blade')"
|
|
10
|
+
@expand="$emit('expand:blade')"
|
|
11
|
+
@collapse="$emit('collapse:blade')"
|
|
12
|
+
>
|
|
13
|
+
<VcDataTable
|
|
14
|
+
:items="data"
|
|
15
|
+
:total-count="totalCount"
|
|
16
|
+
:current-page="currentPage"
|
|
17
|
+
:search-value="searchQuery"
|
|
18
|
+
:state-key="'<%- ModuleNameScreamingSnake %>'"
|
|
19
|
+
@search:change="(val: string) => { searchQuery = val; getItems(); }"
|
|
20
|
+
@item-click="openDetails"
|
|
21
|
+
@pagination-click="(page: number) => { currentPage = page; getItems(); }"
|
|
22
|
+
>
|
|
23
|
+
<!-- Add your columns here -->
|
|
24
|
+
<VcColumn id="name" :header="'Name'" sortable />
|
|
25
|
+
<VcColumn id="createdDate" :header="'Created'" type="datetime" sortable />
|
|
26
|
+
</VcDataTable>
|
|
27
|
+
</VcBlade>
|
|
28
|
+
</template>
|
|
29
|
+
|
|
30
|
+
<script setup lang="ts">
|
|
31
|
+
import {
|
|
32
|
+
VcBlade,
|
|
33
|
+
VcDataTable,
|
|
34
|
+
VcColumn,
|
|
35
|
+
useBladeNavigation,
|
|
36
|
+
type IBladeToolbar,
|
|
37
|
+
type IParentCallArgs,
|
|
38
|
+
} from "@vc-shell/framework";
|
|
39
|
+
import { ref, computed, markRaw } from "vue";
|
|
40
|
+
import use<%- ModuleNamePascalCase %>List from "../composables/useList";
|
|
41
|
+
import Details from "./details.vue";
|
|
42
|
+
|
|
43
|
+
export interface Props {
|
|
44
|
+
expanded?: boolean;
|
|
45
|
+
closable?: boolean;
|
|
46
|
+
param?: string;
|
|
47
|
+
options?: Record<string, unknown>;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface Emits {
|
|
51
|
+
(event: "parent:call", args: IParentCallArgs): void;
|
|
52
|
+
(event: "collapse:blade"): void;
|
|
53
|
+
(event: "expand:blade"): void;
|
|
54
|
+
(event: "close:blade"): void;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
defineOptions({
|
|
58
|
+
url: "/<%- ModuleName %>",
|
|
59
|
+
name: "<%- ModuleNamePascalCase %>List",
|
|
60
|
+
isWorkspace: true,
|
|
61
|
+
menuItem: {
|
|
62
|
+
title: "<%- ModuleNameScreamingSnake %>.MENU.TITLE",
|
|
63
|
+
icon: "lucide-box",
|
|
64
|
+
priority: 10,
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
69
|
+
expanded: true,
|
|
70
|
+
closable: true,
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
defineEmits<Emits>();
|
|
74
|
+
|
|
75
|
+
const { openBlade } = useBladeNavigation();
|
|
76
|
+
|
|
77
|
+
const {
|
|
78
|
+
data,
|
|
79
|
+
loading,
|
|
80
|
+
totalCount,
|
|
81
|
+
currentPage,
|
|
82
|
+
searchQuery,
|
|
83
|
+
getItems,
|
|
84
|
+
} = use<%- ModuleNamePascalCase %>List();
|
|
85
|
+
|
|
86
|
+
const bladeToolbar = ref<IBladeToolbar[]>([
|
|
87
|
+
{
|
|
88
|
+
id: "refresh",
|
|
89
|
+
title: "Refresh",
|
|
90
|
+
icon: "lucide-refresh-cw",
|
|
91
|
+
clickHandler: () => getItems(),
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
id: "add",
|
|
95
|
+
title: "Add",
|
|
96
|
+
icon: "lucide-plus",
|
|
97
|
+
clickHandler: () => openDetails(),
|
|
98
|
+
},
|
|
99
|
+
]);
|
|
100
|
+
|
|
101
|
+
function openDetails(item?: { id?: string }) {
|
|
102
|
+
openBlade({
|
|
103
|
+
blade: markRaw(Details),
|
|
104
|
+
param: item?.id,
|
|
105
|
+
onClose() {
|
|
106
|
+
getItems();
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
getItems();
|
|
112
|
+
|
|
113
|
+
defineExpose({
|
|
114
|
+
title: computed(() => "<%- ModuleNameSentenceCase %>"),
|
|
115
|
+
reload: getItems,
|
|
116
|
+
});
|
|
117
|
+
</script>
|