@jskit-ai/console-web 0.1.33 → 0.1.35
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/package.descriptor.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export default Object.freeze({
|
|
2
2
|
packageVersion: 1,
|
|
3
3
|
packageId: "@jskit-ai/console-web",
|
|
4
|
-
version: "0.1.
|
|
4
|
+
version: "0.1.35",
|
|
5
5
|
kind: "runtime",
|
|
6
6
|
description: "Authenticated console surface scaffold and surface policy wiring.",
|
|
7
7
|
dependsOn: [
|
|
@@ -43,27 +43,56 @@ export default Object.freeze({
|
|
|
43
43
|
outlets: [
|
|
44
44
|
{
|
|
45
45
|
target: "console-settings:primary-menu",
|
|
46
|
-
defaultLinkComponentToken: "local.main.ui.surface-aware-menu-link-item",
|
|
47
46
|
surfaces: ["console"],
|
|
48
47
|
source: "templates/src/pages/console/settings.vue"
|
|
49
48
|
}
|
|
50
49
|
],
|
|
50
|
+
topology: {
|
|
51
|
+
placements: [
|
|
52
|
+
{
|
|
53
|
+
id: "page.section-nav",
|
|
54
|
+
owner: "console-settings",
|
|
55
|
+
description: "Navigation between console settings child pages.",
|
|
56
|
+
surfaces: ["console"],
|
|
57
|
+
variants: {
|
|
58
|
+
compact: {
|
|
59
|
+
outlet: "console-settings:primary-menu",
|
|
60
|
+
renderers: {
|
|
61
|
+
link: "local.main.ui.surface-aware-menu-link-item"
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
medium: {
|
|
65
|
+
outlet: "console-settings:primary-menu",
|
|
66
|
+
renderers: {
|
|
67
|
+
link: "local.main.ui.surface-aware-menu-link-item"
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
expanded: {
|
|
71
|
+
outlet: "console-settings:primary-menu",
|
|
72
|
+
renderers: {
|
|
73
|
+
link: "local.main.ui.surface-aware-menu-link-item"
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
]
|
|
79
|
+
},
|
|
51
80
|
contributions: [
|
|
52
81
|
{
|
|
53
82
|
id: "console.web.profile.menu.console",
|
|
54
|
-
target: "auth
|
|
83
|
+
target: "auth.profile-menu",
|
|
84
|
+
kind: "link",
|
|
55
85
|
surfaces: ["*"],
|
|
56
86
|
order: 600,
|
|
57
|
-
componentToken: "auth.web.profile.menu.link-item",
|
|
58
87
|
when: "auth.authenticated === true && surfaceAccess.consoleowner === true && surface !== \"console\"",
|
|
59
88
|
source: "mutations.text#console-web-profile-menu-console-placement"
|
|
60
89
|
},
|
|
61
90
|
{
|
|
62
91
|
id: "console.web.menu.settings",
|
|
63
|
-
target: "shell
|
|
92
|
+
target: "shell.primary-nav",
|
|
93
|
+
kind: "link",
|
|
64
94
|
surfaces: ["console"],
|
|
65
95
|
order: 100,
|
|
66
|
-
componentToken: "local.main.ui.menu-link-item",
|
|
67
96
|
when: "auth.authenticated === true",
|
|
68
97
|
source: "mutations.text#console-web-console-settings-placement"
|
|
69
98
|
}
|
|
@@ -74,9 +103,9 @@ export default Object.freeze({
|
|
|
74
103
|
mutations: {
|
|
75
104
|
dependencies: {
|
|
76
105
|
runtime: {
|
|
77
|
-
"@jskit-ai/auth-web": "0.1.
|
|
78
|
-
"@jskit-ai/console-core": "0.1.
|
|
79
|
-
"@jskit-ai/shell-web": "0.1.
|
|
106
|
+
"@jskit-ai/auth-web": "0.1.68",
|
|
107
|
+
"@jskit-ai/console-core": "0.1.30",
|
|
108
|
+
"@jskit-ai/shell-web": "0.1.66",
|
|
80
109
|
},
|
|
81
110
|
dev: {}
|
|
82
111
|
},
|
|
@@ -154,7 +183,7 @@ export default Object.freeze({
|
|
|
154
183
|
position: "bottom",
|
|
155
184
|
skipIfContains: "id: \"console.web.profile.menu.console\"",
|
|
156
185
|
value:
|
|
157
|
-
"\naddPlacement({\n id: \"console.web.profile.menu.console\",\n target: \"auth
|
|
186
|
+
"\naddPlacement({\n id: \"console.web.profile.menu.console\",\n target: \"auth.profile-menu\",\n kind: \"link\",\n surfaces: [\"*\"],\n order: 600,\n props: {\n label: \"Go to console\",\n to: \"/console\",\n icon: \"mdi-console-network-outline\"\n },\n when: ({ auth, surfaceAccess, surface }) => {\n return auth?.authenticated === true && surfaceAccess?.consoleowner === true && surface !== \"console\";\n }\n});\n",
|
|
158
187
|
reason: "Append owner-only console navigation entry into the authenticated profile menu outside the console surface.",
|
|
159
188
|
category: "console-web",
|
|
160
189
|
id: "console-web-profile-menu-console-placement"
|
|
@@ -165,10 +194,21 @@ export default Object.freeze({
|
|
|
165
194
|
position: "bottom",
|
|
166
195
|
skipIfContains: "id: \"console.web.menu.settings\"",
|
|
167
196
|
value:
|
|
168
|
-
"\naddPlacement({\n id: \"console.web.menu.settings\",\n target: \"shell
|
|
197
|
+
"\naddPlacement({\n id: \"console.web.menu.settings\",\n target: \"shell.primary-nav\",\n kind: \"link\",\n surfaces: [\"console\"],\n order: 100,\n props: {\n label: \"Settings\",\n to: \"/console/settings\",\n icon: \"mdi-cog-outline\"\n },\n when: ({ auth }) => auth?.authenticated === true\n});\n",
|
|
169
198
|
reason: "Append console-web settings menu placement into app-owned placement registry.",
|
|
170
199
|
category: "console-web",
|
|
171
200
|
id: "console-web-console-settings-placement"
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
op: "append-text",
|
|
204
|
+
file: "src/placementTopology.js",
|
|
205
|
+
position: "bottom",
|
|
206
|
+
skipIfContains: "owner: \"console-settings\"",
|
|
207
|
+
value:
|
|
208
|
+
"\naddPlacementTopology({\n id: \"page.section-nav\",\n owner: \"console-settings\",\n description: \"Navigation between console settings child pages.\",\n surfaces: [\"console\"],\n variants: {\n compact: {\n outlet: \"console-settings:primary-menu\",\n renderers: {\n link: \"local.main.ui.surface-aware-menu-link-item\"\n }\n },\n medium: {\n outlet: \"console-settings:primary-menu\",\n renderers: {\n link: \"local.main.ui.surface-aware-menu-link-item\"\n }\n },\n expanded: {\n outlet: \"console-settings:primary-menu\",\n renderers: {\n link: \"local.main.ui.surface-aware-menu-link-item\"\n }\n }\n }\n});\n",
|
|
209
|
+
reason: "Append console settings semantic topology into app-owned placement topology.",
|
|
210
|
+
category: "console-web",
|
|
211
|
+
id: "console-web-settings-placement-topology"
|
|
172
212
|
}
|
|
173
213
|
]
|
|
174
214
|
}
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jskit-ai/console-web",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.35",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "node --test"
|
|
7
7
|
},
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@jskit-ai/auth-web": "0.1.
|
|
10
|
-
"@jskit-ai/console-core": "0.1.
|
|
11
|
-
"@jskit-ai/shell-web": "0.1.
|
|
9
|
+
"@jskit-ai/auth-web": "0.1.68",
|
|
10
|
+
"@jskit-ai/console-core": "0.1.30",
|
|
11
|
+
"@jskit-ai/shell-web": "0.1.66"
|
|
12
12
|
}
|
|
13
13
|
}
|
|
@@ -1,24 +1,62 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
<
|
|
4
|
-
<
|
|
5
|
-
<
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
2
|
+
<section class="console-home-screen d-flex flex-column ga-4">
|
|
3
|
+
<header class="console-home-screen__header">
|
|
4
|
+
<div>
|
|
5
|
+
<p class="text-overline text-medium-emphasis mb-1">Console</p>
|
|
6
|
+
<h1 class="console-home-screen__title">Operations Console</h1>
|
|
7
|
+
<p class="text-body-2 text-medium-emphasis mb-0">Operator tools, scripts, and diagnostics.</p>
|
|
8
|
+
</div>
|
|
9
|
+
<v-btn color="primary" variant="flat" to="/home">Back to home</v-btn>
|
|
10
|
+
</header>
|
|
11
|
+
|
|
12
|
+
<v-sheet rounded="lg" border class="console-home-screen__panel">
|
|
13
|
+
<div class="console-home-screen__status-row">
|
|
13
14
|
<v-chip color="secondary" variant="tonal" label>Route: /console</v-chip>
|
|
14
15
|
<v-chip color="info" variant="tonal" label>Surface status: enabled</v-chip>
|
|
15
16
|
</div>
|
|
16
|
-
<p class="text-medium-emphasis mb-0">
|
|
17
|
-
|
|
17
|
+
<p class="text-body-2 text-medium-emphasis mb-0">
|
|
18
|
+
Use this surface for operator actions and technical insights that should stay out of the end-user app.
|
|
18
19
|
</p>
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
</div>
|
|
22
|
-
</v-card-text>
|
|
23
|
-
</v-card>
|
|
20
|
+
</v-sheet>
|
|
21
|
+
</section>
|
|
24
22
|
</template>
|
|
23
|
+
|
|
24
|
+
<style scoped>
|
|
25
|
+
.console-home-screen__header {
|
|
26
|
+
align-items: flex-start;
|
|
27
|
+
display: flex;
|
|
28
|
+
gap: 1rem;
|
|
29
|
+
justify-content: space-between;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.console-home-screen__title {
|
|
33
|
+
font-size: clamp(1.5rem, 2.5vw, 2.25rem);
|
|
34
|
+
font-weight: 700;
|
|
35
|
+
letter-spacing: -0.03em;
|
|
36
|
+
line-height: 1.1;
|
|
37
|
+
margin: 0 0 0.4rem;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.console-home-screen__panel {
|
|
41
|
+
display: grid;
|
|
42
|
+
gap: 1rem;
|
|
43
|
+
padding: 1rem;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.console-home-screen__status-row {
|
|
47
|
+
display: flex;
|
|
48
|
+
flex-wrap: wrap;
|
|
49
|
+
gap: 0.5rem;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
@media (max-width: 640px) {
|
|
53
|
+
.console-home-screen__header {
|
|
54
|
+
flex-direction: column;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.console-home-screen__header :deep(.v-btn) {
|
|
58
|
+
min-height: 48px;
|
|
59
|
+
width: 100%;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
</style>
|
|
@@ -1,11 +1,17 @@
|
|
|
1
|
-
<script setup>
|
|
2
|
-
// To redirect this settings shell to a child page, uncomment and edit the example below.
|
|
3
|
-
// import { redirectToChild } from "@jskit-ai/kernel/client/pageRedirects";
|
|
4
|
-
// definePage({
|
|
5
|
-
// redirect: redirectToChild("your_child_segment")
|
|
6
|
-
// });
|
|
7
|
-
</script>
|
|
8
|
-
|
|
9
1
|
<template>
|
|
10
|
-
<
|
|
2
|
+
<section class="console-settings-empty">
|
|
3
|
+
<h2 class="text-h6 mb-2">No console settings yet</h2>
|
|
4
|
+
<p class="text-body-2 text-medium-emphasis mb-0">
|
|
5
|
+
Console settings sections will appear here when installed.
|
|
6
|
+
</p>
|
|
7
|
+
</section>
|
|
11
8
|
</template>
|
|
9
|
+
|
|
10
|
+
<style scoped>
|
|
11
|
+
.console-settings-empty {
|
|
12
|
+
margin-inline: auto;
|
|
13
|
+
max-width: 34rem;
|
|
14
|
+
padding: 2rem 1.25rem;
|
|
15
|
+
text-align: center;
|
|
16
|
+
}
|
|
17
|
+
</style>
|
|
@@ -5,28 +5,66 @@ import { RouterView } from "vue-router";
|
|
|
5
5
|
|
|
6
6
|
<template>
|
|
7
7
|
<section class="settings-shell d-flex flex-column ga-4">
|
|
8
|
-
<
|
|
9
|
-
<
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
<v-col cols="12" md="9" lg="10">
|
|
26
|
-
<RouterView />
|
|
27
|
-
</v-col>
|
|
28
|
-
</v-row>
|
|
29
|
-
</v-card-text>
|
|
30
|
-
</v-card>
|
|
8
|
+
<header>
|
|
9
|
+
<p class="text-overline text-medium-emphasis mb-1">Console</p>
|
|
10
|
+
<h1 class="settings-shell__title">Console settings</h1>
|
|
11
|
+
<p class="text-body-2 text-medium-emphasis mb-0">Global configuration and reference data for the whole app.</p>
|
|
12
|
+
</header>
|
|
13
|
+
|
|
14
|
+
<v-sheet rounded="lg" border class="settings-shell__panel">
|
|
15
|
+
<nav class="settings-shell__nav" aria-label="Console settings sections">
|
|
16
|
+
<v-list nav density="comfortable" class="settings-shell__nav-list">
|
|
17
|
+
<ShellOutlet target="console-settings:primary-menu" />
|
|
18
|
+
</v-list>
|
|
19
|
+
</nav>
|
|
20
|
+
<main class="settings-shell__content">
|
|
21
|
+
<RouterView />
|
|
22
|
+
</main>
|
|
23
|
+
</v-sheet>
|
|
31
24
|
</section>
|
|
32
25
|
</template>
|
|
26
|
+
|
|
27
|
+
<style scoped>
|
|
28
|
+
.settings-shell__title {
|
|
29
|
+
font-size: clamp(1.35rem, 2vw, 1.85rem);
|
|
30
|
+
font-weight: 650;
|
|
31
|
+
letter-spacing: -0.02em;
|
|
32
|
+
line-height: 1.15;
|
|
33
|
+
margin: 0 0 0.35rem;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.settings-shell__panel {
|
|
37
|
+
display: grid;
|
|
38
|
+
gap: 1rem;
|
|
39
|
+
grid-template-columns: minmax(12rem, 16rem) minmax(0, 1fr);
|
|
40
|
+
padding: 1rem;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.settings-shell__nav-list {
|
|
44
|
+
padding: 0;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.settings-shell__content {
|
|
48
|
+
min-width: 0;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@media (max-width: 960px) {
|
|
52
|
+
.settings-shell__panel {
|
|
53
|
+
grid-template-columns: 1fr;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.settings-shell__nav {
|
|
57
|
+
overflow-x: auto;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.settings-shell__nav-list {
|
|
61
|
+
display: flex;
|
|
62
|
+
gap: 0.5rem;
|
|
63
|
+
min-width: max-content;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.settings-shell__nav-list :deep(.v-list-item) {
|
|
67
|
+
min-height: 48px;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
</style>
|
|
@@ -22,6 +22,34 @@ function findTextMutation(id) {
|
|
|
22
22
|
: null;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
function readOutlets(target = "") {
|
|
26
|
+
const outlets = descriptor?.metadata?.ui?.placements?.outlets;
|
|
27
|
+
const normalizedTarget = String(target || "").trim();
|
|
28
|
+
return Array.isArray(outlets)
|
|
29
|
+
? outlets.filter((entry) => String(entry?.target || "").trim() === normalizedTarget)
|
|
30
|
+
: [];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function findTopology(id, owner = "") {
|
|
34
|
+
const placements = descriptor?.metadata?.ui?.placements?.topology?.placements;
|
|
35
|
+
const normalizedId = String(id || "").trim();
|
|
36
|
+
const normalizedOwner = String(owner || "").trim();
|
|
37
|
+
return Array.isArray(placements)
|
|
38
|
+
? placements.find((entry) => {
|
|
39
|
+
const entryId = String(entry?.id || "").trim();
|
|
40
|
+
const entryOwner = String(entry?.owner || "").trim();
|
|
41
|
+
return entryId === normalizedId && entryOwner === normalizedOwner;
|
|
42
|
+
}) || null
|
|
43
|
+
: null;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function findContribution(id) {
|
|
47
|
+
const contributions = descriptor?.metadata?.ui?.placements?.contributions;
|
|
48
|
+
return Array.isArray(contributions)
|
|
49
|
+
? contributions.find((entry) => String(entry?.id || "").trim() === id) || null
|
|
50
|
+
: null;
|
|
51
|
+
}
|
|
52
|
+
|
|
25
53
|
test("console-web installs console surface scripts and files", () => {
|
|
26
54
|
assert.deepEqual(descriptor?.mutations?.packageJson?.scripts, {
|
|
27
55
|
"server:console": "SERVER_SURFACE=console node ./bin/server.js",
|
|
@@ -82,6 +110,49 @@ test("console-web wires console surface policy into app config", () => {
|
|
|
82
110
|
/surfaceAccess\?\.consoleowner === true && surface !== "console"/
|
|
83
111
|
);
|
|
84
112
|
assert.equal(findTextMutation("console-web-console-settings-placement")?.file, "src/placement.js");
|
|
113
|
+
assert.equal(findTextMutation("console-web-settings-placement-topology")?.file, "src/placementTopology.js");
|
|
114
|
+
assert.deepEqual(readOutlets("console-settings:primary-menu"), [
|
|
115
|
+
{
|
|
116
|
+
target: "console-settings:primary-menu",
|
|
117
|
+
surfaces: ["console"],
|
|
118
|
+
source: "templates/src/pages/console/settings.vue"
|
|
119
|
+
}
|
|
120
|
+
]);
|
|
121
|
+
assert.deepEqual(findTopology("page.section-nav", "console-settings"), {
|
|
122
|
+
id: "page.section-nav",
|
|
123
|
+
owner: "console-settings",
|
|
124
|
+
description: "Navigation between console settings child pages.",
|
|
125
|
+
surfaces: ["console"],
|
|
126
|
+
variants: {
|
|
127
|
+
compact: {
|
|
128
|
+
outlet: "console-settings:primary-menu",
|
|
129
|
+
renderers: {
|
|
130
|
+
link: "local.main.ui.surface-aware-menu-link-item"
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
medium: {
|
|
134
|
+
outlet: "console-settings:primary-menu",
|
|
135
|
+
renderers: {
|
|
136
|
+
link: "local.main.ui.surface-aware-menu-link-item"
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
expanded: {
|
|
140
|
+
outlet: "console-settings:primary-menu",
|
|
141
|
+
renderers: {
|
|
142
|
+
link: "local.main.ui.surface-aware-menu-link-item"
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
assert.deepEqual(findContribution("console.web.menu.settings"), {
|
|
148
|
+
id: "console.web.menu.settings",
|
|
149
|
+
target: "shell.primary-nav",
|
|
150
|
+
kind: "link",
|
|
151
|
+
surfaces: ["console"],
|
|
152
|
+
order: 100,
|
|
153
|
+
when: "auth.authenticated === true",
|
|
154
|
+
source: "mutations.text#console-web-console-settings-placement"
|
|
155
|
+
});
|
|
85
156
|
});
|
|
86
157
|
|
|
87
158
|
test("console-web console templates stay shell-driven", async () => {
|
|
@@ -93,9 +164,12 @@ test("console-web console templates stay shell-driven", async () => {
|
|
|
93
164
|
assert.match(wrapperSource, /ShellLayout/);
|
|
94
165
|
assert.match(wrapperSource, /"surface": "console"/);
|
|
95
166
|
assert.match(indexSource, /Operations Console/);
|
|
167
|
+
assert.match(indexSource, /console-home-screen__panel/);
|
|
168
|
+
assert.doesNotMatch(indexSource, /<v-card\b|v-card-title|v-card-subtitle/);
|
|
96
169
|
assert.match(settingsSource, /target="console-settings:primary-menu"/);
|
|
97
|
-
assert.
|
|
170
|
+
assert.doesNotMatch(settingsSource, /default-link-component-token/);
|
|
171
|
+
assert.doesNotMatch(settingsSource, /<v-card\b/);
|
|
98
172
|
assert.match(settingsSource, /<RouterView \/>/);
|
|
99
|
-
assert.match(settingsIndexSource, /
|
|
100
|
-
assert.
|
|
173
|
+
assert.match(settingsIndexSource, /No console settings yet/);
|
|
174
|
+
assert.doesNotMatch(settingsIndexSource, /your_child_segment|To redirect this settings shell/);
|
|
101
175
|
});
|