UI: Maps - add color range type to color settings.
This commit is contained in:
parent
480e6a4935
commit
2d86e816f2
@ -15,15 +15,24 @@
|
|||||||
///
|
///
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DataLayerColorSettings, DataLayerColorType,
|
DataLayerColorSettings,
|
||||||
DataLayerPatternSettings, DataLayerPatternType,
|
DataLayerColorType,
|
||||||
MapDataLayerSettings, MapDataLayerType, mapDataSourceSettingsToDatasource,
|
DataLayerPatternSettings,
|
||||||
MapStringFunction, MapType,
|
DataLayerPatternType,
|
||||||
|
MapDataLayerSettings,
|
||||||
|
MapDataLayerType,
|
||||||
|
mapDataSourceSettingsToDatasource,
|
||||||
|
MapStringFunction,
|
||||||
|
MapType,
|
||||||
TbMapDatasource
|
TbMapDatasource
|
||||||
} from '@shared/models/widget/maps/map.models';
|
} from '@shared/models/widget/maps/map.models';
|
||||||
import {
|
import {
|
||||||
createLabelFromPattern,
|
createLabelFromPattern,
|
||||||
guid, isDefined,
|
guid,
|
||||||
|
isDefined,
|
||||||
|
isDefinedAndNotNull,
|
||||||
|
isNumber,
|
||||||
|
isNumeric,
|
||||||
mergeDeepIgnoreArray,
|
mergeDeepIgnoreArray,
|
||||||
parseTbFunction,
|
parseTbFunction,
|
||||||
safeExecuteTbFunction
|
safeExecuteTbFunction
|
||||||
@ -32,10 +41,11 @@ import L from 'leaflet';
|
|||||||
import { CompiledTbFunction } from '@shared/models/js-function.models';
|
import { CompiledTbFunction } from '@shared/models/js-function.models';
|
||||||
import { forkJoin, Observable, of } from 'rxjs';
|
import { forkJoin, Observable, of } from 'rxjs';
|
||||||
import { map } from 'rxjs/operators';
|
import { map } from 'rxjs/operators';
|
||||||
import { FormattedData } from '@shared/models/widget.models';
|
import { DataKey, FormattedData } from '@shared/models/widget.models';
|
||||||
import { CustomTranslatePipe } from '@shared/pipe/custom-translate.pipe';
|
import { CustomTranslatePipe } from '@shared/pipe/custom-translate.pipe';
|
||||||
import { TbMap } from '@home/components/widget/lib/maps/map';
|
import { TbMap } from '@home/components/widget/lib/maps/map';
|
||||||
import { WidgetContext } from '@home/models/widget-component.models';
|
import { WidgetContext } from '@home/models/widget-component.models';
|
||||||
|
import { ColorRange } from '@shared/models/widget-settings.models';
|
||||||
|
|
||||||
export class DataLayerPatternProcessor {
|
export class DataLayerPatternProcessor {
|
||||||
|
|
||||||
@ -77,22 +87,26 @@ export class DataLayerColorProcessor {
|
|||||||
|
|
||||||
private colorFunction: CompiledTbFunction<MapStringFunction>;
|
private colorFunction: CompiledTbFunction<MapStringFunction>;
|
||||||
private color: string;
|
private color: string;
|
||||||
|
private rangeKey: DataKey;
|
||||||
|
private range: ColorRange[];
|
||||||
|
|
||||||
constructor(private dataLayer: TbMapDataLayer,
|
constructor(private dataLayer: TbMapDataLayer,
|
||||||
private settings: DataLayerColorSettings) {}
|
private settings: DataLayerColorSettings) {}
|
||||||
|
|
||||||
public setup(): Observable<void> {
|
public setup(): Observable<void> {
|
||||||
this.color = this.settings.color;
|
this.color = this.settings.color;
|
||||||
if (this.settings.type === DataLayerColorType.function) {
|
if (this.settings.type === DataLayerColorType.range) {
|
||||||
|
this.rangeKey = this.settings.rangeKey;
|
||||||
|
this.range = this.settings.range;
|
||||||
|
} else if (this.settings.type === DataLayerColorType.function) {
|
||||||
return parseTbFunction<MapStringFunction>(this.dataLayer.getCtx().http, this.settings.colorFunction, ['data', 'dsData']).pipe(
|
return parseTbFunction<MapStringFunction>(this.dataLayer.getCtx().http, this.settings.colorFunction, ['data', 'dsData']).pipe(
|
||||||
map((parsed) => {
|
map((parsed) => {
|
||||||
this.colorFunction = parsed;
|
this.colorFunction = parsed;
|
||||||
return null;
|
return null;
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
} else {
|
|
||||||
return of(null)
|
|
||||||
}
|
}
|
||||||
|
return of(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
public processColor(data: FormattedData<TbMapDatasource>, dsData: FormattedData<TbMapDatasource>[]): string {
|
public processColor(data: FormattedData<TbMapDatasource>, dsData: FormattedData<TbMapDatasource>[]): string {
|
||||||
@ -102,12 +116,33 @@ export class DataLayerColorProcessor {
|
|||||||
if (!color) {
|
if (!color) {
|
||||||
color = this.color;
|
color = this.color;
|
||||||
}
|
}
|
||||||
|
} else if (this.settings.type === DataLayerColorType.range) {
|
||||||
|
color = this.color;
|
||||||
|
if (this.rangeKey && this.range?.length) {
|
||||||
|
const value = data[this.rangeKey.label];
|
||||||
|
if (isDefinedAndNotNull(value) && isNumeric(value)) {
|
||||||
|
const num = Number(value);
|
||||||
|
for (const range of this.range) {
|
||||||
|
if (DataLayerColorProcessor.constantRange(range) && range.from === num) {
|
||||||
|
color = range.color;
|
||||||
|
break;
|
||||||
|
} else if ((!isNumber(range.from) || num >= range.from) && (!isNumber(range.to) || num < range.to)) {
|
||||||
|
color = range.color;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
color = this.color;
|
color = this.color;
|
||||||
}
|
}
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static constantRange(range: ColorRange): boolean {
|
||||||
|
return isNumber(range.from) && isNumber(range.to) && range.from === range.to;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export abstract class TbDataLayerItem<S extends MapDataLayerSettings = MapDataLayerSettings, D extends TbMapDataLayer = TbMapDataLayer, L extends L.Layer = L.Layer> {
|
export abstract class TbDataLayerItem<S extends MapDataLayerSettings = MapDataLayerSettings, D extends TbMapDataLayer = TbMapDataLayer, L extends L.Layer = L.Layer> {
|
||||||
@ -169,6 +204,9 @@ export abstract class TbMapDataLayer<S extends MapDataLayerSettings = MapDataLay
|
|||||||
public setup(): Observable<any> {
|
public setup(): Observable<any> {
|
||||||
this.datasource = mapDataSourceSettingsToDatasource(this.settings);
|
this.datasource = mapDataSourceSettingsToDatasource(this.settings);
|
||||||
this.datasource.dataKeys = this.settings.additionalDataKeys ? [...this.settings.additionalDataKeys] : [];
|
this.datasource.dataKeys = this.settings.additionalDataKeys ? [...this.settings.additionalDataKeys] : [];
|
||||||
|
const colorRangeKeys = this.allColorSettings().filter(settings => settings.type === DataLayerColorType.range && settings.rangeKey)
|
||||||
|
.map(settings => settings.rangeKey);
|
||||||
|
this.datasource.dataKeys.push(...colorRangeKeys);
|
||||||
this.mapDataId = this.datasource.mapDataIds[0];
|
this.mapDataId = this.datasource.mapDataIds[0];
|
||||||
this.datasource = this.setupDatasource(this.datasource);
|
this.datasource = this.setupDatasource(this.datasource);
|
||||||
return forkJoin(
|
return forkJoin(
|
||||||
@ -251,6 +289,10 @@ export abstract class TbMapDataLayer<S extends MapDataLayerSettings = MapDataLay
|
|||||||
return datasource;
|
return datasource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected allColorSettings(): DataLayerColorSettings[] {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
protected onDataLayerEnabled(): void {}
|
protected onDataLayerEnabled(): void {}
|
||||||
|
|
||||||
protected onDataLayerDisabled(): void {}
|
protected onDataLayerDisabled(): void {}
|
||||||
|
|||||||
@ -17,11 +17,12 @@
|
|||||||
import {
|
import {
|
||||||
BaseMarkerShapeSettings,
|
BaseMarkerShapeSettings,
|
||||||
ClusterMarkerColorFunction,
|
ClusterMarkerColorFunction,
|
||||||
|
DataLayerColorSettings,
|
||||||
DataLayerColorType,
|
DataLayerColorType,
|
||||||
defaultBaseMarkersDataLayerSettings,
|
defaultBaseMarkersDataLayerSettings,
|
||||||
isValidLatLng,
|
isValidLatLng,
|
||||||
loadImageWithAspect, MapDataLayerType,
|
loadImageWithAspect,
|
||||||
MapStringFunction,
|
MapDataLayerType,
|
||||||
MapType,
|
MapType,
|
||||||
MarkerIconInfo,
|
MarkerIconInfo,
|
||||||
MarkerIconSettings,
|
MarkerIconSettings,
|
||||||
@ -53,17 +54,19 @@ import { ImagePipe } from '@shared/pipe/image.pipe';
|
|||||||
import { TbMap } from '@home/components/widget/lib/maps/map';
|
import { TbMap } from '@home/components/widget/lib/maps/map';
|
||||||
import {
|
import {
|
||||||
createColorMarkerIconElement,
|
createColorMarkerIconElement,
|
||||||
createColorMarkerShapeURI, MarkerIconContainer,
|
createColorMarkerShapeURI,
|
||||||
|
MarkerIconContainer,
|
||||||
MarkerShape
|
MarkerShape
|
||||||
} from '@shared/models/widget/maps/marker-shape.models';
|
} from '@shared/models/widget/maps/marker-shape.models';
|
||||||
import { MatIconRegistry } from '@angular/material/icon';
|
import { MatIconRegistry } from '@angular/material/icon';
|
||||||
import { DomSanitizer } from '@angular/platform-browser';
|
import { DomSanitizer } from '@angular/platform-browser';
|
||||||
import {
|
import {
|
||||||
TbLatestDataLayerItem,
|
TbLatestDataLayerItem,
|
||||||
TbLatestMapDataLayer, UnplacedMapDataItem
|
TbLatestMapDataLayer,
|
||||||
|
UnplacedMapDataItem
|
||||||
} from '@home/components/widget/lib/maps/data-layer/latest-map-data-layer';
|
} from '@home/components/widget/lib/maps/data-layer/latest-map-data-layer';
|
||||||
import { TbImageMap } from '@home/components/widget/lib/maps/image-map';
|
import { TbImageMap } from '@home/components/widget/lib/maps/image-map';
|
||||||
import { TbMapDataLayer } from '@home/components/widget/lib/maps/data-layer/map-data-layer';
|
import { DataLayerColorProcessor, TbMapDataLayer } from '@home/components/widget/lib/maps/data-layer/map-data-layer';
|
||||||
|
|
||||||
export class MarkerDataProcessor<S extends MarkersDataLayerSettings = MarkersDataLayerSettings> {
|
export class MarkerDataProcessor<S extends MarkersDataLayerSettings = MarkersDataLayerSettings> {
|
||||||
|
|
||||||
@ -218,8 +221,7 @@ abstract class MarkerIconProcessor<S> {
|
|||||||
|
|
||||||
abstract class BaseColorMarkerShapeProcessor<S extends BaseMarkerShapeSettings> extends MarkerIconProcessor<S> {
|
abstract class BaseColorMarkerShapeProcessor<S extends BaseMarkerShapeSettings> extends MarkerIconProcessor<S> {
|
||||||
|
|
||||||
private markerColorFunction: CompiledTbFunction<MapStringFunction>;
|
private colorProcessor: DataLayerColorProcessor;
|
||||||
|
|
||||||
private defaultMarkerIconInfo: MarkerIconInfo;
|
private defaultMarkerIconInfo: MarkerIconInfo;
|
||||||
|
|
||||||
protected constructor(protected dataProcessor: MarkerDataProcessor,
|
protected constructor(protected dataProcessor: MarkerDataProcessor,
|
||||||
@ -229,40 +231,28 @@ abstract class BaseColorMarkerShapeProcessor<S extends BaseMarkerShapeSettings>
|
|||||||
|
|
||||||
public setup(): Observable<void> {
|
public setup(): Observable<void> {
|
||||||
const colorSettings = this.settings.color;
|
const colorSettings = this.settings.color;
|
||||||
if (colorSettings.type === DataLayerColorType.function) {
|
this.colorProcessor = new DataLayerColorProcessor(this.dataProcessor.dataLayer, colorSettings);
|
||||||
return parseTbFunction<MapStringFunction>(this.dataProcessor.dataLayer.getCtx().http, colorSettings.colorFunction, ['data', 'dsData']).pipe(
|
const setup$: Observable<void>[] = [this.colorProcessor.setup()];
|
||||||
map((parsed) => {
|
if (colorSettings.type === DataLayerColorType.constant) {
|
||||||
this.markerColorFunction = parsed;
|
|
||||||
return null;
|
|
||||||
})
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
const color = tinycolor(colorSettings.color);
|
const color = tinycolor(colorSettings.color);
|
||||||
return this.createMarkerShape(color, 0, this.settings.size).pipe(
|
setup$.push(
|
||||||
map((info) => {
|
this.createMarkerShape(color, 0, this.settings.size).pipe(
|
||||||
this.defaultMarkerIconInfo = info;
|
map((info) => {
|
||||||
return null;
|
this.defaultMarkerIconInfo = info;
|
||||||
}
|
return null;
|
||||||
));
|
}))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
return forkJoin(setup$).pipe(map(() => null));
|
||||||
}
|
}
|
||||||
|
|
||||||
public createMarkerIcon(data: FormattedData<TbMapDatasource>, dsData: FormattedData<TbMapDatasource>[], rotationAngle = 0): Observable<MarkerIconInfo> {
|
public createMarkerIcon(data: FormattedData<TbMapDatasource>, dsData: FormattedData<TbMapDatasource>[], rotationAngle = 0): Observable<MarkerIconInfo> {
|
||||||
const colorSettings = this.settings.color;
|
const colorSettings = this.settings.color;
|
||||||
let color: tinycolor.Instance;
|
if (colorSettings.type === DataLayerColorType.constant && rotationAngle === 0) {
|
||||||
if (colorSettings.type === DataLayerColorType.function) {
|
|
||||||
const functionColor = safeExecuteTbFunction(this.markerColorFunction, [data, dsData]);
|
|
||||||
if (isDefinedAndNotNull(functionColor)) {
|
|
||||||
color = tinycolor(functionColor);
|
|
||||||
} else {
|
|
||||||
color = tinycolor(colorSettings.color);
|
|
||||||
}
|
|
||||||
return this.createMarkerShape(color, rotationAngle, this.settings.size);
|
|
||||||
} else if (rotationAngle === 0) {
|
|
||||||
return of(this.defaultMarkerIconInfo);
|
return of(this.defaultMarkerIconInfo);
|
||||||
} else {
|
} else {
|
||||||
color = tinycolor(colorSettings.color);
|
const color = this.colorProcessor.processColor(data, dsData);
|
||||||
return this.createMarkerShape(color, rotationAngle, this.settings.size);
|
return this.createMarkerShape(tinycolor(color), rotationAngle, this.settings.size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -639,6 +629,15 @@ export class TbMarkersDataLayer extends TbLatestMapDataLayer<MarkersDataLayerSet
|
|||||||
return datasource;
|
return datasource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected allColorSettings(): DataLayerColorSettings[] {
|
||||||
|
if (this.settings.markerType === MarkerType.shape) {
|
||||||
|
return [this.settings.markerShape.color];
|
||||||
|
} else if (this.settings.markerType === MarkerType.icon) {
|
||||||
|
return [this.settings.markerIcon.color];
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
protected defaultBaseSettings(map: TbMap<any>): Partial<MarkersDataLayerSettings> {
|
protected defaultBaseSettings(map: TbMap<any>): Partial<MarkersDataLayerSettings> {
|
||||||
return defaultBaseMarkersDataLayerSettings(map.type());
|
return defaultBaseMarkersDataLayerSettings(map.type());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,7 +14,7 @@
|
|||||||
/// limitations under the License.
|
/// limitations under the License.
|
||||||
///
|
///
|
||||||
|
|
||||||
import { ShapeDataLayerSettings, TbMapDatasource } from '@shared/models/widget/maps/map.models';
|
import { DataLayerColorSettings, ShapeDataLayerSettings, TbMapDatasource } from '@shared/models/widget/maps/map.models';
|
||||||
import L from 'leaflet';
|
import L from 'leaflet';
|
||||||
import { TbMap } from '@home/components/widget/lib/maps/map';
|
import { TbMap } from '@home/components/widget/lib/maps/map';
|
||||||
import { forkJoin, Observable } from 'rxjs';
|
import { forkJoin, Observable } from 'rxjs';
|
||||||
@ -45,6 +45,10 @@ export abstract class TbShapesDataLayer<S extends ShapeDataLayerSettings, L exte
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected allColorSettings(): DataLayerColorSettings[] {
|
||||||
|
return [this.settings.fillColor, this.settings.strokeColor];
|
||||||
|
}
|
||||||
|
|
||||||
protected doSetup(): Observable<any> {
|
protected doSetup(): Observable<any> {
|
||||||
this.fillColorProcessor = new DataLayerColorProcessor(this, this.settings.fillColor);
|
this.fillColorProcessor = new DataLayerColorProcessor(this, this.settings.fillColor);
|
||||||
this.strokeColorProcessor = new DataLayerColorProcessor(this, this.settings.strokeColor);
|
this.strokeColorProcessor = new DataLayerColorProcessor(this, this.settings.strokeColor);
|
||||||
|
|||||||
@ -16,16 +16,16 @@
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
calculateInterpolationRatio,
|
calculateInterpolationRatio,
|
||||||
calculateLastPoints,
|
calculateLastPoints, DataLayerColorSettings, DataLayerColorType,
|
||||||
defaultBaseTripsDataLayerSettings,
|
defaultBaseTripsDataLayerSettings,
|
||||||
findRotationAngle,
|
findRotationAngle,
|
||||||
interpolateLineSegment,
|
interpolateLineSegment,
|
||||||
MapDataLayerType,
|
MapDataLayerType, MarkerType,
|
||||||
TbMapDatasource,
|
TbMapDatasource,
|
||||||
TripsDataLayerSettings
|
TripsDataLayerSettings
|
||||||
} from '@shared/models/widget/maps/map.models';
|
} from '@shared/models/widget/maps/map.models';
|
||||||
import { forkJoin, Observable } from 'rxjs';
|
import { forkJoin, Observable } from 'rxjs';
|
||||||
import { FormattedData, WidgetActionType } from '@shared/models/widget.models';
|
import { DataKey, FormattedData, WidgetActionType } from '@shared/models/widget.models';
|
||||||
import { map } from 'rxjs/operators';
|
import { map } from 'rxjs/operators';
|
||||||
import L from 'leaflet';
|
import L from 'leaflet';
|
||||||
import { deepClone, isDefined, isUndefined } from '@core/utils';
|
import { deepClone, isDefined, isUndefined } from '@core/utils';
|
||||||
@ -530,9 +530,14 @@ export class TbTripsDataLayer extends TbMapDataLayer<TripsDataLayerSettings, TbT
|
|||||||
|
|
||||||
protected setupDatasource(datasource: TbMapDatasource): TbMapDatasource {
|
protected setupDatasource(datasource: TbMapDatasource): TbMapDatasource {
|
||||||
datasource.dataKeys = [this.settings.xKey, this.settings.yKey];
|
datasource.dataKeys = [this.settings.xKey, this.settings.yKey];
|
||||||
|
const additionalKeys = this.allColorSettings().filter(settings => settings.type === DataLayerColorType.range && settings.rangeKey)
|
||||||
|
.map(settings => settings.rangeKey);
|
||||||
if (this.settings.additionalDataKeys?.length) {
|
if (this.settings.additionalDataKeys?.length) {
|
||||||
const tsKeys = this.settings.additionalDataKeys.filter(key => key.type === DataKeyType.timeseries);
|
additionalKeys.push(...this.settings.additionalDataKeys);
|
||||||
const latestKeys = this.settings.additionalDataKeys.filter(key => key.type !== DataKeyType.timeseries);
|
}
|
||||||
|
if (additionalKeys.length) {
|
||||||
|
const tsKeys = additionalKeys.filter(key => key.type === DataKeyType.timeseries);
|
||||||
|
const latestKeys = additionalKeys.filter(key => key.type !== DataKeyType.timeseries);
|
||||||
datasource.dataKeys.push(...tsKeys);
|
datasource.dataKeys.push(...tsKeys);
|
||||||
if (latestKeys.length) {
|
if (latestKeys.length) {
|
||||||
datasource.latestDataKeys = latestKeys;
|
datasource.latestDataKeys = latestKeys;
|
||||||
@ -541,6 +546,24 @@ export class TbTripsDataLayer extends TbMapDataLayer<TripsDataLayerSettings, TbT
|
|||||||
return datasource;
|
return datasource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected allColorSettings(): DataLayerColorSettings[] {
|
||||||
|
const colorSettings: DataLayerColorSettings[] = [];
|
||||||
|
if (this.settings.showMarker) {
|
||||||
|
if (this.settings.markerType === MarkerType.shape) {
|
||||||
|
colorSettings.push(this.settings.markerShape.color);
|
||||||
|
} else if (this.settings.markerType === MarkerType.icon) {
|
||||||
|
colorSettings.push(this.settings.markerIcon.color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.settings.showPath) {
|
||||||
|
colorSettings.push(this.settings.pathStrokeColor);
|
||||||
|
}
|
||||||
|
if (this.settings.showPoints) {
|
||||||
|
colorSettings.push(this.settings.pointColor);
|
||||||
|
}
|
||||||
|
return colorSettings;
|
||||||
|
}
|
||||||
|
|
||||||
protected defaultBaseSettings(map: TbMap<any>): Partial<TripsDataLayerSettings> {
|
protected defaultBaseSettings(map: TbMap<any>): Partial<TripsDataLayerSettings> {
|
||||||
return defaultBaseTripsDataLayerSettings(map.type());
|
return defaultBaseTripsDataLayerSettings(map.type());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -85,6 +85,10 @@ export class ColorRangeListComponent implements OnInit, ControlValueAccessor, On
|
|||||||
@Input()
|
@Input()
|
||||||
datasource: Datasource;
|
datasource: Datasource;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
@coerceBoolean()
|
||||||
|
simpleRange = false;
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
@coerceBoolean()
|
@coerceBoolean()
|
||||||
advancedMode = false;
|
advancedMode = false;
|
||||||
@ -133,7 +137,7 @@ export class ColorRangeListComponent implements OnInit, ControlValueAccessor, On
|
|||||||
writeValue(value: any): void {
|
writeValue(value: any): void {
|
||||||
if (value) {
|
if (value) {
|
||||||
let rangeList: ColorRangeSettings = {};
|
let rangeList: ColorRangeSettings = {};
|
||||||
if (isUndefined(value?.advancedMode) && value?.length) {
|
if (this.simpleRange || (isUndefined(value?.advancedMode) && value?.length)) {
|
||||||
rangeList.advancedMode = false;
|
rangeList.advancedMode = false;
|
||||||
rangeList.range = value;
|
rangeList.range = value;
|
||||||
} else {
|
} else {
|
||||||
@ -229,7 +233,11 @@ export class ColorRangeListComponent implements OnInit, ControlValueAccessor, On
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateModel() {
|
updateModel() {
|
||||||
this.propagateChange(this.colorRangeListFormGroup.value);
|
if (this.simpleRange) {
|
||||||
|
this.propagateChange(this.colorRangeListFormGroup.get('range').value);
|
||||||
|
} else {
|
||||||
|
this.propagateChange(this.colorRangeListFormGroup.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,6 +22,9 @@
|
|||||||
<tb-toggle-option [value]="DataLayerColorType.constant">
|
<tb-toggle-option [value]="DataLayerColorType.constant">
|
||||||
{{ 'widgets.maps.data-layer.color-type-constant' | translate }}
|
{{ 'widgets.maps.data-layer.color-type-constant' | translate }}
|
||||||
</tb-toggle-option>
|
</tb-toggle-option>
|
||||||
|
<tb-toggle-option [value]="DataLayerColorType.range">
|
||||||
|
{{ 'widgets.maps.data-layer.color-type-range' | translate }}
|
||||||
|
</tb-toggle-option>
|
||||||
<tb-toggle-option [value]="DataLayerColorType.function">
|
<tb-toggle-option [value]="DataLayerColorType.function">
|
||||||
{{ 'widgets.maps.data-layer.color-type-function' | translate }}
|
{{ 'widgets.maps.data-layer.color-type-function' | translate }}
|
||||||
</tb-toggle-option>
|
</tb-toggle-option>
|
||||||
@ -35,6 +38,35 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="tb-data-layer-color-settings-panel-body" [class.!hidden]="colorSettingsFormGroup.get('type').value !== DataLayerColorType.constant">
|
<div class="tb-data-layer-color-settings-panel-body" [class.!hidden]="colorSettingsFormGroup.get('type').value !== DataLayerColorType.constant">
|
||||||
</div>
|
</div>
|
||||||
|
<div class="tb-data-layer-color-settings-panel-body" [class.!hidden]="colorSettingsFormGroup.get('type').value !== DataLayerColorType.range">
|
||||||
|
<tb-data-key-input
|
||||||
|
inlineField="false"
|
||||||
|
appearance="outline"
|
||||||
|
subscriptSizing="fixed"
|
||||||
|
label="{{ 'widgets.maps.data-layer.color-range-source-key' | translate }}"
|
||||||
|
required
|
||||||
|
requiredText="{{ 'widgets.maps.data-layer.color-range-source-key-required' }}"
|
||||||
|
[datasourceType]="dsType"
|
||||||
|
[entityAliasId]="dsEntityAliasId"
|
||||||
|
[deviceId]="dsDeviceId"
|
||||||
|
[aliasController]="context.aliasController"
|
||||||
|
[widgetType]="widgetType.latest"
|
||||||
|
[dataKeyType]="context.functionsOnly ? DataKeyType.function : null"
|
||||||
|
[dataKeyTypes]="[DataKeyType.attribute, DataKeyType.timeseries]"
|
||||||
|
[callbacks]="context.callbacks"
|
||||||
|
[generateKey]="context.generateDataKey"
|
||||||
|
(keyEdit)="editRangeKey()"
|
||||||
|
formControlName="rangeKey">
|
||||||
|
</tb-data-key-input>
|
||||||
|
<div class="tb-form-panel stroked">
|
||||||
|
<div translate>widgets.maps.data-layer.color-range</div>
|
||||||
|
<tb-color-range-list class="tb-color-ranges-panel"
|
||||||
|
simpleRange
|
||||||
|
formControlName="range"
|
||||||
|
[popover]="popover">
|
||||||
|
</tb-color-range-list>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="tb-data-layer-color-settings-panel-body" [class.!hidden]="colorSettingsFormGroup.get('type').value !== DataLayerColorType.function">
|
<div class="tb-data-layer-color-settings-panel-body" [class.!hidden]="colorSettingsFormGroup.get('type').value !== DataLayerColorType.function">
|
||||||
<ng-container *ngTemplateOutlet="function"></ng-container>
|
<ng-container *ngTemplateOutlet="function"></ng-container>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -16,6 +16,8 @@
|
|||||||
@import '../../../../../../../../../scss/constants';
|
@import '../../../../../../../../../scss/constants';
|
||||||
|
|
||||||
.tb-data-layer-color-settings-panel {
|
.tb-data-layer-color-settings-panel {
|
||||||
|
--mdc-outlined-text-field-outline-color: rgba(0,0,0,0.12);
|
||||||
|
--mat-form-field-trailing-icon-color: rgba(0,0,0,0.38);
|
||||||
width: 700px;
|
width: 700px;
|
||||||
max-width: 90vw;
|
max-width: 90vw;
|
||||||
min-height: 300px;
|
min-height: 300px;
|
||||||
@ -50,4 +52,14 @@
|
|||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
}
|
}
|
||||||
|
.tb-color-ranges-panel {
|
||||||
|
flex: 1;
|
||||||
|
min-height: 0;
|
||||||
|
gap: 16px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
.tb-color-ranges {
|
||||||
|
--mat-icon-color: rgba(0, 0, 0, 0.38);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,12 +17,15 @@
|
|||||||
import { Component, DestroyRef, EventEmitter, Input, OnInit, Output, ViewEncapsulation } from '@angular/core';
|
import { Component, DestroyRef, EventEmitter, Input, OnInit, Output, ViewEncapsulation } from '@angular/core';
|
||||||
import { PageComponent } from '@shared/components/page.component';
|
import { PageComponent } from '@shared/components/page.component';
|
||||||
import { TbPopoverComponent } from '@shared/components/popover.component';
|
import { TbPopoverComponent } from '@shared/components/popover.component';
|
||||||
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
|
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
|
||||||
import { Store } from '@ngrx/store';
|
import { Store } from '@ngrx/store';
|
||||||
import { AppState } from '@core/core.state';
|
import { AppState } from '@core/core.state';
|
||||||
import { WidgetService } from '@core/http/widget.service';
|
import { WidgetService } from '@core/http/widget.service';
|
||||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||||
import { DataLayerColorSettings, DataLayerColorType } from '@shared/models/widget/maps/map.models';
|
import { DataLayerColorSettings, DataLayerColorType, MapType } from '@shared/models/widget/maps/map.models';
|
||||||
|
import { DataKey, DatasourceType, widgetType } from '@shared/models/widget.models';
|
||||||
|
import { DataKeyType } from '@shared/models/telemetry/telemetry.models';
|
||||||
|
import { MapSettingsContext } from '@home/components/widget/lib/settings/common/map/map-settings.component.models';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'tb-data-layer-color-settings-panel',
|
selector: 'tb-data-layer-color-settings-panel',
|
||||||
@ -33,9 +36,25 @@ import { DataLayerColorSettings, DataLayerColorType } from '@shared/models/widge
|
|||||||
})
|
})
|
||||||
export class DataLayerColorSettingsPanelComponent extends PageComponent implements OnInit {
|
export class DataLayerColorSettingsPanelComponent extends PageComponent implements OnInit {
|
||||||
|
|
||||||
|
widgetType = widgetType;
|
||||||
|
|
||||||
|
DataKeyType = DataKeyType;
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
colorSettings: DataLayerColorSettings;
|
colorSettings: DataLayerColorSettings;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
context: MapSettingsContext;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
dsType: DatasourceType;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
dsEntityAliasId: string;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
dsDeviceId: string;
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
helpId = 'widget/lib/map/color_fn';
|
helpId = 'widget/lib/map/color_fn';
|
||||||
|
|
||||||
@ -63,14 +82,18 @@ export class DataLayerColorSettingsPanelComponent extends PageComponent implemen
|
|||||||
{
|
{
|
||||||
type: [this.colorSettings?.type || DataLayerColorType.constant, []],
|
type: [this.colorSettings?.type || DataLayerColorType.constant, []],
|
||||||
color: [this.colorSettings?.color, []],
|
color: [this.colorSettings?.color, []],
|
||||||
|
rangeKey: [this.colorSettings?.rangeKey, [Validators.required]],
|
||||||
|
range: [this.colorSettings?.range, []],
|
||||||
colorFunction: [this.colorSettings?.colorFunction, []]
|
colorFunction: [this.colorSettings?.colorFunction, []]
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
this.colorSettingsFormGroup.get('type').valueChanges.pipe(
|
this.colorSettingsFormGroup.get('type').valueChanges.pipe(
|
||||||
takeUntilDestroyed(this.destroyRef)
|
takeUntilDestroyed(this.destroyRef)
|
||||||
).subscribe(() => {
|
).subscribe(() => {
|
||||||
|
this.updateValidators();
|
||||||
setTimeout(() => {this.popover?.updatePosition();}, 0);
|
setTimeout(() => {this.popover?.updatePosition();}, 0);
|
||||||
});
|
});
|
||||||
|
this.updateValidators();
|
||||||
}
|
}
|
||||||
|
|
||||||
cancel() {
|
cancel() {
|
||||||
@ -82,4 +105,25 @@ export class DataLayerColorSettingsPanelComponent extends PageComponent implemen
|
|||||||
this.colorSettingsApplied.emit(colorSettings);
|
this.colorSettingsApplied.emit(colorSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public editRangeKey() {
|
||||||
|
const targetDataKey: DataKey = this.colorSettingsFormGroup.get('rangeKey').value;
|
||||||
|
this.context.editKey(targetDataKey,
|
||||||
|
this.dsDeviceId, this.dsEntityAliasId, widgetType.latest).subscribe(
|
||||||
|
(updatedDataKey) => {
|
||||||
|
if (updatedDataKey) {
|
||||||
|
this.colorSettingsFormGroup.get('rangeKey').patchValue(updatedDataKey);
|
||||||
|
this.colorSettingsFormGroup.markAsDirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateValidators() {
|
||||||
|
const type: DataLayerColorType = this.colorSettingsFormGroup.get('type').value;
|
||||||
|
if (type === DataLayerColorType.range) {
|
||||||
|
this.colorSettingsFormGroup.get('rangeKey').enable({emitEvent: false});
|
||||||
|
} else {
|
||||||
|
this.colorSettingsFormGroup.get('rangeKey').disable({emitEvent: false});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,13 +16,15 @@
|
|||||||
|
|
||||||
import { Component, forwardRef, Input, Renderer2, ViewContainerRef } from '@angular/core';
|
import { Component, forwardRef, Input, Renderer2, ViewContainerRef } from '@angular/core';
|
||||||
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
|
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||||
import { ComponentStyle } from '@shared/models/widget-settings.models';
|
import { ColorType, ComponentStyle } from '@shared/models/widget-settings.models';
|
||||||
import { MatButton } from '@angular/material/button';
|
import { MatButton } from '@angular/material/button';
|
||||||
import { TbPopoverService } from '@shared/components/popover.service';
|
import { TbPopoverService } from '@shared/components/popover.service';
|
||||||
import { DataLayerColorSettings, DataLayerColorType } from '@shared/models/widget/maps/map.models';
|
import { DataLayerColorSettings, DataLayerColorType } from '@shared/models/widget/maps/map.models';
|
||||||
import {
|
import {
|
||||||
DataLayerColorSettingsPanelComponent
|
DataLayerColorSettingsPanelComponent
|
||||||
} from '@home/components/widget/lib/settings/common/map/data-layer-color-settings-panel.component';
|
} from '@home/components/widget/lib/settings/common/map/data-layer-color-settings-panel.component';
|
||||||
|
import { MapSettingsContext } from '@home/components/widget/lib/settings/common/map/map-settings.component.models';
|
||||||
|
import { DatasourceType } from '@shared/models/widget.models';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'tb-data-layer-color-settings',
|
selector: 'tb-data-layer-color-settings',
|
||||||
@ -41,6 +43,18 @@ export class DataLayerColorSettingsComponent implements ControlValueAccessor {
|
|||||||
@Input()
|
@Input()
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
context: MapSettingsContext;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
dsType: DatasourceType;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
dsEntityAliasId: string;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
dsDeviceId: string;
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
helpId = 'widget/lib/map/color_fn';
|
helpId = 'widget/lib/map/color_fn';
|
||||||
|
|
||||||
@ -85,6 +99,10 @@ export class DataLayerColorSettingsComponent implements ControlValueAccessor {
|
|||||||
} else {
|
} else {
|
||||||
const ctx: any = {
|
const ctx: any = {
|
||||||
colorSettings: this.modelValue,
|
colorSettings: this.modelValue,
|
||||||
|
context: this.context,
|
||||||
|
dsType: this.dsType,
|
||||||
|
dsEntityAliasId: this.dsEntityAliasId,
|
||||||
|
dsDeviceId: this.dsDeviceId,
|
||||||
helpId: this.helpId
|
helpId: this.helpId
|
||||||
};
|
};
|
||||||
const colorSettingsPanelPopover = this.popoverService.displayPopover(trigger, this.renderer,
|
const colorSettingsPanelPopover = this.popoverService.displayPopover(trigger, this.renderer,
|
||||||
@ -103,11 +121,23 @@ export class DataLayerColorSettingsComponent implements ControlValueAccessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private updateColorStyle() {
|
private updateColorStyle() {
|
||||||
if (!this.disabled && this.modelValue) {
|
if (!this.disabled && this.modelValue && this.modelValue.type !== DataLayerColorType.function) {
|
||||||
if (this.modelValue.type === DataLayerColorType.constant) {
|
let colors: string[] = [this.modelValue.color];
|
||||||
this.colorStyle = {backgroundColor: this.modelValue.color};
|
const rangeList = this.modelValue.range;
|
||||||
|
if (this.modelValue.type === DataLayerColorType.range && rangeList?.length) {
|
||||||
|
const rangeColors = rangeList.slice(0, Math.min(2, rangeList.length)).map(r => r.color);
|
||||||
|
colors = colors.concat(rangeColors);
|
||||||
|
}
|
||||||
|
if (colors.length === 1) {
|
||||||
|
this.colorStyle = {backgroundColor: colors[0]};
|
||||||
} else {
|
} else {
|
||||||
this.colorStyle = {};
|
const gradientValues: string[] = [];
|
||||||
|
const step = 100 / colors.length;
|
||||||
|
for (let i = 0; i < colors.length; i++) {
|
||||||
|
gradientValues.push(`${colors[i]} ${step*i}%`);
|
||||||
|
gradientValues.push(`${colors[i]} ${step*(i+1)}%`);
|
||||||
|
}
|
||||||
|
this.colorStyle = {background: `linear-gradient(90deg, ${gradientValues.join(', ')})`};
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.colorStyle = {};
|
this.colorStyle = {};
|
||||||
|
|||||||
@ -200,11 +200,21 @@
|
|||||||
<ng-template matExpansionPanelContent>
|
<ng-template matExpansionPanelContent>
|
||||||
<div *ngIf="dataLayerFormGroup.get('markerType').value === MarkerType.shape" class="tb-form-row space-between column-xs">
|
<div *ngIf="dataLayerFormGroup.get('markerType').value === MarkerType.shape" class="tb-form-row space-between column-xs">
|
||||||
<div translate>widgets.maps.data-layer.marker.shape</div>
|
<div translate>widgets.maps.data-layer.marker.shape</div>
|
||||||
<tb-marker-shape-settings formControlName="markerShape" [trip]="dataLayerType === 'trips'" [markerType]="MarkerType.shape"></tb-marker-shape-settings>
|
<tb-marker-shape-settings formControlName="markerShape"
|
||||||
|
[context]="context"
|
||||||
|
[dsType]="dataLayerFormGroup.get('dsType').value"
|
||||||
|
[dsEntityAliasId]="dataLayerFormGroup.get('dsEntityAliasId').value"
|
||||||
|
[dsDeviceId]="dataLayerFormGroup.get('dsDeviceId').value"
|
||||||
|
[trip]="dataLayerType === 'trips'" [markerType]="MarkerType.shape"></tb-marker-shape-settings>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="dataLayerFormGroup.get('markerType').value === MarkerType.icon" class="tb-form-row space-between column-xs">
|
<div *ngIf="dataLayerFormGroup.get('markerType').value === MarkerType.icon" class="tb-form-row space-between column-xs">
|
||||||
<div translate>widgets.maps.data-layer.marker.icon</div>
|
<div translate>widgets.maps.data-layer.marker.icon</div>
|
||||||
<tb-marker-shape-settings formControlName="markerIcon" [trip]="dataLayerType === 'trips'" [markerType]="MarkerType.icon"></tb-marker-shape-settings>
|
<tb-marker-shape-settings formControlName="markerIcon"
|
||||||
|
[context]="context"
|
||||||
|
[dsType]="dataLayerFormGroup.get('dsType').value"
|
||||||
|
[dsEntityAliasId]="dataLayerFormGroup.get('dsEntityAliasId').value"
|
||||||
|
[dsDeviceId]="dataLayerFormGroup.get('dsDeviceId').value"
|
||||||
|
[trip]="dataLayerType === 'trips'" [markerType]="MarkerType.icon"></tb-marker-shape-settings>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="dataLayerFormGroup.get('markerType').value === MarkerType.image" class="tb-form-row space-between">
|
<div *ngIf="dataLayerFormGroup.get('markerType').value === MarkerType.image" class="tb-form-row space-between">
|
||||||
<div translate>widgets.maps.data-layer.marker.image</div>
|
<div translate>widgets.maps.data-layer.marker.image</div>
|
||||||
@ -275,7 +285,12 @@
|
|||||||
<input matInput type="number" min="0" formControlName="pathStrokeWeight" placeholder="{{ 'widget-config.set' | translate }}">
|
<input matInput type="number" min="0" formControlName="pathStrokeWeight" placeholder="{{ 'widget-config.set' | translate }}">
|
||||||
<span matSuffix>px</span>
|
<span matSuffix>px</span>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<tb-data-layer-color-settings helpId="widget/lib/map/path_color_fn" formControlName="pathStrokeColor"></tb-data-layer-color-settings>
|
<tb-data-layer-color-settings
|
||||||
|
[context]="context"
|
||||||
|
[dsType]="dataLayerFormGroup.get('dsType').value"
|
||||||
|
[dsEntityAliasId]="dataLayerFormGroup.get('dsEntityAliasId').value"
|
||||||
|
[dsDeviceId]="dataLayerFormGroup.get('dsDeviceId').value"
|
||||||
|
helpId="widget/lib/map/path_color_fn" formControlName="pathStrokeColor"></tb-data-layer-color-settings>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tb-form-panel tb-slide-toggle stroked">
|
<div class="tb-form-panel tb-slide-toggle stroked">
|
||||||
@ -361,7 +376,12 @@
|
|||||||
<input matInput type="number" min="0" formControlName="pointSize" placeholder="{{ 'widget-config.set' | translate }}">
|
<input matInput type="number" min="0" formControlName="pointSize" placeholder="{{ 'widget-config.set' | translate }}">
|
||||||
<span matSuffix>px</span>
|
<span matSuffix>px</span>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<tb-data-layer-color-settings helpId="widget/lib/map/path_point_color_fn" formControlName="pointColor"></tb-data-layer-color-settings>
|
<tb-data-layer-color-settings
|
||||||
|
[context]="context"
|
||||||
|
[dsType]="dataLayerFormGroup.get('dsType').value"
|
||||||
|
[dsEntityAliasId]="dataLayerFormGroup.get('dsEntityAliasId').value"
|
||||||
|
[dsDeviceId]="dataLayerFormGroup.get('dsDeviceId').value"
|
||||||
|
helpId="widget/lib/map/path_point_color_fn" formControlName="pointColor"></tb-data-layer-color-settings>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<tb-data-layer-pattern-settings
|
<tb-data-layer-pattern-settings
|
||||||
@ -379,7 +399,12 @@
|
|||||||
<ng-container *ngIf="['polygons', 'circles'].includes(dataLayerType)">
|
<ng-container *ngIf="['polygons', 'circles'].includes(dataLayerType)">
|
||||||
<div class="tb-form-row space-between">
|
<div class="tb-form-row space-between">
|
||||||
<div translate>widgets.maps.data-layer.fill-color</div>
|
<div translate>widgets.maps.data-layer.fill-color</div>
|
||||||
<tb-data-layer-color-settings helpId="{{ dataLayerType === 'polygons' ? 'widget/lib/map/polygon_fill_color_fn' : 'widget/lib/map/circle_fill_color_fn' }}" formControlName="fillColor"></tb-data-layer-color-settings>
|
<tb-data-layer-color-settings
|
||||||
|
[context]="context"
|
||||||
|
[dsType]="dataLayerFormGroup.get('dsType').value"
|
||||||
|
[dsEntityAliasId]="dataLayerFormGroup.get('dsEntityAliasId').value"
|
||||||
|
[dsDeviceId]="dataLayerFormGroup.get('dsDeviceId').value"
|
||||||
|
helpId="{{ dataLayerType === 'polygons' ? 'widget/lib/map/polygon_fill_color_fn' : 'widget/lib/map/circle_fill_color_fn' }}" formControlName="fillColor"></tb-data-layer-color-settings>
|
||||||
</div>
|
</div>
|
||||||
<div class="tb-form-row space-between">
|
<div class="tb-form-row space-between">
|
||||||
<div translate>widgets.maps.data-layer.stroke</div>
|
<div translate>widgets.maps.data-layer.stroke</div>
|
||||||
@ -388,7 +413,12 @@
|
|||||||
<input matInput type="number" min="0" formControlName="strokeWeight" placeholder="{{ 'widget-config.set' | translate }}">
|
<input matInput type="number" min="0" formControlName="strokeWeight" placeholder="{{ 'widget-config.set' | translate }}">
|
||||||
<span matSuffix>px</span>
|
<span matSuffix>px</span>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<tb-data-layer-color-settings helpId="{{ dataLayerType === 'polygons' ? 'widget/lib/map/polygon_stroke_color_fn' : 'widget/lib/map/circle_stroke_color_fn' }}" formControlName="strokeColor"></tb-data-layer-color-settings>
|
<tb-data-layer-color-settings
|
||||||
|
[context]="context"
|
||||||
|
[dsType]="dataLayerFormGroup.get('dsType').value"
|
||||||
|
[dsEntityAliasId]="dataLayerFormGroup.get('dsEntityAliasId').value"
|
||||||
|
[dsDeviceId]="dataLayerFormGroup.get('dsDeviceId').value"
|
||||||
|
helpId="{{ dataLayerType === 'polygons' ? 'widget/lib/map/polygon_stroke_color_fn' : 'widget/lib/map/circle_stroke_color_fn' }}" formControlName="strokeColor"></tb-data-layer-color-settings>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|||||||
@ -30,5 +30,9 @@
|
|||||||
<div *ngIf="markerType === MarkerType.icon" matButtonIcon style="object-fit: contain; width: 24px; height: 24px;" [innerHTML]="iconPreview$ | async" [class.disabled]="disabled">
|
<div *ngIf="markerType === MarkerType.icon" matButtonIcon style="object-fit: contain; width: 24px; height: 24px;" [innerHTML]="iconPreview$ | async" [class.disabled]="disabled">
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
<tb-data-layer-color-settings helpId="widget/lib/map/color_fn" formControlName="color"></tb-data-layer-color-settings>
|
<tb-data-layer-color-settings [context]="context"
|
||||||
|
[dsType]="dsType"
|
||||||
|
[dsEntityAliasId]="dsEntityAliasId"
|
||||||
|
[dsDeviceId]="dsDeviceId"
|
||||||
|
helpId="widget/lib/map/color_fn" formControlName="color"></tb-data-layer-color-settings>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -49,6 +49,8 @@ import { coerceBoolean } from '@shared/decorators/coercion';
|
|||||||
import {
|
import {
|
||||||
MarkerIconShapesComponent
|
MarkerIconShapesComponent
|
||||||
} from '@home/components/widget/lib/settings/common/map/marker-icon-shapes.component';
|
} from '@home/components/widget/lib/settings/common/map/marker-icon-shapes.component';
|
||||||
|
import { MapSettingsContext } from '@home/components/widget/lib/settings/common/map/map-settings.component.models';
|
||||||
|
import { DatasourceType } from '@shared/models/widget.models';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'tb-marker-shape-settings',
|
selector: 'tb-marker-shape-settings',
|
||||||
@ -69,6 +71,18 @@ export class MarkerShapeSettingsComponent implements ControlValueAccessor, OnIni
|
|||||||
@Input()
|
@Input()
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
context: MapSettingsContext;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
dsType: DatasourceType;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
dsEntityAliasId: string;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
dsDeviceId: string;
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
markerType: MarkerType;
|
markerType: MarkerType;
|
||||||
|
|
||||||
|
|||||||
@ -41,7 +41,7 @@ import { Observable, Observer, of, switchMap } from 'rxjs';
|
|||||||
import { map } from 'rxjs/operators';
|
import { map } from 'rxjs/operators';
|
||||||
import { ImagePipe } from '@shared/pipe/image.pipe';
|
import { ImagePipe } from '@shared/pipe/image.pipe';
|
||||||
import { MarkerIconContainer, MarkerShape } from '@shared/models/widget/maps/marker-shape.models';
|
import { MarkerIconContainer, MarkerShape } from '@shared/models/widget/maps/marker-shape.models';
|
||||||
import { DateFormatSettings, simpleDateFormat } from '@shared/models/widget-settings.models';
|
import { ColorRange, DateFormatSettings, simpleDateFormat } from '@shared/models/widget-settings.models';
|
||||||
|
|
||||||
export enum MapType {
|
export enum MapType {
|
||||||
geoMap = 'geoMap',
|
geoMap = 'geoMap',
|
||||||
@ -233,12 +233,15 @@ export enum MarkerType {
|
|||||||
|
|
||||||
export enum DataLayerColorType {
|
export enum DataLayerColorType {
|
||||||
constant = 'constant',
|
constant = 'constant',
|
||||||
|
range = 'range',
|
||||||
function = 'function'
|
function = 'function'
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DataLayerColorSettings {
|
export interface DataLayerColorSettings {
|
||||||
type: DataLayerColorType;
|
type: DataLayerColorType;
|
||||||
color: string;
|
color: string;
|
||||||
|
rangeKey?: DataKey;
|
||||||
|
range?: ColorRange[];
|
||||||
colorFunction?: TbFunction;
|
colorFunction?: TbFunction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -7979,7 +7979,11 @@
|
|||||||
"stroke": "Stroke",
|
"stroke": "Stroke",
|
||||||
"color-settings": "Color settings",
|
"color-settings": "Color settings",
|
||||||
"color-type-constant": "Constant",
|
"color-type-constant": "Constant",
|
||||||
|
"color-type-range": "Range",
|
||||||
"color-type-function": "Function",
|
"color-type-function": "Function",
|
||||||
|
"color-range-source-key": "Color range source key",
|
||||||
|
"color-range-source-key-required": "Color range source key is required",
|
||||||
|
"color-range": "Color range",
|
||||||
"color-function": "Color function",
|
"color-function": "Color function",
|
||||||
"label": "Label",
|
"label": "Label",
|
||||||
"tooltip": "Tooltip",
|
"tooltip": "Tooltip",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user