Commit 1c10ede1c594532329f09ede08f211ff77f967ef

Authored by Igor Kulikov
1 parent c3ebc2f2

Custom actions implementation

@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 "version": "3.0.0", 3 "version": "3.0.0",
4 "scripts": { 4 "scripts": {
5 "ng": "ng", 5 "ng": "ng",
6 - "start": "ng serve --open", 6 + "start": "ng serve --host 0.0.0.0 --open",
7 "build": "ng build", 7 "build": "ng build",
8 "build:prod": "ng build --prod --vendor-chunk", 8 "build:prod": "ng build --prod --vendor-chunk",
9 "test": "ng test", 9 "test": "ng test",
@@ -36,6 +36,9 @@ import { DatasourceService } from '@core/api/datasource.service'; @@ -36,6 +36,9 @@ import { DatasourceService } from '@core/api/datasource.service';
36 import { RafService } from '@core/services/raf.service'; 36 import { RafService } from '@core/services/raf.service';
37 import { EntityAliases } from '@shared/models/alias.models'; 37 import { EntityAliases } from '@shared/models/alias.models';
38 import { EntityInfo } from '@app/shared/models/entity.models'; 38 import { EntityInfo } from '@app/shared/models/entity.models';
  39 +import { Type } from '@angular/core';
  40 +import { AssetService } from '@core/http/asset.service';
  41 +import { DialogService } from '@core/services/dialog.service';
39 42
40 export interface TimewindowFunctions { 43 export interface TimewindowFunctions {
41 onUpdateTimewindow: (startTimeMs: number, endTimeMs: number, interval?: number) => void; 44 onUpdateTimewindow: (startTimeMs: number, endTimeMs: number, interval?: number) => void;
@@ -30,6 +30,7 @@ import { @@ -30,6 +30,7 @@ import {
30 MaterialIconsDialogComponent, 30 MaterialIconsDialogComponent,
31 MaterialIconsDialogData 31 MaterialIconsDialogData
32 } from '@shared/components/dialog/material-icons-dialog.component'; 32 } from '@shared/components/dialog/material-icons-dialog.component';
  33 +import { DynamicComponentFactoryService } from '@core/services/dynamic-component-factory.service';
33 34
34 @Injectable( 35 @Injectable(
35 { 36 {
@@ -41,6 +42,7 @@ export class DialogService { @@ -41,6 +42,7 @@ export class DialogService {
41 constructor( 42 constructor(
42 private translate: TranslateService, 43 private translate: TranslateService,
43 private authService: AuthService, 44 private authService: AuthService,
  45 + private dynamicComponentFactoryService: DynamicComponentFactoryService,
44 public dialog: MatDialog 46 public dialog: MatDialog
45 ) { 47 ) {
46 } 48 }
@@ -31,7 +31,6 @@ import { CommonModule } from '@angular/common'; @@ -31,7 +31,6 @@ import { CommonModule } from '@angular/common';
31 export abstract class DynamicComponentModule implements OnDestroy { 31 export abstract class DynamicComponentModule implements OnDestroy {
32 32
33 ngOnDestroy(): void { 33 ngOnDestroy(): void {
34 - console.log('Module destroyed!');  
35 } 34 }
36 35
37 } 36 }
@@ -56,6 +56,8 @@ import { ManageWidgetActionsComponent } from './widget/action/manage-widget-acti @@ -56,6 +56,8 @@ import { ManageWidgetActionsComponent } from './widget/action/manage-widget-acti
56 import { WidgetActionDialogComponent } from './widget/action/widget-action-dialog.component'; 56 import { WidgetActionDialogComponent } from './widget/action/widget-action-dialog.component';
57 import { CustomActionPrettyResourcesTabsComponent } from './widget/action/custom-action-pretty-resources-tabs.component'; 57 import { CustomActionPrettyResourcesTabsComponent } from './widget/action/custom-action-pretty-resources-tabs.component';
58 import { CustomActionPrettyEditorComponent } from './widget/action/custom-action-pretty-editor.component'; 58 import { CustomActionPrettyEditorComponent } from './widget/action/custom-action-pretty-editor.component';
  59 +import { CustomDialogService } from './widget/dialog/custom-dialog.service';
  60 +import { CustomDialogContainerComponent } from './widget/dialog/custom-dialog-container.component';
59 61
60 @NgModule({ 62 @NgModule({
61 entryComponents: [ 63 entryComponents: [
@@ -72,7 +74,8 @@ import { CustomActionPrettyEditorComponent } from './widget/action/custom-action @@ -72,7 +74,8 @@ import { CustomActionPrettyEditorComponent } from './widget/action/custom-action
72 EntityAliasDialogComponent, 74 EntityAliasDialogComponent,
73 DataKeyConfigDialogComponent, 75 DataKeyConfigDialogComponent,
74 LegendConfigPanelComponent, 76 LegendConfigPanelComponent,
75 - WidgetActionDialogComponent 77 + WidgetActionDialogComponent,
  78 + CustomDialogContainerComponent
76 ], 79 ],
77 declarations: 80 declarations:
78 [ 81 [
@@ -113,7 +116,8 @@ import { CustomActionPrettyEditorComponent } from './widget/action/custom-action @@ -113,7 +116,8 @@ import { CustomActionPrettyEditorComponent } from './widget/action/custom-action
113 ManageWidgetActionsComponent, 116 ManageWidgetActionsComponent,
114 WidgetActionDialogComponent, 117 WidgetActionDialogComponent,
115 CustomActionPrettyResourcesTabsComponent, 118 CustomActionPrettyResourcesTabsComponent,
116 - CustomActionPrettyEditorComponent 119 + CustomActionPrettyEditorComponent,
  120 + CustomDialogContainerComponent
117 ], 121 ],
118 imports: [ 122 imports: [
119 CommonModule, 123 CommonModule,
@@ -149,10 +153,12 @@ import { CustomActionPrettyEditorComponent } from './widget/action/custom-action @@ -149,10 +153,12 @@ import { CustomActionPrettyEditorComponent } from './widget/action/custom-action
149 ManageWidgetActionsComponent, 153 ManageWidgetActionsComponent,
150 WidgetActionDialogComponent, 154 WidgetActionDialogComponent,
151 CustomActionPrettyResourcesTabsComponent, 155 CustomActionPrettyResourcesTabsComponent,
152 - CustomActionPrettyEditorComponent 156 + CustomActionPrettyEditorComponent,
  157 + CustomDialogContainerComponent
153 ], 158 ],
154 providers: [ 159 providers: [
155 - WidgetComponentService 160 + WidgetComponentService,
  161 + CustomDialogService
156 ] 162 ]
157 }) 163 })
158 export class HomeComponentsModule { } 164 export class HomeComponentsModule { }
  1 +/*================================================================================*/
  2 +/*======================= New TB 3.0 / Angular 8 Example =======================*/
  3 +/*================================================================================*/
  4 +/*
  5 +.edit-entity-form mat-form-field {
  6 + padding-right: 10px;
  7 +}
  8 +*/
1 /*=======================================================================*/ 9 /*=======================================================================*/
2 /*========== There are two examples: for edit and add entity ==========*/ 10 /*========== There are two examples: for edit and add entity ==========*/
3 /*=======================================================================*/ 11 /*=======================================================================*/
1 <!--=======================================================================--> 1 <!--=======================================================================-->
  2 +<!--=================== New TB 3.0 / Angular 8 Example =================-->
  3 +<!--=======================================================================-->
  4 +<!--<form #editEntityForm="ngForm" [formGroup]="editEntityFormGroup"-->
  5 +<!-- class="edit-entity-form"-->
  6 +<!-- (ngSubmit)="save()" style="width: 600px;">-->
  7 +<!-- <mat-toolbar fxLayout="row" color="primary">-->
  8 +<!-- <h2>Edit {{entityType.toLowerCase()}} {{entityName}}</h2>-->
  9 +<!-- <span fxFlex></span>-->
  10 +<!-- <button mat-button mat-icon-button-->
  11 +<!-- (click)="cancel()"-->
  12 +<!-- type="button">-->
  13 +<!-- <mat-icon class="material-icons">close</mat-icon>-->
  14 +<!-- </button>-->
  15 +<!-- </mat-toolbar>-->
  16 +<!-- <mat-progress-bar color="warn" mode="indeterminate" *ngIf="isLoading$ | async">-->
  17 +<!-- </mat-progress-bar>-->
  18 +<!-- <div style="height: 4px;" *ngIf="!(isLoading$ | async)"></div>-->
  19 +<!-- <div mat-dialog-content>-->
  20 +<!-- <div class="mat-padding" fxLayout="column">-->
  21 +<!-- <mat-form-field class="mat-block">-->
  22 +<!-- <mat-label>Entity name</mat-label>-->
  23 +<!-- <input matInput formControlName="entityName" required>-->
  24 +<!-- <mat-error *ngIf="editEntityFormGroup.get('entityName').hasError('required')">-->
  25 +<!-- Entity name required-->
  26 +<!-- </mat-error>-->
  27 +<!-- </mat-form-field>-->
  28 +<!-- </div> -->
  29 +<!-- </div>-->
  30 +<!-- <div mat-dialog-actions fxLayout="row">-->
  31 +<!-- <span fxFlex></span>-->
  32 +<!-- <button mat-button mat-raised-button color="primary"-->
  33 +<!-- type="submit"-->
  34 +<!-- [disabled]="(isLoading$ | async) || editEntityForm.invalid || !editEntityForm.dirty">-->
  35 +<!-- {{ 'action.save' | translate }}-->
  36 +<!-- </button>-->
  37 +<!-- <button mat-button color="primary"-->
  38 +<!-- style="margin-right: 20px;"-->
  39 +<!-- type="button"-->
  40 +<!-- [disabled]="(isLoading$ | async)"-->
  41 +<!-- (click)="cancel()" cdkFocusInitial>-->
  42 +<!-- {{ 'action.cancel' | translate }}-->
  43 +<!-- </button>-->
  44 +<!-- </div>-->
  45 +<!--</form>-->
  46 +<!--=======================================================================-->
2 <!--===== There are two example templates: for edit and add entity =====--> 47 <!--===== There are two example templates: for edit and add entity =====-->
3 <!--=======================================================================--> 48 <!--=======================================================================-->
4 <!--======================== Edit entity example ========================--> 49 <!--======================== Edit entity example ========================-->
  1 +/*================================================================================*/
  2 +/*======================= New TB 3.0 / Angular 8 Example =======================*/
  3 +/*================================================================================*/
  4 +//
  5 +//let $injector = widgetContext.$scope.$injector;
  6 +//let deviceService = $injector.get(widgetContext.servicesMap.get('deviceService'));
  7 +//
  8 +//deviceService.getDevice(entityId.id).subscribe(function(device) {
  9 +// console.log(device);
  10 +//});
  11 +//
  12 +//
  13 +//let customDialog = $injector.get(widgetContext.servicesMap.get('customDialog'));
  14 +//
  15 +//customDialog.customDialog(htmlTemplate, EditEntityDialogController).subscribe(
  16 +// function(res) {
  17 +// console.log(res);
  18 +// }
  19 +//);
  20 +//
  21 +//function EditEntityDialogController(instance) {
  22 +// let vm = instance;
  23 +// vm.entityId = entityId;
  24 +// vm.entityName = entityName;
  25 +// vm.entityType = entityId.entityType;
  26 +//
  27 +// vm.editEntityFormGroup = vm.fb.group({
  28 +// entityName: [vm.entityName, [vm.Validators.required]]
  29 +// });
  30 +//
  31 +// vm.cancel = function() {
  32 +// vm.dialogRef.close(null);
  33 +// };
  34 +//
  35 +// vm.save = function() {
  36 +// const newVal = vm.editEntityFormGroup.value;
  37 +// vm.dialogRef.close(newVal);
  38 +// };
  39 +//}
  40 +//
1 /*=======================================================================*/ 41 /*=======================================================================*/
2 /*===== There are three examples: for delete, edit and add entity =====*/ 42 /*===== There are three examples: for delete, edit and add entity =====*/
3 /*=======================================================================*/ 43 /*=======================================================================*/
  1 +///
  2 +/// Copyright © 2016-2019 The Thingsboard Authors
  3 +///
  4 +/// Licensed under the Apache License, Version 2.0 (the "License");
  5 +/// you may not use this file except in compliance with the License.
  6 +/// You may obtain a copy of the License at
  7 +///
  8 +/// http://www.apache.org/licenses/LICENSE-2.0
  9 +///
  10 +/// Unless required by applicable law or agreed to in writing, software
  11 +/// distributed under the License is distributed on an "AS IS" BASIS,
  12 +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 +/// See the License for the specific language governing permissions and
  14 +/// limitations under the License.
  15 +///
  16 +
  17 +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
  18 +import {
  19 + Inject,
  20 + ComponentRef,
  21 + ElementRef,
  22 + ViewContainerRef,
  23 + ComponentFactory,
  24 + Injector,
  25 + ReflectiveInjector,
  26 + Component,
  27 + OnDestroy
  28 +} from '@angular/core';
  29 +import { DialogComponent } from '@shared/components/dialog.component';
  30 +import { Store } from '@ngrx/store';
  31 +import { AppState } from '@core/core.state';
  32 +import { Router } from '@angular/router';
  33 +import {
  34 + CustomDialogComponent,
  35 + CUSTOM_DIALOG_DATA,
  36 + CustomDialogData
  37 +} from '@home/components/widget/dialog/custom-dialog.component';
  38 +
  39 +export interface CustomDialogContainerData {
  40 + controller: (instance: CustomDialogComponent) => void;
  41 + data?: any;
  42 + customComponentFactory: ComponentFactory<CustomDialogComponent>;
  43 +}
  44 +
  45 +@Component({
  46 + selector: 'tb-custom-dialog-container-component',
  47 + template: ''
  48 +})
  49 +export class CustomDialogContainerComponent extends DialogComponent<CustomDialogContainerComponent, any> implements OnDestroy {
  50 +
  51 + private customComponentRef: ComponentRef<CustomDialogComponent>;
  52 +
  53 + constructor(protected store: Store<AppState>,
  54 + protected router: Router,
  55 + public viewContainerRef: ViewContainerRef,
  56 + public dialogRef: MatDialogRef<CustomDialogContainerComponent, any>,
  57 + @Inject(MAT_DIALOG_DATA) public data: CustomDialogContainerData) {
  58 + super(store, router, dialogRef);
  59 + let customDialogData: CustomDialogData = {
  60 + controller: this.data.controller
  61 + };
  62 + if (this.data.data) {
  63 + customDialogData = {...customDialogData, ...this.data.data};
  64 + }
  65 + const injector: Injector = ReflectiveInjector.resolveAndCreate([
  66 + {
  67 + provide: CUSTOM_DIALOG_DATA,
  68 + useValue: customDialogData
  69 + },
  70 + {
  71 + provide: MatDialogRef,
  72 + useValue: dialogRef
  73 + }
  74 + ]);
  75 + this.customComponentRef = this.viewContainerRef.createComponent(this.data.customComponentFactory, 0, injector);
  76 + }
  77 +
  78 + ngOnDestroy(): void {
  79 + super.ngOnDestroy();
  80 + if (this.customComponentRef) {
  81 + this.customComponentRef.destroy();
  82 + }
  83 + }
  84 +
  85 +}
  1 +///
  2 +/// Copyright © 2016-2019 The Thingsboard Authors
  3 +///
  4 +/// Licensed under the Apache License, Version 2.0 (the "License");
  5 +/// you may not use this file except in compliance with the License.
  6 +/// You may obtain a copy of the License at
  7 +///
  8 +/// http://www.apache.org/licenses/LICENSE-2.0
  9 +///
  10 +/// Unless required by applicable law or agreed to in writing, software
  11 +/// distributed under the License is distributed on an "AS IS" BASIS,
  12 +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 +/// See the License for the specific language governing permissions and
  14 +/// limitations under the License.
  15 +///
  16 +
  17 +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
  18 +import { Inject, InjectionToken } from '@angular/core';
  19 +import { DialogComponent } from '@shared/components/dialog.component';
  20 +import { Store } from '@ngrx/store';
  21 +import { AppState } from '@core/core.state';
  22 +import { Router } from '@angular/router';
  23 +import { PageComponent } from '@shared/components/page.component';
  24 +import { CustomDialogContainerComponent } from './custom-dialog-container.component';
  25 +import { FormBuilder, Validators } from '@angular/forms';
  26 +
  27 +export const CUSTOM_DIALOG_DATA = new InjectionToken<any>('ConfigDialogData');
  28 +
  29 +export interface CustomDialogData {
  30 + controller: (instance: CustomDialogComponent) => void;
  31 + [key: string]: any;
  32 +}
  33 +
  34 +export class CustomDialogComponent extends PageComponent {
  35 +
  36 + [key: string]: any;
  37 +
  38 + constructor(protected store: Store<AppState>,
  39 + protected router: Router,
  40 + public dialogRef: MatDialogRef<CustomDialogContainerComponent>,
  41 + public fb: FormBuilder,
  42 + @Inject(CUSTOM_DIALOG_DATA) public data: CustomDialogData) {
  43 + super(store);
  44 + // @ts-ignore
  45 + this.Validators = Validators;
  46 + this.data.controller(this);
  47 + }
  48 +}
  1 +///
  2 +/// Copyright © 2016-2019 The Thingsboard Authors
  3 +///
  4 +/// Licensed under the Apache License, Version 2.0 (the "License");
  5 +/// you may not use this file except in compliance with the License.
  6 +/// You may obtain a copy of the License at
  7 +///
  8 +/// http://www.apache.org/licenses/LICENSE-2.0
  9 +///
  10 +/// Unless required by applicable law or agreed to in writing, software
  11 +/// distributed under the License is distributed on an "AS IS" BASIS,
  12 +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 +/// See the License for the specific language governing permissions and
  14 +/// limitations under the License.
  15 +///
  16 +
  17 +import { Injectable, Injector, NgModule } from '@angular/core';
  18 +import { Observable } from 'rxjs';
  19 +import { MatDialog } from '@angular/material';
  20 +import { TranslateService } from '@ngx-translate/core';
  21 +import { AuthService } from '@core/auth/auth.service';
  22 +import { DynamicComponentFactoryService } from '@core/services/dynamic-component-factory.service';
  23 +import { CommonModule } from '@angular/common';
  24 +import { SharedModule } from '@shared/shared.module';
  25 +import { mergeMap, tap } from 'rxjs/operators';
  26 +import { CustomDialogComponent } from './custom-dialog.component';
  27 +import {
  28 + CustomDialogContainerComponent,
  29 + CustomDialogContainerData
  30 +} from '@home/components/widget/dialog/custom-dialog-container.component';
  31 +
  32 +@Injectable()
  33 +export class CustomDialogService {
  34 +
  35 + constructor(
  36 + private translate: TranslateService,
  37 + private authService: AuthService,
  38 + private dynamicComponentFactoryService: DynamicComponentFactoryService,
  39 + private injector: Injector,
  40 + public dialog: MatDialog
  41 + ) {
  42 + }
  43 +
  44 + customDialog(template: string, controller: (instance: CustomDialogComponent) => void, data?: any): Observable<any> {
  45 + return this.dynamicComponentFactoryService.createDynamicComponentFactory(
  46 + class CustomDialogComponentInstance extends CustomDialogComponent {},
  47 + template,
  48 + [SharedModule, CustomDialogModule]).pipe(
  49 + mergeMap((factory) => {
  50 + const dialogData: CustomDialogContainerData = {
  51 + controller,
  52 + customComponentFactory: factory,
  53 + data
  54 + };
  55 + return this.dialog.open<CustomDialogContainerComponent, CustomDialogContainerData, any>(
  56 + CustomDialogContainerComponent,
  57 + {
  58 + disableClose: true,
  59 + panelClass: ['tb-dialog', 'tb-fullscreen-dialog'],
  60 + data: dialogData
  61 + }).afterClosed().pipe(
  62 + tap(() => {
  63 + this.dynamicComponentFactoryService.destroyDynamicComponentFactory(factory);
  64 + })
  65 + );
  66 + }
  67 + ));
  68 + }
  69 +
  70 +}
  71 +
  72 +@NgModule({
  73 + entryComponents: [
  74 + ],
  75 + declarations:
  76 + [
  77 + ],
  78 + imports: [
  79 + CommonModule,
  80 + SharedModule
  81 + ],
  82 + exports: [
  83 + ]
  84 +})
  85 +class CustomDialogModule { }
@@ -28,7 +28,7 @@ import { @@ -28,7 +28,7 @@ import {
28 OnChanges, 28 OnChanges,
29 OnDestroy, 29 OnDestroy,
30 OnInit, 30 OnInit,
31 - SimpleChanges, 31 + SimpleChanges, Type,
32 ViewChild, 32 ViewChild,
33 ViewContainerRef, 33 ViewContainerRef,
34 ViewEncapsulation 34 ViewEncapsulation
@@ -90,6 +90,15 @@ import { DashboardService } from '@core/http/dashboard.service'; @@ -90,6 +90,15 @@ import { DashboardService } from '@core/http/dashboard.service';
90 import { DatasourceService } from '@core/api/datasource.service'; 90 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 { AssetService } from '@core/http/asset.service';
  94 +import { DialogService } from '@core/services/dialog.service';
  95 +import { CustomDialogService } from '@home/components/widget/dialog/custom-dialog.service';
  96 +
  97 +const ServicesMap = new Map<string, Type<any>>();
  98 +ServicesMap.set('deviceService', DeviceService);
  99 +ServicesMap.set('assetService', AssetService);
  100 +ServicesMap.set('dialogs', DialogService);
  101 +ServicesMap.set('customDialog', CustomDialogService);
93 102
94 @Component({ 103 @Component({
95 selector: 'tb-widget', 104 selector: 'tb-widget',
@@ -242,6 +251,7 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI @@ -242,6 +251,7 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI
242 } 251 }
243 252
244 this.widgetContext = this.dashboardWidget.widgetContext; 253 this.widgetContext = this.dashboardWidget.widgetContext;
  254 + this.widgetContext.servicesMap = ServicesMap;
245 this.widgetContext.inited = false; 255 this.widgetContext.inited = false;
246 this.widgetContext.hideTitlePanel = false; 256 this.widgetContext.hideTitlePanel = false;
247 this.widgetContext.isEdit = this.isEdit; 257 this.widgetContext.isEdit = this.isEdit;
@@ -647,6 +657,7 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI @@ -647,6 +657,7 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI
647 this.dynamicWidgetComponent.errorMessages = this.errorMessages; 657 this.dynamicWidgetComponent.errorMessages = this.errorMessages;
648 658
649 this.widgetContext.$scope = this.dynamicWidgetComponent; 659 this.widgetContext.$scope = this.dynamicWidgetComponent;
  660 + this.widgetContext.$scope.$injector = this.injector;
650 661
651 const containerElement = $(this.elementRef.nativeElement.querySelector('#widget-container')); 662 const containerElement = $(this.elementRef.nativeElement.querySelector('#widget-container'));
652 663
@@ -39,12 +39,16 @@ import { @@ -39,12 +39,16 @@ import {
39 WidgetActionsApi, 39 WidgetActionsApi,
40 WidgetSubscriptionApi 40 WidgetSubscriptionApi
41 } from '@core/api/widget-api.models'; 41 } from '@core/api/widget-api.models';
42 -import { ComponentFactory } from '@angular/core'; 42 +import { ComponentFactory, Type } from '@angular/core';
43 import { HttpErrorResponse } from '@angular/common/http'; 43 import { HttpErrorResponse } from '@angular/common/http';
44 import { RafService } from '@core/services/raf.service'; 44 import { RafService } from '@core/services/raf.service';
45 import { WidgetTypeId } from '@shared/models/id/widget-type-id'; 45 import { WidgetTypeId } from '@shared/models/id/widget-type-id';
46 import { TenantId } from '@shared/models/id/tenant-id'; 46 import { TenantId } from '@shared/models/id/tenant-id';
47 import { WidgetLayout } from '@shared/models/dashboard.models'; 47 import { WidgetLayout } from '@shared/models/dashboard.models';
  48 +import { DeviceService } from '@core/http/device.service';
  49 +import { AssetService } from '@app/core/http/asset.service';
  50 +import { DialogService } from '@core/services/dialog.service';
  51 +import { CustomDialogService } from '@home/components/widget/dialog/custom-dialog.service';
48 52
49 export interface IWidgetAction { 53 export interface IWidgetAction {
50 name: string; 54 name: string;
@@ -98,6 +102,7 @@ export interface WidgetContext { @@ -98,6 +102,7 @@ export interface WidgetContext {
98 customHeaderActions?: Array<WidgetHeaderAction>; 102 customHeaderActions?: Array<WidgetHeaderAction>;
99 widgetActions?: Array<WidgetAction>; 103 widgetActions?: Array<WidgetAction>;
100 104
  105 + servicesMap?: Map<string, Type<any>>;
101 } 106 }
102 107
103 export interface IDynamicWidgetComponent { 108 export interface IDynamicWidgetComponent {
@@ -92,7 +92,7 @@ export class FullscreenDirective implements OnChanges, OnDestroy { @@ -92,7 +92,7 @@ export class FullscreenDirective implements OnChanges, OnDestroy {
92 92
93 this.overlayRef = this.overlay.create(config); 93 this.overlayRef = this.overlay.create(config);
94 this.overlayRef.attach(new EmptyPortal()); 94 this.overlayRef.attach(new EmptyPortal());
95 - this.overlayRef.overlayElement.append( targetElement ); 95 + this.overlayRef.overlayElement.appendChild( targetElement );
96 this.fullscreenChanged.emit(true); 96 this.fullscreenChanged.emit(true);
97 } 97 }
98 98
@@ -100,7 +100,7 @@ export class FullscreenDirective implements OnChanges, OnDestroy { @@ -100,7 +100,7 @@ export class FullscreenDirective implements OnChanges, OnDestroy {
100 const targetElement: HTMLElement = this.fullscreenElement || this.elementRef.nativeElement; 100 const targetElement: HTMLElement = this.fullscreenElement || this.elementRef.nativeElement;
101 if (this.parentElement) { 101 if (this.parentElement) {
102 this.overlayRef.overlayElement.removeChild( targetElement ); 102 this.overlayRef.overlayElement.removeChild( targetElement );
103 - this.parentElement.append(targetElement); 103 + this.parentElement.appendChild(targetElement);
104 this.parentElement = null; 104 this.parentElement = null;
105 } 105 }
106 targetElement.classList.remove('tb-fullscreen'); 106 targetElement.classList.remove('tb-fullscreen');
@@ -332,6 +332,7 @@ pre.tb-highlight { @@ -332,6 +332,7 @@ pre.tb-highlight {
332 332
333 .tb-fullscreen-parent { 333 .tb-fullscreen-parent {
334 background: #eee; 334 background: #eee;
  335 + z-index: 0;
335 } 336 }
336 337
337 mat-label { 338 mat-label {