Add support of latest values for timeseries map widgets
This commit is contained in:
parent
1b95f32b19
commit
c35d60abd9
File diff suppressed because one or more lines are too long
@ -471,6 +471,19 @@ export function flatFormattedData(input: FormattedData[]): FormattedData {
|
||||
return result;
|
||||
}
|
||||
|
||||
export function mergeFormattedData(first: FormattedData[], second: FormattedData[]): FormattedData[] {
|
||||
const merged = first.concat(second);
|
||||
return _(merged).groupBy(el => el.$datasource)
|
||||
.values().value().map((formattedDataArray, i) => {
|
||||
let res = formattedDataArray[0];
|
||||
if (formattedDataArray.length > 1) {
|
||||
const toMerge = formattedDataArray[1];
|
||||
res = {...res, ...toMerge};
|
||||
}
|
||||
return res;
|
||||
});
|
||||
}
|
||||
|
||||
export function processDataPattern(pattern: string, data: FormattedData): Array<ReplaceInfo> {
|
||||
const replaceInfo: Array<ReplaceInfo> = [];
|
||||
try {
|
||||
|
||||
@ -48,7 +48,7 @@ import {
|
||||
formattedDataFormDatasourceData,
|
||||
isDefinedAndNotNull,
|
||||
isNotEmptyStr,
|
||||
isString, safeExecute
|
||||
isString, mergeFormattedData, safeExecute
|
||||
} from '@core/utils';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import {
|
||||
@ -644,13 +644,25 @@ export default abstract class LeafletMap {
|
||||
}
|
||||
|
||||
updateData(drawRoutes: boolean, showPolygon: boolean) {
|
||||
const data = this.ctx.data;
|
||||
let formattedData = formattedDataFormDatasourceData(data);
|
||||
if (this.ctx.latestData && this.ctx.latestData.length) {
|
||||
const formattedLatestData = formattedDataFormDatasourceData(this.ctx.latestData);
|
||||
formattedData = mergeFormattedData(formattedData, formattedLatestData);
|
||||
}
|
||||
let polyData: FormattedData[][] = null;
|
||||
if (drawRoutes) {
|
||||
polyData = formattedDataArrayFromDatasourceData(data);
|
||||
}
|
||||
this.updateFromData(drawRoutes, showPolygon, formattedData, polyData);
|
||||
}
|
||||
|
||||
updateFromData(drawRoutes: boolean, showPolygon: boolean, formattedData: FormattedData[],
|
||||
polyData: FormattedData[][], markerClickCallback?: any) {
|
||||
this.drawRoutes = drawRoutes;
|
||||
this.showPolygon = showPolygon;
|
||||
if (this.map) {
|
||||
const data = this.ctx.data;
|
||||
const formattedData = formattedDataFormDatasourceData(data);
|
||||
if (drawRoutes) {
|
||||
const polyData = formattedDataArrayFromDatasourceData(data);
|
||||
this.updatePolylines(polyData, formattedData, false);
|
||||
}
|
||||
if (showPolygon) {
|
||||
@ -659,7 +671,7 @@ export default abstract class LeafletMap {
|
||||
if (this.options.showCircle) {
|
||||
this.updateCircle(formattedData, false);
|
||||
}
|
||||
this.updateMarkers(formattedData, false);
|
||||
this.updateMarkers(formattedData, false, markerClickCallback);
|
||||
this.updateBoundsInternal();
|
||||
if (this.options.draggableMarker || this.editPolygons || this.editCircle) {
|
||||
let foundEntityWithLocation = false;
|
||||
|
||||
@ -221,7 +221,7 @@ export interface MapImage {
|
||||
update?: boolean;
|
||||
}
|
||||
|
||||
export interface TripAnimationSettings extends PolygonSettings {
|
||||
export interface TripAnimationSettings extends PolygonSettings, CircleSettings {
|
||||
showPoints: boolean;
|
||||
pointColor: string;
|
||||
pointSize: number;
|
||||
|
||||
@ -226,8 +226,12 @@ export class MapWidgetController implements MapWidgetInterface {
|
||||
id: e.$datasource.entityId
|
||||
};
|
||||
|
||||
let dataKeys = e.$datasource.dataKeys;
|
||||
if (e.$datasource.latestDataKeys) {
|
||||
dataKeys = dataKeys.concat(e.$datasource.latestDataKeys);
|
||||
}
|
||||
for (const dataKeyName of Object.keys(values)) {
|
||||
for (const key of e.$datasource.dataKeys) {
|
||||
for (const key of dataKeys) {
|
||||
if (dataKeyName === key.name) {
|
||||
const value = {
|
||||
key: key.name,
|
||||
@ -317,6 +321,10 @@ export class MapWidgetController implements MapWidgetInterface {
|
||||
this.map.setLoading(false);
|
||||
}
|
||||
|
||||
latestDataUpdate() {
|
||||
this.map.updateData(this.drawRoutes, this.settings.showPolygon);
|
||||
}
|
||||
|
||||
resize() {
|
||||
this.map.onResize();
|
||||
this.map?.invalidateSize();
|
||||
|
||||
@ -30,6 +30,7 @@ import {
|
||||
import { MapProviders, TripAnimationSettings } from '@home/components/widget/lib/maps/map-models';
|
||||
import { addCondition, addGroupInfo, addToSchema, initSchema } from '@app/core/schema-utils';
|
||||
import {
|
||||
mapCircleSchema,
|
||||
mapPolygonSchema,
|
||||
pathSchema,
|
||||
pointSchema,
|
||||
@ -48,9 +49,9 @@ import { FormattedData, JsonSettingsSchema, WidgetConfig } from '@shared/models/
|
||||
import moment from 'moment';
|
||||
import {
|
||||
deepClone,
|
||||
formattedDataArrayFromDatasourceData,
|
||||
formattedDataArrayFromDatasourceData, formattedDataFormDatasourceData,
|
||||
isDefined,
|
||||
isUndefined,
|
||||
isUndefined, mergeFormattedData,
|
||||
parseFunction,
|
||||
safeExecute
|
||||
} from '@core/utils';
|
||||
@ -82,6 +83,8 @@ export class TripAnimationComponent implements OnInit, AfterViewInit, OnDestroy
|
||||
normalizationStep: number;
|
||||
interpolatedTimeData: {[time: number]: FormattedData}[] = [];
|
||||
formattedInterpolatedTimeData: FormattedData[][] = [];
|
||||
formattedCurrentPosition: FormattedData[] = [];
|
||||
formattedLatestData: FormattedData[] = [];
|
||||
widgetConfig: WidgetConfig;
|
||||
settings: TripAnimationSettings;
|
||||
mainTooltips = [];
|
||||
@ -104,11 +107,10 @@ export class TripAnimationComponent implements OnInit, AfterViewInit, OnDestroy
|
||||
addGroupInfo(schema, 'Path Settings');
|
||||
addToSchema(schema, addCondition(pointSchema, 'model.showPoints === true', ['showPoints']));
|
||||
addGroupInfo(schema, 'Path Points Settings');
|
||||
const mapPolygonSchemaWithoutEdit = deepClone(mapPolygonSchema);
|
||||
delete mapPolygonSchemaWithoutEdit.schema.properties.editablePolygon;
|
||||
mapPolygonSchemaWithoutEdit.form.splice(mapPolygonSchemaWithoutEdit.form.indexOf('editablePolygon'), 1);
|
||||
addToSchema(schema, addCondition(mapPolygonSchemaWithoutEdit, 'model.showPolygon === true', ['showPolygon']));
|
||||
addToSchema(schema, addCondition(mapPolygonSchema, 'model.showPolygon === true', ['showPolygon']));
|
||||
addGroupInfo(schema, 'Polygon Settings');
|
||||
addToSchema(schema, addCondition(mapCircleSchema, 'model.showCircle === true', ['showCircle']));
|
||||
addGroupInfo(schema, 'Circle Settings');
|
||||
return schema;
|
||||
}
|
||||
|
||||
@ -122,7 +124,6 @@ export class TripAnimationComponent implements OnInit, AfterViewInit, OnDestroy
|
||||
rotationAngle: 0
|
||||
};
|
||||
this.settings = { ...settings, ...this.ctx.settings };
|
||||
this.settings.editablePolygon = false;
|
||||
this.useAnchors = this.settings.showPoints && this.settings.usePointAsAnchor;
|
||||
this.settings.pointAsAnchorFunction = parseFunction(this.settings.pointAsAnchorFunction, ['data', 'dsData', 'dsIndex']);
|
||||
this.settings.tooltipFunction = parseFunction(this.settings.tooltipFunction, ['data', 'dsData', 'dsIndex']);
|
||||
@ -148,6 +149,10 @@ export class TripAnimationComponent implements OnInit, AfterViewInit, OnDestroy
|
||||
this.mapWidget.map.setLoading(false);
|
||||
this.cd.detectChanges();
|
||||
};
|
||||
subscription.callbacks.onLatestDataUpdated = () => {
|
||||
this.formattedLatestData = formattedDataFormDatasourceData(this.ctx.latestData);
|
||||
this.updateCurrentData();
|
||||
};
|
||||
}
|
||||
|
||||
ngAfterViewInit() {
|
||||
@ -171,17 +176,17 @@ export class TripAnimationComponent implements OnInit, AfterViewInit, OnDestroy
|
||||
timeUpdated(time: number) {
|
||||
this.currentTime = time;
|
||||
// get point for each datasource associated with time
|
||||
const currentPosition = this.interpolatedTimeData
|
||||
this.formattedCurrentPosition = this.interpolatedTimeData
|
||||
.map(dataSource => dataSource[time]);
|
||||
for (let j = 0; j < this.interpolatedTimeData.length; j++) {
|
||||
if (isUndefined(currentPosition[j])) {
|
||||
if (isUndefined(this.formattedCurrentPosition[j])) {
|
||||
const timePoints = Object.keys(this.interpolatedTimeData[j]).map(item => parseInt(item, 10));
|
||||
for (let i = 1; i < timePoints.length; i++) {
|
||||
if (timePoints[i - 1] < time && timePoints[i] > time) {
|
||||
const beforePosition = this.interpolatedTimeData[j][timePoints[i - 1]];
|
||||
const afterPosition = this.interpolatedTimeData[j][timePoints[i]];
|
||||
const ratio = getRatio(timePoints[i - 1], timePoints[i], time);
|
||||
currentPosition[j] = {
|
||||
this.formattedCurrentPosition[j] = {
|
||||
...beforePosition,
|
||||
time,
|
||||
...interpolateOnLineSegment(beforePosition, afterPosition, this.settings.latKeyName, this.settings.lngKeyName, ratio)
|
||||
@ -192,25 +197,29 @@ export class TripAnimationComponent implements OnInit, AfterViewInit, OnDestroy
|
||||
}
|
||||
}
|
||||
for (let j = 0; j < this.interpolatedTimeData.length; j++) {
|
||||
if (isUndefined(currentPosition[j])) {
|
||||
currentPosition[j] = this.calculateLastPoints(this.interpolatedTimeData[j], time);
|
||||
if (isUndefined(this.formattedCurrentPosition[j])) {
|
||||
this.formattedCurrentPosition[j] = this.calculateLastPoints(this.interpolatedTimeData[j], time);
|
||||
}
|
||||
}
|
||||
this.updateCurrentData();
|
||||
}
|
||||
|
||||
private updateCurrentData() {
|
||||
let currentPosition = this.formattedCurrentPosition;
|
||||
if (this.formattedLatestData.length) {
|
||||
currentPosition = mergeFormattedData(this.formattedCurrentPosition, this.formattedLatestData);
|
||||
}
|
||||
this.calcLabel(currentPosition);
|
||||
this.calcMainTooltip(currentPosition);
|
||||
if (this.mapWidget && this.mapWidget.map && this.mapWidget.map.map) {
|
||||
this.mapWidget.map.updatePolylines(this.formattedInterpolatedTimeData, currentPosition, true);
|
||||
if (this.settings.showPolygon) {
|
||||
this.mapWidget.map.updatePolygons(currentPosition);
|
||||
}
|
||||
if (this.settings.showPoints) {
|
||||
this.mapWidget.map.updatePoints(this.formattedInterpolatedTimeData, this.calcTooltip);
|
||||
}
|
||||
this.mapWidget.map.updateMarkers(currentPosition, true, (trip) => {
|
||||
this.mapWidget.map.updateFromData(true, this.settings.showPolygon, currentPosition, this.formattedInterpolatedTimeData, (trip) => {
|
||||
this.activeTrip = trip;
|
||||
this.timeUpdated(this.currentTime);
|
||||
this.cd.markForCheck();
|
||||
});
|
||||
if (this.settings.showPoints) {
|
||||
this.mapWidget.map.updatePoints(this.formattedInterpolatedTimeData, this.calcTooltip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user