@jskit-ai/ui-generator 0.1.3
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 +73 -0
- package/package.descriptor.mjs +121 -0
- package/package.json +14 -0
- package/src/server/buildTemplateContext.js +17 -0
- package/src/server/subcommands/container.js +481 -0
- package/src/server/subcommands/element.js +148 -0
- package/src/server/subcommands/support.js +165 -0
- package/templates/src/pages/admin/ui-generator/Page.vue +6 -0
- package/test/buildTemplateContext.test.js +148 -0
- package/test/containerSubcommand.test.js +133 -0
- package/test/elementSubcommand.test.js +127 -0
package/README.md
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# @jskit-ai/ui-generator
|
|
2
|
+
|
|
3
|
+
Generate non-CRUD UI pages and outlet elements for JSKIT apps.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
List available placement targets in the current app:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx jskit list placements
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Generate a page (default placement target):
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npx jskit generate @jskit-ai/ui-generator page --name "Reports Dashboard" --surface admin
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Generate a page in a subdirectory:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npx jskit generate @jskit-ai/ui-generator page --name "Reports Dashboard" --surface admin --directory-prefix ops
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Generate a page and place its menu entry in the workspace cog dropdown:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npx jskit generate @jskit-ai/ui-generator page --name "Reports" --surface admin --placement workspace-tools:primary-menu
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Generate an element at a specific outlet:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npx jskit generate @jskit-ai/ui-generator element --name "Ops Panel" --surface admin --placement workspace-settings:forms
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Generate an element with custom component path:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
npx jskit generate @jskit-ai/ui-generator element --name "Alerts Widget" --surface admin --path src/widgets --placement shell-layout:top-right
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Generate a route container page with nested outlet (for embedded sub-pages):
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
npx jskit generate @jskit-ai/ui-generator container --name "Practice" --surface admin
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Commands
|
|
50
|
+
|
|
51
|
+
- `page`: `--name --surface [--directory-prefix] [--placement]`
|
|
52
|
+
- `element`: `--name --surface [--path] [--placement]`
|
|
53
|
+
- `container`: `--name --surface [--directory-prefix] [--placement]`
|
|
54
|
+
|
|
55
|
+
## Container Workflow
|
|
56
|
+
|
|
57
|
+
- `container` creates app-owned scaffolding:
|
|
58
|
+
- `src/components/SectionContainerShell.vue` (shared container shell with responsive tab row)
|
|
59
|
+
- `src/components/SectionShellTabLinkItem.vue` (tab link item token component)
|
|
60
|
+
- `packages/main/src/client/providers/MainClientProvider.js` registration for `local.main.ui.section-shell.tab-link-item`
|
|
61
|
+
- `<route>.vue` as a thin wrapper around `SectionContainerShell` + `<RouterView />`
|
|
62
|
+
- Generate CRUD pages into that container using `@jskit-ai/crud-ui-generator` with:
|
|
63
|
+
- `--container <route-slug>`
|
|
64
|
+
- `--route-path <resource-slug>`
|
|
65
|
+
- optional `--placement` override (default becomes `<container>:sub-pages` for list pages)
|
|
66
|
+
|
|
67
|
+
## Placement Notes
|
|
68
|
+
|
|
69
|
+
- `--placement` expects `host:position`.
|
|
70
|
+
- Targets come from:
|
|
71
|
+
- app-declared `<ShellOutlet host="..." position="..." />` in `src/**/*.vue`
|
|
72
|
+
- installed package metadata `metadata.ui.placements.outlets`
|
|
73
|
+
- If `--placement` is omitted, the app default outlet is used.
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
export default Object.freeze({
|
|
2
|
+
packageVersion: 1,
|
|
3
|
+
packageId: "@jskit-ai/ui-generator",
|
|
4
|
+
version: "0.1.3",
|
|
5
|
+
kind: "generator",
|
|
6
|
+
description: "Generate app-local non-CRUD UI pages and outlet elements.",
|
|
7
|
+
options: {
|
|
8
|
+
name: {
|
|
9
|
+
required: true,
|
|
10
|
+
inputType: "text",
|
|
11
|
+
defaultValue: "",
|
|
12
|
+
promptLabel: "Element name",
|
|
13
|
+
promptHint: "Display name and route slug source (example: Reports Dashboard)."
|
|
14
|
+
},
|
|
15
|
+
surface: {
|
|
16
|
+
required: true,
|
|
17
|
+
inputType: "text",
|
|
18
|
+
defaultFromConfig: "surfaceDefaultId",
|
|
19
|
+
promptLabel: "Target surface",
|
|
20
|
+
promptHint: "Defaults to config.public.surfaceDefaultId. Must match an enabled surface id."
|
|
21
|
+
},
|
|
22
|
+
path: {
|
|
23
|
+
required: false,
|
|
24
|
+
inputType: "text",
|
|
25
|
+
defaultValue: "src/components",
|
|
26
|
+
promptLabel: "Component path",
|
|
27
|
+
promptHint: "Component directory relative to app root (used by element subcommand)."
|
|
28
|
+
},
|
|
29
|
+
"directory-prefix": {
|
|
30
|
+
required: false,
|
|
31
|
+
inputType: "text",
|
|
32
|
+
defaultValue: "",
|
|
33
|
+
promptLabel: "Page directory prefix",
|
|
34
|
+
promptHint: "Optional subpath under the selected surface pages root (example: crm or ops/team-a)."
|
|
35
|
+
},
|
|
36
|
+
placement: {
|
|
37
|
+
required: false,
|
|
38
|
+
inputType: "text",
|
|
39
|
+
defaultValue: "",
|
|
40
|
+
promptLabel: "Placement target",
|
|
41
|
+
promptHint: "Optional host:position target (defaults to app ShellOutlet default target)."
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
dependsOn: [],
|
|
45
|
+
capabilities: {
|
|
46
|
+
provides: ["ui-generator"],
|
|
47
|
+
requires: []
|
|
48
|
+
},
|
|
49
|
+
runtime: {
|
|
50
|
+
server: {
|
|
51
|
+
providers: []
|
|
52
|
+
},
|
|
53
|
+
client: {
|
|
54
|
+
providers: []
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
metadata: {
|
|
58
|
+
generatorPrimarySubcommand: "page",
|
|
59
|
+
generatorSubcommands: {
|
|
60
|
+
element: {
|
|
61
|
+
entrypoint: "src/server/subcommands/element.js",
|
|
62
|
+
export: "runGeneratorSubcommand"
|
|
63
|
+
},
|
|
64
|
+
container: {
|
|
65
|
+
entrypoint: "src/server/subcommands/container.js",
|
|
66
|
+
export: "runGeneratorSubcommand"
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
apiSummary: {
|
|
70
|
+
surfaces: [
|
|
71
|
+
{
|
|
72
|
+
subpath: "./server/buildTemplateContext",
|
|
73
|
+
summary: "Builds deterministic page menu placement template context values."
|
|
74
|
+
}
|
|
75
|
+
],
|
|
76
|
+
containerTokens: {
|
|
77
|
+
server: [],
|
|
78
|
+
client: []
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
mutations: {
|
|
83
|
+
dependencies: {
|
|
84
|
+
runtime: {
|
|
85
|
+
"@jskit-ai/users-web": "0.1.34"
|
|
86
|
+
},
|
|
87
|
+
dev: {}
|
|
88
|
+
},
|
|
89
|
+
packageJson: {
|
|
90
|
+
scripts: {}
|
|
91
|
+
},
|
|
92
|
+
procfile: {},
|
|
93
|
+
files: [
|
|
94
|
+
{
|
|
95
|
+
from: "templates/src/pages/admin/ui-generator/Page.vue",
|
|
96
|
+
toSurface: "${option:surface|lower}",
|
|
97
|
+
toSurfacePath: "${option:directory-prefix|pathprefix}${option:name|path}/index.vue",
|
|
98
|
+
reason: "Install generated UI page scaffold.",
|
|
99
|
+
category: "ui-generator",
|
|
100
|
+
id: "ui-generator-page-${option:name|snake}"
|
|
101
|
+
}
|
|
102
|
+
],
|
|
103
|
+
text: [
|
|
104
|
+
{
|
|
105
|
+
op: "append-text",
|
|
106
|
+
file: "src/placement.js",
|
|
107
|
+
position: "bottom",
|
|
108
|
+
skipIfContains: "jskit:ui-generator.page.menu:${option:surface|lower}:${option:directory-prefix|path}:${option:name|path}",
|
|
109
|
+
value:
|
|
110
|
+
"\n// jskit:ui-generator.page.menu:${option:surface|lower}:${option:directory-prefix|path}:${option:name|path}\n{\n addPlacement({\n id: \"ui-generator.page.${option:name|kebab}.menu\",\n host: \"__JSKIT_UI_MENU_PLACEMENT_HOST__\",\n position: \"__JSKIT_UI_MENU_PLACEMENT_POSITION__\",\n surfaces: [\"${option:surface|lower}\"],\n order: 155,\n componentToken: \"users.web.shell.surface-aware-menu-link-item\",\n props: {\n label: \"${option:name|trim}\",\n surface: \"${option:surface|lower}\",\n workspaceSuffix: \"/${option:directory-prefix|pathprefix}${option:name|path}\",\n nonWorkspaceSuffix: \"/${option:directory-prefix|pathprefix}${option:name|path}\"\n },\n when: ({ auth }) => Boolean(auth?.authenticated)\n });\n}\n",
|
|
111
|
+
reason: "Append generated UI page menu placement.",
|
|
112
|
+
category: "ui-generator",
|
|
113
|
+
id: "ui-generator-page-placement-menu-${option:name|snake}",
|
|
114
|
+
templateContext: {
|
|
115
|
+
entrypoint: "src/server/buildTemplateContext.js",
|
|
116
|
+
export: "buildUiPageTemplateContext"
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
]
|
|
120
|
+
}
|
|
121
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@jskit-ai/ui-generator",
|
|
3
|
+
"version": "0.1.3",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"test": "node --test"
|
|
7
|
+
},
|
|
8
|
+
"dependencies": {
|
|
9
|
+
"@jskit-ai/kernel": "0.1.20"
|
|
10
|
+
},
|
|
11
|
+
"exports": {
|
|
12
|
+
"./server/buildTemplateContext": "./src/server/buildTemplateContext.js"
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { normalizeText } from "@jskit-ai/kernel/shared/support/normalize";
|
|
2
|
+
import { resolveShellOutletPlacementTargetFromApp } from "@jskit-ai/kernel/server/support";
|
|
3
|
+
|
|
4
|
+
async function buildUiPageTemplateContext({ appRoot, options } = {}) {
|
|
5
|
+
const placementTarget = await resolveShellOutletPlacementTargetFromApp({
|
|
6
|
+
appRoot,
|
|
7
|
+
context: "ui-generator",
|
|
8
|
+
placement: options?.placement
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
return {
|
|
12
|
+
__JSKIT_UI_MENU_PLACEMENT_HOST__: normalizeText(placementTarget?.host),
|
|
13
|
+
__JSKIT_UI_MENU_PLACEMENT_POSITION__: normalizeText(placementTarget?.position)
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export { buildUiPageTemplateContext };
|