|
|
|
@ -36,13 +36,15 @@ import { |
|
|
|
Validator |
|
|
|
} from '@angular/forms'; |
|
|
|
import { |
|
|
|
checkLatestDataKeys, |
|
|
|
defaultTimeSeriesChartYAxisSettings, |
|
|
|
getNextTimeSeriesYAxisId, |
|
|
|
TimeSeriesChartYAxes, |
|
|
|
TimeSeriesChartYAxisId, |
|
|
|
TimeSeriesChartYAxisSettings, |
|
|
|
timeSeriesChartYAxisValid, |
|
|
|
timeSeriesChartYAxisValidator |
|
|
|
timeSeriesChartYAxisValidator, |
|
|
|
updateLatestDataKeys |
|
|
|
} from '@home/components/widget/lib/chart/time-series-chart.models'; |
|
|
|
import { mergeDeep } from '@core/utils'; |
|
|
|
import { CdkDragDrop } from '@angular/cdk/drag-drop'; |
|
|
|
@ -50,7 +52,7 @@ import { coerceBoolean } from '@shared/decorators/coercion'; |
|
|
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; |
|
|
|
import { IAliasController } from '@app/core/public-api'; |
|
|
|
import { DataKeysCallbacks } from '@home/components/widget/lib/settings/common/key/data-keys.component.models'; |
|
|
|
import { DataKey, DataKeyType, Datasource, ValueSourceConfig, ValueSourceType } from '@app/shared/public-api'; |
|
|
|
import { Datasource } from '@app/shared/public-api'; |
|
|
|
|
|
|
|
@Component({ |
|
|
|
selector: 'tb-time-series-chart-y-axes-panel', |
|
|
|
@ -126,7 +128,7 @@ export class TimeSeriesChartYAxesPanelComponent implements ControlValueAccessor, |
|
|
|
for (const axis of axes) { |
|
|
|
yAxes[axis.id] = axis; |
|
|
|
} |
|
|
|
this.updateLatestDataKeys(Object.values(yAxes)); |
|
|
|
updateLatestDataKeys(Object.values(yAxes), this.datasource, this.dataKeyCallbacks); |
|
|
|
this.propagateChange(yAxes); |
|
|
|
} |
|
|
|
); |
|
|
|
@ -149,7 +151,7 @@ export class TimeSeriesChartYAxesPanelComponent implements ControlValueAccessor, |
|
|
|
} |
|
|
|
|
|
|
|
writeValue(value: TimeSeriesChartYAxes | undefined): void { |
|
|
|
const yAxes: TimeSeriesChartYAxes = this.checkLatestDataKeys(value || {}); |
|
|
|
const yAxes: TimeSeriesChartYAxes = checkLatestDataKeys(value || {}, this.datasource); |
|
|
|
if (!yAxes.default) { |
|
|
|
yAxes.default = mergeDeep({} as TimeSeriesChartYAxisSettings, defaultTimeSeriesChartYAxisSettings, |
|
|
|
{id: 'default', order: 0} as TimeSeriesChartYAxisSettings); |
|
|
|
@ -196,8 +198,6 @@ export class TimeSeriesChartYAxesPanelComponent implements ControlValueAccessor, |
|
|
|
const axes: TimeSeriesChartYAxisSettings[] = this.yAxesFormGroup.get('axes').value; |
|
|
|
axis.id = getNextTimeSeriesYAxisId(axes); |
|
|
|
axis.order = axes.length; |
|
|
|
axis.min = this.normalizeAxisLimit(axis.min); |
|
|
|
axis.max = this.normalizeAxisLimit(axis.max); |
|
|
|
const axesArray = this.yAxesFormGroup.get('axes') as UntypedFormArray; |
|
|
|
const axisControl = this.fb.control(axis, [timeSeriesChartYAxisValidator]); |
|
|
|
axesArray.push(axisControl); |
|
|
|
@ -211,100 +211,4 @@ export class TimeSeriesChartYAxesPanelComponent implements ControlValueAccessor, |
|
|
|
return this.fb.array(axesControls); |
|
|
|
} |
|
|
|
|
|
|
|
private checkLatestDataKeys(yAxes: TimeSeriesChartYAxes): TimeSeriesChartYAxes { |
|
|
|
const latestKeys = this.datasource?.latestDataKeys || []; |
|
|
|
const result: TimeSeriesChartYAxes = {}; |
|
|
|
|
|
|
|
for (const [id, axis] of Object.entries(yAxes)) { |
|
|
|
axis.min = this.normalizeAxisLimit(axis.min); |
|
|
|
axis.max = this.normalizeAxisLimit(axis.max); |
|
|
|
const minCfg = axis.min; |
|
|
|
const maxCfg = axis.max; |
|
|
|
|
|
|
|
const minValid = !!minCfg && ( |
|
|
|
minCfg.type !== ValueSourceType.latestKey || |
|
|
|
latestKeys.some(k => this.isYAxisKey(k, minCfg)) |
|
|
|
); |
|
|
|
|
|
|
|
const maxValid = !!maxCfg && ( |
|
|
|
maxCfg.type !== ValueSourceType.latestKey || |
|
|
|
latestKeys.some(k => this.isYAxisKey(k, maxCfg)) |
|
|
|
); |
|
|
|
|
|
|
|
if (minValid && maxValid) { |
|
|
|
result[id] = axis; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return result; |
|
|
|
} |
|
|
|
|
|
|
|
private updateLatestDataKeys(yAxes: TimeSeriesChartYAxisSettings[]) { |
|
|
|
if (this.datasource) { |
|
|
|
let latestKeys = this.datasource.latestDataKeys; |
|
|
|
if (!latestKeys) { |
|
|
|
latestKeys = []; |
|
|
|
this.datasource.latestDataKeys = latestKeys; |
|
|
|
} |
|
|
|
const existingYAxisKeys = latestKeys.filter(k => k.settings?.__yAxisMinKey === true || k.settings?.__yAxisMaxKey === true); |
|
|
|
const foundYAxisKeys: DataKey[] = []; |
|
|
|
|
|
|
|
for(const yAxis of yAxes) { |
|
|
|
const min = yAxis.min as ValueSourceConfig; |
|
|
|
const max = yAxis.max as ValueSourceConfig; |
|
|
|
if (min.type === ValueSourceType.latestKey) { |
|
|
|
const found = existingYAxisKeys.find(k => this.isYAxisKey(k, min)); |
|
|
|
if (!found) { |
|
|
|
const newKey = this.dataKeyCallbacks.generateDataKey(min.latestKey, min.latestKeyType, |
|
|
|
null, true, null); |
|
|
|
newKey.settings.__yAxisMinKey = true; |
|
|
|
latestKeys.push(newKey); |
|
|
|
} else if (foundYAxisKeys.indexOf(found) === -1) { |
|
|
|
foundYAxisKeys.push(found); |
|
|
|
} |
|
|
|
} |
|
|
|
if (max.type === ValueSourceType.latestKey) { |
|
|
|
const found = existingYAxisKeys.find(k => this.isYAxisKey(k, max)); |
|
|
|
if (!found) { |
|
|
|
const newKey = this.dataKeyCallbacks.generateDataKey(max.latestKey, max.latestKeyType, |
|
|
|
null, true, null); |
|
|
|
newKey.settings.__yAxisMaxKey = true; |
|
|
|
latestKeys.push(newKey); |
|
|
|
} else if (foundYAxisKeys.indexOf(found) === -1) { |
|
|
|
foundYAxisKeys.push(found); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
const toRemove = existingYAxisKeys.filter(k => foundYAxisKeys.indexOf(k) === -1); |
|
|
|
for (const key of toRemove) { |
|
|
|
const index = latestKeys.indexOf(key); |
|
|
|
if (index > -1) { |
|
|
|
latestKeys.splice(index, 1); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private isYAxisKey(d: DataKey, limit: ValueSourceConfig): boolean { |
|
|
|
return (d.type === DataKeyType.function && d.label === limit.latestKey) || |
|
|
|
(d.type !== DataKeyType.function && d.name === limit.latestKey && |
|
|
|
d.type === limit.latestKeyType); |
|
|
|
} |
|
|
|
|
|
|
|
private normalizeAxisLimit(limit: string | number | ValueSourceConfig): ValueSourceConfig { |
|
|
|
if (!limit) { |
|
|
|
return { |
|
|
|
type: ValueSourceType.constant, |
|
|
|
value: null, |
|
|
|
entityAlias: null |
|
|
|
}; |
|
|
|
} else if (typeof limit === 'number' || typeof limit === 'string') { |
|
|
|
return { |
|
|
|
type: ValueSourceType.constant, |
|
|
|
value: Number(limit), |
|
|
|
entityAlias: null |
|
|
|
}; |
|
|
|
} |
|
|
|
return limit; |
|
|
|
} |
|
|
|
} |
|
|
|
|