added implementation for dashboards and widget edit; added widget bundle export
This commit is contained in:
parent
83c12d3b4b
commit
bcf28c94e9
@ -185,8 +185,9 @@ export class WidgetService {
|
||||
public saveWidgetTypeDetails(widgetInfo: WidgetInfo,
|
||||
id: WidgetTypeId,
|
||||
createdTime: number,
|
||||
version: number,
|
||||
config?: RequestConfig): Observable<WidgetTypeDetails> {
|
||||
const widgetTypeDetails = toWidgetTypeDetails(widgetInfo, id, undefined, createdTime);
|
||||
const widgetTypeDetails = toWidgetTypeDetails(widgetInfo, id, undefined, createdTime, version);
|
||||
return this.http.post<WidgetTypeDetails>('/api/widgetType', widgetTypeDetails,
|
||||
defaultHttpOptionsFromConfig(config)).pipe(
|
||||
tap((savedWidgetType) => {
|
||||
|
||||
@ -146,7 +146,7 @@ import { IAliasController } from '@core/api/widget-api.models';
|
||||
import { MatButton } from '@angular/material/button';
|
||||
import { VersionControlComponent } from '@home/components/vc/version-control.component';
|
||||
import { TbPopoverService } from '@shared/components/popover.service';
|
||||
import { map, tap } from 'rxjs/operators';
|
||||
import { catchError, map, tap } from 'rxjs/operators';
|
||||
import { LayoutFixedSize, LayoutWidthType } from '@home/components/dashboard-page/layout/layout.models';
|
||||
import { TbPopoverComponent } from '@shared/components/popover.component';
|
||||
import { ResizeObserver } from '@juggle/resize-observer';
|
||||
@ -1027,7 +1027,6 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC
|
||||
|
||||
public saveDashboard() {
|
||||
this.translatedDashboardTitle = this.getTranslatedDashboardTitle();
|
||||
this.setEditMode(false, false);
|
||||
this.notifyDashboardUpdated();
|
||||
}
|
||||
|
||||
@ -1146,7 +1145,15 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC
|
||||
};
|
||||
this.window.parent.postMessage(JSON.stringify(message), '*');
|
||||
} else {
|
||||
this.dashboardService.saveDashboard(this.dashboard).subscribe();
|
||||
this.dashboardService.saveDashboard(this.dashboard).pipe(
|
||||
catchError(() => {
|
||||
this.setEditMode(false, true);
|
||||
return of(null);
|
||||
})
|
||||
).subscribe(() => {
|
||||
this.dashboard.version = this.dashboard.version + 1;
|
||||
this.setEditMode(false, false);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -44,7 +44,7 @@ import { Observable, of, ReplaySubject, Subscription } from 'rxjs';
|
||||
import { MatTab, MatTabGroup } from '@angular/material/tabs';
|
||||
import { EntityTabsComponent } from '@home/components/entity/entity-tabs.component';
|
||||
import { deepClone, mergeDeep } from '@core/utils';
|
||||
import { catchError, take } from 'rxjs/operators';
|
||||
import { catchError } from 'rxjs/operators';
|
||||
|
||||
@Component({
|
||||
selector: 'tb-entity-details-panel',
|
||||
@ -290,7 +290,6 @@ export class EntityDetailsPanelComponent extends PageComponent implements AfterV
|
||||
}
|
||||
this.entitiesTableConfig.saveEntity(editingEntity, this.editingEntity)
|
||||
.pipe(
|
||||
take(1),
|
||||
catchError(() => of(this.entity))
|
||||
)
|
||||
.subscribe(
|
||||
|
||||
@ -113,7 +113,7 @@ export class WidgetComponentService {
|
||||
hasBasicMode: this.utils.editWidgetInfo.hasBasicMode,
|
||||
basicModeDirective: this.utils.editWidgetInfo.basicModeDirective,
|
||||
defaultConfig: this.utils.editWidgetInfo.defaultConfig
|
||||
}, new WidgetTypeId('1'), new TenantId( NULL_UUID ), undefined
|
||||
}, new WidgetTypeId('1'), new TenantId( NULL_UUID ), undefined, null
|
||||
);
|
||||
}
|
||||
const initSubject = new ReplaySubject<void>();
|
||||
|
||||
@ -665,7 +665,7 @@ export const detailsToWidgetInfo = (widgetTypeDetailsEntity: WidgetTypeDetails):
|
||||
};
|
||||
|
||||
export const toWidgetType = (widgetInfo: WidgetInfo, id: WidgetTypeId, tenantId: TenantId,
|
||||
createdTime: number): WidgetType => {
|
||||
createdTime: number, version: number): WidgetType => {
|
||||
const descriptor: WidgetTypeDescriptor = {
|
||||
type: widgetInfo.type,
|
||||
sizeX: widgetInfo.sizeX,
|
||||
@ -688,6 +688,7 @@ export const toWidgetType = (widgetInfo: WidgetInfo, id: WidgetTypeId, tenantId:
|
||||
id,
|
||||
tenantId,
|
||||
createdTime,
|
||||
version,
|
||||
fqn: widgetTypeFqn(widgetInfo.fullFqn),
|
||||
name: widgetInfo.widgetName,
|
||||
deprecated: widgetInfo.deprecated,
|
||||
@ -697,8 +698,8 @@ export const toWidgetType = (widgetInfo: WidgetInfo, id: WidgetTypeId, tenantId:
|
||||
};
|
||||
|
||||
export const toWidgetTypeDetails = (widgetInfo: WidgetInfo, id: WidgetTypeId, tenantId: TenantId,
|
||||
createdTime: number): WidgetTypeDetails => {
|
||||
const widgetTypeEntity = toWidgetType(widgetInfo, id, tenantId, createdTime);
|
||||
createdTime: number, version: number): WidgetTypeDetails => {
|
||||
const widgetTypeEntity = toWidgetType(widgetInfo, id, tenantId, createdTime, version);
|
||||
return {
|
||||
...widgetTypeEntity,
|
||||
description: widgetInfo.description,
|
||||
|
||||
@ -63,7 +63,7 @@ import { forkJoin, mergeMap, of, Subscription } from 'rxjs';
|
||||
import { ResizeObserver } from '@juggle/resize-observer';
|
||||
import { widgetEditorCompleter } from '@home/pages/widget/widget-editor.models';
|
||||
import { Observable } from 'rxjs/internal/Observable';
|
||||
import { map, tap } from 'rxjs/operators';
|
||||
import { catchError, map, tap } from 'rxjs/operators';
|
||||
import { beautifyCss, beautifyHtml, beautifyJs } from '@shared/models/beautify.models';
|
||||
import Timeout = NodeJS.Timeout;
|
||||
|
||||
@ -569,9 +569,12 @@ export class WidgetEditorComponent extends PageComponent implements OnInit, OnDe
|
||||
|
||||
private commitSaveWidget() {
|
||||
const id = (this.widgetTypeDetails && this.widgetTypeDetails.id) ? this.widgetTypeDetails.id : undefined;
|
||||
const version = this.widgetTypeDetails?.version ?? null;
|
||||
const createdTime = (this.widgetTypeDetails && this.widgetTypeDetails.createdTime) ? this.widgetTypeDetails.createdTime : undefined;
|
||||
this.widgetService.saveWidgetTypeDetails(this.widget, id, createdTime).pipe(
|
||||
this.saveWidgetPending = false;
|
||||
this.widgetService.saveWidgetTypeDetails(this.widget, id, createdTime, version).pipe(
|
||||
mergeMap((widgetTypeDetails) => {
|
||||
this.saveWidgetPending = true;
|
||||
const widgetsBundleId = this.route.snapshot.params.widgetsBundleId as string;
|
||||
if (widgetsBundleId && !id) {
|
||||
return this.widgetService.addWidgetFqnToWidgetBundle(widgetsBundleId, widgetTypeDetails.fqn).pipe(
|
||||
@ -579,7 +582,11 @@ export class WidgetEditorComponent extends PageComponent implements OnInit, OnDe
|
||||
);
|
||||
}
|
||||
return of(widgetTypeDetails);
|
||||
})
|
||||
}),
|
||||
catchError(() => {
|
||||
this.undoWidget();
|
||||
return of(null);
|
||||
}),
|
||||
).subscribe({
|
||||
next: (widgetTypeDetails) => {
|
||||
this.saveWidgetPending = false;
|
||||
@ -612,7 +619,7 @@ export class WidgetEditorComponent extends PageComponent implements OnInit, OnDe
|
||||
config.title = this.widget.widgetName;
|
||||
this.widget.defaultConfig = JSON.stringify(config);
|
||||
this.isDirty = false;
|
||||
this.widgetService.saveWidgetTypeDetails(this.widget, undefined, undefined).pipe(
|
||||
this.widgetService.saveWidgetTypeDetails(this.widget, undefined, undefined, null).pipe(
|
||||
mergeMap((widget) => {
|
||||
if (saveWidgetAsData.widgetBundleId) {
|
||||
return this.widgetService.addWidgetFqnToWidgetBundle(saveWidgetAsData.widgetBundleId, widget.fqn).pipe(
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
$conflict-dialog-width: 520px;
|
||||
$conflict-dialog-width: 530px;
|
||||
|
||||
:host {
|
||||
.main-label {
|
||||
|
||||
@ -24,23 +24,23 @@
|
||||
<mat-icon class="material-icons">close</mat-icon>
|
||||
</button>
|
||||
</mat-toolbar>
|
||||
<mat-progress-bar color="warn" mode="indeterminate" *ngIf="isLoading$ | async">
|
||||
<mat-progress-bar color="warn" mode="indeterminate" *ngIf="(isLoading$ | async) && !ignoreLoading">
|
||||
</mat-progress-bar>
|
||||
<div mat-dialog-content>
|
||||
<fieldset [disabled]="isLoading$ | async">
|
||||
<fieldset [disabled]="(isLoading$ | async) && !ignoreLoading">
|
||||
<mat-checkbox [formControl]="exportWidgetsFormControl">{{ 'widgets-bundle.export-widgets-bundle-widgets-prompt' | translate }}</mat-checkbox>
|
||||
</fieldset>
|
||||
</div>
|
||||
<div mat-dialog-actions fxLayoutAlign="end center">
|
||||
<button mat-button color="primary"
|
||||
type="button"
|
||||
[disabled]="(isLoading$ | async)"
|
||||
[disabled]="(isLoading$ | async) && !ignoreLoading"
|
||||
(click)="cancel()">
|
||||
{{ 'action.cancel' | translate }}
|
||||
</button>
|
||||
<button mat-raised-button color="primary"
|
||||
(click)="export()"
|
||||
[disabled]="(isLoading$ | async)">
|
||||
[disabled]="(isLoading$ | async) && !ignoreLoading">
|
||||
{{ 'action.export' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@ -27,6 +27,7 @@ import { isDefinedAndNotNull } from '@core/utils';
|
||||
export interface ExportWidgetsBundleDialogData {
|
||||
widgetsBundle: WidgetsBundle;
|
||||
includeBundleWidgetsInExport: boolean;
|
||||
ignoreLoading?: boolean;
|
||||
}
|
||||
|
||||
export interface ExportWidgetsBundleDialogResult {
|
||||
@ -44,6 +45,8 @@ export class ExportWidgetsBundleDialogComponent extends DialogComponent<ExportWi
|
||||
|
||||
widgetsBundle: WidgetsBundle;
|
||||
|
||||
ignoreLoading = false;
|
||||
|
||||
exportWidgetsFormControl = new FormControl(true);
|
||||
|
||||
constructor(protected store: Store<AppState>,
|
||||
@ -52,6 +55,7 @@ export class ExportWidgetsBundleDialogComponent extends DialogComponent<ExportWi
|
||||
public dialogRef: MatDialogRef<ExportWidgetsBundleDialogComponent, ExportWidgetsBundleDialogResult>) {
|
||||
super(store, router, dialogRef);
|
||||
this.widgetsBundle = data.widgetsBundle;
|
||||
this.ignoreLoading = data.ignoreLoading;
|
||||
if (isDefinedAndNotNull(data.includeBundleWidgetsInExport)) {
|
||||
this.exportWidgetsFormControl.patchValue(data.includeBundleWidgetsInExport, {emitEvent: false});
|
||||
}
|
||||
|
||||
@ -351,28 +351,7 @@ export class ImportExportService {
|
||||
|
||||
forkJoin(tasks).subscribe({
|
||||
next: ({includeBundleWidgetsInExport, widgetsBundle}) => {
|
||||
this.dialog.open<ExportWidgetsBundleDialogComponent, ExportWidgetsBundleDialogData,
|
||||
ExportWidgetsBundleDialogResult>(ExportWidgetsBundleDialogComponent, {
|
||||
disableClose: true,
|
||||
panelClass: ['tb-dialog', 'tb-fullscreen-dialog'],
|
||||
data: {
|
||||
widgetsBundle,
|
||||
includeBundleWidgetsInExport
|
||||
}
|
||||
}).afterClosed().subscribe(
|
||||
(result) => {
|
||||
if (result) {
|
||||
if (includeBundleWidgetsInExport !== result.exportWidgets) {
|
||||
this.store.dispatch(new ActionPreferencesPutUserSettings({includeBundleWidgetsInExport: result.exportWidgets}));
|
||||
}
|
||||
if (result.exportWidgets) {
|
||||
this.exportWidgetsBundleWithWidgetTypes(widgetsBundle);
|
||||
} else {
|
||||
this.exportWidgetsBundleWithWidgetTypeFqns(widgetsBundle);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
this.handleExportWidgetsBundle(widgetsBundle, includeBundleWidgetsInExport);
|
||||
},
|
||||
error: (e) => {
|
||||
this.handleExportError(e, 'widgets-bundle.export-failed-error');
|
||||
@ -400,6 +379,9 @@ export class ImportExportService {
|
||||
}))
|
||||
.subscribe(ruleChainData => this.exportToPc(ruleChainData, entityData.name));
|
||||
return;
|
||||
case EntityType.WIDGETS_BUNDLE:
|
||||
this.exportSelectedWidgetsBundle(entityData as WidgetsBundle);
|
||||
return;
|
||||
case EntityType.DASHBOARD:
|
||||
preparedData = this.prepareDashboardExport(entityData as Dashboard);
|
||||
break;
|
||||
@ -409,6 +391,43 @@ export class ImportExportService {
|
||||
this.exportToPc(preparedData, entityData.name);
|
||||
}
|
||||
|
||||
private exportSelectedWidgetsBundle(widgetsBundle: WidgetsBundle): void {
|
||||
this.store.pipe(select(selectUserSettingsProperty( 'includeBundleWidgetsInExport'))).pipe(take(1)).subscribe({
|
||||
next: (includeBundleWidgetsInExport) => {
|
||||
this.handleExportWidgetsBundle(widgetsBundle, includeBundleWidgetsInExport, true);
|
||||
},
|
||||
error: (e) => {
|
||||
this.handleExportError(e, 'widgets-bundle.export-failed-error');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private handleExportWidgetsBundle(widgetsBundle: WidgetsBundle, includeBundleWidgetsInExport: boolean, ignoreLoading?: boolean): void {
|
||||
this.dialog.open<ExportWidgetsBundleDialogComponent, ExportWidgetsBundleDialogData,
|
||||
ExportWidgetsBundleDialogResult>(ExportWidgetsBundleDialogComponent, {
|
||||
disableClose: true,
|
||||
panelClass: ['tb-dialog', 'tb-fullscreen-dialog'],
|
||||
data: {
|
||||
widgetsBundle,
|
||||
includeBundleWidgetsInExport,
|
||||
ignoreLoading
|
||||
}
|
||||
}).afterClosed().subscribe(
|
||||
(result) => {
|
||||
if (result) {
|
||||
if (includeBundleWidgetsInExport !== result.exportWidgets) {
|
||||
this.store.dispatch(new ActionPreferencesPutUserSettings({includeBundleWidgetsInExport: result.exportWidgets}));
|
||||
}
|
||||
if (result.exportWidgets) {
|
||||
this.exportWidgetsBundleWithWidgetTypes(widgetsBundle);
|
||||
} else {
|
||||
this.exportWidgetsBundleWithWidgetTypeFqns(widgetsBundle);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private exportWidgetsBundleWithWidgetTypes(widgetsBundle: WidgetsBundle) {
|
||||
this.widgetService.exportBundleWidgetTypesDetails(widgetsBundle.id.id).subscribe({
|
||||
next: (widgetTypesDetails) => {
|
||||
|
||||
@ -41,7 +41,7 @@ import { isNotEmptyStr, mergeDeepIgnoreArray } from '@core/utils';
|
||||
import { WidgetConfigComponentData } from '@home/models/widget-component.models';
|
||||
import { ComponentStyle, Font, TimewindowStyle } from '@shared/models/widget-settings.models';
|
||||
import { NULL_UUID } from '@shared/models/id/has-uuid';
|
||||
import { HasTenantId } from '@shared/models/entity.models';
|
||||
import { HasTenantId, HasVersion } from '@shared/models/entity.models';
|
||||
import { DataKeysCallbacks, DataKeySettingsFunction } from '@home/components/widget/config/data-keys.component.models';
|
||||
import { WidgetConfigCallbacks } from '@home/components/widget/config/widget-config.component.models';
|
||||
|
||||
@ -199,7 +199,7 @@ export interface WidgetControllerDescriptor {
|
||||
actionSources?: {[actionSourceId: string]: WidgetActionSource};
|
||||
}
|
||||
|
||||
export interface BaseWidgetType extends BaseData<WidgetTypeId>, HasTenantId {
|
||||
export interface BaseWidgetType extends BaseData<WidgetTypeId>, HasTenantId, HasVersion {
|
||||
tenantId: TenantId;
|
||||
fqn: string;
|
||||
name: string;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user