191 lines
7.8 KiB
TypeScript
191 lines
7.8 KiB
TypeScript
///
|
|
/// 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 { Injectable } from '@angular/core';
|
|
import { HttpClient } from '@angular/common/http';
|
|
import { defaultHttpOptionsFromConfig, RequestConfig } from '@core/http/http-utils';
|
|
import { Observable, of, timer } from 'rxjs';
|
|
import {
|
|
BranchInfo,
|
|
EntityDataDiff,
|
|
EntityDataInfo,
|
|
EntityLoadError,
|
|
entityLoadErrorTranslationMap,
|
|
EntityLoadErrorType,
|
|
EntityVersion,
|
|
VersionCreateRequest,
|
|
VersionCreationResult,
|
|
VersionLoadRequest,
|
|
VersionLoadResult
|
|
} from '@shared/models/vc.models';
|
|
import { PageLink } from '@shared/models/page/page-link';
|
|
import { PageData } from '@shared/models/page/page-data';
|
|
import { EntityId } from '@shared/models/id/entity-id';
|
|
import { EntityType, entityTypeTranslations } from '@shared/models/entity-type.models';
|
|
import { select, Store } from '@ngrx/store';
|
|
import { AppState } from '@core/core.state';
|
|
import { selectIsUserLoaded } from '@core/auth/auth.selectors';
|
|
import { catchError, finalize, switchMap, takeWhile, tap } from 'rxjs/operators';
|
|
import { TranslateService } from '@ngx-translate/core';
|
|
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
|
|
import { ActionLoadFinish, ActionLoadStart } from '@core/interceptors/load.actions';
|
|
|
|
@Injectable({
|
|
providedIn: 'root'
|
|
})
|
|
export class EntitiesVersionControlService {
|
|
|
|
branchList: Array<BranchInfo> = null;
|
|
|
|
constructor(
|
|
private http: HttpClient,
|
|
private translate: TranslateService,
|
|
private sanitizer: DomSanitizer,
|
|
private store: Store<AppState>
|
|
) {
|
|
|
|
this.store.pipe(select(selectIsUserLoaded)).subscribe(
|
|
() => {
|
|
this.branchList = null;
|
|
}
|
|
);
|
|
}
|
|
|
|
public clearBranchList(): void {
|
|
this.branchList = null;
|
|
}
|
|
|
|
public listBranches(): Observable<Array<BranchInfo>> {
|
|
if (!this.branchList) {
|
|
return this.http.get<Array<BranchInfo>>('/api/entities/vc/branches',
|
|
defaultHttpOptionsFromConfig({ignoreErrors: true, ignoreLoading: false})).pipe(
|
|
catchError(() => of([] as Array<BranchInfo>)),
|
|
tap((list) => {
|
|
this.branchList = list;
|
|
})
|
|
);
|
|
} else {
|
|
return of(this.branchList);
|
|
}
|
|
}
|
|
|
|
public getEntityDataInfo(externalEntityId: EntityId,
|
|
versionId: string,
|
|
config?: RequestConfig): Observable<EntityDataInfo> {
|
|
return this.http.get<EntityDataInfo>(`/api/entities/vc/info/${versionId}/${externalEntityId.entityType}/${externalEntityId.id}`,
|
|
defaultHttpOptionsFromConfig(config));
|
|
}
|
|
|
|
public saveEntitiesVersion(request: VersionCreateRequest, config?: RequestConfig): Observable<VersionCreationResult> {
|
|
this.store.dispatch(new ActionLoadStart());
|
|
return this.http.post<string>('/api/entities/vc/version', request,
|
|
defaultHttpOptionsFromConfig({...config, ...{ignoreLoading: true}})).pipe(
|
|
switchMap((requestId) => {
|
|
return timer(0, 2000).pipe(
|
|
switchMap(() => this.getVersionCreateRequestStatus(requestId, config)),
|
|
takeWhile((res) => !res.done, true)
|
|
);
|
|
}),
|
|
finalize(() => {
|
|
const branch = request.branch;
|
|
if (this.branchList && !this.branchList.find(b => b.name === branch)) {
|
|
this.branchList = null;
|
|
}
|
|
this.store.dispatch(new ActionLoadFinish());
|
|
}),
|
|
);
|
|
}
|
|
|
|
private getVersionCreateRequestStatus(requestId: string, config?: RequestConfig): Observable<VersionCreationResult> {
|
|
return this.http.get<VersionCreationResult>(`/api/entities/vc/version/${requestId}/status`,
|
|
defaultHttpOptionsFromConfig({...config, ...{ignoreLoading: true}}));
|
|
}
|
|
|
|
public listEntityVersions(pageLink: PageLink, branch: string,
|
|
externalEntityId: EntityId,
|
|
config?: RequestConfig): Observable<PageData<EntityVersion>> {
|
|
const encodedBranch = encodeURIComponent(branch);
|
|
return this.http.get<PageData<EntityVersion>>(`/api/entities/vc/version/${externalEntityId.entityType}/${externalEntityId.id}${pageLink.toQuery()}&branch=${encodedBranch}`,
|
|
defaultHttpOptionsFromConfig(config));
|
|
}
|
|
|
|
public listEntityTypeVersions(pageLink: PageLink, branch: string,
|
|
entityType: EntityType,
|
|
config?: RequestConfig): Observable<PageData<EntityVersion>> {
|
|
const encodedBranch = encodeURIComponent(branch);
|
|
return this.http.get<PageData<EntityVersion>>(`/api/entities/vc/version/${entityType}${pageLink.toQuery()}&branch=${encodedBranch}`,
|
|
defaultHttpOptionsFromConfig(config));
|
|
}
|
|
|
|
public listVersions(pageLink: PageLink, branch: string,
|
|
config?: RequestConfig): Observable<PageData<EntityVersion>> {
|
|
const encodedBranch = encodeURIComponent(branch);
|
|
return this.http.get<PageData<EntityVersion>>(`/api/entities/vc/version${pageLink.toQuery()}&branch=${encodedBranch}`,
|
|
defaultHttpOptionsFromConfig(config));
|
|
}
|
|
|
|
public loadEntitiesVersion(request: VersionLoadRequest, config?: RequestConfig): Observable<VersionLoadResult> {
|
|
this.store.dispatch(new ActionLoadStart());
|
|
return this.http.post<string>('/api/entities/vc/entity', request,
|
|
defaultHttpOptionsFromConfig({...config, ...{ignoreLoading: true}})).pipe(
|
|
switchMap((requestId) => {
|
|
return timer(0, 2000).pipe(
|
|
switchMap(() => this.getVersionLoadRequestStatus(requestId, config)),
|
|
takeWhile((res) => !res.done, true),
|
|
);
|
|
}),
|
|
finalize(() => {
|
|
this.store.dispatch(new ActionLoadFinish());
|
|
}),
|
|
);
|
|
}
|
|
|
|
private getVersionLoadRequestStatus(requestId: string, config?: RequestConfig): Observable<VersionLoadResult> {
|
|
return this.http.get<VersionLoadResult>(`/api/entities/vc/entity/${requestId}/status`,
|
|
defaultHttpOptionsFromConfig({...config, ...{ignoreLoading: true}}));
|
|
}
|
|
|
|
public compareEntityDataToVersion(entityId: EntityId,
|
|
versionId: string,
|
|
config?: RequestConfig): Observable<EntityDataDiff> {
|
|
return this.http.get<EntityDataDiff>(`/api/entities/vc/diff/${entityId.entityType}/${entityId.id}?versionId=${versionId}`,
|
|
defaultHttpOptionsFromConfig(config));
|
|
}
|
|
|
|
public entityLoadErrorToMessage(entityLoadError: EntityLoadError): SafeHtml {
|
|
const type = entityLoadError.type;
|
|
const messageId = entityLoadErrorTranslationMap.get(type);
|
|
const messageArgs = {} as any;
|
|
switch (type) {
|
|
case EntityLoadErrorType.DEVICE_CREDENTIALS_CONFLICT:
|
|
messageArgs.entityId = entityLoadError.source.id;
|
|
break;
|
|
case EntityLoadErrorType.MISSING_REFERENCED_ENTITY:
|
|
messageArgs.sourceEntityTypeName =
|
|
(this.translate.instant(entityTypeTranslations.get(entityLoadError.source.entityType).type) as string).toLowerCase();
|
|
messageArgs.sourceEntityId = entityLoadError.source.id;
|
|
messageArgs.targetEntityTypeName =
|
|
(this.translate.instant(entityTypeTranslations.get(entityLoadError.target.entityType).type) as string).toLowerCase();
|
|
messageArgs.targetEntityId = entityLoadError.target.id;
|
|
break;
|
|
case EntityLoadErrorType.RUNTIME:
|
|
messageArgs.message = entityLoadError.message;
|
|
break;
|
|
}
|
|
return this.sanitizer.bypassSecurityTrustHtml(this.translate.instant(messageId, messageArgs));
|
|
}
|
|
}
|