From: pujaoshahu Date: Mon, 11 May 2026 13:07:53 +0000 (+0530) Subject: mgr/dashboard: [Dashboard] Incorrect action button label "Edit User" instead of ... X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=81feb0d1c90fd922b7464638a204be71df8fade2;p=ceph.git mgr/dashboard: [Dashboard] Incorrect action button label "Edit User" instead of "Save" in Edit User page Fixes: https://tracker.ceph.com/issues/76507 Signed-off-by: pujaoshahu Summary: Updated submit button labels in edit forms to display "Save" instead of "Edit User", "Edit Pool", or "Edit Host" for better UX consistency, while keeping form titles unchanged. Modified Files role-form.component.ts: Added submitAction property to control submit button label by mode; edit mode uses Save changes, create mode uses Create Role. role-form.component.html: Submit button now binds to submitAction instead of action/resource text. role-form.component.spec.ts: Added tests for submitAction behavior in create and edit modes. user-form.component.ts: Uses submitAction property; edit mode label updated to Save changes. user-form.component.html: Submit button uses submitAction binding. user-form.component.spec.ts: Added/updated tests covering submitAction behavior. pool-form.component.ts: Uses submitAction property; edit mode label updated to Save changes. pool-form.component.html: Submit button uses submitAction binding. pool-form.component.spec.ts: Updated submit label test expectation for edit mode. hosts.component.ts: Edit host modal submit button text changed to Save changes. hosts.component.spec.ts: Updated test to match Save changes button text. app.constants.ts: In the current workspace snapshot, there is no SAVE constant added under ActionLabelsI18n. Signed-off-by: pujaoshahu Signed-off-by: pujashahu --- diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form.component.html index 55ce961fed99..7046fcc2bfbe 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form.component.html @@ -598,7 +598,7 @@ diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form.component.ts index ce3029365566..932edad3c16d 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form.component.ts @@ -119,6 +119,7 @@ export class RbdFormComponent extends CdForm implements OnInit { action: string; resource: string; + submitAction: string; private rbdImage = new ReplaySubject(1); private routerUrl: string; @@ -352,17 +353,21 @@ export class RbdFormComponent extends CdForm implements OnInit { if (url.startsWith('/block/rbd/edit')) { this.mode = this.rbdFormMode.editing; this.action = this.actionLabels.EDIT; + this.submitAction = this.actionLabels.SAVE_CHANGES; this.disableForEdit(); } else if (url.startsWith('/block/rbd/clone')) { this.mode = this.rbdFormMode.cloning; this.disableForClone(); this.action = this.actionLabels.CLONE; + this.submitAction = `${this.action} ${this.resource}`; } else if (url.startsWith('/block/rbd/copy')) { this.mode = this.rbdFormMode.copying; this.action = this.actionLabels.COPY; + this.submitAction = `${this.action} ${this.resource}`; this.disableForCopy(); } else { this.action = this.actionLabels.CREATE; + this.submitAction = `${this.action} ${this.resource}`; } _.each(this.features, (feature) => { this.rbdForm diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/hosts.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/hosts.component.spec.ts index 21375beb0ba3..b9e9494e4e67 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/hosts.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/hosts.component.spec.ts @@ -11,6 +11,7 @@ import { CephSharedModule } from '~/app/ceph/shared/ceph-shared.module'; import { CoreModule } from '~/app/core/core.module'; import { HostService } from '~/app/shared/api/host.service'; import { OrchestratorService } from '~/app/shared/api/orchestrator.service'; +import { ModalCdsService } from '~/app/shared/services/modal-cds.service'; import { TableActionsComponent } from '~/app/shared/datatable/table-actions/table-actions.component'; import { CdTableFetchDataContext } from '~/app/shared/models/cd-table-fetch-data-context'; import { CdTableSelection } from '~/app/shared/models/cd-table-selection'; @@ -274,6 +275,21 @@ describe('HostsComponent', () => { expect(showForceMaintenanceModal.showModal).toBeFalsy(); }); + it('should set host edit modal submit label to Save changes', () => { + const hostService = TestBed.inject(HostService); + const modalService = TestBed.inject(ModalCdsService); + spyOn(hostService, 'getLabels').and.returnValue(of([])); + const showSpy = spyOn(modalService, 'show').and.stub(); + + component.selection = new CdTableSelection(); + component.selection.selected = [{ hostname: 'host-test', labels: [] }]; + + component.editAction(); + + expect(showSpy).toHaveBeenCalled(); + expect(showSpy.calls.mostRecent().args[1].submitButtonText).toBe('Save changes'); + }); + describe('table actions', () => { const fakeHosts = require('./fixtures/host_list_response.json'); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-form/service-form.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-form/service-form.component.html index ba3b673cac4e..b94aec974a21 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-form/service-form.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-form/service-form.component.html @@ -2073,7 +2073,7 @@ diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-form/service-form.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-form/service-form.component.ts index ef80a1ca4cbd..26927c6d4efa 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-form/service-form.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-form/service-form.component.ts @@ -81,6 +81,7 @@ export class ServiceFormComponent extends CdForm implements OnInit { serviceForm: CdFormGroup; action: string; resource: string; + submitAction: string; serviceTypes: string[] = []; serviceIds: string[] = []; selectedHosts: string[] = []; @@ -697,6 +698,7 @@ export class ServiceFormComponent extends CdForm implements OnInit { ngOnInit(): void { this.open = true; this.action = this.actionLabels.CREATE; + this.submitAction = `${this.action} ${this.resource}`; this.resolveRoute(); this.getRgwModuleStatus(); this.mgrModuleService.updateCompleted$.subscribe(() => this.getRgwModuleStatus()); @@ -738,6 +740,8 @@ export class ServiceFormComponent extends CdForm implements OnInit { if (this.editing) { this.action = this.actionLabels.EDIT; + this.submitAction = this.actionLabels.SAVE_CHANGES; + this.disableForEditing(this.serviceType); this.cephServiceService .list(new HttpParams({ fromObject: { limit: -1, offset: 0 } }), this.serviceName) .observable.subscribe((response: CephServiceSpec[]) => { diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.html index 2b2b09d6dfd4..d0ade1b8b5ab 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.html @@ -1146,7 +1146,7 @@ diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.spec.ts index 928205b84792..c07552605424 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.spec.ts @@ -174,6 +174,23 @@ describe('PoolFormComponent', () => { expect(component).toBeTruthy(); }); + describe('submit label', () => { + it('should set submit label to Create Pool in create mode', () => { + expect(component.submitAction).toBe('Create Pool'); + }); + + it('should set submit label to Save changes in edit mode', () => { + fixture.destroy(); + Object.defineProperty(router, 'url', { + get: () => '/pool/edit/somePoolName', + configurable: true + }); + setUpPoolComponent(); + + expect(component.submitAction).toBe('Save changes'); + }); + }); + describe('throws error for not allowed users', () => { const expectError = (redirected: boolean) => { navigationSpy.calls.reset(); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.ts index 5f1e32eccd4d..dfd02d41d266 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.ts @@ -115,6 +115,7 @@ export class PoolFormComponent extends CdForm implements OnInit { currentConfigurationValues: { [configKey: string]: any } = {}; action: string; resource: string; + submitAction: string; icons = Icons; pgAutoscaleModes: string[]; crushUsage: string[] = undefined; // Will only be set if a rule is used by some pool @@ -153,6 +154,9 @@ export class PoolFormComponent extends CdForm implements OnInit { this.editing = this.router.url.startsWith(`/pool/${URLVerbs.EDIT}`); this.action = this.editing ? this.actionLabels.EDIT : this.actionLabels.CREATE; this.resource = $localize`pool`; + this.submitAction = this.editing + ? this.actionLabels.SAVE_CHANGES + : `${this.action} ${_.upperFirst(this.resource)}`; this.authenticate(); this.createForm(); } diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.html b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.html index e24e718a5e18..f42cc2ab21ec 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.html @@ -79,7 +79,7 @@ diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.spec.ts index f10e315e5df2..83cd1c919b8e 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.spec.ts @@ -82,6 +82,10 @@ describe('RoleFormComponent', () => { expect(component.mode).toBeUndefined(); }); + it('should set submit action to Create Role', () => { + expect(component.submitAction).toBe('Create Role'); + }); + it('should submit', () => { const role: RoleFormModel = { name: 'role1', @@ -138,6 +142,10 @@ describe('RoleFormComponent', () => { expect(component.mode).toBe('editing'); }); + it('should set submit action to Save changes', () => { + expect(component.submitAction).toBe('Save changes'); + }); + it('should submit', () => { formHelper.setValue('scopes_permissions', { osd: ['read', 'update'], diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.ts index 18649b2e59f0..9bbfefcc64b0 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.ts @@ -37,6 +37,7 @@ export class RoleFormComponent extends CdForm implements OnInit { action: string; resource: string; + submitAction: string; constructor( private route: ActivatedRoute, @@ -98,8 +99,10 @@ export class RoleFormComponent extends CdForm implements OnInit { if (this.router.url.startsWith('/user-management/roles/edit')) { this.mode = this.roleFormMode.editing; this.action = this.actionLabels.EDIT; + this.submitAction = this.actionLabels.SAVE_CHANGES; } else { this.action = this.actionLabels.CREATE; + this.submitAction = `${this.action} ${_.upperFirst(this.resource)}`; } if (this.mode === this.roleFormMode.editing) { this.initEdit(); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form.component.html b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form.component.html index bc163105c838..84a5bf740d2d 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form.component.html @@ -291,7 +291,7 @@ diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form.component.spec.ts index d68e2e9be539..86312e26a25b 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form.component.spec.ts @@ -86,6 +86,10 @@ describe('UserFormComponent', () => { component.ngOnInit(); }); + it('should set submit label to Create User', () => { + expect(component.submitAction).toBe('Create User'); + }); + it('should not disable fields', () => { [ 'username', @@ -268,6 +272,10 @@ describe('UserFormComponent', () => { expect(form.getValue('roles')).toContain('administrator'); }); + it('should set submit label to Save changes', () => { + expect(component.submitAction).toBe('Save changes'); + }); + it('should alert if user is removing needed role permission', () => { let modalBodyTpl = null; spyOn(modalService, 'show').and.callFake((_content, initialState) => { diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form.component.ts index 420079733405..65d407430410 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form.component.ts @@ -53,6 +53,7 @@ export class UserFormComponent extends CdForm implements OnInit { messages = new SelectMessages({ empty: $localize`There are no roles.` }); action: string; resource: string; + submitAction: string; passwordPolicyHelpText = ''; passwordStrengthLevelClass: string; passwordValuation: string; @@ -146,9 +147,11 @@ export class UserFormComponent extends CdForm implements OnInit { if (this.router.url.startsWith('/user-management/users/edit')) { this.mode = this.userFormMode.editing; this.action = this.actionLabels.EDIT; + this.submitAction = this.actionLabels.SAVE_CHANGES; this.passwordexp = false; } else { this.action = this.actionLabels.CREATE; + this.submitAction = `${this.action} ${_.upperFirst(this.resource)}`; this.passwordexp = true; } this.userForm.get('password').updateValueAndValidity(); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/constants/app.constants.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/constants/app.constants.ts index 41891d9b8432..bc8b457f8bc4 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/constants/app.constants.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/constants/app.constants.ts @@ -170,6 +170,7 @@ export class ActionLabelsI18n { NFS_EXPORT: string; VIEW: string; EDIT_GATEWAYS_GROUP: string; + SAVE_CHANGES: string; constructor() { /* Create a new item */ this.CREATE = $localize`Create`; @@ -263,6 +264,7 @@ export class ActionLabelsI18n { this.NFS_EXPORT = $localize`Create NFS Share`; this.VIEW = $localize`View`; this.EDIT_GATEWAYS_GROUP = $localize`Edit gateways group`; + this.SAVE_CHANGES = $localize`Save changes`; } } diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/host-action.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/host-action.service.ts index f2ae91dd1b2a..93af02328c33 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/host-action.service.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/host-action.service.ts @@ -44,7 +44,7 @@ export class HostActionService { this.cdsModalService.show(FormModalComponent, { titleText: $localize`Edit Host: ${host.hostname}`, fields: [labelsField], - submitButtonText: $localize`Edit Host`, + submitButtonText: $localize`Save changes`, onSubmit: (values: { labels: string[] }) => { this.submitHostLabelUpdate(host.hostname, values.labels, onSuccess); }