38 changed files with 948 additions and 87 deletions
@ -0,0 +1,81 @@ |
|||||
|
<!-- |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
--> |
||||
|
<div class="mat-padding tb-entity-table tb-absolute-fill"> |
||||
|
<div fxFlex fxLayout="column" class="mat-elevation-z1 tb-entity-table-content"> |
||||
|
<mat-toolbar class="mat-table-toolbar"> |
||||
|
<div class="mat-toolbar-tools"> |
||||
|
<div fxLayout="row" fxLayoutAlign="start center" fxLayout.xs="column" fxLayoutAlign.xs="center start" class="title-container"> |
||||
|
<span class="tb-entity-table-title">{{(singleEntityMode ? 'version-control.entity-versions' : 'version-control.versions') | translate}}</span> |
||||
|
<tb-branch-autocomplete |
||||
|
#branchAutocompleteComponent |
||||
|
[selectionMode]="true" |
||||
|
[selectDefaultBranch]="false" |
||||
|
[disabled]="isLoading$ | async" |
||||
|
[ngModel]="branch" |
||||
|
(ngModelChange)="branchChanged($event)"> |
||||
|
</tb-branch-autocomplete> |
||||
|
</div> |
||||
|
<span fxFlex></span> |
||||
|
<button *ngIf="singleEntityMode" mat-raised-button color="primary" |
||||
|
[disabled]="(isLoading$ | async)" |
||||
|
(click)="vcExport($event)"> |
||||
|
{{'version-control.export-to-git' | translate }} |
||||
|
</button> |
||||
|
</div> |
||||
|
</mat-toolbar> |
||||
|
<div fxFlex class="table-container"> |
||||
|
<table mat-table [dataSource]="dataSource" |
||||
|
matSort [matSortActive]="pageLink.sortOrder.property" [matSortDirection]="pageLink.sortDirection()" matSortDisableClear> |
||||
|
<ng-container matColumnDef="timestamp"> |
||||
|
<mat-header-cell *matHeaderCellDef mat-sort-header style="min-width: 150px; max-width: 150px; width: 150px;"> {{ 'version-control.created-time' | translate }} </mat-header-cell> |
||||
|
<mat-cell *matCellDef="let entityVersion"> |
||||
|
{{ entityVersion.timestamp | date:'yyyy-MM-dd HH:mm:ss' }} |
||||
|
</mat-cell> |
||||
|
</ng-container> |
||||
|
<ng-container matColumnDef="id"> |
||||
|
<mat-header-cell *matHeaderCellDef style="width: 40%"> {{ 'version-control.version-id' | translate }} </mat-header-cell> |
||||
|
<mat-cell *matCellDef="let entityVersion"> |
||||
|
{{ entityVersion.id }} |
||||
|
</mat-cell> |
||||
|
</ng-container> |
||||
|
<ng-container matColumnDef="name"> |
||||
|
<mat-header-cell *matHeaderCellDef style="width: 60%"> {{ 'version-control.version-name' | translate }} </mat-header-cell> |
||||
|
<mat-cell *matCellDef="let entityVersion"> |
||||
|
{{ entityVersion.name }} |
||||
|
</mat-cell> |
||||
|
</ng-container> |
||||
|
<mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></mat-header-row> |
||||
|
<mat-row *matRowDef="let entityVersion; columns: displayedColumns;"></mat-row> |
||||
|
</table> |
||||
|
<span [fxShow]="dataSource.isEmpty() | async" |
||||
|
fxLayoutAlign="center center" |
||||
|
class="no-data-found" translate>{{ |
||||
|
singleEntityMode |
||||
|
? 'version-control.no-entity-versions-text' |
||||
|
: 'version-control.no-versions-text' |
||||
|
}}</span> |
||||
|
</div> |
||||
|
<mat-divider></mat-divider> |
||||
|
<mat-paginator [length]="dataSource.total() | async" |
||||
|
[pageIndex]="pageLink.page" |
||||
|
[pageSize]="pageLink.pageSize" |
||||
|
[pageSizeOptions]="[10, 20, 30]" |
||||
|
[hidePageSize]="hidePageSize" |
||||
|
showFirstLastButtons></mat-paginator> |
||||
|
</div> |
||||
|
</div> |
||||
@ -0,0 +1,100 @@ |
|||||
|
/** |
||||
|
* 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 '../../../../../scss/constants'; |
||||
|
|
||||
|
:host { |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
display: block; |
||||
|
.tb-entity-table { |
||||
|
.tb-entity-table-content { |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
background: #fff; |
||||
|
|
||||
|
.mat-toolbar-tools{ |
||||
|
min-height: auto; |
||||
|
} |
||||
|
|
||||
|
.title-container{ |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
|
||||
|
.tb-entity-table-title { |
||||
|
padding-right: 20px; |
||||
|
white-space: nowrap; |
||||
|
overflow: hidden; |
||||
|
text-overflow: ellipsis; |
||||
|
} |
||||
|
|
||||
|
.table-container { |
||||
|
overflow: auto; |
||||
|
} |
||||
|
|
||||
|
.tb-entity-table-info{ |
||||
|
white-space: nowrap; |
||||
|
overflow: hidden; |
||||
|
text-overflow: ellipsis; |
||||
|
} |
||||
|
|
||||
|
.button-widget-action{ |
||||
|
margin-left: auto; |
||||
|
overflow: hidden; |
||||
|
text-overflow: ellipsis; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@media #{$mat-xs} { |
||||
|
.mat-toolbar { |
||||
|
height: auto; |
||||
|
min-height: 100px; |
||||
|
|
||||
|
.tb-entity-table-title{ |
||||
|
padding-bottom: 5px; |
||||
|
width: 100%; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
:host ::ng-deep { |
||||
|
.mat-sort-header-sorted .mat-sort-header-arrow { |
||||
|
opacity: 1 !important; |
||||
|
} |
||||
|
tb-branch-autocomplete { |
||||
|
mat-form-field { |
||||
|
font-size: 16px; |
||||
|
width: 200px; |
||||
|
|
||||
|
.mat-form-field-wrapper { |
||||
|
padding-bottom: 0; |
||||
|
} |
||||
|
|
||||
|
.mat-form-field-underline { |
||||
|
bottom: 0; |
||||
|
} |
||||
|
|
||||
|
@media #{$mat-xs} { |
||||
|
width: 100%; |
||||
|
|
||||
|
.mat-form-field-infix { |
||||
|
width: auto !important; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,244 @@ |
|||||
|
///
|
||||
|
/// 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 { |
||||
|
AfterViewInit, |
||||
|
ChangeDetectorRef, |
||||
|
Component, |
||||
|
ElementRef, |
||||
|
Input, |
||||
|
OnDestroy, |
||||
|
OnInit, |
||||
|
ViewChild |
||||
|
} from '@angular/core'; |
||||
|
import { PageComponent } from '@shared/components/page.component'; |
||||
|
import { Store } from '@ngrx/store'; |
||||
|
import { AppState } from '@core/core.state'; |
||||
|
import { EntityId } from '@shared/models/id/entity-id'; |
||||
|
import { CollectionViewer, DataSource } from '@angular/cdk/collections'; |
||||
|
import { BehaviorSubject, merge, Observable, of, ReplaySubject } from 'rxjs'; |
||||
|
import { emptyPageData, PageData } from '@shared/models/page/page-data'; |
||||
|
import { PageLink } from '@shared/models/page/page-link'; |
||||
|
import { catchError, map, tap } from 'rxjs/operators'; |
||||
|
import { EntityVersion } from '@shared/models/vc.models'; |
||||
|
import { EntitiesVersionControlService } from '@core/http/entities-version-control.service'; |
||||
|
import { MatPaginator } from '@angular/material/paginator'; |
||||
|
import { MatSort } from '@angular/material/sort'; |
||||
|
import { ResizeObserver } from '@juggle/resize-observer'; |
||||
|
import { hidePageSizePixelValue } from '@shared/models/constants'; |
||||
|
import { Direction, SortOrder } from '@shared/models/page/sort-order'; |
||||
|
import { BranchAutocompleteComponent } from '@shared/components/vc/branch-autocomplete.component'; |
||||
|
|
||||
|
@Component({ |
||||
|
selector: 'tb-entity-versions-table', |
||||
|
templateUrl: './entity-versions-table.component.html', |
||||
|
styleUrls: ['./entity-versions-table.component.scss'] |
||||
|
}) |
||||
|
export class EntityVersionsTableComponent extends PageComponent implements OnInit, AfterViewInit, OnDestroy { |
||||
|
|
||||
|
@ViewChild('branchAutocompleteComponent') branchAutocompleteComponent: BranchAutocompleteComponent; |
||||
|
|
||||
|
@Input() |
||||
|
singleEntityMode = false; |
||||
|
|
||||
|
displayedColumns = ['timestamp', 'id', 'name']; |
||||
|
pageLink: PageLink; |
||||
|
dataSource: EntityVersionsDatasource; |
||||
|
hidePageSize = false; |
||||
|
|
||||
|
branch: string = null; |
||||
|
|
||||
|
activeValue = false; |
||||
|
dirtyValue = false; |
||||
|
externalEntityIdValue: EntityId; |
||||
|
|
||||
|
viewsInited = false; |
||||
|
|
||||
|
private componentResize$: ResizeObserver; |
||||
|
|
||||
|
@Input() |
||||
|
set active(active: boolean) { |
||||
|
if (this.activeValue !== active) { |
||||
|
this.activeValue = active; |
||||
|
if (this.activeValue && this.dirtyValue) { |
||||
|
this.dirtyValue = false; |
||||
|
if (this.viewsInited) { |
||||
|
this.initFromDefaultBranch(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Input() |
||||
|
set externalEntityId(externalEntityId: EntityId) { |
||||
|
if (this.externalEntityIdValue !== externalEntityId) { |
||||
|
this.externalEntityIdValue = externalEntityId; |
||||
|
this.resetSortAndFilter(this.activeValue); |
||||
|
if (!this.activeValue) { |
||||
|
this.dirtyValue = true; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@ViewChild(MatPaginator) paginator: MatPaginator; |
||||
|
@ViewChild(MatSort) sort: MatSort; |
||||
|
|
||||
|
constructor(protected store: Store<AppState>, |
||||
|
private entitiesVersionControlService: EntitiesVersionControlService, |
||||
|
private cd: ChangeDetectorRef, |
||||
|
private elementRef: ElementRef) { |
||||
|
super(store); |
||||
|
this.dirtyValue = !this.activeValue; |
||||
|
const sortOrder: SortOrder = { property: 'timestamp', direction: Direction.DESC }; |
||||
|
this.pageLink = new PageLink(10, 0, null, sortOrder); |
||||
|
this.dataSource = new EntityVersionsDatasource(this.entitiesVersionControlService); |
||||
|
} |
||||
|
|
||||
|
ngOnInit() { |
||||
|
this.componentResize$ = new ResizeObserver(() => { |
||||
|
const showHidePageSize = this.elementRef.nativeElement.offsetWidth < hidePageSizePixelValue; |
||||
|
if (showHidePageSize !== this.hidePageSize) { |
||||
|
this.hidePageSize = showHidePageSize; |
||||
|
this.cd.markForCheck(); |
||||
|
} |
||||
|
}); |
||||
|
this.componentResize$.observe(this.elementRef.nativeElement); |
||||
|
} |
||||
|
|
||||
|
ngOnDestroy() { |
||||
|
if (this.componentResize$) { |
||||
|
this.componentResize$.disconnect(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
branchChanged(newBranch: string) { |
||||
|
this.branch = newBranch; |
||||
|
this.paginator.pageIndex = 0; |
||||
|
if (this.activeValue) { |
||||
|
this.updateData(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
ngAfterViewInit() { |
||||
|
this.sort.sortChange.subscribe(() => this.paginator.pageIndex = 0); |
||||
|
merge(this.sort.sortChange, this.paginator.page) |
||||
|
.pipe( |
||||
|
tap(() => this.updateData()) |
||||
|
) |
||||
|
.subscribe(); |
||||
|
this.viewsInited = true; |
||||
|
if (!this.singleEntityMode) { |
||||
|
this.initFromDefaultBranch(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
vcExport($event: Event) { |
||||
|
if ($event) { |
||||
|
$event.stopPropagation(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private initFromDefaultBranch() { |
||||
|
this.branchAutocompleteComponent.selectDefaultBranchIfNeeded(false, true); |
||||
|
} |
||||
|
|
||||
|
private updateData() { |
||||
|
this.pageLink.page = this.paginator.pageIndex; |
||||
|
this.pageLink.pageSize = this.paginator.pageSize; |
||||
|
this.pageLink.sortOrder.property = this.sort.active; |
||||
|
this.pageLink.sortOrder.direction = Direction[this.sort.direction.toUpperCase()]; |
||||
|
this.dataSource.loadEntityVersions(this.singleEntityMode, this.branch, this.externalEntityIdValue, this.pageLink); |
||||
|
} |
||||
|
|
||||
|
private resetSortAndFilter(update: boolean) { |
||||
|
this.branch = null; |
||||
|
this.pageLink.textSearch = null; |
||||
|
if (this.viewsInited) { |
||||
|
this.paginator.pageIndex = 0; |
||||
|
const sortable = this.sort.sortables.get('timestamp'); |
||||
|
this.sort.active = sortable.id; |
||||
|
this.sort.direction = 'desc'; |
||||
|
if (update) { |
||||
|
this.initFromDefaultBranch(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
class EntityVersionsDatasource implements DataSource<EntityVersion> { |
||||
|
|
||||
|
private entityVersionsSubject = new BehaviorSubject<EntityVersion[]>([]); |
||||
|
private pageDataSubject = new BehaviorSubject<PageData<EntityVersion>>(emptyPageData<EntityVersion>()); |
||||
|
|
||||
|
public pageData$ = this.pageDataSubject.asObservable(); |
||||
|
|
||||
|
constructor(private entitiesVersionControlService: EntitiesVersionControlService) {} |
||||
|
|
||||
|
connect(collectionViewer: CollectionViewer): Observable<EntityVersion[] | ReadonlyArray<EntityVersion>> { |
||||
|
return this.entityVersionsSubject.asObservable(); |
||||
|
} |
||||
|
|
||||
|
disconnect(collectionViewer: CollectionViewer): void { |
||||
|
this.entityVersionsSubject.complete(); |
||||
|
this.pageDataSubject.complete(); |
||||
|
} |
||||
|
|
||||
|
loadEntityVersions(singleEntityMode: boolean, |
||||
|
branch: string, externalEntityId: EntityId, |
||||
|
pageLink: PageLink): Observable<PageData<EntityVersion>> { |
||||
|
const result = new ReplaySubject<PageData<EntityVersion>>(); |
||||
|
this.fetchEntityVersions(singleEntityMode, branch, externalEntityId, pageLink).pipe( |
||||
|
catchError(() => of(emptyPageData<EntityVersion>())), |
||||
|
).subscribe( |
||||
|
(pageData) => { |
||||
|
this.entityVersionsSubject.next(pageData.data); |
||||
|
this.pageDataSubject.next(pageData); |
||||
|
result.next(pageData); |
||||
|
} |
||||
|
); |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
fetchEntityVersions(singleEntityMode: boolean, |
||||
|
branch: string, externalEntityId: EntityId, |
||||
|
pageLink: PageLink): Observable<PageData<EntityVersion>> { |
||||
|
if (!branch) { |
||||
|
return of(emptyPageData<EntityVersion>()); |
||||
|
} else { |
||||
|
if (singleEntityMode) { |
||||
|
if (externalEntityId) { |
||||
|
return this.entitiesVersionControlService.listEntityVersions(pageLink, branch, externalEntityId, {ignoreErrors: true}); |
||||
|
} else { |
||||
|
return of(emptyPageData<EntityVersion>()); |
||||
|
} |
||||
|
} else { |
||||
|
return this.entitiesVersionControlService.listVersions(pageLink, branch, {ignoreErrors: true}); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
isEmpty(): Observable<boolean> { |
||||
|
return this.entityVersionsSubject.pipe( |
||||
|
map((entityVersions) => !entityVersions.length) |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
total(): Observable<number> { |
||||
|
return this.pageDataSubject.pipe( |
||||
|
map((pageData) => pageData.totalElements) |
||||
|
); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,25 @@ |
|||||
|
<!-- |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
--> |
||||
|
<tb-version-control-settings #versionControlSettingsComponent [detailsMode]="detailsMode" |
||||
|
*ngIf="!(hasVersionControl$ | async); else versionsTable"> |
||||
|
</tb-version-control-settings> |
||||
|
<ng-template #versionsTable> |
||||
|
<tb-entity-versions-table [singleEntityMode]="singleEntityMode" |
||||
|
[active]="active" |
||||
|
[externalEntityId]="externalEntityId"></tb-entity-versions-table> |
||||
|
</ng-template> |
||||
@ -0,0 +1,18 @@ |
|||||
|
/** |
||||
|
* 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 { |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,61 @@ |
|||||
|
///
|
||||
|
/// 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, ViewChild } from '@angular/core'; |
||||
|
import { select, Store } from '@ngrx/store'; |
||||
|
import { AppState } from '@core/core.state'; |
||||
|
import { selectHasVersionControl } from '@core/auth/auth.selectors'; |
||||
|
import { HasConfirmForm } from '@core/guards/confirm-on-exit.guard'; |
||||
|
import { VersionControlSettingsComponent } from '@home/components/vc/version-control-settings.component'; |
||||
|
import { FormGroup } from '@angular/forms'; |
||||
|
import { EntityId } from '@shared/models/id/entity-id'; |
||||
|
|
||||
|
@Component({ |
||||
|
selector: 'tb-version-control', |
||||
|
templateUrl: './version-control.component.html', |
||||
|
styleUrls: ['./version-control.component.scss'] |
||||
|
}) |
||||
|
export class VersionControlComponent implements OnInit, HasConfirmForm { |
||||
|
|
||||
|
@ViewChild('versionControlSettingsComponent', {static: false}) versionControlSettingsComponent: VersionControlSettingsComponent; |
||||
|
|
||||
|
@Input() |
||||
|
detailsMode = false; |
||||
|
|
||||
|
@Input() |
||||
|
active = true; |
||||
|
|
||||
|
@Input() |
||||
|
singleEntityMode = false; |
||||
|
|
||||
|
@Input() |
||||
|
externalEntityId: EntityId; |
||||
|
|
||||
|
hasVersionControl$ = this.store.pipe(select(selectHasVersionControl)); |
||||
|
|
||||
|
constructor(private store: Store<AppState>) { |
||||
|
|
||||
|
} |
||||
|
|
||||
|
ngOnInit() { |
||||
|
|
||||
|
} |
||||
|
|
||||
|
confirmForm(): FormGroup { |
||||
|
return this.versionControlSettingsComponent?.versionControlSettingsForm; |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,18 @@ |
|||||
|
<!-- |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
--> |
||||
|
<tb-version-control-settings #versionControlSettingsComponent></tb-version-control-settings> |
||||
@ -0,0 +1,44 @@ |
|||||
|
///
|
||||
|
/// 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, OnInit, ViewChild } from '@angular/core'; |
||||
|
import { PageComponent } from '@shared/components/page.component'; |
||||
|
import { HasConfirmForm } from '@core/guards/confirm-on-exit.guard'; |
||||
|
import { Store } from '@ngrx/store'; |
||||
|
import { AppState } from '@core/core.state'; |
||||
|
import { FormGroup } from '@angular/forms'; |
||||
|
import { VersionControlSettingsComponent } from '@home/components/vc/version-control-settings.component'; |
||||
|
|
||||
|
@Component({ |
||||
|
selector: 'tb-version-control-admin-settings', |
||||
|
templateUrl: './version-control-admin-settings.component.html', |
||||
|
styleUrls: [] |
||||
|
}) |
||||
|
export class VersionControlAdminSettingsComponent extends PageComponent implements OnInit, HasConfirmForm { |
||||
|
|
||||
|
@ViewChild('versionControlSettingsComponent') versionControlSettingsComponent: VersionControlSettingsComponent; |
||||
|
|
||||
|
constructor(protected store: Store<AppState>) { |
||||
|
super(store); |
||||
|
} |
||||
|
|
||||
|
ngOnInit() { |
||||
|
} |
||||
|
|
||||
|
confirmForm(): FormGroup { |
||||
|
return this.versionControlSettingsComponent?.versionControlSettingsForm; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,44 @@ |
|||||
|
///
|
||||
|
/// 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 { NgModule } from '@angular/core'; |
||||
|
import { RouterModule, Routes } from '@angular/router'; |
||||
|
import { ConfirmOnExitGuard } from '@core/guards/confirm-on-exit.guard'; |
||||
|
import { Authority } from '@shared/models/authority.enum'; |
||||
|
import { VersionControlComponent } from '@home/components/vc/version-control.component'; |
||||
|
|
||||
|
const routes: Routes = [ |
||||
|
{ |
||||
|
path: 'vc', |
||||
|
component: VersionControlComponent, |
||||
|
canDeactivate: [ConfirmOnExitGuard], |
||||
|
data: { |
||||
|
auth: [Authority.TENANT_ADMIN], |
||||
|
title: 'version-control.version-control', |
||||
|
breadcrumb: { |
||||
|
label: 'version-control.version-control', |
||||
|
icon: 'history' |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
]; |
||||
|
|
||||
|
@NgModule({ |
||||
|
imports: [RouterModule.forChild(routes)], |
||||
|
exports: [RouterModule], |
||||
|
providers: [] |
||||
|
}) |
||||
|
export class VcRoutingModule { } |
||||
@ -0,0 +1,31 @@ |
|||||
|
///
|
||||
|
/// 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 { NgModule } from '@angular/core'; |
||||
|
import { CommonModule } from '@angular/common'; |
||||
|
import { SharedModule } from '@shared/shared.module'; |
||||
|
import { VcRoutingModule } from '@home/pages/vc/vc-routing.module'; |
||||
|
|
||||
|
@NgModule({ |
||||
|
declarations: [ |
||||
|
], |
||||
|
imports: [ |
||||
|
CommonModule, |
||||
|
SharedModule, |
||||
|
VcRoutingModule |
||||
|
] |
||||
|
}) |
||||
|
export class VcModule { } |
||||
Loading…
Reference in new issue