Browse Source

UI: SCADA symbol preview mode.

pull/11391/head
Igor Kulikov 2 years ago
parent
commit
32d34e0acc
  1. 5
      ui-ngx/src/app/core/utils.ts
  2. 2
      ui-ngx/src/app/modules/home/components/widget/lib/svg/iot-svg-widget.component.html
  3. 39
      ui-ngx/src/app/modules/home/components/widget/lib/svg/iot-svg-widget.component.ts
  4. 4
      ui-ngx/src/app/modules/home/components/widget/lib/svg/iot-svg-widget.models.ts
  5. 87
      ui-ngx/src/app/modules/home/components/widget/lib/svg/iot-svg.models.ts
  6. 44
      ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol.component.html
  7. 150
      ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol.component.ts
  8. 63
      ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol.models.ts

5
ui-ngx/src/app/core/utils.ts

@ -229,6 +229,11 @@ export const updateFileContent = (file: File, newContent: string): File => {
return new File([blob], file.name, {type: file.type});
};
export const createFileFromContent = (content: string, name: string, type: string): File => {
const blob = new Blob([content], { type });
return new File([blob], name, { type });
};
const scrollRegex = /(auto|scroll)/;
function parentNodes(node: Node, nodes: Node[]): Node[] {

2
ui-ngx/src/app/modules/home/components/widget/lib/svg/iot-svg-widget.component.html

@ -22,5 +22,5 @@
<div #iotSvgShape class="tb-iot-svg-shape">
</div>
</div>
<mat-progress-bar class="tb-action-widget-progress" style="height: 4px;" color="accent" mode="indeterminate" *ngIf="iotSvgObject.loading$ | async"></mat-progress-bar>
<mat-progress-bar class="tb-action-widget-progress" style="height: 4px;" color="accent" mode="indeterminate" *ngIf="iotSvgObject?.loading$ | async"></mat-progress-bar>
</div>

39
ui-ngx/src/app/modules/home/components/widget/lib/svg/iot-svg-widget.component.ts

@ -35,8 +35,9 @@ import {
iotSvgWidgetDefaultSettings,
IotSvgWidgetSettings
} from '@home/components/widget/lib/svg/iot-svg-widget.models';
import { Observable } from 'rxjs';
import { Observable, of } from 'rxjs';
import { backgroundStyle, ComponentStyle, overlayStyle } from '@shared/models/widget-settings.models';
import { ImageService } from '@core/http/image.service';
@Component({
selector: 'tb-iot-svg-widget',
@ -63,6 +64,7 @@ export class IotSvgWidgetComponent extends
constructor(protected imagePipe: ImagePipe,
protected sanitizer: DomSanitizer,
private renderer: Renderer2,
private imageService: ImageService,
protected cd: ChangeDetectorRef,
private http: HttpClient) {
super(cd);
@ -75,15 +77,40 @@ export class IotSvgWidgetComponent extends
this.backgroundStyle$ = backgroundStyle(this.settings.background, this.imagePipe, this.sanitizer);
this.overlayStyle = overlayStyle(this.settings.background.overlay);
this.iotSvgObject = new IotSvgObject(this.ctx, this.settings.iotSvg, this.settings.iotSvgObject);
let svgContent$: Observable<string>;
if (this.settings.iotSvgContent) {
svgContent$ = of(this.settings.iotSvgContent);
} else if (this.settings.iotSvgUrl) {
svgContent$ = this.imageService.getImageString(this.settings.iotSvgUrl);
} else {
svgContent$ = this.http.get(this.settings.iotSvg, {responseType: 'text'});
}
svgContent$.subscribe(
(content) => {
this.initObject(content);
}
);
}
private initObject(svgContent: string) {
this.iotSvgObject = new IotSvgObject(this.ctx, svgContent, this.settings.iotSvgObject);
this.iotSvgObject.onError((error) => {
this.ctx.showErrorToast(error, 'bottom', 'center', this.ctx.toastTargetId, true);
});
this.iotSvgObject.init().subscribe();
this.iotSvgObject.init();
if (this.iotSvgShape) {
this.iotSvgObject.addTo(this.iotSvgShape.nativeElement);
if (this.autoScale) {
this.onResize();
}
}
}
ngAfterViewInit(): void {
this.iotSvgObject.addTo(this.iotSvgShape.nativeElement);
if (this.iotSvgObject) {
this.iotSvgObject.addTo(this.iotSvgShape.nativeElement);
}
if (this.autoScale) {
this.shapeResize$ = new ResizeObserver(() => {
this.onResize();
@ -114,6 +141,8 @@ export class IotSvgWidgetComponent extends
private onResize() {
const shapeWidth = this.iotSvgShape.nativeElement.getBoundingClientRect().width;
const shapeHeight = this.iotSvgShape.nativeElement.getBoundingClientRect().height;
this.iotSvgObject.setSize(shapeWidth, shapeHeight);
if (this.iotSvgObject) {
this.iotSvgObject.setSize(shapeWidth, shapeHeight);
}
}
}

4
ui-ngx/src/app/modules/home/components/widget/lib/svg/iot-svg-widget.models.ts

@ -18,7 +18,9 @@ import { IotSvgObjectSettings } from '@home/components/widget/lib/svg/iot-svg.mo
import { BackgroundSettings, BackgroundType } from '@shared/models/widget-settings.models';
export interface IotSvgWidgetSettings {
iotSvg: string;
iotSvg?: string;
iotSvgUrl?: string;
iotSvgContent?: string;
iotSvgObject: IotSvgObjectSettings;
background: BackgroundSettings;
}

87
ui-ngx/src/app/modules/home/components/widget/lib/svg/iot-svg.models.ts

@ -34,7 +34,7 @@ import {
parseFunction
} from '@core/utils';
import { BehaviorSubject, forkJoin, Observable, Observer } from 'rxjs';
import { map, share } from 'rxjs/operators';
import { share } from 'rxjs/operators';
import { ValueAction, ValueGetter, ValueSetter } from '@home/components/widget/lib/action/action-widget.models';
import { WidgetContext } from '@home/models/widget-component.models';
import { ColorProcessor, constantColor, Font } from '@shared/models/widget-settings.models';
@ -196,45 +196,38 @@ const updateIotSvgMetadataInDom = (svgDoc: Document, metadata: IotSvgMetadata) =
};
const svgPartsRegex = /(<svg .*?>)(.*)<\/svg>/gms;
const tbMetadataRegex = /<tb:metadata>.*<\/tb:metadata>/gs;
const svgMetadataRegex = /<tb:metadata>.*<\/tb:metadata>/gs;
export const svgRootNodePart = (svgContent: string): string => {
let result = svgContent;
svgPartsRegex.lastIndex = 0;
const match = svgPartsRegex.exec(svgContent);
if (match != null && match.length > 1) {
result = match[1];
}
return result;
};
export interface IoTSvgContentData {
svgRootNode: string;
innerSvg: string;
}
export const innerSvgContent = (svgContent: string): string => {
let result = svgContent;
export const iotSvgContentData = (svgContent: string): IoTSvgContentData => {
const result: IoTSvgContentData = {
svgRootNode: '',
innerSvg: ''
};
svgPartsRegex.lastIndex = 0;
const match = svgPartsRegex.exec(svgContent);
if (match != null && match.length > 2) {
result = match[2];
}
return result;
};
export const stripSvgMetadata = (svgContent: string) => {
let result = svgContent;
svgMetadataRegex.lastIndex = 0;
const match = svgMetadataRegex.exec(svgContent);
if (match !== null && match.length) {
const metadata = match[0];
result = result.replace(metadata, '');
if (match != null) {
if (match.length > 1) {
result.svgRootNode = match[1];
}
if (match.length > 2) {
let innerSvgContent = match[2];
tbMetadataRegex.lastIndex = 0;
const metadataMatch = tbMetadataRegex.exec(svgContent);
if (metadataMatch !== null && metadataMatch.length) {
const metadata = metadataMatch[0];
innerSvgContent = innerSvgContent.replace(metadata, '');
}
result.innerSvg = innerSvgContent;
}
}
return result;
};
export const innerSvgContentFromSvgjs = (svgContent: string): string => {
const result = innerSvgContent(svgContent);
return result.replace(/svgjs:.*?=".*?"/gs, '');
};
const defaultGetValueSettings = (get: IotSvgBehaviorValue): GetValueSettings<any> => ({
action: GetValueAction.DO_NOTHING,
defaultValue: get.defaultValue,
@ -335,21 +328,18 @@ export class IotSvgObject {
private _onError: (error: string) => void = () => {};
constructor(private ctx: WidgetContext,
private svgPath: string,
private inputSettings: IotSvgObjectSettings) {}
public init(): Observable<any> {
return this.ctx.http.get(this.svgPath, {responseType: 'text'}).pipe(
map((inputSvgContent) => {
const doc: XMLDocument = new DOMParser().parseFromString(inputSvgContent, 'image/svg+xml');
this.metadata = parseIotSvgMetadataFromDom(doc);
const defaults = defaultIotSvgObjectSettings(this.metadata);
this.settings = mergeDeep<IotSvgObjectSettings>({}, defaults, this.inputSettings || {});
this.prepareMetadata();
this.prepareSvgShape(doc);
this.initialize();
})
);
private svgContent: string,
private inputSettings: IotSvgObjectSettings) {
}
public init() {
const doc: XMLDocument = new DOMParser().parseFromString(this.svgContent, 'image/svg+xml');
this.metadata = parseIotSvgMetadataFromDom(doc);
const defaults = defaultIotSvgObjectSettings(this.metadata);
this.settings = mergeDeep<IotSvgObjectSettings>({}, defaults, this.inputSettings || {});
this.prepareMetadata();
this.prepareSvgShape(doc);
this.initialize();
}
public onError(onError: (error: string) => void) {
@ -371,6 +361,9 @@ export class IotSvgObject {
this.valueActions.forEach(v => v.destroy());
this.loadingSubject.complete();
this.loadingSubject.unsubscribe();
if (this.svgShape) {
this.svgShape.remove();
}
}
public setSize(targetWidth: number, targetHeight: number) {

44
ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol.component.html

@ -29,41 +29,39 @@
[showCloseDetails]="false"
headerHeightPx="64"
headerTitle="{{symbolData?.imageResource?.title}}">
<div [formGroup]="scadaSymbolFormGroup">
<button mat-button
*ngIf="previewMode"
(click)="exitPreviewMode()">
<mat-icon>chevron_left</mat-icon>
{{ 'action.back' | translate }}
</button>
<div [fxShow]="!previewMode" [formGroup]="scadaSymbolFormGroup">
<tb-scada-symbol-metadata formControlName="metadata">
<div class="tb-scada-symbol-metadata-header-prefix">
<button mat-button
*ngIf="previewMode"
(click)="previewMode = false">
<mat-icon>chevron_left</mat-icon>
{{ 'action.back' | translate }}
</button>
<button *ngIf="!previewMode"
fxHide.gt-sm
<button fxHide.gt-sm
[disabled]="!scadaSymbolFormGroup.valid"
mat-button color="primary"
(click)="previewMode = true">
(click)="enterPreviewMode()">
<mat-icon>visibility</mat-icon>
{{ 'scada.preview' | translate }}
</button>
</div>
<div fxFlex.lt-md class="tb-scada-symbol-metadata-header-suffix" fxLayout="row" fxLayoutAlign="end center" fxLayoutGap="12px">
<button *ngIf="!previewMode"
fxHide.lt-md
<button fxHide.lt-md
[disabled]="!scadaSymbolFormGroup.valid"
mat-button color="primary"
(click)="previewMode = true">
(click)="enterPreviewMode()">
<mat-icon>visibility</mat-icon>
{{ 'widget-config.preview' | translate }}
{{ 'scada.preview' | translate }}
</button>
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="12px">
<button [disabled]="!(scadaSymbolFormGroup.dirty || symbolEditor.dirty)"
<button [disabled]="!(scadaSymbolFormGroup.dirty || symbolEditor?.dirty)"
mat-stroked-button color="primary"
(click)="onRevertScadaSymbolConfig()">
<mat-icon>close</mat-icon>
{{ 'action.decline' | translate }}
</button>
<button [disabled]="!scadaSymbolFormGroup.valid || !(scadaSymbolFormGroup.dirty || symbolEditor.dirty)"
<button [disabled]="!scadaSymbolFormGroup.valid || !(scadaSymbolFormGroup.dirty || symbolEditor?.dirty)"
mat-flat-button color="primary"
(click)="onApplyScadaSymbolConfig()">
<mat-icon>done</mat-icon>
@ -76,7 +74,19 @@
</tb-details-panel>
</mat-drawer>
<mat-drawer-content class="tb-scada-symbol-content">
<tb-scada-symbol-editor #symbolEditor [data]="symbolEditorData"></tb-scada-symbol-editor>
<tb-scada-symbol-editor *ngIf="!previewMode" #symbolEditor [data]="symbolEditorData"></tb-scada-symbol-editor>
<tb-dashboard *ngIf="previewMode"
class="tb-absolute-fill"
[aliasController]="aliasController"
[widgets]="previewWidgets"
[autofillHeight]="true"
[columns]="24"
[margin]="0"
[isEdit]="false"
[isMobileDisabled]="true"
[isEditActionEnabled]="false"
[isRemoveActionEnabled]="false">
</tb-dashboard>
</mat-drawer-content>
</mat-drawer-container>
</div>

150
ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol.component.ts

@ -18,6 +18,7 @@ import {
AfterViewInit,
ChangeDetectorRef,
Component,
EventEmitter,
HostBinding,
OnDestroy,
OnInit,
@ -28,16 +29,35 @@ import { PageComponent } from '@shared/components/page.component';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { ActivatedRoute, Router } from '@angular/router';
import { takeUntil } from 'rxjs/operators';
import { map, switchMap, takeUntil } from 'rxjs/operators';
import { Subject } from 'rxjs';
import { ScadaSymbolData } from '@home/pages/scada-symbol/scada-symbol.models';
import { IotSvgMetadata, parseIotSvgMetadataFromContent } from '@home/components/widget/lib/svg/iot-svg.models';
import {
IotSvgMetadata, IotSvgObjectSettings,
parseIotSvgMetadataFromContent,
updateIotSvgMetadataInContent
} from '@home/components/widget/lib/svg/iot-svg.models';
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { deepClone } from '@core/utils';
import { createFileFromContent, deepClone } from '@core/utils';
import {
ScadaSymbolEditorComponent,
ScadaSymbolEditorData
} from '@home/pages/scada-symbol/scada-symbol-editor.component';
import { ImageService } from '@core/http/image.service';
import { imageResourceType, IMAGES_URL_PREFIX } from '@shared/models/resource.models';
import { HasDirtyFlag } from '@core/guards/confirm-on-exit.guard';
import { IAliasController, IStateController, StateParams } from '@core/api/widget-api.models';
import { EntityAliases } from '@shared/models/alias.models';
import { Filters } from '@shared/models/query/query.models';
import { AliasController } from '@core/api/alias-controller';
import { EntityService } from '@core/http/entity.service';
import { UtilsService } from '@core/services/utils.service';
import { TranslateService } from '@ngx-translate/core';
import { Widget, widgetType } from '@shared/models/widget.models';
import {
iotSvgWidgetDefaultSettings,
IotSvgWidgetSettings
} from '@home/components/widget/lib/svg/iot-svg-widget.models';
@Component({
selector: 'tb-scada-symbol',
@ -45,17 +65,16 @@ import {
styleUrls: ['./scada-symbol.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class ScadaSymbolComponent extends PageComponent implements OnInit, OnDestroy, AfterViewInit {
export class ScadaSymbolComponent extends PageComponent implements OnInit, OnDestroy, AfterViewInit, HasDirtyFlag {
@HostBinding('style.width') width = '100%';
@HostBinding('style.height') height = '100%';
@ViewChild('symbolEditor')
@ViewChild('symbolEditor', {static: false})
symbolEditor: ScadaSymbolEditorComponent;
symbolData: ScadaSymbolData;
symbolEditorData: ScadaSymbolEditorData;
metadata: IotSvgMetadata;
previewMode = false;
@ -65,11 +84,33 @@ export class ScadaSymbolComponent extends PageComponent implements OnInit, OnDes
private origSymbolData: ScadaSymbolData;
updateBreadcrumbs = new EventEmitter();
aliasController: IAliasController;
previewWidgets: Array<Widget> = [];
private previewWidget: Widget;
private forcePristine = false;
get isDirty(): boolean {
return (this.scadaSymbolFormGroup.dirty || this.symbolEditor?.dirty) && !this.forcePristine;
}
set isDirty(value: boolean) {
this.forcePristine = !value;
}
constructor(protected store: Store<AppState>,
private router: Router,
private route: ActivatedRoute,
private fb: UntypedFormBuilder,
private cd: ChangeDetectorRef) {
private cd: ChangeDetectorRef,
private entityService: EntityService,
private utils: UtilsService,
private translate: TranslateService,
private imageService: ImageService) {
super(store);
}
@ -77,6 +118,21 @@ export class ScadaSymbolComponent extends PageComponent implements OnInit, OnDes
this.scadaSymbolFormGroup = this.fb.group({
metadata: [null]
});
const entitiAliases: EntityAliases = {};
// @ts-ignore
const stateController: IStateController = {
getStateParams: (): StateParams => ({})
};
const filters: Filters = {};
this.aliasController = new AliasController(this.utils,
this.entityService,
this.translate,
() => stateController, entitiAliases, filters);
this.route.data.pipe(
takeUntil(this.destroy$)
).subscribe(
@ -98,8 +154,33 @@ export class ScadaSymbolComponent extends PageComponent implements OnInit, OnDes
onApplyScadaSymbolConfig() {
if (this.scadaSymbolFormGroup.valid) {
const svgContent = this.symbolEditor.getContent();
console.log(svgContent);
const svgContent = this.prepareSvgContent();
const file = createFileFromContent(svgContent, this.symbolData.imageResource.fileName,
this.symbolData.imageResource.descriptor.mediaType);
const type = imageResourceType(this.symbolData.imageResource);
let imageInfoObservable =
this.imageService.updateImage(type, this.symbolData.imageResource.resourceKey, file);
const metadata: IotSvgMetadata = this.scadaSymbolFormGroup.get('metadata').value;
if (metadata.title !== this.symbolData.imageResource.title) {
imageInfoObservable = imageInfoObservable.pipe(
switchMap(imageInfo => {
imageInfo.title = metadata.title;
return this.imageService.updateImageInfo(imageInfo);
})
);
}
imageInfoObservable.pipe(
switchMap(imageInfo => this.imageService.getImageString(
`${IMAGES_URL_PREFIX}/${type}/${encodeURIComponent(imageInfo.resourceKey)}`).pipe(
map(content => ({
imageResource: imageInfo,
svgContent: content
}))
))
).subscribe(data => {
this.init(data);
this.updateBreadcrumbs.emit();
});
}
}
@ -107,6 +188,53 @@ export class ScadaSymbolComponent extends PageComponent implements OnInit, OnDes
this.init(this.origSymbolData);
}
enterPreviewMode() {
this.symbolData.svgContent = this.prepareSvgContent();
const iotSvgObject: IotSvgObjectSettings = {};
const settings: IotSvgWidgetSettings = {...iotSvgWidgetDefaultSettings,
...{iotSvg: null, iotSvgContent: this.symbolData.svgContent, iotSvgObject}};
this.previewWidget = {
typeFullFqn: 'system.iot_svg',
type: widgetType.rpc,
sizeX: 24,
sizeY: 24,
row: 0,
col: 0,
config: {
settings,
dropShadow: false,
padding: '0',
margin: '0'
}
};
this.previewWidgets = [this.previewWidget];
this.previewMode = true;
/*setTimeout(() => {
this.updatePreviewWidgetSettings();
}, 2000);*/
}
exitPreviewMode() {
this.symbolEditorData = {
svgContent: this.symbolData.svgContent
};
this.previewMode = false;
}
private updatePreviewWidgetSettings() {
this.previewWidget = deepClone(this.previewWidget);
this.previewWidget.config.title = this.symbolData.imageResource.title;
this.previewWidget.config.showTitle = true;
this.previewWidget.config.padding = '48px';
this.previewWidgets = [this.previewWidget];
}
private prepareSvgContent(): string {
const svgContent = this.symbolEditor.getContent();
const metadata: IotSvgMetadata = this.scadaSymbolFormGroup.get('metadata').value;
return updateIotSvgMetadataInContent(svgContent, metadata);
}
private reset(): void {
this.previewMode = false;
}
@ -117,9 +245,9 @@ export class ScadaSymbolComponent extends PageComponent implements OnInit, OnDes
this.symbolEditorData = {
svgContent: this.symbolData.svgContent
};
this.metadata = parseIotSvgMetadataFromContent(this.symbolData.svgContent);
const metadata = parseIotSvgMetadataFromContent(this.symbolData.svgContent);
this.scadaSymbolFormGroup.patchValue({
metadata: this.metadata
metadata
}, {emitEvent: false});
this.scadaSymbolFormGroup.markAsPristine();
this.cd.markForCheck();

63
ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol.models.ts

@ -18,24 +18,17 @@ import { ImageResourceInfo } from '@shared/models/resource.models';
import * as svgjs from '@svgdotjs/svg.js';
import { Box, Element, Rect, Style, SVG, Svg, Timeline } from '@svgdotjs/svg.js';
import { ResizeObserver } from '@juggle/resize-observer';
import { DynamicComponentFactoryService } from '@core/services/dynamic-component-factory.service';
import { Directive, ElementRef, OnDestroy, Type, ViewContainerRef } from '@angular/core';
import { ViewContainerRef } from '@angular/core';
import { forkJoin, from } from 'rxjs';
import { TbInject } from '@shared/decorators/tb-inject';
import {
setupAddTagPanelTooltip,
setupTagPanelTooltip
} from '@home/pages/scada-symbol/scada-symbol-tooltip.components';
import { iotSvgContentData } from '@home/components/widget/lib/svg/iot-svg.models';
import ITooltipsterInstance = JQueryTooltipster.ITooltipsterInstance;
import TooltipPositioningSide = JQueryTooltipster.TooltipPositioningSide;
import ITooltipsterHelper = JQueryTooltipster.ITooltipsterHelper;
import ITooltipPosition = JQueryTooltipster.ITooltipPosition;
import {
innerSvgContent,
innerSvgContentFromSvgjs,
stripSvgMetadata,
svgRootNodePart
} from '@home/components/widget/lib/svg/iot-svg.models';
export interface ScadaSymbolData {
imageResource: ImageResourceInfo;
@ -69,18 +62,15 @@ export class ScadaSymbolEditObject {
}
this.scale = 1;
this.dirty = false;
this.svgRootNodePart = svgRootNodePart(svgContent);
svgContent = innerSvgContent(svgContent);
svgContent = stripSvgMetadata(svgContent);
console.log(svgContent);
// const doc: XMLDocument = new DOMParser().parseFromString(svgContent, 'image/svg+xml');
this.svgShape = SVG().addTo(this.rootElement).svg(svgContent);
const contentData = iotSvgContentData(svgContent);
this.svgRootNodePart = contentData.svgRootNode;
this.svgShape = SVG().addTo(this.rootElement).svg(contentData.innerSvg);
this.svgShape.node.style.overflow = 'visible';
this.svgShape.node.style['user-select'] = 'none';
this.box = this.svgShape.bbox();
this.svgShape.size(this.box.width, this.box.height);
this.svgShape.viewbox(`0 0 ${this.box.width} ${this.box.height}`);
this.svgShape.style().rule('.tb-element', {cursor: 'pointer', transition: '0.2s filter ease-in-out'});
this.svgShape.style().attr('tb:inner', true).rule('.tb-element', {cursor: 'pointer', transition: '0.2s filter ease-in-out'});
this.updateHoverFilterStyle();
this.performSetup = true;
this.shapeResize$.observe(this.rootElement);
@ -88,17 +78,18 @@ export class ScadaSymbolEditObject {
public getContent(): string {
if (this.svgShape) {
let svgContent = innerSvgContentFromSvgjs(this.svgShape.svg());
console.log(svgContent);
svgContent = `${this.svgRootNodePart}\n${svgContent}\n</svg>`;
const doc: XMLDocument = new DOMParser().parseFromString(svgContent, 'image/svg+xml');
const root = $(doc.documentElement);
root.find('.tb-element').removeClass('tb-element').each((i, e) => {
//
});
root.find('.tooltipstered').removeClass('tooltipstered');
svgContent = doc.documentElement.outerHTML;
return svgContent;
const svgContent = this.svgShape.svg((e: Element) => {
if (e.node.hasAttribute('tb:inner')) {
return false;
} else {
e.node.classList.remove('tb-element', 'tooltipstered');
if (!e.node.classList.length) {
e.node.removeAttribute('class');
}
e.attr('svgjs:data', null);
}
}, false);
return `${this.svgRootNodePart}\n${svgContent}\n</svg>`;
} else {
return null;
}
@ -270,7 +261,7 @@ export class ScadaSymbolEditObject {
const whiteBlur = (2.8 / this.scale).toFixed(2);
const blackBlur = (1.2 / this.scale).toFixed(2);
this.hoverFilterStyle =
this.svgShape.style().rule('.hovered',
this.svgShape.style().attr('tb:inner', true).rule('.hovered',
{
filter:
`drop-shadow(0px 0px ${whiteBlur}px white) drop-shadow(0px 0px ${whiteBlur}px white)
@ -358,6 +349,7 @@ export class ScadaSymbolElement {
.x(this.box.x - groupRectPadding)
.y(this.box.y - groupRectPadding)
.attr({
'tb:inner': true,
fill: 'none',
rx: this.unscaled(6),
stroke: 'rgba(0, 0, 0, 0.38)',
@ -682,18 +674,3 @@ export class ScadaSymbolElement {
}
}
@Directive()
class TbTooltipContent implements OnDestroy {
componentType: Type<any>;
dynamicComponentFactoryService: DynamicComponentFactoryService;
[key: string]: any;
constructor(@TbInject(ElementRef<HTMLElement>) public element: ElementRef<HTMLElement>) {
}
ngOnDestroy(): void {
this.dynamicComponentFactoryService.destroyDynamicComponent(this.componentType);
}
}

Loading…
Cancel
Save