diff --git a/ui-ngx/src/app/core/utils.ts b/ui-ngx/src/app/core/utils.ts index 353727e006..d0bd9ae484 100644 --- a/ui-ngx/src/app/core/utils.ts +++ b/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 { CompiledTbFunction, - compileTbFunction, GenericFunction, + compileTbFunction, + GenericFunction, isNotEmptyTbFunction, TbFunction } from '@shared/models/js-function.models'; @@ -773,6 +774,33 @@ export function deepTrim(obj: T): T { }, (Array.isArray(obj) ? [] : {}) as T); } +export function deepClean | 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 { if (isUndefined(length) || length == null) { length = 1; diff --git a/ui-ngx/src/app/shared/components/time/timewindow-config-dialog.component.ts b/ui-ngx/src/app/shared/components/time/timewindow-config-dialog.component.ts index 07e532cac0..33a9d44cf3 100644 --- a/ui-ngx/src/app/shared/components/time/timewindow-config-dialog.component.ts +++ b/ui-ngx/src/app/shared/components/time/timewindow-config-dialog.component.ts @@ -36,7 +36,7 @@ import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { TimeService } from '@core/services/time.service'; -import { deepClone, isDefined, isDefinedAndNotNull, isObject, mergeDeep } from '@core/utils'; +import { deepClean, deepClone, isDefined, isDefinedAndNotNull, isEmpty, mergeDeepIgnoreArray } from '@core/utils'; import { ToggleHeaderOption } from '@shared/components/toggle-header.component'; import { TranslateService } from '@ngx-translate/core'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; @@ -423,7 +423,7 @@ export class TimewindowConfigDialogComponent extends PageComponent implements On update() { const timewindowFormValue = this.timewindowForm.getRawValue(); - this.timewindow = mergeDeep(this.timewindow, timewindowFormValue); + this.timewindow = mergeDeepIgnoreArray(this.timewindow, timewindowFormValue); const realtimeConfigurableLastIntervalsAvailable = !(timewindowFormValue.hideAggInterval && (timewindowFormValue.realtime.hideInterval || timewindowFormValue.realtime.hideLastInterval)); @@ -434,62 +434,41 @@ export class TimewindowConfigDialogComponent extends PageComponent implements On const historyConfigurableQuickIntervalsAvailable = !(timewindowFormValue.hideAggInterval && (timewindowFormValue.history.hideInterval || timewindowFormValue.history.hideQuickInterval)); - if (realtimeConfigurableLastIntervalsAvailable && timewindowFormValue.realtime.advancedParams.allowedLastIntervals?.length) { - this.timewindow.realtime.advancedParams.allowedLastIntervals = timewindowFormValue.realtime.advancedParams.allowedLastIntervals; - } else { + if (!realtimeConfigurableLastIntervalsAvailable) { delete this.timewindow.realtime.advancedParams.allowedLastIntervals; } - if (realtimeConfigurableQuickIntervalsAvailable && timewindowFormValue.realtime.advancedParams.allowedQuickIntervals?.length) { - this.timewindow.realtime.advancedParams.allowedQuickIntervals = timewindowFormValue.realtime.advancedParams.allowedQuickIntervals; - } else { + if (!realtimeConfigurableQuickIntervalsAvailable) { delete this.timewindow.realtime.advancedParams.allowedQuickIntervals; } - if (realtimeConfigurableLastIntervalsAvailable && isObject(timewindowFormValue.realtime.advancedParams.lastAggIntervalsConfig) && - Object.keys(timewindowFormValue.realtime.advancedParams.lastAggIntervalsConfig).length) { + if (realtimeConfigurableLastIntervalsAvailable && !isEmpty(timewindowFormValue.realtime.advancedParams.lastAggIntervalsConfig)) { this.timewindow.realtime.advancedParams.lastAggIntervalsConfig = timewindowFormValue.realtime.advancedParams.lastAggIntervalsConfig; } else { delete this.timewindow.realtime.advancedParams.lastAggIntervalsConfig; } - if (realtimeConfigurableQuickIntervalsAvailable && isObject(timewindowFormValue.realtime.advancedParams.quickAggIntervalsConfig) && - Object.keys(timewindowFormValue.realtime.advancedParams.quickAggIntervalsConfig).length) { + if (realtimeConfigurableQuickIntervalsAvailable && !isEmpty(timewindowFormValue.realtime.advancedParams.quickAggIntervalsConfig)) { this.timewindow.realtime.advancedParams.quickAggIntervalsConfig = timewindowFormValue.realtime.advancedParams.quickAggIntervalsConfig; } else { delete this.timewindow.realtime.advancedParams.quickAggIntervalsConfig; } - if (historyConfigurableLastIntervalsAvailable && timewindowFormValue.history.advancedParams.allowedLastIntervals?.length) { - this.timewindow.history.advancedParams.allowedLastIntervals = timewindowFormValue.history.advancedParams.allowedLastIntervals; - } else { + if (!historyConfigurableLastIntervalsAvailable) { delete this.timewindow.history.advancedParams.allowedLastIntervals; } - if (historyConfigurableQuickIntervalsAvailable && timewindowFormValue.history.advancedParams.allowedQuickIntervals?.length) { - this.timewindow.history.advancedParams.allowedQuickIntervals = timewindowFormValue.history.advancedParams.allowedQuickIntervals; - } else { + if (!historyConfigurableQuickIntervalsAvailable) { delete this.timewindow.history.advancedParams.allowedQuickIntervals; } - if (historyConfigurableLastIntervalsAvailable && isObject(timewindowFormValue.history.advancedParams.lastAggIntervalsConfig) && - Object.keys(timewindowFormValue.history.advancedParams.lastAggIntervalsConfig).length) { + if (historyConfigurableLastIntervalsAvailable && !isEmpty(timewindowFormValue.history.advancedParams.lastAggIntervalsConfig)) { this.timewindow.history.advancedParams.lastAggIntervalsConfig = timewindowFormValue.history.advancedParams.lastAggIntervalsConfig; } else { delete this.timewindow.history.advancedParams.lastAggIntervalsConfig; } - if (historyConfigurableQuickIntervalsAvailable && isObject(timewindowFormValue.history.advancedParams.quickAggIntervalsConfig) && - Object.keys(timewindowFormValue.history.advancedParams.quickAggIntervalsConfig).length) { + if (historyConfigurableQuickIntervalsAvailable && !isEmpty(timewindowFormValue.history.advancedParams.quickAggIntervalsConfig)) { this.timewindow.history.advancedParams.quickAggIntervalsConfig = timewindowFormValue.history.advancedParams.quickAggIntervalsConfig; } else { delete this.timewindow.history.advancedParams.quickAggIntervalsConfig; } - if (!Object.keys(this.timewindow.realtime.advancedParams).length) { - 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 { + if (timewindowFormValue.hideAggregation) { delete this.timewindow.allowedAggTypes; } @@ -541,7 +520,7 @@ export class TimewindowConfigDialogComponent extends PageComponent implements On if (!this.aggregation) { delete this.timewindow.aggregation; } - this.dialogRef.close(this.timewindow); + this.dialogRef.close(deepClean(this.timewindow)); } cancel() { diff --git a/ui-ngx/src/app/shared/components/time/timewindow-panel.component.ts b/ui-ngx/src/app/shared/components/time/timewindow-panel.component.ts index 9831ec0599..7c6445c6b2 100644 --- a/ui-ngx/src/app/shared/components/time/timewindow-panel.component.ts +++ b/ui-ngx/src/app/shared/components/time/timewindow-panel.component.ts @@ -382,8 +382,7 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit, O takeUntil(this.destroy$) ).subscribe(() => { this.prepareTimewindowConfig(); - this.clearTimewindowConfig(); - this.changeTimewindow.emit(this.timewindow); + this.changeTimewindow.emit(this.clearTimewindowConfig()); }); } } @@ -410,8 +409,7 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit, O update() { this.prepareTimewindowConfig(); - this.clearTimewindowConfig(); - this.result = this.timewindow; + this.result = this.clearTimewindowConfig(); this.overlayRef?.dispose(); } @@ -447,8 +445,8 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit, O } } - private clearTimewindowConfig() { - clearTimewindowConfig(this.timewindow, this.quickIntervalOnly, this.historyOnly, this.aggregation, this.timezone); + private clearTimewindowConfig(): Timewindow { + return clearTimewindowConfig(this.timewindow, this.quickIntervalOnly, this.historyOnly, this.aggregation, this.timezone); } private updateTimewindowForm() { diff --git a/ui-ngx/src/app/shared/models/time/time.models.ts b/ui-ngx/src/app/shared/models/time/time.models.ts index 7c53d93edf..cace546b19 100644 --- a/ui-ngx/src/app/shared/models/time/time.models.ts +++ b/ui-ngx/src/app/shared/models/time/time.models.ts @@ -15,12 +15,11 @@ /// import { TimeService } from '@core/services/time.service'; -import { deepClone, isDefined, isDefinedAndNotNull, isNumeric, isUndefined, isUndefinedOrNull } from '@app/core/utils'; +import { deepClean, deepClone, isDefined, isDefinedAndNotNull, isNumeric, isUndefined } from '@app/core/utils'; import moment_ from 'moment'; import * as momentTz from 'moment-timezone'; import { IntervalType } from '@shared/models/telemetry/telemetry.models'; import { FormGroup } from '@angular/forms'; -import { isEmpty } from 'lodash'; const moment = moment_; @@ -457,8 +456,7 @@ export const initModelFromDefaultTimewindow = (value: Timewindow, quickIntervalO if (historyOnly) { model.selectedTab = TimewindowType.HISTORY; } - clearTimewindowConfig(model, quickIntervalOnly, historyOnly, hasAggregation); - return model; + return clearTimewindowConfig(model, quickIntervalOnly, historyOnly, hasAggregation); }; export const toHistoryTimewindow = (timewindow: Timewindow, startTimeMs: number, endTimeMs: number, @@ -1173,17 +1171,14 @@ export const clearTimewindowConfig = (timewindow: Timewindow, quickIntervalOnly: delete timewindow.aggregation; } - if (isEmpty(timewindow.history)) { - delete timewindow.history; - } - if (historyOnly || isEmpty(timewindow.realtime)) { + if (historyOnly) { delete timewindow.realtime; } - if (!hasTimezone || isUndefinedOrNull(timewindow.timezone)) { + if (!hasTimezone) { delete timewindow.timezone; } - return timewindow; + return deepClean(timewindow); }; export interface TimeInterval {