UI: Add support select widget bundle when save as widget

This commit is contained in:
Vladyslav_Prykhodko 2023-10-23 11:13:51 +03:00
parent deb8cf3a22
commit 60fa8f5f80
6 changed files with 61 additions and 28 deletions

View File

@ -110,6 +110,7 @@
<span class="tb-details-subtitle">{{ 'widgets-bundle.current' | translate }}</span> <span class="tb-details-subtitle">{{ 'widgets-bundle.current' | translate }}</span>
<tb-widgets-bundle-select fxFlexOffset="5" <tb-widgets-bundle-select fxFlexOffset="5"
fxFlex fxFlex
required
[selectFirstBundle]="false" [selectFirstBundle]="false"
[selectBundleAlias]="selectedWidgetsBundleAlias" [selectBundleAlias]="selectedWidgetsBundleAlias"
[ngModel]="null" [ngModel]="null"

View File

@ -15,7 +15,7 @@
limitations under the License. limitations under the License.
--> -->
<form [formGroup]="saveWidgetTypeAsFormGroup" (ngSubmit)="saveAs()"> <form [formGroup]="saveWidgetTypeAsFormGroup" (ngSubmit)="saveAs()" style="width: 360px">
<mat-toolbar color="primary"> <mat-toolbar color="primary">
<h2 translate>widget.save-widget-type-as</h2> <h2 translate>widget.save-widget-type-as</h2>
<span fxFlex></span> <span fxFlex></span>
@ -29,7 +29,6 @@
</mat-progress-bar> </mat-progress-bar>
<div style="height: 4px;" *ngIf="!(isLoading$ | async)"></div> <div style="height: 4px;" *ngIf="!(isLoading$ | async)"></div>
<div mat-dialog-content> <div mat-dialog-content>
<fieldset>
<span translate>widget.save-widget-type-as-text</span> <span translate>widget.save-widget-type-as-text</span>
<mat-form-field class="mat-block"> <mat-form-field class="mat-block">
<mat-label translate>widget.title</mat-label> <mat-label translate>widget.title</mat-label>
@ -38,7 +37,11 @@
{{ 'widget.title-required' | translate }} {{ 'widget.title-required' | translate }}
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
</fieldset> <tb-widgets-bundle-select
formControlName="widgetsBundle"
allowEmptyBundle
bundlesScope="{{bundlesScope}}">
</tb-widgets-bundle-select>
</div> </div>
<div mat-dialog-actions fxLayoutAlign="end center"> <div mat-dialog-actions fxLayoutAlign="end center">
<button mat-button color="primary" <button mat-button color="primary"

View File

@ -18,12 +18,15 @@ import { Component, OnInit } from '@angular/core';
import { MatDialogRef } from '@angular/material/dialog'; import { MatDialogRef } from '@angular/material/dialog';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { DialogComponent } from '@shared/components/dialog.component'; import { DialogComponent } from '@shared/components/dialog.component';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { getCurrentAuthUser } from '@core/auth/auth.selectors';
import { Authority } from '@shared/models/authority.enum';
export interface SaveWidgetTypeAsDialogResult { export interface SaveWidgetTypeAsDialogResult {
widgetName: string; widgetName: string;
widgetBundleId?: string;
} }
@Component({ @Component({
@ -34,18 +37,27 @@ export interface SaveWidgetTypeAsDialogResult {
export class SaveWidgetTypeAsDialogComponent extends export class SaveWidgetTypeAsDialogComponent extends
DialogComponent<SaveWidgetTypeAsDialogComponent, SaveWidgetTypeAsDialogResult> implements OnInit { DialogComponent<SaveWidgetTypeAsDialogComponent, SaveWidgetTypeAsDialogResult> implements OnInit {
saveWidgetTypeAsFormGroup: UntypedFormGroup; saveWidgetTypeAsFormGroup: FormGroup;
bundlesScope: string;
constructor(protected store: Store<AppState>, constructor(protected store: Store<AppState>,
protected router: Router, protected router: Router,
public dialogRef: MatDialogRef<SaveWidgetTypeAsDialogComponent, SaveWidgetTypeAsDialogResult>, public dialogRef: MatDialogRef<SaveWidgetTypeAsDialogComponent, SaveWidgetTypeAsDialogResult>,
public fb: UntypedFormBuilder) { public fb: FormBuilder) {
super(store, router, dialogRef); super(store, router, dialogRef);
const authUser = getCurrentAuthUser(store);
if (authUser.authority === Authority.TENANT_ADMIN) {
this.bundlesScope = 'tenant';
} else {
this.bundlesScope = 'system';
}
} }
ngOnInit(): void { ngOnInit(): void {
this.saveWidgetTypeAsFormGroup = this.fb.group({ this.saveWidgetTypeAsFormGroup = this.fb.group({
title: [null, [Validators.required]] title: [null, [Validators.required]],
widgetsBundle: [null]
}); });
} }
@ -55,8 +67,10 @@ export class SaveWidgetTypeAsDialogComponent extends
saveAs(): void { saveAs(): void {
const widgetName: string = this.saveWidgetTypeAsFormGroup.get('title').value; const widgetName: string = this.saveWidgetTypeAsFormGroup.get('title').value;
const widgetBundleId: string = this.saveWidgetTypeAsFormGroup.get('widgetsBundle').value?.id?.id;
const result: SaveWidgetTypeAsDialogResult = { const result: SaveWidgetTypeAsDialogResult = {
widgetName widgetName,
widgetBundleId
}; };
this.dialogRef.close(result); this.dialogRef.close(result);
} }

View File

@ -588,11 +588,25 @@ export class WidgetEditorComponent extends PageComponent implements OnInit, OnDe
config.title = this.widget.widgetName; config.title = this.widget.widgetName;
this.widget.defaultConfig = JSON.stringify(config); this.widget.defaultConfig = JSON.stringify(config);
this.isDirty = false; this.isDirty = false;
this.widgetService.saveWidgetTypeDetails(this.widget, undefined, undefined).subscribe( this.widgetService.saveWidgetTypeDetails(this.widget, undefined, undefined).pipe(
mergeMap((widget) => {
if (saveWidgetAsData.widgetBundleId) {
return this.widgetService.addWidgetFqnToWidgetBundle(saveWidgetAsData.widgetBundleId, widget.fqn).pipe(
map(() => widget)
);
}
return of(widget);
})
).subscribe(
{ {
next: (widgetTypeDetails) => { next: (widgetTypeDetails) => {
this.saveWidgetAsPending = false; this.saveWidgetAsPending = false;
this.router.navigate(['..', widgetTypeDetails.id.id], {relativeTo: this.route}); if (saveWidgetAsData.widgetBundleId) {
this.router.navigate(['resources', 'widgets-library', 'widgets-bundles',
saveWidgetAsData.widgetBundleId, widgetTypeDetails.id.id]);
} else {
this.router.navigate(['resources', 'widgets-library', 'widget-types', widgetTypeDetails.id.id]);
}
}, },
error: () => { error: () => {
this.saveWidgetAsPending = false; this.saveWidgetAsPending = false;

View File

@ -19,9 +19,9 @@
<mat-select [required]="required" <mat-select [required]="required"
[disabled]="disabled" [disabled]="disabled"
[(ngModel)]="widgetsBundle" [(ngModel)]="widgetsBundle"
matInput
panelClass="tb-widgets-bundle-select" panelClass="tb-widgets-bundle-select"
placeholder="{{ 'widget.select-widgets-bundle' | translate }}" placeholder="{{ 'widget.select-widgets-bundle' | translate }}"
(blur)="onTouched()"
(ngModelChange)="widgetsBundleChanged()"> (ngModelChange)="widgetsBundleChanged()">
<mat-select-trigger> <mat-select-trigger>
<div class="tb-bundle-item"> <div class="tb-bundle-item">
@ -29,6 +29,9 @@
<span translate class="tb-bundle-system" *ngIf="isSystem(widgetsBundle)">widgets-bundle.system</span> <span translate class="tb-bundle-system" *ngIf="isSystem(widgetsBundle)">widgets-bundle.system</span>
</div> </div>
</mat-select-trigger> </mat-select-trigger>
<mat-option [value]="null" *ngIf="!required">
---
</mat-option>
<mat-option *ngFor="let widgetsBundle of widgetsBundles$ | async" [value]="widgetsBundle"> <mat-option *ngFor="let widgetsBundle of widgetsBundles$ | async" [value]="widgetsBundle">
<div class="tb-bundle-item"> <div class="tb-bundle-item">
<span>{{widgetsBundle.title}}</span> <span>{{widgetsBundle.title}}</span>

View File

@ -20,12 +20,12 @@ import { Observable } from 'rxjs';
import { map, share, tap } from 'rxjs/operators'; import { map, share, 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';
import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { WidgetsBundle } from '@shared/models/widgets-bundle.model'; import { WidgetsBundle } from '@shared/models/widgets-bundle.model';
import { WidgetService } from '@core/http/widget.service'; import { WidgetService } from '@core/http/widget.service';
import { isDefined } from '@core/utils'; import { isDefined } from '@core/utils';
import { NULL_UUID } from '@shared/models/id/has-uuid'; import { NULL_UUID } from '@shared/models/id/has-uuid';
import { getCurrentAuthState } from '@core/auth/auth.selectors'; import { getCurrentAuthState } from '@core/auth/auth.selectors';
import { coerceBoolean } from '@shared/decorators/coercion';
@Component({ @Component({
selector: 'tb-widgets-bundle-select', selector: 'tb-widgets-bundle-select',
@ -44,19 +44,15 @@ export class WidgetsBundleSelectComponent implements ControlValueAccessor, OnIni
bundlesScope: 'system' | 'tenant'; bundlesScope: 'system' | 'tenant';
@Input() @Input()
@coerceBoolean()
selectFirstBundle: boolean; selectFirstBundle: boolean;
@Input() @Input()
selectBundleAlias: string; selectBundleAlias: string;
private requiredValue: boolean;
get required(): boolean {
return this.requiredValue;
}
@Input() @Input()
set required(value: boolean) { @coerceBoolean()
this.requiredValue = coerceBooleanProperty(value); required: boolean;
}
@Input() @Input()
disabled: boolean; disabled: boolean;
@ -70,7 +66,8 @@ export class WidgetsBundleSelectComponent implements ControlValueAccessor, OnIni
widgetsBundle: WidgetsBundle | null; widgetsBundle: WidgetsBundle | null;
private propagateChange = (v: any) => { }; onTouched = () => {};
private propagateChange: (value: any) => void = () => {};
constructor(private store: Store<AppState>, constructor(private store: Store<AppState>,
private widgetService: WidgetService) { private widgetService: WidgetService) {
@ -81,6 +78,7 @@ export class WidgetsBundleSelectComponent implements ControlValueAccessor, OnIni
} }
registerOnTouched(fn: any): void { registerOnTouched(fn: any): void {
this.onTouched = fn;
} }
ngOnInit() { ngOnInit() {