Browse Source

UI: Implement new IoT SVG upload.

pull/11391/head
Igor Kulikov 2 years ago
parent
commit
c8b4d95c2b
  1. 5
      ui-ngx/src/app/core/utils.ts
  2. 32
      ui-ngx/src/app/modules/home/components/widget/lib/svg/iot-svg.models.ts
  3. 8
      ui-ngx/src/app/shared/components/image/image-gallery.component.ts
  4. 37
      ui-ngx/src/app/shared/components/image/upload-image-dialog.component.ts

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

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

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

@ -142,12 +142,12 @@ export interface IotSvgMetadata {
properties: IotSvgProperty[];
}
export const emptyMetadata: IotSvgMetadata = {
export const emptyMetadata = (): IotSvgMetadata => ({
title: '',
tags: [],
behavior: [],
properties: []
};
});
export const parseIotSvgMetadataFromContent = (svgContent: string): IotSvgMetadata => {
@ -155,7 +155,7 @@ export const parseIotSvgMetadataFromContent = (svgContent: string): IotSvgMetada
const svgDoc = new DOMParser().parseFromString(svgContent, 'image/svg+xml');
return parseIotSvgMetadataFromDom(svgDoc);
} catch (_e) {
return emptyMetadata;
return emptyMetadata();
}
};
@ -165,14 +165,36 @@ const parseIotSvgMetadataFromDom = (svgDoc: Document): IotSvgMetadata => {
if (elements.length) {
return JSON.parse(elements[0].textContent);
} else {
return emptyMetadata;
return emptyMetadata();
}
} catch (_e) {
console.error(_e);
return emptyMetadata;
return emptyMetadata();
}
};
export const updateIotSvgMetadataInContent = (svgContent: string, metadata: IotSvgMetadata): string => {
const svgDoc = new DOMParser().parseFromString(svgContent, 'image/svg+xml');
updateIotSvgMetadataInDom(svgDoc, metadata);
return svgDoc.documentElement.outerHTML;
};
const updateIotSvgMetadataInDom = (svgDoc: Document, metadata: IotSvgMetadata) => {
svgDoc.documentElement.setAttribute('xmlns:tb', 'https://thingsboard.io/svg');
let metadataElement: Node;
const elements = svgDoc.getElementsByTagName('tb:metadata');
if (elements?.length) {
metadataElement = elements[0];
metadataElement.textContent = '';
} else {
metadataElement = svgDoc.createElement('tb:metadata');
svgDoc.documentElement.insertBefore(metadataElement, svgDoc.documentElement.firstChild);
}
const content = JSON.stringify(metadata, null, 2);
const cdata = svgDoc.createCDATASection(content);
metadataElement.appendChild(cdata);
};
const defaultGetValueSettings = (get: IotSvgBehaviorValue): GetValueSettings<any> => ({
action: GetValueAction.DO_NOTHING,
defaultValue: get.defaultValue,

8
ui-ngx/src/app/shared/components/image/image-gallery.component.ts

@ -661,7 +661,13 @@ export class ImageGalleryComponent extends PageComponent implements OnInit, OnDe
if (this.selectionMode) {
this.imageSelected.next(result);
} else {
this.updateData();
if (this.isScada) {
const type = imageResourceType(result);
const key = encodeURIComponent(result.resourceKey);
this.router.navigateByUrl(`resources/scada-symbols/${type}/${key}`);
} else {
this.updateData();
}
}
}
});

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

@ -33,7 +33,13 @@ import { ImageService } from '@core/http/image.service';
import { ImageResource, ImageResourceInfo, imageResourceType, ResourceSubType } from '@shared/models/resource.models';
import { getCurrentAuthState } from '@core/auth/auth.selectors';
import { forkJoin } from 'rxjs';
import { blobToBase64 } from '@core/utils';
import { blobToBase64, blobToText, updateFileContent } from '@core/utils';
import {
emptyMetadata,
IotSvgMetadata,
parseIotSvgMetadataFromContent,
updateIotSvgMetadataInContent
} from '@home/components/widget/lib/svg/iot-svg.models';
export interface UploadImageDialogData {
imageSubType: ResourceSubType;
@ -61,6 +67,9 @@ export class UploadImageDialogComponent extends
return this.data.imageSubType === ResourceSubType.IOT_SVG;
}
private iotSvgContent: string;
private iotSvgMetadata: IotSvgMetadata;
constructor(protected store: Store<AppState>,
protected router: Router,
private imageService: ImageService,
@ -78,6 +87,20 @@ export class UploadImageDialogComponent extends
});
if (this.uploadImage) {
this.uploadImageFormGroup.addControl('title', this.fb.control(null, [Validators.required]));
if (this.isScada) {
this.uploadImageFormGroup.get('file').valueChanges.subscribe((file: File) => {
if (file) {
blobToText(file).subscribe(content => {
this.iotSvgContent = content;
this.iotSvgMetadata = parseIotSvgMetadataFromContent(this.iotSvgContent);
const titleControl = this.uploadImageFormGroup.get('title');
if (this.iotSvgMetadata.title && (!titleControl.value || !titleControl.touched)) {
titleControl.setValue(this.iotSvgMetadata.title);
}
});
}
});
}
}
}
@ -102,9 +125,19 @@ export class UploadImageDialogComponent extends
upload(): void {
this.submitted = true;
const file: File = this.uploadImageFormGroup.get('file').value;
let file: File = this.uploadImageFormGroup.get('file').value;
if (this.uploadImage) {
const title: string = this.uploadImageFormGroup.get('title').value;
if (this.isScada) {
if (!this.iotSvgMetadata) {
this.iotSvgMetadata = emptyMetadata();
}
if (this.iotSvgMetadata.title !== title) {
this.iotSvgMetadata.title = title;
}
const newContent = updateIotSvgMetadataInContent(this.iotSvgContent, this.iotSvgMetadata);
file = updateFileContent(file, newContent);
}
forkJoin([
this.imageService.uploadImage(file, title, this.data.imageSubType),
blobToBase64(file)

Loading…
Cancel
Save