2021-05-26 13:49:30 +03:00
|
|
|
///
|
2024-01-09 10:46:16 +02:00
|
|
|
/// Copyright © 2016-2024 The Thingsboard Authors
|
2021-05-26 13:49:30 +03:00
|
|
|
///
|
|
|
|
|
/// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
/// you may not use this file except in compliance with the License.
|
|
|
|
|
/// You may obtain a copy of the License at
|
|
|
|
|
///
|
|
|
|
|
/// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
///
|
|
|
|
|
/// Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
/// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
/// See the License for the specific language governing permissions and
|
|
|
|
|
/// limitations under the License.
|
|
|
|
|
///
|
|
|
|
|
|
|
|
|
|
import {
|
2023-07-21 18:26:14 +03:00
|
|
|
AfterViewInit,
|
2021-05-26 13:49:30 +03:00
|
|
|
ChangeDetectionStrategy,
|
|
|
|
|
ChangeDetectorRef,
|
2023-03-02 10:25:06 +02:00
|
|
|
Component,
|
|
|
|
|
ElementRef,
|
|
|
|
|
EventEmitter,
|
|
|
|
|
HostBinding,
|
|
|
|
|
Inject,
|
|
|
|
|
Input,
|
|
|
|
|
OnDestroy,
|
2021-05-26 13:49:30 +03:00
|
|
|
OnInit,
|
2023-03-02 10:25:06 +02:00
|
|
|
Output,
|
|
|
|
|
Renderer2,
|
|
|
|
|
ViewChild,
|
|
|
|
|
ViewEncapsulation
|
2021-05-26 13:49:30 +03:00
|
|
|
} from '@angular/core';
|
|
|
|
|
import { PageComponent } from '@shared/components/page.component';
|
|
|
|
|
import { DashboardWidget, DashboardWidgets } from '@home/models/dashboard-component.models';
|
|
|
|
|
import { Store } from '@ngrx/store';
|
|
|
|
|
import { AppState } from '@core/core.state';
|
|
|
|
|
import { SafeStyle } from '@angular/platform-browser';
|
2023-03-02 10:25:06 +02:00
|
|
|
import { guid, isNotEmptyStr } from '@core/utils';
|
2021-12-22 17:15:10 +02:00
|
|
|
import cssjs from '@core/css/css';
|
|
|
|
|
import { DOCUMENT } from '@angular/common';
|
|
|
|
|
import { GridsterItemComponent } from 'angular-gridster2';
|
2021-05-26 13:49:30 +03:00
|
|
|
|
|
|
|
|
export enum WidgetComponentActionType {
|
|
|
|
|
MOUSE_DOWN,
|
|
|
|
|
CLICKED,
|
|
|
|
|
CONTEXT_MENU,
|
|
|
|
|
EDIT,
|
|
|
|
|
EXPORT,
|
|
|
|
|
REMOVE
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export class WidgetComponentAction {
|
|
|
|
|
event: MouseEvent;
|
|
|
|
|
actionType: WidgetComponentActionType;
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-22 17:15:10 +02:00
|
|
|
// @dynamic
|
2021-05-26 13:49:30 +03:00
|
|
|
@Component({
|
|
|
|
|
selector: 'tb-widget-container',
|
|
|
|
|
templateUrl: './widget-container.component.html',
|
|
|
|
|
styleUrls: ['./widget-container.component.scss'],
|
2023-03-02 10:25:06 +02:00
|
|
|
encapsulation: ViewEncapsulation.None,
|
2021-05-26 13:49:30 +03:00
|
|
|
changeDetection: ChangeDetectionStrategy.OnPush
|
|
|
|
|
})
|
2023-07-21 18:26:14 +03:00
|
|
|
export class WidgetContainerComponent extends PageComponent implements OnInit, AfterViewInit, OnDestroy {
|
2021-12-22 17:15:10 +02:00
|
|
|
|
|
|
|
|
@HostBinding('class')
|
|
|
|
|
widgetContainerClass = 'tb-widget-container';
|
|
|
|
|
|
|
|
|
|
@ViewChild('tbWidgetElement', {static: true})
|
|
|
|
|
tbWidgetElement: ElementRef;
|
|
|
|
|
|
|
|
|
|
@Input()
|
|
|
|
|
gridsterItem: GridsterItemComponent;
|
2021-05-26 13:49:30 +03:00
|
|
|
|
|
|
|
|
@Input()
|
|
|
|
|
widget: DashboardWidget;
|
|
|
|
|
|
|
|
|
|
@Input()
|
|
|
|
|
dashboardStyle: {[klass: string]: any};
|
|
|
|
|
|
|
|
|
|
@Input()
|
|
|
|
|
backgroundImage: SafeStyle | string;
|
|
|
|
|
|
|
|
|
|
@Input()
|
|
|
|
|
isEdit: boolean;
|
|
|
|
|
|
|
|
|
|
@Input()
|
|
|
|
|
isMobile: boolean;
|
|
|
|
|
|
|
|
|
|
@Input()
|
|
|
|
|
dashboardWidgets: DashboardWidgets;
|
|
|
|
|
|
|
|
|
|
@Input()
|
|
|
|
|
isEditActionEnabled: boolean;
|
|
|
|
|
|
|
|
|
|
@Input()
|
|
|
|
|
isExportActionEnabled: boolean;
|
|
|
|
|
|
|
|
|
|
@Input()
|
|
|
|
|
isRemoveActionEnabled: boolean;
|
|
|
|
|
|
|
|
|
|
@Input()
|
|
|
|
|
disableWidgetInteraction = false;
|
|
|
|
|
|
|
|
|
|
@Output()
|
|
|
|
|
widgetFullscreenChanged: EventEmitter<boolean> = new EventEmitter<boolean>();
|
|
|
|
|
|
|
|
|
|
@Output()
|
|
|
|
|
widgetComponentAction: EventEmitter<WidgetComponentAction> = new EventEmitter<WidgetComponentAction>();
|
|
|
|
|
|
2021-12-22 17:15:10 +02:00
|
|
|
private cssClass: string;
|
|
|
|
|
|
2021-05-26 13:49:30 +03:00
|
|
|
constructor(protected store: Store<AppState>,
|
2021-12-22 17:15:10 +02:00
|
|
|
private cd: ChangeDetectorRef,
|
|
|
|
|
private renderer: Renderer2,
|
|
|
|
|
@Inject(DOCUMENT) private document: Document) {
|
2021-05-26 13:49:30 +03:00
|
|
|
super(store);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ngOnInit(): void {
|
|
|
|
|
this.widget.widgetContext.containerChangeDetector = this.cd;
|
2021-12-22 17:15:10 +02:00
|
|
|
const cssString = this.widget.widget.config.widgetCss;
|
|
|
|
|
if (isNotEmptyStr(cssString)) {
|
|
|
|
|
const cssParser = new cssjs();
|
|
|
|
|
cssParser.testMode = false;
|
|
|
|
|
this.cssClass = 'tb-widget-css-' + guid();
|
|
|
|
|
this.renderer.addClass(this.gridsterItem.el, this.cssClass);
|
|
|
|
|
cssParser.cssPreviewNamespace = this.cssClass;
|
|
|
|
|
cssParser.createStyleElement(this.cssClass, cssString);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-21 18:26:14 +03:00
|
|
|
ngAfterViewInit(): void {
|
|
|
|
|
this.widget.widgetContext.$widgetElement = $(this.tbWidgetElement.nativeElement);
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-22 17:15:10 +02:00
|
|
|
ngOnDestroy(): void {
|
|
|
|
|
if (this.cssClass) {
|
|
|
|
|
const el = this.document.getElementById(this.cssClass);
|
|
|
|
|
if (el) {
|
|
|
|
|
el.parentNode.removeChild(el);
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-05-26 13:49:30 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
isHighlighted(widget: DashboardWidget) {
|
|
|
|
|
return this.dashboardWidgets.isHighlighted(widget);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
isNotHighlighted(widget: DashboardWidget) {
|
|
|
|
|
return this.dashboardWidgets.isNotHighlighted(widget);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
onFullscreenChanged(expanded: boolean) {
|
2021-12-22 17:15:10 +02:00
|
|
|
if (expanded) {
|
|
|
|
|
this.renderer.addClass(this.tbWidgetElement.nativeElement, this.cssClass);
|
|
|
|
|
} else {
|
|
|
|
|
this.renderer.removeClass(this.tbWidgetElement.nativeElement, this.cssClass);
|
|
|
|
|
}
|
2021-05-26 13:49:30 +03:00
|
|
|
this.widgetFullscreenChanged.emit(expanded);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
onMouseDown(event: MouseEvent) {
|
|
|
|
|
this.widgetComponentAction.emit({
|
|
|
|
|
event,
|
|
|
|
|
actionType: WidgetComponentActionType.MOUSE_DOWN
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
onClicked(event: MouseEvent) {
|
|
|
|
|
this.widgetComponentAction.emit({
|
|
|
|
|
event,
|
|
|
|
|
actionType: WidgetComponentActionType.CLICKED
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
onContextMenu(event: MouseEvent) {
|
|
|
|
|
this.widgetComponentAction.emit({
|
|
|
|
|
event,
|
|
|
|
|
actionType: WidgetComponentActionType.CONTEXT_MENU
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
onEdit(event: MouseEvent) {
|
|
|
|
|
this.widgetComponentAction.emit({
|
|
|
|
|
event,
|
|
|
|
|
actionType: WidgetComponentActionType.EDIT
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
onExport(event: MouseEvent) {
|
|
|
|
|
this.widgetComponentAction.emit({
|
|
|
|
|
event,
|
|
|
|
|
actionType: WidgetComponentActionType.EXPORT
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
onRemove(event: MouseEvent) {
|
|
|
|
|
this.widgetComponentAction.emit({
|
|
|
|
|
event,
|
|
|
|
|
actionType: WidgetComponentActionType.REMOVE
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|