UI: Initial implementation of entity versions diff component
This commit is contained in:
parent
c46b5b6448
commit
e86b37b4af
@ -79,7 +79,8 @@
|
|||||||
"node_modules/leaflet.markercluster/dist/MarkerCluster.Default.css",
|
"node_modules/leaflet.markercluster/dist/MarkerCluster.Default.css",
|
||||||
"node_modules/@geoman-io/leaflet-geoman-free/dist/leaflet-geoman.css",
|
"node_modules/@geoman-io/leaflet-geoman-free/dist/leaflet-geoman.css",
|
||||||
"node_modules/prismjs/themes/prism.css",
|
"node_modules/prismjs/themes/prism.css",
|
||||||
"node_modules/prismjs/plugins/line-numbers/prism-line-numbers.css"
|
"node_modules/prismjs/plugins/line-numbers/prism-line-numbers.css",
|
||||||
|
"node_modules/ace-diff/dist/ace-diff.min.css"
|
||||||
],
|
],
|
||||||
"stylePreprocessorOptions": {
|
"stylePreprocessorOptions": {
|
||||||
"includePaths": [
|
"includePaths": [
|
||||||
@ -130,7 +131,8 @@
|
|||||||
"jstree",
|
"jstree",
|
||||||
"qrcode",
|
"qrcode",
|
||||||
"wcwidth",
|
"wcwidth",
|
||||||
"leaflet-polylinedecorator"
|
"leaflet-polylinedecorator",
|
||||||
|
"ace-diff"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"configurations": {
|
"configurations": {
|
||||||
|
|||||||
@ -41,6 +41,7 @@
|
|||||||
"@ngx-translate/core": "^13.0.0",
|
"@ngx-translate/core": "^13.0.0",
|
||||||
"@ngx-translate/http-loader": "^6.0.0",
|
"@ngx-translate/http-loader": "^6.0.0",
|
||||||
"ace-builds": "^1.4.13",
|
"ace-builds": "^1.4.13",
|
||||||
|
"ace-diff": "^3.0.3",
|
||||||
"angular-gridster2": "~12.1.1",
|
"angular-gridster2": "~12.1.1",
|
||||||
"angular2-hotkeys": "^2.4.0",
|
"angular2-hotkeys": "^2.4.0",
|
||||||
"canvas-gauges": "^2.1.7",
|
"canvas-gauges": "^2.1.7",
|
||||||
@ -105,6 +106,7 @@
|
|||||||
"@angular/compiler-cli": "^12.2.13",
|
"@angular/compiler-cli": "^12.2.13",
|
||||||
"@angular/language-service": "^12.2.13",
|
"@angular/language-service": "^12.2.13",
|
||||||
"@ngtools/webpack": "~12.2.13",
|
"@ngtools/webpack": "~12.2.13",
|
||||||
|
"@types/ace-diff": "^2.1.1",
|
||||||
"@types/canvas-gauges": "^2.1.4",
|
"@types/canvas-gauges": "^2.1.4",
|
||||||
"@types/flot": "^0.0.32",
|
"@types/flot": "^0.0.32",
|
||||||
"@types/jasmine": "~3.10.2",
|
"@types/jasmine": "~3.10.2",
|
||||||
|
|||||||
@ -158,6 +158,7 @@ import { VersionControlComponent } from '@home/components/vc/version-control.com
|
|||||||
import { EntityVersionsTableComponent } from '@home/components/vc/entity-versions-table.component';
|
import { EntityVersionsTableComponent } from '@home/components/vc/entity-versions-table.component';
|
||||||
import { EntityVersionExportComponent } from '@home/components/vc/entity-version-export.component';
|
import { EntityVersionExportComponent } from '@home/components/vc/entity-version-export.component';
|
||||||
import { EntityVersionRestoreComponent } from '@home/components/vc/entity-version-restore.component';
|
import { EntityVersionRestoreComponent } from '@home/components/vc/entity-version-restore.component';
|
||||||
|
import { EntityVersionDiffComponent } from '@home/components/vc/entity-version-diff.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations:
|
declarations:
|
||||||
@ -286,7 +287,8 @@ import { EntityVersionRestoreComponent } from '@home/components/vc/entity-versio
|
|||||||
VersionControlComponent,
|
VersionControlComponent,
|
||||||
EntityVersionsTableComponent,
|
EntityVersionsTableComponent,
|
||||||
EntityVersionExportComponent,
|
EntityVersionExportComponent,
|
||||||
EntityVersionRestoreComponent
|
EntityVersionRestoreComponent,
|
||||||
|
EntityVersionDiffComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
@ -409,7 +411,8 @@ import { EntityVersionRestoreComponent } from '@home/components/vc/entity-versio
|
|||||||
VersionControlComponent,
|
VersionControlComponent,
|
||||||
EntityVersionsTableComponent,
|
EntityVersionsTableComponent,
|
||||||
EntityVersionExportComponent,
|
EntityVersionExportComponent,
|
||||||
EntityVersionRestoreComponent
|
EntityVersionRestoreComponent,
|
||||||
|
EntityVersionDiffComponent
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
WidgetComponentService,
|
WidgetComponentService,
|
||||||
|
|||||||
@ -0,0 +1,35 @@
|
|||||||
|
<!--
|
||||||
|
|
||||||
|
Copyright © 2016-2022 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.
|
||||||
|
|
||||||
|
-->
|
||||||
|
<section style="min-width: 400px; width: 800px; position: relative;">
|
||||||
|
<mat-toolbar>
|
||||||
|
<h2>{{ 'version-control.diff-entity-with-version' | translate: {versionName} }}</h2>
|
||||||
|
<span fxFlex></span>
|
||||||
|
</mat-toolbar>
|
||||||
|
<mat-progress-bar color="warn" style="z-index: 10; width: 100%; margin-bottom: -4px;" mode="indeterminate"
|
||||||
|
*ngIf="isLoading$ | async">
|
||||||
|
</mat-progress-bar>
|
||||||
|
<div class="diff-viewer" #diffViewer style="height: 350px;"></div>
|
||||||
|
<div fxLayoutAlign="end center" fxLayoutGap="8px">
|
||||||
|
<button mat-button color="primary"
|
||||||
|
type="button"
|
||||||
|
[disabled]="(isLoading$ | async)"
|
||||||
|
(click)="close()" cdkFocusInitial>
|
||||||
|
{{ 'action.close' | translate }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
/**
|
||||||
|
* Copyright © 2016-2022 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.
|
||||||
|
*/
|
||||||
|
:host {
|
||||||
|
.diff-viewer {
|
||||||
|
position: relative;
|
||||||
|
border: 1px solid #c0c0c0;
|
||||||
|
margin-top: 16px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,92 @@
|
|||||||
|
///
|
||||||
|
/// Copyright © 2016-2022 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, ElementRef, Input, OnDestroy, OnInit, ViewChild } from '@angular/core';
|
||||||
|
import { PageComponent } from '@shared/components/page.component';
|
||||||
|
import { FormBuilder } from '@angular/forms';
|
||||||
|
import { Store } from '@ngrx/store';
|
||||||
|
import { AppState } from '@core/core.state';
|
||||||
|
import { EntitiesVersionControlService } from '@core/http/entities-version-control.service';
|
||||||
|
import { EntityId } from '@shared/models/id/entity-id';
|
||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
import { getAceDiff } from '@shared/models/ace/ace.models';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'tb-entity-version-diff',
|
||||||
|
templateUrl: './entity-version-diff.component.html',
|
||||||
|
styleUrls: ['./entity-version-diff.component.scss']
|
||||||
|
})
|
||||||
|
export class EntityVersionDiffComponent extends PageComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
|
@ViewChild('diffViewer', {static: true})
|
||||||
|
diffViewerElmRef: ElementRef<HTMLElement>;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
branch: string;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
versionName: string;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
versionId: string;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
externalEntityId: EntityId;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
onClose: () => void;
|
||||||
|
|
||||||
|
differ: AceDiff;
|
||||||
|
|
||||||
|
constructor(protected store: Store<AppState>,
|
||||||
|
private entitiesVersionControlService: EntitiesVersionControlService,
|
||||||
|
private translate: TranslateService,
|
||||||
|
private fb: FormBuilder) {
|
||||||
|
super(store);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
getAceDiff().subscribe((aceDiff) => {
|
||||||
|
this.differ = new aceDiff.default(
|
||||||
|
{
|
||||||
|
element: this.diffViewerElmRef.nativeElement,
|
||||||
|
left: {
|
||||||
|
copyLinkEnabled: false,
|
||||||
|
editable: false,
|
||||||
|
content: 'Left content!'
|
||||||
|
},
|
||||||
|
right: {
|
||||||
|
copyLinkEnabled: false,
|
||||||
|
editable: false,
|
||||||
|
content: 'Right content!'
|
||||||
|
}
|
||||||
|
} as AceDiff.AceDiffConstructorOpts
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
if (this.differ) {
|
||||||
|
this.differ.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
close(): void {
|
||||||
|
if (this.onClose) {
|
||||||
|
this.onClose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -100,10 +100,17 @@
|
|||||||
</mat-cell>
|
</mat-cell>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container matColumnDef="actions" stickyEnd>
|
<ng-container matColumnDef="actions" stickyEnd>
|
||||||
<mat-header-cell *matHeaderCellDef style="min-width: 40px; max-width: 40px; width: 40px">
|
<mat-header-cell *matHeaderCellDef style="min-width: 80px; max-width: 80px; width: 80px">
|
||||||
</mat-header-cell>
|
</mat-header-cell>
|
||||||
<mat-cell *matCellDef="let entityVersion">
|
<mat-cell *matCellDef="let entityVersion">
|
||||||
<div fxFlex fxLayout="row" fxLayoutAlign="end">
|
<div fxFlex fxLayout="row" fxLayoutAlign="end">
|
||||||
|
<button *ngIf="singleEntityMode" mat-icon-button [disabled]="isLoading$ | async"
|
||||||
|
matTooltip="{{ 'version-control.show-version-diff' | translate }}"
|
||||||
|
matTooltipPosition="above"
|
||||||
|
#diffVersionButton
|
||||||
|
(click)="toggleShowVersionDiff($event, diffVersionButton, entityVersion)">
|
||||||
|
<mat-icon>difference</mat-icon>
|
||||||
|
</button>
|
||||||
<button *ngIf="singleEntityMode" mat-icon-button [disabled]="isLoading$ | async"
|
<button *ngIf="singleEntityMode" mat-icon-button [disabled]="isLoading$ | async"
|
||||||
matTooltip="{{ 'version-control.restore-version' | translate }}"
|
matTooltip="{{ 'version-control.restore-version' | translate }}"
|
||||||
matTooltipPosition="above"
|
matTooltipPosition="above"
|
||||||
|
|||||||
@ -47,6 +47,7 @@ import { EntityVersionExportComponent } from '@home/components/vc/entity-version
|
|||||||
import { MatButton } from '@angular/material/button';
|
import { MatButton } from '@angular/material/button';
|
||||||
import { TbPopoverComponent } from '@shared/components/popover.component';
|
import { TbPopoverComponent } from '@shared/components/popover.component';
|
||||||
import { EntityVersionRestoreComponent } from '@home/components/vc/entity-version-restore.component';
|
import { EntityVersionRestoreComponent } from '@home/components/vc/entity-version-restore.component';
|
||||||
|
import { EntityVersionDiffComponent } from '@home/components/vc/entity-version-diff.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'tb-entity-versions-table',
|
selector: 'tb-entity-versions-table',
|
||||||
@ -209,6 +210,28 @@ export class EntityVersionsTableComponent extends PageComponent implements OnIni
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toggleShowVersionDiff($event: Event, diffVersionButton: MatButton, entityVersion: EntityVersion) {
|
||||||
|
if ($event) {
|
||||||
|
$event.stopPropagation();
|
||||||
|
}
|
||||||
|
const trigger = diffVersionButton._elementRef.nativeElement;
|
||||||
|
if (this.popoverService.hasPopover(trigger)) {
|
||||||
|
this.popoverService.hidePopover(trigger);
|
||||||
|
} else {
|
||||||
|
const diffVersionPopover = this.popoverService.displayPopover(trigger, this.renderer,
|
||||||
|
this.viewContainerRef, EntityVersionDiffComponent, 'left', true, null,
|
||||||
|
{
|
||||||
|
branch: this.branch,
|
||||||
|
versionName: entityVersion.name,
|
||||||
|
versionId: entityVersion.id,
|
||||||
|
externalEntityId: this.externalEntityIdValue,
|
||||||
|
onClose: () => {
|
||||||
|
diffVersionPopover.hide();
|
||||||
|
}
|
||||||
|
}, {}, {}, {}, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
toggleRestoreEntityVersion($event: Event, restoreVersionButton: MatButton, entityVersion: EntityVersion) {
|
toggleRestoreEntityVersion($event: Event, restoreVersionButton: MatButton, entityVersion: EntityVersion) {
|
||||||
if ($event) {
|
if ($event) {
|
||||||
$event.stopPropagation();
|
$event.stopPropagation();
|
||||||
|
|||||||
@ -21,6 +21,7 @@ import { map, mergeMap, tap } from 'rxjs/operators';
|
|||||||
|
|
||||||
let aceDependenciesLoaded = false;
|
let aceDependenciesLoaded = false;
|
||||||
let aceModule: any;
|
let aceModule: any;
|
||||||
|
let aceDiffModule: any;
|
||||||
|
|
||||||
function loadAceDependencies(): Observable<any> {
|
function loadAceDependencies(): Observable<any> {
|
||||||
if (aceDependenciesLoaded) {
|
if (aceDependenciesLoaded) {
|
||||||
@ -74,6 +75,21 @@ export function getAce(): Observable<any> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getAceDiff(): Observable<any> {
|
||||||
|
if (aceDiffModule) {
|
||||||
|
return of(aceDiffModule);
|
||||||
|
} else {
|
||||||
|
return getAce().pipe(
|
||||||
|
mergeMap((ace) => {
|
||||||
|
return from(import('ace-diff'));
|
||||||
|
}),
|
||||||
|
tap((module) => {
|
||||||
|
aceDiffModule = module;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class Range implements Ace.Range {
|
export class Range implements Ace.Range {
|
||||||
|
|
||||||
public start: Ace.Point;
|
public start: Ace.Point;
|
||||||
|
|||||||
@ -3131,7 +3131,9 @@
|
|||||||
"nothing-to-commit": "No changes to commit",
|
"nothing-to-commit": "No changes to commit",
|
||||||
"restore-version": "Restore version",
|
"restore-version": "Restore version",
|
||||||
"restore-entity-from-version": "Restore entity from version '{{versionName}}'",
|
"restore-entity-from-version": "Restore entity from version '{{versionName}}'",
|
||||||
"load-entity-relations": "Load entity relations"
|
"load-entity-relations": "Load entity relations",
|
||||||
|
"show-version-diff": "Show version diff",
|
||||||
|
"diff-entity-with-version": "Diff with entity version '{{versionName}}'"
|
||||||
},
|
},
|
||||||
"widget": {
|
"widget": {
|
||||||
"widget-library": "Widgets Library",
|
"widget-library": "Widgets Library",
|
||||||
|
|||||||
@ -1751,6 +1751,11 @@
|
|||||||
"@turf/helpers" "^6.5.0"
|
"@turf/helpers" "^6.5.0"
|
||||||
"@turf/meta" "^6.5.0"
|
"@turf/meta" "^6.5.0"
|
||||||
|
|
||||||
|
"@types/ace-diff@^2.1.1":
|
||||||
|
version "2.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/ace-diff/-/ace-diff-2.1.1.tgz#1c08919aae8f9c429fcb139dc564c89dd093cbee"
|
||||||
|
integrity sha512-O27fCo2Y0njNslOFSewyRhTyXfLhVhleEU5aTI6ZqFTKENJ8L/LA+Y+ZfcHsHTtwrTWjBXqORmqEHH6Qytqw1w==
|
||||||
|
|
||||||
"@types/canvas-gauges@^2.1.4":
|
"@types/canvas-gauges@^2.1.4":
|
||||||
version "2.1.4"
|
version "2.1.4"
|
||||||
resolved "https://registry.yarnpkg.com/@types/canvas-gauges/-/canvas-gauges-2.1.4.tgz#063881264597d098e78cf5ad921e8ed20ae2ad16"
|
resolved "https://registry.yarnpkg.com/@types/canvas-gauges/-/canvas-gauges-2.1.4.tgz#063881264597d098e78cf5ad921e8ed20ae2ad16"
|
||||||
@ -2190,6 +2195,13 @@ ace-builds@^1.4.13:
|
|||||||
resolved "https://registry.yarnpkg.com/ace-builds/-/ace-builds-1.4.13.tgz#186f42d3849ebcc6a48b93088a058489897514c1"
|
resolved "https://registry.yarnpkg.com/ace-builds/-/ace-builds-1.4.13.tgz#186f42d3849ebcc6a48b93088a058489897514c1"
|
||||||
integrity sha512-SOLzdaQkY6ecPKYRDDg+MY1WoGgXA34cIvYJNNoBMGGUswHmlauU2Hy0UL96vW0Fs/LgFbMUjD+6vqzWTldIYQ==
|
integrity sha512-SOLzdaQkY6ecPKYRDDg+MY1WoGgXA34cIvYJNNoBMGGUswHmlauU2Hy0UL96vW0Fs/LgFbMUjD+6vqzWTldIYQ==
|
||||||
|
|
||||||
|
ace-diff@^3.0.3:
|
||||||
|
version "3.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/ace-diff/-/ace-diff-3.0.3.tgz#84f685ff3d0b1910539fc39259ac73d8b6581e28"
|
||||||
|
integrity sha512-CJaV9Oi6BWLWGL2Kj//h5BNXlRCRu1GYHPOT7o+ZSAuJv9PaL9FWr/cCf16IuSVDo7oj6VriO+qgoHR8G9McLA==
|
||||||
|
dependencies:
|
||||||
|
diff-match-patch "^1.0.5"
|
||||||
|
|
||||||
acorn-import-assertions@^1.7.6:
|
acorn-import-assertions@^1.7.6:
|
||||||
version "1.8.0"
|
version "1.8.0"
|
||||||
resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9"
|
resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user