Skip to content

Commit 86f07d4

Browse files
authored
Merge pull request #234 from fractal-analytics-platform/don't-allow-users-to-leave-a-workflow-task-page-with-unsaved-changes
2 parents e9322ea + acc307a commit 86f07d4

File tree

2 files changed

+79
-16
lines changed

2 files changed

+79
-16
lines changed

src/lib/components/workflow/ArgumentsSchema.svelte

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@
1717
export let args = undefined;
1818
1919
let schemaComponent = undefined;
20-
let unsavedChanges = false;
20+
export let unsavedChanges = false;
2121
let resetChanges = undefined;
22-
let saveChanges = undefined;
22+
export let saveChanges = undefined;
2323
2424
function handleSaveChanges(newArgs) {
2525
return new Promise((resolve, reject) => {
@@ -89,13 +89,13 @@
8989
</div>
9090
<div class='d-flex justify-content-end jschema-controls-bar p-3'>
9191
<div>
92-
<button class='btn btn-success {unsavedChanges ? "" : "disabled"}' on:click={saveChanges}>
93-
Save changes
92+
<button class='btn btn-warning {unsavedChanges ? "" : "disabled"}' on:click={resetChanges.bind(this, args)}>
93+
Discard changes
9494
</button>
9595
</div>
9696
<div class='ms-1'>
97-
<button class='btn btn-warning {unsavedChanges ? "" : "disabled"}' on:click={resetChanges.bind(this, args)}>
98-
Discard changes
97+
<button class='btn btn-success {unsavedChanges ? "" : "disabled"}' on:click={saveChanges}>
98+
Save changes
9999
</button>
100100
</div>
101101
</div>

src/routes/projects/[projectId]/workflows/[workflowId]/+page.svelte

Lines changed: 73 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import { onMount } from 'svelte';
33
import { writable } from 'svelte/store';
44
import { enhance } from '$app/forms';
5-
import { goto } from '$app/navigation';
5+
import { goto, beforeNavigate } from '$app/navigation';
66
import { page } from '$app/stores';
77
import ArgumentForm from '$lib/components/workflow/ArgumentForm.svelte';
88
import ConfirmActionButton from '$lib/components/common/ConfirmActionButton.svelte';
@@ -30,6 +30,9 @@
3030
let argsSchemaAvailable = undefined;
3131
let argsSchemaValid = undefined;
3232
let argsChangesSaved = false;
33+
let argumentsWithUnsavedChanges = false;
34+
let saveArgumentsChanges = undefined;
35+
let preventedTaskContextChange = undefined;
3336
3437
$: updatableWorkflowList = workflow?.task_list || [];
3538
@@ -43,6 +46,15 @@
4346
datasets = $page.data.datasets;
4447
});
4548
49+
beforeNavigate((navigation) => {
50+
if (argumentsWithUnsavedChanges === true) {
51+
// Prevent navigation
52+
navigation.cancel();
53+
// Toggle the modal
54+
toggleUnsavedChangesModal();
55+
}
56+
});
57+
4658
async function handleExportWorkflow() {
4759
const response = await fetch(`/projects/${project.id}/workflows/${workflow.id}/export`, {
4860
method: 'GET',
@@ -142,6 +154,21 @@
142154
async function setActiveWorkflowTaskContext(event) {
143155
const workflowTaskId = event.currentTarget.getAttribute('data-fs-target');
144156
const wft = workflow.task_list.find((task) => task.id == workflowTaskId);
157+
if (argumentsWithUnsavedChanges === true) {
158+
toggleUnsavedChangesModal();
159+
preventedTaskContextChange = wft;
160+
throw new Error('Cannot change workflow task context while there are unsaved changes');
161+
}
162+
setWorkflowTaskContext(wft);
163+
}
164+
165+
function toggleUnsavedChangesModal() {
166+
// eslint-disable-next-line no-undef
167+
const modal = new bootstrap.Modal(document.getElementById('changes-unsaved-dialog'), {});
168+
modal.toggle();
169+
}
170+
171+
function setWorkflowTaskContext(wft) {
145172
workflowTaskContext.set(wft);
146173
// Check if args schema is available
147174
argsSchemaAvailable = wft.task.args_schema === undefined || wft.task.args_schema === null ? false : true;
@@ -293,18 +320,27 @@
293320
</ol>
294321
</nav>
295322
<div>
296-
<a href="/projects/{project?.id}/jobs?workflow={workflow?.id}" class="btn btn-light"
297-
><i class="bi-journal-code" /> List jobs</a
323+
<a href='/projects/{project?.id}/jobs?workflow={workflow?.id}' class='btn btn-light'
324+
><i class='bi-journal-code' /> List jobs</a
298325
>
299-
<button class="btn btn-light" on:click|preventDefault={handleExportWorkflow}
300-
><i class="bi-box-arrow-up" /></button
326+
<button class='btn btn-light' on:click|preventDefault={handleExportWorkflow}
327+
><i class='bi-box-arrow-up' /></button
301328
>
302-
<a id="downloadWorkflowButton" class="d-none">Download workflow link</a>
303-
<button class="btn btn-light" data-bs-toggle="modal" data-bs-target="#editWorkflowModal"
304-
><i class="bi-gear-wide-connected" /></button
329+
<a id='downloadWorkflowButton' class='d-none'>Download workflow link</a>
330+
<button class='btn btn-light' data-bs-toggle='modal' data-bs-target='#editWorkflowModal'
331+
><i class='bi-gear-wide-connected' /></button
305332
>
306-
<button class="btn btn-success" data-bs-toggle="modal" data-bs-target="#runWorkflowModal"
307-
><i class="bi-play-fill" /> Run workflow</button
333+
<button class='btn btn-success' on:click|preventDefault={() => {
334+
if (argumentsWithUnsavedChanges === false) {
335+
// eslint-disable-next-line no-undef
336+
const modal = new bootstrap.Modal(document.getElementById('runWorkflowModal'));
337+
modal.toggle();
338+
} else {
339+
toggleUnsavedChangesModal()
340+
}
341+
}}
342+
><i class='bi-play-fill' /> Run workflow
343+
</button
308344
>
309345
</div>
310346
</div>
@@ -419,7 +455,9 @@
419455
argumentsSchema={selectedWorkflowTask.task.args_schema}
420456
argumentsSchemaVersion={selectedWorkflowTask.task.args_schema_version}
421457
args={selectedWorkflowTask.args}
458+
bind:saveChanges={saveArgumentsChanges}
422459
bind:validSchema={argsSchemaValid}
460+
bind:unsavedChanges={argumentsWithUnsavedChanges}
423461
on:argsSaved={handleArgsSaved}
424462
></ArgumentsSchema>
425463
{:else}
@@ -662,3 +700,28 @@
662700
</div>
663701
</div>
664702
</div>
703+
704+
<div class='modal' tabindex='-1' id='changes-unsaved-dialog'>
705+
<div class='modal-dialog'>
706+
<div class='modal-content'>
707+
<div class='modal-header'>
708+
<h5 class='modal-title'>There are argument changes unsaved</h5>
709+
<button type='button' class='btn-close' data-bs-dismiss='modal' aria-label='Close'></button>
710+
</div>
711+
<div class='modal-body'>
712+
<p>Do you want to save the changes made to the arguments of the current selected workflow task?</p>
713+
</div>
714+
<div class='modal-footer'>
715+
<button type='button' class='btn btn-secondary' data-bs-dismiss='modal'>Cancel</button>
716+
<button type='button' class='btn btn-warning' on:click={ () => {
717+
argumentsWithUnsavedChanges = false
718+
setWorkflowTaskContext(preventedTaskContextChange)
719+
}} data-bs-dismiss='modal'>Discard changes
720+
</button>
721+
<button type='button' class='btn btn-success' on:click={saveArgumentsChanges} data-bs-dismiss='modal'>Save
722+
changes
723+
</button>
724+
</div>
725+
</div>
726+
</div>
727+
</div>

0 commit comments

Comments
 (0)