Browse Source

UI: Entity versions table improvement. Create entity version popover.

pull/6615/head
Igor Kulikov 4 years ago
parent
commit
9d17ff1285
  1. 10
      ui-ngx/src/app/modules/home/components/home-components.module.ts
  2. 6
      ui-ngx/src/app/modules/home/components/profile/device-profile.component.html
  3. 60
      ui-ngx/src/app/modules/home/components/vc/entity-version-export.component.html
  4. 84
      ui-ngx/src/app/modules/home/components/vc/entity-version-export.component.ts
  5. 8
      ui-ngx/src/app/modules/home/components/vc/entity-versions-table.component.html
  6. 2
      ui-ngx/src/app/modules/home/components/vc/entity-versions-table.component.scss
  7. 46
      ui-ngx/src/app/modules/home/components/vc/entity-versions-table.component.ts
  8. 77
      ui-ngx/src/app/modules/home/components/vc/vc-entity-export-dialog.component.html
  9. 105
      ui-ngx/src/app/modules/home/components/vc/vc-entity-export-dialog.component.ts
  10. 1
      ui-ngx/src/app/modules/home/components/vc/version-control.component.html
  11. 3
      ui-ngx/src/app/modules/home/components/vc/version-control.component.ts
  12. 16
      ui-ngx/src/app/modules/home/dialogs/home-dialogs.service.ts
  13. 5
      ui-ngx/src/app/modules/home/pages/asset/asset-tabs.component.html
  14. 6
      ui-ngx/src/app/modules/home/pages/asset/asset.component.html
  15. 10
      ui-ngx/src/app/modules/home/pages/asset/assets-table-config.resolver.ts
  16. 5
      ui-ngx/src/app/modules/home/pages/customer/customer-tabs.component.html
  17. 6
      ui-ngx/src/app/modules/home/pages/customer/customer.component.html
  18. 10
      ui-ngx/src/app/modules/home/pages/customer/customers-table-config.resolver.ts
  19. 6
      ui-ngx/src/app/modules/home/pages/dashboard/dashboard-form.component.html
  20. 5
      ui-ngx/src/app/modules/home/pages/dashboard/dashboard-tabs.component.html
  21. 10
      ui-ngx/src/app/modules/home/pages/dashboard/dashboards-table-config.resolver.ts
  22. 5
      ui-ngx/src/app/modules/home/pages/device-profile/device-profile-tabs.component.html
  23. 10
      ui-ngx/src/app/modules/home/pages/device-profile/device-profiles-table-config.resolver.ts
  24. 2
      ui-ngx/src/app/modules/home/pages/device/device-tabs.component.html
  25. 6
      ui-ngx/src/app/modules/home/pages/device/device.component.html
  26. 10
      ui-ngx/src/app/modules/home/pages/device/devices-table-config.resolver.ts
  27. 5
      ui-ngx/src/app/modules/home/pages/rulechain/rulechain-tabs.component.html
  28. 6
      ui-ngx/src/app/modules/home/pages/rulechain/rulechain.component.html
  29. 10
      ui-ngx/src/app/modules/home/pages/rulechain/rulechains-table-config.resolver.ts
  30. 3
      ui-ngx/src/app/shared/components/popover.component.ts
  31. 4
      ui-ngx/src/app/shared/components/popover.service.ts
  32. 5
      ui-ngx/src/app/shared/components/vc/branch-autocomplete.component.html
  33. 30
      ui-ngx/src/app/shared/components/vc/branch-autocomplete.component.scss
  34. 57
      ui-ngx/src/app/shared/components/vc/branch-autocomplete.component.ts
  35. 9
      ui-ngx/src/assets/locale/locale.constant-en_US.json

10
ui-ngx/src/app/modules/home/components/home-components.module.ts

@ -153,10 +153,10 @@ import { TenantProfileQueuesComponent } from '@home/components/profile/queue/ten
import { QueueFormComponent } from '@home/components/queue/queue-form.component'; import { QueueFormComponent } from '@home/components/queue/queue-form.component';
import { WidgetSettingsModule } from '@home/components/widget/lib/settings/widget-settings.module'; import { WidgetSettingsModule } from '@home/components/widget/lib/settings/widget-settings.module';
import { WidgetSettingsComponent } from '@home/components/widget/widget-settings.component'; import { WidgetSettingsComponent } from '@home/components/widget/widget-settings.component';
import { VcEntityExportDialogComponent } from '@home/components/vc/vc-entity-export-dialog.component';
import { VersionControlSettingsComponent } from '@home/components/vc/version-control-settings.component'; import { VersionControlSettingsComponent } from '@home/components/vc/version-control-settings.component';
import { VersionControlComponent } from '@home/components/vc/version-control.component'; import { VersionControlComponent } from '@home/components/vc/version-control.component';
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';
@NgModule({ @NgModule({
declarations: declarations:
@ -281,10 +281,10 @@ import { EntityVersionsTableComponent } from '@home/components/vc/entity-version
DisplayWidgetTypesPanelComponent, DisplayWidgetTypesPanelComponent,
TenantProfileQueuesComponent, TenantProfileQueuesComponent,
QueueFormComponent, QueueFormComponent,
VcEntityExportDialogComponent,
VersionControlSettingsComponent, VersionControlSettingsComponent,
VersionControlComponent, VersionControlComponent,
EntityVersionsTableComponent EntityVersionsTableComponent,
EntityVersionExportComponent
], ],
imports: [ imports: [
CommonModule, CommonModule,
@ -403,10 +403,10 @@ import { EntityVersionsTableComponent } from '@home/components/vc/entity-version
DisplayWidgetTypesPanelComponent, DisplayWidgetTypesPanelComponent,
TenantProfileQueuesComponent, TenantProfileQueuesComponent,
QueueFormComponent, QueueFormComponent,
VcEntityExportDialogComponent,
VersionControlSettingsComponent, VersionControlSettingsComponent,
VersionControlComponent, VersionControlComponent,
EntityVersionsTableComponent EntityVersionsTableComponent,
EntityVersionExportComponent
], ],
providers: [ providers: [
WidgetComponentService, WidgetComponentService,

6
ui-ngx/src/app/modules/home/components/profile/device-profile.component.html

@ -34,12 +34,6 @@
[fxShow]="!isEdit && !entity?.default"> [fxShow]="!isEdit && !entity?.default">
{{'device-profile.set-default' | translate }} {{'device-profile.set-default' | translate }}
</button> </button>
<button mat-raised-button color="primary"
[disabled]="(isLoading$ | async)"
(click)="onEntityAction($event, 'vcExport')"
[fxShow]="!isEdit">
{{'version-control.export-to-git' | translate }}
</button>
<button mat-raised-button color="primary" <button mat-raised-button color="primary"
[disabled]="(isLoading$ | async)" [disabled]="(isLoading$ | async)"
(click)="onEntityAction($event, 'delete')" (click)="onEntityAction($event, 'delete')"

60
ui-ngx/src/app/modules/home/components/vc/entity-version-export.component.html

@ -0,0 +1,60 @@
<!--
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;">
<mat-toolbar>
<h2>{{ 'version-control.create-entity-version' | translate }}</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>
<form [formGroup]="exportFormGroup" style="padding-top: 16px;">
<fieldset [disabled]="isLoading$ | async">
<div fxFlex fxLayout="column">
<tb-branch-autocomplete
required
formControlName="branch">
</tb-branch-autocomplete>
<mat-form-field class="mat-block" fxFlex>
<mat-label translate>version-control.version-name</mat-label>
<input required matInput formControlName="versionName">
<mat-error *ngIf="exportFormGroup.get('versionName').hasError('required')">
{{ 'version-control.version-name-required' | translate }}
</mat-error>
</mat-form-field>
<mat-checkbox formControlName="saveRelations" style="margin-bottom: 16px;">
{{ 'version-control.export-entity-relations' | translate }}
</mat-checkbox>
</div>
</fieldset>
</form>
<div fxLayoutAlign="end center" fxLayoutGap="8px">
<button mat-button color="primary"
type="button"
[disabled]="(isLoading$ | async)"
(click)="cancel()" cdkFocusInitial>
{{ 'action.cancel' | translate }}
</button>
<button mat-raised-button color="primary"
type="button"
(click)="export()"
[disabled]="(isLoading$ | async) || exportFormGroup.invalid || !exportFormGroup.dirty">
{{ 'action.create' | translate }}
</button>
</div>
</section>

84
ui-ngx/src/app/modules/home/components/vc/entity-version-export.component.ts

@ -0,0 +1,84 @@
///
/// 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, Input, OnInit } from '@angular/core';
import { PageComponent } from '@shared/components/page.component';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import {
SingleEntityVersionCreateRequest,
VersionCreateRequestType,
VersionCreationResult
} from '@shared/models/vc.models';
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';
@Component({
selector: 'tb-entity-version-export',
templateUrl: './entity-version-export.component.html',
styleUrls: []
})
export class EntityVersionExportComponent extends PageComponent implements OnInit {
@Input()
branch: string;
@Input()
entityId: EntityId;
@Input()
onClose: (result: VersionCreationResult | null, branch: string | null) => void;
exportFormGroup: FormGroup;
constructor(protected store: Store<AppState>,
private entitiesVersionControlService: EntitiesVersionControlService,
private fb: FormBuilder) {
super(store);
}
ngOnInit(): void {
this.exportFormGroup = this.fb.group({
branch: [this.branch, [Validators.required]],
versionName: [null, [Validators.required]],
saveRelations: [false, []]
});
}
cancel(): void {
if (this.onClose) {
this.onClose(null, null);
}
}
export(): void {
const request: SingleEntityVersionCreateRequest = {
entityId: this.entityId,
branch: this.exportFormGroup.get('branch').value,
versionName: this.exportFormGroup.get('versionName').value,
config: {
saveRelations: this.exportFormGroup.get('saveRelations').value
},
type: VersionCreateRequestType.SINGLE_ENTITY
};
this.entitiesVersionControlService.saveEntitiesVersion(request).subscribe((result) => {
if (this.onClose) {
this.onClose(result, request.branch);
}
});
}
}

8
ui-ngx/src/app/modules/home/components/vc/entity-versions-table.component.html

@ -31,10 +31,12 @@
</tb-branch-autocomplete> </tb-branch-autocomplete>
</div> </div>
<span fxFlex></span> <span fxFlex></span>
<button *ngIf="singleEntityMode" mat-raised-button color="primary" <button *ngIf="singleEntityMode" mat-stroked-button color="primary"
#exportButton
[disabled]="(isLoading$ | async)" [disabled]="(isLoading$ | async)"
(click)="vcExport($event)"> (click)="toggleVcExport($event, exportButton)">
{{'version-control.export-to-git' | translate }} <mat-icon>update</mat-icon>
{{'version-control.create-version' | translate }}
</button> </button>
</div> </div>
</mat-toolbar> </mat-toolbar>

2
ui-ngx/src/app/modules/home/components/vc/entity-versions-table.component.scss

@ -78,7 +78,7 @@
tb-branch-autocomplete { tb-branch-autocomplete {
mat-form-field { mat-form-field {
font-size: 16px; font-size: 16px;
width: 200px; width: 250px;
.mat-form-field-wrapper { .mat-form-field-wrapper {
padding-bottom: 0; padding-bottom: 0;

46
ui-ngx/src/app/modules/home/components/vc/entity-versions-table.component.ts

@ -21,8 +21,8 @@ import {
ElementRef, ElementRef,
Input, Input,
OnDestroy, OnDestroy,
OnInit, OnInit, Renderer2,
ViewChild ViewChild, ViewContainerRef
} from '@angular/core'; } from '@angular/core';
import { PageComponent } from '@shared/components/page.component'; import { PageComponent } from '@shared/components/page.component';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
@ -33,7 +33,7 @@ import { BehaviorSubject, merge, Observable, of, ReplaySubject } from 'rxjs';
import { emptyPageData, PageData } from '@shared/models/page/page-data'; import { emptyPageData, PageData } from '@shared/models/page/page-data';
import { PageLink } from '@shared/models/page/page-link'; import { PageLink } from '@shared/models/page/page-link';
import { catchError, map, tap } from 'rxjs/operators'; import { catchError, map, tap } from 'rxjs/operators';
import { EntityVersion } from '@shared/models/vc.models'; import { EntityVersion, VersionCreationResult } from '@shared/models/vc.models';
import { EntitiesVersionControlService } from '@core/http/entities-version-control.service'; import { EntitiesVersionControlService } from '@core/http/entities-version-control.service';
import { MatPaginator } from '@angular/material/paginator'; import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
@ -42,6 +42,10 @@ import { hidePageSizePixelValue } from '@shared/models/constants';
import { Direction, SortOrder } from '@shared/models/page/sort-order'; import { Direction, SortOrder } from '@shared/models/page/sort-order';
import { BranchAutocompleteComponent } from '@shared/components/vc/branch-autocomplete.component'; import { BranchAutocompleteComponent } from '@shared/components/vc/branch-autocomplete.component';
import { isNotEmptyStr } from '@core/utils'; import { isNotEmptyStr } from '@core/utils';
import { TbPopoverService } from '@shared/components/popover.service';
import { EntityVersionExportComponent } from '@home/components/vc/entity-version-export.component';
import { MatButton } from '@angular/material/button';
import { TbPopoverComponent } from '@shared/components/popover.component';
@Component({ @Component({
selector: 'tb-entity-versions-table', selector: 'tb-entity-versions-table',
@ -68,6 +72,8 @@ export class EntityVersionsTableComponent extends PageComponent implements OnIni
viewsInited = false; viewsInited = false;
vcExportPopover: TbPopoverComponent;
private componentResize$: ResizeObserver; private componentResize$: ResizeObserver;
@Input() @Input()
@ -94,12 +100,18 @@ export class EntityVersionsTableComponent extends PageComponent implements OnIni
} }
} }
@Input()
entityId: EntityId;
@ViewChild(MatPaginator) paginator: MatPaginator; @ViewChild(MatPaginator) paginator: MatPaginator;
@ViewChild(MatSort) sort: MatSort; @ViewChild(MatSort) sort: MatSort;
constructor(protected store: Store<AppState>, constructor(protected store: Store<AppState>,
private entitiesVersionControlService: EntitiesVersionControlService, private entitiesVersionControlService: EntitiesVersionControlService,
private popoverService: TbPopoverService,
private renderer: Renderer2,
private cd: ChangeDetectorRef, private cd: ChangeDetectorRef,
private viewContainerRef: ViewContainerRef,
private elementRef: ElementRef) { private elementRef: ElementRef) {
super(store); super(store);
this.dirtyValue = !this.activeValue; this.dirtyValue = !this.activeValue;
@ -148,10 +160,36 @@ export class EntityVersionsTableComponent extends PageComponent implements OnIni
} }
} }
vcExport($event: Event) { toggleVcExport($event: Event, exportButton: MatButton) {
if ($event) { if ($event) {
$event.stopPropagation(); $event.stopPropagation();
} }
const trigger = exportButton._elementRef.nativeElement;
if (this.popoverService.hasPopover(trigger)) {
this.popoverService.hidePopover(trigger);
} else {
this.vcExportPopover = this.popoverService.displayPopover(trigger, this.renderer,
this.viewContainerRef, EntityVersionExportComponent, 'bottom', true, null,
{
branch: this.branch,
entityId: this.entityId,
onClose: (result: VersionCreationResult | null, branch: string | null) => {
this.vcExportPopover.hide();
if (result) {
if (this.branch !== branch) {
this.branchChanged(branch);
} else {
this.updateData();
}
}
}
}, {}, {}, {}, false);
this.vcExportPopover.tbVisibleChange.subscribe((visible: boolean) => {
if (!visible) {
this.vcExportPopover = null;
}
});
}
} }
versionIdContent(entityVersion: EntityVersion): string { versionIdContent(entityVersion: EntityVersion): string {

77
ui-ngx/src/app/modules/home/components/vc/vc-entity-export-dialog.component.html

@ -1,77 +0,0 @@
<!--
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;">
<mat-toolbar color="primary">
<h2>{{ (createResult ? 'version-control.entity-version-exported' : 'version-control.export-entity-version') | translate }}</h2>
<span fxFlex></span>
<button mat-button mat-icon-button
(click)="cancel()"
type="button">
<mat-icon class="material-icons">close</mat-icon>
</button>
</mat-toolbar>
<mat-progress-bar color="warn" mode="indeterminate" *ngIf="isLoading$ | async">
</mat-progress-bar>
<div mat-dialog-content>
<form *ngIf="!createResult" [formGroup]="exportFormGroup">
<fieldset [disabled]="isLoading$ | async">
<div fxFlex fxLayout="column">
<tb-branch-autocomplete
required
formControlName="branch">
</tb-branch-autocomplete>
<mat-form-field class="mat-block" fxFlex>
<mat-label translate>version-control.version-name</mat-label>
<input required matInput formControlName="versionName">
<mat-error *ngIf="exportFormGroup.get('versionName').hasError('required')">
{{ 'version-control.version-name-required' | translate }}
</mat-error>
</mat-form-field>
<mat-checkbox formControlName="saveRelations" style="margin-bottom: 16px;">
{{ 'version-control.export-entity-relations' | translate }}
</mat-checkbox>
</div>
</fieldset>
</form>
<div *ngIf="createResult" fxFlex fxLayout="column" fxLayoutAlign="center">
<div [innerHTML]="createResultMessage"></div>
</div>
</div>
<div *ngIf="!createResult" mat-dialog-actions fxLayoutAlign="end center">
<button mat-button color="primary"
type="button"
[disabled]="(isLoading$ | async)"
(click)="cancel()" cdkFocusInitial>
{{ 'action.cancel' | translate }}
</button>
<button mat-raised-button color="primary"
type="button"
(click)="export()"
[disabled]="(isLoading$ | async) || exportFormGroup.invalid || !exportFormGroup.dirty">
{{ 'action.export' | translate }}
</button>
</div>
<div *ngIf="createResult" mat-dialog-actions fxLayoutAlign="end center">
<button mat-button color="primary"
type="button"
[disabled]="(isLoading$ | async)"
(click)="cancel()" cdkFocusInitial>
{{ 'action.close' | translate }}
</button>
</div>
</section>

105
ui-ngx/src/app/modules/home/components/vc/vc-entity-export-dialog.component.ts

@ -1,105 +0,0 @@
///
/// 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, Inject, OnInit, SkipSelf } from '@angular/core';
import { ErrorStateMatcher } from '@angular/material/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { FormBuilder, FormControl, FormGroup, FormGroupDirective, NgForm, Validators } from '@angular/forms';
import { Router } from '@angular/router';
import { DialogComponent } from '@app/shared/components/dialog.component';
import { EntityId } from '@shared/models/id/entity-id';
import {
SingleEntityVersionCreateRequest,
VersionCreateRequestType,
VersionCreationResult
} from '@shared/models/vc.models';
import { EntitiesVersionControlService } from '@core/http/entities-version-control.service';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { TranslateService } from '@ngx-translate/core';
export interface VcEntityExportDialogData {
entityId: EntityId;
}
@Component({
selector: 'tb-vc-entity-export-dialog',
templateUrl: './vc-entity-export-dialog.component.html',
providers: [{provide: ErrorStateMatcher, useExisting: VcEntityExportDialogComponent}],
styleUrls: []
})
export class VcEntityExportDialogComponent extends DialogComponent<VcEntityExportDialogComponent>
implements OnInit, ErrorStateMatcher {
exportFormGroup: FormGroup;
submitted = false;
createResult: VersionCreationResult;
createResultMessage: SafeHtml;
constructor(protected store: Store<AppState>,
protected router: Router,
@Inject(MAT_DIALOG_DATA) public data: VcEntityExportDialogData,
@SkipSelf() private errorStateMatcher: ErrorStateMatcher,
public dialogRef: MatDialogRef<VcEntityExportDialogComponent>,
private entitiesVersionControlService: EntitiesVersionControlService,
private translate: TranslateService,
private domSanitizer: DomSanitizer,
private fb: FormBuilder) {
super(store, router, dialogRef);
this.exportFormGroup = this.fb.group({
branch: [null, [Validators.required]],
versionName: [null, [Validators.required]],
saveRelations: [false, []]
});
}
ngOnInit(): void {
}
isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
const originalErrorState = this.errorStateMatcher.isErrorState(control, form);
const customErrorState = !!(control && control.invalid && this.submitted);
return originalErrorState || customErrorState;
}
cancel(): void {
this.dialogRef.close();
}
export(): void {
this.submitted = true;
const request: SingleEntityVersionCreateRequest = {
entityId: this.data.entityId,
branch: this.exportFormGroup.get('branch').value,
versionName: this.exportFormGroup.get('versionName').value,
config: {
saveRelations: this.exportFormGroup.get('saveRelations').value
},
type: VersionCreateRequestType.SINGLE_ENTITY
};
this.entitiesVersionControlService.saveEntitiesVersion(request).subscribe((result) => {
this.createResult = result;
const message = this.translate.instant('version-control.export-entity-version-result-message',
{name: result.version.name, commitId: result.version.id});
this.createResultMessage = this.domSanitizer.bypassSecurityTrustHtml(message);
});
}
}

1
ui-ngx/src/app/modules/home/components/vc/version-control.component.html

@ -21,5 +21,6 @@
<ng-template #versionsTable> <ng-template #versionsTable>
<tb-entity-versions-table [singleEntityMode]="singleEntityMode" <tb-entity-versions-table [singleEntityMode]="singleEntityMode"
[active]="active" [active]="active"
[entityId]="entityId"
[externalEntityId]="externalEntityId"></tb-entity-versions-table> [externalEntityId]="externalEntityId"></tb-entity-versions-table>
</ng-template> </ng-template>

3
ui-ngx/src/app/modules/home/components/vc/version-control.component.ts

@ -44,6 +44,9 @@ export class VersionControlComponent implements OnInit, HasConfirmForm {
@Input() @Input()
externalEntityId: EntityId; externalEntityId: EntityId;
@Input()
entityId: EntityId;
hasVersionControl$ = this.store.pipe(select(selectHasVersionControl)); hasVersionControl$ = this.store.pipe(select(selectHasVersionControl));
constructor(private store: Store<AppState>) { constructor(private store: Store<AppState>) {

16
ui-ngx/src/app/modules/home/dialogs/home-dialogs.service.ts

@ -22,11 +22,6 @@ import {
ImportDialogCsvComponent, ImportDialogCsvComponent,
ImportDialogCsvData ImportDialogCsvData
} from '@home/components/import-export/import-dialog-csv.component'; } from '@home/components/import-export/import-dialog-csv.component';
import { EntityId } from '@shared/models/id/entity-id';
import {
VcEntityExportDialogComponent,
VcEntityExportDialogData
} from '@home/components/vc/vc-entity-export-dialog.component';
@Injectable() @Injectable()
export class HomeDialogsService { export class HomeDialogsService {
@ -46,17 +41,6 @@ export class HomeDialogsService {
} }
} }
public exportVcEntity(entityId: EntityId): Observable<void> {
return this.dialog.open<VcEntityExportDialogComponent, VcEntityExportDialogData>(VcEntityExportDialogComponent,
{
disableClose: true,
panelClass: ['tb-dialog', 'tb-fullscreen-dialog'],
data: {
entityId
}
}).afterClosed();
}
private openImportDialogCSV(entityType: EntityType, importTitle: string, importFileLabel: string): Observable<boolean> { private openImportDialogCSV(entityType: EntityType, importTitle: string, importFileLabel: string): Observable<boolean> {
return this.dialog.open<ImportDialogCsvComponent, ImportDialogCsvData, return this.dialog.open<ImportDialogCsvComponent, ImportDialogCsvData,
any>(ImportDialogCsvComponent, { any>(ImportDialogCsvComponent, {

5
ui-ngx/src/app/modules/home/pages/asset/asset-tabs.component.html

@ -49,3 +49,8 @@
label="{{ 'audit-log.audit-logs' | translate }}" #auditLogsTab="matTab"> label="{{ 'audit-log.audit-logs' | translate }}" #auditLogsTab="matTab">
<tb-audit-log-table detailsMode="true" [active]="auditLogsTab.isActive" [auditLogMode]="auditLogModes.ENTITY" [entityId]="entity.id"></tb-audit-log-table> <tb-audit-log-table detailsMode="true" [active]="auditLogsTab.isActive" [auditLogMode]="auditLogModes.ENTITY" [entityId]="entity.id"></tb-audit-log-table>
</mat-tab> </mat-tab>
<mat-tab *ngIf="entity && authUser.authority === authorities.TENANT_ADMIN"
label="{{ 'version-control.version-control' | translate }}" #versionControlTab="matTab">
<tb-version-control detailsMode="true" singleEntityMode="true"
[active]="versionControlTab.isActive" [entityId]="entity.id" [externalEntityId]="entity.externalId || entity.id"></tb-version-control>
</mat-tab>

6
ui-ngx/src/app/modules/home/pages/asset/asset.component.html

@ -46,12 +46,6 @@
[fxShow]="!isEdit && assetScope === 'edge'"> [fxShow]="!isEdit && assetScope === 'edge'">
{{ 'edge.unassign-from-edge' | translate }} {{ 'edge.unassign-from-edge' | translate }}
</button> </button>
<button mat-raised-button color="primary"
[disabled]="(isLoading$ | async)"
(click)="onEntityAction($event, 'vcExport')"
[fxShow]="!isEdit && (assetScope === 'customer' || assetScope === 'tenant')">
{{'version-control.export-to-git' | translate }}
</button>
<button mat-raised-button color="primary" <button mat-raised-button color="primary"
[disabled]="(isLoading$ | async)" [disabled]="(isLoading$ | async)"
(click)="onEntityAction($event, 'delete')" (click)="onEntityAction($event, 'delete')"

10
ui-ngx/src/app/modules/home/pages/asset/assets-table-config.resolver.ts

@ -468,13 +468,6 @@ export class AssetsTableConfigResolver implements Resolve<EntityTableConfig<Asse
); );
} }
vcExport($event: Event, asset: Asset) {
if ($event) {
$event.stopPropagation();
}
this.homeDialogs.exportVcEntity(asset.id);
}
onAssetAction(action: EntityAction<AssetInfo>, config: EntityTableConfig<AssetInfo>): boolean { onAssetAction(action: EntityAction<AssetInfo>, config: EntityTableConfig<AssetInfo>): boolean {
switch (action.action) { switch (action.action) {
case 'open': case 'open':
@ -492,9 +485,6 @@ export class AssetsTableConfigResolver implements Resolve<EntityTableConfig<Asse
case 'unassignFromEdge': case 'unassignFromEdge':
this.unassignFromEdge(action.event, action.entity); this.unassignFromEdge(action.event, action.entity);
return true; return true;
case 'vcExport':
this.vcExport(action.event, action.entity);
return true;
} }
return false; return false;
} }

5
ui-ngx/src/app/modules/home/pages/customer/customer-tabs.component.html

@ -49,3 +49,8 @@
label="{{ 'audit-log.audit-logs' | translate }}" #auditLogsTab="matTab"> label="{{ 'audit-log.audit-logs' | translate }}" #auditLogsTab="matTab">
<tb-audit-log-table detailsMode="true" [active]="auditLogsTab.isActive" [auditLogMode]="auditLogModes.CUSTOMER" [customerId]="entity.id"></tb-audit-log-table> <tb-audit-log-table detailsMode="true" [active]="auditLogsTab.isActive" [auditLogMode]="auditLogModes.CUSTOMER" [customerId]="entity.id"></tb-audit-log-table>
</mat-tab> </mat-tab>
<mat-tab *ngIf="entity && authUser.authority === authorities.TENANT_ADMIN"
label="{{ 'version-control.version-control' | translate }}" #versionControlTab="matTab">
<tb-version-control detailsMode="true" singleEntityMode="true"
[active]="versionControlTab.isActive" [entityId]="entity.id" [externalEntityId]="entity.externalId || entity.id"></tb-version-control>
</mat-tab>

6
ui-ngx/src/app/modules/home/pages/customer/customer.component.html

@ -53,12 +53,6 @@
*ngIf="edgesSupportEnabled()"> *ngIf="edgesSupportEnabled()">
{{'customer.manage-edges' | translate }} {{'customer.manage-edges' | translate }}
</button> </button>
<button mat-raised-button color="primary"
[disabled]="(isLoading$ | async)"
(click)="onEntityAction($event, 'vcExport')"
[fxShow]="!isEdit && !isPublic">
{{'version-control.export-to-git' | translate }}
</button>
<button mat-raised-button color="primary" <button mat-raised-button color="primary"
[disabled]="(isLoading$ | async)" [disabled]="(isLoading$ | async)"
(click)="onEntityAction($event, 'delete')" (click)="onEntityAction($event, 'delete')"

10
ui-ngx/src/app/modules/home/pages/customer/customers-table-config.resolver.ts

@ -182,13 +182,6 @@ export class CustomersTableConfigResolver implements Resolve<EntityTableConfig<C
this.router.navigateByUrl(`customers/${customer.id.id}/edgeInstances`); this.router.navigateByUrl(`customers/${customer.id.id}/edgeInstances`);
} }
vcExport($event: Event, customer: Customer) {
if ($event) {
$event.stopPropagation();
}
this.homeDialogs.exportVcEntity(customer.id);
}
onCustomerAction(action: EntityAction<Customer>, config: EntityTableConfig<Customer>): boolean { onCustomerAction(action: EntityAction<Customer>, config: EntityTableConfig<Customer>): boolean {
switch (action.action) { switch (action.action) {
case 'open': case 'open':
@ -209,9 +202,6 @@ export class CustomersTableConfigResolver implements Resolve<EntityTableConfig<C
case 'manageEdges': case 'manageEdges':
this.manageCustomerEdges(action.event, action.entity); this.manageCustomerEdges(action.event, action.entity);
return true; return true;
case 'vcExport':
this.vcExport(action.event, action.entity);
return true;
} }
return false; return false;
} }

6
ui-ngx/src/app/modules/home/pages/dashboard/dashboard-form.component.html

@ -59,12 +59,6 @@
[fxShow]="!isEdit && dashboardScope === 'edge'"> [fxShow]="!isEdit && dashboardScope === 'edge'">
{{ 'edge.unassign-from-edge' | translate }} {{ 'edge.unassign-from-edge' | translate }}
</button> </button>
<button mat-raised-button color="primary"
[disabled]="(isLoading$ | async)"
(click)="onEntityAction($event, 'vcExport')"
[fxShow]="!isEdit && dashboardScope === 'tenant'">
{{'version-control.export-to-git' | translate }}
</button>
<button mat-raised-button color="primary" <button mat-raised-button color="primary"
[disabled]="(isLoading$ | async)" [disabled]="(isLoading$ | async)"
(click)="onEntityAction($event, 'delete')" (click)="onEntityAction($event, 'delete')"

5
ui-ngx/src/app/modules/home/pages/dashboard/dashboard-tabs.component.html

@ -19,3 +19,8 @@
label="{{ 'audit-log.audit-logs' | translate }}" #auditLogsTab="matTab"> label="{{ 'audit-log.audit-logs' | translate }}" #auditLogsTab="matTab">
<tb-audit-log-table [active]="auditLogsTab.isActive" [auditLogMode]="auditLogModes.ENTITY" [entityId]="entity.id" detailsMode="true"></tb-audit-log-table> <tb-audit-log-table [active]="auditLogsTab.isActive" [auditLogMode]="auditLogModes.ENTITY" [entityId]="entity.id" detailsMode="true"></tb-audit-log-table>
</mat-tab> </mat-tab>
<mat-tab *ngIf="entity && authUser.authority === authorities.TENANT_ADMIN"
label="{{ 'version-control.version-control' | translate }}" #versionControlTab="matTab">
<tb-version-control detailsMode="true" singleEntityMode="true"
[active]="versionControlTab.isActive" [entityId]="entity.id" [externalEntityId]="entity.externalId || entity.id"></tb-version-control>
</mat-tab>

10
ui-ngx/src/app/modules/home/pages/dashboard/dashboards-table-config.resolver.ts

@ -539,13 +539,6 @@ export class DashboardsTableConfigResolver implements Resolve<EntityTableConfig<
); );
} }
vcExport($event: Event, dashboard: DashboardInfo) {
if ($event) {
$event.stopPropagation();
}
this.homeDialogs.exportVcEntity(dashboard.id);
}
onDashboardAction(action: EntityAction<DashboardInfo>): boolean { onDashboardAction(action: EntityAction<DashboardInfo>): boolean {
switch (action.action) { switch (action.action) {
case 'open': case 'open':
@ -569,9 +562,6 @@ export class DashboardsTableConfigResolver implements Resolve<EntityTableConfig<
case 'unassignFromEdge': case 'unassignFromEdge':
this.unassignFromEdge(action.event, action.entity); this.unassignFromEdge(action.event, action.entity);
return true; return true;
case 'vcExport':
this.vcExport(action.event, action.entity);
return true;
} }
return false; return false;
} }

5
ui-ngx/src/app/modules/home/pages/device-profile/device-profile-tabs.component.html

@ -75,3 +75,8 @@
label="{{ 'audit-log.audit-logs' | translate }}"> label="{{ 'audit-log.audit-logs' | translate }}">
<tb-audit-log-table detailsMode="true" [active]="auditLogsTab.isActive" [auditLogMode]="auditLogModes.ENTITY" [entityId]="entity.id"></tb-audit-log-table> <tb-audit-log-table detailsMode="true" [active]="auditLogsTab.isActive" [auditLogMode]="auditLogModes.ENTITY" [entityId]="entity.id"></tb-audit-log-table>
</mat-tab> </mat-tab>
<mat-tab *ngIf="entity && authUser.authority === authorities.TENANT_ADMIN"
label="{{ 'version-control.version-control' | translate }}" #versionControlTab="matTab">
<tb-version-control detailsMode="true" singleEntityMode="true"
[active]="versionControlTab.isActive" [entityId]="entity.id" [externalEntityId]="entity.externalId || entity.id"></tb-version-control>
</mat-tab>

10
ui-ngx/src/app/modules/home/pages/device-profile/device-profiles-table-config.resolver.ts

@ -206,13 +206,6 @@ export class DeviceProfilesTableConfigResolver implements Resolve<EntityTableCon
this.importExport.exportDeviceProfile(deviceProfile.id.id); this.importExport.exportDeviceProfile(deviceProfile.id.id);
} }
vcExport($event: Event, deviceProfile: DeviceProfile) {
if ($event) {
$event.stopPropagation();
}
this.homeDialogs.exportVcEntity(deviceProfile.id);
}
onDeviceProfileAction(action: EntityAction<DeviceProfile>): boolean { onDeviceProfileAction(action: EntityAction<DeviceProfile>): boolean {
switch (action.action) { switch (action.action) {
case 'open': case 'open':
@ -224,9 +217,6 @@ export class DeviceProfilesTableConfigResolver implements Resolve<EntityTableCon
case 'export': case 'export':
this.exportDeviceProfile(action.event, action.entity); this.exportDeviceProfile(action.event, action.entity);
return true; return true;
case 'vcExport':
this.vcExport(action.event, action.entity);
return true;
} }
return false; return false;
} }

2
ui-ngx/src/app/modules/home/pages/device/device-tabs.component.html

@ -52,5 +52,5 @@
<mat-tab *ngIf="entity && authUser.authority === authorities.TENANT_ADMIN" <mat-tab *ngIf="entity && authUser.authority === authorities.TENANT_ADMIN"
label="{{ 'version-control.version-control' | translate }}" #versionControlTab="matTab"> label="{{ 'version-control.version-control' | translate }}" #versionControlTab="matTab">
<tb-version-control detailsMode="true" singleEntityMode="true" <tb-version-control detailsMode="true" singleEntityMode="true"
[active]="versionControlTab.isActive" [externalEntityId]="entity.externalId || entity.id"></tb-version-control> [active]="versionControlTab.isActive" [entityId]="entity.id" [externalEntityId]="entity.externalId || entity.id"></tb-version-control>
</mat-tab> </mat-tab>

6
ui-ngx/src/app/modules/home/pages/device/device.component.html

@ -52,12 +52,6 @@
[fxShow]="!isEdit && deviceScope === 'edge'"> [fxShow]="!isEdit && deviceScope === 'edge'">
{{ 'edge.unassign-from-edge' | translate }} {{ 'edge.unassign-from-edge' | translate }}
</button> </button>
<button mat-raised-button color="primary"
[disabled]="(isLoading$ | async)"
(click)="onEntityAction($event, 'vcExport')"
[fxShow]="!isEdit && (deviceScope === 'customer' || deviceScope === 'tenant')">
{{'version-control.export-to-git' | translate }}
</button>
<button mat-raised-button color="primary" fxFlex.xs <button mat-raised-button color="primary" fxFlex.xs
[disabled]="(isLoading$ | async)" [disabled]="(isLoading$ | async)"
(click)="onEntityAction($event, 'delete')" (click)="onEntityAction($event, 'delete')"

10
ui-ngx/src/app/modules/home/pages/device/devices-table-config.resolver.ts

@ -547,13 +547,6 @@ export class DevicesTableConfigResolver implements Resolve<EntityTableConfig<Dev
}); });
} }
vcExport($event: Event, device: Device) {
if ($event) {
$event.stopPropagation();
}
this.homeDialogs.exportVcEntity(device.id);
}
onDeviceAction(action: EntityAction<DeviceInfo>, config: EntityTableConfig<DeviceInfo>): boolean { onDeviceAction(action: EntityAction<DeviceInfo>, config: EntityTableConfig<DeviceInfo>): boolean {
switch (action.action) { switch (action.action) {
case 'open': case 'open':
@ -574,9 +567,6 @@ export class DevicesTableConfigResolver implements Resolve<EntityTableConfig<Dev
case 'manageCredentials': case 'manageCredentials':
this.manageCredentials(action.event, action.entity); this.manageCredentials(action.event, action.entity);
return true; return true;
case 'vcExport':
this.vcExport(action.event, action.entity);
return true;
} }
return false; return false;
} }

5
ui-ngx/src/app/modules/home/pages/rulechain/rulechain-tabs.component.html

@ -52,3 +52,8 @@
label="{{ 'audit-log.audit-logs' | translate }}" #auditLogsTab="matTab"> label="{{ 'audit-log.audit-logs' | translate }}" #auditLogsTab="matTab">
<tb-audit-log-table detailsMode="true" [active]="auditLogsTab.isActive" [auditLogMode]="auditLogModes.ENTITY" [entityId]="entity.id"></tb-audit-log-table> <tb-audit-log-table detailsMode="true" [active]="auditLogsTab.isActive" [auditLogMode]="auditLogModes.ENTITY" [entityId]="entity.id"></tb-audit-log-table>
</mat-tab> </mat-tab>
<mat-tab *ngIf="entity && authUser.authority === authorities.TENANT_ADMIN"
label="{{ 'version-control.version-control' | translate }}" #versionControlTab="matTab">
<tb-version-control detailsMode="true" singleEntityMode="true"
[active]="versionControlTab.isActive" [entityId]="entity.id" [externalEntityId]="entity.externalId || entity.id"></tb-version-control>
</mat-tab>

6
ui-ngx/src/app/modules/home/pages/rulechain/rulechain.component.html

@ -58,12 +58,6 @@
[fxShow]="!isEdit && !isEdgeRootRuleChain() && ruleChainScope === 'edge'"> [fxShow]="!isEdit && !isEdgeRootRuleChain() && ruleChainScope === 'edge'">
{{'edge.unassign-from-edge' | translate }} {{'edge.unassign-from-edge' | translate }}
</button> </button>
<button mat-raised-button color="primary"
[disabled]="(isLoading$ | async)"
(click)="onEntityAction($event, 'vcExport')"
[fxShow]="!isEdit">
{{'version-control.export-to-git' | translate }}
</button>
<button mat-raised-button color="primary" <button mat-raised-button color="primary"
[disabled]="(isLoading$ | async)" [disabled]="(isLoading$ | async)"
(click)="onEntityAction($event, 'delete')" (click)="onEntityAction($event, 'delete')"

10
ui-ngx/src/app/modules/home/pages/rulechain/rulechains-table-config.resolver.ts

@ -360,13 +360,6 @@ export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig<
); );
} }
vcExport($event: Event, ruleChain: RuleChain) {
if ($event) {
$event.stopPropagation();
}
this.homeDialogs.exportVcEntity(ruleChain.id);
}
onRuleChainAction(action: EntityAction<RuleChain>): boolean { onRuleChainAction(action: EntityAction<RuleChain>): boolean {
switch (action.action) { switch (action.action) {
case 'open': case 'open':
@ -390,9 +383,6 @@ export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig<
case 'unsetAutoAssignToEdge': case 'unsetAutoAssignToEdge':
this.unsetAutoAssignToEdgeRuleChain(action.event, action.entity); this.unsetAutoAssignToEdgeRuleChain(action.event, action.entity);
return true; return true;
case 'vcExport':
this.vcExport(action.event, action.entity);
return true;
} }
return false; return false;
} }

3
ui-ngx/src/app/shared/components/popover.component.ts

@ -314,7 +314,7 @@ export class TbPopoverDirective implements OnChanges, OnDestroy, AfterViewInit {
<span class="tb-popover-arrow-content"></span> <span class="tb-popover-arrow-content"></span>
</div> </div>
<div class="tb-popover-inner" [ngStyle]="tbPopoverInnerStyle" role="tooltip"> <div class="tb-popover-inner" [ngStyle]="tbPopoverInnerStyle" role="tooltip">
<div class="tb-popover-close-button" (click)="closeButtonClick($event)">×</div> <div *ngIf="tbShowCloseButton" class="tb-popover-close-button" (click)="closeButtonClick($event)">×</div>
<div style="width: 100%; height: 100%;"> <div style="width: 100%; height: 100%;">
<div class="tb-popover-inner-content"> <div class="tb-popover-inner-content">
<ng-container *ngIf="tbContent"> <ng-container *ngIf="tbContent">
@ -354,6 +354,7 @@ export class TbPopoverComponent implements OnDestroy, OnInit {
tbMouseEnterDelay?: number; tbMouseEnterDelay?: number;
tbMouseLeaveDelay?: number; tbMouseLeaveDelay?: number;
tbHideOnClickOutside = true; tbHideOnClickOutside = true;
tbShowCloseButton = true;
tbAnimationState = 'active'; tbAnimationState = 'active';

4
ui-ngx/src/app/shared/components/popover.service.ts

@ -55,7 +55,8 @@ export class TbPopoverService {
displayPopover<T>(trigger: Element, renderer: Renderer2, hostView: ViewContainerRef, displayPopover<T>(trigger: Element, renderer: Renderer2, hostView: ViewContainerRef,
componentType: Type<T>, preferredPlacement: PopoverPlacement = 'top', hideOnClickOutside = true, componentType: Type<T>, preferredPlacement: PopoverPlacement = 'top', hideOnClickOutside = true,
injector?: Injector, context?: any, overlayStyle: any = {}, popoverStyle: any = {}, style?: any): TbPopoverComponent { injector?: Injector, context?: any, overlayStyle: any = {}, popoverStyle: any = {}, style?: any,
showCloseButton = true): TbPopoverComponent {
const componentRef = hostView.createComponent(this.componentFactory); const componentRef = hostView.createComponent(this.componentFactory);
const component = componentRef.instance; const component = componentRef.instance;
this.popoverWithTriggers.push({ this.popoverWithTriggers.push({
@ -76,6 +77,7 @@ export class TbPopoverService {
component.tbPopoverInnerStyle = popoverStyle; component.tbPopoverInnerStyle = popoverStyle;
component.tbComponentStyle = style; component.tbComponentStyle = style;
component.tbHideOnClickOutside = hideOnClickOutside; component.tbHideOnClickOutside = hideOnClickOutside;
component.tbShowCloseButton = showCloseButton;
component.tbVisibleChange.subscribe((visible: boolean) => { component.tbVisibleChange.subscribe((visible: boolean) => {
if (!visible) { if (!visible) {
component.tbAnimationDone.subscribe(() => { component.tbAnimationDone.subscribe(() => {

5
ui-ngx/src/app/shared/components/vc/branch-autocomplete.component.html

@ -36,8 +36,11 @@
(closed)="onPanelClosed()" (closed)="onPanelClosed()"
#branchAutocomplete="matAutocomplete" #branchAutocomplete="matAutocomplete"
[displayWith]="displayBranchFn"> [displayWith]="displayBranchFn">
<mat-option *ngFor="let branch of filteredBranches | async" [value]="branch"> <mat-option *ngFor="let branch of filteredBranches | async" [value]="branch" class="branch-option">
<mat-icon class="tb-mat-18" *ngIf="selectionMode && branch.name === modelValue">check</mat-icon>
<span class="check-placeholder" *ngIf="selectionMode && branch.name !== modelValue"></span>
<span [innerHTML]="branch.name | highlight:searchText"></span> <span [innerHTML]="branch.name | highlight:searchText"></span>
<small *ngIf="branch.default" class="default-branch">{{ 'version-control.default' | translate }}</small>
</mat-option> </mat-option>
</mat-autocomplete> </mat-autocomplete>
<mat-error *ngIf="branchFormGroup.get('branch').hasError('required')"> <mat-error *ngIf="branchFormGroup.get('branch').hasError('required')">

30
ui-ngx/src/app/shared/components/vc/branch-autocomplete.component.scss

@ -0,0 +1,30 @@
/**
* 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.
*/
.mat-option.branch-option {
.mat-icon, .check-placeholder {
margin-right: 8px;
}
.check-placeholder {
width: 18px;
display: inline-block;
}
.mat-option-text {
width: 100%;
.default-branch {
float: right;
}
}
}

57
ui-ngx/src/app/shared/components/vc/branch-autocomplete.component.ts

@ -14,9 +14,19 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { AfterViewInit, Component, ElementRef, forwardRef, Input, NgZone, OnInit, ViewChild } from '@angular/core'; import {
AfterViewInit,
Component,
ElementRef,
forwardRef,
Input,
NgZone,
OnInit,
ViewChild,
ViewEncapsulation
} from '@angular/core';
import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR } from '@angular/forms'; import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR } from '@angular/forms';
import { Observable, of } from 'rxjs'; import { Observable } from 'rxjs';
import { debounceTime, distinctUntilChanged, map, share, switchMap, tap } from 'rxjs/operators'; import { debounceTime, distinctUntilChanged, map, share, switchMap, tap } from 'rxjs/operators';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppState } from '@app/core/core.state'; import { AppState } from '@app/core/core.state';
@ -29,12 +39,13 @@ import { MatAutocomplete, MatAutocompleteTrigger } from '@angular/material/autoc
@Component({ @Component({
selector: 'tb-branch-autocomplete', selector: 'tb-branch-autocomplete',
templateUrl: './branch-autocomplete.component.html', templateUrl: './branch-autocomplete.component.html',
styleUrls: [], styleUrls: ['./branch-autocomplete.component.scss'],
providers: [{ providers: [{
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => BranchAutocompleteComponent), useExisting: forwardRef(() => BranchAutocompleteComponent),
multi: true multi: true
}] }],
encapsulation: ViewEncapsulation.None
}) })
export class BranchAutocompleteComponent implements ControlValueAccessor, OnInit, AfterViewInit { export class BranchAutocompleteComponent implements ControlValueAccessor, OnInit, AfterViewInit {
@ -216,30 +227,22 @@ export class BranchAutocompleteComponent implements ControlValueAccessor, OnInit
selectAvailableValue() { selectAvailableValue() {
if (this.selectionMode) { if (this.selectionMode) {
const branch = this.branchFormGroup.get('branch').value; const branch = this.branchFormGroup.get('branch').value;
let branchInfo: Observable<BranchInfo> = null; this.getBranches().pipe(
if (isNotEmptyStr(branch)) { map(branches => {
branchInfo = this.getBranches().pipe( let foundBranch = branches.find(b => b.name === branch);
map(branches => { if (!foundBranch && isNotEmptyStr(this.modelValue)) {
let foundBranch = branches.find(b => b.name === branch); foundBranch = branches.find(b => b.name === this.modelValue);
if (!foundBranch && isNotEmptyStr(this.modelValue)) {
foundBranch = branches.find(b => b.name === this.modelValue);
}
return foundBranch;
})
);
} else if (!branch) {
branchInfo = of(null);
}
if (branchInfo) {
branchInfo.subscribe((val) => {
if (!val && this.defaultBranch) {
val = this.defaultBranch;
} }
this.zone.run(() => { return foundBranch;
this.branchFormGroup.get('branch').patchValue(val, {emitEvent: true}); })
}, 0); ).subscribe((val) => {
}); if (!val && this.defaultBranch) {
} val = this.defaultBranch;
}
this.zone.run(() => {
this.branchFormGroup.get('branch').patchValue(val, {emitEvent: true});
}, 0);
});
} }
} }

9
ui-ngx/src/assets/locale/locale.constant-en_US.json

@ -3112,22 +3112,21 @@
"version-control": "Version control", "version-control": "Version control",
"management": "Version control management", "management": "Version control management",
"branch": "Branch", "branch": "Branch",
"default": "Default",
"select-branch": "Select branch", "select-branch": "Select branch",
"branch-required": "Branch is required", "branch-required": "Branch is required",
"export-entity-version": "Export entity version", "create-entity-version": "Create entity version",
"entity-version-exported": "Entity version successfully exported",
"version-name": "Version name", "version-name": "Version name",
"version-name-required": "Version name is required", "version-name-required": "Version name is required",
"export-entity-relations": "Export entity relations", "export-entity-relations": "Export entity relations",
"export-entity-version-result-message": "Entity exported with version '{{name}}' and commit id '{{commitId}}'.",
"export-to-git": "Export to Git",
"entity-versions": "Entity versions", "entity-versions": "Entity versions",
"versions": "Versions", "versions": "Versions",
"created-time": "Created time", "created-time": "Created time",
"version-id": "Version ID", "version-id": "Version ID",
"no-entity-versions-text": "No entity versions found", "no-entity-versions-text": "No entity versions found",
"no-versions-text": "No versions found", "no-versions-text": "No versions found",
"copy-full-version-id": "Copy full version id" "copy-full-version-id": "Copy full version id",
"create-version": "Create version"
}, },
"widget": { "widget": {
"widget-library": "Widgets Library", "widget-library": "Widgets Library",

Loading…
Cancel
Save