Skip to content

Commit c4c8ec2

Browse files
committed
Show confirmation dialog when statuses are only added or removed
1 parent b314bf5 commit c4c8ec2

File tree

4 files changed

+70
-8
lines changed

4 files changed

+70
-8
lines changed

app/controllers/workflows_controller.rb

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -178,10 +178,9 @@ def confirm_statuses # rubocop:disable Metrics/AbcSize
178178

179179
def statuses_for_form
180180
@added_status_ids = []
181+
@has_status_changes = false
181182
@statuses = if @type && params[:status_ids].present?
182-
status_ids = params[:status_ids].map(&:to_i)
183-
@added_status_ids = status_ids - statuses_for_role_and_type.pluck(:id)
184-
Status.where(id: status_ids).order(:position)
183+
statuses_from_params
185184
elsif @type && @role
186185
statuses_for_role_and_type
187186
elsif @type
@@ -191,6 +190,14 @@ def statuses_for_form
191190
end
192191
end
193192

193+
def statuses_from_params
194+
status_ids = params[:status_ids].map(&:to_i)
195+
saved_ids = statuses_for_role_and_type.pluck(:id)
196+
@added_status_ids = status_ids - saved_ids
197+
@has_status_changes = @added_status_ids.any? || (saved_ids - status_ids).any?
198+
Status.where(id: status_ids).order(:position)
199+
end
200+
194201
def statuses_for_role_and_type
195202
@type.statuses(role: @role, tab: current_tab)
196203
end

app/views/workflows/edit.html.erb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ See COPYRIGHT and LICENSE files for more details.
4141
{ action: :update },
4242
id: "workflow_form",
4343
method: :patch,
44-
data: { turbo_frame: "_top", controller: "admin--workflow-checkbox-state" }
44+
data: { turbo_frame: "_top", controller: "admin--workflow-checkbox-state", has_status_changes: ("true" if @has_status_changes) }
4545
) do %>
4646
<%= hidden_field_tag "type_id", @type.id %>
4747
<%= hidden_field_tag "role_id", @role.id %>

frontend/src/stimulus/controllers/dynamic/admin/workflow-checkbox-state.controller.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ interface SavedState {
5656
export default class WorkflowCheckboxStateController extends Controller<HTMLFormElement> {
5757
private initialCheckboxState:Record<string, boolean> = {};
5858
private turboRequests:TurboRequestsService;
59+
private hasStatusChanges = false;
5960

6061
connect() {
6162
void window.OpenProject.getPluginContext().then((context) => {
@@ -72,10 +73,15 @@ export default class WorkflowCheckboxStateController extends Controller<HTMLForm
7273

7374
this.element.addEventListener('submit', this.onFormSubmit);
7475

76+
this.hasStatusChanges = this.element.dataset.hasStatusChanges === 'true';
7577
this.initialCheckboxState = this.captureState();
7678
this.element.addEventListener('change', this.onCheckboxChange);
7779

7880
document.addEventListener('click', this.onTabLinkClick, true);
81+
82+
if (this.hasStatusChanges) {
83+
this.updateRoleDirtyParams(true);
84+
}
7985
}
8086

8187
disconnect() {
@@ -97,16 +103,17 @@ export default class WorkflowCheckboxStateController extends Controller<HTMLForm
97103

98104
private onCheckboxChange = () => {
99105
const current = this.captureState();
100-
const dirty = Object.keys(current).some((key) => current[key] !== this.initialCheckboxState[key]);
106+
const checkboxesDirty = Object.keys(current).some((key) => current[key] !== this.initialCheckboxState[key]);
107+
const dirty = this.hasStatusChanges || checkboxesDirty;
101108
this.element.dataset.dirty = dirty ? 'true' : 'false';
102-
this.updateRoleFormDirtyParam(dirty);
109+
this.updateRoleDirtyParams(dirty);
103110
};
104111

105112
private onTabLinkClick = (event:Event) => {
106113
const target = (event.target as HTMLElement).closest<HTMLAnchorElement>('[data-workflow-tab-link]');
107114
if (!target) return;
108115
if (target.dataset.workflowTabCurrent === 'true') return;
109-
if (this.element.dataset.dirty !== 'true') return;
116+
if (this.element.dataset.dirty !== 'true' && !this.hasStatusChanges) return;
110117

111118
event.preventDefault();
112119
event.stopImmediatePropagation();
@@ -117,7 +124,7 @@ export default class WorkflowCheckboxStateController extends Controller<HTMLForm
117124
});
118125
};
119126

120-
private updateRoleFormDirtyParam(dirty:boolean):void {
127+
private updateRoleDirtyParams(dirty:boolean):void {
121128
const frame = this.element.closest('turbo-frame');
122129
frame?.querySelectorAll<HTMLFormElement>('[data-workflow-role-form]').forEach((form) => {
123130
const url = new URL(form.action);

spec/features/workflows/edit_spec.rb

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,29 @@ def remove_status_via_dialog(status)
273273
expect(page).to have_field workflow_checkbox(1, 0), checked: true
274274
end
275275
end
276+
277+
it "shows a confirmation dialog when switching tabs after adding a status" do
278+
add_status_via_dialog(statuses[2])
279+
expect(page).to have_field workflow_checkbox(0, 2)
280+
281+
click_link "User is author"
282+
283+
expect(page).to have_dialog("Save changes before continuing?")
284+
end
285+
286+
it "shows a confirmation dialog when switching tabs after removing a status" do
287+
remove_status_via_dialog(statuses[1])
288+
289+
within_dialog "Remove statuses" do
290+
click_button "Remove"
291+
end
292+
293+
expect(page).to have_no_field workflow_checkbox(0, 1)
294+
295+
click_link "User is author"
296+
297+
expect(page).to have_dialog("Save changes before continuing?")
298+
end
276299
end
277300

278301
context "when switching roles", :js do
@@ -370,6 +393,31 @@ def remove_status_via_dialog(status)
370393
expect(page).to have_field workflow_checkbox(1, 0), checked: true
371394
end
372395
end
396+
397+
it "shows a confirmation dialog when changing roles after adding a status" do
398+
add_status_via_dialog(statuses[2])
399+
expect(page).to have_no_field workflow_checkbox(0, 2)
400+
401+
click_button role.name
402+
click_button other_role.name
403+
404+
expect(page).to have_dialog("Save changes before continuing?")
405+
end
406+
407+
it "shows a confirmation dialog when changing roles after removing a status" do
408+
remove_status_via_dialog(statuses[1])
409+
410+
within_dialog "Remove statuses" do
411+
click_button "Remove"
412+
end
413+
414+
expect(page).to have_no_field workflow_checkbox(0, 1)
415+
416+
click_button role.name
417+
click_button other_role.name
418+
419+
expect(page).to have_dialog("Save changes before continuing?")
420+
end
373421
end
374422

375423
it "allows navigating to Workflow summary page" do

0 commit comments

Comments
 (0)