Major adjustments
This commit is contained in:
parent
a291e1d2e3
commit
55e33d7f3d
@ -16,48 +16,76 @@
|
|||||||
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import {
|
import {
|
||||||
|
HttpErrorResponse,
|
||||||
HttpEvent,
|
HttpEvent,
|
||||||
HttpHandler,
|
HttpHandler,
|
||||||
HttpInterceptor,
|
HttpInterceptor,
|
||||||
HttpRequest,
|
HttpRequest,
|
||||||
HttpErrorResponse,
|
|
||||||
HttpStatusCode
|
HttpStatusCode
|
||||||
} from '@angular/common/http';
|
} from '@angular/common/http';
|
||||||
import { Observable, throwError, of } from 'rxjs';
|
import { Observable, of, throwError } from 'rxjs';
|
||||||
import { catchError, switchMap } from 'rxjs/operators';
|
import { catchError, switchMap } from 'rxjs/operators';
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
import { EntityConflictDialogComponent } from '@shared/components/dialog/entity-conflict-dialog/entity-conflict-dialog.component';
|
import {
|
||||||
import { EntityId } from '@shared/models/id/entity-id';
|
EntityConflictDialogComponent
|
||||||
|
} from '@shared/components/dialog/entity-conflict-dialog/entity-conflict-dialog.component';
|
||||||
interface ConflictedEntity { version: number; id: EntityId }
|
import { InterceptorConfigService } from '@core/services/interceptor-config.service';
|
||||||
|
import { HasId } from '@shared/models/base-data';
|
||||||
|
import { HasVersion } from '@shared/models/entity.models';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class EntityConflictInterceptor implements HttpInterceptor {
|
export class EntityConflictInterceptor implements HttpInterceptor {
|
||||||
constructor(private dialog: MatDialog) {}
|
|
||||||
|
|
||||||
intercept(request: HttpRequest<unknown & ConflictedEntity>, next: HttpHandler): Observable<HttpEvent<unknown>> {
|
constructor(
|
||||||
|
private dialog: MatDialog,
|
||||||
|
private interceptorConfigService: InterceptorConfigService
|
||||||
|
) {}
|
||||||
|
|
||||||
|
intercept(request: HttpRequest<unknown & HasId & HasVersion>, next: HttpHandler): Observable<HttpEvent<unknown>> {
|
||||||
|
if (!request.url.startsWith('/api/')) {
|
||||||
|
return next.handle(request);
|
||||||
|
}
|
||||||
|
|
||||||
return next.handle(request).pipe(
|
return next.handle(request).pipe(
|
||||||
catchError((error: HttpErrorResponse) => {
|
catchError((error: HttpErrorResponse) => {
|
||||||
if (error.status === HttpStatusCode.Conflict) {
|
if (error.status !== HttpStatusCode.Conflict) {
|
||||||
return this.resolveConflictRequest(request, error.error.message)
|
|
||||||
.pipe(switchMap(httpRequest => next.handle(httpRequest)));
|
|
||||||
} else {
|
|
||||||
return throwError(() => error);
|
return throwError(() => error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return this.handleConflictError(request, next, error);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private resolveConflictRequest(request: HttpRequest<unknown & ConflictedEntity>, message: string): Observable<HttpRequest<unknown>> {
|
private handleConflictError(
|
||||||
const dialogRef = this.dialog.open(EntityConflictDialogComponent, {data: {message, entityId: request.body.id}});
|
request: HttpRequest<unknown & HasId & HasVersion>,
|
||||||
|
next: HttpHandler,
|
||||||
|
error: HttpErrorResponse
|
||||||
|
): Observable<HttpEvent<unknown>> {
|
||||||
|
if (this.interceptorConfigService.getInterceptorConfig(request).ignoreVersionConflict) {
|
||||||
|
return next.handle(this.updateRequestVersion(request));
|
||||||
|
}
|
||||||
|
|
||||||
return dialogRef.afterClosed().pipe(
|
return this.openConflictDialog(request, error.error.message).pipe(
|
||||||
switchMap(result => {
|
switchMap(result => {
|
||||||
if (result) {
|
if (result) {
|
||||||
request.body.version = null;
|
return next.handle(this.updateRequestVersion(request));
|
||||||
}
|
}
|
||||||
return of(request);
|
return of(null);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private updateRequestVersion(request: HttpRequest<unknown & HasId & HasVersion>): HttpRequest<unknown & HasId & HasVersion> {
|
||||||
|
const body = { ...request.body, version: null };
|
||||||
|
return request.clone({ body });
|
||||||
|
}
|
||||||
|
|
||||||
|
private openConflictDialog(request: HttpRequest<unknown & HasId & HasVersion>, message: string): Observable<boolean> {
|
||||||
|
const dialogRef = this.dialog.open(EntityConflictDialogComponent, {
|
||||||
|
data: { message, entity: request.body }
|
||||||
|
});
|
||||||
|
|
||||||
|
return dialogRef.afterClosed();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,10 +16,9 @@
|
|||||||
|
|
||||||
import { HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
|
import { HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
|
||||||
import { Observable } from 'rxjs/internal/Observable';
|
import { Observable } from 'rxjs/internal/Observable';
|
||||||
import { Inject, Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { AuthService } from '@core/auth/auth.service';
|
import { AuthService } from '@core/auth/auth.service';
|
||||||
import { Constants } from '@shared/models/constants';
|
import { Constants } from '@shared/models/constants';
|
||||||
import { InterceptorHttpParams } from './interceptor-http-params';
|
|
||||||
import { catchError, delay, finalize, mergeMap, switchMap } from 'rxjs/operators';
|
import { catchError, delay, finalize, mergeMap, switchMap } from 'rxjs/operators';
|
||||||
import { of, throwError } from 'rxjs';
|
import { of, throwError } from 'rxjs';
|
||||||
import { InterceptorConfig } from './interceptor-config';
|
import { InterceptorConfig } from './interceptor-config';
|
||||||
@ -30,6 +29,7 @@ import { ActionNotificationShow } from '@app/core/notification/notification.acti
|
|||||||
import { DialogService } from '@core/services/dialog.service';
|
import { DialogService } from '@core/services/dialog.service';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { parseHttpErrorMessage } from '@core/utils';
|
import { parseHttpErrorMessage } from '@core/utils';
|
||||||
|
import { InterceptorConfigService } from '@core/services/interceptor-config.service';
|
||||||
|
|
||||||
const tmpHeaders = {};
|
const tmpHeaders = {};
|
||||||
|
|
||||||
@ -39,22 +39,19 @@ export class GlobalHttpInterceptor implements HttpInterceptor {
|
|||||||
private AUTH_SCHEME = 'Bearer ';
|
private AUTH_SCHEME = 'Bearer ';
|
||||||
private AUTH_HEADER_NAME = 'X-Authorization';
|
private AUTH_HEADER_NAME = 'X-Authorization';
|
||||||
|
|
||||||
private internalUrlPrefixes = [
|
|
||||||
'/api/auth/token',
|
|
||||||
'/api/rpc'
|
|
||||||
];
|
|
||||||
|
|
||||||
private activeRequests = 0;
|
private activeRequests = 0;
|
||||||
|
|
||||||
constructor(@Inject(Store) private store: Store<AppState>,
|
constructor(
|
||||||
@Inject(DialogService) private dialogService: DialogService,
|
private store: Store<AppState>,
|
||||||
@Inject(TranslateService) private translate: TranslateService,
|
private dialogService: DialogService,
|
||||||
@Inject(AuthService) private authService: AuthService) {
|
private translate: TranslateService,
|
||||||
}
|
private authService: AuthService,
|
||||||
|
private interceptorConfigService: InterceptorConfigService
|
||||||
|
) {}
|
||||||
|
|
||||||
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
||||||
if (req.url.startsWith('/api/')) {
|
if (req.url.startsWith('/api/')) {
|
||||||
const config = this.getInterceptorConfig(req);
|
const config = this.interceptorConfigService.getInterceptorConfig(req);
|
||||||
this.updateLoadingState(config, true);
|
this.updateLoadingState(config, true);
|
||||||
let observable$: Observable<HttpEvent<any>>;
|
let observable$: Observable<HttpEvent<any>>;
|
||||||
if (this.isTokenBasedAuthEntryPoint(req.url)) {
|
if (this.isTokenBasedAuthEntryPoint(req.url)) {
|
||||||
@ -98,7 +95,7 @@ export class GlobalHttpInterceptor implements HttpInterceptor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private handleResponseError(req: HttpRequest<any>, next: HttpHandler, errorResponse: HttpErrorResponse): Observable<HttpEvent<any>> {
|
private handleResponseError(req: HttpRequest<any>, next: HttpHandler, errorResponse: HttpErrorResponse): Observable<HttpEvent<any>> {
|
||||||
const config = this.getInterceptorConfig(req);
|
const config = this.interceptorConfigService.getInterceptorConfig(req);
|
||||||
let unhandled = false;
|
let unhandled = false;
|
||||||
const ignoreErrors = config.ignoreErrors;
|
const ignoreErrors = config.ignoreErrors;
|
||||||
const resendRequest = config.resendRequest;
|
const resendRequest = config.resendRequest;
|
||||||
@ -171,15 +168,6 @@ export class GlobalHttpInterceptor implements HttpInterceptor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private isInternalUrlPrefix(url: string): boolean {
|
|
||||||
for (const index in this.internalUrlPrefixes) {
|
|
||||||
if (url.startsWith(this.internalUrlPrefixes[index])) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private isTokenBasedAuthEntryPoint(url: string): boolean {
|
private isTokenBasedAuthEntryPoint(url: string): boolean {
|
||||||
return url.startsWith('/api/') &&
|
return url.startsWith('/api/') &&
|
||||||
!url.startsWith(Constants.entryPoints.login) &&
|
!url.startsWith(Constants.entryPoints.login) &&
|
||||||
@ -202,19 +190,6 @@ export class GlobalHttpInterceptor implements HttpInterceptor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private getInterceptorConfig(req: HttpRequest<any>): InterceptorConfig {
|
|
||||||
let config: InterceptorConfig;
|
|
||||||
if (req.params && req.params instanceof InterceptorHttpParams) {
|
|
||||||
config = (req.params as InterceptorHttpParams).interceptorConfig;
|
|
||||||
} else {
|
|
||||||
config = new InterceptorConfig(false, false);
|
|
||||||
}
|
|
||||||
if (this.isInternalUrlPrefix(req.url)) {
|
|
||||||
config.ignoreLoading = true;
|
|
||||||
}
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
|
|
||||||
private showError(error: string, timeout: number = 0) {
|
private showError(error: string, timeout: number = 0) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.store.dispatch(new ActionNotificationShow({message: error, type: 'error'}));
|
this.store.dispatch(new ActionNotificationShow({message: error, type: 'error'}));
|
||||||
|
|||||||
@ -17,5 +17,6 @@
|
|||||||
export class InterceptorConfig {
|
export class InterceptorConfig {
|
||||||
constructor(public ignoreLoading: boolean = false,
|
constructor(public ignoreLoading: boolean = false,
|
||||||
public ignoreErrors: boolean = false,
|
public ignoreErrors: boolean = false,
|
||||||
|
public ignoreVersionConflict: boolean = false,
|
||||||
public resendRequest: boolean = false) {}
|
public resendRequest: boolean = false) {}
|
||||||
}
|
}
|
||||||
|
|||||||
53
ui-ngx/src/app/core/services/interceptor-config.service.ts
Normal file
53
ui-ngx/src/app/core/services/interceptor-config.service.ts
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
///
|
||||||
|
/// Copyright © 2016-2024 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 { HttpRequest } from '@angular/common/http';
|
||||||
|
import { InterceptorConfig } from '@core/interceptors/interceptor-config';
|
||||||
|
import { InterceptorHttpParams } from '@core/interceptors/interceptor-http-params';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class InterceptorConfigService {
|
||||||
|
|
||||||
|
private readonly internalUrlPrefixes = [
|
||||||
|
'/api/auth/token',
|
||||||
|
'/api/rpc'
|
||||||
|
];
|
||||||
|
|
||||||
|
getInterceptorConfig(req: HttpRequest<unknown>): InterceptorConfig {
|
||||||
|
let config: InterceptorConfig;
|
||||||
|
if (req.params && req.params instanceof InterceptorHttpParams) {
|
||||||
|
config = (req.params as InterceptorHttpParams).interceptorConfig;
|
||||||
|
} else {
|
||||||
|
config = new InterceptorConfig();
|
||||||
|
}
|
||||||
|
if (this.isInternalUrlPrefix(req.url)) {
|
||||||
|
config.ignoreLoading = true;
|
||||||
|
}
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
private isInternalUrlPrefix(url: string): boolean {
|
||||||
|
for (const prefix of this.internalUrlPrefixes) {
|
||||||
|
if (url.startsWith(prefix)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -27,9 +27,9 @@
|
|||||||
<div mat-dialog-content>
|
<div mat-dialog-content>
|
||||||
<div class="message-container">
|
<div class="message-container">
|
||||||
<span>{{ data.message }}.</span>
|
<span>{{ data.message }}.</span>
|
||||||
<span *ngIf="ExportableEntityTypes.includes(data.entityId.entityType)">
|
<span>
|
||||||
{{ 'entity.version-conflict.link' | translate:
|
{{ 'entity.version-conflict.link' | translate:
|
||||||
{ entityType: (entityTypeTranslations.get(data.entityId.entityType).type | translate) }
|
{ entityType: (entityTypeTranslations.get(data.entity.id.entityType).type | translate) }
|
||||||
}}
|
}}
|
||||||
<a class="cursor-pointer" (click)="onLinkClick($event)">{{ 'entity.link' | translate }}</a>.
|
<a class="cursor-pointer" (click)="onLinkClick($event)">{{ 'entity.link' | translate }}</a>.
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@ -18,14 +18,13 @@ import { Component, Inject } from '@angular/core';
|
|||||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||||
import { SharedModule } from '@shared/shared.module';
|
import { SharedModule } from '@shared/shared.module';
|
||||||
import { ImportExportService } from '@shared/import-export/import-export.service';
|
import { ImportExportService } from '@shared/import-export/import-export.service';
|
||||||
import { ExportableEntityTypes } from '@shared/import-export/import-export.models';
|
|
||||||
import { EntityId } from '@shared/models/id/entity-id';
|
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { EntityType, entityTypeTranslations } from '@shared/models/entity-type.models';
|
import { entityTypeTranslations } from '@shared/models/entity-type.models';
|
||||||
|
import { EntityInfoData } from '@shared/models/entity.models';
|
||||||
|
|
||||||
interface EntityConflictDialogData {
|
interface EntityConflictDialogData {
|
||||||
message: string;
|
message: string;
|
||||||
entityId: EntityId & {entityType: EntityType};
|
entity: EntityInfoData;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -39,7 +38,6 @@ interface EntityConflictDialogData {
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class EntityConflictDialogComponent {
|
export class EntityConflictDialogComponent {
|
||||||
readonly ExportableEntityTypes = ExportableEntityTypes;
|
|
||||||
readonly entityTypeTranslations = entityTypeTranslations;
|
readonly entityTypeTranslations = entityTypeTranslations;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@ -58,6 +56,6 @@ export class EntityConflictDialogComponent {
|
|||||||
|
|
||||||
onLinkClick(event: MouseEvent): void {
|
onLinkClick(event: MouseEvent): void {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
this.importExportService.exportEntity(this.data.entityId);
|
this.importExportService.exportEntity(this.data.entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,16 +17,6 @@
|
|||||||
import { Widget, WidgetTypeDetails } from '@app/shared/models/widget.models';
|
import { Widget, WidgetTypeDetails } from '@app/shared/models/widget.models';
|
||||||
import { DashboardLayoutId } from '@shared/models/dashboard.models';
|
import { DashboardLayoutId } from '@shared/models/dashboard.models';
|
||||||
import { WidgetsBundle } from '@shared/models/widgets-bundle.model';
|
import { WidgetsBundle } from '@shared/models/widgets-bundle.model';
|
||||||
import { EntityType } from '@shared/models/entity-type.models';
|
|
||||||
|
|
||||||
export const ExportableEntityTypes = [
|
|
||||||
EntityType.DEVICE_PROFILE,
|
|
||||||
EntityType.ASSET_PROFILE,
|
|
||||||
EntityType.RULE_CHAIN,
|
|
||||||
EntityType.DASHBOARD,
|
|
||||||
EntityType.WIDGET_TYPE,
|
|
||||||
EntityType.WIDGETS_BUNDLE
|
|
||||||
];
|
|
||||||
|
|
||||||
export interface ImportWidgetResult {
|
export interface ImportWidgetResult {
|
||||||
widget: Widget;
|
widget: Widget;
|
||||||
|
|||||||
@ -55,7 +55,7 @@ import { EntityType } from '@shared/models/entity-type.models';
|
|||||||
import { UtilsService } from '@core/services/utils.service';
|
import { UtilsService } from '@core/services/utils.service';
|
||||||
import { WidgetService } from '@core/http/widget.service';
|
import { WidgetService } from '@core/http/widget.service';
|
||||||
import { WidgetsBundle } from '@shared/models/widgets-bundle.model';
|
import { WidgetsBundle } from '@shared/models/widgets-bundle.model';
|
||||||
import { ImportEntitiesResultInfo, ImportEntityData } from '@shared/models/entity.models';
|
import { EntityInfoData, ImportEntitiesResultInfo, ImportEntityData } from '@shared/models/entity.models';
|
||||||
import { RequestConfig } from '@core/http/http-utils';
|
import { RequestConfig } from '@core/http/http-utils';
|
||||||
import { RuleChain, RuleChainImport, RuleChainMetaData, RuleChainType } from '@shared/models/rule-chain.models';
|
import { RuleChain, RuleChainImport, RuleChainMetaData, RuleChainType } from '@shared/models/rule-chain.models';
|
||||||
import { RuleChainService } from '@core/http/rule-chain.service';
|
import { RuleChainService } from '@core/http/rule-chain.service';
|
||||||
@ -79,7 +79,7 @@ import { ImageService } from '@core/http/image.service';
|
|||||||
import { ImageExportData, ImageResourceInfo, ImageResourceType } from '@shared/models/resource.models';
|
import { ImageExportData, ImageResourceInfo, ImageResourceType } from '@shared/models/resource.models';
|
||||||
import { selectUserSettingsProperty } from '@core/auth/auth.selectors';
|
import { selectUserSettingsProperty } from '@core/auth/auth.selectors';
|
||||||
import { ActionPreferencesPutUserSettings } from '@core/auth/auth.actions';
|
import { ActionPreferencesPutUserSettings } from '@core/auth/auth.actions';
|
||||||
import { ExportableEntity } from '@shared/models/base-data';
|
import { ExportableEntity, HasId } from '@shared/models/base-data';
|
||||||
import { EntityId } from '@shared/models/id/entity-id';
|
import { EntityId } from '@shared/models/id/entity-id';
|
||||||
|
|
||||||
export type editMissingAliasesFunction = (widgets: Array<Widget>, isSingleWidget: boolean,
|
export type editMissingAliasesFunction = (widgets: Array<Widget>, isSingleWidget: boolean,
|
||||||
@ -380,29 +380,33 @@ export class ImportExportService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public exportEntity(entityId: EntityId): void {
|
public exportEntity(entityData: EntityInfoData): void {
|
||||||
switch (entityId.entityType) {
|
let preparedData;
|
||||||
|
switch (entityData.id.entityType) {
|
||||||
case EntityType.DEVICE_PROFILE:
|
case EntityType.DEVICE_PROFILE:
|
||||||
this.exportDeviceProfile(entityId.id);
|
|
||||||
break;
|
|
||||||
case EntityType.ASSET_PROFILE:
|
case EntityType.ASSET_PROFILE:
|
||||||
this.exportAssetProfile(entityId.id);
|
preparedData = this.prepareProfileExport(entityData as DeviceProfile | AssetProfile);
|
||||||
break;
|
break;
|
||||||
case EntityType.RULE_CHAIN:
|
case EntityType.RULE_CHAIN:
|
||||||
this.exportRuleChain(entityId.id);
|
this.ruleChainService.getRuleChainMetadata(entityData.id.id)
|
||||||
break;
|
.pipe(
|
||||||
|
take(1),
|
||||||
|
map((ruleChainMetaData) => {
|
||||||
|
const ruleChainExport: RuleChainImport = {
|
||||||
|
ruleChain: this.prepareRuleChain(entityData as RuleChain),
|
||||||
|
metadata: this.prepareRuleChainMetaData(ruleChainMetaData)
|
||||||
|
};
|
||||||
|
return ruleChainExport;
|
||||||
|
}))
|
||||||
|
.subscribe(ruleChainData => this.exportToPc(ruleChainData, entityData.name));
|
||||||
|
return;
|
||||||
case EntityType.DASHBOARD:
|
case EntityType.DASHBOARD:
|
||||||
this.exportDashboard(entityId.id);
|
preparedData = this.prepareDashboardExport(entityData as Dashboard);
|
||||||
break;
|
|
||||||
case EntityType.WIDGET_TYPE:
|
|
||||||
this.exportWidgetType(entityId.id);
|
|
||||||
break;
|
|
||||||
case EntityType.WIDGETS_BUNDLE:
|
|
||||||
this.exportWidgetsBundle(entityId.id);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throwError(() => 'Not supported Entity Type');
|
preparedData = this.prepareExport(entityData);
|
||||||
}
|
}
|
||||||
|
this.exportToPc(preparedData, entityData.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
private exportWidgetsBundleWithWidgetTypes(widgetsBundle: WidgetsBundle) {
|
private exportWidgetsBundleWithWidgetTypes(widgetsBundle: WidgetsBundle) {
|
||||||
@ -1133,6 +1137,9 @@ export class ImportExportService {
|
|||||||
if (isDefined(exportedData.externalId)) {
|
if (isDefined(exportedData.externalId)) {
|
||||||
delete exportedData.externalId;
|
delete exportedData.externalId;
|
||||||
}
|
}
|
||||||
|
if (isDefined(exportedData.version)) {
|
||||||
|
delete exportedData.version;
|
||||||
|
}
|
||||||
return exportedData;
|
return exportedData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -22,9 +22,9 @@ import { EntitySearchQuery } from '@shared/models/relation.models';
|
|||||||
import { AssetProfileId } from '@shared/models/id/asset-profile-id';
|
import { AssetProfileId } from '@shared/models/id/asset-profile-id';
|
||||||
import { RuleChainId } from '@shared/models/id/rule-chain-id';
|
import { RuleChainId } from '@shared/models/id/rule-chain-id';
|
||||||
import { DashboardId } from '@shared/models/id/dashboard-id';
|
import { DashboardId } from '@shared/models/id/dashboard-id';
|
||||||
import { EntityInfoData, HasTenantId } from '@shared/models/entity.models';
|
import { EntityInfoData, HasTenantId, HasVersion } from '@shared/models/entity.models';
|
||||||
|
|
||||||
export interface AssetProfile extends BaseData<AssetProfileId>, HasTenantId, ExportableEntity<AssetProfileId> {
|
export interface AssetProfile extends BaseData<AssetProfileId>, HasTenantId, HasVersion, ExportableEntity<AssetProfileId> {
|
||||||
tenantId?: TenantId;
|
tenantId?: TenantId;
|
||||||
name: string;
|
name: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
@ -42,7 +42,7 @@ export interface AssetProfileInfo extends EntityInfoData {
|
|||||||
defaultDashboardId?: DashboardId;
|
defaultDashboardId?: DashboardId;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Asset extends BaseData<AssetId>, HasTenantId, ExportableEntity<AssetId> {
|
export interface Asset extends BaseData<AssetId>, HasTenantId, HasVersion, ExportableEntity<AssetId> {
|
||||||
tenantId?: TenantId;
|
tenantId?: TenantId;
|
||||||
customerId?: CustomerId;
|
customerId?: CustomerId;
|
||||||
name: string;
|
name: string;
|
||||||
|
|||||||
@ -18,9 +18,9 @@ import { CustomerId } from '@shared/models/id/customer-id';
|
|||||||
import { ContactBased } from '@shared/models/contact-based.model';
|
import { ContactBased } from '@shared/models/contact-based.model';
|
||||||
import { TenantId } from './id/tenant-id';
|
import { TenantId } from './id/tenant-id';
|
||||||
import { ExportableEntity } from '@shared/models/base-data';
|
import { ExportableEntity } from '@shared/models/base-data';
|
||||||
import { HasTenantId } from '@shared/models/entity.models';
|
import { HasTenantId, HasVersion } from '@shared/models/entity.models';
|
||||||
|
|
||||||
export interface Customer extends ContactBased<CustomerId>, HasTenantId, ExportableEntity<CustomerId> {
|
export interface Customer extends ContactBased<CustomerId>, HasTenantId, HasVersion, ExportableEntity<CustomerId> {
|
||||||
tenantId: TenantId;
|
tenantId: TenantId;
|
||||||
title: string;
|
title: string;
|
||||||
additionalInfo?: any;
|
additionalInfo?: any;
|
||||||
|
|||||||
@ -23,9 +23,9 @@ import { Timewindow } from '@shared/models/time/time.models';
|
|||||||
import { EntityAliases } from './alias.models';
|
import { EntityAliases } from './alias.models';
|
||||||
import { Filters } from '@shared/models/query/query.models';
|
import { Filters } from '@shared/models/query/query.models';
|
||||||
import { MatDialogRef } from '@angular/material/dialog';
|
import { MatDialogRef } from '@angular/material/dialog';
|
||||||
import { HasTenantId } from '@shared/models/entity.models';
|
import { HasTenantId, HasVersion } from '@shared/models/entity.models';
|
||||||
|
|
||||||
export interface DashboardInfo extends BaseData<DashboardId>, HasTenantId, ExportableEntity<DashboardId> {
|
export interface DashboardInfo extends BaseData<DashboardId>, HasTenantId, HasVersion, ExportableEntity<DashboardId> {
|
||||||
tenantId?: TenantId;
|
tenantId?: TenantId;
|
||||||
title?: string;
|
title?: string;
|
||||||
image?: string;
|
image?: string;
|
||||||
|
|||||||
@ -22,7 +22,7 @@ import { DeviceCredentialsId } from '@shared/models/id/device-credentials-id';
|
|||||||
import { EntitySearchQuery } from '@shared/models/relation.models';
|
import { EntitySearchQuery } from '@shared/models/relation.models';
|
||||||
import { DeviceProfileId } from '@shared/models/id/device-profile-id';
|
import { DeviceProfileId } from '@shared/models/id/device-profile-id';
|
||||||
import { RuleChainId } from '@shared/models/id/rule-chain-id';
|
import { RuleChainId } from '@shared/models/id/rule-chain-id';
|
||||||
import { EntityInfoData, HasTenantId } from '@shared/models/entity.models';
|
import { EntityInfoData, HasTenantId, HasVersion } from '@shared/models/entity.models';
|
||||||
import { FilterPredicateValue, KeyFilter } from '@shared/models/query/query.models';
|
import { FilterPredicateValue, KeyFilter } from '@shared/models/query/query.models';
|
||||||
import { TimeUnit } from '@shared/models/time/time.models';
|
import { TimeUnit } from '@shared/models/time/time.models';
|
||||||
import * as _moment from 'moment';
|
import * as _moment from 'moment';
|
||||||
@ -584,7 +584,7 @@ export interface DeviceProfileData {
|
|||||||
provisionConfiguration?: DeviceProvisionConfiguration;
|
provisionConfiguration?: DeviceProvisionConfiguration;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DeviceProfile extends BaseData<DeviceProfileId>, HasTenantId, ExportableEntity<DeviceProfileId> {
|
export interface DeviceProfile extends BaseData<DeviceProfileId>, HasTenantId, HasVersion, ExportableEntity<DeviceProfileId> {
|
||||||
tenantId?: TenantId;
|
tenantId?: TenantId;
|
||||||
name: string;
|
name: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
@ -711,7 +711,7 @@ export interface DeviceData {
|
|||||||
transportConfiguration: DeviceTransportConfiguration;
|
transportConfiguration: DeviceTransportConfiguration;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Device extends BaseData<DeviceId>, HasTenantId, ExportableEntity<DeviceId> {
|
export interface Device extends BaseData<DeviceId>, HasTenantId, HasVersion, ExportableEntity<DeviceId> {
|
||||||
tenantId?: TenantId;
|
tenantId?: TenantId;
|
||||||
customerId?: CustomerId;
|
customerId?: CustomerId;
|
||||||
name: string;
|
name: string;
|
||||||
@ -801,7 +801,7 @@ export const credentialTypesByTransportType = new Map<DeviceTransportType, Devic
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
export interface DeviceCredentials extends BaseData<DeviceCredentialsId> {
|
export interface DeviceCredentials extends BaseData<DeviceCredentialsId>, HasTenantId {
|
||||||
deviceId: DeviceId;
|
deviceId: DeviceId;
|
||||||
credentialsType: DeviceCredentialsType;
|
credentialsType: DeviceCredentialsType;
|
||||||
credentialsId: string;
|
credentialsId: string;
|
||||||
|
|||||||
@ -22,9 +22,9 @@ import { EntitySearchQuery } from '@shared/models/relation.models';
|
|||||||
import { RuleChainId } from '@shared/models/id/rule-chain-id';
|
import { RuleChainId } from '@shared/models/id/rule-chain-id';
|
||||||
import { BaseEventBody } from '@shared/models/event.models';
|
import { BaseEventBody } from '@shared/models/event.models';
|
||||||
import { EventId } from '@shared/models/id/event-id';
|
import { EventId } from '@shared/models/id/event-id';
|
||||||
import { HasTenantId } from '@shared/models/entity.models';
|
import { HasTenantId, HasVersion } from '@shared/models/entity.models';
|
||||||
|
|
||||||
export interface Edge extends BaseData<EdgeId>, HasTenantId {
|
export interface Edge extends BaseData<EdgeId>, HasTenantId, HasVersion {
|
||||||
tenantId?: TenantId;
|
tenantId?: TenantId;
|
||||||
customerId?: CustomerId;
|
customerId?: CustomerId;
|
||||||
name: string;
|
name: string;
|
||||||
|
|||||||
@ -20,7 +20,7 @@ import { CustomerId } from '@shared/models/id/customer-id';
|
|||||||
import { EntityViewId } from '@shared/models/id/entity-view-id';
|
import { EntityViewId } from '@shared/models/id/entity-view-id';
|
||||||
import { EntityId } from '@shared/models/id/entity-id';
|
import { EntityId } from '@shared/models/id/entity-id';
|
||||||
import { EntitySearchQuery } from '@shared/models/relation.models';
|
import { EntitySearchQuery } from '@shared/models/relation.models';
|
||||||
import { HasTenantId } from '@shared/models/entity.models';
|
import { HasTenantId, HasVersion } from '@shared/models/entity.models';
|
||||||
|
|
||||||
export interface AttributesEntityView {
|
export interface AttributesEntityView {
|
||||||
cs: Array<string>;
|
cs: Array<string>;
|
||||||
@ -33,7 +33,7 @@ export interface TelemetryEntityView {
|
|||||||
attributes: AttributesEntityView;
|
attributes: AttributesEntityView;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EntityView extends BaseData<EntityViewId>, HasTenantId, ExportableEntity<EntityViewId> {
|
export interface EntityView extends BaseData<EntityViewId>, HasTenantId, HasVersion, ExportableEntity<EntityViewId> {
|
||||||
tenantId: TenantId;
|
tenantId: TenantId;
|
||||||
customerId: CustomerId;
|
customerId: CustomerId;
|
||||||
entityId: EntityId;
|
entityId: EntityId;
|
||||||
|
|||||||
@ -187,3 +187,7 @@ export const entityFields: {[fieldName: string]: EntityField} = {
|
|||||||
export interface HasTenantId {
|
export interface HasTenantId {
|
||||||
tenantId?: TenantId;
|
tenantId?: TenantId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface HasVersion {
|
||||||
|
version?: number;
|
||||||
|
}
|
||||||
|
|||||||
@ -20,9 +20,9 @@ import { RuleChainId } from '@shared/models/id/rule-chain-id';
|
|||||||
import { RuleNodeId } from '@shared/models/id/rule-node-id';
|
import { RuleNodeId } from '@shared/models/id/rule-node-id';
|
||||||
import { RuleNode, RuleNodeComponentDescriptor, RuleNodeType } from '@shared/models/rule-node.models';
|
import { RuleNode, RuleNodeComponentDescriptor, RuleNodeType } from '@shared/models/rule-node.models';
|
||||||
import { ComponentClusteringMode, ComponentType } from '@shared/models/component-descriptor.models';
|
import { ComponentClusteringMode, ComponentType } from '@shared/models/component-descriptor.models';
|
||||||
import { HasTenantId } from '@shared/models/entity.models';
|
import { HasTenantId, HasVersion } from '@shared/models/entity.models';
|
||||||
|
|
||||||
export interface RuleChain extends BaseData<RuleChainId>, HasTenantId, ExportableEntity<RuleChainId> {
|
export interface RuleChain extends BaseData<RuleChainId>, HasTenantId, HasVersion, ExportableEntity<RuleChainId> {
|
||||||
tenantId: TenantId;
|
tenantId: TenantId;
|
||||||
name: string;
|
name: string;
|
||||||
firstRuleNodeId: RuleNodeId;
|
firstRuleNodeId: RuleNodeId;
|
||||||
|
|||||||
@ -17,9 +17,9 @@
|
|||||||
import { BaseData, ExportableEntity } from '@shared/models/base-data';
|
import { BaseData, ExportableEntity } from '@shared/models/base-data';
|
||||||
import { TenantId } from '@shared/models/id/tenant-id';
|
import { TenantId } from '@shared/models/id/tenant-id';
|
||||||
import { WidgetsBundleId } from '@shared/models/id/widgets-bundle-id';
|
import { WidgetsBundleId } from '@shared/models/id/widgets-bundle-id';
|
||||||
import { HasTenantId } from '@shared/models/entity.models';
|
import { HasTenantId, HasVersion } from '@shared/models/entity.models';
|
||||||
|
|
||||||
export interface WidgetsBundle extends BaseData<WidgetsBundleId>, HasTenantId, ExportableEntity<WidgetsBundleId> {
|
export interface WidgetsBundle extends BaseData<WidgetsBundleId>, HasTenantId, HasVersion, ExportableEntity<WidgetsBundleId> {
|
||||||
tenantId: TenantId;
|
tenantId: TenantId;
|
||||||
alias: string;
|
alias: string;
|
||||||
title: string;
|
title: string;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user