@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
237 lines (232 loc) • 22 kB
JavaScript
import * as i0 from '@angular/core';
import { input, viewChild, inject, DestroyRef, signal, effect, ChangeDetectionStrategy, Component, computed } from '@angular/core';
import { toSignal, takeUntilDestroyed } from '@angular/core/rxjs-interop';
import * as i1 from '@angular/forms';
import { NgForm, FormBuilder, ControlContainer, FormsModule, ReactiveFormsModule } from '@angular/forms';
import { AlertService, FormGroupComponent, IconDirective, C8yTranslatePipe, DashboardChildComponent, DismissAlertStrategy, DynamicComponentAlert } from '@c8y/ngx-components';
import { WidgetConfigService } from '@c8y/ngx-components/context-dashboard';
import { EventsViewService, EventsListComponent } from '@c8y/ngx-components/events';
import { PRESET_NAME, LocalControlsComponent, GLOBAL_CONTEXT_DISPLAY_MODE, REFRESH_OPTION, GlobalContextConnectorComponent } from '@c8y/ngx-components/global-context';
import { from } from 'rxjs';
import { shareReplay, debounceTime, switchMap } from 'rxjs/operators';
import { gettext } from '@c8y/ngx-components/gettext';
class EventListWidgetConfigComponent {
constructor() {
this.config = input(...(ngDevMode ? [undefined, { debugName: "config" }] : []));
this.eventListPreview = viewChild('eventListPreview', ...(ngDevMode ? [{ debugName: "eventListPreview" }] : []));
this.alertService = inject(AlertService);
this.destroyRef = inject(DestroyRef);
this.eventsViewService = inject(EventsViewService);
this.form = inject(NgForm);
this.formBuilder = inject(FormBuilder);
this.widgetConfigService = inject(WidgetConfigService);
this.events = signal(undefined, ...(ngDevMode ? [{ debugName: "events" }] : []));
this.isLoading = signal(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
this.controls = PRESET_NAME.ALARM_LIST;
this.navigationOptions = {
allowNavigationToEventsView: false,
alwaysNavigateToAllEvents: false,
queryParamsHandling: 'merge'
};
this.formGroup = this.formBuilder.group({
type: [''],
showEventsForChildren: [true]
});
this.typeValue = toSignal(this.formGroup.controls.type.valueChanges, {
initialValue: this.formGroup.controls.type.value
});
this.config$ = this.widgetConfigService.currentConfig$.pipe(takeUntilDestroyed(this.destroyRef), shareReplay(1));
this.configState = toSignal(this.config$);
effect(() => {
const template = this.eventListPreview();
this.widgetConfigService.setPreview(template ?? null);
});
}
ngOnInit() {
const cfg = this.config();
this.formGroup.patchValue({
type: cfg?.type ?? '',
showEventsForChildren: cfg?.showEventsForChildren ?? true
});
this.form.form.addControl('config', this.formGroup);
this.formGroup.valueChanges
.pipe(debounceTime(300), takeUntilDestroyed(this.destroyRef))
.subscribe(value => {
Object.assign(cfg, value);
this.fetchEvents({ ...cfg, ...value });
});
this.widgetConfigService.addOnBeforeSave(config => {
Object.assign(config, this.formGroup.value);
return true;
});
this.config$
.pipe(takeUntilDestroyed(this.destroyRef), switchMap(config => from(this.fetchEvents({ ...config, ...this.formGroup.value }))))
.subscribe();
}
clearType() {
this.formGroup.controls.type.setValue('');
}
async fetchEvents(config) {
try {
this.isLoading.set(true);
const filter = this.eventsViewService.buildEventsFilter({
source: config.device?.id ?? null,
withSourceChildren: config.showEventsForChildren ?? true,
type: config.type ?? null,
dateTimeContext: config.dateTimeContext
});
const result = await this.eventsViewService.retrieveEvents({ ...filter, pageSize: 10 });
this.events.set(result);
}
catch (error) {
this.alertService.addServerFailure(error);
}
finally {
this.isLoading.set(false);
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EventListWidgetConfigComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: EventListWidgetConfigComponent, isStandalone: true, selector: "c8y-event-list-widget-config", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "eventListPreview", first: true, predicate: ["eventListPreview"], descendants: true, isSignal: true }], ngImport: i0, template: "<div [formGroup]=\"formGroup\">\n <fieldset class=\"c8y-fieldset\">\n <legend translate>Type</legend>\n <c8y-form-group>\n <div style=\"position: relative\">\n <input\n class=\"form-control\"\n [style.padding-right]=\"typeValue() ? '32px' : null\"\n formControlName=\"type\"\n [placeholder]=\"'e.g. {{ example }}' | translate: { example: 'c8y_LocationUpdate' }\"\n />\n @if (typeValue()) {\n <button\n class=\"btn btn-clean\"\n style=\"position: absolute; right: 8px; top: 50%; transform: translateY(-50%)\"\n [title]=\"'Clear' | translate\"\n type=\"button\"\n (click)=\"clearType()\"\n >\n <i c8yIcon=\"times\"></i>\n </button>\n }\n </div>\n </c8y-form-group>\n </fieldset>\n <fieldset\n class=\"c8y-fieldset\"\n data-cy=\"c8y-event-list-widget-config--child-devices-section\"\n >\n <legend>{{ 'Child devices' | translate }}</legend>\n <c8y-form-group class=\"m-b-8\">\n <label\n class=\"c8y-switch\"\n [title]=\"'Show events from child devices' | translate\"\n data-cy=\"c8y-event-list-widget-config--child-devices-label\"\n >\n <input\n type=\"checkbox\"\n formControlName=\"showEventsForChildren\"\n data-cy=\"c8y-event-list-widget-config--showEventsForChildren-checkbox\"\n />\n <span></span>\n <span>{{ 'Show events' | translate }}</span>\n <span class=\"sr-only\">{{ 'Show events' | translate }}</span>\n </label>\n </c8y-form-group>\n </fieldset>\n</div>\n\n<ng-template #eventListPreview>\n @let previewDisplayMode = configState()?.displayMode;\n @if (previewDisplayMode && previewDisplayMode !== 'dashboard') {\n <c8y-local-controls\n [controls]=\"controls\"\n [displayMode]=\"previewDisplayMode\"\n [config]=\"{\n dateTimeContext: configState()?.dateTimeContext,\n aggregation: configState()?.aggregation,\n isAutoRefreshEnabled: configState()?.isAutoRefreshEnabled,\n refreshInterval: configState()?.refreshInterval,\n refreshOption: configState()?.refreshOption\n }\"\n [disabled]=\"true\"\n ></c8y-local-controls>\n }\n <c8y-events-list\n [events]=\"events()\"\n [isLoading]=\"isLoading()\"\n [navigationOptions]=\"navigationOptions\"\n ></c8y-events-list>\n</ng-template>\n", dependencies: [{ kind: "component", type: EventsListComponent, selector: "c8y-events-list", inputs: ["events", "isLoading", "loadMoreMode", "showPreview", "navigationOptions"], outputs: ["onScrollingStateChange", "onPreviewStateChange", "onSelectedEvent"] }, { kind: "component", type: FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "ngmodule", type: FormsModule }, { 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.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "component", type: LocalControlsComponent, selector: "c8y-local-controls", inputs: ["controls", "displayMode", "config", "isLoading", "disabled", "emitRefresh"], outputs: ["configChange", "refresh"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }], viewProviders: [{ provide: ControlContainer, useExisting: NgForm }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EventListWidgetConfigComponent, decorators: [{
type: Component,
args: [{ selector: 'c8y-event-list-widget-config', changeDetection: ChangeDetectionStrategy.OnPush, viewProviders: [{ provide: ControlContainer, useExisting: NgForm }], imports: [
C8yTranslatePipe,
EventsListComponent,
FormGroupComponent,
FormsModule,
IconDirective,
LocalControlsComponent,
ReactiveFormsModule
], template: "<div [formGroup]=\"formGroup\">\n <fieldset class=\"c8y-fieldset\">\n <legend translate>Type</legend>\n <c8y-form-group>\n <div style=\"position: relative\">\n <input\n class=\"form-control\"\n [style.padding-right]=\"typeValue() ? '32px' : null\"\n formControlName=\"type\"\n [placeholder]=\"'e.g. {{ example }}' | translate: { example: 'c8y_LocationUpdate' }\"\n />\n @if (typeValue()) {\n <button\n class=\"btn btn-clean\"\n style=\"position: absolute; right: 8px; top: 50%; transform: translateY(-50%)\"\n [title]=\"'Clear' | translate\"\n type=\"button\"\n (click)=\"clearType()\"\n >\n <i c8yIcon=\"times\"></i>\n </button>\n }\n </div>\n </c8y-form-group>\n </fieldset>\n <fieldset\n class=\"c8y-fieldset\"\n data-cy=\"c8y-event-list-widget-config--child-devices-section\"\n >\n <legend>{{ 'Child devices' | translate }}</legend>\n <c8y-form-group class=\"m-b-8\">\n <label\n class=\"c8y-switch\"\n [title]=\"'Show events from child devices' | translate\"\n data-cy=\"c8y-event-list-widget-config--child-devices-label\"\n >\n <input\n type=\"checkbox\"\n formControlName=\"showEventsForChildren\"\n data-cy=\"c8y-event-list-widget-config--showEventsForChildren-checkbox\"\n />\n <span></span>\n <span>{{ 'Show events' | translate }}</span>\n <span class=\"sr-only\">{{ 'Show events' | translate }}</span>\n </label>\n </c8y-form-group>\n </fieldset>\n</div>\n\n<ng-template #eventListPreview>\n @let previewDisplayMode = configState()?.displayMode;\n @if (previewDisplayMode && previewDisplayMode !== 'dashboard') {\n <c8y-local-controls\n [controls]=\"controls\"\n [displayMode]=\"previewDisplayMode\"\n [config]=\"{\n dateTimeContext: configState()?.dateTimeContext,\n aggregation: configState()?.aggregation,\n isAutoRefreshEnabled: configState()?.isAutoRefreshEnabled,\n refreshInterval: configState()?.refreshInterval,\n refreshOption: configState()?.refreshOption\n }\"\n [disabled]=\"true\"\n ></c8y-local-controls>\n }\n <c8y-events-list\n [events]=\"events()\"\n [isLoading]=\"isLoading()\"\n [navigationOptions]=\"navigationOptions\"\n ></c8y-events-list>\n</ng-template>\n" }]
}], ctorParameters: () => [], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }], eventListPreview: [{ type: i0.ViewChild, args: ['eventListPreview', { isSignal: true }] }] } });
class EventListWidgetComponent {
constructor() {
this.config = input(...(ngDevMode ? [undefined, { debugName: "config" }] : []));
this.alertService = inject(AlertService);
this.dashboardChild = inject(DashboardChildComponent);
this.eventsViewService = inject(EventsViewService);
this.isListScrolled = signal(false, ...(ngDevMode ? [{ debugName: "isListScrolled" }] : []));
this.displayMode = signal(GLOBAL_CONTEXT_DISPLAY_MODE.DASHBOARD, ...(ngDevMode ? [{ debugName: "displayMode" }] : []));
this.contextConfig = signal({}, ...(ngDevMode ? [{ debugName: "contextConfig" }] : []));
this.isLinkedToGlobal = signal(undefined, ...(ngDevMode ? [{ debugName: "isLinkedToGlobal" }] : []));
this.events = signal(undefined, ...(ngDevMode ? [{ debugName: "events" }] : []));
this.isLoading = signal(true, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
this.widgetControls = signal(PRESET_NAME.ALARM_LIST, ...(ngDevMode ? [{ debugName: "widgetControls" }] : []));
this.sourceId = '';
this.GLOBAL_CONTEXT_DISPLAY_MODE = GLOBAL_CONTEXT_DISPLAY_MODE;
this.REFRESH_OPTION = REFRESH_OPTION;
this.navigationOptions = computed(() => ({
alwaysNavigateToAllEvents: !this.config()?.device,
allowNavigationToEventsView: true,
queryParamsHandling: ''
}), ...(ngDevMode ? [{ debugName: "navigationOptions" }] : []));
this.TIMEOUT_ERROR_TEXT = gettext('The request is taking longer than usual. We apologize for the inconvenience.');
this.SERVER_ERROR_TEXT = gettext('Server error occurred.');
}
async ngOnInit() {
this.alerts.setAlertGroupDismissStrategy('warning', DismissAlertStrategy.TEMPORARY_OR_PERMANENT);
const cfg = this.config();
this.migrateLegacyConfig(cfg);
this.sourceId =
cfg?.device?.id ??
this.dashboardChild['data']?.device?.id ??
this.dashboardChild['data']?.context?.id ??
'';
const displayMode = cfg?.displayMode || GLOBAL_CONTEXT_DISPLAY_MODE.DASHBOARD;
this.displayMode.set(displayMode);
const initialContextConfig = {
dateTimeContext: cfg?.dateTimeContext,
aggregation: cfg?.aggregation,
isAutoRefreshEnabled: cfg?.isAutoRefreshEnabled,
refreshInterval: cfg?.refreshInterval,
refreshOption: cfg?.refreshOption
};
this.contextConfig.set(initialContextConfig);
if (displayMode !== GLOBAL_CONTEXT_DISPLAY_MODE.DASHBOARD) {
await this.fetchEvents();
}
}
onContextChange(event) {
const { diff, context } = event;
if (diff.isAutoRefreshEnabled === false &&
Object.keys(diff).length === 1 &&
context.refreshOption === REFRESH_OPTION.LIVE) {
return;
}
this.contextConfig.set(context);
void this.fetchEvents();
}
onRefresh() {
void this.fetchEvents();
}
onScrollingStateChange(isScrolling) {
this.isListScrolled.set(isScrolling);
const current = this.contextConfig();
if (current.refreshOption === REFRESH_OPTION.HISTORY) {
return;
}
this.contextConfig.set({ ...current, isAutoRefreshEnabled: !isScrolling });
this.isLinkedToGlobal.set(!isScrolling);
}
onPreviewStateChange(isOpen) {
const current = this.contextConfig();
if (current.refreshOption === REFRESH_OPTION.HISTORY) {
return;
}
if (isOpen || !this.isListScrolled()) {
this.contextConfig.set({ ...current, isAutoRefreshEnabled: !isOpen });
this.isLinkedToGlobal.set(!isOpen);
}
}
migrateLegacyConfig(cfg) {
if (!cfg || cfg.type) {
return;
}
const legacyType = cfg['options'];
if (legacyType && typeof legacyType === 'object' && 'type' in legacyType) {
cfg.type = legacyType.type;
}
}
async fetchEvents() {
try {
this.isLoading.set(true);
const effectiveConfig = {
...this.config(),
...this.contextConfig()
};
const filter = this.eventsViewService.buildEventsFilter({
source: this.sourceId || null,
withSourceChildren: this.config()?.showEventsForChildren ?? true,
type: effectiveConfig.type ?? null,
dateTimeContext: effectiveConfig.dateTimeContext
});
const result = await this.eventsViewService.retrieveEvents({ ...filter, pageSize: 10 });
this.events.set(result);
}
catch (error) {
const err = error;
this.alerts.addAlerts(new DynamicComponentAlert({
type: 'warning',
text: err.name === 'TimeoutError'
? this.TIMEOUT_ERROR_TEXT
: (err.message ?? this.SERVER_ERROR_TEXT)
}));
this.alertService.addServerFailure(error);
}
finally {
this.isLoading.set(false);
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EventListWidgetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: EventListWidgetComponent, isStandalone: true, selector: "c8y-event-list-widget", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (displayMode() === GLOBAL_CONTEXT_DISPLAY_MODE.DASHBOARD) {\n <c8y-global-context-connector\n [controls]=\"widgetControls()\"\n [config]=\"contextConfig()\"\n [isLoading]=\"isLoading()\"\n [dashboardChild]=\"dashboardChild\"\n [linked]=\"isLinkedToGlobal()\"\n (configChange)=\"onContextChange($event)\"\n (refresh)=\"onRefresh()\"\n ></c8y-global-context-connector>\n} @else {\n <c8y-local-controls\n [controls]=\"widgetControls()\"\n [displayMode]=\"displayMode()\"\n [config]=\"contextConfig()\"\n [isLoading]=\"isLoading()\"\n (configChange)=\"onContextChange($event)\"\n (refresh)=\"onRefresh()\"\n ></c8y-local-controls>\n}\n\n<c8y-events-list\n [events]=\"events()\"\n [isLoading]=\"isLoading()\"\n [showPreview]=\"true\"\n [navigationOptions]=\"navigationOptions()\"\n (onScrollingStateChange)=\"onScrollingStateChange($event)\"\n (onPreviewStateChange)=\"onPreviewStateChange($event)\"\n></c8y-events-list>\n", dependencies: [{ kind: "component", type: EventsListComponent, selector: "c8y-events-list", inputs: ["events", "isLoading", "loadMoreMode", "showPreview", "navigationOptions"], outputs: ["onScrollingStateChange", "onPreviewStateChange", "onSelectedEvent"] }, { kind: "component", type: LocalControlsComponent, selector: "c8y-local-controls", inputs: ["controls", "displayMode", "config", "isLoading", "disabled", "emitRefresh"], outputs: ["configChange", "refresh"] }, { kind: "component", type: GlobalContextConnectorComponent, selector: "c8y-global-context-connector", inputs: ["controls", "config", "isLoading", "dashboardChild", "linked", "emitRefresh"], outputs: ["configChange", "refresh", "linkedChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EventListWidgetComponent, decorators: [{
type: Component,
args: [{ selector: 'c8y-event-list-widget', changeDetection: ChangeDetectionStrategy.OnPush, imports: [EventsListComponent, LocalControlsComponent, GlobalContextConnectorComponent], template: "@if (displayMode() === GLOBAL_CONTEXT_DISPLAY_MODE.DASHBOARD) {\n <c8y-global-context-connector\n [controls]=\"widgetControls()\"\n [config]=\"contextConfig()\"\n [isLoading]=\"isLoading()\"\n [dashboardChild]=\"dashboardChild\"\n [linked]=\"isLinkedToGlobal()\"\n (configChange)=\"onContextChange($event)\"\n (refresh)=\"onRefresh()\"\n ></c8y-global-context-connector>\n} @else {\n <c8y-local-controls\n [controls]=\"widgetControls()\"\n [displayMode]=\"displayMode()\"\n [config]=\"contextConfig()\"\n [isLoading]=\"isLoading()\"\n (configChange)=\"onContextChange($event)\"\n (refresh)=\"onRefresh()\"\n ></c8y-local-controls>\n}\n\n<c8y-events-list\n [events]=\"events()\"\n [isLoading]=\"isLoading()\"\n [showPreview]=\"true\"\n [navigationOptions]=\"navigationOptions()\"\n (onScrollingStateChange)=\"onScrollingStateChange($event)\"\n (onPreviewStateChange)=\"onPreviewStateChange($event)\"\n></c8y-events-list>\n" }]
}], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }] } });
/**
* Generated bundle index. Do not edit.
*/
export { EventListWidgetComponent, EventListWidgetConfigComponent };
//# sourceMappingURL=c8y-ngx-components-widgets-implementations-events.mjs.map