@c8y/ngx-components 1023.48.0 → 1023.48.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/alarms/index.d.ts.map +1 -1
- package/fesm2022/c8y-ngx-components-ai-ai-chat.mjs +3 -3
- package/fesm2022/c8y-ngx-components-ai-ai-chat.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-alarms.mjs +5 -4
- package/fesm2022/c8y-ngx-components-alarms.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-definitions-html-widget-ai-config.mjs +1 -1
- package/fesm2022/c8y-ngx-components-widgets-definitions-html-widget-ai-config.mjs.map +1 -1
- package/locales/de.po +80 -0
- package/locales/es.po +79 -0
- package/locales/fr.po +79 -0
- package/locales/ja_JP.po +73 -0
- package/locales/ko.po +77 -0
- package/locales/nl.po +80 -0
- package/locales/pl.po +78 -0
- package/locales/pt_BR.po +78 -0
- package/locales/zh_CN.po +78 -0
- package/locales/zh_TW.po +78 -0
- package/package.json +1 -1
package/alarms/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sources":["../../alarms/alarms.model.ts","../../alarms/alarm-details-custom-button/alarm-details-button.service.ts","../../alarms/alarm-details-custom-button/alarm-details-button.pipe.ts","../../alarms/alarm-details.service.ts","../../alarms/alarms-activity-tracker.service.ts","../../alarms/alarms-view.service.ts","../../alarms/ng1-smart-rules-upgrade.service.ts","../../alarms/alarm-details.component.ts","../../alarms/alarm-empty.component.ts","../../alarms/alarm-info.component.ts","../../alarms/alarm-list-custom-indicator/alarm-list-indicator.service.ts","../../alarms/alarm-list-custom-indicator/alarm-list-indicator.pipe.ts","../../alarms/alarm-severities-to-title.pipe.ts","../../alarms/alarm-severity-to-icon.pipe.ts","../../alarms/alarm-severity-to-icon-class.pipe.ts","../../alarms/alarm-severity-to-label.pipe.ts","../../alarms/alarm-status-to-icon.pipe.ts","../../alarms/alarm-status-to-label.pipe.ts","../../alarms/alarms-filter.component.ts","../../alarms/alarms-icon.component.ts","../../alarms/alarms-interval-refresh.component.ts","../../alarms/alarms-list.component.ts","../../alarms/alarms.component.ts","../../alarms/alarms.helper.ts","../../alarms/audit-changes-message.pipe.ts","../../alarms/alarms-date-filter.component.ts","../../alarms/alarms-type-filter.component.ts","../../alarms/alarms.module.ts","../../alarms/alarms.guard.ts","../../alarms/alarms-navigation.factory.ts"],"sourcesContent":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAuBE;;;AAGG;;AAGH;;;;AAIG;AACH;AAEA;;;;AAIG;AACH;AAEA;;;;AAIG;AACH;AACD;AAED;AAEM;;;AAEN;;;;;AAMM;AAEN;;AAEG;AACH;AAMA;;;;;;AAOA;AAEM;AACN;;AAEG;AACH;AAOM;;;;;AAMN;;AAEG;AACH;AAKA;AAQM;;AAEJ;;;AAKF;AAEA;AAOA;AAMA;AAEM;AACJ;;AAGF;;AAEG;AACH;AAiBA;AAEA;;AAEG;AACG;AACJ;;AAEG;;AAEH;;;;AAIG;;AAEH;;;AAGG;;AAEH;;;;;;;AAOG;;;;;;;;;;AAWH;;;;AAIG;AACH;;AAED;;;AAIA;AAEK;;;;AAIL;AAEK;AAEN;;;;;;;;;;;;;;;;;;;;;;;;AA0BA;AAEE;AACE;;;AAGC;AAED;AACE;;;;;AAKG;AACH;AAID;AAED;AACE;;;;AAIG;;AAEJ;AACF;AACF;;AC9QD;AAMI;AACA;AADQ;AAIV;AAsBA;;;AAMD;;ACxCD;AAWc;AAAQ;AAEpB;;;AAGD;;AClBD;AAMc;AAFZ;AAEoB;AAEpB;;;;;;;;;;;;;;;;;;;;;;;;AAwBG;;AAoBH;;;;;;;;;;;;;;;;;AAiBG;;AAcH;;;;;;;;;;;;;;;;;;;;AAoBG;;AAyBH;;;AAgBD;;AChJD;AAEE;AACA;;AAGA;AACA;;;AAIA;AAKA;AAOA;AAIA;;;;AAiBD;;ACpBD;;;;;;;;AAQG;AACH;AAiBI;AACA;AACA;AACA;AACA;AAjBF;;;;;AAMA;AACA;AACA;;AAKU;AAYV;;AAEG;AACH;AAIA;;;;;;;;;AASG;AACH;;AAgCA;;;AAGG;AACH;AAIA;;;;;;;;;AASG;AACG;AAgBN;;;;;AAKG;AACH;AAKA;;;;;;AAMG;AACH;AAMA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BG;AACG;;;AA2BN;;;;;AAKG;;AAsBH;;;;;AAKG;AACH;AAIA;;;AAGG;;AASH;;;;AAIG;;AAOH;;;;;AAKG;AACH;AAYA;;;;;;;;AAQG;AACH;AAWA;;;;;;;AAOG;AACH;;;AAOD;;ACvVD;;;;;;;AAOG;AACH;;AAEE;AACA;AACD;AAED;AAIA;;;;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sources":["../../alarms/alarms.model.ts","../../alarms/alarm-details-custom-button/alarm-details-button.service.ts","../../alarms/alarm-details-custom-button/alarm-details-button.pipe.ts","../../alarms/alarm-details.service.ts","../../alarms/alarms-activity-tracker.service.ts","../../alarms/alarms-view.service.ts","../../alarms/ng1-smart-rules-upgrade.service.ts","../../alarms/alarm-details.component.ts","../../alarms/alarm-empty.component.ts","../../alarms/alarm-info.component.ts","../../alarms/alarm-list-custom-indicator/alarm-list-indicator.service.ts","../../alarms/alarm-list-custom-indicator/alarm-list-indicator.pipe.ts","../../alarms/alarm-severities-to-title.pipe.ts","../../alarms/alarm-severity-to-icon.pipe.ts","../../alarms/alarm-severity-to-icon-class.pipe.ts","../../alarms/alarm-severity-to-label.pipe.ts","../../alarms/alarm-status-to-icon.pipe.ts","../../alarms/alarm-status-to-label.pipe.ts","../../alarms/alarms-filter.component.ts","../../alarms/alarms-icon.component.ts","../../alarms/alarms-interval-refresh.component.ts","../../alarms/alarms-list.component.ts","../../alarms/alarms.component.ts","../../alarms/alarms.helper.ts","../../alarms/audit-changes-message.pipe.ts","../../alarms/alarms-date-filter.component.ts","../../alarms/alarms-type-filter.component.ts","../../alarms/alarms.module.ts","../../alarms/alarms.guard.ts","../../alarms/alarms-navigation.factory.ts"],"sourcesContent":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],"names":[],"mappings":"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"}
|
|
@@ -219,7 +219,7 @@ class AiChatComponent {
|
|
|
219
219
|
content: this.prompt,
|
|
220
220
|
timestamp: new Date().toISOString()
|
|
221
221
|
});
|
|
222
|
-
|
|
222
|
+
this.prompt = '';
|
|
223
223
|
}
|
|
224
224
|
/**
|
|
225
225
|
* Handles cancellation of ongoing operations during loading state.
|
|
@@ -229,11 +229,11 @@ class AiChatComponent {
|
|
|
229
229
|
this.onCancel.emit();
|
|
230
230
|
}
|
|
231
231
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AiChatComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
232
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: AiChatComponent, isStandalone: true, selector: "c8y-ai-chat", inputs: { isLoading: "isLoading", disabled: "disabled", prompt: "prompt", config: "config" }, outputs: { onMessage: "onMessage", onCancel: "onCancel" }, host: { classAttribute: "d-contents" }, queries: [{ propertyName: "messages", predicate: AiChatMessageComponent }], ngImport: i0, template: "<div\n class=\"d-col fit-h fit-w flex-grow\"\n [attr.aria-label]=\"config.headline | translate\"\n role=\"region\"\n>\n @if (messages.length > 0) {\n <div\n class=\"inner-scroll flex-grow d-col-reverse min-height-0 bg-level-0\"\n [attr.aria-label]=\"'Chat conversation' | translate\"\n aria-live=\"polite\"\n aria-atomic=\"false\"\n role=\"log\"\n >\n <div class=\"d-col p-l-16 p-r-16\">\n <ng-content select=\"c8y-ai-chat-message\"></ng-content>\n <ng-content></ng-content>\n </div>\n </div>\n }\n <div [ngClass]=\"{ 'd-col fit-h': messages.length === 0 }\">\n @if (messages.length === 0) {\n <div\n class=\"p-24\"\n aria-live=\"polite\"\n role=\"status\"\n >\n <h4 class=\"m-b-16 text-medium\">{{ config.headline | translate }}</h4>\n <p class=\"p-b-8 text-balance\">{{ config.title | translate }}</p>\n <p class=\"text-muted text-balance\">{{ config.welcomeText | translate }}</p>\n </div>\n }\n <div class=\"chat-input bg-level-1\">\n <div class=\"d-flex inner-scroll a-i-center gap-8 p-l-16 p-r-16 p-b-8\">\n <ng-content select=\"c8y-ai-chat-suggestion\"></ng-content>\n </div>\n <div class=\"chat-input-group\">\n <label\n class=\"sr-only\"\n for=\"chat-input-{{ componentId }}\"\n >\n {{ config.placeholder | translate }}\n </label>\n <textarea\n class=\"form-control no-resize\"\n style=\"max-height: 200px !important\"\n [attr.aria-label]=\"config.placeholder | translate\"\n id=\"chat-input-{{ componentId }}\"\n [attr.aria-describedby]=\"config.disclaimerText ? 'chat-disclaimer-' + componentId : null\"\n [attr.aria-busy]=\"isLoading\"\n [placeholder]=\"\n (messages.length === 0 ? config.placeholder : config.placeholderAfterFirstMessage)\n | translate\n \"\n [(ngModel)]=\"prompt\"\n (keydown.enter)=\"sendMessage($event)\"\n [disabled]=\"
|
|
232
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: AiChatComponent, isStandalone: true, selector: "c8y-ai-chat", inputs: { isLoading: "isLoading", disabled: "disabled", prompt: "prompt", config: "config" }, outputs: { onMessage: "onMessage", onCancel: "onCancel" }, host: { classAttribute: "d-contents" }, queries: [{ propertyName: "messages", predicate: AiChatMessageComponent }], ngImport: i0, template: "<div\n class=\"d-col fit-h fit-w flex-grow\"\n [attr.aria-label]=\"config.headline | translate\"\n role=\"region\"\n>\n @if (messages.length > 0) {\n <div\n class=\"inner-scroll flex-grow d-col-reverse min-height-0 bg-level-0\"\n [attr.aria-label]=\"'Chat conversation' | translate\"\n aria-live=\"polite\"\n aria-atomic=\"false\"\n role=\"log\"\n >\n <div class=\"d-col p-l-16 p-r-16\">\n <ng-content select=\"c8y-ai-chat-message\"></ng-content>\n <ng-content></ng-content>\n </div>\n </div>\n }\n <div [ngClass]=\"{ 'd-col fit-h': messages.length === 0 }\">\n @if (messages.length === 0) {\n <div\n class=\"p-24\"\n aria-live=\"polite\"\n role=\"status\"\n >\n <h4 class=\"m-b-16 text-medium\">{{ config.headline | translate }}</h4>\n <p class=\"p-b-8 text-balance\">{{ config.title | translate }}</p>\n <p class=\"text-muted text-balance\">{{ config.welcomeText | translate }}</p>\n </div>\n }\n <div class=\"chat-input bg-level-1\">\n <div class=\"d-flex inner-scroll a-i-center gap-8 p-l-16 p-r-16 p-b-8\">\n <ng-content select=\"c8y-ai-chat-suggestion\"></ng-content>\n </div>\n <div class=\"chat-input-group\">\n <label\n class=\"sr-only\"\n for=\"chat-input-{{ componentId }}\"\n >\n {{ config.placeholder | translate }}\n </label>\n <textarea\n class=\"form-control no-resize\"\n style=\"max-height: 200px !important\"\n [attr.aria-label]=\"config.placeholder | translate\"\n id=\"chat-input-{{ componentId }}\"\n [attr.aria-describedby]=\"config.disclaimerText ? 'chat-disclaimer-' + componentId : null\"\n [attr.aria-busy]=\"isLoading\"\n [placeholder]=\"\n (messages.length === 0 ? config.placeholder : config.placeholderAfterFirstMessage)\n | translate\n \"\n [(ngModel)]=\"prompt\"\n (keydown.enter)=\"sendMessage($event)\"\n [disabled]=\"disabled\"\n c8y-textarea-autoresize\n ></textarea>\n <div class=\"chat-input-group-btn\">\n @if (!isLoading) {\n <button\n class=\"btn btn-dot\"\n [attr.title]=\"config.sendButtonText | translate\"\n [attr.aria-label]=\"config.sendButtonText | translate\"\n type=\"button\"\n (click)=\"sendMessage($event)\"\n [disabled]=\"disabled || prompt.trim().length === 0\"\n >\n <i [c8yIcon]=\"config.userInterfaceIcons?.send || 'arrow-circle-right'\"></i>\n </button>\n } @else {\n <button\n class=\"btn btn-dot btn-dot--danger\"\n [attr.title]=\"config.cancelButtonText | translate\"\n [attr.aria-label]=\"config.cancelButtonText | translate\"\n type=\"button\"\n (click)=\"cancel()\"\n >\n <i [c8yIcon]=\"config.userInterfaceIcons?.cancel || 'stop'\"></i>\n </button>\n }\n </div>\n </div>\n @if (config.disclaimerText) {\n <div\n class=\"text-muted m-b-8 text-10 p-l-16\"\n id=\"chat-disclaimer-{{ componentId }}\"\n role=\"note\"\n >\n {{ config.disclaimerText | translate }}\n </div>\n }\n </div>\n </div>\n</div>\n", dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.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$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: TextareaAutoresizeDirective, selector: "[c8y-textarea-autoresize]" }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }] }); }
|
|
233
233
|
}
|
|
234
234
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AiChatComponent, decorators: [{
|
|
235
235
|
type: Component,
|
|
236
|
-
args: [{ selector: 'c8y-ai-chat', imports: [C8yTranslatePipe, FormsModule, TextareaAutoresizeDirective, IconDirective, NgClass], standalone: true, host: { class: 'd-contents' }, template: "<div\n class=\"d-col fit-h fit-w flex-grow\"\n [attr.aria-label]=\"config.headline | translate\"\n role=\"region\"\n>\n @if (messages.length > 0) {\n <div\n class=\"inner-scroll flex-grow d-col-reverse min-height-0 bg-level-0\"\n [attr.aria-label]=\"'Chat conversation' | translate\"\n aria-live=\"polite\"\n aria-atomic=\"false\"\n role=\"log\"\n >\n <div class=\"d-col p-l-16 p-r-16\">\n <ng-content select=\"c8y-ai-chat-message\"></ng-content>\n <ng-content></ng-content>\n </div>\n </div>\n }\n <div [ngClass]=\"{ 'd-col fit-h': messages.length === 0 }\">\n @if (messages.length === 0) {\n <div\n class=\"p-24\"\n aria-live=\"polite\"\n role=\"status\"\n >\n <h4 class=\"m-b-16 text-medium\">{{ config.headline | translate }}</h4>\n <p class=\"p-b-8 text-balance\">{{ config.title | translate }}</p>\n <p class=\"text-muted text-balance\">{{ config.welcomeText | translate }}</p>\n </div>\n }\n <div class=\"chat-input bg-level-1\">\n <div class=\"d-flex inner-scroll a-i-center gap-8 p-l-16 p-r-16 p-b-8\">\n <ng-content select=\"c8y-ai-chat-suggestion\"></ng-content>\n </div>\n <div class=\"chat-input-group\">\n <label\n class=\"sr-only\"\n for=\"chat-input-{{ componentId }}\"\n >\n {{ config.placeholder | translate }}\n </label>\n <textarea\n class=\"form-control no-resize\"\n style=\"max-height: 200px !important\"\n [attr.aria-label]=\"config.placeholder | translate\"\n id=\"chat-input-{{ componentId }}\"\n [attr.aria-describedby]=\"config.disclaimerText ? 'chat-disclaimer-' + componentId : null\"\n [attr.aria-busy]=\"isLoading\"\n [placeholder]=\"\n (messages.length === 0 ? config.placeholder : config.placeholderAfterFirstMessage)\n | translate\n \"\n [(ngModel)]=\"prompt\"\n (keydown.enter)=\"sendMessage($event)\"\n [disabled]=\"
|
|
236
|
+
args: [{ selector: 'c8y-ai-chat', imports: [C8yTranslatePipe, FormsModule, TextareaAutoresizeDirective, IconDirective, NgClass], standalone: true, host: { class: 'd-contents' }, template: "<div\n class=\"d-col fit-h fit-w flex-grow\"\n [attr.aria-label]=\"config.headline | translate\"\n role=\"region\"\n>\n @if (messages.length > 0) {\n <div\n class=\"inner-scroll flex-grow d-col-reverse min-height-0 bg-level-0\"\n [attr.aria-label]=\"'Chat conversation' | translate\"\n aria-live=\"polite\"\n aria-atomic=\"false\"\n role=\"log\"\n >\n <div class=\"d-col p-l-16 p-r-16\">\n <ng-content select=\"c8y-ai-chat-message\"></ng-content>\n <ng-content></ng-content>\n </div>\n </div>\n }\n <div [ngClass]=\"{ 'd-col fit-h': messages.length === 0 }\">\n @if (messages.length === 0) {\n <div\n class=\"p-24\"\n aria-live=\"polite\"\n role=\"status\"\n >\n <h4 class=\"m-b-16 text-medium\">{{ config.headline | translate }}</h4>\n <p class=\"p-b-8 text-balance\">{{ config.title | translate }}</p>\n <p class=\"text-muted text-balance\">{{ config.welcomeText | translate }}</p>\n </div>\n }\n <div class=\"chat-input bg-level-1\">\n <div class=\"d-flex inner-scroll a-i-center gap-8 p-l-16 p-r-16 p-b-8\">\n <ng-content select=\"c8y-ai-chat-suggestion\"></ng-content>\n </div>\n <div class=\"chat-input-group\">\n <label\n class=\"sr-only\"\n for=\"chat-input-{{ componentId }}\"\n >\n {{ config.placeholder | translate }}\n </label>\n <textarea\n class=\"form-control no-resize\"\n style=\"max-height: 200px !important\"\n [attr.aria-label]=\"config.placeholder | translate\"\n id=\"chat-input-{{ componentId }}\"\n [attr.aria-describedby]=\"config.disclaimerText ? 'chat-disclaimer-' + componentId : null\"\n [attr.aria-busy]=\"isLoading\"\n [placeholder]=\"\n (messages.length === 0 ? config.placeholder : config.placeholderAfterFirstMessage)\n | translate\n \"\n [(ngModel)]=\"prompt\"\n (keydown.enter)=\"sendMessage($event)\"\n [disabled]=\"disabled\"\n c8y-textarea-autoresize\n ></textarea>\n <div class=\"chat-input-group-btn\">\n @if (!isLoading) {\n <button\n class=\"btn btn-dot\"\n [attr.title]=\"config.sendButtonText | translate\"\n [attr.aria-label]=\"config.sendButtonText | translate\"\n type=\"button\"\n (click)=\"sendMessage($event)\"\n [disabled]=\"disabled || prompt.trim().length === 0\"\n >\n <i [c8yIcon]=\"config.userInterfaceIcons?.send || 'arrow-circle-right'\"></i>\n </button>\n } @else {\n <button\n class=\"btn btn-dot btn-dot--danger\"\n [attr.title]=\"config.cancelButtonText | translate\"\n [attr.aria-label]=\"config.cancelButtonText | translate\"\n type=\"button\"\n (click)=\"cancel()\"\n >\n <i [c8yIcon]=\"config.userInterfaceIcons?.cancel || 'stop'\"></i>\n </button>\n }\n </div>\n </div>\n @if (config.disclaimerText) {\n <div\n class=\"text-muted m-b-8 text-10 p-l-16\"\n id=\"chat-disclaimer-{{ componentId }}\"\n role=\"note\"\n >\n {{ config.disclaimerText | translate }}\n </div>\n }\n </div>\n </div>\n</div>\n" }]
|
|
237
237
|
}], propDecorators: { isLoading: [{
|
|
238
238
|
type: Input
|
|
239
239
|
}], disabled: [{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"c8y-ngx-components-ai-ai-chat.mjs","sources":["../../ai/ai-chat/ai-chat-message-action.component.ts","../../ai/ai-chat/ai-chat-message-action.component.html","../../ai/ai-chat/ai-chat-message.component.ts","../../ai/ai-chat/ai-chat-message.component.html","../../ai/ai-chat/ai-chat-suggestion.component.ts","../../ai/ai-chat/ai-chat-suggestion.component.html","../../ai/ai-chat/ai-chat.component.ts","../../ai/ai-chat/ai-chat.component.html","../../ai/ai-chat/c8y-ngx-components-ai-ai-chat.ts"],"sourcesContent":["import { Component, EventEmitter, Input, Output } from '@angular/core';\nimport { C8yTranslatePipe, IconDirective } from '@c8y/ngx-components';\nimport { SupportedIconsSuggestions } from '@c8y/ngx-components/icon-selector/icons';\nimport { TooltipModule } from 'ngx-bootstrap/tooltip';\n\n/**\n * An action button that can be added to chat messages.\n * Typically used for actions like copying, regenerating, or providing feedback on messages.\n */\n@Component({\n selector: 'c8y-ai-chat-message-action',\n templateUrl: './ai-chat-message-action.component.html',\n standalone: true,\n imports: [TooltipModule, C8yTranslatePipe, IconDirective]\n})\nexport class AiChatMessageActionComponent {\n /**\n * Disables the action button when true.\n */\n @Input()\n disabled = false;\n\n /**\n * Tooltip text displayed when hovering over the action button.\n */\n @Input()\n tooltip = '';\n\n /**\n * Icon to display in the action button.\n */\n @Input()\n icon: SupportedIconsSuggestions = 'cog';\n\n /**\n * Emitted when the action button is clicked.\n */\n @Output()\n click = new EventEmitter<void>();\n}\n","<button\n class=\"btn btn-dot text-muted\"\n [attr.aria-label]=\"tooltip | translate\"\n [tooltip]=\"tooltip | translate\"\n [adaptivePosition]=\"true\"\n [delay]=\"500\"\n (click)=\"click.emit()\"\n [disabled]=\"disabled\"\n>\n <i\n class=\"text-12\"\n [c8yIcon]=\"icon\"\n ></i>\n</button>\n","import { Component, computed, input, inject } from '@angular/core';\nimport { gettext } from '@c8y/ngx-components/gettext';\nimport { AIMessage } from '@c8y/ngx-components/ai';\nimport { C8yTranslatePipe, DatePipe, MarkdownToHtmlPipe } from '@c8y/ngx-components';\nimport { AsyncPipe, NgClass } from '@angular/common';\nimport { TooltipModule } from 'ngx-bootstrap/tooltip';\nimport { TranslateService } from '@ngx-translate/core';\n\n@Component({\n selector: 'c8y-ai-chat-message',\n templateUrl: './ai-chat-message.component.html',\n standalone: true,\n imports: [MarkdownToHtmlPipe, AsyncPipe, NgClass, TooltipModule, C8yTranslatePipe, DatePipe]\n})\nexport class AiChatMessageComponent {\n readonly role = input<AIMessage['role']>();\n readonly message = input<AIMessage>();\n private readonly translateService = inject(TranslateService);\n\n private readonly roleResolved = computed(() => {\n return this.message()?.role || this.role();\n });\n\n /**\n * Generates an accessible label for the message container.\n * Includes the role (user or assistant) and timestamp if available.\n * @returns The aria-label string for screen readers\n */\n readonly ariaLabel = computed(() => {\n const tpl =\n this.roleResolved() === 'user'\n ? gettext('You said: \"{{ message }}\"')\n : gettext('Assistant said: \"{{ message }}\"');\n const msg = this.message();\n return this.translateService.instant(tpl, { message: msg?.content || gettext('No response.') });\n });\n\n /**\n * Generates an accessible label for the message content.\n * Prefixes the content with contextual information about who sent it.\n * @returns The aria-label string with prefixed role information\n */\n readonly messageContentAriaLabel = computed(() => {\n const msg = this.message();\n const time = msg?.timestamp ? new Date(msg.timestamp).toLocaleTimeString() : '';\n let tpl: string;\n if (time) {\n tpl =\n this.roleResolved() === 'user'\n ? gettext('User message at {{ time }}')\n : gettext('Assistant message at {{ time }}');\n } else {\n tpl = this.roleResolved() === 'user' ? gettext('User message') : gettext('Assistant message');\n }\n return this.translateService.instant(tpl, { time });\n });\n}\n","<div\n class=\"d-col p-b-16\"\n [attr.aria-label]=\"ariaLabel()\"\n role=\"article\"\n>\n <div\n class=\"chat-message text-break-word\"\n [ngClass]=\"{\n 'user-message': message()?.role === 'user' || role() === 'user',\n 'agent-message': message()?.role === 'assistant' || role() === 'assistant'\n }\"\n >\n <div\n class=\"message-content\"\n [attr.aria-label]=\"messageContentAriaLabel()\"\n [innerHTML]=\"message()?.content | markdownToHtml | async\"\n ></div>\n <ng-content select=\":not(c8y-ai-chat-message-action)\"></ng-content>\n @if (message()?.timestamp) {\n <div class=\"message-timestamp\">\n <span [tooltip]=\"message()?.timestamp | c8yDate\">\n {{ message()?.timestamp | c8yDate: 'adaptiveDate' }}\n </span>\n </div>\n }\n </div>\n <div\n class=\"message-action\"\n [attr.aria-label]=\"'Message actions' | translate\"\n role=\"toolbar\"\n [ngClass]=\"{\n 'user-action showOnHover': message()?.role === 'user' || role() === 'user',\n 'agent-action p-l-16': message()?.role === 'assistant' || role() === 'assistant'\n }\"\n >\n <ng-content select=\"c8y-ai-chat-message-action\"></ng-content>\n </div>\n</div>\n","import { Component, EventEmitter, Input, Output } from '@angular/core';\nimport { C8yTranslatePipe, IconDirective } from '@c8y/ngx-components';\nimport { AIMessage } from '@c8y/ngx-components/ai';\nimport { SupportedIconsSuggestions } from '@c8y/ngx-components/icon-selector/icons';\n\n/**\n * A suggestion chip that can be displayed in the chat interface.\n * When clicked, it automatically populates and sends a predefined prompt.\n */\n@Component({\n selector: 'c8y-ai-chat-suggestion',\n templateUrl: './ai-chat-suggestion.component.html',\n standalone: true,\n imports: [IconDirective, C8yTranslatePipe]\n})\nexport class AiChatSuggestionComponent {\n /**\n * The visible label text displayed on the suggestion chip.\n */\n @Input()\n label: string;\n\n /**\n * The prompt text that will be sent when the suggestion is clicked.\n */\n @Input()\n prompt: string;\n\n /**\n * Icon to display alongside the suggestion label.\n */\n @Input()\n icon: SupportedIconsSuggestions = 'c8y-bulb';\n\n /**\n * When true, uses AI-styled buttons instead of default styling.\n */\n @Input()\n useAiButtons = false;\n\n /**\n * Disables the suggestion chip when true.\n */\n @Input()\n disabled = false;\n\n /**\n * Emitted when the suggestion is clicked, providing the prompt as an AIMessage.\n */\n @Output()\n suggestionClicked = new EventEmitter<AIMessage>();\n\n /**\n * Handles suggestion click and emits the prompt as a user message.\n */\n suggest() {\n this.suggestionClicked.emit({\n content: this.prompt,\n role: 'user',\n timestamp: new Date().toISOString()\n });\n }\n}\n","@if (!useAiButtons) {\n <button\n class=\"btn btn-default btn-sm\"\n [title]=\"prompt | translate\"\n (click)=\"suggest()\"\n [disabled]=\"disabled\"\n >\n <i [c8yIcon]=\"icon\"></i>\n {{ label | translate }}\n </button>\n} @else {\n <button\n class=\"btn btn-sm btn-ai\"\n [title]=\"prompt | translate\"\n (click)=\"suggest()\"\n [disabled]=\"disabled\"\n >\n <span>{{ label | translate }}</span>\n </button>\n}\n","import { NgClass } from '@angular/common';\nimport { Component, ContentChildren, EventEmitter, Input, Output, QueryList } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { C8yTranslatePipe, IconDirective, TextareaAutoresizeDirective } from '@c8y/ngx-components';\nimport { gettext } from '@c8y/ngx-components/gettext';\nimport { AIMessage, ChatConfig } from '@c8y/ngx-components/ai';\nimport { AiChatMessageComponent } from './ai-chat-message.component';\n\n/**\n * An interactive chat interface component for AI-powered conversations.\n * Displays messages in a conversation format with support for loading states,\n * custom configuration, and markdown formatting.\n */\n@Component({\n selector: 'c8y-ai-chat',\n templateUrl: './ai-chat.component.html',\n imports: [C8yTranslatePipe, FormsModule, TextareaAutoresizeDirective, IconDirective, NgClass],\n standalone: true,\n host: { class: 'd-contents' }\n})\nexport class AiChatComponent {\n /**\n * Indicates whether the chat is currently processing a request.\n * When true, displays a cancel button instead of send button and disables the input.\n */\n @Input()\n isLoading = false;\n\n /**\n * Disables the chat input and send button when true.\n */\n @Input()\n disabled = false;\n\n /**\n * The current text in the chat input field. Supports two-way binding.\n */\n @Input()\n prompt = '';\n\n /**\n * Emitted when the user sends a message.\n * Provides an AIMessage object with role, content, and timestamp.\n */\n @Output()\n onMessage = new EventEmitter<AIMessage>();\n\n /**\n * Emitted when the user cancels an ongoing operation during loading state.\n */\n @Output()\n onCancel = new EventEmitter<void>();\n\n /**\n * Child message components displayed in the chat.\n */\n @ContentChildren(AiChatMessageComponent) messages: QueryList<AiChatMessageComponent>;\n\n readonly componentId = `chat-${crypto.randomUUID()}`;\n\n private _config: ChatConfig = {\n headline: gettext('Welcome!'),\n welcomeText: '',\n title: gettext('What can I help you with?'),\n placeholder: gettext('Type your message here…'),\n placeholderAfterFirstMessage: gettext('Type your next message here…'),\n sendButtonText: gettext('Send'),\n cancelButtonText: gettext('Cancel'),\n disclaimerText: gettext(\n 'AI-generated responses can contain errors. Verify the details before use.'\n ),\n userInterfaceIcons: {\n send: 'arrow-circle-up',\n cancel: 'stop-circle'\n }\n };\n\n /**\n * Configuration object for customizing labels, placeholders, and icons.\n * Accepts partial configuration to override defaults.\n */\n @Input()\n set config(value: Partial<ChatConfig>) {\n this._config = { ...this._config, ...value };\n }\n get config() {\n return this._config;\n }\n\n /**\n * Handles message submission when the user sends a message.\n * Emits the onMessage event and clears the input.\n * @param $event - The event object from the form submission\n */\n sendMessage($event: Event): void {\n $event.preventDefault();\n if (!this.prompt) return;\n this.onMessage.emit({\n role: 'user',\n content: this.prompt,\n timestamp: new Date().toISOString()\n });\n // this.prompt = '';\n }\n\n /**\n * Handles cancellation of ongoing operations during loading state.\n * Emits the onCancel event.\n */\n cancel(): void {\n this.onCancel.emit();\n }\n}\n","<div\n class=\"d-col fit-h fit-w flex-grow\"\n [attr.aria-label]=\"config.headline | translate\"\n role=\"region\"\n>\n @if (messages.length > 0) {\n <div\n class=\"inner-scroll flex-grow d-col-reverse min-height-0 bg-level-0\"\n [attr.aria-label]=\"'Chat conversation' | translate\"\n aria-live=\"polite\"\n aria-atomic=\"false\"\n role=\"log\"\n >\n <div class=\"d-col p-l-16 p-r-16\">\n <ng-content select=\"c8y-ai-chat-message\"></ng-content>\n <ng-content></ng-content>\n </div>\n </div>\n }\n <div [ngClass]=\"{ 'd-col fit-h': messages.length === 0 }\">\n @if (messages.length === 0) {\n <div\n class=\"p-24\"\n aria-live=\"polite\"\n role=\"status\"\n >\n <h4 class=\"m-b-16 text-medium\">{{ config.headline | translate }}</h4>\n <p class=\"p-b-8 text-balance\">{{ config.title | translate }}</p>\n <p class=\"text-muted text-balance\">{{ config.welcomeText | translate }}</p>\n </div>\n }\n <div class=\"chat-input bg-level-1\">\n <div class=\"d-flex inner-scroll a-i-center gap-8 p-l-16 p-r-16 p-b-8\">\n <ng-content select=\"c8y-ai-chat-suggestion\"></ng-content>\n </div>\n <div class=\"chat-input-group\">\n <label\n class=\"sr-only\"\n for=\"chat-input-{{ componentId }}\"\n >\n {{ config.placeholder | translate }}\n </label>\n <textarea\n class=\"form-control no-resize\"\n style=\"max-height: 200px !important\"\n [attr.aria-label]=\"config.placeholder | translate\"\n id=\"chat-input-{{ componentId }}\"\n [attr.aria-describedby]=\"config.disclaimerText ? 'chat-disclaimer-' + componentId : null\"\n [attr.aria-busy]=\"isLoading\"\n [placeholder]=\"\n (messages.length === 0 ? config.placeholder : config.placeholderAfterFirstMessage)\n | translate\n \"\n [(ngModel)]=\"prompt\"\n (keydown.enter)=\"sendMessage($event)\"\n [disabled]=\"isLoading || disabled\"\n c8y-textarea-autoresize\n ></textarea>\n <div class=\"chat-input-group-btn\">\n @if (!isLoading) {\n <button\n class=\"btn btn-dot\"\n [attr.title]=\"config.sendButtonText | translate\"\n [attr.aria-label]=\"config.sendButtonText | translate\"\n type=\"button\"\n (click)=\"sendMessage($event)\"\n [disabled]=\"disabled || prompt.trim().length === 0\"\n >\n <i [c8yIcon]=\"config.userInterfaceIcons?.send || 'arrow-circle-right'\"></i>\n </button>\n } @else {\n <button\n class=\"btn btn-dot btn-dot--danger\"\n [attr.title]=\"config.cancelButtonText | translate\"\n [attr.aria-label]=\"config.cancelButtonText | translate\"\n type=\"button\"\n (click)=\"cancel()\"\n >\n <i [c8yIcon]=\"config.userInterfaceIcons?.cancel || 'stop'\"></i>\n </button>\n }\n </div>\n </div>\n @if (config.disclaimerText) {\n <div\n class=\"text-muted m-b-8 text-10 p-l-16\"\n id=\"chat-disclaimer-{{ componentId }}\"\n role=\"note\"\n >\n {{ config.disclaimerText | translate }}\n </div>\n }\n </div>\n </div>\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["i1"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"c8y-ngx-components-ai-ai-chat.mjs","sources":["../../ai/ai-chat/ai-chat-message-action.component.ts","../../ai/ai-chat/ai-chat-message-action.component.html","../../ai/ai-chat/ai-chat-message.component.ts","../../ai/ai-chat/ai-chat-message.component.html","../../ai/ai-chat/ai-chat-suggestion.component.ts","../../ai/ai-chat/ai-chat-suggestion.component.html","../../ai/ai-chat/ai-chat.component.ts","../../ai/ai-chat/ai-chat.component.html","../../ai/ai-chat/c8y-ngx-components-ai-ai-chat.ts"],"sourcesContent":["import { Component, EventEmitter, Input, Output } from '@angular/core';\nimport { C8yTranslatePipe, IconDirective } from '@c8y/ngx-components';\nimport { SupportedIconsSuggestions } from '@c8y/ngx-components/icon-selector/icons';\nimport { TooltipModule } from 'ngx-bootstrap/tooltip';\n\n/**\n * An action button that can be added to chat messages.\n * Typically used for actions like copying, regenerating, or providing feedback on messages.\n */\n@Component({\n selector: 'c8y-ai-chat-message-action',\n templateUrl: './ai-chat-message-action.component.html',\n standalone: true,\n imports: [TooltipModule, C8yTranslatePipe, IconDirective]\n})\nexport class AiChatMessageActionComponent {\n /**\n * Disables the action button when true.\n */\n @Input()\n disabled = false;\n\n /**\n * Tooltip text displayed when hovering over the action button.\n */\n @Input()\n tooltip = '';\n\n /**\n * Icon to display in the action button.\n */\n @Input()\n icon: SupportedIconsSuggestions = 'cog';\n\n /**\n * Emitted when the action button is clicked.\n */\n @Output()\n click = new EventEmitter<void>();\n}\n","<button\n class=\"btn btn-dot text-muted\"\n [attr.aria-label]=\"tooltip | translate\"\n [tooltip]=\"tooltip | translate\"\n [adaptivePosition]=\"true\"\n [delay]=\"500\"\n (click)=\"click.emit()\"\n [disabled]=\"disabled\"\n>\n <i\n class=\"text-12\"\n [c8yIcon]=\"icon\"\n ></i>\n</button>\n","import { Component, computed, input, inject } from '@angular/core';\nimport { gettext } from '@c8y/ngx-components/gettext';\nimport { AIMessage } from '@c8y/ngx-components/ai';\nimport { C8yTranslatePipe, DatePipe, MarkdownToHtmlPipe } from '@c8y/ngx-components';\nimport { AsyncPipe, NgClass } from '@angular/common';\nimport { TooltipModule } from 'ngx-bootstrap/tooltip';\nimport { TranslateService } from '@ngx-translate/core';\n\n@Component({\n selector: 'c8y-ai-chat-message',\n templateUrl: './ai-chat-message.component.html',\n standalone: true,\n imports: [MarkdownToHtmlPipe, AsyncPipe, NgClass, TooltipModule, C8yTranslatePipe, DatePipe]\n})\nexport class AiChatMessageComponent {\n readonly role = input<AIMessage['role']>();\n readonly message = input<AIMessage>();\n private readonly translateService = inject(TranslateService);\n\n private readonly roleResolved = computed(() => {\n return this.message()?.role || this.role();\n });\n\n /**\n * Generates an accessible label for the message container.\n * Includes the role (user or assistant) and timestamp if available.\n * @returns The aria-label string for screen readers\n */\n readonly ariaLabel = computed(() => {\n const tpl =\n this.roleResolved() === 'user'\n ? gettext('You said: \"{{ message }}\"')\n : gettext('Assistant said: \"{{ message }}\"');\n const msg = this.message();\n return this.translateService.instant(tpl, { message: msg?.content || gettext('No response.') });\n });\n\n /**\n * Generates an accessible label for the message content.\n * Prefixes the content with contextual information about who sent it.\n * @returns The aria-label string with prefixed role information\n */\n readonly messageContentAriaLabel = computed(() => {\n const msg = this.message();\n const time = msg?.timestamp ? new Date(msg.timestamp).toLocaleTimeString() : '';\n let tpl: string;\n if (time) {\n tpl =\n this.roleResolved() === 'user'\n ? gettext('User message at {{ time }}')\n : gettext('Assistant message at {{ time }}');\n } else {\n tpl = this.roleResolved() === 'user' ? gettext('User message') : gettext('Assistant message');\n }\n return this.translateService.instant(tpl, { time });\n });\n}\n","<div\n class=\"d-col p-b-16\"\n [attr.aria-label]=\"ariaLabel()\"\n role=\"article\"\n>\n <div\n class=\"chat-message text-break-word\"\n [ngClass]=\"{\n 'user-message': message()?.role === 'user' || role() === 'user',\n 'agent-message': message()?.role === 'assistant' || role() === 'assistant'\n }\"\n >\n <div\n class=\"message-content\"\n [attr.aria-label]=\"messageContentAriaLabel()\"\n [innerHTML]=\"message()?.content | markdownToHtml | async\"\n ></div>\n <ng-content select=\":not(c8y-ai-chat-message-action)\"></ng-content>\n @if (message()?.timestamp) {\n <div class=\"message-timestamp\">\n <span [tooltip]=\"message()?.timestamp | c8yDate\">\n {{ message()?.timestamp | c8yDate: 'adaptiveDate' }}\n </span>\n </div>\n }\n </div>\n <div\n class=\"message-action\"\n [attr.aria-label]=\"'Message actions' | translate\"\n role=\"toolbar\"\n [ngClass]=\"{\n 'user-action showOnHover': message()?.role === 'user' || role() === 'user',\n 'agent-action p-l-16': message()?.role === 'assistant' || role() === 'assistant'\n }\"\n >\n <ng-content select=\"c8y-ai-chat-message-action\"></ng-content>\n </div>\n</div>\n","import { Component, EventEmitter, Input, Output } from '@angular/core';\nimport { C8yTranslatePipe, IconDirective } from '@c8y/ngx-components';\nimport { AIMessage } from '@c8y/ngx-components/ai';\nimport { SupportedIconsSuggestions } from '@c8y/ngx-components/icon-selector/icons';\n\n/**\n * A suggestion chip that can be displayed in the chat interface.\n * When clicked, it automatically populates and sends a predefined prompt.\n */\n@Component({\n selector: 'c8y-ai-chat-suggestion',\n templateUrl: './ai-chat-suggestion.component.html',\n standalone: true,\n imports: [IconDirective, C8yTranslatePipe]\n})\nexport class AiChatSuggestionComponent {\n /**\n * The visible label text displayed on the suggestion chip.\n */\n @Input()\n label: string;\n\n /**\n * The prompt text that will be sent when the suggestion is clicked.\n */\n @Input()\n prompt: string;\n\n /**\n * Icon to display alongside the suggestion label.\n */\n @Input()\n icon: SupportedIconsSuggestions = 'c8y-bulb';\n\n /**\n * When true, uses AI-styled buttons instead of default styling.\n */\n @Input()\n useAiButtons = false;\n\n /**\n * Disables the suggestion chip when true.\n */\n @Input()\n disabled = false;\n\n /**\n * Emitted when the suggestion is clicked, providing the prompt as an AIMessage.\n */\n @Output()\n suggestionClicked = new EventEmitter<AIMessage>();\n\n /**\n * Handles suggestion click and emits the prompt as a user message.\n */\n suggest() {\n this.suggestionClicked.emit({\n content: this.prompt,\n role: 'user',\n timestamp: new Date().toISOString()\n });\n }\n}\n","@if (!useAiButtons) {\n <button\n class=\"btn btn-default btn-sm\"\n [title]=\"prompt | translate\"\n (click)=\"suggest()\"\n [disabled]=\"disabled\"\n >\n <i [c8yIcon]=\"icon\"></i>\n {{ label | translate }}\n </button>\n} @else {\n <button\n class=\"btn btn-sm btn-ai\"\n [title]=\"prompt | translate\"\n (click)=\"suggest()\"\n [disabled]=\"disabled\"\n >\n <span>{{ label | translate }}</span>\n </button>\n}\n","import { NgClass } from '@angular/common';\nimport { Component, ContentChildren, EventEmitter, Input, Output, QueryList } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { C8yTranslatePipe, IconDirective, TextareaAutoresizeDirective } from '@c8y/ngx-components';\nimport { gettext } from '@c8y/ngx-components/gettext';\nimport { AIMessage, ChatConfig } from '@c8y/ngx-components/ai';\nimport { AiChatMessageComponent } from './ai-chat-message.component';\n\n/**\n * An interactive chat interface component for AI-powered conversations.\n * Displays messages in a conversation format with support for loading states,\n * custom configuration, and markdown formatting.\n */\n@Component({\n selector: 'c8y-ai-chat',\n templateUrl: './ai-chat.component.html',\n imports: [C8yTranslatePipe, FormsModule, TextareaAutoresizeDirective, IconDirective, NgClass],\n standalone: true,\n host: { class: 'd-contents' }\n})\nexport class AiChatComponent {\n /**\n * Indicates whether the chat is currently processing a request.\n * When true, displays a cancel button instead of send button and disables the input.\n */\n @Input()\n isLoading = false;\n\n /**\n * Disables the chat input and send button when true.\n */\n @Input()\n disabled = false;\n\n /**\n * The current text in the chat input field. Supports two-way binding.\n */\n @Input()\n prompt = '';\n\n /**\n * Emitted when the user sends a message.\n * Provides an AIMessage object with role, content, and timestamp.\n */\n @Output()\n onMessage = new EventEmitter<AIMessage>();\n\n /**\n * Emitted when the user cancels an ongoing operation during loading state.\n */\n @Output()\n onCancel = new EventEmitter<void>();\n\n /**\n * Child message components displayed in the chat.\n */\n @ContentChildren(AiChatMessageComponent) messages: QueryList<AiChatMessageComponent>;\n\n readonly componentId = `chat-${crypto.randomUUID()}`;\n\n private _config: ChatConfig = {\n headline: gettext('Welcome!'),\n welcomeText: '',\n title: gettext('What can I help you with?'),\n placeholder: gettext('Type your message here…'),\n placeholderAfterFirstMessage: gettext('Type your next message here…'),\n sendButtonText: gettext('Send'),\n cancelButtonText: gettext('Cancel'),\n disclaimerText: gettext(\n 'AI-generated responses can contain errors. Verify the details before use.'\n ),\n userInterfaceIcons: {\n send: 'arrow-circle-up',\n cancel: 'stop-circle'\n }\n };\n\n /**\n * Configuration object for customizing labels, placeholders, and icons.\n * Accepts partial configuration to override defaults.\n */\n @Input()\n set config(value: Partial<ChatConfig>) {\n this._config = { ...this._config, ...value };\n }\n get config() {\n return this._config;\n }\n\n /**\n * Handles message submission when the user sends a message.\n * Emits the onMessage event and clears the input.\n * @param $event - The event object from the form submission\n */\n sendMessage($event: Event): void {\n $event.preventDefault();\n if (!this.prompt) return;\n this.onMessage.emit({\n role: 'user',\n content: this.prompt,\n timestamp: new Date().toISOString()\n });\n this.prompt = '';\n }\n\n /**\n * Handles cancellation of ongoing operations during loading state.\n * Emits the onCancel event.\n */\n cancel(): void {\n this.onCancel.emit();\n }\n}\n","<div\n class=\"d-col fit-h fit-w flex-grow\"\n [attr.aria-label]=\"config.headline | translate\"\n role=\"region\"\n>\n @if (messages.length > 0) {\n <div\n class=\"inner-scroll flex-grow d-col-reverse min-height-0 bg-level-0\"\n [attr.aria-label]=\"'Chat conversation' | translate\"\n aria-live=\"polite\"\n aria-atomic=\"false\"\n role=\"log\"\n >\n <div class=\"d-col p-l-16 p-r-16\">\n <ng-content select=\"c8y-ai-chat-message\"></ng-content>\n <ng-content></ng-content>\n </div>\n </div>\n }\n <div [ngClass]=\"{ 'd-col fit-h': messages.length === 0 }\">\n @if (messages.length === 0) {\n <div\n class=\"p-24\"\n aria-live=\"polite\"\n role=\"status\"\n >\n <h4 class=\"m-b-16 text-medium\">{{ config.headline | translate }}</h4>\n <p class=\"p-b-8 text-balance\">{{ config.title | translate }}</p>\n <p class=\"text-muted text-balance\">{{ config.welcomeText | translate }}</p>\n </div>\n }\n <div class=\"chat-input bg-level-1\">\n <div class=\"d-flex inner-scroll a-i-center gap-8 p-l-16 p-r-16 p-b-8\">\n <ng-content select=\"c8y-ai-chat-suggestion\"></ng-content>\n </div>\n <div class=\"chat-input-group\">\n <label\n class=\"sr-only\"\n for=\"chat-input-{{ componentId }}\"\n >\n {{ config.placeholder | translate }}\n </label>\n <textarea\n class=\"form-control no-resize\"\n style=\"max-height: 200px !important\"\n [attr.aria-label]=\"config.placeholder | translate\"\n id=\"chat-input-{{ componentId }}\"\n [attr.aria-describedby]=\"config.disclaimerText ? 'chat-disclaimer-' + componentId : null\"\n [attr.aria-busy]=\"isLoading\"\n [placeholder]=\"\n (messages.length === 0 ? config.placeholder : config.placeholderAfterFirstMessage)\n | translate\n \"\n [(ngModel)]=\"prompt\"\n (keydown.enter)=\"sendMessage($event)\"\n [disabled]=\"disabled\"\n c8y-textarea-autoresize\n ></textarea>\n <div class=\"chat-input-group-btn\">\n @if (!isLoading) {\n <button\n class=\"btn btn-dot\"\n [attr.title]=\"config.sendButtonText | translate\"\n [attr.aria-label]=\"config.sendButtonText | translate\"\n type=\"button\"\n (click)=\"sendMessage($event)\"\n [disabled]=\"disabled || prompt.trim().length === 0\"\n >\n <i [c8yIcon]=\"config.userInterfaceIcons?.send || 'arrow-circle-right'\"></i>\n </button>\n } @else {\n <button\n class=\"btn btn-dot btn-dot--danger\"\n [attr.title]=\"config.cancelButtonText | translate\"\n [attr.aria-label]=\"config.cancelButtonText | translate\"\n type=\"button\"\n (click)=\"cancel()\"\n >\n <i [c8yIcon]=\"config.userInterfaceIcons?.cancel || 'stop'\"></i>\n </button>\n }\n </div>\n </div>\n @if (config.disclaimerText) {\n <div\n class=\"text-muted m-b-8 text-10 p-l-16\"\n id=\"chat-disclaimer-{{ componentId }}\"\n role=\"note\"\n >\n {{ config.disclaimerText | translate }}\n </div>\n }\n </div>\n </div>\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["i1"],"mappings":"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"}
|
|
@@ -3,7 +3,7 @@ import { Injectable, Pipe, InjectionToken, HostListener, Input, Optional, Compon
|
|
|
3
3
|
import { combineLatest, BehaviorSubject, Subject, fromEvent, firstValueFrom, of, from, forkJoin, EMPTY, Observable, pipe, take, takeUntil as takeUntil$1, map as map$1 } from 'rxjs';
|
|
4
4
|
import { filter, map, switchMap, startWith, debounceTime, takeUntil, distinctUntilChanged, catchError, finalize, tap, shareReplay, throttleTime } from 'rxjs/operators';
|
|
5
5
|
import * as i3 from '@c8y/ngx-components';
|
|
6
|
-
import { Permissions, ViewContext, SupportedApps, IconDirective, EmptyStateComponent, LoadingComponent, ListGroupComponent, ForOfDirective, ListItemTimelineComponent, ListItemComponent, ListItemBodyComponent, SplitViewDetailsActionsComponent, IconPanelComponent, C8yTranslatePipe, DatePipe, HumanizeAppNamePipe, AssetLinkPipe, TitleComponent, TabsOutletComponent, ProductExperienceDirective, RequiredInputPlaceholderDirective, CountdownIntervalComponent, DynamicComponentAlertAggregator, DynamicComponentAlert, C8yTranslateDirective, ListItemIconComponent, DynamicComponentAlertsComponent, SplitViewListComponent, SplitViewHeaderActionsComponent, SplitViewAlertsComponent, FormGroupComponent, DateTimePickerComponent, MessagesComponent, MessageDirective, ListItemCheckboxComponent, SplitViewComponent, SplitViewDetailsComponent, HelpComponent, ActionBarItemComponent, AlarmWithChildrenRealtimeService, RouterTabsResolver, ContextRouteGuard, ContextRouteComponent, hookNavigator, hookRoute, CommonModule, CoreModule, HeaderModule, C8yTranslateModule, DynamicComponentModule, RelativeTimePipe, NavigatorNode } from '@c8y/ngx-components';
|
|
6
|
+
import { Permissions, ViewContext, SupportedApps, IconDirective, EmptyStateComponent, LoadingComponent, ListGroupComponent, ForOfDirective, ListItemTimelineComponent, ListItemComponent, ListItemBodyComponent, SplitViewDetailsActionsComponent, IconPanelComponent, C8yTranslatePipe, DatePipe, HumanizeAppNamePipe, AssetLinkPipe, MarkdownToHtmlPipe, TitleComponent, TabsOutletComponent, ProductExperienceDirective, RequiredInputPlaceholderDirective, CountdownIntervalComponent, DynamicComponentAlertAggregator, DynamicComponentAlert, C8yTranslateDirective, ListItemIconComponent, DynamicComponentAlertsComponent, SplitViewListComponent, SplitViewHeaderActionsComponent, SplitViewAlertsComponent, FormGroupComponent, DateTimePickerComponent, MessagesComponent, MessageDirective, ListItemCheckboxComponent, SplitViewComponent, SplitViewDetailsComponent, HelpComponent, ActionBarItemComponent, AlarmWithChildrenRealtimeService, RouterTabsResolver, ContextRouteGuard, ContextRouteComponent, hookNavigator, hookRoute, CommonModule, CoreModule, HeaderModule, C8yTranslateModule, DynamicComponentModule, RelativeTimePipe, NavigatorNode } from '@c8y/ngx-components';
|
|
7
7
|
import { sortBy, cloneDeep } from 'lodash-es';
|
|
8
8
|
import { NgClass, NgStyle, NgTemplateOutlet, AsyncPipe, JsonPipe, LowerCasePipe, NgIf, NgFor, TitleCasePipe } from '@angular/common';
|
|
9
9
|
import * as i1 from '@angular/router';
|
|
@@ -1201,7 +1201,7 @@ class AlarmDetailsComponent {
|
|
|
1201
1201
|
this.alarmInfoSections = sections;
|
|
1202
1202
|
}
|
|
1203
1203
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AlarmDetailsComponent, deps: [{ token: AlarmDetailsService }, { token: i2.AlarmService }, { token: i3.AlertService }, { token: i3.AppStateService }, { token: i2.AuditService }, { token: i3.RelativeTimePipe }, { token: Ng1SmartRulesUpgradeService, optional: true }, { token: i1$1.TranslateService }, { token: i2.InventoryService }, { token: AlarmsViewService }, { token: i3.ColorService }, { token: i3.InterAppService }, { token: i3.GainsightService }, { token: AlarmsActivityTrackerService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1204
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: AlarmDetailsComponent, isStandalone: true, selector: "c8y-alarm-details", inputs: { selectedAlarm: "selectedAlarm", showSections: "showSections", hiddenSections: "hiddenSections", showActions: "showActions", hiddenActions: "hiddenActions", showExternalNavigation: "showExternalNavigation" }, host: { listeners: { "document:visibilitychange": "visibilityChange()" } }, providers: [AlarmsActivityTrackerService], usesOnChanges: true, ngImport: i0, template: "@if (selectedAlarm) {\n <div\n class=\"card-header p-24 m-b-16 bg-component separator-bottom sticky-top\"\n style=\"margin: 0 -24px\"\n >\n <h4\n class=\"m-0\"\n data-cy=\"c8y-alarm-details-title\"\n >\n {{ selectedAlarm.text | translate }}\n </h4>\n </div>\n}\n\n<c8y-icon-panel [sections]=\"alarmInfoSections\">\n @if (showSections && !hiddenSections?.source) {\n <div\n class=\"col-xs-12 col-md-6 d-flex p-b-8\"\n data-cy=\"c8y-alarm-details--source-wrapper\"\n >\n <div class=\"border-all fit-w d-flex\">\n <div class=\"p-8\">\n <i\n class=\"icon-24 m-t-4 stroked-icon status\"\n c8yIcon=\"contactless-payment\"\n ></i>\n </div>\n <div class=\"p-t-8 p-b-8 p-r-8\">\n <p class=\"text-label-small m-b-0 m-r-8\">{{ 'Source' | translate }}</p>\n <p class=\"small\">\n <button\n class=\"btn-link text-muted p-0 m-r-8 text-left\"\n title=\"{{ selectedAlarm?.source?.name }}\"\n type=\"button\"\n routerLink=\"{{ selectedAlarmMO | assetLink }}\"\n >\n <small class=\"icon-flex\">\n <i c8yIcon=\"exchange\"></i>\n {{ selectedAlarm?.source?.name || selectedAlarm?.source?.id }}\n </small>\n </button>\n @if (showSourceNavigationLink$ | async) {\n <button\n class=\"btn-link p-0 text-left\"\n title=\"{{\n linkTitle\n | translate\n : { appName: userDeviceManagementApp$ | async | humanizeAppName | async }\n }}\"\n type=\"button\"\n (click)=\"goToAlarmSource(selectedAlarm?.id)\"\n data-cy=\"alarm-details-device-management-link\"\n >\n {{ userDeviceManagementApp$ | async | humanizeAppName | async }}\n <i c8yIcon=\"external-link\"></i>\n </button>\n }\n </p>\n </div>\n </div>\n </div>\n }\n\n @if (showSections && !hiddenSections?.type) {\n <div\n class=\"col-xs-12 col-md-6 d-flex p-b-8\"\n data-cy=\"c8y-alarm-details--severity-type-wrapper\"\n >\n <div class=\"border-all fit-w d-flex\">\n <div class=\"p-8\">\n <span\n class=\"circle-icon-wrapper\"\n [ngStyle]=\"{ 'background-color': typeColor }\"\n >\n <i\n class=\"stroked-icon\"\n c8yIcon=\"bell\"\n ></i>\n </span>\n </div>\n <div class=\"p-t-8 p-b-8 p-r-8 min-width-0\">\n <p class=\"text-label-small m-b-0 m-r-8\">{{ 'Type' | translate }}</p>\n <p\n class=\"small text-truncate\"\n title=\"{{ selectedAlarm?.type }}\"\n >\n <code>{{ selectedAlarm?.type }}</code>\n </p>\n </div>\n </div>\n </div>\n }\n\n <div class=\"col-xs-12 col-md-12 p-b-16\">\n <div class=\"border-all fit-w d-flex\">\n <div class=\"p-8\">\n <i\n class=\"icon-24 text-gray-dark m-t-4\"\n c8yIcon=\"calendar\"\n data-cy=\"c8y-alarm-details--last-updated-icon\"\n ></i>\n </div>\n <div class=\"p-t-8 p-b-0 p-r-8 flex-grow\">\n <div class=\"content-flex-50\">\n @if (selectedAlarm?.count > 1 && showSections && !hiddenSections?.occurrenceCount) {\n <div\n class=\"col-4 p-b-8\"\n data-cy=\"c8y-alarm-details--number-of-occurrences-wrapper\"\n >\n <p class=\"text-label-small m-b-0 m-r-8\">\n {{ 'Number of occurrences' | translate }}\n </p>\n <p>\n <span\n class=\"badge badge-info\"\n data-cy=\"c8y-alarm-details--badge\"\n >\n {{ selectedAlarm?.count }}\n </span>\n </p>\n </div>\n }\n @if (selectedAlarm?.count > 1 && showSections && !hiddenSections?.firstOccurrence) {\n <div\n class=\"col-4 p-b-8\"\n data-cy=\"c8y-alarm-details--first-occurrence-wrapper\"\n >\n <p class=\"text-label-small m-b-0 m-r-8\">{{ 'First occurrence' | translate }}</p>\n <p class=\"small\">\n {{ selectedAlarm?.creationTime | c8yDate: 'medium' }}\n <button\n class=\"btn-help btn-help--sm\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{\n 'Time in which the alarm was created. The time shown corresponds to the server\\'s time. Device time can be different from server time.'\n | translate\n }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n ></button>\n </p>\n </div>\n }\n @if (showSections && !hiddenSections?.lastOccurrence) {\n <div\n class=\"col-4 p-b-8\"\n data-cy=\"c8y-alarm-details--last-updated-wrapper\"\n >\n <p class=\"text-label-small m-b-0 m-r-8\">{{ 'Last occurrence' | translate }}</p>\n <p class=\"small\">\n {{ selectedAlarm?.lastUpdated | c8yDate: 'medium' }}\n <button\n class=\"btn-help btn-help--sm\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{\n 'Time in which the alarm was last updated. The time shown corresponds to the server\\'s time. Device time can be different from server time.'\n | translate\n }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n ></button>\n </p>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n\n @if (customFragments && showSections && !hiddenSections?.customData) {\n <div\n class=\"col-xs-12 col-md-12 p-b-16\"\n data-cy=\"c8y-alarm-details--custom-fragments-wrapper\"\n >\n <div class=\"border-all fit-w d-flex\">\n <div class=\"p-8\">\n <i\n class=\"icon-24 text-gray-dark m-t-4\"\n c8yIcon=\"outgoing-data\"\n ></i>\n </div>\n <div\n class=\"p-t-8 p-b-0 p-r-8 flex-grow\"\n data-cy=\"alarm-details-custom-data\"\n >\n <p class=\"text-label-small m-b-4 m-r-8\">{{ 'Custom data' | translate }}</p>\n <pre><code>{{ customFragments | json }}</code></pre>\n </div>\n </div>\n </div>\n }\n</c8y-icon-panel>\n\n@if (showActions) {\n <c8y-sv-details-actions [actions]=\"alarmActions\">\n @for (button of selectedAlarm | alarmDetailsButton: selectedAlarmMO | async; track $index) {\n <button\n class=\"btn btn-default btn-sm no-swing\"\n [title]=\"button.title | translate\"\n type=\"button\"\n [ngClass]=\"button.additionalButtonClasses\"\n (click)=\"detailsButtonAction(button, selectedAlarm!)\"\n [disabled]=\"button.disabled\"\n >\n <i\n [c8yIcon]=\"button.icon\"\n [ngClass]=\"button.additionalIconClasses\"\n ></i>\n @if (button.label) {\n <span>{{ button.label | translate }}</span>\n }\n </button>\n }\n </c8y-sv-details-actions>\n}\n\n@if (showSections && !hiddenSections?.auditLogs) {\n <ng-template #noAuditLogAvailable>\n <div class=\"p-16\">\n <c8y-ui-empty-state\n [icon]=\"'archive'\"\n [title]=\"'No audit logs found.' | translate\"\n [horizontal]=\"true\"\n ></c8y-ui-empty-state>\n </div>\n </ng-template>\n\n <div>\n <div class=\"legend form-block\">{{ 'Audit logs' | translate }}</div>\n\n @if (isLoading || auditLog?.data.length) {\n @if (isLoading) {\n <c8y-loading></c8y-loading>\n }\n\n @if (!isLoading) {\n <c8y-list-group data-cy=\"c8y-alarms-details--audit-logs\">\n <c8y-li-timeline *c8yFor=\"let log of auditLog; loadMore: 'hidden'\">\n {{ log.creationTime | c8yDate: 'mediumDate' }}\n {{ log.creationTime | c8yDate: 'mediumTime' }}\n <c8y-li>\n <c8y-li-body>\n <p class=\"text-truncate-wrap separator-bottom p-b-4\">\n {{ log | auditChangesMessage }}\n </p>\n <div class=\"c8y-list__item__footer\">\n @if (log.user) {\n <span class=\"m-r-16 small\">\n <span class=\"text-label-small\">\n {{ 'by`user`' | translate }}\n </span>\n {{ log.user }}\n </span>\n }\n <span class=\"small\">\n <span class=\"text-label-small\">\n {{ 'device time' | translate }}\n </span>\n {{ log.time | c8yDate: 'medium' }}\n </span>\n </div>\n </c8y-li-body>\n </c8y-li>\n </c8y-li-timeline>\n </c8y-list-group>\n }\n } @else {\n <ng-container [ngTemplateOutlet]=\"noAuditLogAvailable\"></ng-container>\n }\n </div>\n}\n", dependencies: [{ kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: PopoverDirective, selector: "[popover]", inputs: ["adaptivePosition", "boundariesElement", "popover", "popoverContext", "popoverTitle", "placement", "outsideClick", "triggers", "container", "containerClass", "isOpen", "delay"], outputs: ["onShown", "onHidden"], exportAs: ["bs-popover"] }, { kind: "component", type: EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "component", type: LoadingComponent, selector: "c8y-loading", inputs: ["layout", "progress", "message"] }, { kind: "component", type: ListGroupComponent, selector: "c8y-list-group" }, { kind: "directive", type: ForOfDirective, selector: "[c8yFor]", inputs: ["c8yForOf", "c8yForLoadMore", "c8yForPipe", "c8yForNotFound", "c8yForMaxIterations", "c8yForLoadingTemplate", "c8yForLoadNextLabel", "c8yForLoadingLabel", "c8yForRealtime", "c8yForRealtimeOptions", "c8yForComparator", "c8yForEnableVirtualScroll", "c8yForVirtualScrollElementSize", "c8yForVirtualScrollStrategy", "c8yForVirtualScrollContainerHeight"], outputs: ["c8yForCount", "c8yForChange", "c8yForLoadMoreComponent"] }, { kind: "component", type: ListItemTimelineComponent, selector: "c8y-list-item-timeline, c8y-li-timeline" }, { kind: "component", type: ListItemComponent, selector: "c8y-list-item, c8y-li", inputs: ["active", "highlighted", "emptyActions", "dense", "collapsed", "selectable"], outputs: ["collapsedChange"] }, { kind: "component", type: ListItemBodyComponent, selector: "c8y-list-item-body, c8y-li-body", inputs: ["body"] }, { kind: "component", type: SplitViewDetailsActionsComponent, selector: "c8y-sv-details-actions", inputs: ["actions"] }, { kind: "component", type: IconPanelComponent, selector: "c8y-icon-panel", inputs: ["sections", "ariaLabel"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: JsonPipe, name: "json" }, { kind: "pipe", type: DatePipe, name: "c8yDate" }, { kind: "pipe", type: HumanizeAppNamePipe, name: "humanizeAppName" }, { kind: "pipe", type: AssetLinkPipe, name: "assetLink" }, { kind: "pipe", type: AlarmDetailsButtonPipe, name: "alarmDetailsButton" }, { kind: "pipe", type: AuditChangesMessagePipe, name: "auditChangesMessage" }] }); }
|
|
1204
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: AlarmDetailsComponent, isStandalone: true, selector: "c8y-alarm-details", inputs: { selectedAlarm: "selectedAlarm", showSections: "showSections", hiddenSections: "hiddenSections", showActions: "showActions", hiddenActions: "hiddenActions", showExternalNavigation: "showExternalNavigation" }, host: { listeners: { "document:visibilitychange": "visibilityChange()" } }, providers: [AlarmsActivityTrackerService], usesOnChanges: true, ngImport: i0, template: "@if (selectedAlarm) {\n <div\n class=\"card-header p-24 m-b-16 bg-component separator-bottom sticky-top\"\n style=\"margin: 0 -24px\"\n >\n <h4\n class=\"m-0\"\n data-cy=\"c8y-alarm-details-title\"\n [innerHTML]=\"selectedAlarm.text | translate | markdownToHtml | async\"\n ></h4>\n </div>\n}\n\n<c8y-icon-panel [sections]=\"alarmInfoSections\">\n @if (showSections && !hiddenSections?.source) {\n <div\n class=\"col-xs-12 col-md-6 d-flex p-b-8\"\n data-cy=\"c8y-alarm-details--source-wrapper\"\n >\n <div class=\"border-all fit-w d-flex\">\n <div class=\"p-8\">\n <i\n class=\"icon-24 m-t-4 stroked-icon status\"\n c8yIcon=\"contactless-payment\"\n ></i>\n </div>\n <div class=\"p-t-8 p-b-8 p-r-8\">\n <p class=\"text-label-small m-b-0 m-r-8\">{{ 'Source' | translate }}</p>\n <p class=\"small\">\n <button\n class=\"btn-link text-muted p-0 m-r-8 text-left\"\n title=\"{{ selectedAlarm?.source?.name }}\"\n type=\"button\"\n routerLink=\"{{ selectedAlarmMO | assetLink }}\"\n >\n <small class=\"icon-flex\">\n <i c8yIcon=\"exchange\"></i>\n {{ selectedAlarm?.source?.name || selectedAlarm?.source?.id }}\n </small>\n </button>\n @if (showSourceNavigationLink$ | async) {\n <button\n class=\"btn-link p-0 text-left\"\n title=\"{{\n linkTitle\n | translate\n : { appName: userDeviceManagementApp$ | async | humanizeAppName | async }\n }}\"\n type=\"button\"\n (click)=\"goToAlarmSource(selectedAlarm?.id)\"\n data-cy=\"alarm-details-device-management-link\"\n >\n {{ userDeviceManagementApp$ | async | humanizeAppName | async }}\n <i c8yIcon=\"external-link\"></i>\n </button>\n }\n </p>\n </div>\n </div>\n </div>\n }\n\n @if (showSections && !hiddenSections?.type) {\n <div\n class=\"col-xs-12 col-md-6 d-flex p-b-8\"\n data-cy=\"c8y-alarm-details--severity-type-wrapper\"\n >\n <div class=\"border-all fit-w d-flex\">\n <div class=\"p-8\">\n <span\n class=\"circle-icon-wrapper\"\n [ngStyle]=\"{ 'background-color': typeColor }\"\n >\n <i\n class=\"stroked-icon\"\n c8yIcon=\"bell\"\n ></i>\n </span>\n </div>\n <div class=\"p-t-8 p-b-8 p-r-8 min-width-0\">\n <p class=\"text-label-small m-b-0 m-r-8\">{{ 'Type' | translate }}</p>\n <p\n class=\"small text-truncate\"\n title=\"{{ selectedAlarm?.type }}\"\n >\n <code>{{ selectedAlarm?.type }}</code>\n </p>\n </div>\n </div>\n </div>\n }\n\n <div class=\"col-xs-12 col-md-12 p-b-16\">\n <div class=\"border-all fit-w d-flex\">\n <div class=\"p-8\">\n <i\n class=\"icon-24 text-gray-dark m-t-4\"\n c8yIcon=\"calendar\"\n data-cy=\"c8y-alarm-details--last-updated-icon\"\n ></i>\n </div>\n <div class=\"p-t-8 p-b-0 p-r-8 flex-grow\">\n <div class=\"content-flex-50\">\n @if (selectedAlarm?.count > 1 && showSections && !hiddenSections?.occurrenceCount) {\n <div\n class=\"col-4 p-b-8\"\n data-cy=\"c8y-alarm-details--number-of-occurrences-wrapper\"\n >\n <p class=\"text-label-small m-b-0 m-r-8\">\n {{ 'Number of occurrences' | translate }}\n </p>\n <p>\n <span\n class=\"badge badge-info\"\n data-cy=\"c8y-alarm-details--badge\"\n >\n {{ selectedAlarm?.count }}\n </span>\n </p>\n </div>\n }\n @if (selectedAlarm?.count > 1 && showSections && !hiddenSections?.firstOccurrence) {\n <div\n class=\"col-4 p-b-8\"\n data-cy=\"c8y-alarm-details--first-occurrence-wrapper\"\n >\n <p class=\"text-label-small m-b-0 m-r-8\">{{ 'First occurrence' | translate }}</p>\n <p class=\"small\">\n {{ selectedAlarm?.creationTime | c8yDate: 'medium' }}\n <button\n class=\"btn-help btn-help--sm\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{\n 'Time in which the alarm was created. The time shown corresponds to the server\\'s time. Device time can be different from server time.'\n | translate\n }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n ></button>\n </p>\n </div>\n }\n @if (showSections && !hiddenSections?.lastOccurrence) {\n <div\n class=\"col-4 p-b-8\"\n data-cy=\"c8y-alarm-details--last-updated-wrapper\"\n >\n <p class=\"text-label-small m-b-0 m-r-8\">{{ 'Last occurrence' | translate }}</p>\n <p class=\"small\">\n {{ selectedAlarm?.lastUpdated | c8yDate: 'medium' }}\n <button\n class=\"btn-help btn-help--sm\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{\n 'Time in which the alarm was last updated. The time shown corresponds to the server\\'s time. Device time can be different from server time.'\n | translate\n }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n ></button>\n </p>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n\n @if (customFragments && showSections && !hiddenSections?.customData) {\n <div\n class=\"col-xs-12 col-md-12 p-b-16\"\n data-cy=\"c8y-alarm-details--custom-fragments-wrapper\"\n >\n <div class=\"border-all fit-w d-flex\">\n <div class=\"p-8\">\n <i\n class=\"icon-24 text-gray-dark m-t-4\"\n c8yIcon=\"outgoing-data\"\n ></i>\n </div>\n <div\n class=\"p-t-8 p-b-0 p-r-8 flex-grow\"\n data-cy=\"alarm-details-custom-data\"\n >\n <p class=\"text-label-small m-b-4 m-r-8\">{{ 'Custom data' | translate }}</p>\n <pre><code>{{ customFragments | json }}</code></pre>\n </div>\n </div>\n </div>\n }\n</c8y-icon-panel>\n\n@if (showActions) {\n <c8y-sv-details-actions [actions]=\"alarmActions\">\n @for (button of selectedAlarm | alarmDetailsButton: selectedAlarmMO | async; track $index) {\n <button\n class=\"btn btn-default btn-sm no-swing\"\n [title]=\"button.title | translate\"\n type=\"button\"\n [ngClass]=\"button.additionalButtonClasses\"\n (click)=\"detailsButtonAction(button, selectedAlarm!)\"\n [disabled]=\"button.disabled\"\n >\n <i\n [c8yIcon]=\"button.icon\"\n [ngClass]=\"button.additionalIconClasses\"\n ></i>\n @if (button.label) {\n <span>{{ button.label | translate }}</span>\n }\n </button>\n }\n </c8y-sv-details-actions>\n}\n\n@if (showSections && !hiddenSections?.auditLogs) {\n <ng-template #noAuditLogAvailable>\n <div class=\"p-16\">\n <c8y-ui-empty-state\n [icon]=\"'archive'\"\n [title]=\"'No audit logs found.' | translate\"\n [horizontal]=\"true\"\n ></c8y-ui-empty-state>\n </div>\n </ng-template>\n\n <div>\n <div class=\"legend form-block\">{{ 'Audit logs' | translate }}</div>\n\n @if (isLoading || auditLog?.data.length) {\n @if (isLoading) {\n <c8y-loading></c8y-loading>\n }\n\n @if (!isLoading) {\n <c8y-list-group data-cy=\"c8y-alarms-details--audit-logs\">\n <c8y-li-timeline *c8yFor=\"let log of auditLog; loadMore: 'hidden'\">\n {{ log.creationTime | c8yDate: 'mediumDate' }}\n {{ log.creationTime | c8yDate: 'mediumTime' }}\n <c8y-li>\n <c8y-li-body>\n <p class=\"text-truncate-wrap separator-bottom p-b-4\">\n {{ log | auditChangesMessage }}\n </p>\n <div class=\"c8y-list__item__footer\">\n @if (log.user) {\n <span class=\"m-r-16 small\">\n <span class=\"text-label-small\">\n {{ 'by`user`' | translate }}\n </span>\n {{ log.user }}\n </span>\n }\n <span class=\"small\">\n <span class=\"text-label-small\">\n {{ 'device time' | translate }}\n </span>\n {{ log.time | c8yDate: 'medium' }}\n </span>\n </div>\n </c8y-li-body>\n </c8y-li>\n </c8y-li-timeline>\n </c8y-list-group>\n }\n } @else {\n <ng-container [ngTemplateOutlet]=\"noAuditLogAvailable\"></ng-container>\n }\n </div>\n}\n", dependencies: [{ kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: PopoverDirective, selector: "[popover]", inputs: ["adaptivePosition", "boundariesElement", "popover", "popoverContext", "popoverTitle", "placement", "outsideClick", "triggers", "container", "containerClass", "isOpen", "delay"], outputs: ["onShown", "onHidden"], exportAs: ["bs-popover"] }, { kind: "component", type: EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "component", type: LoadingComponent, selector: "c8y-loading", inputs: ["layout", "progress", "message"] }, { kind: "component", type: ListGroupComponent, selector: "c8y-list-group" }, { kind: "directive", type: ForOfDirective, selector: "[c8yFor]", inputs: ["c8yForOf", "c8yForLoadMore", "c8yForPipe", "c8yForNotFound", "c8yForMaxIterations", "c8yForLoadingTemplate", "c8yForLoadNextLabel", "c8yForLoadingLabel", "c8yForRealtime", "c8yForRealtimeOptions", "c8yForComparator", "c8yForEnableVirtualScroll", "c8yForVirtualScrollElementSize", "c8yForVirtualScrollStrategy", "c8yForVirtualScrollContainerHeight"], outputs: ["c8yForCount", "c8yForChange", "c8yForLoadMoreComponent"] }, { kind: "component", type: ListItemTimelineComponent, selector: "c8y-list-item-timeline, c8y-li-timeline" }, { kind: "component", type: ListItemComponent, selector: "c8y-list-item, c8y-li", inputs: ["active", "highlighted", "emptyActions", "dense", "collapsed", "selectable"], outputs: ["collapsedChange"] }, { kind: "component", type: ListItemBodyComponent, selector: "c8y-list-item-body, c8y-li-body", inputs: ["body"] }, { kind: "component", type: SplitViewDetailsActionsComponent, selector: "c8y-sv-details-actions", inputs: ["actions"] }, { kind: "component", type: IconPanelComponent, selector: "c8y-icon-panel", inputs: ["sections", "ariaLabel"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: JsonPipe, name: "json" }, { kind: "pipe", type: DatePipe, name: "c8yDate" }, { kind: "pipe", type: HumanizeAppNamePipe, name: "humanizeAppName" }, { kind: "pipe", type: AssetLinkPipe, name: "assetLink" }, { kind: "pipe", type: AlarmDetailsButtonPipe, name: "alarmDetailsButton" }, { kind: "pipe", type: AuditChangesMessagePipe, name: "auditChangesMessage" }, { kind: "pipe", type: MarkdownToHtmlPipe, name: "markdownToHtml" }] }); }
|
|
1205
1205
|
}
|
|
1206
1206
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AlarmDetailsComponent, decorators: [{
|
|
1207
1207
|
type: Component,
|
|
@@ -1228,8 +1228,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
1228
1228
|
AuditChangesMessagePipe,
|
|
1229
1229
|
SplitViewDetailsActionsComponent,
|
|
1230
1230
|
IconPanelComponent,
|
|
1231
|
-
NgTemplateOutlet
|
|
1232
|
-
|
|
1231
|
+
NgTemplateOutlet,
|
|
1232
|
+
MarkdownToHtmlPipe
|
|
1233
|
+
], template: "@if (selectedAlarm) {\n <div\n class=\"card-header p-24 m-b-16 bg-component separator-bottom sticky-top\"\n style=\"margin: 0 -24px\"\n >\n <h4\n class=\"m-0\"\n data-cy=\"c8y-alarm-details-title\"\n [innerHTML]=\"selectedAlarm.text | translate | markdownToHtml | async\"\n ></h4>\n </div>\n}\n\n<c8y-icon-panel [sections]=\"alarmInfoSections\">\n @if (showSections && !hiddenSections?.source) {\n <div\n class=\"col-xs-12 col-md-6 d-flex p-b-8\"\n data-cy=\"c8y-alarm-details--source-wrapper\"\n >\n <div class=\"border-all fit-w d-flex\">\n <div class=\"p-8\">\n <i\n class=\"icon-24 m-t-4 stroked-icon status\"\n c8yIcon=\"contactless-payment\"\n ></i>\n </div>\n <div class=\"p-t-8 p-b-8 p-r-8\">\n <p class=\"text-label-small m-b-0 m-r-8\">{{ 'Source' | translate }}</p>\n <p class=\"small\">\n <button\n class=\"btn-link text-muted p-0 m-r-8 text-left\"\n title=\"{{ selectedAlarm?.source?.name }}\"\n type=\"button\"\n routerLink=\"{{ selectedAlarmMO | assetLink }}\"\n >\n <small class=\"icon-flex\">\n <i c8yIcon=\"exchange\"></i>\n {{ selectedAlarm?.source?.name || selectedAlarm?.source?.id }}\n </small>\n </button>\n @if (showSourceNavigationLink$ | async) {\n <button\n class=\"btn-link p-0 text-left\"\n title=\"{{\n linkTitle\n | translate\n : { appName: userDeviceManagementApp$ | async | humanizeAppName | async }\n }}\"\n type=\"button\"\n (click)=\"goToAlarmSource(selectedAlarm?.id)\"\n data-cy=\"alarm-details-device-management-link\"\n >\n {{ userDeviceManagementApp$ | async | humanizeAppName | async }}\n <i c8yIcon=\"external-link\"></i>\n </button>\n }\n </p>\n </div>\n </div>\n </div>\n }\n\n @if (showSections && !hiddenSections?.type) {\n <div\n class=\"col-xs-12 col-md-6 d-flex p-b-8\"\n data-cy=\"c8y-alarm-details--severity-type-wrapper\"\n >\n <div class=\"border-all fit-w d-flex\">\n <div class=\"p-8\">\n <span\n class=\"circle-icon-wrapper\"\n [ngStyle]=\"{ 'background-color': typeColor }\"\n >\n <i\n class=\"stroked-icon\"\n c8yIcon=\"bell\"\n ></i>\n </span>\n </div>\n <div class=\"p-t-8 p-b-8 p-r-8 min-width-0\">\n <p class=\"text-label-small m-b-0 m-r-8\">{{ 'Type' | translate }}</p>\n <p\n class=\"small text-truncate\"\n title=\"{{ selectedAlarm?.type }}\"\n >\n <code>{{ selectedAlarm?.type }}</code>\n </p>\n </div>\n </div>\n </div>\n }\n\n <div class=\"col-xs-12 col-md-12 p-b-16\">\n <div class=\"border-all fit-w d-flex\">\n <div class=\"p-8\">\n <i\n class=\"icon-24 text-gray-dark m-t-4\"\n c8yIcon=\"calendar\"\n data-cy=\"c8y-alarm-details--last-updated-icon\"\n ></i>\n </div>\n <div class=\"p-t-8 p-b-0 p-r-8 flex-grow\">\n <div class=\"content-flex-50\">\n @if (selectedAlarm?.count > 1 && showSections && !hiddenSections?.occurrenceCount) {\n <div\n class=\"col-4 p-b-8\"\n data-cy=\"c8y-alarm-details--number-of-occurrences-wrapper\"\n >\n <p class=\"text-label-small m-b-0 m-r-8\">\n {{ 'Number of occurrences' | translate }}\n </p>\n <p>\n <span\n class=\"badge badge-info\"\n data-cy=\"c8y-alarm-details--badge\"\n >\n {{ selectedAlarm?.count }}\n </span>\n </p>\n </div>\n }\n @if (selectedAlarm?.count > 1 && showSections && !hiddenSections?.firstOccurrence) {\n <div\n class=\"col-4 p-b-8\"\n data-cy=\"c8y-alarm-details--first-occurrence-wrapper\"\n >\n <p class=\"text-label-small m-b-0 m-r-8\">{{ 'First occurrence' | translate }}</p>\n <p class=\"small\">\n {{ selectedAlarm?.creationTime | c8yDate: 'medium' }}\n <button\n class=\"btn-help btn-help--sm\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{\n 'Time in which the alarm was created. The time shown corresponds to the server\\'s time. Device time can be different from server time.'\n | translate\n }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n ></button>\n </p>\n </div>\n }\n @if (showSections && !hiddenSections?.lastOccurrence) {\n <div\n class=\"col-4 p-b-8\"\n data-cy=\"c8y-alarm-details--last-updated-wrapper\"\n >\n <p class=\"text-label-small m-b-0 m-r-8\">{{ 'Last occurrence' | translate }}</p>\n <p class=\"small\">\n {{ selectedAlarm?.lastUpdated | c8yDate: 'medium' }}\n <button\n class=\"btn-help btn-help--sm\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{\n 'Time in which the alarm was last updated. The time shown corresponds to the server\\'s time. Device time can be different from server time.'\n | translate\n }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n ></button>\n </p>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n\n @if (customFragments && showSections && !hiddenSections?.customData) {\n <div\n class=\"col-xs-12 col-md-12 p-b-16\"\n data-cy=\"c8y-alarm-details--custom-fragments-wrapper\"\n >\n <div class=\"border-all fit-w d-flex\">\n <div class=\"p-8\">\n <i\n class=\"icon-24 text-gray-dark m-t-4\"\n c8yIcon=\"outgoing-data\"\n ></i>\n </div>\n <div\n class=\"p-t-8 p-b-0 p-r-8 flex-grow\"\n data-cy=\"alarm-details-custom-data\"\n >\n <p class=\"text-label-small m-b-4 m-r-8\">{{ 'Custom data' | translate }}</p>\n <pre><code>{{ customFragments | json }}</code></pre>\n </div>\n </div>\n </div>\n }\n</c8y-icon-panel>\n\n@if (showActions) {\n <c8y-sv-details-actions [actions]=\"alarmActions\">\n @for (button of selectedAlarm | alarmDetailsButton: selectedAlarmMO | async; track $index) {\n <button\n class=\"btn btn-default btn-sm no-swing\"\n [title]=\"button.title | translate\"\n type=\"button\"\n [ngClass]=\"button.additionalButtonClasses\"\n (click)=\"detailsButtonAction(button, selectedAlarm!)\"\n [disabled]=\"button.disabled\"\n >\n <i\n [c8yIcon]=\"button.icon\"\n [ngClass]=\"button.additionalIconClasses\"\n ></i>\n @if (button.label) {\n <span>{{ button.label | translate }}</span>\n }\n </button>\n }\n </c8y-sv-details-actions>\n}\n\n@if (showSections && !hiddenSections?.auditLogs) {\n <ng-template #noAuditLogAvailable>\n <div class=\"p-16\">\n <c8y-ui-empty-state\n [icon]=\"'archive'\"\n [title]=\"'No audit logs found.' | translate\"\n [horizontal]=\"true\"\n ></c8y-ui-empty-state>\n </div>\n </ng-template>\n\n <div>\n <div class=\"legend form-block\">{{ 'Audit logs' | translate }}</div>\n\n @if (isLoading || auditLog?.data.length) {\n @if (isLoading) {\n <c8y-loading></c8y-loading>\n }\n\n @if (!isLoading) {\n <c8y-list-group data-cy=\"c8y-alarms-details--audit-logs\">\n <c8y-li-timeline *c8yFor=\"let log of auditLog; loadMore: 'hidden'\">\n {{ log.creationTime | c8yDate: 'mediumDate' }}\n {{ log.creationTime | c8yDate: 'mediumTime' }}\n <c8y-li>\n <c8y-li-body>\n <p class=\"text-truncate-wrap separator-bottom p-b-4\">\n {{ log | auditChangesMessage }}\n </p>\n <div class=\"c8y-list__item__footer\">\n @if (log.user) {\n <span class=\"m-r-16 small\">\n <span class=\"text-label-small\">\n {{ 'by`user`' | translate }}\n </span>\n {{ log.user }}\n </span>\n }\n <span class=\"small\">\n <span class=\"text-label-small\">\n {{ 'device time' | translate }}\n </span>\n {{ log.time | c8yDate: 'medium' }}\n </span>\n </div>\n </c8y-li-body>\n </c8y-li>\n </c8y-li-timeline>\n </c8y-list-group>\n }\n } @else {\n <ng-container [ngTemplateOutlet]=\"noAuditLogAvailable\"></ng-container>\n }\n </div>\n}\n" }]
|
|
1233
1234
|
}], ctorParameters: () => [{ type: AlarmDetailsService }, { type: i2.AlarmService }, { type: i3.AlertService }, { type: i3.AppStateService }, { type: i2.AuditService }, { type: i3.RelativeTimePipe }, { type: Ng1SmartRulesUpgradeService, decorators: [{
|
|
1234
1235
|
type: Optional
|
|
1235
1236
|
}] }, { type: i1$1.TranslateService }, { type: i2.InventoryService }, { type: AlarmsViewService }, { type: i3.ColorService }, { type: i3.InterAppService }, { type: i3.GainsightService }, { type: AlarmsActivityTrackerService }], propDecorators: { selectedAlarm: [{
|