Update navigation to ensure tab param isn't reset on updating roles

This commit is contained in:
Mir Bhatia
2026-04-28 15:48:41 +02:00
parent 3c4d231cc1
commit eea4c36b7c
4 changed files with 34 additions and 19 deletions
@@ -48,7 +48,7 @@ module Workflows
def data_attributes
{
controller: "admin--workflow-role-select",
"admin--workflow-role-select-base-url-value": helpers.edit_workflow_path(@type),
"admin--workflow-role-select-base-url-value": helpers.edit_workflow_tab_path(@type, @tab),
"admin--workflow-role-select-current-role-ids-value": @roles.map(&:id).join(","),
"admin--workflow-role-select-admin--workflow-checkbox-state-outlet": "#workflow_form"
}
@@ -162,6 +162,7 @@ class Workflows::TabsController < ApplicationController
def set_roles
@roles = @eligible_roles.where(id: params[:role_ids])
@roles = [@eligible_roles.first] if @roles.empty?
end
def statuses_for_form
@@ -313,7 +313,7 @@ export default class WorkflowCheckboxStateController extends Controller<HTMLForm
if (this.isDirtyValue) {
this.confirmThenNavigate(url);
} else {
Turbo.visit(url);
this.frameNavigateTo(url);
}
}
@@ -323,14 +323,27 @@ export default class WorkflowCheckboxStateController extends Controller<HTMLForm
this.hasCheckboxChangesValue = false;
this.hasStatusChangesValue = false;
this.confirmationDialogTarget.close();
setTimeout(() => { Turbo.visit(url); }, 0);
setTimeout(() => { this.frameNavigateTo(url); }, 0);
},
() => {
this.element.requestSubmit();
this.confirmationDialogTarget.close();
// Delay to allow the flash message from the form submission to appear.
setTimeout(() => { Turbo.visit(url); }, 1000);
setTimeout(() => { this.frameNavigateTo(url); }, 1000);
},
);
}
// This keeps the url in the /tabs/:tab/edit format consistently,
// rather than doing a Turbo.visit which changes the format.
// It also keeps history usable, similar to data-turbo-action="advance".
private frameNavigateTo(url:string) {
const turboFrame = this.element.closest('turbo-frame') as HTMLElement | null;
if (turboFrame) {
turboFrame.setAttribute('src', url);
history.pushState({}, '', url);
} else {
Turbo.visit(url);
}
}
}
@@ -62,26 +62,27 @@ export default class WorkflowRoleSelectController extends Controller {
// For when all roles are deselected
if (!selectedIds.length) {
const url = new URL(this.baseUrlValue, window.location.origin);
if (this.hasAdminWorkflowCheckboxStateOutlet) {
this.adminWorkflowCheckboxStateOutlet.navigateTo(url.toString());
} else {
Turbo.visit(url.toString());
}
this.navigateTo(this.buildUrl([]));
return;
}
const currentIds = this.currentRoleIdsValue.split(',').filter(Boolean);
if (selectedIds.slice().sort().join(',') === currentIds.slice().sort().join(',')) return;
const url = new URL(this.baseUrlValue, window.location.origin);
selectedIds.forEach((id) => url.searchParams.append('role_ids[]', id!));
if (this.hasAdminWorkflowCheckboxStateOutlet) {
this.adminWorkflowCheckboxStateOutlet.navigateTo(url.toString());
} else {
Turbo.visit(url.toString());
}
this.navigateTo(this.buildUrl(selectedIds as string[]));
};
private buildUrl(roleIds:string[]):string {
const url = new URL(this.baseUrlValue, window.location.origin);
roleIds.forEach((id) => url.searchParams.append('role_ids[]', id));
return url.toString();
}
private navigateTo(url:string) {
if (this.hasAdminWorkflowCheckboxStateOutlet) {
this.adminWorkflowCheckboxStateOutlet.navigateTo(url);
} else {
Turbo.visit(url);
}
}
}