From 064778951a76cf718ad8478d17413ccba166db41 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Wed, 12 May 2021 17:04:42 +0300 Subject: [PATCH] UI: Ability to update dashboard image from screenshot --- ui-ngx/package.json | 1 + .../dashboard-image-dialog.component.html | 66 +++++++++ .../dashboard-image-dialog.component.scss | 54 +++++++ .../dashboard-image-dialog.component.ts | 132 ++++++++++++++++++ .../dashboard-page.component.html | 11 +- .../dashboard-page.component.ts | 38 ++++- .../dashboard-settings-dialog.component.html | 3 + .../dashboard-settings-dialog.component.ts | 3 +- .../home/components/home-components.module.ts | 3 + .../src/app/shared/models/dashboard.models.ts | 1 + .../assets/locale/locale.constant-en_US.json | 3 + ui-ngx/yarn.lock | 19 +++ 12 files changed, 330 insertions(+), 4 deletions(-) create mode 100644 ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-image-dialog.component.html create mode 100644 ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-image-dialog.component.scss create mode 100644 ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-image-dialog.component.ts diff --git a/ui-ngx/package.json b/ui-ngx/package.json index 775a685ae8..89b38ead12 100644 --- a/ui-ngx/package.json +++ b/ui-ngx/package.json @@ -47,6 +47,7 @@ "flot": "git://github.com/thingsboard/flot.git#0.9-work", "flot.curvedlines": "git://github.com/MichaelZinsmaier/CurvedLines.git#master", "font-awesome": "^4.7.0", + "html2canvas": "^1.0.0-rc.7", "jquery": "^3.5.1", "jquery.terminal": "^2.18.3", "js-beautify": "^1.13.0", diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-image-dialog.component.html b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-image-dialog.component.html new file mode 100644 index 0000000000..f37e2991f3 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-image-dialog.component.html @@ -0,0 +1,66 @@ + +
+ +

dashboard.update-image

+ + +
+ + +
+
+
+
{{ 'dashboard.no-image' | translate }}
+ +
+ +
+ + +
+
+
+ +
+
+
+ + +
+
diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-image-dialog.component.scss b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-image-dialog.component.scss new file mode 100644 index 0000000000..7960026d56 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-image-dialog.component.scss @@ -0,0 +1,54 @@ +/** + * Copyright © 2016-2021 The Thingsboard Authors + * + * 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. + */ + +$previewSize: 300px !default; + +:host { + .tb-image-preview { + width: auto; + max-width: $previewSize - 2; + height: auto; + max-height: $previewSize - 2; + } + + .tb-image-preview-container { + position: relative; + float: left; + width: $previewSize; + height: $previewSize; + margin-right: 12px; + vertical-align: top; + border: solid 1px; + + div { + width: 100%; + font-size: 18px; + text-align: center; + } + + div, + .tb-image-preview { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + } + } + + .taking-screenshot-progress { + background-color: rgba(255, 255, 255, 0.65); + } +} diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-image-dialog.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-image-dialog.component.ts new file mode 100644 index 0000000000..3586f781d5 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-image-dialog.component.ts @@ -0,0 +1,132 @@ +/// +/// Copyright © 2016-2021 The Thingsboard Authors +/// +/// 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 { Component, Inject } from '@angular/core'; +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { Store } from '@ngrx/store'; +import { AppState } from '@core/core.state'; +import { FormBuilder, FormGroup } from '@angular/forms'; +import { Router } from '@angular/router'; +import { DialogComponent } from '@app/shared/components/dialog.component'; +import { DashboardId } from '@shared/models/id/dashboard-id'; +import { DashboardService } from '@core/http/dashboard.service'; +import { DomSanitizer, SafeUrl } from '@angular/platform-browser'; +import html2canvas from 'html2canvas'; +import { map, share } from 'rxjs/operators'; +import { BehaviorSubject, from } from 'rxjs'; + +export interface DashboardImageDialogData { + dashboardId: DashboardId; + currentImage?: string; + dashboardElement: HTMLElement; +} + +export interface DashboardImageDialogResult { + image?: string; +} + +@Component({ + selector: 'tb-dashboard-image-dialog', + templateUrl: './dashboard-image-dialog.component.html', + styleUrls: ['./dashboard-image-dialog.component.scss'] +}) +export class DashboardImageDialogComponent extends DialogComponent { + + takingScreenshotSubject = new BehaviorSubject(false); + + takingScreenshot$ = this.takingScreenshotSubject.asObservable().pipe( + share() + ); + + dashboardId: DashboardId; + safeImageUrl?: SafeUrl; + dashboardElement: HTMLElement; + + dashboardImageFormGroup: FormGroup; + + constructor(protected store: Store, + protected router: Router, + @Inject(MAT_DIALOG_DATA) public data: DashboardImageDialogData, + public dialogRef: MatDialogRef, + private dashboardService: DashboardService, + private sanitizer: DomSanitizer, + private fb: FormBuilder) { + super(store, router, dialogRef); + + this.dashboardId = this.data.dashboardId; + this.updateImage(this.data.currentImage); + this.dashboardElement = this.data.dashboardElement; + + this.dashboardImageFormGroup = this.fb.group({ + dashboardImage: [this.data.currentImage] + }); + + this.dashboardImageFormGroup.get('dashboardImage').valueChanges.subscribe( + (newImage) => { + this.updateImage(newImage); + } + ); + } + + takeScreenShot() { + this.takingScreenshotSubject.next(true); + from(html2canvas(this.dashboardElement, { + logging: false, + useCORS: true, + foreignObjectRendering: false, + scale: 512 / this.dashboardElement.clientWidth + })).pipe( + map(canvas => canvas.toDataURL())).subscribe( + (image) => { + this.updateImage(image); + this.dashboardImageFormGroup.patchValue({dashboardImage: image}, {emitEvent: false}); + this.dashboardImageFormGroup.markAsDirty(); + this.takingScreenshotSubject.next(false); + }, + (e) => { + this.takingScreenshotSubject.next(false); + } + ); + } + + cancel(): void { + this.dialogRef.close(null); + } + + save(): void { + this.dashboardService.getDashboard(this.dashboardId.id).subscribe( + (dashboard) => { + const newImage: string = this.dashboardImageFormGroup.get('dashboardImage').value; + dashboard.image = newImage; + this.dashboardService.saveDashboard(dashboard).subscribe( + () => { + this.dialogRef.close({ + image: newImage + }); + } + ); + } + ); + } + + private updateImage(imageUrl: string) { + if (imageUrl) { + this.safeImageUrl = this.sanitizer.bypassSecurityTrustUrl(imageUrl); + } else { + this.safeImageUrl = null; + } + } +} diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.html b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.html index 9b50dcfb86..50fbbbec13 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.html +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.html @@ -81,6 +81,12 @@ (click)="isFullscreen = !isFullscreen"> {{ isFullscreen ? 'fullscreen_exit' : 'fullscreen' }} + -