Merge branch 'master' of github.com:thingsboard/thingsboard

This commit is contained in:
Igor Kulikov 2020-05-20 19:43:25 +03:00
commit dcd00e587a
10 changed files with 127 additions and 97 deletions

View File

@ -244,7 +244,7 @@ export default abstract class LeafletMap {
} }
// Markers // Markers
updateMarkers(markersData) { updateMarkers(markersData, callback?) {
markersData.filter(mdata => !!this.convertPosition(mdata)).forEach(data => { markersData.filter(mdata => !!this.convertPosition(mdata)).forEach(data => {
if (data.rotationAngle || data.rotationAngle === 0) { if (data.rotationAngle || data.rotationAngle === 0) {
const currentImage = this.options.useMarkerImageFunction ? const currentImage = this.options.useMarkerImageFunction ?
@ -265,7 +265,7 @@ export default abstract class LeafletMap {
this.updateMarker(data.entityName, data, markersData, this.options) this.updateMarker(data.entityName, data, markersData, this.options)
} }
else { else {
this.createMarker(data.entityName, data, markersData, this.options as MarkerSettings); this.createMarker(data.entityName, data, markersData, this.options as MarkerSettings, callback);
} }
}); });
this.markersData = markersData; this.markersData = markersData;
@ -276,9 +276,11 @@ export default abstract class LeafletMap {
this.saveMarkerLocation({ ...data, ...this.convertToCustomFormat(e.target._latlng) }); this.saveMarkerLocation({ ...data, ...this.convertToCustomFormat(e.target._latlng) });
} }
private createMarker(key: string, data: FormattedData, dataSources: FormattedData[], settings: MarkerSettings) { private createMarker(key: string, data: FormattedData, dataSources: FormattedData[], settings: MarkerSettings, callback?) {
this.ready$.subscribe(() => { this.ready$.subscribe(() => {
const newMarker = new Marker(this.convertPosition(data), settings, data, dataSources, this.dragMarker); const newMarker = new Marker(this.convertPosition(data), settings, data, dataSources, this.dragMarker);
if (callback)
newMarker.leafletMarker.on('click', () => { callback(data, true) });
if (this.bounds) if (this.bounds)
this.fitBounds(this.bounds.extend(newMarker.leafletMarker.getLatLng())); this.fitBounds(this.bounds.extend(newMarker.leafletMarker.getLatLng()));
this.markers.set(key, newMarker); this.markers.set(key, newMarker);
@ -344,16 +346,20 @@ export default abstract class LeafletMap {
// Polyline // Polyline
updatePolylines(polyData: FormattedData[][], data?: FormattedData) { updatePolylines(polyData: FormattedData[][], data?: FormattedData) {
polyData.forEach((dataSource) => { polyData.forEach((dataSource: FormattedData[]) => {
if (dataSource.length) {
data = data || dataSource[0]; data = data || dataSource[0];
if (this.polylines.get(data.$datasource.entityName)) { if (dataSource.length && data.entityName === dataSource[0].entityName) {
if (this.polylines.get(data.entityName)) {
this.updatePolyline(data, dataSource, this.options); this.updatePolyline(data, dataSource, this.options);
} }
else { else {
this.createPolyline(data, dataSource, this.options); this.createPolyline(data, dataSource, this.options);
} }
} }
else {
if (data)
this.removePolyline(dataSource[0]?.entityName)
}
}) })
} }
@ -363,22 +369,35 @@ export default abstract class LeafletMap {
dataSources.map(el => this.convertPosition(el)).filter(el => !!el), data, dataSources, settings); dataSources.map(el => this.convertPosition(el)).filter(el => !!el), data, dataSources, settings);
const bounds = poly.leafletPoly.getBounds(); const bounds = poly.leafletPoly.getBounds();
this.fitBounds(bounds); this.fitBounds(bounds);
this.polylines.set(data.$datasource.entityName, poly); this.polylines.set(data.entityName, poly);
}); });
} }
updatePolyline(data: FormattedData, dataSources: FormattedData[], settings: PolylineSettings) { updatePolyline(data: FormattedData, dataSources: FormattedData[], settings: PolylineSettings) {
this.ready$.subscribe(() => { this.ready$.subscribe(() => {
const poly = this.polylines.get(data.$datasource.entityName); const poly = this.polylines.get(data.entityName);
const oldBounds = poly.leafletPoly.getBounds();
poly.updatePolyline(dataSources.map(el => this.convertPosition(el)).filter(el => !!el), data, dataSources, settings); poly.updatePolyline(dataSources.map(el => this.convertPosition(el)).filter(el => !!el), data, dataSources, settings);
const newBounds = poly.leafletPoly.getBounds();
if (oldBounds.toBBoxString() !== newBounds.toBBoxString()) {
this.fitBounds(newBounds);
}
}); });
} }
removePolyline(name: string) {
const poly = this.polylines.get(name);
if (poly) {
this.map.removeLayer(poly.leafletPoly);
this.polylines.delete(name);
}
}
// Polygon // Polygon
updatePolygons(polyData: FormattedData[]) { updatePolygons(polyData: FormattedData[]) {
polyData.forEach((data: FormattedData) => { polyData.forEach((data: FormattedData) => {
if (data.hasOwnProperty(this.options.polygonKeyName)) { if (data && data.hasOwnProperty(this.options.polygonKeyName)) {
if (typeof (data[this.options.polygonKeyName]) === 'string') { if (typeof (data[this.options.polygonKeyName]) === 'string') {
data[this.options.polygonKeyName] = JSON.parse(data[this.options.polygonKeyName]) as LatLngTuple[]; data[this.options.polygonKeyName] = JSON.parse(data[this.options.polygonKeyName]) as LatLngTuple[];
} }
@ -403,8 +422,13 @@ export default abstract class LeafletMap {
updatePolygon(polyData: FormattedData, dataSources: FormattedData[], settings: PolygonSettings) { updatePolygon(polyData: FormattedData, dataSources: FormattedData[], settings: PolygonSettings) {
this.ready$.subscribe(() => { this.ready$.subscribe(() => {
const poly = this.polygons.get(polyData.$datasource.entityName); const poly = this.polygons.get(polyData.entityName);
const oldBounds = poly.leafletPoly.getBounds();
poly.updatePolygon(polyData, dataSources, settings); poly.updatePolygon(polyData, dataSources, settings);
const newBounds = poly.leafletPoly.getBounds();
if (oldBounds.toBBoxString() !== newBounds.toBBoxString()) {
this.fitBounds(newBounds);
}
}); });
} }
} }

View File

@ -26,6 +26,7 @@ import {
export type GenericFunction = (data: FormattedData, dsData: FormattedData[], dsIndex: number) => string; export type GenericFunction = (data: FormattedData, dsData: FormattedData[], dsIndex: number) => string;
export type MarkerImageFunction = (data: FormattedData, dsData: FormattedData[], dsIndex: number) => string; export type MarkerImageFunction = (data: FormattedData, dsData: FormattedData[], dsIndex: number) => string;
export type GetTooltip= (point: FormattedData, setTooltip?: boolean) => string;
export type MapSettings = { export type MapSettings = {
draggableMarker: boolean; draggableMarker: boolean;

View File

@ -69,7 +69,6 @@ export class MapWidgetController implements MapWidgetInterface {
this.settings.markerClick = this.getDescriptors('markerClick'); this.settings.markerClick = this.getDescriptors('markerClick');
this.settings.polygonClick = this.getDescriptors('polygonClick'); this.settings.polygonClick = this.getDescriptors('polygonClick');
// this.settings.
const MapClass = providerSets[this.provider]?.MapClass; const MapClass = providerSets[this.provider]?.MapClass;
if (!MapClass) { if (!MapClass) {
return; return;

View File

@ -258,7 +258,7 @@ export function parseArray(input: any[]): any[] {
time: el[0], time: el[0],
deviceType: null deviceType: null
}; };
entityArray.filter(e => e.data.length).forEach(entity => { entityArray.filter(e => e.data.length && e.data[i]).forEach(entity => {
obj[entity?.dataKey?.label] = entity?.data[i][1]; obj[entity?.dataKey?.label] = entity?.data[i][1];
obj[entity?.dataKey?.label + '|ts'] = entity?.data[0][0]; obj[entity?.dataKey?.label + '|ts'] = entity?.data[0][0];
if (entity?.dataKey?.label === 'type') { if (entity?.dataKey?.label === 'type') {

View File

@ -65,7 +65,6 @@ export class Polyline {
this.dataSources = dataSources; this.dataSources = dataSources;
this.leafletPoly.setLatLngs(locations); this.leafletPoly.setLatLngs(locations);
this.leafletPoly.setStyle(this.getPolyStyle(settings)); this.leafletPoly.setStyle(this.getPolyStyle(settings));
// this.setPolylineLatLngs(data);
if (this.polylineDecorator) if (this.polylineDecorator)
this.polylineDecorator.setPaths(this.leafletPoly); this.polylineDecorator.setPaths(this.leafletPoly);
} }
@ -92,8 +91,4 @@ export class Polyline {
getPolylineLatLngs() { getPolylineLatLngs() {
return this.leafletPoly.getLatLngs(); return this.leafletPoly.getLatLngs();
} }
setPolylineLatLngs(latLngs) {
this.leafletPoly.setLatLngs(latLngs);
}
} }

View File

@ -56,6 +56,7 @@ export class TripAnimationComponent implements OnInit, AfterViewInit {
historicalData: FormattedData[][]; historicalData: FormattedData[][];
normalizationStep: number; normalizationStep: number;
interpolatedTimeData = []; interpolatedTimeData = [];
intervals = [];
widgetConfig: WidgetConfig; widgetConfig: WidgetConfig;
settings; settings;
mainTooltip = ''; mainTooltip = '';
@ -68,6 +69,7 @@ export class TripAnimationComponent implements OnInit, AfterViewInit {
maxTimeFormat: string; maxTimeFormat: string;
anchors: number[] = []; anchors: number[] = [];
useAnchors: boolean; useAnchors: boolean;
currentTime: number;
static getSettingsSchema(): JsonSettingsSchema { static getSettingsSchema(): JsonSettingsSchema {
const schema = initSchema(); const schema = initSchema();
@ -99,17 +101,17 @@ export class TripAnimationComponent implements OnInit, AfterViewInit {
this.settings.fitMapBounds = true; this.settings.fitMapBounds = true;
this.normalizationStep = this.settings.normalizationStep; this.normalizationStep = this.settings.normalizationStep;
const subscription = this.ctx.subscriptions[Object.keys(this.ctx.subscriptions)[0]]; const subscription = this.ctx.subscriptions[Object.keys(this.ctx.subscriptions)[0]];
if (subscription) { if (subscription) subscription.callbacks.onDataUpdated = () => {
subscription.callbacks.onDataUpdated = () => { this.historicalData = parseArray(this.ctx.data).filter(arr => arr.length);
this.historicalData = parseArray(this.ctx.data); if (this.historicalData.length) {
this.activeTrip = this.historicalData[0][0]; this.activeTrip = this.historicalData[0][0];
this.calculateIntervals(); this.calculateIntervals();
this.timeUpdated(this.minTime); this.timeUpdated(this.minTime);
}
this.mapWidget.map.map?.invalidateSize(); this.mapWidget.map.map?.invalidateSize();
this.cd.detectChanges(); this.cd.detectChanges();
} }
} }
}
ngAfterViewInit() { ngAfterViewInit() {
const ctxCopy: WidgetContext = _.cloneDeep(this.ctx); const ctxCopy: WidgetContext = _.cloneDeep(this.ctx);
@ -117,8 +119,16 @@ export class TripAnimationComponent implements OnInit, AfterViewInit {
} }
timeUpdated(time: number) { timeUpdated(time: number) {
const currentPosition = this.interpolatedTimeData.map(dataSource => dataSource[time]); this.currentTime = time;
if(isUndefined(currentPosition[0])){ const currentPosition = this.interpolatedTimeData
.map(dataSource => dataSource[time])
.filter(ds => ds)
.map(ds => {
ds.minTime = this.minTimeFormat;
ds.maxTime = this.maxTimeFormat;
return ds;
});
if (isUndefined(currentPosition[0])) {
const timePoints = Object.keys(this.interpolatedTimeData[0]).map(item => parseInt(item, 10)); const timePoints = Object.keys(this.interpolatedTimeData[0]).map(item => parseInt(item, 10));
for (let i = 1; i < timePoints.length; i++) { for (let i = 1; i < timePoints.length; i++) {
if (timePoints[i - 1] < time && timePoints[i] > time) { if (timePoints[i - 1] < time && timePoints[i] > time) {
@ -134,7 +144,6 @@ export class TripAnimationComponent implements OnInit, AfterViewInit {
} }
} }
} }
this.activeTrip = currentPosition[0];
this.calcLabel(); this.calcLabel();
this.calcTooltip(); this.calcTooltip();
if (this.mapWidget) { if (this.mapWidget) {
@ -145,7 +154,10 @@ export class TripAnimationComponent implements OnInit, AfterViewInit {
if (this.settings.showPoints) { if (this.settings.showPoints) {
this.mapWidget.map.updatePoints(_.values(_.union(this.interpolatedTimeData)[0]), this.calcTooltip); this.mapWidget.map.updatePoints(_.values(_.union(this.interpolatedTimeData)[0]), this.calcTooltip);
} }
this.mapWidget.map.updateMarkers(currentPosition); this.mapWidget.map.updateMarkers(currentPosition, (trip) => {
this.activeTrip = trip;
this.timeUpdated(this.currentTime)
});
} }
} }
@ -185,6 +197,7 @@ export class TripAnimationComponent implements OnInit, AfterViewInit {
SecurityContext.HTML, tooltipText); SecurityContext.HTML, tooltipText);
this.cd.detectChanges(); this.cd.detectChanges();
} }
this.activeTrip = point;
return tooltipText; return tooltipText;
} }
@ -212,7 +225,7 @@ export class TripAnimationComponent implements OnInit, AfterViewInit {
}; };
} }
const timeStamp = Object.keys(result); const timeStamp = Object.keys(result);
for(let i = 0; i < timeStamp.length - 1; i++){ for (let i = 0; i < timeStamp.length - 1; i++) {
result[timeStamp[i]].rotationAngle += findAngle(result[timeStamp[i]], result[timeStamp[i + 1]], latKeyName, lngKeyName) result[timeStamp[i]].rotationAngle += findAngle(result[timeStamp[i]], result[timeStamp[i + 1]], latKeyName, lngKeyName)
} }
return result; return result;

View File

@ -85,7 +85,8 @@
formControlName="entityId"> formControlName="entityId">
</tb-entity-select> </tb-entity-select>
</section> </section>
<div formGroupName="keys"> <div class="mat-accordion-container" formGroupName="keys">
<mat-accordion [multi]="true">
<mat-expansion-panel formGroupName="attributes" [expanded]="true"> <mat-expansion-panel formGroupName="attributes" [expanded]="true">
<mat-expansion-panel-header> <mat-expansion-panel-header>
<mat-panel-title> <mat-panel-title>
@ -130,6 +131,7 @@
[dataKeyType]="dataKeyType.timeseries"> [dataKeyType]="dataKeyType.timeseries">
</tb-entity-keys-list> </tb-entity-keys-list>
</mat-expansion-panel> </mat-expansion-panel>
</mat-accordion>
</div> </div>
<tb-datetime <tb-datetime
dateText="entity-view.start-date" dateText="entity-view.start-date"

View File

@ -14,16 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
:host { :host {
mat-expansion-panel { .mat-accordion-container {
margin-bottom: 16px; margin-bottom: 16px;
} }
} }
.tb-dialog {
:host {
mat-expansion-panel {
margin-left: 6px;
margin-right: 6px;
}
}
}

View File

@ -14,9 +14,15 @@
* limitations under the License. * limitations under the License.
*/ */
:host ::ng-deep { :host ::ng-deep {
.mat-checkbox.hinted-checkbox { .mat-checkbox{
&.hinted-checkbox {
.mat-checkbox-inner-container { .mat-checkbox-inner-container {
margin-top: 4px; margin-top: 4px;
} }
} }
.mat-checkbox-layout{
white-space: normal;
}
}
} }

View File

@ -864,7 +864,6 @@ mat-label {
min-width: 100%; min-width: 100%;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
overflow: auto;
} }
.mat-dialog-content { .mat-dialog-content {
margin: 0; margin: 0;
@ -914,7 +913,7 @@ mat-label {
.mat-dialog-container { .mat-dialog-container {
> *:first-child, form { > *:first-child, form {
min-width: 100% !important; min-width: 100% !important;
height: 100vh; height: 100%;
} }
.mat-dialog-content { .mat-dialog-content {
max-height: 100%; max-height: 100%;