UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

237 lines (232 loc) 22 kB
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