Browse Source

Merge pull request #13110 from ArtemDzhereleiko/AD/bug-fix/scada-bad-xml

Show Error msg for bad xml on save SCADA symbol
pull/13184/head
Igor Kulikov 1 year ago
committed by GitHub
parent
commit
e7c007f444
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 2
      ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol.models.ts
  2. 149
      ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol.component.ts
  3. 4
      ui-ngx/src/app/shared/components/image/upload-image-dialog.component.html
  4. 63
      ui-ngx/src/app/shared/components/image/upload-image-dialog.component.ts

2
ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol.models.ts

@ -271,7 +271,7 @@ export const updateScadaSymbolMetadataInContent = (svgContent: string, metadata:
const svgDoc = new DOMParser().parseFromString(svgContent, 'image/svg+xml'); const svgDoc = new DOMParser().parseFromString(svgContent, 'image/svg+xml');
const parsererror = svgDoc.getElementsByTagName('parsererror'); const parsererror = svgDoc.getElementsByTagName('parsererror');
if (parsererror?.length) { if (parsererror?.length) {
return parsererror[0].outerHTML; throw Error(parsererror[0].textContent)
} }
updateScadaSymbolMetadataInDom(svgDoc, metadata); updateScadaSymbolMetadataInDom(svgDoc, metadata);
return svgDoc.documentElement.outerHTML; return svgDoc.documentElement.outerHTML;

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

@ -79,6 +79,7 @@ import {
SaveWidgetTypeAsDialogResult SaveWidgetTypeAsDialogResult
} from '@home/pages/widget/save-widget-type-as-dialog.component'; } from '@home/pages/widget/save-widget-type-as-dialog.component';
import { WidgetService } from '@core/http/widget.service'; import { WidgetService } from '@core/http/widget.service';
import { ActionNotificationShow } from '@core/notification/notification.actions';
@Component({ @Component({
selector: 'tb-scada-symbol', selector: 'tb-scada-symbol',
@ -213,32 +214,36 @@ export class ScadaSymbolComponent extends PageComponent
this.editObjectCallbacks.tagsUpdated(tags); this.editObjectCallbacks.tagsUpdated(tags);
} }
const metadata: ScadaSymbolMetadata = this.scadaSymbolFormGroup.get('metadata').value; const metadata: ScadaSymbolMetadata = this.scadaSymbolFormGroup.get('metadata').value;
const scadaSymbolContent = this.prepareScadaSymbolContent(metadata); try {
const file = createFileFromContent(scadaSymbolContent, this.symbolData.imageResource.fileName, const scadaSymbolContent = this.prepareScadaSymbolContent(metadata);
this.symbolData.imageResource.descriptor.mediaType); const file = createFileFromContent(scadaSymbolContent, this.symbolData.imageResource.fileName,
const type = imageResourceType(this.symbolData.imageResource); this.symbolData.imageResource.descriptor.mediaType);
let imageInfoObservable = const type = imageResourceType(this.symbolData.imageResource);
this.imageService.updateImage(type, this.symbolData.imageResource.resourceKey, file); let imageInfoObservable =
if (metadata.title !== this.symbolData.imageResource.title) { this.imageService.updateImage(type, this.symbolData.imageResource.resourceKey, file);
imageInfoObservable = imageInfoObservable.pipe( if (metadata.title !== this.symbolData.imageResource.title) {
switchMap(imageInfo => { imageInfoObservable = imageInfoObservable.pipe(
imageInfo.title = metadata.title; switchMap(imageInfo => {
return this.imageService.updateImageInfo(imageInfo); imageInfo.title = metadata.title;
}) return this.imageService.updateImageInfo(imageInfo);
); })
} );
imageInfoObservable.pipe( }
switchMap(imageInfo => this.imageService.getImageString( imageInfoObservable.pipe(
switchMap(imageInfo => this.imageService.getImageString(
`${IMAGES_URL_PREFIX}/${type}/${encodeURIComponent(imageInfo.resourceKey)}`).pipe( `${IMAGES_URL_PREFIX}/${type}/${encodeURIComponent(imageInfo.resourceKey)}`).pipe(
map(content => ({ map(content => ({
imageResource: imageInfo, imageResource: imageInfo,
scadaSymbolContent: content scadaSymbolContent: content
})) }))
)) ))
).subscribe(data => { ).subscribe(data => {
this.init(data); this.init(data);
this.updateBreadcrumbs.emit(); this.updateBreadcrumbs.emit();
}); });
} catch (e) {
this.store.dispatch(new ActionNotificationShow({ message: e.message, type: 'error' }));
}
} }
} }
@ -248,43 +253,47 @@ export class ScadaSymbolComponent extends PageComponent
enterPreviewMode() { enterPreviewMode() {
this.previewMetadata = this.scadaSymbolFormGroup.get('metadata').value; this.previewMetadata = this.scadaSymbolFormGroup.get('metadata').value;
this.symbolData.scadaSymbolContent = this.prepareScadaSymbolContent(this.previewMetadata); try {
this.previewScadaSymbolObjectSettings = { this.symbolData.scadaSymbolContent = this.prepareScadaSymbolContent(this.previewMetadata);
behavior: {}, this.previewScadaSymbolObjectSettings = {
properties: {} behavior: {},
}; properties: {}
this.scadaPreviewFormGroup.patchValue({ };
scadaSymbolObjectSettings: this.previewScadaSymbolObjectSettings this.scadaPreviewFormGroup.patchValue({
}, {emitEvent: false}); scadaSymbolObjectSettings: this.previewScadaSymbolObjectSettings
this.scadaPreviewFormGroup.markAsPristine(); }, {emitEvent: false});
const settings: ScadaSymbolWidgetSettings = {...scadaSymbolWidgetDefaultSettings, this.scadaPreviewFormGroup.markAsPristine();
...{ const settings: ScadaSymbolWidgetSettings = {...scadaSymbolWidgetDefaultSettings,
...{
simulated: true, simulated: true,
scadaSymbolUrl: null, scadaSymbolUrl: null,
scadaSymbolContent: this.symbolData.scadaSymbolContent, scadaSymbolContent: this.symbolData.scadaSymbolContent,
scadaSymbolObjectSettings: this.previewScadaSymbolObjectSettings, scadaSymbolObjectSettings: this.previewScadaSymbolObjectSettings,
padding: '0', padding: '0',
background: colorBackground('rgba(0,0,0,0)') background: colorBackground('rgba(0,0,0,0)')
} }
}; };
this.previewWidget = { this.previewWidget = {
typeFullFqn: 'system.scada_symbol', typeFullFqn: 'system.scada_symbol',
type: widgetType.rpc, type: widgetType.rpc,
sizeX: this.previewMetadata.widgetSizeX || 3, sizeX: this.previewMetadata.widgetSizeX || 3,
sizeY: this.previewMetadata.widgetSizeY || 3, sizeY: this.previewMetadata.widgetSizeY || 3,
row: 0, row: 0,
col: 0, col: 0,
config: { config: {
settings, settings,
showTitle: false, showTitle: false,
dropShadow: false, dropShadow: false,
padding: '0', padding: '0',
margin: '0', margin: '0',
backgroundColor: 'rgba(0,0,0,0)' backgroundColor: 'rgba(0,0,0,0)'
} }
}; };
this.previewWidgets = [this.previewWidget]; this.previewWidgets = [this.previewWidget];
this.previewMode = true; this.previewMode = true;
} catch (e) {
this.store.dispatch(new ActionNotificationShow({ message: e.message, type: 'error' }));
}
} }
exitPreviewMode() { exitPreviewMode() {
@ -374,19 +383,23 @@ export class ScadaSymbolComponent extends PageComponent
metadata = parseScadaSymbolMetadataFromContent(this.origSymbolData.scadaSymbolContent); metadata = parseScadaSymbolMetadataFromContent(this.origSymbolData.scadaSymbolContent);
} }
const linkElement = document.createElement('a'); const linkElement = document.createElement('a');
const scadaSymbolContent = this.prepareScadaSymbolContent(metadata); try {
const blob = new Blob([scadaSymbolContent], { type: this.symbolData.imageResource.descriptor.mediaType }); const scadaSymbolContent = this.prepareScadaSymbolContent(metadata);
const url = URL.createObjectURL(blob); const blob = new Blob([scadaSymbolContent], { type: this.symbolData.imageResource.descriptor.mediaType });
linkElement.setAttribute('href', url); const url = URL.createObjectURL(blob);
linkElement.setAttribute('download', this.symbolData.imageResource.fileName); linkElement.setAttribute('href', url);
const clickEvent = new MouseEvent('click', linkElement.setAttribute('download', this.symbolData.imageResource.fileName);
{ const clickEvent = new MouseEvent('click',
view: window, {
bubbles: true, view: window,
cancelable: false bubbles: true,
} cancelable: false
); }
linkElement.dispatchEvent(clickEvent); );
linkElement.dispatchEvent(clickEvent);
} catch (e) {
this.store.dispatch(new ActionNotificationShow({ message: e.message, type: 'error' }));
}
} }
createWidget() { createWidget() {

4
ui-ngx/src/app/shared/components/image/upload-image-dialog.component.html

@ -28,8 +28,8 @@
<mat-progress-bar color="warn" mode="indeterminate" *ngIf="isLoading$ | async"> <mat-progress-bar color="warn" mode="indeterminate" *ngIf="isLoading$ | async">
</mat-progress-bar> </mat-progress-bar>
<div style="height: 4px;" *ngIf="!(isLoading$ | async)"></div> <div style="height: 4px;" *ngIf="!(isLoading$ | async)"></div>
<div mat-dialog-content> <div mat-dialog-content class="relative">
<fieldset [disabled]="isLoading$ | async"> <fieldset [disabled]="isLoading$ | async" tb-toast toastTarget="uploadRoot" >
<tb-image-input resultAsFile <tb-image-input resultAsFile
processImageApiLink processImageApiLink
label="{{(isScada ? 'scada.symbol-preview' : 'image.image-preview') | translate}}" label="{{(isScada ? 'scada.symbol-preview' : 'image.image-preview') | translate}}"

63
ui-ngx/src/app/shared/components/image/upload-image-dialog.component.ts

@ -41,6 +41,7 @@ import {
updateScadaSymbolMetadataInContent updateScadaSymbolMetadataInContent
} from '@home/components/widget/lib/scada/scada-symbol.models'; } from '@home/components/widget/lib/scada/scada-symbol.models';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { ActionNotificationShow } from '@core/notification/notification.actions';
export interface UploadImageDialogData { export interface UploadImageDialogData {
imageSubType: ResourceSubType; imageSubType: ResourceSubType;
@ -135,38 +136,48 @@ export class UploadImageDialogComponent extends
upload(): void { upload(): void {
this.submitted = true; this.submitted = true;
let file: File = this.uploadImageFormGroup.get('file').value; let file: File = this.uploadImageFormGroup.get('file').value;
if (this.uploadImage) { try {
const title: string = this.uploadImageFormGroup.get('title').value; if (this.uploadImage) {
if (this.isScada) { const title: string = this.uploadImageFormGroup.get('title').value;
if (!this.scadaSymbolMetadata) { if (this.isScada) {
this.scadaSymbolMetadata = emptyMetadata(); if (!this.scadaSymbolMetadata) {
} this.scadaSymbolMetadata = emptyMetadata();
if (this.scadaSymbolMetadata.title !== title) { }
this.scadaSymbolMetadata.title = title; if (this.scadaSymbolMetadata.title !== title) {
this.scadaSymbolMetadata.title = title;
}
const newContent = updateScadaSymbolMetadataInContent(this.scadaSymbolContent, this.scadaSymbolMetadata);
file = updateFileContent(file, newContent);
} }
const newContent = updateScadaSymbolMetadataInContent(this.scadaSymbolContent, this.scadaSymbolMetadata);
file = updateFileContent(file, newContent);
}
forkJoin([
this.imageService.uploadImage(file, title, this.data.imageSubType),
blobToBase64(file)
]).subscribe(([imageInfo, base64]) => {
this.dialogRef.close({image: Object.assign(imageInfo, {base64})});
});
} else {
if (this.isScada) {
blobToText(file).subscribe(scadaSymbolContent => {
this.dialogRef.close({scadaSymbolContent});
});
} else {
const image = this.data.image;
forkJoin([ forkJoin([
this.imageService.updateImage(imageResourceType(image), image.resourceKey, file), this.imageService.uploadImage(file, title, this.data.imageSubType),
blobToBase64(file) blobToBase64(file)
]).subscribe(([imageInfo, base64]) => { ]).subscribe(([imageInfo, base64]) => {
this.dialogRef.close({image:Object.assign(imageInfo, {base64})}); this.dialogRef.close({image: Object.assign(imageInfo, {base64})});
}); });
} else {
if (this.isScada) {
blobToText(file).subscribe(scadaSymbolContent => {
this.dialogRef.close({scadaSymbolContent});
});
} else {
const image = this.data.image;
forkJoin([
this.imageService.updateImage(imageResourceType(image), image.resourceKey, file),
blobToBase64(file)
]).subscribe(([imageInfo, base64]) => {
this.dialogRef.close({image:Object.assign(imageInfo, {base64})});
});
}
} }
} catch (e) {
this.store.dispatch(new ActionNotificationShow({
message: e.message,
type: 'error',
verticalPosition: 'top',
horizontalPosition: 'right',
target: 'uploadRoot'
}));
} }
} }
} }

Loading…
Cancel
Save