@franzzemen/brokenstock-shell 0.0.28 → 0.0.29
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.
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { InjectionToken, makeEnvironmentProviders, signal, computed, Injectable, inject, input, Directive, isDevMode, effect, untracked, HostListener, ViewChild, ChangeDetectionStrategy, Component, NgZone, viewChild, afterNextRender } from '@angular/core';
|
|
3
3
|
import * as i2$1 from '@angular/router';
|
|
4
|
-
import { Router, RouterLink, RouterLinkActive, RouterOutlet
|
|
4
|
+
import { Router, RouterLink, ActivatedRoute, RouterLinkActive, RouterOutlet } from '@angular/router';
|
|
5
5
|
import { HttpHeader, BEARER_TOKEN_REGEX, USERNAME_REGEX, PASSWORD_REGEX } from '@franzzemen/utility';
|
|
6
6
|
import { validateCredentials } from '@franzzemen/identity';
|
|
7
7
|
import { HttpClient } from '@angular/common/http';
|
|
@@ -11,7 +11,7 @@ import { NG_VALIDATORS, FormsModule } from '@angular/forms';
|
|
|
11
11
|
import { Marked } from 'marked';
|
|
12
12
|
import { gfmHeadingId } from 'marked-gfm-heading-id';
|
|
13
13
|
import fm from 'front-matter';
|
|
14
|
-
import { NgClass, DOCUMENT, DatePipe } from '@angular/common';
|
|
14
|
+
import { NgClass, CommonModule, DOCUMENT, DatePipe } from '@angular/common';
|
|
15
15
|
import { z } from 'zod/v4';
|
|
16
16
|
import * as i1 from '@angular/material/icon';
|
|
17
17
|
import { MatIconModule } from '@angular/material/icon';
|
|
@@ -1236,6 +1236,211 @@ var faqAuthoringPanel = /*#__PURE__*/Object.freeze({
|
|
|
1236
1236
|
FaqAuthoringPanel: FaqAuthoringPanel
|
|
1237
1237
|
});
|
|
1238
1238
|
|
|
1239
|
+
/**
|
|
1240
|
+
* Public, SEO-targeted FAQ index. Prerendered at build time on the
|
|
1241
|
+
* consumer side (e.g. /help in broken-stock). Lists every manifest
|
|
1242
|
+
* entry where `audience === 'public' && seoReady === true`, grouped
|
|
1243
|
+
* by category and ordered by `order`.
|
|
1244
|
+
*/
|
|
1245
|
+
class PublicFaqIndex {
|
|
1246
|
+
constructor() {
|
|
1247
|
+
this.loader = inject(FAQ_CONTENT_LOADER);
|
|
1248
|
+
this._entries = signal([], ...(ngDevMode ? [{ debugName: "_entries" }] : /* istanbul ignore next */ []));
|
|
1249
|
+
this.loading = signal(true, ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
|
|
1250
|
+
this.groups = computed(() => {
|
|
1251
|
+
const visible = this._entries().filter((e) => e.audience === 'public' && e.seoReady);
|
|
1252
|
+
const byCategory = new Map();
|
|
1253
|
+
for (const entry of visible) {
|
|
1254
|
+
const list = byCategory.get(entry.category) ?? [];
|
|
1255
|
+
list.push(entry);
|
|
1256
|
+
byCategory.set(entry.category, list);
|
|
1257
|
+
}
|
|
1258
|
+
const groups = [];
|
|
1259
|
+
for (const [category, entries] of byCategory) {
|
|
1260
|
+
entries.sort((a, b) => a.order - b.order || a.title.localeCompare(b.title));
|
|
1261
|
+
groups.push({ category, entries });
|
|
1262
|
+
}
|
|
1263
|
+
groups.sort((a, b) => a.category.localeCompare(b.category));
|
|
1264
|
+
return groups;
|
|
1265
|
+
}, ...(ngDevMode ? [{ debugName: "groups" }] : /* istanbul ignore next */ []));
|
|
1266
|
+
}
|
|
1267
|
+
async ngOnInit() {
|
|
1268
|
+
try {
|
|
1269
|
+
const manifest = await this.loader.loadManifest();
|
|
1270
|
+
this._entries.set(manifest.entries);
|
|
1271
|
+
}
|
|
1272
|
+
finally {
|
|
1273
|
+
this.loading.set(false);
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: PublicFaqIndex, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1277
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.13", type: PublicFaqIndex, isStandalone: true, selector: "public-faq-index", ngImport: i0, template: `
|
|
1278
|
+
<article class="public-faq-index">
|
|
1279
|
+
<header>
|
|
1280
|
+
<h1>Brokenstock Help</h1>
|
|
1281
|
+
<p class="lead">Documentation and walkthroughs for the Brokenstock trade-journal platform.</p>
|
|
1282
|
+
</header>
|
|
1283
|
+
@if (loading()) {
|
|
1284
|
+
<p>Loading…</p>
|
|
1285
|
+
} @else if (groups().length === 0) {
|
|
1286
|
+
<p>No help pages are published yet.</p>
|
|
1287
|
+
} @else {
|
|
1288
|
+
@for (group of groups(); track group.category) {
|
|
1289
|
+
<section>
|
|
1290
|
+
<h2>{{ group.category }}</h2>
|
|
1291
|
+
<ul>
|
|
1292
|
+
@for (entry of group.entries; track entry.key) {
|
|
1293
|
+
<li>
|
|
1294
|
+
<a [routerLink]="['/help', entry.file]">{{ entry.title }}</a>
|
|
1295
|
+
@if (entry.description) {
|
|
1296
|
+
<span class="desc"> — {{ entry.description }}</span>
|
|
1297
|
+
}
|
|
1298
|
+
</li>
|
|
1299
|
+
}
|
|
1300
|
+
</ul>
|
|
1301
|
+
</section>
|
|
1302
|
+
}
|
|
1303
|
+
}
|
|
1304
|
+
</article>
|
|
1305
|
+
`, isInline: true, styles: [":host{display:block}.public-faq-index{max-width:860px;margin:0 auto;padding:2rem 1.25rem 4rem;font-family:system-ui,-apple-system,Segoe UI,sans-serif;line-height:1.55}header h1{font-size:2.25rem;margin:0 0 .5rem}.lead{color:#555;margin:0 0 2rem;font-size:1.1rem}h2{font-size:1.35rem;margin:1.75rem 0 .5rem;border-bottom:1px solid #eee;padding-bottom:.25rem}ul{list-style:none;padding:0;margin:0}li{padding:.4rem 0}a{color:#1565c0;text-decoration:none;font-weight:500}a:hover{text-decoration:underline}.desc{color:#666;font-weight:400}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }] }); }
|
|
1306
|
+
}
|
|
1307
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: PublicFaqIndex, decorators: [{
|
|
1308
|
+
type: Component,
|
|
1309
|
+
args: [{ selector: 'public-faq-index', standalone: true, imports: [CommonModule, RouterLink], template: `
|
|
1310
|
+
<article class="public-faq-index">
|
|
1311
|
+
<header>
|
|
1312
|
+
<h1>Brokenstock Help</h1>
|
|
1313
|
+
<p class="lead">Documentation and walkthroughs for the Brokenstock trade-journal platform.</p>
|
|
1314
|
+
</header>
|
|
1315
|
+
@if (loading()) {
|
|
1316
|
+
<p>Loading…</p>
|
|
1317
|
+
} @else if (groups().length === 0) {
|
|
1318
|
+
<p>No help pages are published yet.</p>
|
|
1319
|
+
} @else {
|
|
1320
|
+
@for (group of groups(); track group.category) {
|
|
1321
|
+
<section>
|
|
1322
|
+
<h2>{{ group.category }}</h2>
|
|
1323
|
+
<ul>
|
|
1324
|
+
@for (entry of group.entries; track entry.key) {
|
|
1325
|
+
<li>
|
|
1326
|
+
<a [routerLink]="['/help', entry.file]">{{ entry.title }}</a>
|
|
1327
|
+
@if (entry.description) {
|
|
1328
|
+
<span class="desc"> — {{ entry.description }}</span>
|
|
1329
|
+
}
|
|
1330
|
+
</li>
|
|
1331
|
+
}
|
|
1332
|
+
</ul>
|
|
1333
|
+
</section>
|
|
1334
|
+
}
|
|
1335
|
+
}
|
|
1336
|
+
</article>
|
|
1337
|
+
`, styles: [":host{display:block}.public-faq-index{max-width:860px;margin:0 auto;padding:2rem 1.25rem 4rem;font-family:system-ui,-apple-system,Segoe UI,sans-serif;line-height:1.55}header h1{font-size:2.25rem;margin:0 0 .5rem}.lead{color:#555;margin:0 0 2rem;font-size:1.1rem}h2{font-size:1.35rem;margin:1.75rem 0 .5rem;border-bottom:1px solid #eee;padding-bottom:.25rem}ul{list-style:none;padding:0;margin:0}li{padding:.4rem 0}a{color:#1565c0;text-decoration:none;font-weight:500}a:hover{text-decoration:underline}.desc{color:#666;font-weight:400}\n"] }]
|
|
1338
|
+
}] });
|
|
1339
|
+
|
|
1340
|
+
/**
|
|
1341
|
+
* Public, SEO-targeted FAQ page. Prerendered at build time per
|
|
1342
|
+
* qualifying manifest entry (e.g. /help/landing, /help/trade/segments).
|
|
1343
|
+
*
|
|
1344
|
+
* The route is `help/**` so multi-segment file paths work; this
|
|
1345
|
+
* component reads the wildcard path off `ActivatedRoute.url`.
|
|
1346
|
+
*/
|
|
1347
|
+
class PublicFaqPage {
|
|
1348
|
+
constructor() {
|
|
1349
|
+
this.route = inject(ActivatedRoute);
|
|
1350
|
+
this.loader = inject(FAQ_CONTENT_LOADER);
|
|
1351
|
+
this.renderer = inject(FaqMarkdownRendererService);
|
|
1352
|
+
this.entry = signal(null, ...(ngDevMode ? [{ debugName: "entry" }] : /* istanbul ignore next */ []));
|
|
1353
|
+
this.body = signal('', ...(ngDevMode ? [{ debugName: "body" }] : /* istanbul ignore next */ []));
|
|
1354
|
+
this.loading = signal(true, ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
|
|
1355
|
+
this.renderedHtml = computed(() => {
|
|
1356
|
+
const entry = this.entry();
|
|
1357
|
+
const body = this.body();
|
|
1358
|
+
if (!entry || !body)
|
|
1359
|
+
return '';
|
|
1360
|
+
return this.renderer.render(body, {
|
|
1361
|
+
context: 'page',
|
|
1362
|
+
imagePrefix: entry.imagePrefix
|
|
1363
|
+
? `/assets/faq/${entry.imagePrefix}`
|
|
1364
|
+
: undefined,
|
|
1365
|
+
});
|
|
1366
|
+
}, ...(ngDevMode ? [{ debugName: "renderedHtml" }] : /* istanbul ignore next */ []));
|
|
1367
|
+
}
|
|
1368
|
+
async ngOnInit() {
|
|
1369
|
+
try {
|
|
1370
|
+
const segments = this.route.snapshot.url.map((s) => s.path);
|
|
1371
|
+
const filePath = segments.join('/');
|
|
1372
|
+
if (!filePath) {
|
|
1373
|
+
return;
|
|
1374
|
+
}
|
|
1375
|
+
const manifest = await this.loader.loadManifest();
|
|
1376
|
+
const match = manifest.entries.find((e) => e.file === filePath &&
|
|
1377
|
+
e.audience === 'public' &&
|
|
1378
|
+
e.seoReady);
|
|
1379
|
+
if (!match)
|
|
1380
|
+
return;
|
|
1381
|
+
const content = await this.loader.loadContent(match.key);
|
|
1382
|
+
if (content === null)
|
|
1383
|
+
return;
|
|
1384
|
+
const parsed = this.renderer.parse(content);
|
|
1385
|
+
this.entry.set(match);
|
|
1386
|
+
this.body.set(parsed.body);
|
|
1387
|
+
}
|
|
1388
|
+
finally {
|
|
1389
|
+
this.loading.set(false);
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: PublicFaqPage, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1393
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.13", type: PublicFaqPage, isStandalone: true, selector: "public-faq-page", ngImport: i0, template: `
|
|
1394
|
+
<article class="public-faq-page">
|
|
1395
|
+
<nav class="crumbs">
|
|
1396
|
+
<a routerLink="/help">← Help</a>
|
|
1397
|
+
</nav>
|
|
1398
|
+
@if (loading()) {
|
|
1399
|
+
<p>Loading…</p>
|
|
1400
|
+
} @else if (!entry()) {
|
|
1401
|
+
<header>
|
|
1402
|
+
<h1>Page not found</h1>
|
|
1403
|
+
<p>That help page doesn't exist or isn't published. Try the <a routerLink="/help">help index</a>.</p>
|
|
1404
|
+
</header>
|
|
1405
|
+
} @else {
|
|
1406
|
+
<header>
|
|
1407
|
+
<h1>{{ entry()!.title }}</h1>
|
|
1408
|
+
@if (entry()!.description) {
|
|
1409
|
+
<p class="lead">{{ entry()!.description }}</p>
|
|
1410
|
+
}
|
|
1411
|
+
</header>
|
|
1412
|
+
<div class="body" [innerHTML]="renderedHtml()"></div>
|
|
1413
|
+
}
|
|
1414
|
+
</article>
|
|
1415
|
+
`, isInline: true, styles: [":host{display:block}.public-faq-page{max-width:860px;margin:0 auto;padding:2rem 1.25rem 4rem;font-family:system-ui,-apple-system,Segoe UI,sans-serif;line-height:1.6}.crumbs{margin-bottom:1.5rem;font-size:.9rem}.crumbs a{color:#1565c0;text-decoration:none}.crumbs a:hover{text-decoration:underline}header h1{font-size:2.1rem;margin:0 0 .5rem}.lead{color:#555;font-size:1.1rem;margin:0 0 1.5rem}.body :is(h1,h2,h3,h4){margin-top:2rem}.body a{color:#1565c0}.body img{max-width:100%;height:auto}.body pre{background:#f6f8fa;padding:.75rem 1rem;border-radius:6px;overflow-x:auto}.body code{background:#f6f8fa;padding:.1rem .3rem;border-radius:3px;font-size:.9em}.body pre code{background:transparent;padding:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }] }); }
|
|
1416
|
+
}
|
|
1417
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: PublicFaqPage, decorators: [{
|
|
1418
|
+
type: Component,
|
|
1419
|
+
args: [{ selector: 'public-faq-page', standalone: true, imports: [CommonModule, RouterLink], template: `
|
|
1420
|
+
<article class="public-faq-page">
|
|
1421
|
+
<nav class="crumbs">
|
|
1422
|
+
<a routerLink="/help">← Help</a>
|
|
1423
|
+
</nav>
|
|
1424
|
+
@if (loading()) {
|
|
1425
|
+
<p>Loading…</p>
|
|
1426
|
+
} @else if (!entry()) {
|
|
1427
|
+
<header>
|
|
1428
|
+
<h1>Page not found</h1>
|
|
1429
|
+
<p>That help page doesn't exist or isn't published. Try the <a routerLink="/help">help index</a>.</p>
|
|
1430
|
+
</header>
|
|
1431
|
+
} @else {
|
|
1432
|
+
<header>
|
|
1433
|
+
<h1>{{ entry()!.title }}</h1>
|
|
1434
|
+
@if (entry()!.description) {
|
|
1435
|
+
<p class="lead">{{ entry()!.description }}</p>
|
|
1436
|
+
}
|
|
1437
|
+
</header>
|
|
1438
|
+
<div class="body" [innerHTML]="renderedHtml()"></div>
|
|
1439
|
+
}
|
|
1440
|
+
</article>
|
|
1441
|
+
`, styles: [":host{display:block}.public-faq-page{max-width:860px;margin:0 auto;padding:2rem 1.25rem 4rem;font-family:system-ui,-apple-system,Segoe UI,sans-serif;line-height:1.6}.crumbs{margin-bottom:1.5rem;font-size:.9rem}.crumbs a{color:#1565c0;text-decoration:none}.crumbs a:hover{text-decoration:underline}header h1{font-size:2.1rem;margin:0 0 .5rem}.lead{color:#555;font-size:1.1rem;margin:0 0 1.5rem}.body :is(h1,h2,h3,h4){margin-top:2rem}.body a{color:#1565c0}.body img{max-width:100%;height:auto}.body pre{background:#f6f8fa;padding:.75rem 1rem;border-radius:6px;overflow-x:auto}.body code{background:#f6f8fa;padding:.1rem .3rem;border-radius:3px;font-size:.9em}.body pre code{background:transparent;padding:0}\n"] }]
|
|
1442
|
+
}] });
|
|
1443
|
+
|
|
1239
1444
|
class ThemeService {
|
|
1240
1445
|
constructor() {
|
|
1241
1446
|
this.mode = signal('dark', ...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
|
|
@@ -2048,5 +2253,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImpo
|
|
|
2048
2253
|
* Generated bundle index. Do not edit.
|
|
2049
2254
|
*/
|
|
2050
2255
|
|
|
2051
|
-
export { AuthenticationService, CLEAR_USAGE, CommandRegistryService, CommandService, CommandTerminal, ConfirmDialog, FAQ_CONTENT_LOADER, FAQ_DEV_EDITOR, FAQ_DEV_MODE, FAQ_DEV_WORKSPACE_ROOT, FaqAuthoringPanel, FaqHistoryService, FaqMarkdownRendererService, FaqModal, FaqService, HELP_USAGE, HttpFaqContentLoader, KeyboardShortcutService, Login, MainContent, RegexValidatorDirective, SHELL_APP_NAME, SHELL_AUTH_URLS, SHELL_COMMANDS, SHELL_MENU_ITEMS, SHELL_POST_LOGIN_ROUTE, Shell, SideMenu, StatusBar, TerminalFocusService, ThemeService, ThinkingService, audienceAllowed, authGuard, authInterceptor, buildFallbackChain, guestGuard, provideShellConfig, tokenize };
|
|
2256
|
+
export { AuthenticationService, CLEAR_USAGE, CommandRegistryService, CommandService, CommandTerminal, ConfirmDialog, FAQ_CONTENT_LOADER, FAQ_DEV_EDITOR, FAQ_DEV_MODE, FAQ_DEV_WORKSPACE_ROOT, FaqAuthoringPanel, FaqHistoryService, FaqMarkdownRendererService, FaqModal, FaqService, HELP_USAGE, HttpFaqContentLoader, KeyboardShortcutService, Login, MainContent, PublicFaqIndex, PublicFaqPage, RegexValidatorDirective, SHELL_APP_NAME, SHELL_AUTH_URLS, SHELL_COMMANDS, SHELL_MENU_ITEMS, SHELL_POST_LOGIN_ROUTE, Shell, SideMenu, StatusBar, TerminalFocusService, ThemeService, ThinkingService, audienceAllowed, authGuard, authInterceptor, buildFallbackChain, guestGuard, provideShellConfig, tokenize };
|
|
2052
2257
|
//# sourceMappingURL=franzzemen-brokenstock-shell.mjs.map
|