Skip to content

Commit

Permalink
SNRGY-3651 chart widget: add field to select data source by entity group
Browse files Browse the repository at this point in the history
  • Loading branch information
gr-st committed Dec 6, 2024
1 parent 94a7da5 commit ee44037
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,23 @@

<form fxLayout="column" [formGroup]="form" *ngIf="ready">
<div *ngIf="showSource">
<h2>Choose a {{dataSourcePlaceholder}}</h2>
<mat-form-field appearance="outline" color="accent">
<mat-label>{{dataSourcePlaceholder}}</mat-label>
<h2>Choose a Data Source</h2>
<mat-form-field appearance="outline" color="accent">
<mat-label>Data Source Class</mat-label>
<mat-select #dataSourceClass formControlName="dataSourceClass">
<mat-option *ngFor="let entity of getSortedDataSourceClasses()" [value]="entity">
{{entity}}
</mat-option>
</mat-select>
<mat-error senergyError label="Data Source Class"></mat-error>
</mat-form-field>
<mat-form-field [class.cdk-visually-hidden]="!dataSourceClass.value" appearance="outline" color="accent">
<mat-label>{{getLabelFromCurrentDataSource()}}</mat-label>
<senergy-select-search [required]="true" [multiple]="true" [compareWith]="compare" formControlName="exports"
(selectionChange)="dataSourceChanged($event.value)" [options]="dataSourceOptions"
[getOptionViewValue]="getDataSourceName" >
(selectionChange)="dataSourceChanged($event.value)" [options]="currentDataSourceOptions"
[getOptionViewValue]="getDataSourceName">
</senergy-select-search>
<mat-error senergyError [label]="dataSourcePlaceholder"></mat-error>
<mat-error senergyError></mat-error>
</mat-form-field>
</div>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, EventEmitter, Input, OnChanges, OnInit, Output } from '@angular/core';
import {ChangeDetectorRef, Component, EventEmitter, Input, OnChanges, OnInit, Output} from '@angular/core';
import { AbstractControl, FormControl, FormGroup, ValidatorFn, Validators } from '@angular/forms';
import { catchError, concatMap, defaultIfEmpty, EMPTY, forkJoin, map, mergeMap, Observable, of, Subject, throwError } from 'rxjs';
import { DeviceGroupCriteriaModel, DeviceGroupModel } from 'src/app/modules/devices/device-groups/shared/device-groups.model';
Expand Down Expand Up @@ -58,6 +58,8 @@ export class DataSourceSelectorComponent implements OnInit {
timeRangeEnum = ChartsExportRangeTimeTypeEnum;
timeRangeTypes = [this.timeRangeEnum.Relative, this.timeRangeEnum.RelativeAhead, this.timeRangeEnum.Absolute];
dataSourceOptions: Map<string, ChartsExportMeasurementModel[] | DeviceInstanceModel[] | DeviceGroupModel[]> = new Map();
currentDataSourceOptions: ChartsExportMeasurementModel[] | DeviceInstanceModel[] | DeviceGroupModel[] = [];
currentDataSourceClass = '';
ready = false;
waitingForDataSourceChange = false;
exportList: ChartsExportMeasurementModel[] = [];
Expand Down Expand Up @@ -108,9 +110,9 @@ export class DataSourceSelectorComponent implements OnInit {
@Input() showTimeRange = true;
@Input() showSource = true;
@Output() updatedDataSourceConfig = new EventEmitter<DataSourceConfig>();
dataSourcePlaceholder = '';

constructor(
private cdref: ChangeDetectorRef,
private deviceTypeService: DeviceTypeService,
private conceptsService: ConceptsService,
private exportService: ExportService,
Expand All @@ -121,8 +123,6 @@ export class DataSourceSelectorComponent implements OnInit {
) {}

ngOnInit(): void {
// console.log(this.dataSourceConfig)
this.setDataSourcePlaceholder();
this.setupDataSources().pipe(
concatMap((_) => this.loadFieldOptions(this.dataSourceConfig?.exports || [])),
map((fieldOptions) => {
Expand All @@ -131,52 +131,28 @@ export class DataSourceSelectorComponent implements OnInit {
this.form.get('fieldOptions').patchValue(fieldOptions);
this.setupOutput();
this.setupGroupTypes();
// console.log(this.form)
this.form.controls['dataSourceClass'].valueChanges.subscribe((val: string) => {
this.updateCurrentDataSourceOptions(val);
});
})
).subscribe({
next: (_) => {
this.ready = true;
this.waitingForDataSourceChange = false;
},
error: (err) => {
console.log("Could not init: " + err);
console.log('Could not init: ' + err);
this.ready = true;
this.waitingForDataSourceChange = false;
}
});
}

setDataSourcePlaceholder() {
let seperatorNeeded = false;
if(this.showDevicesAsSource) {
this.dataSourcePlaceholder += 'Device';
seperatorNeeded = true;
}
if(this.showDeviceGroupsAsSource) {
if(seperatorNeeded) {
this.dataSourcePlaceholder += '/';
}
this.dataSourcePlaceholder += 'Device Group';
}

if(this.showExportsAsSource) {
if(seperatorNeeded) {
this.dataSourcePlaceholder += '/';
}
this.dataSourcePlaceholder += 'Export';
}

if(this.showLocationsAsSource) {
if(seperatorNeeded) {
this.dataSourcePlaceholder += '/';
}
this.dataSourcePlaceholder += 'Location';
}
}

initForm() {
this.form = new FormGroup({
exports: new FormControl(this.dataSourceConfig?.exports || []),
dataSourceClass: new FormControl(this.getDataSourceClassFromExports(this.dataSourceConfig?.exports) || '', Validators.required),
exports: new FormControl(this.dataSourceConfig?.exports || [], Validators.required),
timeRange: new FormGroup({
type: new FormControl(this.dataSourceConfig?.timeRange?.type || '', Validators.required),
start: new FormControl(this.dataSourceConfig?.timeRange?.start || ''),
Expand All @@ -192,6 +168,9 @@ export class DataSourceSelectorComponent implements OnInit {
fields: new FormControl(this.dataSourceConfig?.fields || []),
fieldOptions: new FormControl([])
});
setTimeout(() => {
this.currentDataSourceOptions = this.getDataSourceOptions(this.getDataSourceClassFromExports(this.dataSourceConfig?.exports)||'');
}, 0);
}

setupOutput() {
Expand Down Expand Up @@ -463,7 +442,7 @@ export class DataSourceSelectorComponent implements OnInit {
}
}),
catchError(err => {
console.log("could not get exports");
console.log('could not get exports');
console.log(err);
return throwError(() => err);
})
Expand All @@ -476,7 +455,7 @@ export class DataSourceSelectorComponent implements OnInit {
this.dataSourceOptions.set('Devices', devices.result);
}),
catchError(err => {
console.log("could not get devices");
console.log('could not get devices');
console.log(err);
return throwError(() => err);
})
Expand Down Expand Up @@ -515,7 +494,7 @@ export class DataSourceSelectorComponent implements OnInit {
return forkJoin(innerObs);
}),
catchError(err => {
console.log("could not get device group");
console.log('could not get device group');
console.log(err);
return throwError(() => err);
})
Expand All @@ -541,7 +520,7 @@ export class DataSourceSelectorComponent implements OnInit {
if(this.showLocationsAsSource) {
obs.push(this.getLocations());
}
obs.push(this.functionsService.getFunctions('', 9999, 0, 'name', 'asc').pipe(map(functions => this.functions = functions)))
obs.push(this.functionsService.getFunctions('', 9999, 0, 'name', 'asc').pipe(map(functions => this.functions = functions)));
if(obs.length === 0) {
obs.push(of(true));
}
Expand Down Expand Up @@ -572,7 +551,7 @@ export class DataSourceSelectorComponent implements OnInit {
}

filterSelectedFields(selectedDataSources: (ChartsExportMeasurementModel | DeviceInstanceModel | DeviceGroupModel)[]) {
/* Filter the selected fields depending on the current selection of the data source
/* Filter the selected fields depending on the current selection of the data source
*/
const selectedFields = JSON.parse(JSON.stringify(this.form.value['fields']));
const filteredFields: ChartsExportVAxesModel[] = [];
Expand Down Expand Up @@ -611,7 +590,7 @@ export class DataSourceSelectorComponent implements OnInit {
observables = observables.concat(this.updateDeviceFields(selectedElement as DeviceInstanceModel));
}
});


return forkJoin(observables).pipe(
defaultIfEmpty([]), // in case observables is empty
Expand All @@ -625,7 +604,7 @@ export class DataSourceSelectorComponent implements OnInit {
return options;
}),
catchError(err => {
console.log("could not load field options");
console.log('could not load field options');
console.log(err);
return throwError(() => err);
})
Expand Down Expand Up @@ -743,7 +722,7 @@ export class DataSourceSelectorComponent implements OnInit {
a.valueName === b.valueName);
const deviceMatch = (a.deviceId != null && b.deviceId != null &&
a.deviceId === b.deviceId &&
a.serviceId === b.serviceId &&
a.serviceId === b.serviceId &&
a.valuePath === b.valuePath);
const deviceGroupMatch = (a.deviceGroupId != null && b.deviceGroupId != null &&
a.deviceGroupId === b.deviceGroupId &&
Expand All @@ -757,4 +736,68 @@ export class DataSourceSelectorComponent implements OnInit {
getDataSourceName(x: any): string {
return x.display_name || x.name;
}

getSortedDataSourceClasses(): string[] {
let classes: string[] = [];
Array.from(this.dataSourceOptions.keys()).forEach(cl => {
const exports: any = this.dataSourceOptions.get(cl as string);
if (exports.length>0) {
classes.push(cl as string);
}
});
classes = classes.sort();
return classes;
}

getDataSourceOptions(entity: string): ChartsExportMeasurementModel[] | DeviceInstanceModel[] | DeviceGroupModel[] | [] {
const val = this.dataSourceOptions.get(entity);
if (val !== undefined) {
return val;
} else {
return [];
}
}

updateCurrentDataSourceOptions(dataSourceClass: string) {
if (dataSourceClass!== this.currentDataSourceClass) {
this.form.controls['exports'].reset([]);
}
this.currentDataSourceClass = dataSourceClass;
this.currentDataSourceOptions = this.getDataSourceOptions(dataSourceClass);
this.cdref.detectChanges();
}

getLabelFromCurrentDataSource(){
const val = this.form.controls['dataSourceClass'].value;
const dataSourceSingular: Map<string, string> = new Map([
['Device Groups', 'Device Group'],
['Devices', 'Device'],
['Exports', 'Export'],
['Locations', 'Location'],
]);
return dataSourceSingular.get(val) as string;
}

getDataSourceClassFromExports(exports: (ChartsExportMeasurementModel | DeviceInstanceModel | DeviceGroupModel)[] | undefined){
if (!exports){
return null;
}
const searchItem = exports[0];
for (const [key, values] of this.dataSourceOptions.entries()) {
if (this.getExportIDs(values).includes(searchItem.id)) {
return key;
}
}
return null;
}

getExportIDs(exportValues: (ChartsExportMeasurementModel | DeviceInstanceModel | DeviceGroupModel) []){
const ids: string[] = [];
exportValues.forEach(item => {
if ('id' in item) {
ids.push((item as any).id);
}
});
return ids;
}
}

0 comments on commit ee44037

Please sign in to comment.