Commit f9574d7041a453efaa9cc72a836c6231b3880b76

Authored by Adsumus
2 parents 8979a511 a868f006

Merge branch 'develop/3.0' of https://github.com/thingsboard/thingsboard into map/3.0

Showing 34 changed files with 187 additions and 174 deletions
@@ -13,9 +13,9 @@ Before performing initial installation you can configure the type of database to @@ -13,9 +13,9 @@ Before performing initial installation you can configure the type of database to
13 In order to set database type change the value of `DATABASE` variable in `.env` file to one of the following: 13 In order to set database type change the value of `DATABASE` variable in `.env` file to one of the following:
14 14
15 - `postgres` - use PostgreSQL database; 15 - `postgres` - use PostgreSQL database;
16 -- `cassandra` - use Cassandra database; 16 +- `hybrid` - use PostgreSQL for entities database and Cassandra for timeseries database;
17 17
18 -**NOTE**: According to the database type corresponding docker service will be deployed (see `docker-compose.postgres.yml`, `docker-compose.cassandra.yml` for details). 18 +**NOTE**: According to the database type corresponding docker service will be deployed (see `docker-compose.postgres.yml`, `docker-compose.hybrid.yml` for details).
19 19
20 Execute the following command to create log folders for the services and chown of these folders to the docker container users. 20 Execute the following command to create log folders for the services and chown of these folders to the docker container users.
21 To be able to change user, **chown** command is used, which requires sudo permissions (script will request password for a sudo access): 21 To be able to change user, **chown** command is used, which requires sudo permissions (script will request password for a sudo access):
1 { 1 {
2 "name": "thingsboard-js-executor", 2 "name": "thingsboard-js-executor",
3 - "version": "2.4.3", 3 + "version": "3.0.0",
4 "lockfileVersion": 1, 4 "lockfileVersion": 1,
5 "requires": true, 5 "requires": true,
6 "dependencies": { 6 "dependencies": {
1 { 1 {
2 "name": "thingsboard-web-ui", 2 "name": "thingsboard-web-ui",
3 - "version": "2.4.3", 3 + "version": "3.0.0",
4 "lockfileVersion": 1, 4 "lockfileVersion": 1,
5 "requires": true, 5 "requires": true,
6 "dependencies": { 6 "dependencies": {
@@ -49,7 +49,6 @@ @@ -49,7 +49,6 @@
49 ] 49 ]
50 }, 50 },
51 "scripts": [ 51 "scripts": [
52 - "node_modules/javascript-detect-element-resize/detect-element-resize.js",  
53 "node_modules/jquery/dist/jquery.min.js", 52 "node_modules/jquery/dist/jquery.min.js",
54 "node_modules/jquery.terminal/js/jquery.terminal.min.js", 53 "node_modules/jquery.terminal/js/jquery.terminal.min.js",
55 "node_modules/flot/lib/jquery.colorhelpers.js", 54 "node_modules/flot/lib/jquery.colorhelpers.js",
@@ -1561,6 +1561,11 @@ @@ -1561,6 +1561,11 @@
1561 } 1561 }
1562 } 1562 }
1563 }, 1563 },
  1564 + "@juggle/resize-observer": {
  1565 + "version": "3.1.3",
  1566 + "resolved": "https://registry.npmjs.org/@juggle/resize-observer/-/resize-observer-3.1.3.tgz",
  1567 + "integrity": "sha512-y7qc6SzZBlSpx8hEDfV0S9Cx6goROX/vBhS2Ru1Q78Jp1FlCMbxp7UcAN90rLgB3X8DSMBgDFxcmoG/VfdAhFA=="
  1568 + },
1564 "@mat-datetimepicker/core": { 1569 "@mat-datetimepicker/core": {
1565 "version": "4.1.0", 1570 "version": "4.1.0",
1566 "resolved": "https://registry.npmjs.org/@mat-datetimepicker/core/-/core-4.1.0.tgz", 1571 "resolved": "https://registry.npmjs.org/@mat-datetimepicker/core/-/core-4.1.0.tgz",
@@ -7083,11 +7088,6 @@ @@ -7083,11 +7088,6 @@
7083 "integrity": "sha1-43zwsX8ZnM4jvqcbIDk5Uka07E4=", 7088 "integrity": "sha1-43zwsX8ZnM4jvqcbIDk5Uka07E4=",
7084 "dev": true 7089 "dev": true
7085 }, 7090 },
7086 - "javascript-detect-element-resize": {  
7087 - "version": "0.5.3",  
7088 - "resolved": "https://registry.npmjs.org/javascript-detect-element-resize/-/javascript-detect-element-resize-0.5.3.tgz",  
7089 - "integrity": "sha1-GnHNUd/lZZB/KZAS/nOilBBAJd4="  
7090 - },  
7091 "jest-worker": { 7091 "jest-worker": {
7092 "version": "25.1.0", 7092 "version": "25.1.0",
7093 "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-25.1.0.tgz", 7093 "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-25.1.0.tgz",
@@ -28,6 +28,7 @@ @@ -28,6 +28,7 @@
28 "@date-io/date-fns": "^2.6.1", 28 "@date-io/date-fns": "^2.6.1",
29 "@flowjs/flow.js": "^2.14.0", 29 "@flowjs/flow.js": "^2.14.0",
30 "@flowjs/ngx-flow": "^0.4.3", 30 "@flowjs/ngx-flow": "^0.4.3",
  31 + "@juggle/resize-observer": "^3.1.3",
31 "@mat-datetimepicker/core": "^4.1.0", 32 "@mat-datetimepicker/core": "^4.1.0",
32 "@material-ui/core": "^4.9.11", 33 "@material-ui/core": "^4.9.11",
33 "@material-ui/icons": "^4.9.1", 34 "@material-ui/icons": "^4.9.1",
@@ -49,7 +50,6 @@ @@ -49,7 +50,6 @@
49 "flot": "git://github.com/thingsboard/flot.git#0.9-work", 50 "flot": "git://github.com/thingsboard/flot.git#0.9-work",
50 "flot.curvedlines": "git://github.com/MichaelZinsmaier/CurvedLines.git#master", 51 "flot.curvedlines": "git://github.com/MichaelZinsmaier/CurvedLines.git#master",
51 "font-awesome": "^4.7.0", 52 "font-awesome": "^4.7.0",
52 - "javascript-detect-element-resize": "^0.5.3",  
53 "jquery": "^3.5.0", 53 "jquery": "^3.5.0",
54 "jquery.terminal": "^2.15.4", 54 "jquery.terminal": "^2.15.4",
55 "js-beautify": "^1.11.0", 55 "js-beautify": "^1.11.0",
@@ -123,7 +123,7 @@ export class AliasController implements IAliasController { @@ -123,7 +123,7 @@ export class AliasController implements IAliasController {
123 } 123 }
124 124
125 getAliasInfo(aliasId: string): Observable<AliasInfo> { 125 getAliasInfo(aliasId: string): Observable<AliasInfo> {
126 - const aliasInfo = this.resolvedAliases[aliasId]; 126 + let aliasInfo = this.resolvedAliases[aliasId];
127 if (aliasInfo) { 127 if (aliasInfo) {
128 return of(aliasInfo); 128 return of(aliasInfo);
129 } else if (this.resolvedAliasesObservable[aliasId]) { 129 } else if (this.resolvedAliasesObservable[aliasId]) {
@@ -159,7 +159,12 @@ export class AliasController implements IAliasController { @@ -159,7 +159,12 @@ export class AliasController implements IAliasController {
159 delete this.resolvedAliasesObservable[aliasId]; 159 delete this.resolvedAliasesObservable[aliasId];
160 return res; 160 return res;
161 } 161 }
162 - return this.resolvedAliasesObservable[aliasId]; 162 + aliasInfo = this.resolvedAliases[aliasId];
  163 + if (aliasInfo) {
  164 + return of(aliasInfo);
  165 + } else {
  166 + return this.resolvedAliasesObservable[aliasId];
  167 + }
163 } 168 }
164 } 169 }
165 170
@@ -19,7 +19,7 @@ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; @@ -19,7 +19,7 @@ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
19 import { Store } from '@ngrx/store'; 19 import { Store } from '@ngrx/store';
20 import { AppState } from '@core/core.state'; 20 import { AppState } from '@core/core.state';
21 import { FormBuilder, FormGroup } from '@angular/forms'; 21 import { FormBuilder, FormGroup } from '@angular/forms';
22 -import { Observable, Subject } from 'rxjs'; 22 +import { Observable, ReplaySubject } from 'rxjs';
23 import { Router } from '@angular/router'; 23 import { Router } from '@angular/router';
24 import { DialogComponent } from '@app/shared/components/dialog.component'; 24 import { DialogComponent } from '@app/shared/components/dialog.component';
25 import { 25 import {
@@ -30,7 +30,7 @@ import { @@ -30,7 +30,7 @@ import {
30 alarmStatusTranslations 30 alarmStatusTranslations
31 } from '@app/shared/models/alarm.models'; 31 } from '@app/shared/models/alarm.models';
32 import { AlarmService } from '@core/http/alarm.service'; 32 import { AlarmService } from '@core/http/alarm.service';
33 -import { share, tap } from 'rxjs/operators'; 33 +import { tap } from 'rxjs/operators';
34 import { DatePipe } from '@angular/common'; 34 import { DatePipe } from '@angular/common';
35 import { TranslateService } from '@ngx-translate/core'; 35 import { TranslateService } from '@ngx-translate/core';
36 36
@@ -54,10 +54,9 @@ export class AlarmDetailsDialogComponent extends DialogComponent<AlarmDetailsDia @@ -54,10 +54,9 @@ export class AlarmDetailsDialogComponent extends DialogComponent<AlarmDetailsDia
54 allowClear: boolean; 54 allowClear: boolean;
55 displayDetails: boolean; 55 displayDetails: boolean;
56 56
57 - loadAlarmSubject = new Subject<AlarmInfo>(); 57 + loadAlarmSubject = new ReplaySubject<AlarmInfo>();
58 alarm$: Observable<AlarmInfo> = this.loadAlarmSubject.asObservable().pipe( 58 alarm$: Observable<AlarmInfo> = this.loadAlarmSubject.asObservable().pipe(
59 - tap(alarm => this.loadAlarmFields(alarm)),  
60 - share() 59 + tap(alarm => this.loadAlarmFields(alarm))
61 ); 60 );
62 61
63 alarmSeverityColorsMap = alarmSeverityColors; 62 alarmSeverityColorsMap = alarmSeverityColors;
@@ -43,6 +43,6 @@ export class AlarmTableHeaderComponent extends EntityTableHeaderComponent<AlarmI @@ -43,6 +43,6 @@ export class AlarmTableHeaderComponent extends EntityTableHeaderComponent<AlarmI
43 43
44 searchStatusChanged(searchStatus: AlarmSearchStatus) { 44 searchStatusChanged(searchStatus: AlarmSearchStatus) {
45 this.alarmTableConfig.searchStatus = searchStatus; 45 this.alarmTableConfig.searchStatus = searchStatus;
46 - this.alarmTableConfig.table.updateData(); 46 + this.alarmTableConfig.table.resetSortAndFilter(true, true);
47 } 47 }
48 } 48 }
@@ -63,12 +63,16 @@ export class AliasesEntitySelectComponent implements OnInit, OnDestroy { @@ -63,12 +63,16 @@ export class AliasesEntitySelectComponent implements OnInit, OnDestroy {
63 ngOnInit(): void { 63 ngOnInit(): void {
64 this.rxSubscriptions.push(this.aliasController.entityAliasesChanged.subscribe( 64 this.rxSubscriptions.push(this.aliasController.entityAliasesChanged.subscribe(
65 () => { 65 () => {
66 - this.updateDisplayValue(); 66 + setTimeout(() => {
  67 + this.updateDisplayValue();
  68 + }, 0);
67 } 69 }
68 )); 70 ));
69 this.rxSubscriptions.push(this.aliasController.entityAliasResolved.subscribe( 71 this.rxSubscriptions.push(this.aliasController.entityAliasResolved.subscribe(
70 () => { 72 () => {
71 - this.updateDisplayValue(); 73 + setTimeout(() => {
  74 + this.updateDisplayValue();
  75 + }, 0);
72 } 76 }
73 )); 77 ));
74 } 78 }
@@ -53,6 +53,7 @@ import { Widget, WidgetPosition } from '@app/shared/models/widget.models'; @@ -53,6 +53,7 @@ import { Widget, WidgetPosition } from '@app/shared/models/widget.models';
53 import { MatMenuTrigger } from '@angular/material/menu'; 53 import { MatMenuTrigger } from '@angular/material/menu';
54 import { SafeStyle } from '@angular/platform-browser'; 54 import { SafeStyle } from '@angular/platform-browser';
55 import { distinct } from 'rxjs/operators'; 55 import { distinct } from 'rxjs/operators';
  56 +import { ResizeObserver } from '@juggle/resize-observer';
56 57
57 @Component({ 58 @Component({
58 selector: 'tb-dashboard', 59 selector: 'tb-dashboard',
@@ -166,7 +167,7 @@ export class DashboardComponent extends PageComponent implements IDashboardCompo @@ -166,7 +167,7 @@ export class DashboardComponent extends PageComponent implements IDashboardCompo
166 167
167 private optionsChangeNotificationsPaused = false; 168 private optionsChangeNotificationsPaused = false;
168 169
169 - private gridsterResizeListener = null; 170 + private gridsterResize$: ResizeObserver;
170 171
171 constructor(protected store: Store<AppState>, 172 constructor(protected store: Store<AppState>,
172 private timeService: TimeService, 173 private timeService: TimeService,
@@ -225,9 +226,8 @@ export class DashboardComponent extends PageComponent implements IDashboardCompo @@ -225,9 +226,8 @@ export class DashboardComponent extends PageComponent implements IDashboardCompo
225 226
226 ngOnDestroy(): void { 227 ngOnDestroy(): void {
227 super.ngOnDestroy(); 228 super.ngOnDestroy();
228 - if (this.gridsterResizeListener) {  
229 - // @ts-ignore  
230 - removeResizeListener(this.gridster.el, this.gridsterResizeListener); 229 + if (this.gridsterResize$) {
  230 + this.gridsterResize$.disconnect();
231 } 231 }
232 if (this.breakpointObserverSubscription) { 232 if (this.breakpointObserverSubscription) {
233 this.breakpointObserverSubscription.unsubscribe(); 233 this.breakpointObserverSubscription.unsubscribe();
@@ -290,9 +290,10 @@ export class DashboardComponent extends PageComponent implements IDashboardCompo @@ -290,9 +290,10 @@ export class DashboardComponent extends PageComponent implements IDashboardCompo
290 } 290 }
291 291
292 ngAfterViewInit(): void { 292 ngAfterViewInit(): void {
293 - this.gridsterResizeListener = this.onGridsterParentResize.bind(this);  
294 - // @ts-ignore  
295 - addResizeListener(this.gridster.el, this.gridsterResizeListener); 293 + this.gridsterResize$ = new ResizeObserver(() => {
  294 + this.onGridsterParentResize()
  295 + });
  296 + this.gridsterResize$.observe(this.gridster.el);
296 } 297 }
297 298
298 onUpdateTimewindow(startTimeMs: number, endTimeMs: number, interval?: number, persist?: boolean): void { 299 onUpdateTimewindow(startTimeMs: number, endTimeMs: number, interval?: number, persist?: boolean): void {
@@ -491,8 +492,8 @@ export class DashboardComponent extends PageComponent implements IDashboardCompo @@ -491,8 +492,8 @@ export class DashboardComponent extends PageComponent implements IDashboardCompo
491 const parentHeight = this.gridster.el.offsetHeight; 492 const parentHeight = this.gridster.el.offsetHeight;
492 if (this.isMobileSize && this.mobileAutofillHeight && parentHeight) { 493 if (this.isMobileSize && this.mobileAutofillHeight && parentHeight) {
493 this.updateMobileOpts(parentHeight); 494 this.updateMobileOpts(parentHeight);
494 - this.notifyGridsterOptionsChanged();  
495 } 495 }
  496 + this.notifyGridsterOptionsChanged();
496 } 497 }
497 498
498 private updateLayoutOpts() { 499 private updateLayoutOpts() {
@@ -434,9 +434,9 @@ export class EntitiesTableComponent extends PageComponent implements AfterViewIn @@ -434,9 +434,9 @@ export class EntitiesTableComponent extends PageComponent implements AfterViewIn
434 this.updateData(); 434 this.updateData();
435 } 435 }
436 436
437 - resetSortAndFilter(update: boolean = true) { 437 + resetSortAndFilter(update: boolean = true, preserveTimewindow: boolean = false) {
438 this.pageLink.textSearch = null; 438 this.pageLink.textSearch = null;
439 - if (this.entitiesTableConfig.useTimePageLink) { 439 + if (this.entitiesTableConfig.useTimePageLink && !preserveTimewindow) {
440 this.timewindow = historyInterval(DAY); 440 this.timewindow = historyInterval(DAY);
441 } 441 }
442 if (this.displayPagination) { 442 if (this.displayPagination) {
@@ -40,6 +40,6 @@ export class EventTableHeaderComponent extends EntityTableHeaderComponent<Event> @@ -40,6 +40,6 @@ export class EventTableHeaderComponent extends EntityTableHeaderComponent<Event>
40 40
41 eventTypeChanged(eventType: EventType | DebugEventType) { 41 eventTypeChanged(eventType: EventType | DebugEventType) {
42 this.eventTableConfig.eventType = eventType; 42 this.eventTableConfig.eventType = eventType;
43 - this.eventTableConfig.table.updateData(); 43 + this.eventTableConfig.table.resetSortAndFilter(true, true);
44 } 44 }
45 } 45 }
@@ -35,6 +35,7 @@ import { CustomActionDescriptor } from '@shared/models/widget.models'; @@ -35,6 +35,7 @@ import { CustomActionDescriptor } from '@shared/models/widget.models';
35 import * as ace from 'ace-builds'; 35 import * as ace from 'ace-builds';
36 import { CancelAnimationFrame, RafService } from '@core/services/raf.service'; 36 import { CancelAnimationFrame, RafService } from '@core/services/raf.service';
37 import { css_beautify, html_beautify } from 'js-beautify'; 37 import { css_beautify, html_beautify } from 'js-beautify';
  38 +import { ResizeObserver } from '@juggle/resize-observer';
38 39
39 @Component({ 40 @Component({
40 selector: 'tb-custom-action-pretty-resources-tabs', 41 selector: 'tb-custom-action-pretty-resources-tabs',
@@ -64,7 +65,7 @@ export class CustomActionPrettyResourcesTabsComponent extends PageComponent impl @@ -64,7 +65,7 @@ export class CustomActionPrettyResourcesTabsComponent extends PageComponent impl
64 65
65 aceEditors: ace.Ace.Editor[] = []; 66 aceEditors: ace.Ace.Editor[] = [];
66 editorsResizeCafs: {[editorId: string]: CancelAnimationFrame} = {}; 67 editorsResizeCafs: {[editorId: string]: CancelAnimationFrame} = {};
67 - aceResizeListeners: { element: any, resizeListener: any }[] = []; 68 + aceResize$: ResizeObserver;
68 htmlEditor: ace.Ace.Editor; 69 htmlEditor: ace.Ace.Editor;
69 cssEditor: ace.Ace.Editor; 70 cssEditor: ace.Ace.Editor;
70 setValuesPending = false; 71 setValuesPending = false;
@@ -84,10 +85,7 @@ export class CustomActionPrettyResourcesTabsComponent extends PageComponent impl @@ -84,10 +85,7 @@ export class CustomActionPrettyResourcesTabsComponent extends PageComponent impl
84 } 85 }
85 86
86 ngOnDestroy(): void { 87 ngOnDestroy(): void {
87 - this.aceResizeListeners.forEach((resizeListener) => {  
88 - // @ts-ignore  
89 - removeResizeListener(resizeListener.element, resizeListener.resizeListener);  
90 - }); 88 + this.aceResize$.disconnect();
91 } 89 }
92 90
93 ngOnChanges(changes: SimpleChanges): void { 91 ngOnChanges(changes: SimpleChanges): void {
@@ -153,6 +151,12 @@ export class CustomActionPrettyResourcesTabsComponent extends PageComponent impl @@ -153,6 +151,12 @@ export class CustomActionPrettyResourcesTabsComponent extends PageComponent impl
153 } 151 }
154 152
155 private initAceEditors() { 153 private initAceEditors() {
  154 + this.aceResize$ = new ResizeObserver((entries) => {
  155 + entries.forEach((entry) => {
  156 + const editor = this.aceEditors.find(aceEditor => aceEditor.container === entry.target);
  157 + this.onAceEditorResize(editor);
  158 + })
  159 + });
156 this.htmlEditor = this.createAceEditor(this.htmlInputElmRef, 'html'); 160 this.htmlEditor = this.createAceEditor(this.htmlInputElmRef, 'html');
157 this.htmlEditor.on('input', () => { 161 this.htmlEditor.on('input', () => {
158 const editorValue = this.htmlEditor.getValue(); 162 const editorValue = this.htmlEditor.getValue();
@@ -187,12 +191,7 @@ export class CustomActionPrettyResourcesTabsComponent extends PageComponent impl @@ -187,12 +191,7 @@ export class CustomActionPrettyResourcesTabsComponent extends PageComponent impl
187 const aceEditor = ace.edit(editorElement, editorOptions); 191 const aceEditor = ace.edit(editorElement, editorOptions);
188 aceEditor.session.setUseWrapMode(true); 192 aceEditor.session.setUseWrapMode(true);
189 this.aceEditors.push(aceEditor); 193 this.aceEditors.push(aceEditor);
190 -  
191 - const resizeListener = this.onAceEditorResize.bind(this, aceEditor);  
192 -  
193 - // @ts-ignore  
194 - addResizeListener(editorElement, resizeListener);  
195 - this.aceResizeListeners.push({element: editorElement, resizeListener}); 194 + this.aceResize$.observe(editorElement);
196 return aceEditor; 195 return aceEditor;
197 } 196 }
198 197
@@ -84,9 +84,6 @@ export class DateRangeNavigatorWidgetComponent extends PageComponent implements @@ -84,9 +84,6 @@ export class DateRangeNavigatorWidgetComponent extends PageComponent implements
84 } 84 }
85 85
86 ngOnInit(): void { 86 ngOnInit(): void {
87 - this.dashboardTimewindowChangedSubscription = this.ctx.dashboard.dashboardTimewindowChanged.subscribe(() => {  
88 - this.widgetContextTimewindowSync();  
89 - });  
90 this.settings = this.ctx.settings; 87 this.settings = this.ctx.settings;
91 this.settings.useSessionStorage = isDefined(this.settings.useSessionStorage) ? this.settings.useSessionStorage : true; 88 this.settings.useSessionStorage = isDefined(this.settings.useSessionStorage) ? this.settings.useSessionStorage : true;
92 let selection; 89 let selection;
@@ -110,6 +107,9 @@ export class DateRangeNavigatorWidgetComponent extends PageComponent implements @@ -110,6 +107,9 @@ export class DateRangeNavigatorWidgetComponent extends PageComponent implements
110 } 107 }
111 this.selectedStepSize = this.datesMap[this.settings.stepSize || 'day'].ts; 108 this.selectedStepSize = this.datesMap[this.settings.stepSize || 'day'].ts;
112 this.widgetContextTimewindowSync(); 109 this.widgetContextTimewindowSync();
  110 + this.dashboardTimewindowChangedSubscription = this.ctx.dashboard.dashboardTimewindowChanged.subscribe(() => {
  111 + this.widgetContextTimewindowSync();
  112 + });
113 } 113 }
114 114
115 ngOnDestroy(): void { 115 ngOnDestroy(): void {
@@ -58,6 +58,7 @@ import { AttributeData, AttributeScope } from '@shared/models/telemetry/telemetr @@ -58,6 +58,7 @@ import { AttributeData, AttributeScope } from '@shared/models/telemetry/telemetr
58 import { forkJoin, Observable } from 'rxjs'; 58 import { forkJoin, Observable } from 'rxjs';
59 import { tap } from 'rxjs/operators'; 59 import { tap } from 'rxjs/operators';
60 import { ImportExportService } from '@home/components/import-export/import-export.service'; 60 import { ImportExportService } from '@home/components/import-export/import-export.service';
  61 +import { ResizeObserver } from '@juggle/resize-observer';
61 62
62 // @dynamic 63 // @dynamic
63 @Component({ 64 @Component({
@@ -93,7 +94,7 @@ export class GatewayFormComponent extends PageComponent implements OnInit, OnDes @@ -93,7 +94,7 @@ export class GatewayFormComponent extends PageComponent implements OnInit, OnDes
93 private successfulSaved: string; 94 private successfulSaved: string;
94 private gatewayNameExists: string; 95 private gatewayNameExists: string;
95 private archiveFileName: string; 96 private archiveFileName: string;
96 - private formResizeListener: any; 97 + private formResize$: ResizeObserver;
97 private subscribeStorageType$: any; 98 private subscribeStorageType$: any;
98 private subscribeGateway$: any; 99 private subscribeGateway$: any;
99 100
@@ -116,15 +117,15 @@ export class GatewayFormComponent extends PageComponent implements OnInit, OnDes @@ -116,15 +117,15 @@ export class GatewayFormComponent extends PageComponent implements OnInit, OnDes
116 117
117 this.buildForm(); 118 this.buildForm();
118 this.ctx.updateWidgetParams(); 119 this.ctx.updateWidgetParams();
119 - this.formResizeListener = this.resize.bind(this);  
120 - // @ts-ignore  
121 - addResizeListener(this.formContainerRef.nativeElement, this.formResizeListener); 120 + this.formResize$ = new ResizeObserver(() => {
  121 + this.resize();
  122 + });
  123 + this.formResize$.observe(this.formContainerRef.nativeElement);
122 } 124 }
123 125
124 ngOnDestroy(): void { 126 ngOnDestroy(): void {
125 - if (this.formResizeListener) {  
126 - // @ts-ignore  
127 - removeResizeListener(this.formContainerRef.nativeElement, this.formResizeListener); 127 + if (this.formResize$) {
  128 + this.formResize$.disconnect();
128 } 129 }
129 this.subscribeGateway$.unsubscribe(); 130 this.subscribeGateway$.unsubscribe();
130 this.subscribeStorageType$.unsubscribe(); 131 this.subscribeStorageType$.unsubscribe();
@@ -33,6 +33,7 @@ import { AttributeService } from '@core/http/attribute.service'; @@ -33,6 +33,7 @@ import { AttributeService } from '@core/http/attribute.service';
33 import { AttributeData, AttributeScope, LatestTelemetry } from '@shared/models/telemetry/telemetry.models'; 33 import { AttributeData, AttributeScope, LatestTelemetry } from '@shared/models/telemetry/telemetry.models';
34 import { forkJoin, Observable } from 'rxjs'; 34 import { forkJoin, Observable } from 'rxjs';
35 import { EntityId } from '@shared/models/id/entity-id'; 35 import { EntityId } from '@shared/models/id/entity-id';
  36 +import { ResizeObserver } from '@juggle/resize-observer';
36 37
37 type FieldAlignment = 'row' | 'column'; 38 type FieldAlignment = 'row' | 'column';
38 39
@@ -94,7 +95,7 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni @@ -94,7 +95,7 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni
94 @Input() 95 @Input()
95 ctx: WidgetContext; 96 ctx: WidgetContext;
96 97
97 - private formResizeListener: any; 98 + private formResize$: ResizeObserver;
98 private settings: MultipleInputWidgetSettings; 99 private settings: MultipleInputWidgetSettings;
99 private widgetConfig: WidgetConfig; 100 private widgetConfig: WidgetConfig;
100 private subscription: IWidgetSubscription; 101 private subscription: IWidgetSubscription;
@@ -135,15 +136,15 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni @@ -135,15 +136,15 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni
135 this.updateDatasources(); 136 this.updateDatasources();
136 this.buildForm(); 137 this.buildForm();
137 this.ctx.updateWidgetParams(); 138 this.ctx.updateWidgetParams();
138 - this.formResizeListener = this.resize.bind(this);  
139 - // @ts-ignore  
140 - addResizeListener(this.formContainerRef.nativeElement, this.formResizeListener); 139 + this.formResize$ = new ResizeObserver(() => {
  140 + this.resize();
  141 + });
  142 + this.formResize$.observe(this.formContainerRef.nativeElement);
141 } 143 }
142 144
143 ngOnDestroy(): void { 145 ngOnDestroy(): void {
144 - if (this.formResizeListener) {  
145 - // @ts-ignore  
146 - removeResizeListener(this.formContainerRef.nativeElement, this.formResizeListener); 146 + if (this.formResize$) {
  147 + this.formResize$.disconnect();
147 } 148 }
148 } 149 }
149 150
@@ -22,9 +22,9 @@ import { Store } from '@ngrx/store'; @@ -22,9 +22,9 @@ import { Store } from '@ngrx/store';
22 import { AppState } from '@core/core.state'; 22 import { AppState } from '@core/core.state';
23 import { isDefined, isNumber } from '@core/utils'; 23 import { isDefined, isNumber } from '@core/utils';
24 import { CanvasDigitalGauge, CanvasDigitalGaugeOptions } from '@home/components/widget/lib/canvas-digital-gauge'; 24 import { CanvasDigitalGauge, CanvasDigitalGaugeOptions } from '@home/components/widget/lib/canvas-digital-gauge';
25 -import GenericOptions = CanvasGauges.GenericOptions;  
26 import * as tinycolor_ from 'tinycolor2'; 25 import * as tinycolor_ from 'tinycolor2';
27 -import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; 26 +import GenericOptions = CanvasGauges.GenericOptions;
  27 +import { ResizeObserver } from '@juggle/resize-observer';
28 28
29 const tinycolor = tinycolor_; 29 const tinycolor = tinycolor_;
30 30
@@ -103,7 +103,7 @@ export class KnobComponent extends PageComponent implements OnInit, OnDestroy { @@ -103,7 +103,7 @@ export class KnobComponent extends PageComponent implements OnInit, OnDestroy {
103 103
104 private canvasBar: CanvasDigitalGauge; 104 private canvasBar: CanvasDigitalGauge;
105 105
106 - private knobResizeListener: any; 106 + private knobResize$: ResizeObserver;
107 107
108 constructor(private utils: UtilsService, 108 constructor(private utils: UtilsService,
109 protected store: Store<AppState>) { 109 protected store: Store<AppState>) {
@@ -126,16 +126,16 @@ export class KnobComponent extends PageComponent implements OnInit, OnDestroy { @@ -126,16 +126,16 @@ export class KnobComponent extends PageComponent implements OnInit, OnDestroy {
126 this.textMeasure = $(this.textMeasureRef.nativeElement); 126 this.textMeasure = $(this.textMeasureRef.nativeElement);
127 this.canvasBarElement = this.canvasBarElementRef.nativeElement; 127 this.canvasBarElement = this.canvasBarElementRef.nativeElement;
128 128
129 - this.knobResizeListener = this.resize.bind(this);  
130 - // @ts-ignore  
131 - addResizeListener(this.knobContainerRef.nativeElement, this.knobResizeListener); 129 + this.knobResize$ = new ResizeObserver(() => {
  130 + this.resize();
  131 + });
  132 + this.knobResize$.observe(this.knobContainerRef.nativeElement);
132 this.init(); 133 this.init();
133 } 134 }
134 135
135 ngOnDestroy(): void { 136 ngOnDestroy(): void {
136 - if (this.knobResizeListener) {  
137 - // @ts-ignore  
138 - removeResizeListener(this.knobContainerRef.nativeElement, this.knobResizeListener); 137 + if (this.knobResize$) {
  138 + this.knobResize$.disconnect();
139 } 139 }
140 } 140 }
141 141
@@ -25,6 +25,7 @@ import { UtilsService } from '@core/services/utils.service'; @@ -25,6 +25,7 @@ import { UtilsService } from '@core/services/utils.service';
25 import { IWidgetSubscription, SubscriptionInfo, WidgetSubscriptionOptions } from '@core/api/widget-api.models'; 25 import { IWidgetSubscription, SubscriptionInfo, WidgetSubscriptionOptions } from '@core/api/widget-api.models';
26 import { DatasourceType, widgetType } from '@shared/models/widget.models'; 26 import { DatasourceType, widgetType } from '@shared/models/widget.models';
27 import { EntityType } from '@shared/models/entity-type.models'; 27 import { EntityType } from '@shared/models/entity-type.models';
  28 +import { ResizeObserver } from '@juggle/resize-observer';
28 import Timeout = NodeJS.Timeout; 29 import Timeout = NodeJS.Timeout;
29 30
30 const tinycolor = tinycolor_; 31 const tinycolor = tinycolor_;
@@ -93,7 +94,7 @@ export class LedIndicatorComponent extends PageComponent implements OnInit, OnDe @@ -93,7 +94,7 @@ export class LedIndicatorComponent extends PageComponent implements OnInit, OnDe
93 private ledErrorContainer: JQuery<HTMLElement>; 94 private ledErrorContainer: JQuery<HTMLElement>;
94 private ledError: JQuery<HTMLElement>; 95 private ledError: JQuery<HTMLElement>;
95 96
96 - private ledResizeListener: any; 97 + private ledResize$: ResizeObserver;
97 98
98 private subscriptionOptions: WidgetSubscriptionOptions = { 99 private subscriptionOptions: WidgetSubscriptionOptions = {
99 callbacks: { 100 callbacks: {
@@ -122,9 +123,10 @@ export class LedIndicatorComponent extends PageComponent implements OnInit, OnDe @@ -122,9 +123,10 @@ export class LedIndicatorComponent extends PageComponent implements OnInit, OnDe
122 this.ledErrorContainer = $(this.ledErrorContainerRef.nativeElement); 123 this.ledErrorContainer = $(this.ledErrorContainerRef.nativeElement);
123 this.ledError = $(this.ledErrorRef.nativeElement); 124 this.ledError = $(this.ledErrorRef.nativeElement);
124 125
125 - this.ledResizeListener = this.resize.bind(this);  
126 - // @ts-ignore  
127 - addResizeListener(this.ledContainerRef.nativeElement, this.ledResizeListener); 126 + this.ledResize$ = new ResizeObserver(() => {
  127 + this.resize();
  128 + });
  129 + this.ledResize$.observe(this.ledContainerRef.nativeElement);
128 this.init(); 130 this.init();
129 } 131 }
130 132
@@ -136,9 +138,8 @@ export class LedIndicatorComponent extends PageComponent implements OnInit, OnDe @@ -136,9 +138,8 @@ export class LedIndicatorComponent extends PageComponent implements OnInit, OnDe
136 if (this.subscription) { 138 if (this.subscription) {
137 this.ctx.subscriptionApi.removeSubscription(this.subscription.id); 139 this.ctx.subscriptionApi.removeSubscription(this.subscription.id);
138 } 140 }
139 - if (this.ledResizeListener) {  
140 - // @ts-ignore  
141 - removeResizeListener(this.ledContainerRef.nativeElement, this.ledResizeListener); 141 + if (this.ledResize$) {
  142 + this.ledResize$.disconnect();
142 } 143 }
143 } 144 }
144 145
@@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
14 /// limitations under the License. 14 /// limitations under the License.
15 /// 15 ///
16 16
17 -import { AfterViewInit, Component, ElementRef, Input, OnDestroy, OnInit, ViewChild } from '@angular/core'; 17 +import { Component, ElementRef, Input, OnDestroy, OnInit, ViewChild } from '@angular/core';
18 import { PageComponent } from '@shared/components/page.component'; 18 import { PageComponent } from '@shared/components/page.component';
19 import { WidgetContext } from '@home/models/widget-component.models'; 19 import { WidgetContext } from '@home/models/widget-component.models';
20 import { UtilsService } from '@core/services/utils.service'; 20 import { UtilsService } from '@core/services/utils.service';
@@ -24,6 +24,7 @@ import { isDefined } from '@core/utils'; @@ -24,6 +24,7 @@ import { isDefined } from '@core/utils';
24 import { IWidgetSubscription, SubscriptionInfo, WidgetSubscriptionOptions } from '@core/api/widget-api.models'; 24 import { IWidgetSubscription, SubscriptionInfo, WidgetSubscriptionOptions } from '@core/api/widget-api.models';
25 import { DatasourceType, widgetType } from '@shared/models/widget.models'; 25 import { DatasourceType, widgetType } from '@shared/models/widget.models';
26 import { EntityType } from '@shared/models/entity-type.models'; 26 import { EntityType } from '@shared/models/entity-type.models';
  27 +import { ResizeObserver } from '@juggle/resize-observer';
27 28
28 type RetrieveValueMethod = 'rpc' | 'attribute' | 'timeseries'; 29 type RetrieveValueMethod = 'rpc' | 'attribute' | 'timeseries';
29 30
@@ -88,7 +89,7 @@ export class RoundSwitchComponent extends PageComponent implements OnInit, OnDes @@ -88,7 +89,7 @@ export class RoundSwitchComponent extends PageComponent implements OnInit, OnDes
88 private switchErrorContainer: JQuery<HTMLElement>; 89 private switchErrorContainer: JQuery<HTMLElement>;
89 private switchError: JQuery<HTMLElement>; 90 private switchError: JQuery<HTMLElement>;
90 91
91 - private switchResizeListener: any; 92 + private switchResize$: ResizeObserver;
92 93
93 constructor(private utils: UtilsService, 94 constructor(private utils: UtilsService,
94 protected store: Store<AppState>) { 95 protected store: Store<AppState>) {
@@ -110,20 +111,19 @@ export class RoundSwitchComponent extends PageComponent implements OnInit, OnDes @@ -110,20 +111,19 @@ export class RoundSwitchComponent extends PageComponent implements OnInit, OnDes
110 this.onValue(); 111 this.onValue();
111 }); 112 });
112 113
113 - this.switchResizeListener = this.resize.bind(this);  
114 - // @ts-ignore  
115 - addResizeListener(this.switchContainerRef.nativeElement, this.switchResizeListener); 114 + this.switchResize$ = new ResizeObserver(() => {
  115 + this.resize();
  116 + });
  117 + this.switchResize$.observe(this.switchContainerRef.nativeElement);
116 this.init(); 118 this.init();
117 - // this.ctx.resize = this.resize.bind(this);  
118 } 119 }
119 120
120 ngOnDestroy(): void { 121 ngOnDestroy(): void {
121 if (this.valueSubscription) { 122 if (this.valueSubscription) {
122 this.ctx.subscriptionApi.removeSubscription(this.valueSubscription.id); 123 this.ctx.subscriptionApi.removeSubscription(this.valueSubscription.id);
123 } 124 }
124 - if (this.switchResizeListener) {  
125 - // @ts-ignore  
126 - removeResizeListener(this.switchContainerRef.nativeElement, this.switchResizeListener); 125 + if (this.switchResize$) {
  126 + this.switchResize$.disconnect();
127 } 127 }
128 } 128 }
129 129
@@ -25,6 +25,7 @@ import { IWidgetSubscription, SubscriptionInfo, WidgetSubscriptionOptions } from @@ -25,6 +25,7 @@ import { IWidgetSubscription, SubscriptionInfo, WidgetSubscriptionOptions } from
25 import { DatasourceType, widgetType } from '@shared/models/widget.models'; 25 import { DatasourceType, widgetType } from '@shared/models/widget.models';
26 import { EntityType } from '@shared/models/entity-type.models'; 26 import { EntityType } from '@shared/models/entity-type.models';
27 import { MatSlideToggle } from '@angular/material/slide-toggle'; 27 import { MatSlideToggle } from '@angular/material/slide-toggle';
  28 +import { ResizeObserver } from '@juggle/resize-observer';
28 29
29 const switchAspectRation = 2.7893; 30 const switchAspectRation = 2.7893;
30 31
@@ -98,7 +99,7 @@ export class SwitchComponent extends PageComponent implements OnInit, OnDestroy @@ -98,7 +99,7 @@ export class SwitchComponent extends PageComponent implements OnInit, OnDestroy
98 private switchErrorContainer: JQuery<HTMLElement>; 99 private switchErrorContainer: JQuery<HTMLElement>;
99 private switchError: JQuery<HTMLElement>; 100 private switchError: JQuery<HTMLElement>;
100 101
101 - private switchResizeListener: any; 102 + private switchResize$: ResizeObserver;
102 103
103 constructor(private utils: UtilsService, 104 constructor(private utils: UtilsService,
104 protected store: Store<AppState>) { 105 protected store: Store<AppState>) {
@@ -118,9 +119,10 @@ export class SwitchComponent extends PageComponent implements OnInit, OnDestroy @@ -118,9 +119,10 @@ export class SwitchComponent extends PageComponent implements OnInit, OnDestroy
118 this.switchErrorContainer = $(this.switchErrorContainerRef.nativeElement); 119 this.switchErrorContainer = $(this.switchErrorContainerRef.nativeElement);
119 this.switchError = $(this.switchErrorRef.nativeElement); 120 this.switchError = $(this.switchErrorRef.nativeElement);
120 121
121 - this.switchResizeListener = this.resize.bind(this);  
122 - // @ts-ignore  
123 - addResizeListener(this.switchContainerRef.nativeElement, this.switchResizeListener); 122 + this.switchResize$ = new ResizeObserver(() => {
  123 + this.resize();
  124 + })
  125 + this.switchResize$.observe(this.switchContainerRef.nativeElement);
124 this.init(); 126 this.init();
125 } 127 }
126 128
@@ -128,9 +130,8 @@ export class SwitchComponent extends PageComponent implements OnInit, OnDestroy @@ -128,9 +130,8 @@ export class SwitchComponent extends PageComponent implements OnInit, OnDestroy
128 if (this.valueSubscription) { 130 if (this.valueSubscription) {
129 this.ctx.subscriptionApi.removeSubscription(this.valueSubscription.id); 131 this.ctx.subscriptionApi.removeSubscription(this.valueSubscription.id);
130 } 132 }
131 - if (this.switchResizeListener) {  
132 - // @ts-ignore  
133 - removeResizeListener(this.switchContainerRef.nativeElement, this.switchResizeListener); 133 + if (this.switchResize$) {
  134 + this.switchResize$.disconnect();
134 } 135 }
135 } 136 }
136 137
@@ -91,6 +91,7 @@ import { DatasourceService } from '@core/api/datasource.service'; @@ -91,6 +91,7 @@ import { DatasourceService } from '@core/api/datasource.service';
91 import { WidgetSubscription } from '@core/api/widget-subscription'; 91 import { WidgetSubscription } from '@core/api/widget-subscription';
92 import { EntityService } from '@core/http/entity.service'; 92 import { EntityService } from '@core/http/entity.service';
93 import { ServicesMap } from '@home/models/services.map'; 93 import { ServicesMap } from '@home/models/services.map';
  94 +import { ResizeObserver } from '@juggle/resize-observer';
94 95
95 @Component({ 96 @Component({
96 selector: 'tb-widget', 97 selector: 'tb-widget',
@@ -140,7 +141,7 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI @@ -140,7 +141,7 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI
140 141
141 cafs: {[cafId: string]: CancelAnimationFrame} = {}; 142 cafs: {[cafId: string]: CancelAnimationFrame} = {};
142 143
143 - onResizeListener = null; 144 + private widgetResize$: ResizeObserver;
144 145
145 private cssParser = new cssjs(); 146 private cssParser = new cssjs();
146 147
@@ -647,10 +648,8 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI @@ -647,10 +648,8 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI
647 } 648 }
648 649
649 private destroyDynamicWidgetComponent() { 650 private destroyDynamicWidgetComponent() {
650 - if (this.widgetContext.$containerParent && this.onResizeListener) {  
651 - // @ts-ignore  
652 - removeResizeListener(this.widgetContext.$containerParent[0], this.onResizeListener);  
653 - this.onResizeListener = null; 651 + if (this.widgetContext.$containerParent && this.widgetResize$) {
  652 + this.widgetResize$.disconnect()
654 } 653 }
655 if (this.dynamicWidgetComponentRef) { 654 if (this.dynamicWidgetComponentRef) {
656 this.dynamicWidgetComponentRef.destroy(); 655 this.dynamicWidgetComponentRef.destroy();
@@ -709,9 +708,10 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI @@ -709,9 +708,10 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI
709 } 708 }
710 } 709 }
711 710
712 - this.onResizeListener = this.onResize.bind(this);  
713 - // @ts-ignore  
714 - addResizeListener(this.widgetContext.$containerParent[0], this.onResizeListener); 711 + this.widgetResize$ = new ResizeObserver(() => {
  712 + this.onResize();
  713 + });
  714 + this.widgetResize$.observe(this.widgetContext.$containerParent[0]);
715 } 715 }
716 716
717 private createSubscription(options: WidgetSubscriptionOptions, subscribe?: boolean): Observable<IWidgetSubscription> { 717 private createSubscription(options: WidgetSubscriptionOptions, subscribe?: boolean): Observable<IWidgetSubscription> {
@@ -389,7 +389,7 @@ export class DashboardWidget implements GridsterItem, IDashboardWidget { @@ -389,7 +389,7 @@ export class DashboardWidget implements GridsterItem, IDashboardWidget {
389 padding: this.padding, 389 padding: this.padding,
390 margin: this.margin}; 390 margin: this.margin};
391 if (this.widget.config.widgetStyle) { 391 if (this.widget.config.widgetStyle) {
392 - this.style = {...this.widget.config.widgetStyle, ...this.style}; 392 + this.style = {...this.style, ...this.widget.config.widgetStyle};
393 } 393 }
394 394
395 this.showWidgetTitlePanel = this.widgetContext.hideTitlePanel ? false : 395 this.showWidgetTitlePanel = this.widgetContext.hideTitlePanel ? false :
@@ -474,7 +474,8 @@ export class DashboardWidget implements GridsterItem, IDashboardWidget { @@ -474,7 +474,8 @@ export class DashboardWidget implements GridsterItem, IDashboardWidget {
474 if (mobileHeight) { 474 if (mobileHeight) {
475 res = mobileHeight; 475 res = mobileHeight;
476 } else { 476 } else {
477 - res = this.widget.sizeY * 24 / this.dashboard.gridsterOpts.minCols; 477 + const sizeY = this.widgetLayout ? this.widgetLayout.sizeY : this.widget.sizeY;
  478 + res = sizeY * 24 / this.dashboard.gridsterOpts.minCols;
478 } 479 }
479 } else { 480 } else {
480 if (this.widgetLayout) { 481 if (this.widgetLayout) {
@@ -36,7 +36,7 @@ export class AssetTableHeaderComponent extends EntityTableHeaderComponent<AssetI @@ -36,7 +36,7 @@ export class AssetTableHeaderComponent extends EntityTableHeaderComponent<AssetI
36 36
37 assetTypeChanged(assetType: string) { 37 assetTypeChanged(assetType: string) {
38 this.entitiesTableConfig.componentsData.assetType = assetType; 38 this.entitiesTableConfig.componentsData.assetType = assetType;
39 - this.entitiesTableConfig.table.updateData(); 39 + this.entitiesTableConfig.table.resetSortAndFilter(true);
40 } 40 }
41 41
42 } 42 }
@@ -14,8 +14,7 @@ @@ -14,8 +14,7 @@
14 /// limitations under the License. 14 /// limitations under the License.
15 /// 15 ///
16 16
17 -import { Component, OnDestroy, OnInit, ViewEncapsulation, Input, Output, EventEmitter } from '@angular/core';  
18 -import { PageComponent } from '@shared/components/page.component'; 17 +import { Component, EventEmitter, Input, OnInit, Output, ViewEncapsulation } from '@angular/core';
19 18
20 @Component({ 19 @Component({
21 selector: 'tb-dashboard-toolbar', 20 selector: 'tb-dashboard-toolbar',
@@ -36,7 +36,7 @@ export class DeviceTableHeaderComponent extends EntityTableHeaderComponent<Devic @@ -36,7 +36,7 @@ export class DeviceTableHeaderComponent extends EntityTableHeaderComponent<Devic
36 36
37 deviceTypeChanged(deviceType: string) { 37 deviceTypeChanged(deviceType: string) {
38 this.entitiesTableConfig.componentsData.deviceType = deviceType; 38 this.entitiesTableConfig.componentsData.deviceType = deviceType;
39 - this.entitiesTableConfig.table.updateData(); 39 + this.entitiesTableConfig.table.resetSortAndFilter(true);
40 } 40 }
41 41
42 } 42 }
@@ -36,7 +36,7 @@ export class EntityViewTableHeaderComponent extends EntityTableHeaderComponent<E @@ -36,7 +36,7 @@ export class EntityViewTableHeaderComponent extends EntityTableHeaderComponent<E
36 36
37 entityViewTypeChanged(entityViewType: string) { 37 entityViewTypeChanged(entityViewType: string) {
38 this.entitiesTableConfig.componentsData.entityViewType = entityViewType; 38 this.entitiesTableConfig.componentsData.entityViewType = entityViewType;
39 - this.entitiesTableConfig.table.updateData(); 39 + this.entitiesTableConfig.table.resetSortAndFilter(true);
40 } 40 }
41 41
42 } 42 }
@@ -46,6 +46,7 @@ import { @@ -46,6 +46,7 @@ import {
46 } from '@home/pages/widget/save-widget-type-as-dialog.component'; 46 } from '@home/pages/widget/save-widget-type-as-dialog.component';
47 import { Subscription } from 'rxjs'; 47 import { Subscription } from 'rxjs';
48 import Timeout = NodeJS.Timeout; 48 import Timeout = NodeJS.Timeout;
  49 +import { ResizeObserver } from '@juggle/resize-observer';
49 50
50 // @dynamic 51 // @dynamic
51 @Component({ 52 @Component({
@@ -124,7 +125,7 @@ export class WidgetEditorComponent extends PageComponent implements OnInit, OnDe @@ -124,7 +125,7 @@ export class WidgetEditorComponent extends PageComponent implements OnInit, OnDe
124 jsonSettingsEditor: ace.Ace.Editor; 125 jsonSettingsEditor: ace.Ace.Editor;
125 dataKeyJsonSettingsEditor: ace.Ace.Editor; 126 dataKeyJsonSettingsEditor: ace.Ace.Editor;
126 jsEditor: ace.Ace.Editor; 127 jsEditor: ace.Ace.Editor;
127 - aceResizeListeners: { element: any, resizeListener: any }[] = []; 128 + aceResize$: ResizeObserver;
128 129
129 onWindowMessageListener = this.onWindowMessage.bind(this); 130 onWindowMessageListener = this.onWindowMessage.bind(this);
130 131
@@ -193,10 +194,7 @@ export class WidgetEditorComponent extends PageComponent implements OnInit, OnDe @@ -193,10 +194,7 @@ export class WidgetEditorComponent extends PageComponent implements OnInit, OnDe
193 194
194 ngOnDestroy(): void { 195 ngOnDestroy(): void {
195 this.window.removeEventListener('message', this.onWindowMessageListener); 196 this.window.removeEventListener('message', this.onWindowMessageListener);
196 - this.aceResizeListeners.forEach((resizeListener) => {  
197 - // @ts-ignore  
198 - removeResizeListener(resizeListener.element, resizeListener.resizeListener);  
199 - }); 197 + this.aceResize$.disconnect();
200 this.rxSubscriptions.forEach((subscription) => { 198 this.rxSubscriptions.forEach((subscription) => {
201 subscription.unsubscribe(); 199 subscription.unsubscribe();
202 }); 200 });
@@ -272,6 +270,12 @@ export class WidgetEditorComponent extends PageComponent implements OnInit, OnDe @@ -272,6 +270,12 @@ export class WidgetEditorComponent extends PageComponent implements OnInit, OnDe
272 } 270 }
273 271
274 private initAceEditors() { 272 private initAceEditors() {
  273 + this.aceResize$ = new ResizeObserver((entries) => {
  274 + entries.forEach((entry) => {
  275 + const editor = this.aceEditors.find(aceEditor => aceEditor.container === entry.target);
  276 + this.onAceEditorResize(editor);
  277 + })
  278 + });
275 this.htmlEditor = this.createAceEditor(this.htmlInputElmRef, 'html'); 279 this.htmlEditor = this.createAceEditor(this.htmlInputElmRef, 'html');
276 this.htmlEditor.on('input', () => { 280 this.htmlEditor.on('input', () => {
277 const editorValue = this.htmlEditor.getValue(); 281 const editorValue = this.htmlEditor.getValue();
@@ -342,12 +346,7 @@ export class WidgetEditorComponent extends PageComponent implements OnInit, OnDe @@ -342,12 +346,7 @@ export class WidgetEditorComponent extends PageComponent implements OnInit, OnDe
342 const aceEditor = ace.edit(editorElement, editorOptions); 346 const aceEditor = ace.edit(editorElement, editorOptions);
343 aceEditor.session.setUseWrapMode(true); 347 aceEditor.session.setUseWrapMode(true);
344 this.aceEditors.push(aceEditor); 348 this.aceEditors.push(aceEditor);
345 -  
346 - const resizeListener = this.onAceEditorResize.bind(this, aceEditor);  
347 -  
348 - // @ts-ignore  
349 - addResizeListener(editorElement, resizeListener);  
350 - this.aceResizeListeners.push({element: editorElement, resizeListener}); 349 + this.aceResize$.observe(editorElement);
351 return aceEditor; 350 return aceEditor;
352 } 351 }
353 352
@@ -93,7 +93,6 @@ export class BreadcrumbComponent implements OnInit, OnDestroy { @@ -93,7 +93,6 @@ export class BreadcrumbComponent implements OnInit, OnDestroy {
93 const icon = breadcrumbConfig.icon || 'home'; 93 const icon = breadcrumbConfig.icon || 'home';
94 const isMdiIcon = icon.startsWith('mdi:'); 94 const isMdiIcon = icon.startsWith('mdi:');
95 const link = [ route.pathFromRoot.map(v => v.url.map(segment => segment.toString()).join('/')).join('/') ]; 95 const link = [ route.pathFromRoot.map(v => v.url.map(segment => segment.toString()).join('/')).join('/') ];
96 - const queryParams = route.queryParams;  
97 const breadcrumb = { 96 const breadcrumb = {
98 label, 97 label,
99 labelFunction, 98 labelFunction,
@@ -101,7 +100,7 @@ export class BreadcrumbComponent implements OnInit, OnDestroy { @@ -101,7 +100,7 @@ export class BreadcrumbComponent implements OnInit, OnDestroy {
101 icon, 100 icon,
102 isMdiIcon, 101 isMdiIcon,
103 link, 102 link,
104 - queryParams 103 + queryParams: null
105 }; 104 };
106 newBreadcrumbs = [...breadcrumbs, breadcrumb]; 105 newBreadcrumbs = [...breadcrumbs, breadcrumb];
107 } 106 }
@@ -29,6 +29,7 @@ import { @@ -29,6 +29,7 @@ import {
29 } from '@angular/core'; 29 } from '@angular/core';
30 import { WINDOW } from '@core/services/window.service'; 30 import { WINDOW } from '@core/services/window.service';
31 import { CanColorCtor, mixinColor } from '@angular/material/core'; 31 import { CanColorCtor, mixinColor } from '@angular/material/core';
  32 +import { ResizeObserver } from '@juggle/resize-observer';
32 33
33 export declare type FabToolbarDirection = 'left' | 'right'; 34 export declare type FabToolbarDirection = 'left' | 'right';
34 35
@@ -77,14 +78,14 @@ export class FabActionsDirective implements OnInit { @@ -77,14 +78,14 @@ export class FabActionsDirective implements OnInit {
77 }) 78 })
78 export class FabToolbarComponent extends MatFabToolbarMixinBase implements OnInit, OnDestroy, AfterViewInit, OnChanges { 79 export class FabToolbarComponent extends MatFabToolbarMixinBase implements OnInit, OnDestroy, AfterViewInit, OnChanges {
79 80
  81 + private fabToolbarResize$: ResizeObserver;
  82 +
80 @Input() 83 @Input()
81 isOpen: boolean; 84 isOpen: boolean;
82 85
83 @Input() 86 @Input()
84 direction: FabToolbarDirection; 87 direction: FabToolbarDirection;
85 88
86 - fabToolbarResizeListener = this.onFabToolbarResize.bind(this);  
87 -  
88 constructor(private el: ElementRef<HTMLElement>, 89 constructor(private el: ElementRef<HTMLElement>,
89 @Inject(WINDOW) private window: Window) { 90 @Inject(WINDOW) private window: Window) {
90 super(el); 91 super(el);
@@ -96,13 +97,14 @@ export class FabToolbarComponent extends MatFabToolbarMixinBase implements OnIni @@ -96,13 +97,14 @@ export class FabToolbarComponent extends MatFabToolbarMixinBase implements OnIni
96 element.find('mat-fab-trigger').find('button') 97 element.find('mat-fab-trigger').find('button')
97 .prepend('<div class="mat-fab-toolbar-background"></div>'); 98 .prepend('<div class="mat-fab-toolbar-background"></div>');
98 element.addClass(`mat-${this.direction}`); 99 element.addClass(`mat-${this.direction}`);
99 - // @ts-ignore  
100 - addResizeListener(this.el.nativeElement, this.fabToolbarResizeListener); 100 + this.fabToolbarResize$ = new ResizeObserver(() => {
  101 + this.onFabToolbarResize();
  102 + });
  103 + this.fabToolbarResize$.observe(this.el.nativeElement);
101 } 104 }
102 105
103 ngOnDestroy(): void { 106 ngOnDestroy(): void {
104 - // @ts-ignore  
105 - removeResizeListener(this.el.nativeElement, this.fabToolbarResizeListener); 107 + this.fabToolbarResize$.disconnect();
106 } 108 }
107 109
108 ngAfterViewInit(): void { 110 ngAfterViewInit(): void {
@@ -15,11 +15,11 @@ @@ -15,11 +15,11 @@
15 /// 15 ///
16 16
17 import { 17 import {
18 - ChangeDetectionStrategy,  
19 Component, 18 Component,
20 ElementRef, 19 ElementRef,
21 forwardRef, 20 forwardRef,
22 - Input, OnDestroy, 21 + Input,
  22 + OnDestroy,
23 OnInit, 23 OnInit,
24 ViewChild, 24 ViewChild,
25 ViewEncapsulation 25 ViewEncapsulation
@@ -34,6 +34,7 @@ import { UtilsService } from '@core/services/utils.service'; @@ -34,6 +34,7 @@ import { UtilsService } from '@core/services/utils.service';
34 import { guid, isUndefined } from '@app/core/utils'; 34 import { guid, isUndefined } from '@app/core/utils';
35 import { TranslateService } from '@ngx-translate/core'; 35 import { TranslateService } from '@ngx-translate/core';
36 import { CancelAnimationFrame, RafService } from '@core/services/raf.service'; 36 import { CancelAnimationFrame, RafService } from '@core/services/raf.service';
  37 +import { ResizeObserver } from '@juggle/resize-observer';
37 38
38 @Component({ 39 @Component({
39 selector: 'tb-js-func', 40 selector: 'tb-js-func',
@@ -60,7 +61,7 @@ export class JsFuncComponent implements OnInit, OnDestroy, ControlValueAccessor, @@ -60,7 +61,7 @@ export class JsFuncComponent implements OnInit, OnDestroy, ControlValueAccessor,
60 61
61 private jsEditor: ace.Ace.Editor; 62 private jsEditor: ace.Ace.Editor;
62 private editorsResizeCaf: CancelAnimationFrame; 63 private editorsResizeCaf: CancelAnimationFrame;
63 - private editorResizeListener: any; 64 + private editorResize$: ResizeObserver;
64 65
65 toastTargetId = `jsFuncEditor-${guid()}`; 66 toastTargetId = `jsFuncEditor-${guid()}`;
66 67
@@ -152,16 +153,15 @@ export class JsFuncComponent implements OnInit, OnDestroy, ControlValueAccessor, @@ -152,16 +153,15 @@ export class JsFuncComponent implements OnInit, OnDestroy, ControlValueAccessor,
152 this.cleanupJsErrors(); 153 this.cleanupJsErrors();
153 this.updateView(); 154 this.updateView();
154 }); 155 });
155 - this.editorResizeListener = this.onAceEditorResize.bind(this);  
156 - // @ts-ignore  
157 - addResizeListener(editorElement, this.editorResizeListener); 156 + this.editorResize$ = new ResizeObserver(() => {
  157 + this.onAceEditorResize();
  158 + });
  159 + this.editorResize$.observe(editorElement);
158 } 160 }
159 161
160 ngOnDestroy(): void { 162 ngOnDestroy(): void {
161 - if (this.editorResizeListener) {  
162 - const editorElement = this.javascriptEditorElmRef.nativeElement;  
163 - // @ts-ignore  
164 - removeResizeListener(editorElement, this.editorResizeListener); 163 + if (this.editorResize$) {
  164 + this.editorResize$.disconnect();
165 } 165 }
166 } 166 }
167 167
@@ -20,10 +20,10 @@ import { @@ -20,10 +20,10 @@ import {
20 forwardRef, 20 forwardRef,
21 Input, 21 Input,
22 OnChanges, 22 OnChanges,
  23 + OnDestroy,
23 OnInit, 24 OnInit,
24 - ViewChild,  
25 SimpleChanges, 25 SimpleChanges,
26 - OnDestroy 26 + ViewChild
27 } from '@angular/core'; 27 } from '@angular/core';
28 import { ControlValueAccessor, FormControl, NG_VALIDATORS, NG_VALUE_ACCESSOR, Validator } from '@angular/forms'; 28 import { ControlValueAccessor, FormControl, NG_VALIDATORS, NG_VALUE_ACCESSOR, Validator } from '@angular/forms';
29 import * as ace from 'ace-builds'; 29 import * as ace from 'ace-builds';
@@ -34,6 +34,7 @@ import { AppState } from '@core/core.state'; @@ -34,6 +34,7 @@ import { AppState } from '@core/core.state';
34 import { ContentType, contentTypesMap } from '@shared/models/constants'; 34 import { ContentType, contentTypesMap } from '@shared/models/constants';
35 import { CancelAnimationFrame, RafService } from '@core/services/raf.service'; 35 import { CancelAnimationFrame, RafService } from '@core/services/raf.service';
36 import { guid } from '@core/utils'; 36 import { guid } from '@core/utils';
  37 +import { ResizeObserver } from '@juggle/resize-observer';
37 38
38 @Component({ 39 @Component({
39 selector: 'tb-json-content', 40 selector: 'tb-json-content',
@@ -59,7 +60,7 @@ export class JsonContentComponent implements OnInit, ControlValueAccessor, Valid @@ -59,7 +60,7 @@ export class JsonContentComponent implements OnInit, ControlValueAccessor, Valid
59 60
60 private jsonEditor: ace.Ace.Editor; 61 private jsonEditor: ace.Ace.Editor;
61 private editorsResizeCaf: CancelAnimationFrame; 62 private editorsResizeCaf: CancelAnimationFrame;
62 - private editorResizeListener: any; 63 + private editorResize$: ResizeObserver;
63 64
64 toastTargetId = `jsonContentEditor-${guid()}`; 65 toastTargetId = `jsonContentEditor-${guid()}`;
65 66
@@ -97,8 +98,6 @@ export class JsonContentComponent implements OnInit, ControlValueAccessor, Valid @@ -97,8 +98,6 @@ export class JsonContentComponent implements OnInit, ControlValueAccessor, Valid
97 98
98 contentValid: boolean; 99 contentValid: boolean;
99 100
100 - validationError: string;  
101 -  
102 errorShowed = false; 101 errorShowed = false;
103 102
104 private propagateChange = null; 103 private propagateChange = null;
@@ -135,16 +134,15 @@ export class JsonContentComponent implements OnInit, ControlValueAccessor, Valid @@ -135,16 +134,15 @@ export class JsonContentComponent implements OnInit, ControlValueAccessor, Valid
135 this.cleanupJsonErrors(); 134 this.cleanupJsonErrors();
136 this.updateView(); 135 this.updateView();
137 }); 136 });
138 - this.editorResizeListener = this.onAceEditorResize.bind(this);  
139 - // @ts-ignore  
140 - addResizeListener(editorElement, this.editorResizeListener); 137 + this.editorResize$ = new ResizeObserver(() => {
  138 + this.onAceEditorResize();
  139 + });
  140 + this.editorResize$.observe(editorElement);
141 } 141 }
142 142
143 ngOnDestroy(): void { 143 ngOnDestroy(): void {
144 - if (this.editorResizeListener) {  
145 - const editorElement = this.jsonEditorElmRef.nativeElement;  
146 - // @ts-ignore  
147 - removeResizeListener(editorElement, this.editorResizeListener); 144 + if (this.editorResize$) {
  145 + this.editorResize$.disconnect();
148 } 146 }
149 } 147 }
150 148
@@ -15,7 +15,6 @@ @@ -15,7 +15,6 @@
15 /// 15 ///
16 16
17 import { 17 import {
18 - ChangeDetectionStrategy,  
19 Component, 18 Component,
20 ElementRef, 19 ElementRef,
21 forwardRef, 20 forwardRef,
@@ -106,6 +105,8 @@ export class JsonFormComponent implements OnInit, ControlValueAccessor, Validato @@ -106,6 +105,8 @@ export class JsonFormComponent implements OnInit, ControlValueAccessor, Validato
106 105
107 private propagateChange = null; 106 private propagateChange = null;
108 private propagateChangePending = false; 107 private propagateChangePending = false;
  108 + private writingValue = false;
  109 + private updateViewPending = false;
109 110
110 constructor(public elementRef: ElementRef, 111 constructor(public elementRef: ElementRef,
111 private translate: TranslateService, 112 private translate: TranslateService,
@@ -143,6 +144,7 @@ export class JsonFormComponent implements OnInit, ControlValueAccessor, Validato @@ -143,6 +144,7 @@ export class JsonFormComponent implements OnInit, ControlValueAccessor, Validato
143 } 144 }
144 145
145 writeValue(data: JsonFormComponentData): void { 146 writeValue(data: JsonFormComponentData): void {
  147 + this.writingValue = true;
146 this.data = data; 148 this.data = data;
147 this.schema = this.data && this.data.schema ? deepClone(this.data.schema) : { 149 this.schema = this.data && this.data.schema ? deepClone(this.data.schema) : {
148 type: 'object' 150 type: 'object'
@@ -154,19 +156,29 @@ export class JsonFormComponent implements OnInit, ControlValueAccessor, Validato @@ -154,19 +156,29 @@ export class JsonFormComponent implements OnInit, ControlValueAccessor, Validato
154 this.model = inspector.sanitize(this.schema, this.model).data; 156 this.model = inspector.sanitize(this.schema, this.model).data;
155 this.updateAndRender(); 157 this.updateAndRender();
156 this.isModelValid = this.validateModel(); 158 this.isModelValid = this.validateModel();
157 - if (!this.isModelValid) { 159 + this.writingValue = false;
  160 + if (!this.isModelValid || this.updateViewPending) {
158 this.updateView(); 161 this.updateView();
159 } 162 }
160 } 163 }
161 164
162 updateView() { 165 updateView() {
163 - if (this.data) {  
164 - this.data.model = this.model;  
165 - if (this.propagateChange) {  
166 - this.propagateChange(this.data);  
167 - } else {  
168 - this.propagateChangePending = true; 166 + if (!this.writingValue) {
  167 + this.updateViewPending = false;
  168 + if (this.data) {
  169 + this.data.model = this.model;
  170 + if (this.propagateChange) {
  171 + try {
  172 + this.propagateChange(this.data);
  173 + } catch (e) {
  174 + this.propagateChangePending = true;
  175 + }
  176 + } else {
  177 + this.propagateChangePending = true;
  178 + }
169 } 179 }
  180 + } else {
  181 + this.updateViewPending = true;
170 } 182 }
171 } 183 }
172 184
@@ -14,16 +14,8 @@ @@ -14,16 +14,8 @@
14 /// limitations under the License. 14 /// limitations under the License.
15 /// 15 ///
16 16
17 -import {  
18 - Attribute, ChangeDetectionStrategy,  
19 - Component,  
20 - ElementRef,  
21 - forwardRef,  
22 - Input, OnDestroy,  
23 - OnInit,  
24 - ViewChild  
25 -} from '@angular/core';  
26 -import { ControlValueAccessor, NG_VALUE_ACCESSOR, FormControl, Validator, NG_VALIDATORS } from '@angular/forms'; 17 +import { Component, ElementRef, forwardRef, Input, OnDestroy, OnInit, ViewChild } from '@angular/core';
  18 +import { ControlValueAccessor, FormControl, NG_VALIDATORS, NG_VALUE_ACCESSOR, Validator } from '@angular/forms';
27 import * as ace from 'ace-builds'; 19 import * as ace from 'ace-builds';
28 import { coerceBooleanProperty } from '@angular/cdk/coercion'; 20 import { coerceBooleanProperty } from '@angular/cdk/coercion';
29 import { ActionNotificationHide, ActionNotificationShow } from '@core/notification/notification.actions'; 21 import { ActionNotificationHide, ActionNotificationShow } from '@core/notification/notification.actions';
@@ -31,6 +23,7 @@ import { Store } from '@ngrx/store'; @@ -31,6 +23,7 @@ import { Store } from '@ngrx/store';
31 import { AppState } from '@core/core.state'; 23 import { AppState } from '@core/core.state';
32 import { CancelAnimationFrame, RafService } from '@core/services/raf.service'; 24 import { CancelAnimationFrame, RafService } from '@core/services/raf.service';
33 import { guid } from '@core/utils'; 25 import { guid } from '@core/utils';
  26 +import { ResizeObserver } from '@juggle/resize-observer';
34 27
35 @Component({ 28 @Component({
36 selector: 'tb-json-object-edit', 29 selector: 'tb-json-object-edit',
@@ -56,7 +49,7 @@ export class JsonObjectEditComponent implements OnInit, ControlValueAccessor, Va @@ -56,7 +49,7 @@ export class JsonObjectEditComponent implements OnInit, ControlValueAccessor, Va
56 49
57 private jsonEditor: ace.Ace.Editor; 50 private jsonEditor: ace.Ace.Editor;
58 private editorsResizeCaf: CancelAnimationFrame; 51 private editorsResizeCaf: CancelAnimationFrame;
59 - private editorResizeListener: any; 52 + private editorResize$: ResizeObserver;
60 53
61 toastTargetId = `jsonObjectEditor-${guid()}`; 54 toastTargetId = `jsonObjectEditor-${guid()}`;
62 55
@@ -128,16 +121,15 @@ export class JsonObjectEditComponent implements OnInit, ControlValueAccessor, Va @@ -128,16 +121,15 @@ export class JsonObjectEditComponent implements OnInit, ControlValueAccessor, Va
128 this.cleanupJsonErrors(); 121 this.cleanupJsonErrors();
129 this.updateView(); 122 this.updateView();
130 }); 123 });
131 - this.editorResizeListener = this.onAceEditorResize.bind(this);  
132 - // @ts-ignore  
133 - addResizeListener(editorElement, this.editorResizeListener); 124 + this.editorResize$ = new ResizeObserver(() => {
  125 + this.onAceEditorResize();
  126 + });
  127 + this.editorResize$.observe(editorElement);
134 } 128 }
135 129
136 ngOnDestroy(): void { 130 ngOnDestroy(): void {
137 - if (this.editorResizeListener) {  
138 - const editorElement = this.jsonEditorElmRef.nativeElement;  
139 - // @ts-ignore  
140 - removeResizeListener(editorElement, this.editorResizeListener); 131 + if (this.editorResize$) {
  132 + this.editorResize$.disconnect();
141 } 133 }
142 } 134 }
143 135