Browse Source

Merge pull request #13753 from ChantsovaEkaterina/improvement/clear-timewindow-configuration

Optimized the size of timewindow in dashboard configuration when saving
pull/13894/head
Igor Kulikov 1 year ago
committed by GitHub
parent
commit
af7b9e8455
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 39
      ui-ngx/src/app/core/services/dashboard-utils.service.ts
  2. 47
      ui-ngx/src/app/core/utils.ts
  3. 3
      ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts
  4. 17
      ui-ngx/src/app/modules/home/components/widget/config/widget-config.component.models.ts
  5. 21
      ui-ngx/src/app/modules/home/components/widget/widget-config.component.ts
  6. 172
      ui-ngx/src/app/shared/components/time/timewindow-config-dialog.component.ts
  7. 110
      ui-ngx/src/app/shared/components/time/timewindow-panel.component.ts
  8. 3
      ui-ngx/src/app/shared/components/time/timewindow.component.ts
  9. 140
      ui-ngx/src/app/shared/models/time/time.models.ts
  10. 8
      ui-ngx/src/app/shared/models/widget.models.ts
  11. 67
      ui-ngx/src/app/shared/models/widget/maps/map-model.definition.ts
  12. 1
      ui-ngx/src/app/shared/models/widget/widget-model.definition.ts

39
ui-ngx/src/app/core/services/dashboard-utils.service.ts

@ -38,6 +38,7 @@ import {
import { deepClone, isDefined, isDefinedAndNotNull, isNotEmptyStr, isString, isUndefined } from '@core/utils'; import { deepClone, isDefined, isDefinedAndNotNull, isNotEmptyStr, isString, isUndefined } from '@core/utils';
import { import {
Datasource, Datasource,
datasourcesHasAggregation,
datasourcesHasOnlyComparisonAggregation, datasourcesHasOnlyComparisonAggregation,
DatasourceType, DatasourceType,
defaultLegendConfig, defaultLegendConfig,
@ -49,7 +50,8 @@ import {
WidgetConfigMode, WidgetConfigMode,
WidgetSize, WidgetSize,
widgetType, widgetType,
WidgetTypeDescriptor WidgetTypeDescriptor,
widgetTypeHasTimewindow
} from '@app/shared/models/widget.models'; } from '@app/shared/models/widget.models';
import { EntityType } from '@shared/models/entity-type.models'; import { EntityType } from '@shared/models/entity-type.models';
import { AliasFilterType, EntityAlias, EntityAliasFilter } from '@app/shared/models/alias.models'; import { AliasFilterType, EntityAlias, EntityAliasFilter } from '@app/shared/models/alias.models';
@ -234,6 +236,7 @@ export class DashboardUtilsService {
public validateAndUpdateWidget(widget: Widget): Widget { public validateAndUpdateWidget(widget: Widget): Widget {
widget.config = this.validateAndUpdateWidgetConfig(widget.config, widget.type); widget.config = this.validateAndUpdateWidgetConfig(widget.config, widget.type);
widget = this.validateAndUpdateWidgetTypeFqn(widget); widget = this.validateAndUpdateWidgetTypeFqn(widget);
this.removeTimewindowConfigIfUnused(widget);
if (isDefined((widget as any).title)) { if (isDefined((widget as any).title)) {
delete (widget as any).title; delete (widget as any).title;
} }
@ -294,8 +297,11 @@ export class DashboardUtilsService {
} }
widgetConfig.datasources = this.validateAndUpdateDatasources(widgetConfig.datasources); widgetConfig.datasources = this.validateAndUpdateDatasources(widgetConfig.datasources);
if (type === widgetType.latest) { if (type === widgetType.latest) {
const onlyHistoryTimewindow = datasourcesHasOnlyComparisonAggregation(widgetConfig.datasources); if (datasourcesHasAggregation(widgetConfig.datasources)) {
widgetConfig.timewindow = initModelFromDefaultTimewindow(widgetConfig.timewindow, true, onlyHistoryTimewindow, this.timeService); const onlyHistoryTimewindow = datasourcesHasOnlyComparisonAggregation(widgetConfig.datasources);
widgetConfig.timewindow = initModelFromDefaultTimewindow(widgetConfig.timewindow, true,
onlyHistoryTimewindow, this.timeService, false);
}
} else if (type === widgetType.rpc) { } else if (type === widgetType.rpc) {
if (widgetConfig.targetDeviceAliasIds && widgetConfig.targetDeviceAliasIds.length) { if (widgetConfig.targetDeviceAliasIds && widgetConfig.targetDeviceAliasIds.length) {
widgetConfig.targetDevice = { widgetConfig.targetDevice = {
@ -348,6 +354,33 @@ export class DashboardUtilsService {
return widgetConfig; return widgetConfig;
} }
private removeTimewindowConfigIfUnused(widget: Widget) {
const widgetHasTimewindow = this.widgetHasTimewindow(widget);
if (!widgetHasTimewindow || widget.config.useDashboardTimewindow) {
delete widget.config.displayTimewindow;
delete widget.config.timewindow;
delete widget.config.timewindowStyle;
if (!widgetHasTimewindow) {
delete widget.config.useDashboardTimewindow;
}
}
}
private widgetHasTimewindow(widget: Widget): boolean {
const widgetDefinition = findWidgetModelDefinition(widget);
if (widgetDefinition) {
return widgetDefinition.hasTimewindow(widget);
}
return widgetTypeHasTimewindow(widget.type)
|| (widget.type === widgetType.latest && datasourcesHasAggregation(widget.config.datasources));
}
public prepareWidgetForSaving(widget: Widget): Widget {
this.removeTimewindowConfigIfUnused(widget);
return widget;
}
public prepareWidgetForScadaLayout(widget: Widget, isScada: boolean): Widget { public prepareWidgetForScadaLayout(widget: Widget, isScada: boolean): Widget {
const config = widget.config; const config = widget.config;
config.showTitle = false; config.showTitle = false;

47
ui-ngx/src/app/core/utils.ts

@ -27,7 +27,8 @@ import { serverErrorCodesTranslations } from '@shared/models/constants';
import { SubscriptionEntityInfo } from '@core/api/widget-api.models'; import { SubscriptionEntityInfo } from '@core/api/widget-api.models';
import { import {
CompiledTbFunction, CompiledTbFunction,
compileTbFunction, GenericFunction, compileTbFunction,
GenericFunction,
isNotEmptyTbFunction, isNotEmptyTbFunction,
TbFunction TbFunction
} from '@shared/models/js-function.models'; } from '@shared/models/js-function.models';
@ -196,6 +197,23 @@ export function deleteNullProperties(obj: any) {
}); });
} }
export function deleteFalseProperties(obj: Record<string, any>): void {
if (isUndefinedOrNull(obj)) {
return;
}
Object.keys(obj).forEach((propName) => {
if (obj[propName] === false || isUndefinedOrNull(obj[propName])) {
delete obj[propName];
} else if (isObject(obj[propName])) {
deleteFalseProperties(obj[propName]);
} else if (Array.isArray(obj[propName])) {
(obj[propName] as any[]).forEach((elem) => {
deleteFalseProperties(elem);
});
}
});
}
export function objToBase64(obj: any): string { export function objToBase64(obj: any): string {
const json = JSON.stringify(obj); const json = JSON.stringify(obj);
return btoa(encodeURIComponent(json).replace(/%([0-9A-F]{2})/g, return btoa(encodeURIComponent(json).replace(/%([0-9A-F]{2})/g,
@ -773,6 +791,33 @@ export function deepTrim<T>(obj: T): T {
}, (Array.isArray(obj) ? [] : {}) as T); }, (Array.isArray(obj) ? [] : {}) as T);
} }
export function deepClean<T extends Record<string, any> | any[]>(obj: T, {
cleanKeys = []
} = {}): T {
return _.transform(obj, (result, value, key) => {
if (cleanKeys.includes(key)) {
return;
}
if (Array.isArray(value) || isLiteralObject(value)) {
value = deepClean(value, {cleanKeys});
}
if(isLiteralObject(value) && isEmpty(value)) {
return;
}
if (Array.isArray(value) && !value.length) {
return;
}
if (value === undefined || value === null || value === '' || Number.isNaN(value)) {
return;
}
if (Array.isArray(result)) {
return result.push(value);
}
result[key] = value;
});
}
export function generateSecret(length?: number): string { export function generateSecret(length?: number): string {
if (isUndefined(length) || length == null) { if (isUndefined(length) || length == null) {
length = 1; length = 1;

3
ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts

@ -1323,6 +1323,7 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC
} }
private addWidgetToDashboard(widget: Widget) { private addWidgetToDashboard(widget: Widget) {
this.dashboardUtils.prepareWidgetForSaving(widget);
if (this.addingLayoutCtx) { if (this.addingLayoutCtx) {
this.addWidgetToLayout(widget, this.addingLayoutCtx.id); this.addWidgetToLayout(widget, this.addingLayoutCtx.id);
this.addingLayoutCtx = null; this.addingLayoutCtx = null;
@ -1410,7 +1411,7 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC
saveWidget() { saveWidget() {
this.editWidgetComponent.widgetFormGroup.markAsPristine(); this.editWidgetComponent.widgetFormGroup.markAsPristine();
const widget = deepClone(this.editingWidget); const widget = this.dashboardUtils.prepareWidgetForSaving(deepClone(this.editingWidget));
const widgetLayout = deepClone(this.editingWidgetLayout); const widgetLayout = deepClone(this.editingWidgetLayout);
const id = this.editingWidgetOriginal.id; const id = this.editingWidgetOriginal.id;
this.dashboardConfiguration.widgets[id] = widget; this.dashboardConfiguration.widgets[id] = widget;

17
ui-ngx/src/app/modules/home/components/widget/config/widget-config.component.models.ts

@ -23,11 +23,19 @@ import { PageComponent } from '@shared/components/page.component';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';
import { AbstractControl, UntypedFormGroup } from '@angular/forms'; import { AbstractControl, UntypedFormGroup } from '@angular/forms';
import { DataKey, DatasourceType, Widget, WidgetConfigMode, widgetType } from '@shared/models/widget.models'; import {
DataKey,
DatasourceType,
Widget,
widgetTypeCanHaveTimewindow,
WidgetConfigMode,
widgetType
} from '@shared/models/widget.models';
import { WidgetConfigComponent } from '@home/components/widget/widget-config.component'; import { WidgetConfigComponent } from '@home/components/widget/widget-config.component';
import { isDefinedAndNotNull } from '@core/utils'; import { isDefinedAndNotNull, isUndefinedOrNull } from '@core/utils';
import { IAliasController } from '@core/api/widget-api.models'; import { IAliasController } from '@core/api/widget-api.models';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { initModelFromDefaultTimewindow } from '@shared/models/time/time.models';
export type WidgetConfigCallbacks = DatasourceCallbacks & WidgetActionCallbacks; export type WidgetConfigCallbacks = DatasourceCallbacks & WidgetActionCallbacks;
@ -107,6 +115,11 @@ export abstract class BasicWidgetConfigComponent extends PageComponent implement
if (this.isAdd) { if (this.isAdd) {
this.setupDefaults(widgetConfig); this.setupDefaults(widgetConfig);
} }
if (widgetTypeCanHaveTimewindow(widgetConfig.widgetType) && isUndefinedOrNull(widgetConfig.config.timewindow)) {
widgetConfig.config.timewindow = initModelFromDefaultTimewindow(null,
widgetConfig.widgetType === widgetType.latest, false, this.widgetConfigComponent.timeService,
widgetConfig.widgetType === widgetType.timeseries);
}
this.onConfigSet(widgetConfig); this.onConfigSet(widgetConfig);
this.updateValidators(false); this.updateValidators(false);
for (const trigger of this.validatorTriggers()) { for (const trigger of this.validatorTriggers()) {

21
ui-ngx/src/app/modules/home/components/widget/widget-config.component.ts

@ -38,6 +38,7 @@ import {
TargetDevice, TargetDevice,
targetDeviceValid, targetDeviceValid,
Widget, Widget,
widgetTypeCanHaveTimewindow,
WidgetConfigMode, WidgetConfigMode,
widgetType widgetType
} from '@shared/models/widget.models'; } from '@shared/models/widget.models';
@ -53,7 +54,7 @@ import {
Validators Validators
} from '@angular/forms'; } from '@angular/forms';
import { WidgetConfigComponentData } from '@home/models/widget-component.models'; import { WidgetConfigComponentData } from '@home/models/widget-component.models';
import { deepClone, genNextLabel, isDefined, isObject } from '@app/core/utils'; import { deepClone, genNextLabel, isDefined, isDefinedAndNotNull, isObject } from '@app/core/utils';
import { alarmFields, AlarmSearchStatus } from '@shared/models/alarm.models'; import { alarmFields, AlarmSearchStatus } from '@shared/models/alarm.models';
import { IAliasController } from '@core/api/widget-api.models'; import { IAliasController } from '@core/api/widget-api.models';
import { EntityAlias } from '@shared/models/alias.models'; import { EntityAlias } from '@shared/models/alias.models';
@ -84,6 +85,8 @@ import { DataKeySettingsFunction } from '@home/components/widget/lib/settings/co
import { defaultFormProperties, FormProperty } from '@shared/models/dynamic-form.models'; import { defaultFormProperties, FormProperty } from '@shared/models/dynamic-form.models';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { WidgetService } from '@core/http/widget.service'; import { WidgetService } from '@core/http/widget.service';
import { TimeService } from '@core/services/time.service';
import { initModelFromDefaultTimewindow } from '@shared/models/time/time.models';
import Timeout = NodeJS.Timeout; import Timeout = NodeJS.Timeout;
@Component({ @Component({
@ -201,6 +204,7 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, OnDe
constructor(protected store: Store<AppState>, constructor(protected store: Store<AppState>,
private utils: UtilsService, private utils: UtilsService,
private entityService: EntityService, private entityService: EntityService,
public timeService: TimeService,
private dialog: MatDialog, private dialog: MatDialog,
public translate: TranslateService, public translate: TranslateService,
private fb: UntypedFormBuilder, private fb: UntypedFormBuilder,
@ -366,16 +370,16 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, OnDe
this.dataSettings = this.fb.group({}); this.dataSettings = this.fb.group({});
this.targetDeviceSettings = this.fb.group({}); this.targetDeviceSettings = this.fb.group({});
this.advancedSettings = this.fb.group({}); this.advancedSettings = this.fb.group({});
if (this.widgetType === widgetType.timeseries || this.widgetType === widgetType.alarm || this.widgetType === widgetType.latest) { if (widgetTypeCanHaveTimewindow(this.widgetType)) {
this.dataSettings.addControl('timewindowConfig', this.fb.control({ this.dataSettings.addControl('timewindowConfig', this.fb.control({
useDashboardTimewindow: true, useDashboardTimewindow: true,
displayTimewindow: true, displayTimewindow: true,
timewindow: null, timewindow: null,
timewindowStyle: null timewindowStyle: null
})); }));
if (this.widgetType === widgetType.alarm) { }
this.dataSettings.addControl('alarmFilterConfig', this.fb.control(null)); if (this.widgetType === widgetType.alarm) {
} this.dataSettings.addControl('alarmFilterConfig', this.fb.control(null));
} }
if (this.modelValue.isDataEnabled) { if (this.modelValue.isDataEnabled) {
if (this.widgetType !== widgetType.rpc && if (this.widgetType !== widgetType.rpc &&
@ -529,14 +533,17 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, OnDe
}, },
{emitEvent: false} {emitEvent: false}
); );
if (this.widgetType === widgetType.timeseries || this.widgetType === widgetType.alarm || this.widgetType === widgetType.latest) { if (widgetTypeCanHaveTimewindow(this.widgetType)) {
const useDashboardTimewindow = isDefined(config.useDashboardTimewindow) ? const useDashboardTimewindow = isDefined(config.useDashboardTimewindow) ?
config.useDashboardTimewindow : true; config.useDashboardTimewindow : true;
this.dataSettings.get('timewindowConfig').patchValue({ this.dataSettings.get('timewindowConfig').patchValue({
useDashboardTimewindow, useDashboardTimewindow,
displayTimewindow: isDefined(config.displayTimewindow) ? displayTimewindow: isDefined(config.displayTimewindow) ?
config.displayTimewindow : true, config.displayTimewindow : true,
timewindow: config.timewindow, timewindow: isDefinedAndNotNull(config.timewindow)
? config.timewindow
: initModelFromDefaultTimewindow(null, this.widgetType === widgetType.latest, this.onlyHistoryTimewindow(),
this.timeService, this.widgetType === widgetType.timeseries),
timewindowStyle: config.timewindowStyle timewindowStyle: config.timewindowStyle
}, {emitEvent: false}); }, {emitEvent: false});
} }

172
ui-ngx/src/app/shared/components/time/timewindow-config-dialog.component.ts

@ -36,7 +36,15 @@ import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { TimeService } from '@core/services/time.service'; import { TimeService } from '@core/services/time.service';
import { deepClone, isDefined, isDefinedAndNotNull, isObject, mergeDeep } from '@core/utils'; import {
deepClean,
deepClone,
deleteFalseProperties,
isDefined,
isDefinedAndNotNull,
isEmpty,
mergeDeepIgnoreArray
} from '@core/utils';
import { ToggleHeaderOption } from '@shared/components/toggle-header.component'; import { ToggleHeaderOption } from '@shared/components/toggle-header.component';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
@ -152,73 +160,73 @@ export class TimewindowConfigDialogComponent extends PageComponent implements On
this.timewindowForm = this.fb.group({ this.timewindowForm = this.fb.group({
selectedTab: [isDefined(this.timewindow.selectedTab) ? this.timewindow.selectedTab : TimewindowType.REALTIME], selectedTab: [isDefined(this.timewindow.selectedTab) ? this.timewindow.selectedTab : TimewindowType.REALTIME],
realtime: this.fb.group({ realtime: this.fb.group({
realtimeType: [ isDefined(realtime?.realtimeType) ? this.timewindow.realtime.realtimeType : RealtimeWindowType.LAST_INTERVAL ], realtimeType: [ isDefined(realtime?.realtimeType) ? realtime.realtimeType : RealtimeWindowType.LAST_INTERVAL ],
timewindowMs: [ isDefined(realtime?.timewindowMs) ? this.timewindow.realtime.timewindowMs : null ], timewindowMs: [ isDefined(realtime?.timewindowMs) ? realtime.timewindowMs : null ],
interval: [ isDefined(realtime?.interval) ? this.timewindow.realtime.interval : null ], interval: [ isDefined(realtime?.interval) ? realtime.interval : null ],
quickInterval: [ isDefined(realtime?.quickInterval) ? this.timewindow.realtime.quickInterval : null ], quickInterval: [ isDefined(realtime?.quickInterval) ? realtime.quickInterval : null ],
disableCustomInterval: [ isDefinedAndNotNull(this.timewindow.realtime?.disableCustomInterval) disableCustomInterval: [ isDefinedAndNotNull(realtime?.disableCustomInterval)
? this.timewindow.realtime?.disableCustomInterval : false ], ? realtime.disableCustomInterval : false ],
disableCustomGroupInterval: [ isDefinedAndNotNull(this.timewindow.realtime?.disableCustomGroupInterval) disableCustomGroupInterval: [ isDefinedAndNotNull(realtime?.disableCustomGroupInterval)
? this.timewindow.realtime?.disableCustomGroupInterval : false ], ? realtime.disableCustomGroupInterval : false ],
hideInterval: [ isDefinedAndNotNull(this.timewindow.realtime.hideInterval) hideInterval: [ isDefinedAndNotNull(realtime?.hideInterval)
? this.timewindow.realtime.hideInterval : false ], ? realtime.hideInterval : false ],
hideLastInterval: [{ hideLastInterval: [{
value: isDefinedAndNotNull(this.timewindow.realtime.hideLastInterval) value: isDefinedAndNotNull(realtime?.hideLastInterval)
? this.timewindow.realtime.hideLastInterval : false, ? realtime.hideLastInterval : false,
disabled: this.timewindow.realtime.hideInterval disabled: realtime?.hideInterval
}], }],
hideQuickInterval: [{ hideQuickInterval: [{
value: isDefinedAndNotNull(this.timewindow.realtime.hideQuickInterval) value: isDefinedAndNotNull(realtime?.hideQuickInterval)
? this.timewindow.realtime.hideQuickInterval : false, ? realtime.hideQuickInterval : false,
disabled: this.timewindow.realtime.hideInterval disabled: realtime?.hideInterval
}], }],
advancedParams: this.fb.group({ advancedParams: this.fb.group({
allowedLastIntervals: [ isDefinedAndNotNull(this.timewindow.realtime?.advancedParams?.allowedLastIntervals) allowedLastIntervals: [ isDefinedAndNotNull(realtime?.advancedParams?.allowedLastIntervals)
? this.timewindow.realtime.advancedParams.allowedLastIntervals : null ], ? realtime.advancedParams.allowedLastIntervals : null ],
allowedQuickIntervals: [ isDefinedAndNotNull(this.timewindow.realtime?.advancedParams?.allowedQuickIntervals) allowedQuickIntervals: [ isDefinedAndNotNull(realtime?.advancedParams?.allowedQuickIntervals)
? this.timewindow.realtime.advancedParams.allowedQuickIntervals : null ], ? realtime.advancedParams.allowedQuickIntervals : null ],
lastAggIntervalsConfig: [ isDefinedAndNotNull(this.timewindow.realtime?.advancedParams?.lastAggIntervalsConfig) lastAggIntervalsConfig: [ isDefinedAndNotNull(realtime?.advancedParams?.lastAggIntervalsConfig)
? this.timewindow.realtime.advancedParams.lastAggIntervalsConfig : null ], ? realtime.advancedParams.lastAggIntervalsConfig : null ],
quickAggIntervalsConfig: [ isDefinedAndNotNull(this.timewindow.realtime?.advancedParams?.quickAggIntervalsConfig) quickAggIntervalsConfig: [ isDefinedAndNotNull(realtime?.advancedParams?.quickAggIntervalsConfig)
? this.timewindow.realtime.advancedParams.quickAggIntervalsConfig : null ] ? realtime.advancedParams.quickAggIntervalsConfig : null ]
}) })
}), }),
history: this.fb.group({ history: this.fb.group({
historyType: [ isDefined(history?.historyType) ? this.timewindow.history.historyType : HistoryWindowType.LAST_INTERVAL ], historyType: [ isDefined(history?.historyType) ? history.historyType : HistoryWindowType.LAST_INTERVAL ],
timewindowMs: [ isDefined(history?.timewindowMs) ? this.timewindow.history.timewindowMs : null ], timewindowMs: [ isDefined(history?.timewindowMs) ? history.timewindowMs : null ],
interval: [ isDefined(history?.interval) ? this.timewindow.history.interval : null ], interval: [ isDefined(history?.interval) ? history.interval : null ],
fixedTimewindow: [ isDefined(history?.fixedTimewindow) ? this.timewindow.history.fixedTimewindow : null ], fixedTimewindow: [ isDefined(history?.fixedTimewindow) ? history.fixedTimewindow : null ],
quickInterval: [ isDefined(history?.quickInterval) ? this.timewindow.history.quickInterval : null ], quickInterval: [ isDefined(history?.quickInterval) ? history.quickInterval : null ],
disableCustomInterval: [ isDefinedAndNotNull(this.timewindow.history?.disableCustomInterval) disableCustomInterval: [ isDefinedAndNotNull(history?.disableCustomInterval)
? this.timewindow.history?.disableCustomInterval : false ], ? history.disableCustomInterval : false ],
disableCustomGroupInterval: [ isDefinedAndNotNull(this.timewindow.history?.disableCustomGroupInterval) disableCustomGroupInterval: [ isDefinedAndNotNull(history?.disableCustomGroupInterval)
? this.timewindow.history?.disableCustomGroupInterval : false ], ? history.disableCustomGroupInterval : false ],
hideInterval: [ isDefinedAndNotNull(this.timewindow.history.hideInterval) hideInterval: [ isDefinedAndNotNull(history?.hideInterval)
? this.timewindow.history.hideInterval : false ], ? history.hideInterval : false ],
hideLastInterval: [{ hideLastInterval: [{
value: isDefinedAndNotNull(this.timewindow.history.hideLastInterval) value: isDefinedAndNotNull(history?.hideLastInterval)
? this.timewindow.history.hideLastInterval : false, ? history.hideLastInterval : false,
disabled: this.timewindow.history.hideInterval disabled: history?.hideInterval
}], }],
hideQuickInterval: [{ hideQuickInterval: [{
value: isDefinedAndNotNull(this.timewindow.history.hideQuickInterval) value: isDefinedAndNotNull(history?.hideQuickInterval)
? this.timewindow.history.hideQuickInterval : false, ? history.hideQuickInterval : false,
disabled: this.timewindow.history.hideInterval disabled: history?.hideInterval
}], }],
hideFixedInterval: [{ hideFixedInterval: [{
value: isDefinedAndNotNull(this.timewindow.history.hideFixedInterval) value: isDefinedAndNotNull(history?.hideFixedInterval)
? this.timewindow.history.hideFixedInterval : false, ? history.hideFixedInterval : false,
disabled: this.timewindow.history.hideInterval disabled: history?.hideInterval
}], }],
advancedParams: this.fb.group({ advancedParams: this.fb.group({
allowedLastIntervals: [ isDefinedAndNotNull(this.timewindow.history?.advancedParams?.allowedLastIntervals) allowedLastIntervals: [ isDefinedAndNotNull(history?.advancedParams?.allowedLastIntervals)
? this.timewindow.history.advancedParams.allowedLastIntervals : null ], ? history.advancedParams.allowedLastIntervals : null ],
allowedQuickIntervals: [ isDefinedAndNotNull(this.timewindow.history?.advancedParams?.allowedQuickIntervals) allowedQuickIntervals: [ isDefinedAndNotNull(history?.advancedParams?.allowedQuickIntervals)
? this.timewindow.history.advancedParams.allowedQuickIntervals : null ], ? history.advancedParams.allowedQuickIntervals : null ],
lastAggIntervalsConfig: [ isDefinedAndNotNull(this.timewindow.history?.advancedParams?.lastAggIntervalsConfig) lastAggIntervalsConfig: [ isDefinedAndNotNull(history?.advancedParams?.lastAggIntervalsConfig)
? this.timewindow.history.advancedParams.lastAggIntervalsConfig : null ], ? history.advancedParams.lastAggIntervalsConfig : null ],
quickAggIntervalsConfig: [ isDefinedAndNotNull(this.timewindow.history?.advancedParams?.quickAggIntervalsConfig) quickAggIntervalsConfig: [ isDefinedAndNotNull(history?.advancedParams?.quickAggIntervalsConfig)
? this.timewindow.history.advancedParams.quickAggIntervalsConfig : null ] ? history.advancedParams.quickAggIntervalsConfig : null ]
}) })
}), }),
aggregation: this.fb.group({ aggregation: this.fb.group({
@ -423,7 +431,7 @@ export class TimewindowConfigDialogComponent extends PageComponent implements On
update() { update() {
const timewindowFormValue = this.timewindowForm.getRawValue(); const timewindowFormValue = this.timewindowForm.getRawValue();
this.timewindow = mergeDeep(this.timewindow, timewindowFormValue); this.timewindow = mergeDeepIgnoreArray(this.timewindow, timewindowFormValue);
const realtimeConfigurableLastIntervalsAvailable = !(timewindowFormValue.hideAggInterval && const realtimeConfigurableLastIntervalsAvailable = !(timewindowFormValue.hideAggInterval &&
(timewindowFormValue.realtime.hideInterval || timewindowFormValue.realtime.hideLastInterval)); (timewindowFormValue.realtime.hideInterval || timewindowFormValue.realtime.hideLastInterval));
@ -434,82 +442,50 @@ export class TimewindowConfigDialogComponent extends PageComponent implements On
const historyConfigurableQuickIntervalsAvailable = !(timewindowFormValue.hideAggInterval && const historyConfigurableQuickIntervalsAvailable = !(timewindowFormValue.hideAggInterval &&
(timewindowFormValue.history.hideInterval || timewindowFormValue.history.hideQuickInterval)); (timewindowFormValue.history.hideInterval || timewindowFormValue.history.hideQuickInterval));
if (realtimeConfigurableLastIntervalsAvailable && timewindowFormValue.realtime.advancedParams.allowedLastIntervals?.length) { if (!realtimeConfigurableLastIntervalsAvailable) {
this.timewindow.realtime.advancedParams.allowedLastIntervals = timewindowFormValue.realtime.advancedParams.allowedLastIntervals;
} else {
delete this.timewindow.realtime.advancedParams.allowedLastIntervals; delete this.timewindow.realtime.advancedParams.allowedLastIntervals;
} }
if (realtimeConfigurableQuickIntervalsAvailable && timewindowFormValue.realtime.advancedParams.allowedQuickIntervals?.length) { if (!realtimeConfigurableQuickIntervalsAvailable) {
this.timewindow.realtime.advancedParams.allowedQuickIntervals = timewindowFormValue.realtime.advancedParams.allowedQuickIntervals;
} else {
delete this.timewindow.realtime.advancedParams.allowedQuickIntervals; delete this.timewindow.realtime.advancedParams.allowedQuickIntervals;
} }
if (realtimeConfigurableLastIntervalsAvailable && isObject(timewindowFormValue.realtime.advancedParams.lastAggIntervalsConfig) && if (realtimeConfigurableLastIntervalsAvailable && !isEmpty(timewindowFormValue.realtime.advancedParams.lastAggIntervalsConfig)) {
Object.keys(timewindowFormValue.realtime.advancedParams.lastAggIntervalsConfig).length) {
this.timewindow.realtime.advancedParams.lastAggIntervalsConfig = timewindowFormValue.realtime.advancedParams.lastAggIntervalsConfig; this.timewindow.realtime.advancedParams.lastAggIntervalsConfig = timewindowFormValue.realtime.advancedParams.lastAggIntervalsConfig;
} else { } else {
delete this.timewindow.realtime.advancedParams.lastAggIntervalsConfig; delete this.timewindow.realtime.advancedParams.lastAggIntervalsConfig;
} }
if (realtimeConfigurableQuickIntervalsAvailable && isObject(timewindowFormValue.realtime.advancedParams.quickAggIntervalsConfig) && if (realtimeConfigurableQuickIntervalsAvailable && !isEmpty(timewindowFormValue.realtime.advancedParams.quickAggIntervalsConfig)) {
Object.keys(timewindowFormValue.realtime.advancedParams.quickAggIntervalsConfig).length) {
this.timewindow.realtime.advancedParams.quickAggIntervalsConfig = timewindowFormValue.realtime.advancedParams.quickAggIntervalsConfig; this.timewindow.realtime.advancedParams.quickAggIntervalsConfig = timewindowFormValue.realtime.advancedParams.quickAggIntervalsConfig;
} else { } else {
delete this.timewindow.realtime.advancedParams.quickAggIntervalsConfig; delete this.timewindow.realtime.advancedParams.quickAggIntervalsConfig;
} }
if (historyConfigurableLastIntervalsAvailable && timewindowFormValue.history.advancedParams.allowedLastIntervals?.length) { if (!historyConfigurableLastIntervalsAvailable) {
this.timewindow.history.advancedParams.allowedLastIntervals = timewindowFormValue.history.advancedParams.allowedLastIntervals;
} else {
delete this.timewindow.history.advancedParams.allowedLastIntervals; delete this.timewindow.history.advancedParams.allowedLastIntervals;
} }
if (historyConfigurableQuickIntervalsAvailable && timewindowFormValue.history.advancedParams.allowedQuickIntervals?.length) { if (!historyConfigurableQuickIntervalsAvailable) {
this.timewindow.history.advancedParams.allowedQuickIntervals = timewindowFormValue.history.advancedParams.allowedQuickIntervals;
} else {
delete this.timewindow.history.advancedParams.allowedQuickIntervals; delete this.timewindow.history.advancedParams.allowedQuickIntervals;
} }
if (historyConfigurableLastIntervalsAvailable && isObject(timewindowFormValue.history.advancedParams.lastAggIntervalsConfig) && if (historyConfigurableLastIntervalsAvailable && !isEmpty(timewindowFormValue.history.advancedParams.lastAggIntervalsConfig)) {
Object.keys(timewindowFormValue.history.advancedParams.lastAggIntervalsConfig).length) {
this.timewindow.history.advancedParams.lastAggIntervalsConfig = timewindowFormValue.history.advancedParams.lastAggIntervalsConfig; this.timewindow.history.advancedParams.lastAggIntervalsConfig = timewindowFormValue.history.advancedParams.lastAggIntervalsConfig;
} else { } else {
delete this.timewindow.history.advancedParams.lastAggIntervalsConfig; delete this.timewindow.history.advancedParams.lastAggIntervalsConfig;
} }
if (historyConfigurableQuickIntervalsAvailable && isObject(timewindowFormValue.history.advancedParams.quickAggIntervalsConfig) && if (historyConfigurableQuickIntervalsAvailable && !isEmpty(timewindowFormValue.history.advancedParams.quickAggIntervalsConfig)) {
Object.keys(timewindowFormValue.history.advancedParams.quickAggIntervalsConfig).length) {
this.timewindow.history.advancedParams.quickAggIntervalsConfig = timewindowFormValue.history.advancedParams.quickAggIntervalsConfig; this.timewindow.history.advancedParams.quickAggIntervalsConfig = timewindowFormValue.history.advancedParams.quickAggIntervalsConfig;
} else { } else {
delete this.timewindow.history.advancedParams.quickAggIntervalsConfig; delete this.timewindow.history.advancedParams.quickAggIntervalsConfig;
} }
if (!Object.keys(this.timewindow.realtime.advancedParams).length) { if (timewindowFormValue.hideAggregation) {
delete this.timewindow.realtime.advancedParams;
}
if (!Object.keys(this.timewindow.history.advancedParams).length) {
delete this.timewindow.history.advancedParams;
}
if (timewindowFormValue.allowedAggTypes?.length && !timewindowFormValue.hideAggregation) {
this.timewindow.allowedAggTypes = timewindowFormValue.allowedAggTypes;
} else {
delete this.timewindow.allowedAggTypes; delete this.timewindow.allowedAggTypes;
} }
if (!this.timewindow.realtime.disableCustomInterval) {
delete this.timewindow.realtime.disableCustomInterval;
}
if (!this.timewindow.realtime.disableCustomGroupInterval) {
delete this.timewindow.realtime.disableCustomGroupInterval;
}
if (!this.timewindow.history.disableCustomInterval) {
delete this.timewindow.history.disableCustomInterval;
}
if (!this.timewindow.history.disableCustomGroupInterval) {
delete this.timewindow.history.disableCustomGroupInterval;
}
if (!this.aggregation) { if (!this.aggregation) {
delete this.timewindow.aggregation; delete this.timewindow.aggregation;
} }
this.dialogRef.close(this.timewindow);
deleteFalseProperties(this.timewindow);
this.dialogRef.close(deepClean(this.timewindow));
} }
cancel() { cancel() {

110
ui-ngx/src/app/shared/components/time/timewindow-panel.component.ts

@ -27,12 +27,14 @@ import {
} from '@angular/core'; } from '@angular/core';
import { import {
AggregationType, AggregationType,
clearTimewindowConfig,
currentHistoryTimewindow, currentHistoryTimewindow,
currentRealtimeTimewindow, currentRealtimeTimewindow,
historyAllowedAggIntervals, historyAllowedAggIntervals,
HistoryWindowType, HistoryWindowType,
historyWindowTypeTranslations, historyWindowTypeTranslations,
Interval, Interval,
MINUTE,
QuickTimeInterval, QuickTimeInterval,
realtimeAllowedAggIntervals, realtimeAllowedAggIntervals,
RealtimeWindowType, RealtimeWindowType,
@ -167,14 +169,14 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit, O
}); });
} }
if ((this.isEdit || !this.timewindow.realtime.hideLastInterval) && !this.quickIntervalOnly) { if ((this.isEdit || !this.timewindow.realtime?.hideLastInterval) && !this.quickIntervalOnly) {
this.realtimeTimewindowOptions.push({ this.realtimeTimewindowOptions.push({
name: this.translate.instant(realtimeWindowTypeTranslations.get(RealtimeWindowType.LAST_INTERVAL)), name: this.translate.instant(realtimeWindowTypeTranslations.get(RealtimeWindowType.LAST_INTERVAL)),
value: this.realtimeTypes.LAST_INTERVAL value: this.realtimeTypes.LAST_INTERVAL
}); });
} }
if (this.isEdit || !this.timewindow.realtime.hideQuickInterval || this.quickIntervalOnly) { if (this.isEdit || !this.timewindow.realtime?.hideQuickInterval || this.quickIntervalOnly) {
this.realtimeTimewindowOptions.push({ this.realtimeTimewindowOptions.push({
name: this.translate.instant(realtimeWindowTypeTranslations.get(RealtimeWindowType.INTERVAL)), name: this.translate.instant(realtimeWindowTypeTranslations.get(RealtimeWindowType.INTERVAL)),
value: this.realtimeTypes.INTERVAL value: this.realtimeTypes.INTERVAL
@ -188,21 +190,21 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit, O
}); });
} }
if (this.isEdit || !this.timewindow.history.hideLastInterval) { if (this.isEdit || !this.timewindow.history?.hideLastInterval) {
this.historyTimewindowOptions.push({ this.historyTimewindowOptions.push({
name: this.translate.instant(historyWindowTypeTranslations.get(HistoryWindowType.LAST_INTERVAL)), name: this.translate.instant(historyWindowTypeTranslations.get(HistoryWindowType.LAST_INTERVAL)),
value: this.historyTypes.LAST_INTERVAL value: this.historyTypes.LAST_INTERVAL
}); });
} }
if (this.isEdit || !this.timewindow.history.hideFixedInterval) { if (this.isEdit || !this.timewindow.history?.hideFixedInterval) {
this.historyTimewindowOptions.push({ this.historyTimewindowOptions.push({
name: this.translate.instant(historyWindowTypeTranslations.get(HistoryWindowType.FIXED)), name: this.translate.instant(historyWindowTypeTranslations.get(HistoryWindowType.FIXED)),
value: this.historyTypes.FIXED value: this.historyTypes.FIXED
}); });
} }
if (this.isEdit || !this.timewindow.history.hideQuickInterval) { if (this.isEdit || !this.timewindow.history?.hideQuickInterval) {
this.historyTimewindowOptions.push({ this.historyTimewindowOptions.push({
name: this.translate.instant(historyWindowTypeTranslations.get(HistoryWindowType.INTERVAL)), name: this.translate.instant(historyWindowTypeTranslations.get(HistoryWindowType.INTERVAL)),
value: this.historyTypes.INTERVAL value: this.historyTypes.INTERVAL
@ -211,10 +213,10 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit, O
this.realtimeTypeSelectionAvailable = this.realtimeTimewindowOptions.length > 1; this.realtimeTypeSelectionAvailable = this.realtimeTimewindowOptions.length > 1;
this.historyTypeSelectionAvailable = this.historyTimewindowOptions.length > 1; this.historyTypeSelectionAvailable = this.historyTimewindowOptions.length > 1;
this.realtimeIntervalSelectionAvailable = this.isEdit || !(this.timewindow.realtime.hideInterval || this.realtimeIntervalSelectionAvailable = this.isEdit || !(this.timewindow.realtime?.hideInterval ||
(this.timewindow.realtime.hideLastInterval && this.timewindow.realtime.hideQuickInterval)); (this.timewindow.realtime?.hideLastInterval && this.timewindow.realtime?.hideQuickInterval));
this.historyIntervalSelectionAvailable = this.isEdit || !(this.timewindow.history.hideInterval || this.historyIntervalSelectionAvailable = this.isEdit || !(this.timewindow.history?.hideInterval ||
(this.timewindow.history.hideLastInterval && this.timewindow.history.hideQuickInterval && this.timewindow.history.hideFixedInterval)); (this.timewindow.history?.hideLastInterval && this.timewindow.history?.hideQuickInterval && this.timewindow.history?.hideFixedInterval));
this.aggregationOptionsAvailable = this.aggregation && (this.isEdit || this.aggregationOptionsAvailable = this.aggregation && (this.isEdit ||
!(this.timewindow.hideAggregation && this.timewindow.hideAggInterval)); !(this.timewindow.hideAggregation && this.timewindow.hideAggInterval));
@ -230,28 +232,28 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit, O
const aggregation = this.timewindow.aggregation; const aggregation = this.timewindow.aggregation;
if (!this.isEdit) { if (!this.isEdit) {
if (realtime.hideLastInterval && !realtime.hideQuickInterval) { if (realtime?.hideLastInterval && !realtime?.hideQuickInterval) {
realtime.realtimeType = RealtimeWindowType.INTERVAL; realtime.realtimeType = RealtimeWindowType.INTERVAL;
} }
if (realtime.hideQuickInterval && !realtime.hideLastInterval) { if (realtime?.hideQuickInterval && !realtime?.hideLastInterval) {
realtime.realtimeType = RealtimeWindowType.LAST_INTERVAL; realtime.realtimeType = RealtimeWindowType.LAST_INTERVAL;
} }
if (history.hideLastInterval) { if (history?.hideLastInterval) {
if (!history.hideFixedInterval) { if (!history.hideFixedInterval) {
history.historyType = HistoryWindowType.FIXED; history.historyType = HistoryWindowType.FIXED;
} else if (!history.hideQuickInterval) { } else if (!history.hideQuickInterval) {
history.historyType = HistoryWindowType.INTERVAL; history.historyType = HistoryWindowType.INTERVAL;
} }
} }
if (history.hideFixedInterval) { if (history?.hideFixedInterval) {
if (!history.hideLastInterval) { if (!history.hideLastInterval) {
history.historyType = HistoryWindowType.LAST_INTERVAL; history.historyType = HistoryWindowType.LAST_INTERVAL;
} else if (!history.hideQuickInterval) { } else if (!history.hideQuickInterval) {
history.historyType = HistoryWindowType.INTERVAL; history.historyType = HistoryWindowType.INTERVAL;
} }
} }
if (history.hideQuickInterval) { if (history?.hideQuickInterval) {
if (!history.hideLastInterval) { if (!history.hideLastInterval) {
history.historyType = HistoryWindowType.LAST_INTERVAL; history.historyType = HistoryWindowType.LAST_INTERVAL;
} else if (!history.hideFixedInterval) { } else if (!history.hideFixedInterval) {
@ -265,29 +267,29 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit, O
realtime: this.fb.group({ realtime: this.fb.group({
realtimeType: [{ realtimeType: [{
value: isDefined(realtime?.realtimeType) ? realtime.realtimeType : RealtimeWindowType.LAST_INTERVAL, value: isDefined(realtime?.realtimeType) ? realtime.realtimeType : RealtimeWindowType.LAST_INTERVAL,
disabled: realtime.hideInterval disabled: realtime?.hideInterval
}], }],
timewindowMs: [{ timewindowMs: [{
value: isDefined(realtime?.timewindowMs) ? realtime.timewindowMs : null, value: isDefined(realtime?.timewindowMs) ? realtime.timewindowMs : MINUTE,
disabled: realtime.hideInterval || realtime.hideLastInterval disabled: realtime?.hideInterval || realtime?.hideLastInterval
}], }],
interval: [{ interval: [{
value:isDefined(realtime?.interval) ? realtime.interval : null, value:isDefined(realtime?.interval) ? realtime.interval : null,
disabled: hideAggInterval disabled: hideAggInterval
}], }],
quickInterval: [{ quickInterval: [{
value: isDefined(realtime?.quickInterval) ? realtime.quickInterval : null, value: isDefined(realtime?.quickInterval) ? realtime.quickInterval : QuickTimeInterval.CURRENT_DAY,
disabled: realtime.hideInterval || realtime.hideQuickInterval disabled: realtime?.hideInterval || realtime?.hideQuickInterval
}] }]
}), }),
history: this.fb.group({ history: this.fb.group({
historyType: [{ historyType: [{
value: isDefined(history?.historyType) ? history.historyType : HistoryWindowType.LAST_INTERVAL, value: isDefined(history?.historyType) ? history.historyType : HistoryWindowType.LAST_INTERVAL,
disabled: history.hideInterval disabled: history?.hideInterval
}], }],
timewindowMs: [{ timewindowMs: [{
value: isDefined(history?.timewindowMs) ? history.timewindowMs : null, value: isDefined(history?.timewindowMs) ? history.timewindowMs : MINUTE,
disabled: history.hideInterval || history.hideLastInterval disabled: history?.hideInterval || history?.hideLastInterval
}], }],
interval: [{ interval: [{
value:isDefined(history?.interval) ? history.interval : null, value:isDefined(history?.interval) ? history.interval : null,
@ -296,11 +298,11 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit, O
fixedTimewindow: [{ fixedTimewindow: [{
value: isDefined(history?.fixedTimewindow) && this.timewindow.selectedTab === TimewindowType.HISTORY value: isDefined(history?.fixedTimewindow) && this.timewindow.selectedTab === TimewindowType.HISTORY
&& history.historyType === HistoryWindowType.FIXED ? history.fixedTimewindow : null, && history.historyType === HistoryWindowType.FIXED ? history.fixedTimewindow : null,
disabled: history.hideInterval || history.hideFixedInterval disabled: history?.hideInterval || history?.hideFixedInterval
}], }],
quickInterval: [{ quickInterval: [{
value: isDefined(history?.quickInterval) ? history.quickInterval : null, value: isDefined(history?.quickInterval) ? history.quickInterval : QuickTimeInterval.CURRENT_DAY,
disabled: history.hideInterval || history.hideQuickInterval disabled: history?.hideInterval || history?.hideQuickInterval
}] }]
}), }),
aggregation: this.fb.group({ aggregation: this.fb.group({
@ -379,8 +381,7 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit, O
this.timewindowForm.valueChanges.pipe( this.timewindowForm.valueChanges.pipe(
takeUntil(this.destroy$) takeUntil(this.destroy$)
).subscribe(() => { ).subscribe(() => {
this.prepareTimewindowConfig(); this.changeTimewindow.emit(this.prepareTimewindowConfig());
this.changeTimewindow.emit(this.timewindow);
}); });
} }
} }
@ -406,27 +407,29 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit, O
} }
update() { update() {
this.prepareTimewindowConfig(); this.result = this.prepareTimewindowConfig();
this.result = this.timewindow;
this.overlayRef?.dispose(); this.overlayRef?.dispose();
} }
private prepareTimewindowConfig() { private prepareTimewindowConfig(clearConfig = true): Timewindow {
const timewindowFormValue = this.timewindowForm.getRawValue(); const timewindowFormValue = this.timewindowForm.getRawValue();
this.timewindow.selectedTab = timewindowFormValue.selectedTab; this.timewindow.selectedTab = timewindowFormValue.selectedTab;
this.timewindow.realtime = {...this.timewindow.realtime, ...{ if (this.timewindow.selectedTab === TimewindowType.REALTIME) {
realtimeType: timewindowFormValue.realtime.realtimeType, this.timewindow.realtime = {...this.timewindow.realtime, ...{
timewindowMs: timewindowFormValue.realtime.timewindowMs, realtimeType: timewindowFormValue.realtime.realtimeType,
quickInterval: timewindowFormValue.realtime.quickInterval, timewindowMs: timewindowFormValue.realtime.timewindowMs,
interval: timewindowFormValue.realtime.interval quickInterval: timewindowFormValue.realtime.quickInterval,
}}; interval: timewindowFormValue.realtime.interval,
this.timewindow.history = {...this.timewindow.history, ...{ }};
historyType: timewindowFormValue.history.historyType, } else {
timewindowMs: timewindowFormValue.history.timewindowMs, this.timewindow.history = {...this.timewindow.history, ...{
interval: timewindowFormValue.history.interval, historyType: timewindowFormValue.history.historyType,
fixedTimewindow: timewindowFormValue.history.fixedTimewindow, timewindowMs: timewindowFormValue.history.timewindowMs,
quickInterval: timewindowFormValue.history.quickInterval, fixedTimewindow: timewindowFormValue.history.fixedTimewindow,
}}; quickInterval: timewindowFormValue.history.quickInterval,
interval: timewindowFormValue.history.interval,
}};
}
if (this.aggregation) { if (this.aggregation) {
this.timewindow.aggregation = { this.timewindow.aggregation = {
@ -437,6 +440,12 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit, O
if (this.timezone) { if (this.timezone) {
this.timewindow.timezone = timewindowFormValue.timezone; this.timewindow.timezone = timewindowFormValue.timezone;
} }
if (clearConfig) {
return clearTimewindowConfig(this.timewindow, this.quickIntervalOnly, this.historyOnly, this.aggregation, this.timezone);
} else {
return deepClone(this.timewindow);
}
} }
private updateTimewindowForm() { private updateTimewindowForm() {
@ -546,7 +555,6 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit, O
} }
openTimewindowConfig() { openTimewindowConfig() {
this.prepareTimewindowConfig();
this.dialog.open<TimewindowConfigDialogComponent, TimewindowConfigDialogData, Timewindow>( this.dialog.open<TimewindowConfigDialogComponent, TimewindowConfigDialogData, Timewindow>(
TimewindowConfigDialogComponent, { TimewindowConfigDialogComponent, {
autoFocus: false, autoFocus: false,
@ -555,7 +563,7 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit, O
data: { data: {
quickIntervalOnly: this.quickIntervalOnly, quickIntervalOnly: this.quickIntervalOnly,
aggregation: this.aggregation, aggregation: this.aggregation,
timewindow: deepClone(this.timewindow) timewindow: this.prepareTimewindowConfig(false)
} }
}).afterClosed() }).afterClosed()
.subscribe((res) => { .subscribe((res) => {
@ -568,12 +576,12 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit, O
} }
private updateTimewindowAdvancedParams() { private updateTimewindowAdvancedParams() {
this.realtimeDisableCustomInterval = this.timewindow.realtime.disableCustomInterval; this.realtimeDisableCustomInterval = this.timewindow.realtime?.disableCustomInterval;
this.realtimeDisableCustomGroupInterval = this.timewindow.realtime.disableCustomGroupInterval; this.realtimeDisableCustomGroupInterval = this.timewindow.realtime?.disableCustomGroupInterval;
this.historyDisableCustomInterval = this.timewindow.history.disableCustomInterval; this.historyDisableCustomInterval = this.timewindow.history?.disableCustomInterval;
this.historyDisableCustomGroupInterval = this.timewindow.history.disableCustomGroupInterval; this.historyDisableCustomGroupInterval = this.timewindow.history?.disableCustomGroupInterval;
if (this.timewindow.realtime.advancedParams) { if (this.timewindow.realtime?.advancedParams) {
this.realtimeAdvancedParams = this.timewindow.realtime.advancedParams; this.realtimeAdvancedParams = this.timewindow.realtime.advancedParams;
this.realtimeAllowedLastIntervals = this.timewindow.realtime.advancedParams.allowedLastIntervals; this.realtimeAllowedLastIntervals = this.timewindow.realtime.advancedParams.allowedLastIntervals;
this.realtimeAllowedQuickIntervals = this.timewindow.realtime.advancedParams.allowedQuickIntervals; this.realtimeAllowedQuickIntervals = this.timewindow.realtime.advancedParams.allowedQuickIntervals;
@ -582,7 +590,7 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit, O
this.realtimeAllowedLastIntervals = null; this.realtimeAllowedLastIntervals = null;
this.realtimeAllowedQuickIntervals = null; this.realtimeAllowedQuickIntervals = null;
} }
if (this.timewindow.history.advancedParams) { if (this.timewindow.history?.advancedParams) {
this.historyAdvancedParams = this.timewindow.history.advancedParams; this.historyAdvancedParams = this.timewindow.history.advancedParams;
this.historyAllowedLastIntervals = this.timewindow.history.advancedParams.allowedLastIntervals; this.historyAllowedLastIntervals = this.timewindow.history.advancedParams.allowedLastIntervals;
this.historyAllowedQuickIntervals = this.timewindow.history.advancedParams.allowedQuickIntervals; this.historyAllowedQuickIntervals = this.timewindow.history.advancedParams.allowedQuickIntervals;

3
ui-ngx/src/app/shared/components/time/timewindow.component.ts

@ -319,7 +319,8 @@ export class TimewindowComponent implements ControlValueAccessor, OnInit, OnChan
} }
writeValue(obj: Timewindow): void { writeValue(obj: Timewindow): void {
this.innerValue = initModelFromDefaultTimewindow(obj, this.quickIntervalOnly, this.historyOnly, this.timeService); this.innerValue = initModelFromDefaultTimewindow(obj, this.quickIntervalOnly, this.historyOnly, this.timeService,
this.aggregation);
this.timewindowDisabled = this.isTimewindowDisabled(); this.timewindowDisabled = this.isTimewindowDisabled();
if (this.onHistoryOnlyChanged()) { if (this.onHistoryOnlyChanged()) {
setTimeout(() => { setTimeout(() => {

140
ui-ngx/src/app/shared/models/time/time.models.ts

@ -15,7 +15,7 @@
/// ///
import { TimeService } from '@core/services/time.service'; import { TimeService } from '@core/services/time.service';
import { deepClone, isDefined, isDefinedAndNotNull, isNumeric, isUndefined } from '@app/core/utils'; import { deepClean, deepClone, isDefined, isDefinedAndNotNull, isNumeric, isUndefined } from '@app/core/utils';
import moment_ from 'moment'; import moment_ from 'moment';
import * as momentTz from 'moment-timezone'; import * as momentTz from 'moment-timezone';
import { IntervalType } from '@shared/models/telemetry/telemetry.models'; import { IntervalType } from '@shared/models/telemetry/telemetry.models';
@ -281,19 +281,12 @@ export const historyInterval = (timewindowMs: number): Timewindow => ({
export const defaultTimewindow = (timeService: TimeService): Timewindow => { export const defaultTimewindow = (timeService: TimeService): Timewindow => {
const currentTime = moment().valueOf(); const currentTime = moment().valueOf();
return { return {
displayValue: '',
hideAggregation: false,
hideAggInterval: false,
hideTimezone: false,
selectedTab: TimewindowType.REALTIME, selectedTab: TimewindowType.REALTIME,
realtime: { realtime: {
realtimeType: RealtimeWindowType.LAST_INTERVAL, realtimeType: RealtimeWindowType.LAST_INTERVAL,
interval: SECOND, interval: SECOND,
timewindowMs: MINUTE, timewindowMs: MINUTE,
quickInterval: QuickTimeInterval.CURRENT_DAY, quickInterval: QuickTimeInterval.CURRENT_DAY,
hideInterval: false,
hideLastInterval: false,
hideQuickInterval: false
}, },
history: { history: {
historyType: HistoryWindowType.LAST_INTERVAL, historyType: HistoryWindowType.LAST_INTERVAL,
@ -304,10 +297,6 @@ export const defaultTimewindow = (timeService: TimeService): Timewindow => {
endTimeMs: currentTime endTimeMs: currentTime
}, },
quickInterval: QuickTimeInterval.CURRENT_DAY, quickInterval: QuickTimeInterval.CURRENT_DAY,
hideInterval: false,
hideLastInterval: false,
hideFixedInterval: false,
hideQuickInterval: false
}, },
aggregation: { aggregation: {
type: AggregationType.AVG, type: AggregationType.AVG,
@ -325,40 +314,47 @@ const getTimewindowType = (timewindow: Timewindow): TimewindowType => {
}; };
export const initModelFromDefaultTimewindow = (value: Timewindow, quickIntervalOnly: boolean, export const initModelFromDefaultTimewindow = (value: Timewindow, quickIntervalOnly: boolean,
historyOnly: boolean, timeService: TimeService): Timewindow => { historyOnly: boolean, timeService: TimeService, hasAggregation: boolean): Timewindow => {
const model = defaultTimewindow(timeService); const model = defaultTimewindow(timeService);
if (value) { if (value) {
if (value.allowedAggTypes?.length) { if (value.allowedAggTypes?.length) {
model.allowedAggTypes = value.allowedAggTypes; model.allowedAggTypes = value.allowedAggTypes;
} }
model.hideAggregation = value.hideAggregation; if (value.hideAggregation) {
model.hideAggInterval = value.hideAggInterval; model.hideAggregation = value.hideAggregation;
model.hideTimezone = value.hideTimezone; }
if (value.hideAggInterval) {
model.hideAggInterval = value.hideAggInterval;
}
if (value.hideTimezone) {
model.hideTimezone = value.hideTimezone;
}
model.selectedTab = getTimewindowType(value); model.selectedTab = getTimewindowType(value);
// for backward compatibility // for backward compatibility
if (isDefinedAndNotNull((value as any).hideInterval)) { if ((value as any).hideInterval) {
model.realtime.hideInterval = (value as any).hideInterval; model.realtime.hideInterval = (value as any).hideInterval;
model.history.hideInterval = (value as any).hideInterval; model.history.hideInterval = (value as any).hideInterval;
delete (value as any).hideInterval; delete (value as any).hideInterval;
} }
if (isDefinedAndNotNull((value as any).hideLastInterval)) { if ((value as any).hideLastInterval) {
model.realtime.hideLastInterval = (value as any).hideLastInterval; model.realtime.hideLastInterval = (value as any).hideLastInterval;
delete (value as any).hideLastInterval; delete (value as any).hideLastInterval;
} }
if (isDefinedAndNotNull((value as any).hideQuickInterval)) { if ((value as any).hideQuickInterval) {
model.realtime.hideQuickInterval = (value as any).hideQuickInterval; model.realtime.hideQuickInterval = (value as any).hideQuickInterval;
delete (value as any).hideQuickInterval; delete (value as any).hideQuickInterval;
} }
if (isDefined(value.realtime)) { if (isDefined(value.realtime)) {
if (isDefinedAndNotNull(value.realtime.hideInterval)) { if (value.realtime.hideInterval) {
model.realtime.hideInterval = value.realtime.hideInterval; model.realtime.hideInterval = value.realtime.hideInterval;
} }
if (isDefinedAndNotNull(value.realtime.hideLastInterval)) { if (value.realtime.hideLastInterval) {
model.realtime.hideLastInterval = value.realtime.hideLastInterval; model.realtime.hideLastInterval = value.realtime.hideLastInterval;
} }
if (isDefinedAndNotNull(value.realtime.hideQuickInterval)) { if (value.realtime.hideQuickInterval) {
model.realtime.hideQuickInterval = value.realtime.hideQuickInterval; model.realtime.hideQuickInterval = value.realtime.hideQuickInterval;
} }
if (value.realtime.disableCustomInterval) { if (value.realtime.disableCustomInterval) {
@ -392,16 +388,16 @@ export const initModelFromDefaultTimewindow = (value: Timewindow, quickIntervalO
} }
} }
if (isDefined(value.history)) { if (isDefined(value.history)) {
if (isDefinedAndNotNull(value.history.hideInterval)) { if (value.history.hideInterval) {
model.history.hideInterval = value.history.hideInterval; model.history.hideInterval = value.history.hideInterval;
} }
if (isDefinedAndNotNull(value.history.hideLastInterval)) { if (value.history.hideLastInterval) {
model.history.hideLastInterval = value.history.hideLastInterval; model.history.hideLastInterval = value.history.hideLastInterval;
} }
if (isDefinedAndNotNull(value.history.hideFixedInterval)) { if (value.history.hideFixedInterval) {
model.history.hideFixedInterval = value.history.hideFixedInterval; model.history.hideFixedInterval = value.history.hideFixedInterval;
} }
if (isDefinedAndNotNull(value.history.hideQuickInterval)) { if (value.history.hideQuickInterval) {
model.history.hideQuickInterval = value.history.hideQuickInterval; model.history.hideQuickInterval = value.history.hideQuickInterval;
} }
if (value.history.disableCustomInterval) { if (value.history.disableCustomInterval) {
@ -450,7 +446,9 @@ export const initModelFromDefaultTimewindow = (value: Timewindow, quickIntervalO
} }
model.aggregation.limit = value.aggregation.limit || Math.floor(timeService.getMaxDatapointsLimit() / 2); model.aggregation.limit = value.aggregation.limit || Math.floor(timeService.getMaxDatapointsLimit() / 2);
} }
model.timezone = value.timezone; if (value.timezone) {
model.timezone = value.timezone;
}
} }
if (quickIntervalOnly) { if (quickIntervalOnly) {
model.realtime.realtimeType = RealtimeWindowType.INTERVAL; model.realtime.realtimeType = RealtimeWindowType.INTERVAL;
@ -458,7 +456,7 @@ export const initModelFromDefaultTimewindow = (value: Timewindow, quickIntervalO
if (historyOnly) { if (historyOnly) {
model.selectedTab = TimewindowType.HISTORY; model.selectedTab = TimewindowType.HISTORY;
} }
return model; return clearTimewindowConfig(model, quickIntervalOnly, historyOnly, hasAggregation);
}; };
export const toHistoryTimewindow = (timewindow: Timewindow, startTimeMs: number, endTimeMs: number, export const toHistoryTimewindow = (timewindow: Timewindow, startTimeMs: number, endTimeMs: number,
@ -1098,19 +1096,91 @@ export const cloneSelectedTimewindow = (timewindow: Timewindow): Timewindow => {
if (timewindow.allowedAggTypes?.length) { if (timewindow.allowedAggTypes?.length) {
cloned.allowedAggTypes = timewindow.allowedAggTypes; cloned.allowedAggTypes = timewindow.allowedAggTypes;
} }
cloned.hideAggregation = timewindow.hideAggregation || false; if (timewindow.hideAggregation) {
cloned.hideAggInterval = timewindow.hideAggInterval || false; cloned.hideAggregation = timewindow.hideAggregation;
cloned.hideTimezone = timewindow.hideTimezone || false; }
if (timewindow.hideAggInterval) {
cloned.hideAggInterval = timewindow.hideAggInterval;
}
if (timewindow.hideTimezone) {
cloned.hideTimezone = timewindow.hideTimezone;
}
if (isDefined(timewindow.selectedTab)) { if (isDefined(timewindow.selectedTab)) {
cloned.selectedTab = timewindow.selectedTab; cloned.selectedTab = timewindow.selectedTab;
} }
cloned.realtime = deepClone(timewindow.realtime); if (isDefined(timewindow.realtime)) {
cloned.history = deepClone(timewindow.history); cloned.realtime = deepClone(timewindow.realtime);
cloned.aggregation = deepClone(timewindow.aggregation); }
cloned.timezone = timewindow.timezone; if (isDefined(timewindow.history)) {
cloned.history = deepClone(timewindow.history);
}
if (isDefined(timewindow.aggregation)) {
cloned.aggregation = deepClone(timewindow.aggregation);
}
if (timewindow.timezone) {
cloned.timezone = timewindow.timezone;
}
return cloned; return cloned;
}; };
export const clearTimewindowConfig = (timewindow: Timewindow, quickIntervalOnly: boolean,
historyOnly: boolean, hasAggregation: boolean, hasTimezone = true): Timewindow => {
if (timewindow.selectedTab === TimewindowType.REALTIME) {
if (quickIntervalOnly || timewindow.realtime.realtimeType === RealtimeWindowType.INTERVAL) {
delete timewindow.realtime.timewindowMs;
} else {
delete timewindow.realtime.quickInterval;
}
delete timewindow.history?.historyType;
delete timewindow.history?.timewindowMs;
delete timewindow.history?.fixedTimewindow;
delete timewindow.history?.quickInterval;
delete timewindow.history?.interval;
if (!hasAggregation) {
delete timewindow.realtime.interval;
}
} else {
if (timewindow.history.historyType === HistoryWindowType.LAST_INTERVAL) {
delete timewindow.history.fixedTimewindow;
delete timewindow.history.quickInterval;
} else if (timewindow.history.historyType === HistoryWindowType.FIXED) {
delete timewindow.history.timewindowMs;
delete timewindow.history.quickInterval;
} else if (timewindow.history.historyType === HistoryWindowType.INTERVAL) {
delete timewindow.history.timewindowMs;
delete timewindow.history.fixedTimewindow;
} else {
delete timewindow.history.timewindowMs;
delete timewindow.history.fixedTimewindow;
delete timewindow.history.quickInterval;
}
delete timewindow.realtime?.realtimeType;
delete timewindow.realtime?.timewindowMs;
delete timewindow.realtime?.quickInterval;
delete timewindow.realtime?.interval;
if (!hasAggregation) {
delete timewindow.history.interval;
}
}
if (!hasAggregation) {
delete timewindow.aggregation;
}
if (historyOnly) {
delete timewindow.realtime;
}
if (!hasTimezone) {
delete timewindow.timezone;
}
return deepClean(timewindow);
};
export interface TimeInterval { export interface TimeInterval {
name: string; name: string;
translateParams: {[key: string]: any}; translateParams: {[key: string]: any};

8
ui-ngx/src/app/shared/models/widget.models.ts

@ -489,6 +489,14 @@ export const targetDeviceValid = (targetDevice?: TargetDevice): boolean =>
((targetDevice.type === TargetDeviceType.device && !!targetDevice.deviceId) || ((targetDevice.type === TargetDeviceType.device && !!targetDevice.deviceId) ||
(targetDevice.type === TargetDeviceType.entity && !!targetDevice.entityAliasId)); (targetDevice.type === TargetDeviceType.entity && !!targetDevice.entityAliasId));
export const widgetTypeHasTimewindow = (type: widgetType): boolean => {
return type === widgetType.timeseries || type === widgetType.alarm;
}
export const widgetTypeCanHaveTimewindow = (type: widgetType): boolean => {
return widgetTypeHasTimewindow(type) || type === widgetType.latest;
}
export const datasourcesHasAggregation = (datasources?: Array<Datasource>): boolean => { export const datasourcesHasAggregation = (datasources?: Array<Datasource>): boolean => {
if (datasources) { if (datasources) {
const foundDatasource = datasources.find(datasource => { const foundDatasource = datasources.find(datasource => {

67
ui-ngx/src/app/shared/models/widget/maps/map-model.definition.ts

@ -17,13 +17,18 @@
import { EntityAliases, EntityAliasInfo, getEntityAliasId } from '@shared/models/alias.models'; import { EntityAliases, EntityAliasInfo, getEntityAliasId } from '@shared/models/alias.models';
import { FilterInfo, Filters, getFilterId } from '@shared/models/query/query.models'; import { FilterInfo, Filters, getFilterId } from '@shared/models/query/query.models';
import { Dashboard } from '@shared/models/dashboard.models'; import { Dashboard } from '@shared/models/dashboard.models';
import { Datasource, DatasourceType, Widget } from '@shared/models/widget.models'; import { DataKey, Datasource, datasourcesHasAggregation, DatasourceType, Widget } from '@shared/models/widget.models';
import { import {
additionalMapDataSourcesToDatasources,
BaseMapSettings, BaseMapSettings,
CirclesDataLayerSettings,
MapDataLayerSettings, MapDataLayerSettings,
MapDataLayerType,
MapDataSourceSettings, MapDataSourceSettings,
mapDataSourceSettingsToDatasource, mapDataSourceSettingsToDatasource,
MapType MapType,
MarkersDataLayerSettings,
PolygonsDataLayerSettings
} from '@shared/models/widget/maps/map.models'; } from '@shared/models/widget/maps/map.models';
import { WidgetModelDefinition } from '@shared/models/widget/widget-model.definition'; import { WidgetModelDefinition } from '@shared/models/widget/widget-model.definition';
@ -124,6 +129,27 @@ export const MapModelDefinition: WidgetModelDefinition<MapDatasourcesInfo> = {
datasources.push(...getMapDataLayersDatasources(settings.additionalDataSources)); datasources.push(...getMapDataLayersDatasources(settings.additionalDataSources));
} }
return datasources; return datasources;
},
hasTimewindow(widget: Widget): boolean {
const settings: BaseMapSettings = widget.config.settings as BaseMapSettings;
if (settings.trips?.length) {
return true;
} else {
const datasources: Datasource[] = [];
if (settings.markers?.length) {
datasources.push(...getMapLatestDataLayersDatasources(settings.markers, 'markers'));
}
if (settings.polygons?.length) {
datasources.push(...getMapLatestDataLayersDatasources(settings.polygons, 'polygons'));
}
if (settings.circles?.length) {
datasources.push(...getMapLatestDataLayersDatasources(settings.circles, 'circles'));
}
if (settings.additionalDataSources?.length) {
datasources.push(...additionalMapDataSourcesToDatasources(settings.additionalDataSources));
}
return datasourcesHasAggregation(datasources);
}
} }
}; };
@ -223,3 +249,40 @@ const getMapDataLayersDatasources = (settings: MapDataLayerSettings[] | MapDataS
}); });
return datasources; return datasources;
}; };
const getMapLatestDataLayersDatasources = (settings: MapDataLayerSettings[],
dataLayerType: MapDataLayerType): Datasource[] => {
const datasources: Datasource[] = [];
settings.forEach((dsSettings) => {
const dataKeys: DataKey[] = getMapLatestDataLayerDatasourceDataKeys(dsSettings, dataLayerType);
const datasource: Datasource = mapDataSourceSettingsToDatasource(dsSettings);
datasource.dataKeys.push(...dataKeys);
datasources.push(datasource);
if ((dsSettings).additionalDataSources?.length) {
(dsSettings).additionalDataSources.forEach((ds) => {
const additionalDatasource: Datasource = mapDataSourceSettingsToDatasource(ds);
additionalDatasource.dataKeys.push(...dataKeys);
datasources.push(additionalDatasource);
});
}
});
return datasources;
};
const getMapLatestDataLayerDatasourceDataKeys = (settings: MapDataLayerSettings,
dataLayerType: MapDataLayerType): DataKey[] => {
const dataKeys = settings.additionalDataKeys || [];
switch (dataLayerType) {
case 'markers':
const markersSettings = settings as MarkersDataLayerSettings;
dataKeys.push(markersSettings.xKey, markersSettings.yKey);
break;
case 'polygons':
dataKeys.push((settings as PolygonsDataLayerSettings).polygonKey);
break;
case 'circles':
dataKeys.push((settings as CirclesDataLayerSettings).circleKey);
break;
}
return dataKeys;
};

1
ui-ngx/src/app/shared/models/widget/widget-model.definition.ts

@ -25,6 +25,7 @@ export interface WidgetModelDefinition<T = any> {
prepareExportInfo(dashboard: Dashboard, widget: Widget): T; prepareExportInfo(dashboard: Dashboard, widget: Widget): T;
updateFromExportInfo(widget: Widget, entityAliases: EntityAliases, filters: Filters, info: T): void; updateFromExportInfo(widget: Widget, entityAliases: EntityAliases, filters: Filters, info: T): void;
datasources(widget: Widget): Datasource[]; datasources(widget: Widget): Datasource[];
hasTimewindow(widget: Widget): boolean;
} }
const widgetModelRegistry: WidgetModelDefinition[] = [ const widgetModelRegistry: WidgetModelDefinition[] = [

Loading…
Cancel
Save