Browse Source

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

pull/2664/head
Adsumus 7 years ago
parent
commit
f9574d7041
  1. 4
      docker/README.md
  2. 2
      msa/js-executor/package-lock.json
  3. 2
      msa/web-ui/package-lock.json
  4. 1
      ui-ngx/angular.json
  5. 10
      ui-ngx/package-lock.json
  6. 2
      ui-ngx/package.json
  7. 9
      ui-ngx/src/app/core/api/alias-controller.ts
  8. 9
      ui-ngx/src/app/modules/home/components/alarm/alarm-details-dialog.component.ts
  9. 2
      ui-ngx/src/app/modules/home/components/alarm/alarm-table-header.component.ts
  10. 8
      ui-ngx/src/app/modules/home/components/alias/aliases-entity-select.component.ts
  11. 17
      ui-ngx/src/app/modules/home/components/dashboard/dashboard.component.ts
  12. 4
      ui-ngx/src/app/modules/home/components/entity/entities-table.component.ts
  13. 2
      ui-ngx/src/app/modules/home/components/event/event-table-header.component.ts
  14. 21
      ui-ngx/src/app/modules/home/components/widget/action/custom-action-pretty-resources-tabs.component.ts
  15. 6
      ui-ngx/src/app/modules/home/components/widget/lib/date-range-navigator/date-range-navigator.component.ts
  16. 15
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-form.component.ts
  17. 15
      ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.ts
  18. 18
      ui-ngx/src/app/modules/home/components/widget/lib/rpc/knob.component.ts
  19. 15
      ui-ngx/src/app/modules/home/components/widget/lib/rpc/led-indicator.component.ts
  20. 18
      ui-ngx/src/app/modules/home/components/widget/lib/rpc/round-switch.component.ts
  21. 15
      ui-ngx/src/app/modules/home/components/widget/lib/rpc/switch.component.ts
  22. 16
      ui-ngx/src/app/modules/home/components/widget/widget.component.ts
  23. 5
      ui-ngx/src/app/modules/home/models/dashboard-component.models.ts
  24. 2
      ui-ngx/src/app/modules/home/pages/asset/asset-table-header.component.ts
  25. 3
      ui-ngx/src/app/modules/home/pages/dashboard/dashboard-toolbar.component.ts
  26. 2
      ui-ngx/src/app/modules/home/pages/device/device-table-header.component.ts
  27. 2
      ui-ngx/src/app/modules/home/pages/entity-view/entity-view-table-header.component.ts
  28. 21
      ui-ngx/src/app/modules/home/pages/widget/widget-editor.component.ts
  29. 3
      ui-ngx/src/app/shared/components/breadcrumb.component.ts
  30. 14
      ui-ngx/src/app/shared/components/fab-toolbar.component.ts
  31. 20
      ui-ngx/src/app/shared/components/js-func.component.ts
  32. 22
      ui-ngx/src/app/shared/components/json-content.component.ts
  33. 28
      ui-ngx/src/app/shared/components/json-form/json-form.component.ts
  34. 28
      ui-ngx/src/app/shared/components/json-object-edit.component.ts

4
docker/README.md

@ -13,9 +13,9 @@ Before performing initial installation you can configure the type of database to
In order to set database type change the value of `DATABASE` variable in `.env` file to one of the following: In order to set database type change the value of `DATABASE` variable in `.env` file to one of the following:
- `postgres` - use PostgreSQL database; - `postgres` - use PostgreSQL database;
- `cassandra` - use Cassandra database; - `hybrid` - use PostgreSQL for entities database and Cassandra for timeseries database;
**NOTE**: According to the database type corresponding docker service will be deployed (see `docker-compose.postgres.yml`, `docker-compose.cassandra.yml` for details). **NOTE**: According to the database type corresponding docker service will be deployed (see `docker-compose.postgres.yml`, `docker-compose.hybrid.yml` for details).
Execute the following command to create log folders for the services and chown of these folders to the docker container users. Execute the following command to create log folders for the services and chown of these folders to the docker container users.
To be able to change user, **chown** command is used, which requires sudo permissions (script will request password for a sudo access): To be able to change user, **chown** command is used, which requires sudo permissions (script will request password for a sudo access):

2
msa/js-executor/package-lock.json

@ -1,6 +1,6 @@
{ {
"name": "thingsboard-js-executor", "name": "thingsboard-js-executor",
"version": "2.4.3", "version": "3.0.0",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {

2
msa/web-ui/package-lock.json

@ -1,6 +1,6 @@
{ {
"name": "thingsboard-web-ui", "name": "thingsboard-web-ui",
"version": "2.4.3", "version": "3.0.0",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {

1
ui-ngx/angular.json

@ -49,7 +49,6 @@
] ]
}, },
"scripts": [ "scripts": [
"node_modules/javascript-detect-element-resize/detect-element-resize.js",
"node_modules/jquery/dist/jquery.min.js", "node_modules/jquery/dist/jquery.min.js",
"node_modules/jquery.terminal/js/jquery.terminal.min.js", "node_modules/jquery.terminal/js/jquery.terminal.min.js",
"node_modules/flot/lib/jquery.colorhelpers.js", "node_modules/flot/lib/jquery.colorhelpers.js",

10
ui-ngx/package-lock.json

@ -1561,6 +1561,11 @@
} }
} }
}, },
"@juggle/resize-observer": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/@juggle/resize-observer/-/resize-observer-3.1.3.tgz",
"integrity": "sha512-y7qc6SzZBlSpx8hEDfV0S9Cx6goROX/vBhS2Ru1Q78Jp1FlCMbxp7UcAN90rLgB3X8DSMBgDFxcmoG/VfdAhFA=="
},
"@mat-datetimepicker/core": { "@mat-datetimepicker/core": {
"version": "4.1.0", "version": "4.1.0",
"resolved": "https://registry.npmjs.org/@mat-datetimepicker/core/-/core-4.1.0.tgz", "resolved": "https://registry.npmjs.org/@mat-datetimepicker/core/-/core-4.1.0.tgz",
@ -7083,11 +7088,6 @@
"integrity": "sha1-43zwsX8ZnM4jvqcbIDk5Uka07E4=", "integrity": "sha1-43zwsX8ZnM4jvqcbIDk5Uka07E4=",
"dev": true "dev": true
}, },
"javascript-detect-element-resize": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/javascript-detect-element-resize/-/javascript-detect-element-resize-0.5.3.tgz",
"integrity": "sha1-GnHNUd/lZZB/KZAS/nOilBBAJd4="
},
"jest-worker": { "jest-worker": {
"version": "25.1.0", "version": "25.1.0",
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-25.1.0.tgz", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-25.1.0.tgz",

2
ui-ngx/package.json

@ -28,6 +28,7 @@
"@date-io/date-fns": "^2.6.1", "@date-io/date-fns": "^2.6.1",
"@flowjs/flow.js": "^2.14.0", "@flowjs/flow.js": "^2.14.0",
"@flowjs/ngx-flow": "^0.4.3", "@flowjs/ngx-flow": "^0.4.3",
"@juggle/resize-observer": "^3.1.3",
"@mat-datetimepicker/core": "^4.1.0", "@mat-datetimepicker/core": "^4.1.0",
"@material-ui/core": "^4.9.11", "@material-ui/core": "^4.9.11",
"@material-ui/icons": "^4.9.1", "@material-ui/icons": "^4.9.1",
@ -49,7 +50,6 @@
"flot": "git://github.com/thingsboard/flot.git#0.9-work", "flot": "git://github.com/thingsboard/flot.git#0.9-work",
"flot.curvedlines": "git://github.com/MichaelZinsmaier/CurvedLines.git#master", "flot.curvedlines": "git://github.com/MichaelZinsmaier/CurvedLines.git#master",
"font-awesome": "^4.7.0", "font-awesome": "^4.7.0",
"javascript-detect-element-resize": "^0.5.3",
"jquery": "^3.5.0", "jquery": "^3.5.0",
"jquery.terminal": "^2.15.4", "jquery.terminal": "^2.15.4",
"js-beautify": "^1.11.0", "js-beautify": "^1.11.0",

9
ui-ngx/src/app/core/api/alias-controller.ts

@ -123,7 +123,7 @@ export class AliasController implements IAliasController {
} }
getAliasInfo(aliasId: string): Observable<AliasInfo> { getAliasInfo(aliasId: string): Observable<AliasInfo> {
const aliasInfo = this.resolvedAliases[aliasId]; let aliasInfo = this.resolvedAliases[aliasId];
if (aliasInfo) { if (aliasInfo) {
return of(aliasInfo); return of(aliasInfo);
} else if (this.resolvedAliasesObservable[aliasId]) { } else if (this.resolvedAliasesObservable[aliasId]) {
@ -159,7 +159,12 @@ export class AliasController implements IAliasController {
delete this.resolvedAliasesObservable[aliasId]; delete this.resolvedAliasesObservable[aliasId];
return res; return res;
} }
return this.resolvedAliasesObservable[aliasId]; aliasInfo = this.resolvedAliases[aliasId];
if (aliasInfo) {
return of(aliasInfo);
} else {
return this.resolvedAliasesObservable[aliasId];
}
} }
} }

9
ui-ngx/src/app/modules/home/components/alarm/alarm-details-dialog.component.ts

@ -19,7 +19,7 @@ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';
import { FormBuilder, FormGroup } from '@angular/forms'; import { FormBuilder, FormGroup } from '@angular/forms';
import { Observable, Subject } from 'rxjs'; import { Observable, ReplaySubject } from 'rxjs';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { DialogComponent } from '@app/shared/components/dialog.component'; import { DialogComponent } from '@app/shared/components/dialog.component';
import { import {
@ -30,7 +30,7 @@ import {
alarmStatusTranslations alarmStatusTranslations
} from '@app/shared/models/alarm.models'; } from '@app/shared/models/alarm.models';
import { AlarmService } from '@core/http/alarm.service'; import { AlarmService } from '@core/http/alarm.service';
import { share, tap } from 'rxjs/operators'; import { tap } from 'rxjs/operators';
import { DatePipe } from '@angular/common'; import { DatePipe } from '@angular/common';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
@ -54,10 +54,9 @@ export class AlarmDetailsDialogComponent extends DialogComponent<AlarmDetailsDia
allowClear: boolean; allowClear: boolean;
displayDetails: boolean; displayDetails: boolean;
loadAlarmSubject = new Subject<AlarmInfo>(); loadAlarmSubject = new ReplaySubject<AlarmInfo>();
alarm$: Observable<AlarmInfo> = this.loadAlarmSubject.asObservable().pipe( alarm$: Observable<AlarmInfo> = this.loadAlarmSubject.asObservable().pipe(
tap(alarm => this.loadAlarmFields(alarm)), tap(alarm => this.loadAlarmFields(alarm))
share()
); );
alarmSeverityColorsMap = alarmSeverityColors; alarmSeverityColorsMap = alarmSeverityColors;

2
ui-ngx/src/app/modules/home/components/alarm/alarm-table-header.component.ts

@ -43,6 +43,6 @@ export class AlarmTableHeaderComponent extends EntityTableHeaderComponent<AlarmI
searchStatusChanged(searchStatus: AlarmSearchStatus) { searchStatusChanged(searchStatus: AlarmSearchStatus) {
this.alarmTableConfig.searchStatus = searchStatus; this.alarmTableConfig.searchStatus = searchStatus;
this.alarmTableConfig.table.updateData(); this.alarmTableConfig.table.resetSortAndFilter(true, true);
} }
} }

8
ui-ngx/src/app/modules/home/components/alias/aliases-entity-select.component.ts

@ -63,12 +63,16 @@ export class AliasesEntitySelectComponent implements OnInit, OnDestroy {
ngOnInit(): void { ngOnInit(): void {
this.rxSubscriptions.push(this.aliasController.entityAliasesChanged.subscribe( this.rxSubscriptions.push(this.aliasController.entityAliasesChanged.subscribe(
() => { () => {
this.updateDisplayValue(); setTimeout(() => {
this.updateDisplayValue();
}, 0);
} }
)); ));
this.rxSubscriptions.push(this.aliasController.entityAliasResolved.subscribe( this.rxSubscriptions.push(this.aliasController.entityAliasResolved.subscribe(
() => { () => {
this.updateDisplayValue(); setTimeout(() => {
this.updateDisplayValue();
}, 0);
} }
)); ));
} }

17
ui-ngx/src/app/modules/home/components/dashboard/dashboard.component.ts

@ -53,6 +53,7 @@ import { Widget, WidgetPosition } from '@app/shared/models/widget.models';
import { MatMenuTrigger } from '@angular/material/menu'; import { MatMenuTrigger } from '@angular/material/menu';
import { SafeStyle } from '@angular/platform-browser'; import { SafeStyle } from '@angular/platform-browser';
import { distinct } from 'rxjs/operators'; import { distinct } from 'rxjs/operators';
import { ResizeObserver } from '@juggle/resize-observer';
@Component({ @Component({
selector: 'tb-dashboard', selector: 'tb-dashboard',
@ -166,7 +167,7 @@ export class DashboardComponent extends PageComponent implements IDashboardCompo
private optionsChangeNotificationsPaused = false; private optionsChangeNotificationsPaused = false;
private gridsterResizeListener = null; private gridsterResize$: ResizeObserver;
constructor(protected store: Store<AppState>, constructor(protected store: Store<AppState>,
private timeService: TimeService, private timeService: TimeService,
@ -225,9 +226,8 @@ export class DashboardComponent extends PageComponent implements IDashboardCompo
ngOnDestroy(): void { ngOnDestroy(): void {
super.ngOnDestroy(); super.ngOnDestroy();
if (this.gridsterResizeListener) { if (this.gridsterResize$) {
// @ts-ignore this.gridsterResize$.disconnect();
removeResizeListener(this.gridster.el, this.gridsterResizeListener);
} }
if (this.breakpointObserverSubscription) { if (this.breakpointObserverSubscription) {
this.breakpointObserverSubscription.unsubscribe(); this.breakpointObserverSubscription.unsubscribe();
@ -290,9 +290,10 @@ export class DashboardComponent extends PageComponent implements IDashboardCompo
} }
ngAfterViewInit(): void { ngAfterViewInit(): void {
this.gridsterResizeListener = this.onGridsterParentResize.bind(this); this.gridsterResize$ = new ResizeObserver(() => {
// @ts-ignore this.onGridsterParentResize()
addResizeListener(this.gridster.el, this.gridsterResizeListener); });
this.gridsterResize$.observe(this.gridster.el);
} }
onUpdateTimewindow(startTimeMs: number, endTimeMs: number, interval?: number, persist?: boolean): void { onUpdateTimewindow(startTimeMs: number, endTimeMs: number, interval?: number, persist?: boolean): void {
@ -491,8 +492,8 @@ export class DashboardComponent extends PageComponent implements IDashboardCompo
const parentHeight = this.gridster.el.offsetHeight; const parentHeight = this.gridster.el.offsetHeight;
if (this.isMobileSize && this.mobileAutofillHeight && parentHeight) { if (this.isMobileSize && this.mobileAutofillHeight && parentHeight) {
this.updateMobileOpts(parentHeight); this.updateMobileOpts(parentHeight);
this.notifyGridsterOptionsChanged();
} }
this.notifyGridsterOptionsChanged();
} }
private updateLayoutOpts() { private updateLayoutOpts() {

4
ui-ngx/src/app/modules/home/components/entity/entities-table.component.ts

@ -434,9 +434,9 @@ export class EntitiesTableComponent extends PageComponent implements AfterViewIn
this.updateData(); this.updateData();
} }
resetSortAndFilter(update: boolean = true) { resetSortAndFilter(update: boolean = true, preserveTimewindow: boolean = false) {
this.pageLink.textSearch = null; this.pageLink.textSearch = null;
if (this.entitiesTableConfig.useTimePageLink) { if (this.entitiesTableConfig.useTimePageLink && !preserveTimewindow) {
this.timewindow = historyInterval(DAY); this.timewindow = historyInterval(DAY);
} }
if (this.displayPagination) { if (this.displayPagination) {

2
ui-ngx/src/app/modules/home/components/event/event-table-header.component.ts

@ -40,6 +40,6 @@ export class EventTableHeaderComponent extends EntityTableHeaderComponent<Event>
eventTypeChanged(eventType: EventType | DebugEventType) { eventTypeChanged(eventType: EventType | DebugEventType) {
this.eventTableConfig.eventType = eventType; this.eventTableConfig.eventType = eventType;
this.eventTableConfig.table.updateData(); this.eventTableConfig.table.resetSortAndFilter(true, true);
} }
} }

21
ui-ngx/src/app/modules/home/components/widget/action/custom-action-pretty-resources-tabs.component.ts

@ -35,6 +35,7 @@ import { CustomActionDescriptor } from '@shared/models/widget.models';
import * as ace from 'ace-builds'; import * as ace from 'ace-builds';
import { CancelAnimationFrame, RafService } from '@core/services/raf.service'; import { CancelAnimationFrame, RafService } from '@core/services/raf.service';
import { css_beautify, html_beautify } from 'js-beautify'; import { css_beautify, html_beautify } from 'js-beautify';
import { ResizeObserver } from '@juggle/resize-observer';
@Component({ @Component({
selector: 'tb-custom-action-pretty-resources-tabs', selector: 'tb-custom-action-pretty-resources-tabs',
@ -64,7 +65,7 @@ export class CustomActionPrettyResourcesTabsComponent extends PageComponent impl
aceEditors: ace.Ace.Editor[] = []; aceEditors: ace.Ace.Editor[] = [];
editorsResizeCafs: {[editorId: string]: CancelAnimationFrame} = {}; editorsResizeCafs: {[editorId: string]: CancelAnimationFrame} = {};
aceResizeListeners: { element: any, resizeListener: any }[] = []; aceResize$: ResizeObserver;
htmlEditor: ace.Ace.Editor; htmlEditor: ace.Ace.Editor;
cssEditor: ace.Ace.Editor; cssEditor: ace.Ace.Editor;
setValuesPending = false; setValuesPending = false;
@ -84,10 +85,7 @@ export class CustomActionPrettyResourcesTabsComponent extends PageComponent impl
} }
ngOnDestroy(): void { ngOnDestroy(): void {
this.aceResizeListeners.forEach((resizeListener) => { this.aceResize$.disconnect();
// @ts-ignore
removeResizeListener(resizeListener.element, resizeListener.resizeListener);
});
} }
ngOnChanges(changes: SimpleChanges): void { ngOnChanges(changes: SimpleChanges): void {
@ -153,6 +151,12 @@ export class CustomActionPrettyResourcesTabsComponent extends PageComponent impl
} }
private initAceEditors() { private initAceEditors() {
this.aceResize$ = new ResizeObserver((entries) => {
entries.forEach((entry) => {
const editor = this.aceEditors.find(aceEditor => aceEditor.container === entry.target);
this.onAceEditorResize(editor);
})
});
this.htmlEditor = this.createAceEditor(this.htmlInputElmRef, 'html'); this.htmlEditor = this.createAceEditor(this.htmlInputElmRef, 'html');
this.htmlEditor.on('input', () => { this.htmlEditor.on('input', () => {
const editorValue = this.htmlEditor.getValue(); const editorValue = this.htmlEditor.getValue();
@ -187,12 +191,7 @@ export class CustomActionPrettyResourcesTabsComponent extends PageComponent impl
const aceEditor = ace.edit(editorElement, editorOptions); const aceEditor = ace.edit(editorElement, editorOptions);
aceEditor.session.setUseWrapMode(true); aceEditor.session.setUseWrapMode(true);
this.aceEditors.push(aceEditor); this.aceEditors.push(aceEditor);
this.aceResize$.observe(editorElement);
const resizeListener = this.onAceEditorResize.bind(this, aceEditor);
// @ts-ignore
addResizeListener(editorElement, resizeListener);
this.aceResizeListeners.push({element: editorElement, resizeListener});
return aceEditor; return aceEditor;
} }

6
ui-ngx/src/app/modules/home/components/widget/lib/date-range-navigator/date-range-navigator.component.ts

@ -84,9 +84,6 @@ export class DateRangeNavigatorWidgetComponent extends PageComponent implements
} }
ngOnInit(): void { ngOnInit(): void {
this.dashboardTimewindowChangedSubscription = this.ctx.dashboard.dashboardTimewindowChanged.subscribe(() => {
this.widgetContextTimewindowSync();
});
this.settings = this.ctx.settings; this.settings = this.ctx.settings;
this.settings.useSessionStorage = isDefined(this.settings.useSessionStorage) ? this.settings.useSessionStorage : true; this.settings.useSessionStorage = isDefined(this.settings.useSessionStorage) ? this.settings.useSessionStorage : true;
let selection; let selection;
@ -110,6 +107,9 @@ export class DateRangeNavigatorWidgetComponent extends PageComponent implements
} }
this.selectedStepSize = this.datesMap[this.settings.stepSize || 'day'].ts; this.selectedStepSize = this.datesMap[this.settings.stepSize || 'day'].ts;
this.widgetContextTimewindowSync(); this.widgetContextTimewindowSync();
this.dashboardTimewindowChangedSubscription = this.ctx.dashboard.dashboardTimewindowChanged.subscribe(() => {
this.widgetContextTimewindowSync();
});
} }
ngOnDestroy(): void { ngOnDestroy(): void {

15
ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-form.component.ts

@ -58,6 +58,7 @@ import { AttributeData, AttributeScope } from '@shared/models/telemetry/telemetr
import { forkJoin, Observable } from 'rxjs'; import { forkJoin, Observable } from 'rxjs';
import { tap } from 'rxjs/operators'; import { tap } from 'rxjs/operators';
import { ImportExportService } from '@home/components/import-export/import-export.service'; import { ImportExportService } from '@home/components/import-export/import-export.service';
import { ResizeObserver } from '@juggle/resize-observer';
// @dynamic // @dynamic
@Component({ @Component({
@ -93,7 +94,7 @@ export class GatewayFormComponent extends PageComponent implements OnInit, OnDes
private successfulSaved: string; private successfulSaved: string;
private gatewayNameExists: string; private gatewayNameExists: string;
private archiveFileName: string; private archiveFileName: string;
private formResizeListener: any; private formResize$: ResizeObserver;
private subscribeStorageType$: any; private subscribeStorageType$: any;
private subscribeGateway$: any; private subscribeGateway$: any;
@ -116,15 +117,15 @@ export class GatewayFormComponent extends PageComponent implements OnInit, OnDes
this.buildForm(); this.buildForm();
this.ctx.updateWidgetParams(); this.ctx.updateWidgetParams();
this.formResizeListener = this.resize.bind(this); this.formResize$ = new ResizeObserver(() => {
// @ts-ignore this.resize();
addResizeListener(this.formContainerRef.nativeElement, this.formResizeListener); });
this.formResize$.observe(this.formContainerRef.nativeElement);
} }
ngOnDestroy(): void { ngOnDestroy(): void {
if (this.formResizeListener) { if (this.formResize$) {
// @ts-ignore this.formResize$.disconnect();
removeResizeListener(this.formContainerRef.nativeElement, this.formResizeListener);
} }
this.subscribeGateway$.unsubscribe(); this.subscribeGateway$.unsubscribe();
this.subscribeStorageType$.unsubscribe(); this.subscribeStorageType$.unsubscribe();

15
ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.ts

@ -33,6 +33,7 @@ import { AttributeService } from '@core/http/attribute.service';
import { AttributeData, AttributeScope, LatestTelemetry } from '@shared/models/telemetry/telemetry.models'; import { AttributeData, AttributeScope, LatestTelemetry } from '@shared/models/telemetry/telemetry.models';
import { forkJoin, Observable } from 'rxjs'; import { forkJoin, Observable } from 'rxjs';
import { EntityId } from '@shared/models/id/entity-id'; import { EntityId } from '@shared/models/id/entity-id';
import { ResizeObserver } from '@juggle/resize-observer';
type FieldAlignment = 'row' | 'column'; type FieldAlignment = 'row' | 'column';
@ -94,7 +95,7 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni
@Input() @Input()
ctx: WidgetContext; ctx: WidgetContext;
private formResizeListener: any; private formResize$: ResizeObserver;
private settings: MultipleInputWidgetSettings; private settings: MultipleInputWidgetSettings;
private widgetConfig: WidgetConfig; private widgetConfig: WidgetConfig;
private subscription: IWidgetSubscription; private subscription: IWidgetSubscription;
@ -135,15 +136,15 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni
this.updateDatasources(); this.updateDatasources();
this.buildForm(); this.buildForm();
this.ctx.updateWidgetParams(); this.ctx.updateWidgetParams();
this.formResizeListener = this.resize.bind(this); this.formResize$ = new ResizeObserver(() => {
// @ts-ignore this.resize();
addResizeListener(this.formContainerRef.nativeElement, this.formResizeListener); });
this.formResize$.observe(this.formContainerRef.nativeElement);
} }
ngOnDestroy(): void { ngOnDestroy(): void {
if (this.formResizeListener) { if (this.formResize$) {
// @ts-ignore this.formResize$.disconnect();
removeResizeListener(this.formContainerRef.nativeElement, this.formResizeListener);
} }
} }

18
ui-ngx/src/app/modules/home/components/widget/lib/rpc/knob.component.ts

@ -22,9 +22,9 @@ import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';
import { isDefined, isNumber } from '@core/utils'; import { isDefined, isNumber } from '@core/utils';
import { CanvasDigitalGauge, CanvasDigitalGaugeOptions } from '@home/components/widget/lib/canvas-digital-gauge'; import { CanvasDigitalGauge, CanvasDigitalGaugeOptions } from '@home/components/widget/lib/canvas-digital-gauge';
import GenericOptions = CanvasGauges.GenericOptions;
import * as tinycolor_ from 'tinycolor2'; import * as tinycolor_ from 'tinycolor2';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; import GenericOptions = CanvasGauges.GenericOptions;
import { ResizeObserver } from '@juggle/resize-observer';
const tinycolor = tinycolor_; const tinycolor = tinycolor_;
@ -103,7 +103,7 @@ export class KnobComponent extends PageComponent implements OnInit, OnDestroy {
private canvasBar: CanvasDigitalGauge; private canvasBar: CanvasDigitalGauge;
private knobResizeListener: any; private knobResize$: ResizeObserver;
constructor(private utils: UtilsService, constructor(private utils: UtilsService,
protected store: Store<AppState>) { protected store: Store<AppState>) {
@ -126,16 +126,16 @@ export class KnobComponent extends PageComponent implements OnInit, OnDestroy {
this.textMeasure = $(this.textMeasureRef.nativeElement); this.textMeasure = $(this.textMeasureRef.nativeElement);
this.canvasBarElement = this.canvasBarElementRef.nativeElement; this.canvasBarElement = this.canvasBarElementRef.nativeElement;
this.knobResizeListener = this.resize.bind(this); this.knobResize$ = new ResizeObserver(() => {
// @ts-ignore this.resize();
addResizeListener(this.knobContainerRef.nativeElement, this.knobResizeListener); });
this.knobResize$.observe(this.knobContainerRef.nativeElement);
this.init(); this.init();
} }
ngOnDestroy(): void { ngOnDestroy(): void {
if (this.knobResizeListener) { if (this.knobResize$) {
// @ts-ignore this.knobResize$.disconnect();
removeResizeListener(this.knobContainerRef.nativeElement, this.knobResizeListener);
} }
} }

15
ui-ngx/src/app/modules/home/components/widget/lib/rpc/led-indicator.component.ts

@ -25,6 +25,7 @@ import { UtilsService } from '@core/services/utils.service';
import { IWidgetSubscription, SubscriptionInfo, WidgetSubscriptionOptions } from '@core/api/widget-api.models'; import { IWidgetSubscription, SubscriptionInfo, WidgetSubscriptionOptions } from '@core/api/widget-api.models';
import { DatasourceType, widgetType } from '@shared/models/widget.models'; import { DatasourceType, widgetType } from '@shared/models/widget.models';
import { EntityType } from '@shared/models/entity-type.models'; import { EntityType } from '@shared/models/entity-type.models';
import { ResizeObserver } from '@juggle/resize-observer';
import Timeout = NodeJS.Timeout; import Timeout = NodeJS.Timeout;
const tinycolor = tinycolor_; const tinycolor = tinycolor_;
@ -93,7 +94,7 @@ export class LedIndicatorComponent extends PageComponent implements OnInit, OnDe
private ledErrorContainer: JQuery<HTMLElement>; private ledErrorContainer: JQuery<HTMLElement>;
private ledError: JQuery<HTMLElement>; private ledError: JQuery<HTMLElement>;
private ledResizeListener: any; private ledResize$: ResizeObserver;
private subscriptionOptions: WidgetSubscriptionOptions = { private subscriptionOptions: WidgetSubscriptionOptions = {
callbacks: { callbacks: {
@ -122,9 +123,10 @@ export class LedIndicatorComponent extends PageComponent implements OnInit, OnDe
this.ledErrorContainer = $(this.ledErrorContainerRef.nativeElement); this.ledErrorContainer = $(this.ledErrorContainerRef.nativeElement);
this.ledError = $(this.ledErrorRef.nativeElement); this.ledError = $(this.ledErrorRef.nativeElement);
this.ledResizeListener = this.resize.bind(this); this.ledResize$ = new ResizeObserver(() => {
// @ts-ignore this.resize();
addResizeListener(this.ledContainerRef.nativeElement, this.ledResizeListener); });
this.ledResize$.observe(this.ledContainerRef.nativeElement);
this.init(); this.init();
} }
@ -136,9 +138,8 @@ export class LedIndicatorComponent extends PageComponent implements OnInit, OnDe
if (this.subscription) { if (this.subscription) {
this.ctx.subscriptionApi.removeSubscription(this.subscription.id); this.ctx.subscriptionApi.removeSubscription(this.subscription.id);
} }
if (this.ledResizeListener) { if (this.ledResize$) {
// @ts-ignore this.ledResize$.disconnect();
removeResizeListener(this.ledContainerRef.nativeElement, this.ledResizeListener);
} }
} }

18
ui-ngx/src/app/modules/home/components/widget/lib/rpc/round-switch.component.ts

@ -14,7 +14,7 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { AfterViewInit, Component, ElementRef, Input, OnDestroy, OnInit, ViewChild } from '@angular/core'; import { Component, ElementRef, Input, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { PageComponent } from '@shared/components/page.component'; import { PageComponent } from '@shared/components/page.component';
import { WidgetContext } from '@home/models/widget-component.models'; import { WidgetContext } from '@home/models/widget-component.models';
import { UtilsService } from '@core/services/utils.service'; import { UtilsService } from '@core/services/utils.service';
@ -24,6 +24,7 @@ import { isDefined } from '@core/utils';
import { IWidgetSubscription, SubscriptionInfo, WidgetSubscriptionOptions } from '@core/api/widget-api.models'; import { IWidgetSubscription, SubscriptionInfo, WidgetSubscriptionOptions } from '@core/api/widget-api.models';
import { DatasourceType, widgetType } from '@shared/models/widget.models'; import { DatasourceType, widgetType } from '@shared/models/widget.models';
import { EntityType } from '@shared/models/entity-type.models'; import { EntityType } from '@shared/models/entity-type.models';
import { ResizeObserver } from '@juggle/resize-observer';
type RetrieveValueMethod = 'rpc' | 'attribute' | 'timeseries'; type RetrieveValueMethod = 'rpc' | 'attribute' | 'timeseries';
@ -88,7 +89,7 @@ export class RoundSwitchComponent extends PageComponent implements OnInit, OnDes
private switchErrorContainer: JQuery<HTMLElement>; private switchErrorContainer: JQuery<HTMLElement>;
private switchError: JQuery<HTMLElement>; private switchError: JQuery<HTMLElement>;
private switchResizeListener: any; private switchResize$: ResizeObserver;
constructor(private utils: UtilsService, constructor(private utils: UtilsService,
protected store: Store<AppState>) { protected store: Store<AppState>) {
@ -110,20 +111,19 @@ export class RoundSwitchComponent extends PageComponent implements OnInit, OnDes
this.onValue(); this.onValue();
}); });
this.switchResizeListener = this.resize.bind(this); this.switchResize$ = new ResizeObserver(() => {
// @ts-ignore this.resize();
addResizeListener(this.switchContainerRef.nativeElement, this.switchResizeListener); });
this.switchResize$.observe(this.switchContainerRef.nativeElement);
this.init(); this.init();
// this.ctx.resize = this.resize.bind(this);
} }
ngOnDestroy(): void { ngOnDestroy(): void {
if (this.valueSubscription) { if (this.valueSubscription) {
this.ctx.subscriptionApi.removeSubscription(this.valueSubscription.id); this.ctx.subscriptionApi.removeSubscription(this.valueSubscription.id);
} }
if (this.switchResizeListener) { if (this.switchResize$) {
// @ts-ignore this.switchResize$.disconnect();
removeResizeListener(this.switchContainerRef.nativeElement, this.switchResizeListener);
} }
} }

15
ui-ngx/src/app/modules/home/components/widget/lib/rpc/switch.component.ts

@ -25,6 +25,7 @@ import { IWidgetSubscription, SubscriptionInfo, WidgetSubscriptionOptions } from
import { DatasourceType, widgetType } from '@shared/models/widget.models'; import { DatasourceType, widgetType } from '@shared/models/widget.models';
import { EntityType } from '@shared/models/entity-type.models'; import { EntityType } from '@shared/models/entity-type.models';
import { MatSlideToggle } from '@angular/material/slide-toggle'; import { MatSlideToggle } from '@angular/material/slide-toggle';
import { ResizeObserver } from '@juggle/resize-observer';
const switchAspectRation = 2.7893; const switchAspectRation = 2.7893;
@ -98,7 +99,7 @@ export class SwitchComponent extends PageComponent implements OnInit, OnDestroy
private switchErrorContainer: JQuery<HTMLElement>; private switchErrorContainer: JQuery<HTMLElement>;
private switchError: JQuery<HTMLElement>; private switchError: JQuery<HTMLElement>;
private switchResizeListener: any; private switchResize$: ResizeObserver;
constructor(private utils: UtilsService, constructor(private utils: UtilsService,
protected store: Store<AppState>) { protected store: Store<AppState>) {
@ -118,9 +119,10 @@ export class SwitchComponent extends PageComponent implements OnInit, OnDestroy
this.switchErrorContainer = $(this.switchErrorContainerRef.nativeElement); this.switchErrorContainer = $(this.switchErrorContainerRef.nativeElement);
this.switchError = $(this.switchErrorRef.nativeElement); this.switchError = $(this.switchErrorRef.nativeElement);
this.switchResizeListener = this.resize.bind(this); this.switchResize$ = new ResizeObserver(() => {
// @ts-ignore this.resize();
addResizeListener(this.switchContainerRef.nativeElement, this.switchResizeListener); })
this.switchResize$.observe(this.switchContainerRef.nativeElement);
this.init(); this.init();
} }
@ -128,9 +130,8 @@ export class SwitchComponent extends PageComponent implements OnInit, OnDestroy
if (this.valueSubscription) { if (this.valueSubscription) {
this.ctx.subscriptionApi.removeSubscription(this.valueSubscription.id); this.ctx.subscriptionApi.removeSubscription(this.valueSubscription.id);
} }
if (this.switchResizeListener) { if (this.switchResize$) {
// @ts-ignore this.switchResize$.disconnect();
removeResizeListener(this.switchContainerRef.nativeElement, this.switchResizeListener);
} }
} }

16
ui-ngx/src/app/modules/home/components/widget/widget.component.ts

@ -91,6 +91,7 @@ import { DatasourceService } from '@core/api/datasource.service';
import { WidgetSubscription } from '@core/api/widget-subscription'; import { WidgetSubscription } from '@core/api/widget-subscription';
import { EntityService } from '@core/http/entity.service'; import { EntityService } from '@core/http/entity.service';
import { ServicesMap } from '@home/models/services.map'; import { ServicesMap } from '@home/models/services.map';
import { ResizeObserver } from '@juggle/resize-observer';
@Component({ @Component({
selector: 'tb-widget', selector: 'tb-widget',
@ -140,7 +141,7 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI
cafs: {[cafId: string]: CancelAnimationFrame} = {}; cafs: {[cafId: string]: CancelAnimationFrame} = {};
onResizeListener = null; private widgetResize$: ResizeObserver;
private cssParser = new cssjs(); private cssParser = new cssjs();
@ -647,10 +648,8 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI
} }
private destroyDynamicWidgetComponent() { private destroyDynamicWidgetComponent() {
if (this.widgetContext.$containerParent && this.onResizeListener) { if (this.widgetContext.$containerParent && this.widgetResize$) {
// @ts-ignore this.widgetResize$.disconnect()
removeResizeListener(this.widgetContext.$containerParent[0], this.onResizeListener);
this.onResizeListener = null;
} }
if (this.dynamicWidgetComponentRef) { if (this.dynamicWidgetComponentRef) {
this.dynamicWidgetComponentRef.destroy(); this.dynamicWidgetComponentRef.destroy();
@ -709,9 +708,10 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI
} }
} }
this.onResizeListener = this.onResize.bind(this); this.widgetResize$ = new ResizeObserver(() => {
// @ts-ignore this.onResize();
addResizeListener(this.widgetContext.$containerParent[0], this.onResizeListener); });
this.widgetResize$.observe(this.widgetContext.$containerParent[0]);
} }
private createSubscription(options: WidgetSubscriptionOptions, subscribe?: boolean): Observable<IWidgetSubscription> { private createSubscription(options: WidgetSubscriptionOptions, subscribe?: boolean): Observable<IWidgetSubscription> {

5
ui-ngx/src/app/modules/home/models/dashboard-component.models.ts

@ -389,7 +389,7 @@ export class DashboardWidget implements GridsterItem, IDashboardWidget {
padding: this.padding, padding: this.padding,
margin: this.margin}; margin: this.margin};
if (this.widget.config.widgetStyle) { if (this.widget.config.widgetStyle) {
this.style = {...this.widget.config.widgetStyle, ...this.style}; this.style = {...this.style, ...this.widget.config.widgetStyle};
} }
this.showWidgetTitlePanel = this.widgetContext.hideTitlePanel ? false : this.showWidgetTitlePanel = this.widgetContext.hideTitlePanel ? false :
@ -474,7 +474,8 @@ export class DashboardWidget implements GridsterItem, IDashboardWidget {
if (mobileHeight) { if (mobileHeight) {
res = mobileHeight; res = mobileHeight;
} else { } else {
res = this.widget.sizeY * 24 / this.dashboard.gridsterOpts.minCols; const sizeY = this.widgetLayout ? this.widgetLayout.sizeY : this.widget.sizeY;
res = sizeY * 24 / this.dashboard.gridsterOpts.minCols;
} }
} else { } else {
if (this.widgetLayout) { if (this.widgetLayout) {

2
ui-ngx/src/app/modules/home/pages/asset/asset-table-header.component.ts

@ -36,7 +36,7 @@ export class AssetTableHeaderComponent extends EntityTableHeaderComponent<AssetI
assetTypeChanged(assetType: string) { assetTypeChanged(assetType: string) {
this.entitiesTableConfig.componentsData.assetType = assetType; this.entitiesTableConfig.componentsData.assetType = assetType;
this.entitiesTableConfig.table.updateData(); this.entitiesTableConfig.table.resetSortAndFilter(true);
} }
} }

3
ui-ngx/src/app/modules/home/pages/dashboard/dashboard-toolbar.component.ts

@ -14,8 +14,7 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { Component, OnDestroy, OnInit, ViewEncapsulation, Input, Output, EventEmitter } from '@angular/core'; import { Component, EventEmitter, Input, OnInit, Output, ViewEncapsulation } from '@angular/core';
import { PageComponent } from '@shared/components/page.component';
@Component({ @Component({
selector: 'tb-dashboard-toolbar', selector: 'tb-dashboard-toolbar',

2
ui-ngx/src/app/modules/home/pages/device/device-table-header.component.ts

@ -36,7 +36,7 @@ export class DeviceTableHeaderComponent extends EntityTableHeaderComponent<Devic
deviceTypeChanged(deviceType: string) { deviceTypeChanged(deviceType: string) {
this.entitiesTableConfig.componentsData.deviceType = deviceType; this.entitiesTableConfig.componentsData.deviceType = deviceType;
this.entitiesTableConfig.table.updateData(); this.entitiesTableConfig.table.resetSortAndFilter(true);
} }
} }

2
ui-ngx/src/app/modules/home/pages/entity-view/entity-view-table-header.component.ts

@ -36,7 +36,7 @@ export class EntityViewTableHeaderComponent extends EntityTableHeaderComponent<E
entityViewTypeChanged(entityViewType: string) { entityViewTypeChanged(entityViewType: string) {
this.entitiesTableConfig.componentsData.entityViewType = entityViewType; this.entitiesTableConfig.componentsData.entityViewType = entityViewType;
this.entitiesTableConfig.table.updateData(); this.entitiesTableConfig.table.resetSortAndFilter(true);
} }
} }

21
ui-ngx/src/app/modules/home/pages/widget/widget-editor.component.ts

@ -46,6 +46,7 @@ import {
} from '@home/pages/widget/save-widget-type-as-dialog.component'; } from '@home/pages/widget/save-widget-type-as-dialog.component';
import { Subscription } from 'rxjs'; import { Subscription } from 'rxjs';
import Timeout = NodeJS.Timeout; import Timeout = NodeJS.Timeout;
import { ResizeObserver } from '@juggle/resize-observer';
// @dynamic // @dynamic
@Component({ @Component({
@ -124,7 +125,7 @@ export class WidgetEditorComponent extends PageComponent implements OnInit, OnDe
jsonSettingsEditor: ace.Ace.Editor; jsonSettingsEditor: ace.Ace.Editor;
dataKeyJsonSettingsEditor: ace.Ace.Editor; dataKeyJsonSettingsEditor: ace.Ace.Editor;
jsEditor: ace.Ace.Editor; jsEditor: ace.Ace.Editor;
aceResizeListeners: { element: any, resizeListener: any }[] = []; aceResize$: ResizeObserver;
onWindowMessageListener = this.onWindowMessage.bind(this); onWindowMessageListener = this.onWindowMessage.bind(this);
@ -193,10 +194,7 @@ export class WidgetEditorComponent extends PageComponent implements OnInit, OnDe
ngOnDestroy(): void { ngOnDestroy(): void {
this.window.removeEventListener('message', this.onWindowMessageListener); this.window.removeEventListener('message', this.onWindowMessageListener);
this.aceResizeListeners.forEach((resizeListener) => { this.aceResize$.disconnect();
// @ts-ignore
removeResizeListener(resizeListener.element, resizeListener.resizeListener);
});
this.rxSubscriptions.forEach((subscription) => { this.rxSubscriptions.forEach((subscription) => {
subscription.unsubscribe(); subscription.unsubscribe();
}); });
@ -272,6 +270,12 @@ export class WidgetEditorComponent extends PageComponent implements OnInit, OnDe
} }
private initAceEditors() { private initAceEditors() {
this.aceResize$ = new ResizeObserver((entries) => {
entries.forEach((entry) => {
const editor = this.aceEditors.find(aceEditor => aceEditor.container === entry.target);
this.onAceEditorResize(editor);
})
});
this.htmlEditor = this.createAceEditor(this.htmlInputElmRef, 'html'); this.htmlEditor = this.createAceEditor(this.htmlInputElmRef, 'html');
this.htmlEditor.on('input', () => { this.htmlEditor.on('input', () => {
const editorValue = this.htmlEditor.getValue(); const editorValue = this.htmlEditor.getValue();
@ -342,12 +346,7 @@ export class WidgetEditorComponent extends PageComponent implements OnInit, OnDe
const aceEditor = ace.edit(editorElement, editorOptions); const aceEditor = ace.edit(editorElement, editorOptions);
aceEditor.session.setUseWrapMode(true); aceEditor.session.setUseWrapMode(true);
this.aceEditors.push(aceEditor); this.aceEditors.push(aceEditor);
this.aceResize$.observe(editorElement);
const resizeListener = this.onAceEditorResize.bind(this, aceEditor);
// @ts-ignore
addResizeListener(editorElement, resizeListener);
this.aceResizeListeners.push({element: editorElement, resizeListener});
return aceEditor; return aceEditor;
} }

3
ui-ngx/src/app/shared/components/breadcrumb.component.ts

@ -93,7 +93,6 @@ export class BreadcrumbComponent implements OnInit, OnDestroy {
const icon = breadcrumbConfig.icon || 'home'; const icon = breadcrumbConfig.icon || 'home';
const isMdiIcon = icon.startsWith('mdi:'); const isMdiIcon = icon.startsWith('mdi:');
const link = [ route.pathFromRoot.map(v => v.url.map(segment => segment.toString()).join('/')).join('/') ]; const link = [ route.pathFromRoot.map(v => v.url.map(segment => segment.toString()).join('/')).join('/') ];
const queryParams = route.queryParams;
const breadcrumb = { const breadcrumb = {
label, label,
labelFunction, labelFunction,
@ -101,7 +100,7 @@ export class BreadcrumbComponent implements OnInit, OnDestroy {
icon, icon,
isMdiIcon, isMdiIcon,
link, link,
queryParams queryParams: null
}; };
newBreadcrumbs = [...breadcrumbs, breadcrumb]; newBreadcrumbs = [...breadcrumbs, breadcrumb];
} }

14
ui-ngx/src/app/shared/components/fab-toolbar.component.ts

@ -29,6 +29,7 @@ import {
} from '@angular/core'; } from '@angular/core';
import { WINDOW } from '@core/services/window.service'; import { WINDOW } from '@core/services/window.service';
import { CanColorCtor, mixinColor } from '@angular/material/core'; import { CanColorCtor, mixinColor } from '@angular/material/core';
import { ResizeObserver } from '@juggle/resize-observer';
export declare type FabToolbarDirection = 'left' | 'right'; export declare type FabToolbarDirection = 'left' | 'right';
@ -77,14 +78,14 @@ export class FabActionsDirective implements OnInit {
}) })
export class FabToolbarComponent extends MatFabToolbarMixinBase implements OnInit, OnDestroy, AfterViewInit, OnChanges { export class FabToolbarComponent extends MatFabToolbarMixinBase implements OnInit, OnDestroy, AfterViewInit, OnChanges {
private fabToolbarResize$: ResizeObserver;
@Input() @Input()
isOpen: boolean; isOpen: boolean;
@Input() @Input()
direction: FabToolbarDirection; direction: FabToolbarDirection;
fabToolbarResizeListener = this.onFabToolbarResize.bind(this);
constructor(private el: ElementRef<HTMLElement>, constructor(private el: ElementRef<HTMLElement>,
@Inject(WINDOW) private window: Window) { @Inject(WINDOW) private window: Window) {
super(el); super(el);
@ -96,13 +97,14 @@ export class FabToolbarComponent extends MatFabToolbarMixinBase implements OnIni
element.find('mat-fab-trigger').find('button') element.find('mat-fab-trigger').find('button')
.prepend('<div class="mat-fab-toolbar-background"></div>'); .prepend('<div class="mat-fab-toolbar-background"></div>');
element.addClass(`mat-${this.direction}`); element.addClass(`mat-${this.direction}`);
// @ts-ignore this.fabToolbarResize$ = new ResizeObserver(() => {
addResizeListener(this.el.nativeElement, this.fabToolbarResizeListener); this.onFabToolbarResize();
});
this.fabToolbarResize$.observe(this.el.nativeElement);
} }
ngOnDestroy(): void { ngOnDestroy(): void {
// @ts-ignore this.fabToolbarResize$.disconnect();
removeResizeListener(this.el.nativeElement, this.fabToolbarResizeListener);
} }
ngAfterViewInit(): void { ngAfterViewInit(): void {

20
ui-ngx/src/app/shared/components/js-func.component.ts

@ -15,11 +15,11 @@
/// ///
import { import {
ChangeDetectionStrategy,
Component, Component,
ElementRef, ElementRef,
forwardRef, forwardRef,
Input, OnDestroy, Input,
OnDestroy,
OnInit, OnInit,
ViewChild, ViewChild,
ViewEncapsulation ViewEncapsulation
@ -34,6 +34,7 @@ import { UtilsService } from '@core/services/utils.service';
import { guid, isUndefined } from '@app/core/utils'; import { guid, isUndefined } from '@app/core/utils';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { CancelAnimationFrame, RafService } from '@core/services/raf.service'; import { CancelAnimationFrame, RafService } from '@core/services/raf.service';
import { ResizeObserver } from '@juggle/resize-observer';
@Component({ @Component({
selector: 'tb-js-func', selector: 'tb-js-func',
@ -60,7 +61,7 @@ export class JsFuncComponent implements OnInit, OnDestroy, ControlValueAccessor,
private jsEditor: ace.Ace.Editor; private jsEditor: ace.Ace.Editor;
private editorsResizeCaf: CancelAnimationFrame; private editorsResizeCaf: CancelAnimationFrame;
private editorResizeListener: any; private editorResize$: ResizeObserver;
toastTargetId = `jsFuncEditor-${guid()}`; toastTargetId = `jsFuncEditor-${guid()}`;
@ -152,16 +153,15 @@ export class JsFuncComponent implements OnInit, OnDestroy, ControlValueAccessor,
this.cleanupJsErrors(); this.cleanupJsErrors();
this.updateView(); this.updateView();
}); });
this.editorResizeListener = this.onAceEditorResize.bind(this); this.editorResize$ = new ResizeObserver(() => {
// @ts-ignore this.onAceEditorResize();
addResizeListener(editorElement, this.editorResizeListener); });
this.editorResize$.observe(editorElement);
} }
ngOnDestroy(): void { ngOnDestroy(): void {
if (this.editorResizeListener) { if (this.editorResize$) {
const editorElement = this.javascriptEditorElmRef.nativeElement; this.editorResize$.disconnect();
// @ts-ignore
removeResizeListener(editorElement, this.editorResizeListener);
} }
} }

22
ui-ngx/src/app/shared/components/json-content.component.ts

@ -20,10 +20,10 @@ import {
forwardRef, forwardRef,
Input, Input,
OnChanges, OnChanges,
OnDestroy,
OnInit, OnInit,
ViewChild,
SimpleChanges, SimpleChanges,
OnDestroy ViewChild
} from '@angular/core'; } from '@angular/core';
import { ControlValueAccessor, FormControl, NG_VALIDATORS, NG_VALUE_ACCESSOR, Validator } from '@angular/forms'; import { ControlValueAccessor, FormControl, NG_VALIDATORS, NG_VALUE_ACCESSOR, Validator } from '@angular/forms';
import * as ace from 'ace-builds'; import * as ace from 'ace-builds';
@ -34,6 +34,7 @@ import { AppState } from '@core/core.state';
import { ContentType, contentTypesMap } from '@shared/models/constants'; import { ContentType, contentTypesMap } from '@shared/models/constants';
import { CancelAnimationFrame, RafService } from '@core/services/raf.service'; import { CancelAnimationFrame, RafService } from '@core/services/raf.service';
import { guid } from '@core/utils'; import { guid } from '@core/utils';
import { ResizeObserver } from '@juggle/resize-observer';
@Component({ @Component({
selector: 'tb-json-content', selector: 'tb-json-content',
@ -59,7 +60,7 @@ export class JsonContentComponent implements OnInit, ControlValueAccessor, Valid
private jsonEditor: ace.Ace.Editor; private jsonEditor: ace.Ace.Editor;
private editorsResizeCaf: CancelAnimationFrame; private editorsResizeCaf: CancelAnimationFrame;
private editorResizeListener: any; private editorResize$: ResizeObserver;
toastTargetId = `jsonContentEditor-${guid()}`; toastTargetId = `jsonContentEditor-${guid()}`;
@ -97,8 +98,6 @@ export class JsonContentComponent implements OnInit, ControlValueAccessor, Valid
contentValid: boolean; contentValid: boolean;
validationError: string;
errorShowed = false; errorShowed = false;
private propagateChange = null; private propagateChange = null;
@ -135,16 +134,15 @@ export class JsonContentComponent implements OnInit, ControlValueAccessor, Valid
this.cleanupJsonErrors(); this.cleanupJsonErrors();
this.updateView(); this.updateView();
}); });
this.editorResizeListener = this.onAceEditorResize.bind(this); this.editorResize$ = new ResizeObserver(() => {
// @ts-ignore this.onAceEditorResize();
addResizeListener(editorElement, this.editorResizeListener); });
this.editorResize$.observe(editorElement);
} }
ngOnDestroy(): void { ngOnDestroy(): void {
if (this.editorResizeListener) { if (this.editorResize$) {
const editorElement = this.jsonEditorElmRef.nativeElement; this.editorResize$.disconnect();
// @ts-ignore
removeResizeListener(editorElement, this.editorResizeListener);
} }
} }

28
ui-ngx/src/app/shared/components/json-form/json-form.component.ts

@ -15,7 +15,6 @@
/// ///
import { import {
ChangeDetectionStrategy,
Component, Component,
ElementRef, ElementRef,
forwardRef, forwardRef,
@ -106,6 +105,8 @@ export class JsonFormComponent implements OnInit, ControlValueAccessor, Validato
private propagateChange = null; private propagateChange = null;
private propagateChangePending = false; private propagateChangePending = false;
private writingValue = false;
private updateViewPending = false;
constructor(public elementRef: ElementRef, constructor(public elementRef: ElementRef,
private translate: TranslateService, private translate: TranslateService,
@ -143,6 +144,7 @@ export class JsonFormComponent implements OnInit, ControlValueAccessor, Validato
} }
writeValue(data: JsonFormComponentData): void { writeValue(data: JsonFormComponentData): void {
this.writingValue = true;
this.data = data; this.data = data;
this.schema = this.data && this.data.schema ? deepClone(this.data.schema) : { this.schema = this.data && this.data.schema ? deepClone(this.data.schema) : {
type: 'object' type: 'object'
@ -154,19 +156,29 @@ export class JsonFormComponent implements OnInit, ControlValueAccessor, Validato
this.model = inspector.sanitize(this.schema, this.model).data; this.model = inspector.sanitize(this.schema, this.model).data;
this.updateAndRender(); this.updateAndRender();
this.isModelValid = this.validateModel(); this.isModelValid = this.validateModel();
if (!this.isModelValid) { this.writingValue = false;
if (!this.isModelValid || this.updateViewPending) {
this.updateView(); this.updateView();
} }
} }
updateView() { updateView() {
if (this.data) { if (!this.writingValue) {
this.data.model = this.model; this.updateViewPending = false;
if (this.propagateChange) { if (this.data) {
this.propagateChange(this.data); this.data.model = this.model;
} else { if (this.propagateChange) {
this.propagateChangePending = true; try {
this.propagateChange(this.data);
} catch (e) {
this.propagateChangePending = true;
}
} else {
this.propagateChangePending = true;
}
} }
} else {
this.updateViewPending = true;
} }
} }

28
ui-ngx/src/app/shared/components/json-object-edit.component.ts

@ -14,16 +14,8 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { import { Component, ElementRef, forwardRef, Input, OnDestroy, OnInit, ViewChild } from '@angular/core';
Attribute, ChangeDetectionStrategy, import { ControlValueAccessor, FormControl, NG_VALIDATORS, NG_VALUE_ACCESSOR, Validator } from '@angular/forms';
Component,
ElementRef,
forwardRef,
Input, OnDestroy,
OnInit,
ViewChild
} from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR, FormControl, Validator, NG_VALIDATORS } from '@angular/forms';
import * as ace from 'ace-builds'; import * as ace from 'ace-builds';
import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { ActionNotificationHide, ActionNotificationShow } from '@core/notification/notification.actions'; import { ActionNotificationHide, ActionNotificationShow } from '@core/notification/notification.actions';
@ -31,6 +23,7 @@ import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';
import { CancelAnimationFrame, RafService } from '@core/services/raf.service'; import { CancelAnimationFrame, RafService } from '@core/services/raf.service';
import { guid } from '@core/utils'; import { guid } from '@core/utils';
import { ResizeObserver } from '@juggle/resize-observer';
@Component({ @Component({
selector: 'tb-json-object-edit', selector: 'tb-json-object-edit',
@ -56,7 +49,7 @@ export class JsonObjectEditComponent implements OnInit, ControlValueAccessor, Va
private jsonEditor: ace.Ace.Editor; private jsonEditor: ace.Ace.Editor;
private editorsResizeCaf: CancelAnimationFrame; private editorsResizeCaf: CancelAnimationFrame;
private editorResizeListener: any; private editorResize$: ResizeObserver;
toastTargetId = `jsonObjectEditor-${guid()}`; toastTargetId = `jsonObjectEditor-${guid()}`;
@ -128,16 +121,15 @@ export class JsonObjectEditComponent implements OnInit, ControlValueAccessor, Va
this.cleanupJsonErrors(); this.cleanupJsonErrors();
this.updateView(); this.updateView();
}); });
this.editorResizeListener = this.onAceEditorResize.bind(this); this.editorResize$ = new ResizeObserver(() => {
// @ts-ignore this.onAceEditorResize();
addResizeListener(editorElement, this.editorResizeListener); });
this.editorResize$.observe(editorElement);
} }
ngOnDestroy(): void { ngOnDestroy(): void {
if (this.editorResizeListener) { if (this.editorResize$) {
const editorElement = this.jsonEditorElmRef.nativeElement; this.editorResize$.disconnect();
// @ts-ignore
removeResizeListener(editorElement, this.editorResizeListener);
} }
} }

Loading…
Cancel
Save