athena-portal-app-kit 1.0.0 → 1.0.2
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/assets/athena-bootstrap.js +5 -1
- package/assets/athena-icons.js +25 -0
- package/assets/athena-me.js +3 -0
- package/assets/preview-embed.js +313 -0
- package/assets/preview-shell.css +13 -0
- package/assets/preview-shell.js +39 -8
- package/package.json +1 -1
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"use strict";
|
|
7
7
|
|
|
8
8
|
var CONFIG_PATH = "./athena-app.config.json";
|
|
9
|
-
var DEFAULT_KIT = "https://cdn.jsdelivr.net/npm/athena-portal-app-kit@1
|
|
9
|
+
var DEFAULT_KIT = "https://cdn.jsdelivr.net/npm/athena-portal-app-kit@1";
|
|
10
10
|
var DEFAULT_PORTAL = "https://backoffice.athenacare.health";
|
|
11
11
|
|
|
12
12
|
function loadScript(src) {
|
|
@@ -76,6 +76,10 @@
|
|
|
76
76
|
.then(function (config) {
|
|
77
77
|
if (!config.portalOrigin) config.portalOrigin = DEFAULT_PORTAL;
|
|
78
78
|
if (!config.kitOrigin) config.kitOrigin = DEFAULT_KIT;
|
|
79
|
+
globalThis.__ATHENA_KIT_ORIGIN__ = (config.kitOrigin || DEFAULT_KIT).replace(
|
|
80
|
+
/\/$/,
|
|
81
|
+
"",
|
|
82
|
+
);
|
|
79
83
|
global.__ATHENA_APP_CONFIG__ = config;
|
|
80
84
|
|
|
81
85
|
var urls = deriveAssetUrls(config);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registers Web Awesome default icon library → kit sharp-solid SVGs.
|
|
3
|
+
* Load as type="module" after webawesome.loader.js. Set window.__ATHENA_KIT_ORIGIN__
|
|
4
|
+
* before this script (athena-bootstrap and preview templates do).
|
|
5
|
+
*/
|
|
6
|
+
const DEFAULT_KIT = "https://cdn.jsdelivr.net/npm/athena-portal-app-kit@1";
|
|
7
|
+
const kit = String(globalThis.__ATHENA_KIT_ORIGIN__ || DEFAULT_KIT).replace(
|
|
8
|
+
/\/$/,
|
|
9
|
+
"",
|
|
10
|
+
);
|
|
11
|
+
|
|
12
|
+
const { registerIconLibrary } = await import(
|
|
13
|
+
kit + "/assets/webawesome/dist-cdn/webawesome.loader.js"
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
registerIconLibrary("default", {
|
|
17
|
+
resolver: (name) =>
|
|
18
|
+
kit +
|
|
19
|
+
"/assets/fontawesome/svgs/sharp-solid/" +
|
|
20
|
+
encodeURIComponent(String(name || "link").trim() || "link") +
|
|
21
|
+
".svg",
|
|
22
|
+
mutator: (svg) => {
|
|
23
|
+
svg.setAttribute("fill", "currentColor");
|
|
24
|
+
},
|
|
25
|
+
});
|
package/assets/athena-me.js
CHANGED
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single-file Back Office preview — Claude artifact / preview.html only.
|
|
3
|
+
* Renders wa-page + drawer around an existing <main class="portal-app">.
|
|
4
|
+
* No iframe, no sibling files, no portal API calls.
|
|
5
|
+
*/
|
|
6
|
+
(function () {
|
|
7
|
+
"use strict";
|
|
8
|
+
|
|
9
|
+
var DEFAULT_KIT = "https://cdn.jsdelivr.net/npm/athena-portal-app-kit@1";
|
|
10
|
+
var ROLES = [
|
|
11
|
+
"staff",
|
|
12
|
+
"providers",
|
|
13
|
+
"managers",
|
|
14
|
+
"executive",
|
|
15
|
+
"board",
|
|
16
|
+
"admin",
|
|
17
|
+
];
|
|
18
|
+
var ROLE_RANK = {
|
|
19
|
+
admin: 5,
|
|
20
|
+
board: 4,
|
|
21
|
+
executive: 3,
|
|
22
|
+
managers: 2,
|
|
23
|
+
providers: 1,
|
|
24
|
+
staff: 0,
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
var activeKit = DEFAULT_KIT;
|
|
28
|
+
|
|
29
|
+
function el(tag, className) {
|
|
30
|
+
var node = document.createElement(tag);
|
|
31
|
+
if (className) node.className = className;
|
|
32
|
+
return node;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function injectStylesheet(href) {
|
|
36
|
+
var link = document.createElement("link");
|
|
37
|
+
link.rel = "stylesheet";
|
|
38
|
+
link.href = href;
|
|
39
|
+
document.head.appendChild(link);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function faKitSolidIconSrc(icon) {
|
|
43
|
+
var name = (icon || "link").trim() || "link";
|
|
44
|
+
return (
|
|
45
|
+
activeKit +
|
|
46
|
+
"/assets/fontawesome/svgs/sharp-solid/" +
|
|
47
|
+
encodeURIComponent(name) +
|
|
48
|
+
".svg"
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function defaultRole(config) {
|
|
53
|
+
return (
|
|
54
|
+
(config.dev && config.dev.role) ||
|
|
55
|
+
config.minRole ||
|
|
56
|
+
"staff"
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function buildViewer(role) {
|
|
61
|
+
if (ROLE_RANK[role] === undefined) role = "staff";
|
|
62
|
+
return {
|
|
63
|
+
userId: "00000000-0000-0000-0000-000000000001",
|
|
64
|
+
email: "preview@local.test",
|
|
65
|
+
firstName: "Preview",
|
|
66
|
+
lastName: "User",
|
|
67
|
+
role: role,
|
|
68
|
+
status: "active",
|
|
69
|
+
roleRank: ROLE_RANK[role] ?? 0,
|
|
70
|
+
fixture: true,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function setPreviewViewer(role) {
|
|
75
|
+
globalThis.__ATHENA_VIEWER__ = buildViewer(role);
|
|
76
|
+
if (globalThis.AthenaMe && typeof globalThis.AthenaMe.refresh === "function") {
|
|
77
|
+
globalThis.AthenaMe.refresh();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function syntheticNav(config) {
|
|
82
|
+
var href = config.appKey ? "/apps/" + config.appKey : "#";
|
|
83
|
+
var category = config.navCategory || "applications";
|
|
84
|
+
if (
|
|
85
|
+
category !== "applications" &&
|
|
86
|
+
category !== "dashboards" &&
|
|
87
|
+
category !== "administration"
|
|
88
|
+
) {
|
|
89
|
+
category = "applications";
|
|
90
|
+
}
|
|
91
|
+
var entry = {
|
|
92
|
+
key: config.appKey || "preview-app",
|
|
93
|
+
href: href,
|
|
94
|
+
label: config.label || config.appKey || "Your app",
|
|
95
|
+
icon: config.icon || "link",
|
|
96
|
+
};
|
|
97
|
+
var sections = {
|
|
98
|
+
applications: [],
|
|
99
|
+
dashboards: [],
|
|
100
|
+
administration: [],
|
|
101
|
+
};
|
|
102
|
+
sections[category] = [entry];
|
|
103
|
+
return sections;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function sortLinks(links) {
|
|
107
|
+
return links.slice().sort(function (a, b) {
|
|
108
|
+
return String(a.label).localeCompare(String(b.label));
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function navIcon(entry) {
|
|
113
|
+
var wa = document.createElement("wa-icon");
|
|
114
|
+
wa.setAttribute("src", faKitSolidIconSrc(entry.icon || "link"));
|
|
115
|
+
wa.setAttribute("label", "");
|
|
116
|
+
return wa;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function sidebarLink(entry, activeHref) {
|
|
120
|
+
var a = el("a", "shell-sidebar-link");
|
|
121
|
+
a.href = entry.href;
|
|
122
|
+
a.setAttribute("data-shell-link", entry.key);
|
|
123
|
+
if (activeHref && entry.href === activeHref) {
|
|
124
|
+
a.setAttribute("aria-current", "page");
|
|
125
|
+
}
|
|
126
|
+
a.addEventListener("click", function (e) {
|
|
127
|
+
e.preventDefault();
|
|
128
|
+
});
|
|
129
|
+
a.appendChild(navIcon(entry));
|
|
130
|
+
a.appendChild(document.createTextNode(entry.label));
|
|
131
|
+
return a;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function fillNavGroup(container, links, activeHref) {
|
|
135
|
+
if (!container) return;
|
|
136
|
+
container.replaceChildren();
|
|
137
|
+
sortLinks(links).forEach(function (link) {
|
|
138
|
+
container.appendChild(sidebarLink(link, activeHref));
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function buildEmbedShell(config, role, sections) {
|
|
143
|
+
var activeHref = config.appKey ? "/apps/" + config.appKey : "";
|
|
144
|
+
var waPage = document.createElement("wa-page");
|
|
145
|
+
waPage.className = "shell athena-preview-shell";
|
|
146
|
+
waPage.setAttribute("mobile-breakpoint", "48rem");
|
|
147
|
+
|
|
148
|
+
var headerSlot = el("div", "shell-header-bar wa-cluster wa-gap-m");
|
|
149
|
+
headerSlot.setAttribute("slot", "header");
|
|
150
|
+
|
|
151
|
+
var menuBtn = document.createElement("wa-button");
|
|
152
|
+
menuBtn.setAttribute("type", "button");
|
|
153
|
+
menuBtn.setAttribute("appearance", "outlined");
|
|
154
|
+
menuBtn.setAttribute("variant", "neutral");
|
|
155
|
+
menuBtn.setAttribute("size", "s");
|
|
156
|
+
menuBtn.setAttribute("aria-label", "Open sidebar");
|
|
157
|
+
menuBtn.setAttribute("data-drawer", "open nav-drawer");
|
|
158
|
+
|
|
159
|
+
var markIcon = document.createElement("i");
|
|
160
|
+
markIcon.className = "fa-kit fa-athenacare-mark";
|
|
161
|
+
markIcon.setAttribute("aria-hidden", "true");
|
|
162
|
+
menuBtn.appendChild(markIcon);
|
|
163
|
+
headerSlot.appendChild(menuBtn);
|
|
164
|
+
|
|
165
|
+
var spacer = el("span", "shell-header-spacer");
|
|
166
|
+
spacer.setAttribute("aria-hidden", "true");
|
|
167
|
+
headerSlot.appendChild(spacer);
|
|
168
|
+
|
|
169
|
+
var drawer = document.createElement("wa-drawer");
|
|
170
|
+
drawer.id = "nav-drawer";
|
|
171
|
+
drawer.setAttribute("without-header", "");
|
|
172
|
+
drawer.setAttribute("aria-label", "Athena Care");
|
|
173
|
+
drawer.setAttribute("placement", "start");
|
|
174
|
+
drawer.setAttribute("light-dismiss", "");
|
|
175
|
+
|
|
176
|
+
var wordmarkOuter = el("div", "shell-drawer-wordmark");
|
|
177
|
+
var wordmarkLink = el(
|
|
178
|
+
"a",
|
|
179
|
+
"shell-drawer-wordmark-link shell-drawer-wordmark-brand",
|
|
180
|
+
);
|
|
181
|
+
wordmarkLink.href = "#";
|
|
182
|
+
wordmarkLink.setAttribute("aria-label", "Athena Care home");
|
|
183
|
+
wordmarkLink.addEventListener("click", function (e) {
|
|
184
|
+
e.preventDefault();
|
|
185
|
+
});
|
|
186
|
+
var wmMark = document.createElement("i");
|
|
187
|
+
wmMark.className = "fa-kit fa-athenacare-mark";
|
|
188
|
+
wmMark.setAttribute("aria-hidden", "true");
|
|
189
|
+
var wmText = el("span", "shell-drawer-wordmark-text");
|
|
190
|
+
wmText.textContent = "Athena Care";
|
|
191
|
+
wordmarkLink.appendChild(wmMark);
|
|
192
|
+
wordmarkLink.appendChild(wmText);
|
|
193
|
+
wordmarkOuter.appendChild(wordmarkLink);
|
|
194
|
+
drawer.appendChild(wordmarkOuter);
|
|
195
|
+
|
|
196
|
+
var nav = el("nav", "wa-stack wa-gap-m");
|
|
197
|
+
nav.setAttribute("aria-label", "Sidebar navigation");
|
|
198
|
+
|
|
199
|
+
var hApps = el("div", "shell-nav-heading");
|
|
200
|
+
hApps.textContent = "Applications";
|
|
201
|
+
nav.appendChild(hApps);
|
|
202
|
+
var appsEl = el("div", "wa-stack wa-gap-s shell-nav-applications");
|
|
203
|
+
fillNavGroup(appsEl, sections.applications, activeHref);
|
|
204
|
+
nav.appendChild(appsEl);
|
|
205
|
+
|
|
206
|
+
var dashRegion = el("div", "shell-nav-admin-region");
|
|
207
|
+
dashRegion.setAttribute("data-shell-dashboards-region", "");
|
|
208
|
+
if (sections.dashboards.length === 0) dashRegion.hidden = true;
|
|
209
|
+
var hDash = el("div", "shell-nav-heading shell-nav-heading--group");
|
|
210
|
+
hDash.textContent = "DASHBOARDS";
|
|
211
|
+
var dashEl = el("div", "wa-stack wa-gap-s shell-nav-dashboards");
|
|
212
|
+
fillNavGroup(dashEl, sections.dashboards, activeHref);
|
|
213
|
+
dashRegion.appendChild(hDash);
|
|
214
|
+
dashRegion.appendChild(dashEl);
|
|
215
|
+
nav.appendChild(dashRegion);
|
|
216
|
+
|
|
217
|
+
var adminRegion = el("div", "shell-nav-admin-region");
|
|
218
|
+
adminRegion.setAttribute("data-shell-admin-region", "");
|
|
219
|
+
if (sections.administration.length === 0) adminRegion.hidden = true;
|
|
220
|
+
var hAdmin = el("div", "shell-nav-heading shell-nav-heading--group");
|
|
221
|
+
hAdmin.textContent = "ADMINISTRATION";
|
|
222
|
+
var adminEl = el("div", "wa-stack wa-gap-s shell-nav-administration");
|
|
223
|
+
fillNavGroup(adminEl, sections.administration, activeHref);
|
|
224
|
+
adminRegion.appendChild(hAdmin);
|
|
225
|
+
adminRegion.appendChild(adminEl);
|
|
226
|
+
nav.appendChild(adminRegion);
|
|
227
|
+
|
|
228
|
+
var hAcct = el("div", "shell-nav-heading shell-nav-heading--group");
|
|
229
|
+
hAcct.textContent = "Preview";
|
|
230
|
+
nav.appendChild(hAcct);
|
|
231
|
+
|
|
232
|
+
var roleField = el("div", "athena-preview-role-field");
|
|
233
|
+
var roleLabel = document.createElement("label");
|
|
234
|
+
roleLabel.setAttribute("for", "athena-preview-role");
|
|
235
|
+
roleLabel.textContent = "Preview as";
|
|
236
|
+
roleField.appendChild(roleLabel);
|
|
237
|
+
|
|
238
|
+
var roleSelect = document.createElement("select");
|
|
239
|
+
roleSelect.id = "athena-preview-role";
|
|
240
|
+
roleSelect.setAttribute("aria-label", "Preview as role");
|
|
241
|
+
ROLES.forEach(function (r) {
|
|
242
|
+
var opt = document.createElement("option");
|
|
243
|
+
opt.value = r;
|
|
244
|
+
opt.textContent = r.charAt(0).toUpperCase() + r.slice(1);
|
|
245
|
+
if (r === role) opt.selected = true;
|
|
246
|
+
roleSelect.appendChild(opt);
|
|
247
|
+
});
|
|
248
|
+
roleField.appendChild(roleSelect);
|
|
249
|
+
nav.appendChild(roleField);
|
|
250
|
+
|
|
251
|
+
drawer.appendChild(nav);
|
|
252
|
+
|
|
253
|
+
var main = el("main", "shell-main");
|
|
254
|
+
var appWrap = el("div", "athena-preview-embed-app");
|
|
255
|
+
main.appendChild(appWrap);
|
|
256
|
+
|
|
257
|
+
roleSelect.addEventListener("change", function () {
|
|
258
|
+
setPreviewViewer(roleSelect.value);
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
waPage.appendChild(headerSlot);
|
|
262
|
+
waPage.appendChild(drawer);
|
|
263
|
+
waPage.appendChild(main);
|
|
264
|
+
|
|
265
|
+
return { shell: waPage, appSlot: appWrap };
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
function showError(message) {
|
|
269
|
+
var p = el("p", "shell-subtle");
|
|
270
|
+
p.style.padding = "1rem";
|
|
271
|
+
p.textContent = message;
|
|
272
|
+
document.body.appendChild(p);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
function mount() {
|
|
276
|
+
var config = globalThis.__ATHENA_APP_CONFIG__;
|
|
277
|
+
if (!config || typeof config !== "object") {
|
|
278
|
+
showError("Missing preview config.");
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
var appMain = document.querySelector("main.portal-app");
|
|
283
|
+
if (!appMain) {
|
|
284
|
+
showError("Missing <main class=\"portal-app\"> for preview.");
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
var kit = (config.kitOrigin || DEFAULT_KIT).replace(/\/$/, "");
|
|
289
|
+
activeKit = kit;
|
|
290
|
+
globalThis.__ATHENA_KIT_ORIGIN__ = kit;
|
|
291
|
+
|
|
292
|
+
injectStylesheet(kit + "/assets/athena-app.css");
|
|
293
|
+
injectStylesheet(kit + "/assets/shell-base.css");
|
|
294
|
+
injectStylesheet(kit + "/assets/preview-shell.css");
|
|
295
|
+
|
|
296
|
+
document.documentElement.classList.add("embedded");
|
|
297
|
+
document.title = (config.label || "App") + " — preview";
|
|
298
|
+
|
|
299
|
+
var role = defaultRole(config);
|
|
300
|
+
setPreviewViewer(role);
|
|
301
|
+
|
|
302
|
+
var sections = syntheticNav(config);
|
|
303
|
+
var built = buildEmbedShell(config, role, sections);
|
|
304
|
+
built.appSlot.appendChild(appMain);
|
|
305
|
+
document.body.replaceChildren(built.shell);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
if (document.readyState === "loading") {
|
|
309
|
+
document.addEventListener("DOMContentLoaded", mount);
|
|
310
|
+
} else {
|
|
311
|
+
mount();
|
|
312
|
+
}
|
|
313
|
+
})();
|
package/assets/preview-shell.css
CHANGED
|
@@ -19,6 +19,19 @@ wa-page.shell.athena-preview-shell > main.shell-main > .athena-preview-app {
|
|
|
19
19
|
min-height: 24rem;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
.athena-preview-embed-app {
|
|
23
|
+
display: block;
|
|
24
|
+
min-height: 0;
|
|
25
|
+
overflow: auto;
|
|
26
|
+
height: calc(100dvh - var(--athena-preview-chrome-offset, 5rem));
|
|
27
|
+
min-height: 24rem;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
wa-page.shell.athena-preview-shell > main.shell-main > .athena-preview-embed-app {
|
|
31
|
+
display: block;
|
|
32
|
+
min-height: 0;
|
|
33
|
+
}
|
|
34
|
+
|
|
22
35
|
.athena-preview-role-field {
|
|
23
36
|
padding: 0 0.25rem;
|
|
24
37
|
}
|
package/assets/preview-shell.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
(function () {
|
|
6
6
|
"use strict";
|
|
7
7
|
|
|
8
|
-
var DEFAULT_KIT = "https://cdn.jsdelivr.net/npm/athena-portal-app-kit@1
|
|
8
|
+
var DEFAULT_KIT = "https://cdn.jsdelivr.net/npm/athena-portal-app-kit@1";
|
|
9
9
|
var DEFAULT_PORTAL = "https://backoffice.athenacare.health";
|
|
10
10
|
var ROLES = [
|
|
11
11
|
"staff",
|
|
@@ -83,6 +83,31 @@
|
|
|
83
83
|
};
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
+
function syntheticNav(config) {
|
|
87
|
+
var href = config.appKey ? "/apps/" + config.appKey : "#";
|
|
88
|
+
var category = config.navCategory || "applications";
|
|
89
|
+
if (
|
|
90
|
+
category !== "applications" &&
|
|
91
|
+
category !== "dashboards" &&
|
|
92
|
+
category !== "administration"
|
|
93
|
+
) {
|
|
94
|
+
category = "applications";
|
|
95
|
+
}
|
|
96
|
+
var entry = {
|
|
97
|
+
key: config.appKey || "preview-app",
|
|
98
|
+
href: href,
|
|
99
|
+
label: config.label || config.appKey || "Your app",
|
|
100
|
+
icon: config.icon || "link",
|
|
101
|
+
};
|
|
102
|
+
var sections = {
|
|
103
|
+
applications: [],
|
|
104
|
+
dashboards: [],
|
|
105
|
+
administration: [],
|
|
106
|
+
};
|
|
107
|
+
sections[category] = [entry];
|
|
108
|
+
return sections;
|
|
109
|
+
}
|
|
110
|
+
|
|
86
111
|
function ensureAppInNav(sections, config) {
|
|
87
112
|
if (!config.appKey) return sections;
|
|
88
113
|
var href = "/apps/" + config.appKey;
|
|
@@ -171,7 +196,7 @@
|
|
|
171
196
|
menuBtn.setAttribute("type", "button");
|
|
172
197
|
menuBtn.setAttribute("appearance", "outlined");
|
|
173
198
|
menuBtn.setAttribute("variant", "neutral");
|
|
174
|
-
menuBtn.setAttribute("size", "
|
|
199
|
+
menuBtn.setAttribute("size", "s");
|
|
175
200
|
menuBtn.setAttribute("aria-label", "Open sidebar");
|
|
176
201
|
menuBtn.setAttribute("data-drawer", "open nav-drawer");
|
|
177
202
|
|
|
@@ -323,12 +348,18 @@
|
|
|
323
348
|
document.title = (config.label || "App") + " — preview";
|
|
324
349
|
|
|
325
350
|
var role = defaultRole(config);
|
|
326
|
-
return fetchNav(portal, role)
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
)
|
|
331
|
-
|
|
351
|
+
return fetchNav(portal, role)
|
|
352
|
+
.then(function (payload) {
|
|
353
|
+
return ensureAppInNav(parseNavSections(payload), config);
|
|
354
|
+
})
|
|
355
|
+
.catch(function () {
|
|
356
|
+
return ensureAppInNav(syntheticNav(config), config);
|
|
357
|
+
})
|
|
358
|
+
.then(function (sections) {
|
|
359
|
+
document.body.replaceChildren(
|
|
360
|
+
buildPreviewShell(config, role, sections),
|
|
361
|
+
);
|
|
362
|
+
});
|
|
332
363
|
})
|
|
333
364
|
.catch(function (err) {
|
|
334
365
|
console.error("[preview-shell]", err);
|
package/package.json
CHANGED