Merge pull request #69218 from rhcs-dashboard/77030-control-flow-fix-pool-creation-page

mgr/dashboard: Fixing control flow on submit button for pool creation page

Reviewed-by: Abhishek Desai <abhishek.desai1@ibm.com>
Reviewed-by: Puja Shahu <pshahu@redhat.com>
Reviewed-by: Afreen Misbah <afreen@ibm.com>
This commit is contained in:
Pedro Gonzalez Gomez 2026-07-22 12:57:22 +02:00 committed by GitHub
commit 93703c3971
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 91 additions and 4 deletions

View File

@ -41,6 +41,7 @@ import { RbdMirroringService } from '~/app/shared/api/rbd-mirroring.service';
import { MonitorService } from '~/app/shared/api/monitor.service';
import { ModalCdsService } from '~/app/shared/services/modal-cds.service';
import { Permissions } from '~/app/shared/models/permissions';
import { FROM_STORAGE_CLASS } from './../../rgw/models/rgw-storage-class.model';
interface FormFieldDescription {
externalFieldName: string;
@ -125,6 +126,8 @@ export class PoolFormComponent extends CdForm implements OnInit {
isApplicationsSelected = true;
msrCrush: boolean = false;
isStretchMode: boolean = false;
private fromStorageClass: boolean = false;
private previousPath: string = '';
readonly DEFAULT_REPLICATED_MIN_SIZE = 1;
readonly DEFAULT_REPLICATED_MAX_SIZE = 3;
@ -155,6 +158,9 @@ export class PoolFormComponent extends CdForm implements OnInit {
this.resource = $localize`pool`;
this.authenticate();
this.createForm();
const nav = this.router.getCurrentNavigation();
this.fromStorageClass = nav?.extras?.state?.['from'] === FROM_STORAGE_CLASS;
this.previousPath = nav?.extras?.state?.['returnUrl'] || '/pool';
}
authenticate() {
@ -1148,10 +1154,18 @@ export class PoolFormComponent extends CdForm implements OnInit {
}
this.form.setErrors({ cdSubmitButton: true });
},
complete: () => this.router.navigate(['/pool'])
complete: () => this.navigateAfterPoolForm()
});
}
navigateAfterPoolForm(): void {
if (this.fromStorageClass) {
this.router.navigate([this.previousPath]);
} else {
this.router.navigate(['/pool']);
}
}
appSelection(events: SelectOption[]) {
this.data.applications.selected = events.map((e: SelectOption) => e.name);
this.form.get('name').updateValueAndValidity({ emitEvent: false, onlySelf: true });

View File

@ -350,3 +350,5 @@ export const AclHelperText: AclMaps = {
export const POOL = {
PATH: '/pool/create'
};
export const FROM_STORAGE_CLASS = 'from-storage-class';

View File

@ -131,7 +131,15 @@
spacingClass="mb-2"
(action)="navigateCreatePool()"
>
<span i18n>To create a new pool click <a [routerLink]="[POOL.PATH]">here</a></span>
<span i18n
>To create a new pool click
<a
href="#"
(click)="navigateCreatePool()"
>
here
</a>
</span>
</cd-alert-panel>
<cds-select
label="Pool"

View File

@ -1,7 +1,8 @@
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { Router } from '@angular/router';
import { SharedModule } from '~/app/shared/shared.module';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { ReactiveFormsModule } from '@angular/forms';
@ -15,10 +16,15 @@ import {
import { CoreModule } from '~/app/core/core.module';
import { RgwStorageClassFormComponent } from './rgw-storage-class-form.component';
import { TIER_TYPE_DISPLAY } from '../models/rgw-storage-class.model';
import { PoolFormComponent } from '../../pool/pool-form/pool-form.component';
import { RgwZonegroupService } from '~/app/shared/api/rgw-zonegroup.service';
import { PoolService } from '~/app/shared/api/pool.service';
import { of } from 'rxjs';
describe('RgwStorageClassFormComponent', () => {
let component: RgwStorageClassFormComponent;
let fixture: ComponentFixture<RgwStorageClassFormComponent>;
let router: Router;
beforeEach(async () => {
await TestBed.configureTestingModule({
@ -38,8 +44,14 @@ describe('RgwStorageClassFormComponent', () => {
declarations: [RgwStorageClassFormComponent]
}).compileComponents();
spyOn(TestBed.inject(RgwZonegroupService), 'getAllZonegroupsInfo').and.returnValue(
of({ zonegroups: [], default_zonegroup: '' })
);
spyOn(TestBed.inject(PoolService), 'getList').and.returnValue(of([]));
fixture = TestBed.createComponent(RgwStorageClassFormComponent);
component = fixture.componentInstance;
router = TestBed.inject(Router);
fixture.detectChanges();
});
@ -195,4 +207,47 @@ describe('RgwStorageClassFormComponent', () => {
expect(component).toBeTruthy();
});
});
describe('pool form navigation from storage class form', () => {
const storageClassReturnUrl = '/rgw/storage-class/create';
const createPoolFormNavigationContext = (
fromStorageClass: boolean,
previousPath: string,
poolRouter: Router
) => {
const poolForm = Object.create(PoolFormComponent.prototype) as PoolFormComponent;
(poolForm as any).fromStorageClass = fromStorageClass;
(poolForm as any).previousPath = previousPath;
(poolForm as any).router = poolRouter;
return poolForm;
};
it('should return to storage class form after pool creation when opened from storage class', () => {
const navigateSpy = spyOn(router, 'navigate');
const poolForm = createPoolFormNavigationContext(true, storageClassReturnUrl, router);
poolForm.navigateAfterPoolForm();
expect(navigateSpy).toHaveBeenCalledWith([storageClassReturnUrl]);
});
it('should return to pool list after pool creation when not opened from storage class', () => {
const navigateSpy = spyOn(router, 'navigate');
const poolForm = createPoolFormNavigationContext(false, '/pool', router);
poolForm.navigateAfterPoolForm();
expect(navigateSpy).toHaveBeenCalledWith(['/pool']);
});
it('should return to pool list when pool creation is cancelled outside storage class form', () => {
const navigateSpy = spyOn(router, 'navigate');
const poolForm = createPoolFormNavigationContext(false, '/pool', router);
poolForm.navigateAfterPoolForm();
expect(navigateSpy).toHaveBeenCalledWith(['/pool']);
});
});
});

View File

@ -64,7 +64,8 @@ import {
AclType,
ZoneRequest,
AllZonesResponse,
POOL
POOL,
FROM_STORAGE_CLASS
} from '../models/rgw-storage-class.model';
import { NotificationType } from '~/app/shared/enum/notification-type.enum';
import { NotificationService } from '~/app/shared/services/notification.service';
@ -120,6 +121,7 @@ export class RgwStorageClassFormComponent extends CdForm implements OnInit {
rgwPools: Pool[];
zones: any[];
POOL = POOL;
FROM_STORAGE_CLASS = FROM_STORAGE_CLASS;
constructor(
public actionLabels: ActionLabelsI18n,
@ -633,6 +635,12 @@ export class RgwStorageClassFormComponent extends CdForm implements OnInit {
this.router.navigate([`rgw/storage-class`]);
}
navigateCreatePool(): void {
this.router.navigate([POOL.PATH], {
state: { from: FROM_STORAGE_CLASS, returnUrl: this.router.url }
});
}
getTierTargetByStorageClass(placementTargetInfo: PlacementTarget, storageClass: string) {
const tierTarget = placementTargetInfo?.tier_targets?.find(
(target: TierTarget) => target.val.storage_class === storageClass