@ah-oh/ao-workspaces-design-system 0.0.53 → 0.0.55
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.
|
@@ -27,7 +27,9 @@ import { MarkdownComponent } from 'ngx-markdown';
|
|
|
27
27
|
import { CdkMenu, CdkMenuItem } from '@angular/cdk/menu';
|
|
28
28
|
import { Overlay, CdkOverlayOrigin, CdkConnectedOverlay } from '@angular/cdk/overlay';
|
|
29
29
|
import { ComponentPortal } from '@angular/cdk/portal';
|
|
30
|
-
import { SurfaceComponent, A2uiRendererService, BasicCatalogBase, A2UI_RENDERER_CONFIG, provideMarkdownRenderer } from '@a2ui/angular/v0_9';
|
|
30
|
+
import { SurfaceComponent, A2uiRendererService, CatalogComponent, BasicCatalogBase, A2UI_RENDERER_CONFIG, provideMarkdownRenderer } from '@a2ui/angular/v0_9';
|
|
31
|
+
import { ChoicePickerApi } from '@a2ui/web_core/v0_9/basic_catalog';
|
|
32
|
+
import { renderMarkdown } from '@a2ui/markdown-it';
|
|
31
33
|
|
|
32
34
|
class DesignSystem {
|
|
33
35
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: DesignSystem, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
@@ -5146,7 +5148,8 @@ class WorkspaceNavbarService {
|
|
|
5146
5148
|
companies = new BehaviorSubject([]);
|
|
5147
5149
|
companies$ = this.companies.asObservable();
|
|
5148
5150
|
companiesSignal = toSignal(this.companies$);
|
|
5149
|
-
activeAppId;
|
|
5151
|
+
activeAppId = new BehaviorSubject(undefined);
|
|
5152
|
+
activeAppIdSignal = toSignal(this.activeAppId.asObservable());
|
|
5150
5153
|
loginUrl = 'https://login.ah-oh.com';
|
|
5151
5154
|
production = true;
|
|
5152
5155
|
preserveRedirectUrl = true;
|
|
@@ -5154,10 +5157,10 @@ class WorkspaceNavbarService {
|
|
|
5154
5157
|
return this.session.value;
|
|
5155
5158
|
}
|
|
5156
5159
|
get currentAppId() {
|
|
5157
|
-
return this.activeAppId;
|
|
5160
|
+
return this.activeAppId.value;
|
|
5158
5161
|
}
|
|
5159
5162
|
init(config) {
|
|
5160
|
-
this.activeAppId
|
|
5163
|
+
this.activeAppId.next(config.appId);
|
|
5161
5164
|
this.production = config.production;
|
|
5162
5165
|
this.preserveRedirectUrl = config.preserveRedirectUrl ?? true;
|
|
5163
5166
|
if (config.loginUrl) {
|
|
@@ -5179,6 +5182,7 @@ class WorkspaceNavbarService {
|
|
|
5179
5182
|
...res,
|
|
5180
5183
|
isExternalUser: res.companyId !== res.enabledCompanyId,
|
|
5181
5184
|
};
|
|
5185
|
+
this.activeAppId.next(userSession.appId ?? userSession.product ?? config.appId);
|
|
5182
5186
|
this.session.next(userSession);
|
|
5183
5187
|
this.loadWorkspaceApps().subscribe();
|
|
5184
5188
|
this.findEnabledCompanies().subscribe();
|
|
@@ -5196,21 +5200,11 @@ class WorkspaceNavbarService {
|
|
|
5196
5200
|
}
|
|
5197
5201
|
loadWorkspaceApps() {
|
|
5198
5202
|
return this.http.get(WorkspaceNavbarService.WORKSPACE_APPS_URL).pipe(map$1(response => {
|
|
5199
|
-
|
|
5200
|
-
|
|
5201
|
-
|
|
5202
|
-
|
|
5203
|
-
|
|
5204
|
-
}));
|
|
5205
|
-
response = {
|
|
5206
|
-
...response,
|
|
5207
|
-
products: apps.filter(a => response.products.some(p => p.appId === a.appId)),
|
|
5208
|
-
customApps: apps.filter(a => response.customApps.some(c => c.appId === a.appId)),
|
|
5209
|
-
};
|
|
5210
|
-
}
|
|
5211
|
-
this.workspaceApps.next(apps);
|
|
5212
|
-
this.workspaceAppsResponse.next(response);
|
|
5213
|
-
return apps;
|
|
5203
|
+
const normalizedResponse = this.normalizeWorkspaceAppsResponse(response);
|
|
5204
|
+
const workspaceApps = [...normalizedResponse.products, ...normalizedResponse.customApps];
|
|
5205
|
+
this.workspaceApps.next(workspaceApps);
|
|
5206
|
+
this.workspaceAppsResponse.next(normalizedResponse);
|
|
5207
|
+
return workspaceApps;
|
|
5214
5208
|
}), catchError(err => {
|
|
5215
5209
|
console.error('Failed to load workspace apps:', err);
|
|
5216
5210
|
return of([]);
|
|
@@ -5230,14 +5224,16 @@ class WorkspaceNavbarService {
|
|
|
5230
5224
|
if (!session) {
|
|
5231
5225
|
throw new Error('Session is not initialized.');
|
|
5232
5226
|
}
|
|
5233
|
-
const appId = args.appId ?? this.
|
|
5227
|
+
const appId = args.appId ?? this.currentAppId ?? 'admin';
|
|
5234
5228
|
const companyId = args.companyId ?? session.enabledCompanyId;
|
|
5235
5229
|
return this.http
|
|
5236
5230
|
.get(`/auth-api/users/new-company/${companyId}/${session.userId}/${appId}`)
|
|
5237
5231
|
.pipe(tap(({ jwtKey }) => {
|
|
5238
5232
|
const app = this.workspaceApps.value.find(a => a.appId === appId);
|
|
5239
|
-
const
|
|
5240
|
-
|
|
5233
|
+
const targetUrl = app
|
|
5234
|
+
? this.getRuntimeBaseUrl(app, args.isTesting)
|
|
5235
|
+
: window.location.origin;
|
|
5236
|
+
window.location.href = this.buildJwtRedirectUrl({ targetUrl, jwtKey });
|
|
5241
5237
|
}));
|
|
5242
5238
|
}
|
|
5243
5239
|
switchApp(appId, isTesting = false) {
|
|
@@ -5252,15 +5248,18 @@ class WorkspaceNavbarService {
|
|
|
5252
5248
|
return this.http
|
|
5253
5249
|
.get(`/auth-api/users/new-company/${session.enabledCompanyId}/${session.userId}/${appId}`)
|
|
5254
5250
|
.pipe(tap(({ jwtKey }) => {
|
|
5255
|
-
const
|
|
5256
|
-
window.location.href =
|
|
5251
|
+
const targetUrl = this.getRuntimeBaseUrl(app, isTesting);
|
|
5252
|
+
window.location.href = this.buildJwtRedirectUrl({ targetUrl, jwtKey });
|
|
5257
5253
|
}));
|
|
5258
5254
|
}
|
|
5259
5255
|
createCompany() {
|
|
5260
5256
|
return this.http
|
|
5261
5257
|
.get(`${WorkspaceNavbarService.AUTH_BASE_URL}/jwt-key`)
|
|
5262
5258
|
.pipe(tap(({ jwtKey }) => {
|
|
5263
|
-
window.location.href =
|
|
5259
|
+
window.location.href = this.buildLoginPathUrl('create-company', {
|
|
5260
|
+
product: this.currentAppId,
|
|
5261
|
+
jwtKey,
|
|
5262
|
+
});
|
|
5264
5263
|
}));
|
|
5265
5264
|
}
|
|
5266
5265
|
signOut() {
|
|
@@ -5271,13 +5270,14 @@ class WorkspaceNavbarService {
|
|
|
5271
5270
|
}));
|
|
5272
5271
|
}
|
|
5273
5272
|
buildLoginUrl() {
|
|
5274
|
-
|
|
5273
|
+
const url = new URL(this.loginUrl, window.location.origin);
|
|
5274
|
+
url.searchParams.set('product', this.currentAppId ?? 'admin');
|
|
5275
5275
|
if (this.preserveRedirectUrl) {
|
|
5276
5276
|
const currentUrl = new URL(window.location.href);
|
|
5277
5277
|
currentUrl.searchParams.delete('jwtKey');
|
|
5278
|
-
url
|
|
5278
|
+
url.searchParams.set('redirectUrl', currentUrl.toString());
|
|
5279
5279
|
}
|
|
5280
|
-
return url;
|
|
5280
|
+
return url.toString();
|
|
5281
5281
|
}
|
|
5282
5282
|
replaceSessionParams(url) {
|
|
5283
5283
|
const session = this.session.value;
|
|
@@ -5290,7 +5290,7 @@ class WorkspaceNavbarService {
|
|
|
5290
5290
|
const app = this.workspaceApps.value.find(a => a.appId === appId);
|
|
5291
5291
|
if (!app)
|
|
5292
5292
|
return undefined;
|
|
5293
|
-
return
|
|
5293
|
+
return this.getRuntimeBaseUrl(app, isTesting);
|
|
5294
5294
|
}
|
|
5295
5295
|
getCompanyLogo(companyId) {
|
|
5296
5296
|
return this.http.get(`${WorkspaceNavbarService.COMPANY_URL}/${companyId}/logo`);
|
|
@@ -5308,6 +5308,45 @@ class WorkspaceNavbarService {
|
|
|
5308
5308
|
};
|
|
5309
5309
|
return devUrls[appId] ?? `http://localhost:4200`;
|
|
5310
5310
|
}
|
|
5311
|
+
normalizeWorkspaceAppsResponse(response) {
|
|
5312
|
+
if (this.production) {
|
|
5313
|
+
return response;
|
|
5314
|
+
}
|
|
5315
|
+
return {
|
|
5316
|
+
...response,
|
|
5317
|
+
products: response.products.map(app => this.withRuntimeBaseUrl(app)),
|
|
5318
|
+
customApps: response.customApps.map(app => this.withRuntimeBaseUrl(app)),
|
|
5319
|
+
};
|
|
5320
|
+
}
|
|
5321
|
+
withRuntimeBaseUrl(app) {
|
|
5322
|
+
return {
|
|
5323
|
+
...app,
|
|
5324
|
+
baseUrl: this.getRuntimeBaseUrl(app),
|
|
5325
|
+
};
|
|
5326
|
+
}
|
|
5327
|
+
getRuntimeBaseUrl(app, isTesting = false) {
|
|
5328
|
+
if (isTesting && app.testingUrl) {
|
|
5329
|
+
return app.testingUrl;
|
|
5330
|
+
}
|
|
5331
|
+
if (!this.production) {
|
|
5332
|
+
return app.testingUrl ?? this.getLegacyDevUrl(app.appId);
|
|
5333
|
+
}
|
|
5334
|
+
return app.baseUrl;
|
|
5335
|
+
}
|
|
5336
|
+
buildJwtRedirectUrl(arg) {
|
|
5337
|
+
const url = new URL(arg.targetUrl, window.location.origin);
|
|
5338
|
+
url.searchParams.set('jwtKey', arg.jwtKey);
|
|
5339
|
+
return url.toString();
|
|
5340
|
+
}
|
|
5341
|
+
buildLoginPathUrl(path, params) {
|
|
5342
|
+
const baseUrl = this.loginUrl.endsWith('/') ? this.loginUrl : `${this.loginUrl}/`;
|
|
5343
|
+
const url = new URL(path, baseUrl);
|
|
5344
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
5345
|
+
if (value)
|
|
5346
|
+
url.searchParams.set(key, value);
|
|
5347
|
+
});
|
|
5348
|
+
return url.toString();
|
|
5349
|
+
}
|
|
5311
5350
|
getEnabledApps() {
|
|
5312
5351
|
const session = this.session.value;
|
|
5313
5352
|
return session?.enabledApps ?? this.buildLegacyEnabledApps(session);
|
|
@@ -6930,11 +6969,11 @@ class ChatMessageComponent {
|
|
|
6930
6969
|
}
|
|
6931
6970
|
}
|
|
6932
6971
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: ChatMessageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
6933
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.13", type: ChatMessageComponent, isStandalone: true, selector: "lib-chat-message", inputs: { parts: { classPropertyName: "parts", publicName: "parts", isSignal: true, isRequired: false, transformFunction: null }, side: { classPropertyName: "side", publicName: "side", isSignal: true, isRequired: false, transformFunction: null }, showTyping: { classPropertyName: "showTyping", publicName: "showTyping", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"message\" [class.right]=\"side() === 'right'\" [class.left]=\"side() === 'left'\">\n @for (part of normalisedParts(); track $index) {\n @switch (part.kind) {\n @case ('text') {\n <markdown\n [data]=\"part.content\"\n (ready)=\"onMarkdownReady($any($event))\"\n ></markdown>\n }\n @case ('a2ui') {\n <a2ui-v09-surface [surfaceId]=\"part.surface.surfaceId\"></a2ui-v09-surface>\n }\n }\n }\n @if (showTyping()) {\n <div class=\"typing-indicator\">\n <div></div>\n <div></div>\n <div></div>\n </div>\n }\n</div>\n", styles: [".message{padding:
|
|
6972
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.13", type: ChatMessageComponent, isStandalone: true, selector: "lib-chat-message", inputs: { parts: { classPropertyName: "parts", publicName: "parts", isSignal: true, isRequired: false, transformFunction: null }, side: { classPropertyName: "side", publicName: "side", isSignal: true, isRequired: false, transformFunction: null }, showTyping: { classPropertyName: "showTyping", publicName: "showTyping", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"message\" [class.right]=\"side() === 'right'\" [class.left]=\"side() === 'left'\">\n @for (part of normalisedParts(); track $index) {\n @switch (part.kind) {\n @case ('text') {\n <markdown\n [data]=\"part.content\"\n (ready)=\"onMarkdownReady($any($event))\"\n ></markdown>\n }\n @case ('a2ui') {\n <a2ui-v09-surface [surfaceId]=\"part.surface.surfaceId\"></a2ui-v09-surface>\n }\n }\n }\n @if (showTyping()) {\n <div class=\"typing-indicator\">\n <div></div>\n <div></div>\n <div></div>\n </div>\n }\n</div>\n", styles: [".message{padding:12px 14px;border-radius:8px;background-color:#fff;color:var(--color-text-primary, #252525);font-size:14px;line-height:1.45;max-width:430px;position:relative}.message:before{content:\"\";height:0;width:0;position:absolute;bottom:0;border:12px solid;border-color:transparent transparent white transparent}.message.right{margin-left:32px;border-bottom-right-radius:0;align-self:flex-end}.message.right:before{left:auto;right:-12px}.message.left{margin-right:32px;margin-left:0;border-bottom-left-radius:0;align-self:flex-start}.message.left:before{left:-12px;right:auto}.message ::ng-deep markdown p{margin:0 0 10px}.message ::ng-deep markdown p:last-child{margin-bottom:0}.message ::ng-deep a2ui-v09-surface{display:block;margin-top:8px}.message ::ng-deep .a2ui-text h1,.message ::ng-deep .a2ui-text h2,.message ::ng-deep .a2ui-text h3,.message ::ng-deep .a2ui-text h4{font-weight:600}.message .typing-indicator{margin:24px auto;display:flex;justify-content:center;flex-direction:row;gap:1px}.message .typing-indicator div{width:9px;height:9px;border-radius:50%;background-color:var(--color-grey-mid)}.message .typing-indicator div:nth-child(1){animation:.9s blink infinite 0s}.message .typing-indicator div:nth-child(2){animation:.9s blink infinite .3s}.message .typing-indicator div:nth-child(3){animation:.9s blink infinite .6s}@keyframes blink{0%{opacity:.5;transform:scaleY(1),translateY(0)}20%{transform:scaleY(.4) translateY(6px)}50%{opacity:1;transform:scaleY(1) translateY(0)}to{opacity:.5}}\n"], dependencies: [{ kind: "component", type: MarkdownComponent, selector: "markdown, [markdown]", inputs: ["data", "src", "disableSanitizer", "inline", "clipboard", "clipboardButtonComponent", "clipboardButtonTemplate", "emoji", "katex", "katexOptions", "mermaid", "mermaidOptions", "lineHighlight", "line", "lineOffset", "lineNumbers", "start", "commandLine", "filterOutput", "host", "prompt", "output", "user"], outputs: ["error", "load", "ready"] }, { kind: "component", type: SurfaceComponent, selector: "a2ui-v09-surface", inputs: ["surfaceId", "dataContextPath"] }] });
|
|
6934
6973
|
}
|
|
6935
6974
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: ChatMessageComponent, decorators: [{
|
|
6936
6975
|
type: Component,
|
|
6937
|
-
args: [{ selector: 'lib-chat-message', imports: [MarkdownComponent, SurfaceComponent], template: "<div class=\"message\" [class.right]=\"side() === 'right'\" [class.left]=\"side() === 'left'\">\n @for (part of normalisedParts(); track $index) {\n @switch (part.kind) {\n @case ('text') {\n <markdown\n [data]=\"part.content\"\n (ready)=\"onMarkdownReady($any($event))\"\n ></markdown>\n }\n @case ('a2ui') {\n <a2ui-v09-surface [surfaceId]=\"part.surface.surfaceId\"></a2ui-v09-surface>\n }\n }\n }\n @if (showTyping()) {\n <div class=\"typing-indicator\">\n <div></div>\n <div></div>\n <div></div>\n </div>\n }\n</div>\n", styles: [".message{padding:
|
|
6976
|
+
args: [{ selector: 'lib-chat-message', imports: [MarkdownComponent, SurfaceComponent], template: "<div class=\"message\" [class.right]=\"side() === 'right'\" [class.left]=\"side() === 'left'\">\n @for (part of normalisedParts(); track $index) {\n @switch (part.kind) {\n @case ('text') {\n <markdown\n [data]=\"part.content\"\n (ready)=\"onMarkdownReady($any($event))\"\n ></markdown>\n }\n @case ('a2ui') {\n <a2ui-v09-surface [surfaceId]=\"part.surface.surfaceId\"></a2ui-v09-surface>\n }\n }\n }\n @if (showTyping()) {\n <div class=\"typing-indicator\">\n <div></div>\n <div></div>\n <div></div>\n </div>\n }\n</div>\n", styles: [".message{padding:12px 14px;border-radius:8px;background-color:#fff;color:var(--color-text-primary, #252525);font-size:14px;line-height:1.45;max-width:430px;position:relative}.message:before{content:\"\";height:0;width:0;position:absolute;bottom:0;border:12px solid;border-color:transparent transparent white transparent}.message.right{margin-left:32px;border-bottom-right-radius:0;align-self:flex-end}.message.right:before{left:auto;right:-12px}.message.left{margin-right:32px;margin-left:0;border-bottom-left-radius:0;align-self:flex-start}.message.left:before{left:-12px;right:auto}.message ::ng-deep markdown p{margin:0 0 10px}.message ::ng-deep markdown p:last-child{margin-bottom:0}.message ::ng-deep a2ui-v09-surface{display:block;margin-top:8px}.message ::ng-deep .a2ui-text h1,.message ::ng-deep .a2ui-text h2,.message ::ng-deep .a2ui-text h3,.message ::ng-deep .a2ui-text h4{font-weight:600}.message .typing-indicator{margin:24px auto;display:flex;justify-content:center;flex-direction:row;gap:1px}.message .typing-indicator div{width:9px;height:9px;border-radius:50%;background-color:var(--color-grey-mid)}.message .typing-indicator div:nth-child(1){animation:.9s blink infinite 0s}.message .typing-indicator div:nth-child(2){animation:.9s blink infinite .3s}.message .typing-indicator div:nth-child(3){animation:.9s blink infinite .6s}@keyframes blink{0%{opacity:.5;transform:scaleY(1),translateY(0)}20%{transform:scaleY(.4) translateY(6px)}50%{opacity:1;transform:scaleY(1) translateY(0)}to{opacity:.5}}\n"] }]
|
|
6938
6977
|
}], propDecorators: { parts: [{ type: i0.Input, args: [{ isSignal: true, alias: "parts", required: false }] }], side: [{ type: i0.Input, args: [{ isSignal: true, alias: "side", required: false }] }], showTyping: [{ type: i0.Input, args: [{ isSignal: true, alias: "showTyping", required: false }] }] } });
|
|
6939
6978
|
|
|
6940
6979
|
class RobinChatService {
|
|
@@ -7033,12 +7072,11 @@ class ChatComponent {
|
|
|
7033
7072
|
dispatcher = inject(RobinChatActionDispatcher);
|
|
7034
7073
|
authService = inject(WorkspaceNavbarService);
|
|
7035
7074
|
destroyRef = inject(DestroyRef);
|
|
7075
|
+
appName = inject(ROBIN_SEARCH_APP_NAME);
|
|
7036
7076
|
product;
|
|
7037
|
-
handbookType;
|
|
7038
7077
|
currentThreadId;
|
|
7039
7078
|
ngOnInit() {
|
|
7040
7079
|
this.product = this.resolveProduct();
|
|
7041
|
-
this.handbookType = this.product;
|
|
7042
7080
|
this.dispatcher.responses$
|
|
7043
7081
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
7044
7082
|
.subscribe(response => this.handleResponse(response));
|
|
@@ -7091,7 +7129,12 @@ class ChatComponent {
|
|
|
7091
7129
|
for (const turn of projected) {
|
|
7092
7130
|
for (const part of turn.parts) {
|
|
7093
7131
|
if (part.kind === 'a2ui') {
|
|
7094
|
-
|
|
7132
|
+
try {
|
|
7133
|
+
this.renderer.processMessages(part.surface.messages);
|
|
7134
|
+
}
|
|
7135
|
+
catch (error) {
|
|
7136
|
+
console.warn('[RobinChat] A2UI history render failed', error);
|
|
7137
|
+
}
|
|
7095
7138
|
}
|
|
7096
7139
|
}
|
|
7097
7140
|
}
|
|
@@ -7123,7 +7166,7 @@ class ChatComponent {
|
|
|
7123
7166
|
question: 'Bitte begrüße den User kurz und biete Hilfe an.',
|
|
7124
7167
|
threadId: this.currentThreadId,
|
|
7125
7168
|
product: this.product,
|
|
7126
|
-
|
|
7169
|
+
appName: this.appName,
|
|
7127
7170
|
type: this.searchType ?? null,
|
|
7128
7171
|
})
|
|
7129
7172
|
.then(response => this.handleResponse(response))
|
|
@@ -7137,7 +7180,7 @@ class ChatComponent {
|
|
|
7137
7180
|
question,
|
|
7138
7181
|
threadId: this.currentThreadId,
|
|
7139
7182
|
product: this.product,
|
|
7140
|
-
|
|
7183
|
+
appName: this.appName,
|
|
7141
7184
|
type: this.searchType ?? null,
|
|
7142
7185
|
})
|
|
7143
7186
|
.then(response => this.handleResponse(response))
|
|
@@ -7145,32 +7188,47 @@ class ChatComponent {
|
|
|
7145
7188
|
}
|
|
7146
7189
|
handleResponse(response) {
|
|
7147
7190
|
this.setThreadId(response.threadId);
|
|
7148
|
-
this.
|
|
7149
|
-
|
|
7150
|
-
|
|
7191
|
+
this.tryRetireOldSurfaces();
|
|
7192
|
+
this.appendAssistantTurn(this.processA2uiParts(response.parts));
|
|
7193
|
+
this.threads.set(undefined);
|
|
7194
|
+
this.activeRequest.set(false);
|
|
7195
|
+
}
|
|
7196
|
+
tryRetireOldSurfaces() {
|
|
7197
|
+
try {
|
|
7198
|
+
this.retireOldSurfaces();
|
|
7199
|
+
}
|
|
7200
|
+
catch (error) {
|
|
7201
|
+
console.warn('[RobinChat] A2UI surface retirement failed', error);
|
|
7202
|
+
}
|
|
7203
|
+
}
|
|
7204
|
+
processA2uiParts(parts) {
|
|
7205
|
+
const renderable = [];
|
|
7206
|
+
for (const part of parts) {
|
|
7207
|
+
if (part.kind !== 'a2ui') {
|
|
7208
|
+
renderable.push(part);
|
|
7209
|
+
continue;
|
|
7210
|
+
}
|
|
7211
|
+
try {
|
|
7151
7212
|
this.renderer.processMessages(part.surface.messages);
|
|
7213
|
+
renderable.push(part);
|
|
7214
|
+
}
|
|
7215
|
+
catch (error) {
|
|
7216
|
+
console.warn('[RobinChat] A2UI render failed', error);
|
|
7152
7217
|
}
|
|
7153
7218
|
}
|
|
7154
|
-
|
|
7155
|
-
this.threads.set(undefined);
|
|
7156
|
-
this.activeRequest.set(false);
|
|
7219
|
+
return renderable.length > 0 ? renderable : [{ kind: 'text', content: ERROR_FALLBACK }];
|
|
7157
7220
|
}
|
|
7158
7221
|
/**
|
|
7159
7222
|
* Removes A2UI surfaces from the renderer that belong to older turns and
|
|
7160
7223
|
* strips their `a2ui` parts so the chat history doesn't accumulate stale
|
|
7161
7224
|
* interactive cards as the conversation progresses.
|
|
7162
7225
|
*/
|
|
7163
|
-
retireOldSurfaces(
|
|
7164
|
-
const incoming = new Set(response.parts
|
|
7165
|
-
.filter(part => part.kind === 'a2ui')
|
|
7166
|
-
.map(part => part.surface.surfaceId));
|
|
7226
|
+
retireOldSurfaces() {
|
|
7167
7227
|
const toDelete = [];
|
|
7168
7228
|
const nextTurns = this.turns().map(turn => {
|
|
7169
7229
|
const filtered = turn.parts.filter(part => {
|
|
7170
7230
|
if (part.kind !== 'a2ui')
|
|
7171
7231
|
return true;
|
|
7172
|
-
if (incoming.has(part.surface.surfaceId))
|
|
7173
|
-
return true;
|
|
7174
7232
|
toDelete.push(part.surface.surfaceId);
|
|
7175
7233
|
return false;
|
|
7176
7234
|
});
|
|
@@ -7227,11 +7285,11 @@ class ChatComponent {
|
|
|
7227
7285
|
}
|
|
7228
7286
|
}
|
|
7229
7287
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: ChatComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
7230
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.13", type: ChatComponent, isStandalone: true, selector: "lib-chat", inputs: { searchType: "searchType" }, outputs: { closed: "closed" }, viewQueries: [{ propertyName: "historyElement", first: true, predicate: ["conversation"], descendants: true }, { propertyName: "textField", first: true, predicate: ["textField"], descendants: true }], ngImport: i0, template: "<div class=\"sidebar\">\n @if (showHistory()) {\n <div class=\"chat-history\">\n <div class=\"header\">\n <h3>Verlauf</h3>\n </div>\n <div class=\"history-items\">\n @if (threads() === undefined) {\n <div class=\"history-empty\">L\u00E4dt\u2026</div>\n } @else if (threads()!.length === 0) {\n <div class=\"history-empty\">Noch keine Gespr\u00E4che.</div>\n }\n @for (item of threads(); track item.threadId) {\n <div class=\"chat-history-item\" (click)=\"openThread(item.threadId)\">\n <div class=\"preview\">{{ item.lastMessage }}</div>\n <div class=\"footer\">\n <div>{{ item.messageCount }} Nachrichten</div>\n <div>{{ item.updatedAt | date: 'dd.MM.yyyy HH:mm' }}</div>\n </div>\n </div>\n }\n </div>\n </div>\n }\n <div class=\"chat\">\n <div class=\"header\">\n <button ao-button variant=\"outline\" (click)=\"toggleHistory()\">\n <ao-icon [svg]=\"historyIcon\"></ao-icon>\n </button>\n <h2>Hilfecenter</h2>\n <div class=\"flex\">\n <button ao-button variant=\"outline\" (click)=\"newChat()\">\n <ao-icon [svg]=\"addIcon\"></ao-icon>\n </button>\n <button ao-button variant=\"outline\" (click)=\"showHistory.set(false); closed.emit()\">\n <ao-icon [svg]=\"closeIcon\"></ao-icon>\n </button>\n </div>\n </div>\n <div class=\"conversation-history\" #conversation>\n @for (turn of turns(); track $index) {\n <lib-chat-message\n [parts]=\"turn.parts\"\n [side]=\"turn.role === 'assistant' ? 'left' : 'right'\"\n >\n </lib-chat-message>\n }\n @if (activeRequest()) {\n <lib-chat-message [showTyping]=\"true\" side=\"left\"></lib-chat-message>\n }\n </div>\n\n <div class=\"input\">\n <textarea\n #textField\n rows=\"1\"\n class=\"textarea\"\n [formControl]=\"inputControl\"\n (keydown.enter)=\"send(); $event.stopPropagation(); $event.preventDefault()\"\n (input)=\"setSize()\"\n ></textarea>\n <button ao-button variant=\"primary\" (click)=\"send()\" class=\"send-button\">\n <ao-icon [svg]=\"sendIcon\"></ao-icon>\n </button>\n </div>\n </div>\n</div>\n", styles: ["@charset \"UTF-8\";.sidebar{display:flex;flex-direction:row;height:100%;position:relative}.header{background-color:#fff;padding:
|
|
7288
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.13", type: ChatComponent, isStandalone: true, selector: "lib-chat", inputs: { searchType: "searchType" }, outputs: { closed: "closed" }, viewQueries: [{ propertyName: "historyElement", first: true, predicate: ["conversation"], descendants: true }, { propertyName: "textField", first: true, predicate: ["textField"], descendants: true }], ngImport: i0, template: "<div class=\"sidebar\">\n @if (showHistory()) {\n <div class=\"chat-history\">\n <div class=\"header\">\n <h3>Verlauf</h3>\n </div>\n <div class=\"history-items\">\n @if (threads() === undefined) {\n <div class=\"history-empty\">L\u00E4dt\u2026</div>\n } @else if (threads()!.length === 0) {\n <div class=\"history-empty\">Noch keine Gespr\u00E4che.</div>\n }\n @for (item of threads(); track item.threadId) {\n <div class=\"chat-history-item\" (click)=\"openThread(item.threadId)\">\n <div class=\"preview\">{{ item.lastMessage }}</div>\n <div class=\"footer\">\n <div>{{ item.messageCount }} Nachrichten</div>\n <div>{{ item.updatedAt | date: 'dd.MM.yyyy HH:mm' }}</div>\n </div>\n </div>\n }\n </div>\n </div>\n }\n <div class=\"chat\">\n <div class=\"header\">\n <button ao-button variant=\"outline\" (click)=\"toggleHistory()\">\n <ao-icon [svg]=\"historyIcon\"></ao-icon>\n </button>\n <h2>Hilfecenter</h2>\n <div class=\"flex\">\n <button ao-button variant=\"outline\" (click)=\"newChat()\">\n <ao-icon [svg]=\"addIcon\"></ao-icon>\n </button>\n <button ao-button variant=\"outline\" (click)=\"showHistory.set(false); closed.emit()\">\n <ao-icon [svg]=\"closeIcon\"></ao-icon>\n </button>\n </div>\n </div>\n <div class=\"conversation-history\" #conversation>\n @for (turn of turns(); track $index) {\n <lib-chat-message\n [parts]=\"turn.parts\"\n [side]=\"turn.role === 'assistant' ? 'left' : 'right'\"\n >\n </lib-chat-message>\n }\n @if (activeRequest()) {\n <lib-chat-message [showTyping]=\"true\" side=\"left\"></lib-chat-message>\n }\n </div>\n\n <div class=\"input\">\n <textarea\n #textField\n rows=\"1\"\n class=\"textarea\"\n [formControl]=\"inputControl\"\n (keydown.enter)=\"send(); $event.stopPropagation(); $event.preventDefault()\"\n (input)=\"setSize()\"\n ></textarea>\n <button ao-button variant=\"primary\" (click)=\"send()\" class=\"send-button\">\n <ao-icon [svg]=\"sendIcon\"></ao-icon>\n </button>\n </div>\n </div>\n</div>\n", styles: ["@charset \"UTF-8\";.sidebar{display:flex;flex-direction:row;height:100%;position:relative}.header{background-color:#fff;padding:6px 8px;display:flex;height:50px;flex-direction:row;align-items:center}.header h2,.header h3{margin:0}.header h2{font-size:18px;font-weight:600}.header h3{font-size:16px}.chat{display:flex;flex-direction:column;height:100%;width:500px;background-color:#f3f3f3;border-left:1px solid #e9e9e9}.chat .header{justify-content:space-between}.chat .header .flex{display:flex;align-items:center;gap:10px}.conversation-history{--a2ui-color-primary: #212121;--a2ui-color-on-primary: #ffffff;--a2ui-color-surface: #ffffff;--a2ui-color-on-background: #212121;--a2ui-color-border: #e9e9e9;--a2ui-text-color-text: #212121;--a2ui-text-caption-color: #909090;--a2ui-text-a-color: #ff004d;--a2ui-spacing-xs: 5px;--a2ui-spacing-s: 10px;--a2ui-spacing-m: 15px;--a2ui-spacing-l: 20px;--a2ui-row-gap: 12px;--a2ui-column-gap: 10px;--a2ui-font-family-title: inherit;--a2ui-font-size-2xl: 22px;--a2ui-font-size-xl: 19px;--a2ui-font-size-l: 16px;--a2ui-font-size-m: 14px;--a2ui-font-size-s: 13px;--a2ui-font-size-xs: 12px;--a2ui-card-background: #ffffff;--a2ui-card-border-radius: 8px;--a2ui-card-padding: 14px;--a2ui-card-border: none;--a2ui-button-background: #ffffff;--a2ui-button-border: 1px solid #212121;--a2ui-button-border-radius: 999px;--a2ui-button-padding: 8px 14px;--a2ui-button-font-weight: 500;--a2ui-choicepicker-gap: 10px;--a2ui-choicepicker-padding: 0;--a2ui-choicepicker-checkbox-size: 18px;--a2ui-choicepicker-chip-background: #ffffff;--a2ui-choicepicker-chip-background-selected: #212121;--a2ui-choicepicker-chip-border: 1px solid #212121;--a2ui-choicepicker-chip-border-radius: 999px;--a2ui-choicepicker-chip-padding: 7px 14px;--a2ui-choicepicker-chip-color: #212121;--a2ui-choicepicker-chip-border-hover: #ff004d;--a2ui-checkbox-border: 1px solid #212121;--a2ui-checkbox-border-radius: 4px;--a2ui-checkbox-size: 18px;--a2ui-textfield-border: 1px solid #e9e9e9;--a2ui-textfield-border-radius: 8px;--a2ui-textfield-padding: 10px 14px;--a2ui-textfield-color-border-focus: #ff004d;accent-color:#ff004d}.conversation-history ::ng-deep .a2ui-chip:not(.active){color:#212121}.conversation-history{display:flex;flex-direction:column;gap:16px;padding:16px;flex-grow:1;min-height:0;overflow-y:auto}.conversation-history markdown{display:block}.possible-questions{padding:0 20px 10px;display:flex;flex-wrap:wrap;gap:8px}.possible-questions .question-chip{cursor:pointer;transition:all .2s ease;background-color:#e9e9e9;padding:8px;border-radius:5px}.possible-questions .question-chip:hover{transform:translateY(-1px);box-shadow:0 2px 4px #0000001a}.input{margin:0 12px 12px;position:relative}.input .textarea{font-family:inherit;background:#212121;border:1px solid #212121;border-radius:4px;color:#fff;z-index:10000;padding:12px 64px 12px 12px;width:100%;box-sizing:border-box;min-height:43px;resize:none}.input .textarea:focus{border-color:#ff004d;outline:none}.input .send-button{position:absolute;right:10px;bottom:9px}.chat-history{background-color:#f3f3f3;border-left:1px solid #e9e9e9;width:300px;height:100vh;overflow:auto;position:fixed;right:500px;top:0}.chat-history .header{justify-content:center}.chat-history .history-items{display:flex;flex-direction:column;gap:8px;padding:8px;overflow:auto}.chat-history .history-items .history-empty{padding:16px 8px;color:#909090;text-align:center;font-size:13px}.chat-history .history-items .chat-history-item{cursor:pointer;background-color:#fff;border-radius:4px;padding:8px}.chat-history .history-items .chat-history-item:hover{filter:brightness(.97)}.chat-history .history-items .chat-history-item .preview{font-size:13px;line-height:1.4;margin-bottom:6px;display:-webkit-box;-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.chat-history .history-items .chat-history-item .footer{color:#909090;font-size:11px;display:flex;flex-direction:row;justify-content:space-between}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: ChatMessageComponent, selector: "lib-chat-message", inputs: ["parts", "side", "showTyping"] }, { kind: "component", type: IconComponent, selector: "ao-icon", inputs: ["svg", "size"] }, { kind: "component", type: ButtonComponent, selector: "button[ao-button], a[ao-button]", inputs: ["variant", "icon", "iconTrailing"] }, { kind: "pipe", type: DatePipe, name: "date" }] });
|
|
7231
7289
|
}
|
|
7232
7290
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: ChatComponent, decorators: [{
|
|
7233
7291
|
type: Component,
|
|
7234
|
-
args: [{ selector: 'lib-chat', imports: [ReactiveFormsModule, ChatMessageComponent, IconComponent, ButtonComponent, DatePipe], template: "<div class=\"sidebar\">\n @if (showHistory()) {\n <div class=\"chat-history\">\n <div class=\"header\">\n <h3>Verlauf</h3>\n </div>\n <div class=\"history-items\">\n @if (threads() === undefined) {\n <div class=\"history-empty\">L\u00E4dt\u2026</div>\n } @else if (threads()!.length === 0) {\n <div class=\"history-empty\">Noch keine Gespr\u00E4che.</div>\n }\n @for (item of threads(); track item.threadId) {\n <div class=\"chat-history-item\" (click)=\"openThread(item.threadId)\">\n <div class=\"preview\">{{ item.lastMessage }}</div>\n <div class=\"footer\">\n <div>{{ item.messageCount }} Nachrichten</div>\n <div>{{ item.updatedAt | date: 'dd.MM.yyyy HH:mm' }}</div>\n </div>\n </div>\n }\n </div>\n </div>\n }\n <div class=\"chat\">\n <div class=\"header\">\n <button ao-button variant=\"outline\" (click)=\"toggleHistory()\">\n <ao-icon [svg]=\"historyIcon\"></ao-icon>\n </button>\n <h2>Hilfecenter</h2>\n <div class=\"flex\">\n <button ao-button variant=\"outline\" (click)=\"newChat()\">\n <ao-icon [svg]=\"addIcon\"></ao-icon>\n </button>\n <button ao-button variant=\"outline\" (click)=\"showHistory.set(false); closed.emit()\">\n <ao-icon [svg]=\"closeIcon\"></ao-icon>\n </button>\n </div>\n </div>\n <div class=\"conversation-history\" #conversation>\n @for (turn of turns(); track $index) {\n <lib-chat-message\n [parts]=\"turn.parts\"\n [side]=\"turn.role === 'assistant' ? 'left' : 'right'\"\n >\n </lib-chat-message>\n }\n @if (activeRequest()) {\n <lib-chat-message [showTyping]=\"true\" side=\"left\"></lib-chat-message>\n }\n </div>\n\n <div class=\"input\">\n <textarea\n #textField\n rows=\"1\"\n class=\"textarea\"\n [formControl]=\"inputControl\"\n (keydown.enter)=\"send(); $event.stopPropagation(); $event.preventDefault()\"\n (input)=\"setSize()\"\n ></textarea>\n <button ao-button variant=\"primary\" (click)=\"send()\" class=\"send-button\">\n <ao-icon [svg]=\"sendIcon\"></ao-icon>\n </button>\n </div>\n </div>\n</div>\n", styles: ["@charset \"UTF-8\";.sidebar{display:flex;flex-direction:row;height:100%;position:relative}.header{background-color:#fff;padding:
|
|
7292
|
+
args: [{ selector: 'lib-chat', imports: [ReactiveFormsModule, ChatMessageComponent, IconComponent, ButtonComponent, DatePipe], template: "<div class=\"sidebar\">\n @if (showHistory()) {\n <div class=\"chat-history\">\n <div class=\"header\">\n <h3>Verlauf</h3>\n </div>\n <div class=\"history-items\">\n @if (threads() === undefined) {\n <div class=\"history-empty\">L\u00E4dt\u2026</div>\n } @else if (threads()!.length === 0) {\n <div class=\"history-empty\">Noch keine Gespr\u00E4che.</div>\n }\n @for (item of threads(); track item.threadId) {\n <div class=\"chat-history-item\" (click)=\"openThread(item.threadId)\">\n <div class=\"preview\">{{ item.lastMessage }}</div>\n <div class=\"footer\">\n <div>{{ item.messageCount }} Nachrichten</div>\n <div>{{ item.updatedAt | date: 'dd.MM.yyyy HH:mm' }}</div>\n </div>\n </div>\n }\n </div>\n </div>\n }\n <div class=\"chat\">\n <div class=\"header\">\n <button ao-button variant=\"outline\" (click)=\"toggleHistory()\">\n <ao-icon [svg]=\"historyIcon\"></ao-icon>\n </button>\n <h2>Hilfecenter</h2>\n <div class=\"flex\">\n <button ao-button variant=\"outline\" (click)=\"newChat()\">\n <ao-icon [svg]=\"addIcon\"></ao-icon>\n </button>\n <button ao-button variant=\"outline\" (click)=\"showHistory.set(false); closed.emit()\">\n <ao-icon [svg]=\"closeIcon\"></ao-icon>\n </button>\n </div>\n </div>\n <div class=\"conversation-history\" #conversation>\n @for (turn of turns(); track $index) {\n <lib-chat-message\n [parts]=\"turn.parts\"\n [side]=\"turn.role === 'assistant' ? 'left' : 'right'\"\n >\n </lib-chat-message>\n }\n @if (activeRequest()) {\n <lib-chat-message [showTyping]=\"true\" side=\"left\"></lib-chat-message>\n }\n </div>\n\n <div class=\"input\">\n <textarea\n #textField\n rows=\"1\"\n class=\"textarea\"\n [formControl]=\"inputControl\"\n (keydown.enter)=\"send(); $event.stopPropagation(); $event.preventDefault()\"\n (input)=\"setSize()\"\n ></textarea>\n <button ao-button variant=\"primary\" (click)=\"send()\" class=\"send-button\">\n <ao-icon [svg]=\"sendIcon\"></ao-icon>\n </button>\n </div>\n </div>\n</div>\n", styles: ["@charset \"UTF-8\";.sidebar{display:flex;flex-direction:row;height:100%;position:relative}.header{background-color:#fff;padding:6px 8px;display:flex;height:50px;flex-direction:row;align-items:center}.header h2,.header h3{margin:0}.header h2{font-size:18px;font-weight:600}.header h3{font-size:16px}.chat{display:flex;flex-direction:column;height:100%;width:500px;background-color:#f3f3f3;border-left:1px solid #e9e9e9}.chat .header{justify-content:space-between}.chat .header .flex{display:flex;align-items:center;gap:10px}.conversation-history{--a2ui-color-primary: #212121;--a2ui-color-on-primary: #ffffff;--a2ui-color-surface: #ffffff;--a2ui-color-on-background: #212121;--a2ui-color-border: #e9e9e9;--a2ui-text-color-text: #212121;--a2ui-text-caption-color: #909090;--a2ui-text-a-color: #ff004d;--a2ui-spacing-xs: 5px;--a2ui-spacing-s: 10px;--a2ui-spacing-m: 15px;--a2ui-spacing-l: 20px;--a2ui-row-gap: 12px;--a2ui-column-gap: 10px;--a2ui-font-family-title: inherit;--a2ui-font-size-2xl: 22px;--a2ui-font-size-xl: 19px;--a2ui-font-size-l: 16px;--a2ui-font-size-m: 14px;--a2ui-font-size-s: 13px;--a2ui-font-size-xs: 12px;--a2ui-card-background: #ffffff;--a2ui-card-border-radius: 8px;--a2ui-card-padding: 14px;--a2ui-card-border: none;--a2ui-button-background: #ffffff;--a2ui-button-border: 1px solid #212121;--a2ui-button-border-radius: 999px;--a2ui-button-padding: 8px 14px;--a2ui-button-font-weight: 500;--a2ui-choicepicker-gap: 10px;--a2ui-choicepicker-padding: 0;--a2ui-choicepicker-checkbox-size: 18px;--a2ui-choicepicker-chip-background: #ffffff;--a2ui-choicepicker-chip-background-selected: #212121;--a2ui-choicepicker-chip-border: 1px solid #212121;--a2ui-choicepicker-chip-border-radius: 999px;--a2ui-choicepicker-chip-padding: 7px 14px;--a2ui-choicepicker-chip-color: #212121;--a2ui-choicepicker-chip-border-hover: #ff004d;--a2ui-checkbox-border: 1px solid #212121;--a2ui-checkbox-border-radius: 4px;--a2ui-checkbox-size: 18px;--a2ui-textfield-border: 1px solid #e9e9e9;--a2ui-textfield-border-radius: 8px;--a2ui-textfield-padding: 10px 14px;--a2ui-textfield-color-border-focus: #ff004d;accent-color:#ff004d}.conversation-history ::ng-deep .a2ui-chip:not(.active){color:#212121}.conversation-history{display:flex;flex-direction:column;gap:16px;padding:16px;flex-grow:1;min-height:0;overflow-y:auto}.conversation-history markdown{display:block}.possible-questions{padding:0 20px 10px;display:flex;flex-wrap:wrap;gap:8px}.possible-questions .question-chip{cursor:pointer;transition:all .2s ease;background-color:#e9e9e9;padding:8px;border-radius:5px}.possible-questions .question-chip:hover{transform:translateY(-1px);box-shadow:0 2px 4px #0000001a}.input{margin:0 12px 12px;position:relative}.input .textarea{font-family:inherit;background:#212121;border:1px solid #212121;border-radius:4px;color:#fff;z-index:10000;padding:12px 64px 12px 12px;width:100%;box-sizing:border-box;min-height:43px;resize:none}.input .textarea:focus{border-color:#ff004d;outline:none}.input .send-button{position:absolute;right:10px;bottom:9px}.chat-history{background-color:#f3f3f3;border-left:1px solid #e9e9e9;width:300px;height:100vh;overflow:auto;position:fixed;right:500px;top:0}.chat-history .header{justify-content:center}.chat-history .history-items{display:flex;flex-direction:column;gap:8px;padding:8px;overflow:auto}.chat-history .history-items .history-empty{padding:16px 8px;color:#909090;text-align:center;font-size:13px}.chat-history .history-items .chat-history-item{cursor:pointer;background-color:#fff;border-radius:4px;padding:8px}.chat-history .history-items .chat-history-item:hover{filter:brightness(.97)}.chat-history .history-items .chat-history-item .preview{font-size:13px;line-height:1.4;margin-bottom:6px;display:-webkit-box;-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.chat-history .history-items .chat-history-item .footer{color:#909090;font-size:11px;display:flex;flex-direction:row;justify-content:space-between}\n"] }]
|
|
7235
7293
|
}], propDecorators: { historyElement: [{
|
|
7236
7294
|
type: ViewChild,
|
|
7237
7295
|
args: ['conversation']
|
|
@@ -7295,6 +7353,9 @@ class WorkspaceNavbarComponent {
|
|
|
7295
7353
|
const url = this.currentUrl() ?? '';
|
|
7296
7354
|
return this.findBestRouteMatch(url, this.activeSubTopNavItems())?.id ?? '';
|
|
7297
7355
|
}, ...(ngDevMode ? [{ debugName: "activeSubTopNavItemId" }] : /* istanbul ignore next */ []));
|
|
7356
|
+
activeWorkspaceAppId = computed(() => {
|
|
7357
|
+
return this.workspaceNavbarService.activeAppIdSignal() ?? this.appId();
|
|
7358
|
+
}, ...(ngDevMode ? [{ debugName: "activeWorkspaceAppId" }] : /* istanbul ignore next */ []));
|
|
7298
7359
|
signOutIcon = phosphorSignOut;
|
|
7299
7360
|
plusIcon = phosphorPlus;
|
|
7300
7361
|
chatIcon = phosphorRobot;
|
|
@@ -7319,9 +7380,7 @@ class WorkspaceNavbarComponent {
|
|
|
7319
7380
|
icon: this.resolveIcon(app),
|
|
7320
7381
|
tooltip: app.name,
|
|
7321
7382
|
});
|
|
7322
|
-
const productItems = response.products
|
|
7323
|
-
.map(mapApp)
|
|
7324
|
-
.sort((a, b) => {
|
|
7383
|
+
const productItems = response.products.map(mapApp).sort((a, b) => {
|
|
7325
7384
|
const indexA = this.productOrder.indexOf(a.id.toLowerCase());
|
|
7326
7385
|
const indexB = this.productOrder.indexOf(b.id.toLowerCase());
|
|
7327
7386
|
const posA = indexA === -1 ? this.productOrder.length : indexA;
|
|
@@ -7403,7 +7462,7 @@ class WorkspaceNavbarComponent {
|
|
|
7403
7462
|
this.workspaceNavbarService.signOut().subscribe();
|
|
7404
7463
|
return;
|
|
7405
7464
|
}
|
|
7406
|
-
if (item.id === this.
|
|
7465
|
+
if (item.id === this.activeWorkspaceAppId()) {
|
|
7407
7466
|
return;
|
|
7408
7467
|
}
|
|
7409
7468
|
const apps = this.workspaceNavbarService.workspaceAppsSignal() ?? [];
|
|
@@ -7456,7 +7515,7 @@ class WorkspaceNavbarComponent {
|
|
|
7456
7515
|
});
|
|
7457
7516
|
}
|
|
7458
7517
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: WorkspaceNavbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
7459
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.13", type: WorkspaceNavbarComponent, isStandalone: true, selector: "ao-workspace-navbar", inputs: { appId: { classPropertyName: "appId", publicName: "appId", isSignal: true, isRequired: true, transformFunction: null }, production: { classPropertyName: "production", publicName: "production", isSignal: true, isRequired: false, transformFunction: null }, topNavItems: { classPropertyName: "topNavItems", publicName: "topNavItems", isSignal: true, isRequired: false, transformFunction: null }, showSearch: { classPropertyName: "showSearch", publicName: "showSearch", isSignal: true, isRequired: false, transformFunction: null }, showNotifications: { classPropertyName: "showNotifications", publicName: "showNotifications", isSignal: true, isRequired: false, transformFunction: null }, notificationCount: { classPropertyName: "notificationCount", publicName: "notificationCount", isSignal: true, isRequired: false, transformFunction: null }, searchPlaceholder: { classPropertyName: "searchPlaceholder", publicName: "searchPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, recommendedFilters: { classPropertyName: "recommendedFilters", publicName: "recommendedFilters", isSignal: true, isRequired: false, transformFunction: null }, activeFilter: { classPropertyName: "activeFilter", publicName: "activeFilter", isSignal: true, isRequired: false, transformFunction: null }, resultGroups: { classPropertyName: "resultGroups", publicName: "resultGroups", isSignal: true, isRequired: false, transformFunction: null }, pageSuggestion: { classPropertyName: "pageSuggestion", publicName: "pageSuggestion", isSignal: true, isRequired: false, transformFunction: null }, aiSuggestions: { classPropertyName: "aiSuggestions", publicName: "aiSuggestions", isSignal: true, isRequired: false, transformFunction: null }, searchLoading: { classPropertyName: "searchLoading", publicName: "searchLoading", isSignal: true, isRequired: false, transformFunction: null }, searchError: { classPropertyName: "searchError", publicName: "searchError", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activeFilter: "activeFilterChange", topNavItemClick: "topNavItemClick", topNavItemChange: "topNavItemChange", subTopNavItemClick: "subTopNavItemClick", subTopNavItemChange: "subTopNavItemChange", appSwitched: "appSwitched", searchSubmit: "searchSubmit", searchQueryChange: "searchQueryChange", searchViewAll: "searchViewAll", searchResultSelect: "searchResultSelect", searchAiSuggestionSelect: "searchAiSuggestionSelect", searchPageSuggestionSelect: "searchPageSuggestionSelect", searchFilterSelect: "searchFilterSelect", searchFilterClear: "searchFilterClear", notificationClick: "notificationClick" }, host: { classAttribute: "ao-workspace-navbar" }, ngImport: i0, template: "<ao-side-nav\n [items]=\"workspaceAppNavItems()\"\n [bottomItems]=\"bottomNavItems()\"\n [activeItemId]=\"
|
|
7518
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.13", type: WorkspaceNavbarComponent, isStandalone: true, selector: "ao-workspace-navbar", inputs: { appId: { classPropertyName: "appId", publicName: "appId", isSignal: true, isRequired: true, transformFunction: null }, production: { classPropertyName: "production", publicName: "production", isSignal: true, isRequired: false, transformFunction: null }, topNavItems: { classPropertyName: "topNavItems", publicName: "topNavItems", isSignal: true, isRequired: false, transformFunction: null }, showSearch: { classPropertyName: "showSearch", publicName: "showSearch", isSignal: true, isRequired: false, transformFunction: null }, showNotifications: { classPropertyName: "showNotifications", publicName: "showNotifications", isSignal: true, isRequired: false, transformFunction: null }, notificationCount: { classPropertyName: "notificationCount", publicName: "notificationCount", isSignal: true, isRequired: false, transformFunction: null }, searchPlaceholder: { classPropertyName: "searchPlaceholder", publicName: "searchPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, recommendedFilters: { classPropertyName: "recommendedFilters", publicName: "recommendedFilters", isSignal: true, isRequired: false, transformFunction: null }, activeFilter: { classPropertyName: "activeFilter", publicName: "activeFilter", isSignal: true, isRequired: false, transformFunction: null }, resultGroups: { classPropertyName: "resultGroups", publicName: "resultGroups", isSignal: true, isRequired: false, transformFunction: null }, pageSuggestion: { classPropertyName: "pageSuggestion", publicName: "pageSuggestion", isSignal: true, isRequired: false, transformFunction: null }, aiSuggestions: { classPropertyName: "aiSuggestions", publicName: "aiSuggestions", isSignal: true, isRequired: false, transformFunction: null }, searchLoading: { classPropertyName: "searchLoading", publicName: "searchLoading", isSignal: true, isRequired: false, transformFunction: null }, searchError: { classPropertyName: "searchError", publicName: "searchError", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activeFilter: "activeFilterChange", topNavItemClick: "topNavItemClick", topNavItemChange: "topNavItemChange", subTopNavItemClick: "subTopNavItemClick", subTopNavItemChange: "subTopNavItemChange", appSwitched: "appSwitched", searchSubmit: "searchSubmit", searchQueryChange: "searchQueryChange", searchViewAll: "searchViewAll", searchResultSelect: "searchResultSelect", searchAiSuggestionSelect: "searchAiSuggestionSelect", searchPageSuggestionSelect: "searchPageSuggestionSelect", searchFilterSelect: "searchFilterSelect", searchFilterClear: "searchFilterClear", notificationClick: "notificationClick" }, host: { classAttribute: "ao-workspace-navbar" }, ngImport: i0, template: "<ao-side-nav\n [items]=\"workspaceAppNavItems()\"\n [bottomItems]=\"bottomNavItems()\"\n [activeItemId]=\"activeWorkspaceAppId()\"\n [expanded]=\"false\"\n (itemClick)=\"onSideNavItemClick($event)\"\n>\n <ao-logo-menu\n aoSideNavLogo\n [items]=\"companyMenuItems()\"\n [selectedItem]=\"selectedCompanyId()\"\n (selectionChange)=\"onCompanyChange($event)\"\n >\n @if (companyLogo()) {\n <img [src]=\"companyLogo()\" alt=\"Logo\" class=\"workspace-navbar__logo\" />\n } @else {\n <svg\n class=\"workspace-navbar__logo\"\n width=\"96\"\n height=\"120\"\n viewBox=\"0 0 96 120\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-label=\"Logo\"\n role=\"img\"\n >\n <path\n d=\"M36.6592 37.5955L31.1625 31.4924C28.1349 28.1284 28.4073 22.9247 31.7689 19.8971C33.2769 18.5401 35.2266 17.7918 37.2633 17.7918C39.5929 17.7918 41.8195 18.7781 43.3664 20.4967C45.458 22.824 46.0484 26.0826 44.911 28.998C44.4465 30.1903 43.7234 31.2338 42.7623 32.0988L36.6592 37.5955ZM95.5987 76.4613L83.6854 63.2299L70.4585 75.1363L48.5725 50.8269L54.6802 45.3279C57.6779 42.6253 60.035 39.2156 61.4949 35.4696C65.0969 26.2497 63.2204 15.9497 56.6001 8.58568C46.9981 -2.06444 30.5149 -2.92488 19.8556 6.66801C9.20088 16.2655 8.3359 32.7464 17.9311 43.4057L23.4255 49.5065L14.1118 57.8957C13.5099 58.438 12.9287 58.9621 12.3817 59.4792L12.3703 59.4655L11.2742 60.4518C4.49141 66.5572 0.493621 74.9372 0.0153502 84.045C-0.00525137 84.4317 -0.000673098 84.8185 0.00390115 85.2029L0.0084674 85.7086L0.00160688 87.1494L17.7823 87.1503L17.7938 85.7224L17.7915 85.4134C17.7892 85.2716 17.7869 85.1297 17.7938 84.9809C18.0203 80.6216 19.938 76.61 23.1852 73.6855L35.341 62.7379L57.2271 87.0473L45.0712 97.995C42.1055 100.668 38.261 102.151 34.2449 102.174L32.817 102.183V120L34.2586 119.998C42.6547 119.977 50.7258 116.86 56.9868 111.226L69.1404 100.281L81.0446 113.503L94.276 101.592L82.3718 88.3677L95.5987 76.4613Z\"\n fill=\"#FF004D\"\n />\n </svg>\n }\n </ao-logo-menu>\n</ao-side-nav>\n\n<div class=\"workspace-navbar__main\" [class.workspace-navbar__main--with-subnav]=\"hasSubTopNav()\">\n <div\n class=\"workspace-navbar__nav-wrapper\"\n [class.workspace-navbar__nav-wrapper--hidden]=\"navHidden()\"\n >\n <ao-top-nav\n [items]=\"topNavItems()\"\n [activeItemId]=\"activeTopNavItemId()\"\n [showSearch]=\"showSearch()\"\n [showNotifications]=\"showNotifications()\"\n [notificationCount]=\"notificationCount()\"\n [searchPlaceholder]=\"searchPlaceholder()\"\n [recommendedFilters]=\"recommendedFilters()\"\n [(activeFilter)]=\"activeFilter\"\n [resultGroups]=\"resultGroups()\"\n [pageSuggestion]=\"pageSuggestion()\"\n [aiSuggestions]=\"aiSuggestions()\"\n [searchLoading]=\"searchLoading()\"\n [searchError]=\"searchError()\"\n (itemClick)=\"onTopNavClick($event)\"\n (itemChange)=\"onTopNavChange($event)\"\n (searchSubmit)=\"searchSubmit.emit($event)\"\n (searchQueryChange)=\"searchQueryChange.emit($event)\"\n (searchViewAll)=\"searchViewAll.emit($event)\"\n (searchResultSelect)=\"searchResultSelect.emit($event)\"\n (searchAiSuggestionSelect)=\"searchAiSuggestionSelect.emit($event)\"\n (searchPageSuggestionSelect)=\"searchPageSuggestionSelect.emit($event)\"\n (searchFilterSelect)=\"searchFilterSelect.emit($event)\"\n (searchFilterClear)=\"searchFilterClear.emit()\"\n (notificationClick)=\"onNotificationClick()\"\n [showTools]=\"showTools()\"\n />\n\n @if (hasSubTopNav()) {\n <ao-sub-top-nav\n [items]=\"activeSubTopNavItems()\"\n [activeItemId]=\"activeSubTopNavItemId()\"\n (itemClick)=\"onSubTopNavClick($event)\"\n (itemChange)=\"onSubTopNavChange($event)\"\n />\n }\n </div>\n\n <main class=\"workspace-navbar__content\">\n <ng-content />\n </main>\n</div>\n\n<button ao-button class=\"handbook-chat\" variant=\"primary\" (click)=\"chatOpen.set(!chatOpen())\">\n <ao-icon [svg]=\"chatIcon\" />\n</button>\n\n<div class=\"chat-container\" [class.open]=\"chatOpen()\">\n <lib-chat [searchType]=\"activeFilter()?.type\" (closed)=\"chatOpen.set(false)\" />\n</div>\n", styles: [":host{display:block;min-height:100vh}.workspace-navbar__main{margin-left:70px;padding-top:50px;min-height:100vh}.workspace-navbar__main.workspace-navbar__main--with-subnav{padding-top:100px}.workspace-navbar__nav-wrapper{position:fixed;top:0;left:0;right:0;z-index:3;transform:translateY(0);transition:transform .25s ease}.workspace-navbar__nav-wrapper--hidden{transform:translateY(-100%)}.workspace-navbar__content{padding:30px 0}.workspace-navbar__logo{max-width:32px;max-height:32px;object-fit:contain}.handbook-chat{position:fixed;right:1.5em;bottom:1.5em;z-index:100}.chat-container{position:fixed;width:500px;height:100vh;right:0;top:0;margin-right:-500px;transition:margin-right .5s ease-in-out;background-color:#fff}.chat-container.open{margin-right:0;z-index:501}\n"], dependencies: [{ kind: "component", type: SideNavComponent, selector: "ao-side-nav", inputs: ["items", "bottomItems", "activeItemId", "expanded"], outputs: ["activeItemIdChange", "itemClick", "itemChange", "bottomItemClick"] }, { kind: "component", type: TopNavComponent, selector: "ao-top-nav", inputs: ["items", "activeItemId", "showSearch", "showNotifications", "notificationCount", "searchPlaceholder", "showTools", "recommendedFilters", "activeFilter", "resultGroups", "pageSuggestion", "aiSuggestions", "searchLoading", "searchError"], outputs: ["activeItemIdChange", "activeFilterChange", "itemClick", "itemChange", "searchSubmit", "searchQueryChange", "searchResultSelect", "searchAiSuggestionSelect", "searchPageSuggestionSelect", "searchFilterSelect", "searchFilterClear", "searchViewAll", "notificationClick"] }, { kind: "component", type: SubTopNavComponent, selector: "ao-sub-top-nav", inputs: ["items", "activeItemId"], outputs: ["activeItemIdChange", "itemClick", "itemChange"] }, { kind: "component", type: LogoMenuComponent, selector: "ao-logo-menu", inputs: ["items", "selectedItem", "searchPlaceholder"], outputs: ["selectedItemChange", "selectionChange"] }, { kind: "component", type: IconComponent, selector: "ao-icon", inputs: ["svg", "size"] }, { kind: "component", type: ButtonComponent, selector: "button[ao-button], a[ao-button]", inputs: ["variant", "icon", "iconTrailing"] }, { kind: "component", type: ChatComponent, selector: "lib-chat", inputs: ["searchType"], outputs: ["closed"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
7460
7519
|
}
|
|
7461
7520
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: WorkspaceNavbarComponent, decorators: [{
|
|
7462
7521
|
type: Component,
|
|
@@ -7470,9 +7529,149 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImpo
|
|
|
7470
7529
|
ChatComponent,
|
|
7471
7530
|
], changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
7472
7531
|
class: 'ao-workspace-navbar',
|
|
7473
|
-
}, template: "<ao-side-nav\n [items]=\"workspaceAppNavItems()\"\n [bottomItems]=\"bottomNavItems()\"\n [activeItemId]=\"
|
|
7532
|
+
}, template: "<ao-side-nav\n [items]=\"workspaceAppNavItems()\"\n [bottomItems]=\"bottomNavItems()\"\n [activeItemId]=\"activeWorkspaceAppId()\"\n [expanded]=\"false\"\n (itemClick)=\"onSideNavItemClick($event)\"\n>\n <ao-logo-menu\n aoSideNavLogo\n [items]=\"companyMenuItems()\"\n [selectedItem]=\"selectedCompanyId()\"\n (selectionChange)=\"onCompanyChange($event)\"\n >\n @if (companyLogo()) {\n <img [src]=\"companyLogo()\" alt=\"Logo\" class=\"workspace-navbar__logo\" />\n } @else {\n <svg\n class=\"workspace-navbar__logo\"\n width=\"96\"\n height=\"120\"\n viewBox=\"0 0 96 120\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-label=\"Logo\"\n role=\"img\"\n >\n <path\n d=\"M36.6592 37.5955L31.1625 31.4924C28.1349 28.1284 28.4073 22.9247 31.7689 19.8971C33.2769 18.5401 35.2266 17.7918 37.2633 17.7918C39.5929 17.7918 41.8195 18.7781 43.3664 20.4967C45.458 22.824 46.0484 26.0826 44.911 28.998C44.4465 30.1903 43.7234 31.2338 42.7623 32.0988L36.6592 37.5955ZM95.5987 76.4613L83.6854 63.2299L70.4585 75.1363L48.5725 50.8269L54.6802 45.3279C57.6779 42.6253 60.035 39.2156 61.4949 35.4696C65.0969 26.2497 63.2204 15.9497 56.6001 8.58568C46.9981 -2.06444 30.5149 -2.92488 19.8556 6.66801C9.20088 16.2655 8.3359 32.7464 17.9311 43.4057L23.4255 49.5065L14.1118 57.8957C13.5099 58.438 12.9287 58.9621 12.3817 59.4792L12.3703 59.4655L11.2742 60.4518C4.49141 66.5572 0.493621 74.9372 0.0153502 84.045C-0.00525137 84.4317 -0.000673098 84.8185 0.00390115 85.2029L0.0084674 85.7086L0.00160688 87.1494L17.7823 87.1503L17.7938 85.7224L17.7915 85.4134C17.7892 85.2716 17.7869 85.1297 17.7938 84.9809C18.0203 80.6216 19.938 76.61 23.1852 73.6855L35.341 62.7379L57.2271 87.0473L45.0712 97.995C42.1055 100.668 38.261 102.151 34.2449 102.174L32.817 102.183V120L34.2586 119.998C42.6547 119.977 50.7258 116.86 56.9868 111.226L69.1404 100.281L81.0446 113.503L94.276 101.592L82.3718 88.3677L95.5987 76.4613Z\"\n fill=\"#FF004D\"\n />\n </svg>\n }\n </ao-logo-menu>\n</ao-side-nav>\n\n<div class=\"workspace-navbar__main\" [class.workspace-navbar__main--with-subnav]=\"hasSubTopNav()\">\n <div\n class=\"workspace-navbar__nav-wrapper\"\n [class.workspace-navbar__nav-wrapper--hidden]=\"navHidden()\"\n >\n <ao-top-nav\n [items]=\"topNavItems()\"\n [activeItemId]=\"activeTopNavItemId()\"\n [showSearch]=\"showSearch()\"\n [showNotifications]=\"showNotifications()\"\n [notificationCount]=\"notificationCount()\"\n [searchPlaceholder]=\"searchPlaceholder()\"\n [recommendedFilters]=\"recommendedFilters()\"\n [(activeFilter)]=\"activeFilter\"\n [resultGroups]=\"resultGroups()\"\n [pageSuggestion]=\"pageSuggestion()\"\n [aiSuggestions]=\"aiSuggestions()\"\n [searchLoading]=\"searchLoading()\"\n [searchError]=\"searchError()\"\n (itemClick)=\"onTopNavClick($event)\"\n (itemChange)=\"onTopNavChange($event)\"\n (searchSubmit)=\"searchSubmit.emit($event)\"\n (searchQueryChange)=\"searchQueryChange.emit($event)\"\n (searchViewAll)=\"searchViewAll.emit($event)\"\n (searchResultSelect)=\"searchResultSelect.emit($event)\"\n (searchAiSuggestionSelect)=\"searchAiSuggestionSelect.emit($event)\"\n (searchPageSuggestionSelect)=\"searchPageSuggestionSelect.emit($event)\"\n (searchFilterSelect)=\"searchFilterSelect.emit($event)\"\n (searchFilterClear)=\"searchFilterClear.emit()\"\n (notificationClick)=\"onNotificationClick()\"\n [showTools]=\"showTools()\"\n />\n\n @if (hasSubTopNav()) {\n <ao-sub-top-nav\n [items]=\"activeSubTopNavItems()\"\n [activeItemId]=\"activeSubTopNavItemId()\"\n (itemClick)=\"onSubTopNavClick($event)\"\n (itemChange)=\"onSubTopNavChange($event)\"\n />\n }\n </div>\n\n <main class=\"workspace-navbar__content\">\n <ng-content />\n </main>\n</div>\n\n<button ao-button class=\"handbook-chat\" variant=\"primary\" (click)=\"chatOpen.set(!chatOpen())\">\n <ao-icon [svg]=\"chatIcon\" />\n</button>\n\n<div class=\"chat-container\" [class.open]=\"chatOpen()\">\n <lib-chat [searchType]=\"activeFilter()?.type\" (closed)=\"chatOpen.set(false)\" />\n</div>\n", styles: [":host{display:block;min-height:100vh}.workspace-navbar__main{margin-left:70px;padding-top:50px;min-height:100vh}.workspace-navbar__main.workspace-navbar__main--with-subnav{padding-top:100px}.workspace-navbar__nav-wrapper{position:fixed;top:0;left:0;right:0;z-index:3;transform:translateY(0);transition:transform .25s ease}.workspace-navbar__nav-wrapper--hidden{transform:translateY(-100%)}.workspace-navbar__content{padding:30px 0}.workspace-navbar__logo{max-width:32px;max-height:32px;object-fit:contain}.handbook-chat{position:fixed;right:1.5em;bottom:1.5em;z-index:100}.chat-container{position:fixed;width:500px;height:100vh;right:0;top:0;margin-right:-500px;transition:margin-right .5s ease-in-out;background-color:#fff}.chat-container.open{margin-right:0;z-index:501}\n"] }]
|
|
7474
7533
|
}], ctorParameters: () => [], propDecorators: { appId: [{ type: i0.Input, args: [{ isSignal: true, alias: "appId", required: true }] }], production: [{ type: i0.Input, args: [{ isSignal: true, alias: "production", required: false }] }], topNavItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "topNavItems", required: false }] }], showSearch: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSearch", required: false }] }], showNotifications: [{ type: i0.Input, args: [{ isSignal: true, alias: "showNotifications", required: false }] }], notificationCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "notificationCount", required: false }] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], recommendedFilters: [{ type: i0.Input, args: [{ isSignal: true, alias: "recommendedFilters", required: false }] }], activeFilter: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeFilter", required: false }] }, { type: i0.Output, args: ["activeFilterChange"] }], resultGroups: [{ type: i0.Input, args: [{ isSignal: true, alias: "resultGroups", required: false }] }], pageSuggestion: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSuggestion", required: false }] }], aiSuggestions: [{ type: i0.Input, args: [{ isSignal: true, alias: "aiSuggestions", required: false }] }], searchLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchLoading", required: false }] }], searchError: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchError", required: false }] }], topNavItemClick: [{ type: i0.Output, args: ["topNavItemClick"] }], topNavItemChange: [{ type: i0.Output, args: ["topNavItemChange"] }], subTopNavItemClick: [{ type: i0.Output, args: ["subTopNavItemClick"] }], subTopNavItemChange: [{ type: i0.Output, args: ["subTopNavItemChange"] }], appSwitched: [{ type: i0.Output, args: ["appSwitched"] }], searchSubmit: [{ type: i0.Output, args: ["searchSubmit"] }], searchQueryChange: [{ type: i0.Output, args: ["searchQueryChange"] }], searchViewAll: [{ type: i0.Output, args: ["searchViewAll"] }], searchResultSelect: [{ type: i0.Output, args: ["searchResultSelect"] }], searchAiSuggestionSelect: [{ type: i0.Output, args: ["searchAiSuggestionSelect"] }], searchPageSuggestionSelect: [{ type: i0.Output, args: ["searchPageSuggestionSelect"] }], searchFilterSelect: [{ type: i0.Output, args: ["searchFilterSelect"] }], searchFilterClear: [{ type: i0.Output, args: ["searchFilterClear"] }], notificationClick: [{ type: i0.Output, args: ["notificationClick"] }] } });
|
|
7475
7534
|
|
|
7535
|
+
/**
|
|
7536
|
+
* Robin-flavoured ChoicePicker that keeps the basic A2UI look but turns chip
|
|
7537
|
+
* selections into server actions so quick-reply chips behave like chat buttons.
|
|
7538
|
+
*/
|
|
7539
|
+
class AoChoicePickerComponent extends CatalogComponent {
|
|
7540
|
+
displayStyle = computed(() => this.readString('displayStyle') ?? 'checkbox', ...(ngDevMode ? [{ debugName: "displayStyle" }] : /* istanbul ignore next */ []));
|
|
7541
|
+
options = computed(() => this.readOptions(), ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
|
|
7542
|
+
selectedValue = computed(() => this.readSelectedValues(), ...(ngDevMode ? [{ debugName: "selectedValue" }] : /* istanbul ignore next */ []));
|
|
7543
|
+
renderer = inject(A2uiRendererService);
|
|
7544
|
+
isMultiple() {
|
|
7545
|
+
return this.readString('variant') === 'multipleSelection';
|
|
7546
|
+
}
|
|
7547
|
+
isSelected(value) {
|
|
7548
|
+
return this.selectedValue().includes(value);
|
|
7549
|
+
}
|
|
7550
|
+
selectOption(option) {
|
|
7551
|
+
const nextValue = this.getNextValue(option.value);
|
|
7552
|
+
this.props()['value']?.onUpdate([...nextValue]);
|
|
7553
|
+
if (this.displayStyle() === 'chips')
|
|
7554
|
+
this.dispatchSelection(option, nextValue);
|
|
7555
|
+
}
|
|
7556
|
+
getNextValue(value) {
|
|
7557
|
+
if (!this.isMultiple())
|
|
7558
|
+
return [value];
|
|
7559
|
+
if (this.isSelected(value))
|
|
7560
|
+
return this.selectedValue().filter(item => item !== value);
|
|
7561
|
+
return [...this.selectedValue(), value];
|
|
7562
|
+
}
|
|
7563
|
+
dispatchSelection(option, selectedValues) {
|
|
7564
|
+
const surface = this.renderer.surfaceGroup.getSurface(this.surfaceId());
|
|
7565
|
+
if (!surface)
|
|
7566
|
+
return;
|
|
7567
|
+
void surface.dispatchAction({
|
|
7568
|
+
event: {
|
|
7569
|
+
name: 'choiceSelected',
|
|
7570
|
+
context: {
|
|
7571
|
+
componentId: this.componentId(),
|
|
7572
|
+
label: option.label,
|
|
7573
|
+
selectedValue: option.value,
|
|
7574
|
+
selectedValues: [...selectedValues],
|
|
7575
|
+
},
|
|
7576
|
+
},
|
|
7577
|
+
}, this.componentId());
|
|
7578
|
+
}
|
|
7579
|
+
readString(key) {
|
|
7580
|
+
const value = this.props()[key]?.value();
|
|
7581
|
+
return typeof value === 'string' ? value : undefined;
|
|
7582
|
+
}
|
|
7583
|
+
readSelectedValues() {
|
|
7584
|
+
const value = this.props()['value']?.value();
|
|
7585
|
+
if (!Array.isArray(value))
|
|
7586
|
+
return [];
|
|
7587
|
+
return value.filter((item) => typeof item === 'string');
|
|
7588
|
+
}
|
|
7589
|
+
readOptions() {
|
|
7590
|
+
const value = this.props()['options']?.value();
|
|
7591
|
+
if (!Array.isArray(value))
|
|
7592
|
+
return [];
|
|
7593
|
+
return value.filter(this.isChoicePickerOption);
|
|
7594
|
+
}
|
|
7595
|
+
isChoicePickerOption(value) {
|
|
7596
|
+
if (!value || typeof value !== 'object')
|
|
7597
|
+
return false;
|
|
7598
|
+
const option = value;
|
|
7599
|
+
return typeof option['label'] === 'string' && typeof option['value'] === 'string';
|
|
7600
|
+
}
|
|
7601
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: AoChoicePickerComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
7602
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.13", type: AoChoicePickerComponent, isStandalone: true, selector: "lib-ao-choice-picker", usesInheritance: true, ngImport: i0, template: `
|
|
7603
|
+
<div class="a2ui-choice-picker">
|
|
7604
|
+
@if (displayStyle() === 'chips') {
|
|
7605
|
+
<div class="a2ui-chips-group">
|
|
7606
|
+
@for (option of options(); track option.value) {
|
|
7607
|
+
<button
|
|
7608
|
+
type="button"
|
|
7609
|
+
class="a2ui-chip"
|
|
7610
|
+
[class.active]="isSelected(option.value)"
|
|
7611
|
+
(click)="selectOption(option)"
|
|
7612
|
+
>
|
|
7613
|
+
{{ option.label }}
|
|
7614
|
+
</button>
|
|
7615
|
+
}
|
|
7616
|
+
</div>
|
|
7617
|
+
} @else {
|
|
7618
|
+
<div class="a2ui-options-group">
|
|
7619
|
+
@for (option of options(); track option.value) {
|
|
7620
|
+
<label class="a2ui-option-label">
|
|
7621
|
+
<input
|
|
7622
|
+
[type]="isMultiple() ? 'checkbox' : 'radio'"
|
|
7623
|
+
[name]="componentId()"
|
|
7624
|
+
[value]="option.value"
|
|
7625
|
+
[checked]="isSelected(option.value)"
|
|
7626
|
+
(change)="selectOption(option)"
|
|
7627
|
+
class="a2ui-option-input"
|
|
7628
|
+
/>
|
|
7629
|
+
<span class="a2ui-option-text">{{ option.label }}</span>
|
|
7630
|
+
</label>
|
|
7631
|
+
}
|
|
7632
|
+
</div>
|
|
7633
|
+
}
|
|
7634
|
+
</div>
|
|
7635
|
+
`, isInline: true, styles: [".a2ui-choice-picker{padding:var(--a2ui-choicepicker-padding, 0);width:100%}.a2ui-options-group,.a2ui-chips-group{display:flex;flex-wrap:wrap;gap:var(--a2ui-choicepicker-gap, var(--a2ui-spacing-xs, .25rem))}.a2ui-options-group{flex-direction:column}.a2ui-option-label{align-items:center;color:var(--a2ui-text-color-text, var(--a2ui-color-on-background, #333));cursor:pointer;display:flex;gap:var(--a2ui-choicepicker-gap, var(--a2ui-spacing-xs, .25rem))}.a2ui-option-input{height:var(--a2ui-choicepicker-checkbox-size, 1rem);width:var(--a2ui-choicepicker-checkbox-size, 1rem)}.a2ui-chip{background:var(--a2ui-choicepicker-chip-background, var(--a2ui-color-surface, #fff));border:var(--a2ui-choicepicker-chip-border, 1px solid var(--a2ui-color-border, #ccc));border-radius:var(--a2ui-choicepicker-chip-border-radius, 100px);color:var(--a2ui-choicepicker-chip-color, var(--a2ui-color-on-background, #333));cursor:pointer;font:inherit;padding:var( --a2ui-choicepicker-chip-padding, var(--a2ui-spacing-s, .5rem) var(--a2ui-spacing-m, 1rem) );transition:background-color .16s ease,border-color .16s ease,color .16s ease,transform .16s ease}.a2ui-chip:hover{border-color:var(--a2ui-choicepicker-chip-border-hover, var(--a2ui-color-primary, #17e));transform:translateY(-1px)}.a2ui-chip.active{background:var( --a2ui-choicepicker-chip-background-selected, var(--a2ui-color-primary, #17e) );border-color:var( --a2ui-choicepicker-chip-background-selected, var(--a2ui-color-primary, #17e) );color:var(--a2ui-color-on-primary, #fff)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
7636
|
+
}
|
|
7637
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: AoChoicePickerComponent, decorators: [{
|
|
7638
|
+
type: Component,
|
|
7639
|
+
args: [{ selector: 'lib-ao-choice-picker', template: `
|
|
7640
|
+
<div class="a2ui-choice-picker">
|
|
7641
|
+
@if (displayStyle() === 'chips') {
|
|
7642
|
+
<div class="a2ui-chips-group">
|
|
7643
|
+
@for (option of options(); track option.value) {
|
|
7644
|
+
<button
|
|
7645
|
+
type="button"
|
|
7646
|
+
class="a2ui-chip"
|
|
7647
|
+
[class.active]="isSelected(option.value)"
|
|
7648
|
+
(click)="selectOption(option)"
|
|
7649
|
+
>
|
|
7650
|
+
{{ option.label }}
|
|
7651
|
+
</button>
|
|
7652
|
+
}
|
|
7653
|
+
</div>
|
|
7654
|
+
} @else {
|
|
7655
|
+
<div class="a2ui-options-group">
|
|
7656
|
+
@for (option of options(); track option.value) {
|
|
7657
|
+
<label class="a2ui-option-label">
|
|
7658
|
+
<input
|
|
7659
|
+
[type]="isMultiple() ? 'checkbox' : 'radio'"
|
|
7660
|
+
[name]="componentId()"
|
|
7661
|
+
[value]="option.value"
|
|
7662
|
+
[checked]="isSelected(option.value)"
|
|
7663
|
+
(change)="selectOption(option)"
|
|
7664
|
+
class="a2ui-option-input"
|
|
7665
|
+
/>
|
|
7666
|
+
<span class="a2ui-option-text">{{ option.label }}</span>
|
|
7667
|
+
</label>
|
|
7668
|
+
}
|
|
7669
|
+
</div>
|
|
7670
|
+
}
|
|
7671
|
+
</div>
|
|
7672
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".a2ui-choice-picker{padding:var(--a2ui-choicepicker-padding, 0);width:100%}.a2ui-options-group,.a2ui-chips-group{display:flex;flex-wrap:wrap;gap:var(--a2ui-choicepicker-gap, var(--a2ui-spacing-xs, .25rem))}.a2ui-options-group{flex-direction:column}.a2ui-option-label{align-items:center;color:var(--a2ui-text-color-text, var(--a2ui-color-on-background, #333));cursor:pointer;display:flex;gap:var(--a2ui-choicepicker-gap, var(--a2ui-spacing-xs, .25rem))}.a2ui-option-input{height:var(--a2ui-choicepicker-checkbox-size, 1rem);width:var(--a2ui-choicepicker-checkbox-size, 1rem)}.a2ui-chip{background:var(--a2ui-choicepicker-chip-background, var(--a2ui-color-surface, #fff));border:var(--a2ui-choicepicker-chip-border, 1px solid var(--a2ui-color-border, #ccc));border-radius:var(--a2ui-choicepicker-chip-border-radius, 100px);color:var(--a2ui-choicepicker-chip-color, var(--a2ui-color-on-background, #333));cursor:pointer;font:inherit;padding:var( --a2ui-choicepicker-chip-padding, var(--a2ui-spacing-s, .5rem) var(--a2ui-spacing-m, 1rem) );transition:background-color .16s ease,border-color .16s ease,color .16s ease,transform .16s ease}.a2ui-chip:hover{border-color:var(--a2ui-choicepicker-chip-border-hover, var(--a2ui-color-primary, #17e));transform:translateY(-1px)}.a2ui-chip.active{background:var( --a2ui-choicepicker-chip-background-selected, var(--a2ui-color-primary, #17e) );border-color:var( --a2ui-choicepicker-chip-background-selected, var(--a2ui-color-primary, #17e) );color:var(--a2ui-color-on-primary, #fff)}\n"] }]
|
|
7673
|
+
}] });
|
|
7674
|
+
|
|
7476
7675
|
const AO_CATALOG_ID = 'ah-oh.com:robin-v1';
|
|
7477
7676
|
/**
|
|
7478
7677
|
* Robin's design-system catalog. Phase 1 delegates entirely to the upstream
|
|
@@ -7487,7 +7686,12 @@ const AO_CATALOG_ID = 'ah-oh.com:robin-v1';
|
|
|
7487
7686
|
*/
|
|
7488
7687
|
class AoCatalog extends BasicCatalogBase {
|
|
7489
7688
|
constructor() {
|
|
7490
|
-
super({
|
|
7689
|
+
super({
|
|
7690
|
+
id: AO_CATALOG_ID,
|
|
7691
|
+
components: {
|
|
7692
|
+
choicePicker: { ...ChoicePickerApi, component: AoChoicePickerComponent },
|
|
7693
|
+
},
|
|
7694
|
+
});
|
|
7491
7695
|
}
|
|
7492
7696
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: AoCatalog, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
7493
7697
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: AoCatalog, providedIn: 'root' });
|
|
@@ -7506,7 +7710,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImpo
|
|
|
7506
7710
|
function provideRobinA2ui() {
|
|
7507
7711
|
return makeEnvironmentProviders([
|
|
7508
7712
|
AoCatalog,
|
|
7509
|
-
provideMarkdownRenderer(),
|
|
7713
|
+
provideMarkdownRenderer((markdown) => renderMarkdown(markdown).catch(renderFallbackMarkdown)),
|
|
7510
7714
|
{
|
|
7511
7715
|
provide: A2UI_RENDERER_CONFIG,
|
|
7512
7716
|
useFactory: () => {
|
|
@@ -7523,6 +7727,24 @@ function provideRobinA2ui() {
|
|
|
7523
7727
|
A2uiRendererService,
|
|
7524
7728
|
]);
|
|
7525
7729
|
}
|
|
7730
|
+
function renderFallbackMarkdown(markdown) {
|
|
7731
|
+
return escapeHtml(markdown)
|
|
7732
|
+
.replace(/^#### (.*)$/gim, '<h4>$1</h4>')
|
|
7733
|
+
.replace(/^### (.*)$/gim, '<h3>$1</h3>')
|
|
7734
|
+
.replace(/^## (.*)$/gim, '<h2>$1</h2>')
|
|
7735
|
+
.replace(/^# (.*)$/gim, '<h1>$1</h1>')
|
|
7736
|
+
.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
|
|
7737
|
+
.replace(/\*(.*?)\*/g, '<em>$1</em>')
|
|
7738
|
+
.replace(/\n/g, '<br>');
|
|
7739
|
+
}
|
|
7740
|
+
function escapeHtml(value) {
|
|
7741
|
+
return value
|
|
7742
|
+
.replace(/&/g, '&')
|
|
7743
|
+
.replace(/</g, '<')
|
|
7744
|
+
.replace(/>/g, '>')
|
|
7745
|
+
.replace(/"/g, '"')
|
|
7746
|
+
.replace(/'/g, ''');
|
|
7747
|
+
}
|
|
7526
7748
|
|
|
7527
7749
|
/*
|
|
7528
7750
|
* Public API Surface of design-system
|