Skip to content

Commit eb02055

Browse files
committed
Switching datasets on continue workflow applies correct filters
1 parent 7071913 commit eb02055

File tree

5 files changed

+305
-117
lines changed

5 files changed

+305
-117
lines changed

src/lib/components/v2/projects/datasets/DatasetImagesTable.svelte

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import BooleanIcon from 'fractal-components/common/BooleanIcon.svelte';
77
import { objectChanged } from '$lib/common/component_utilities';
88
import SlimSelect from 'slim-select';
9-
import { onMount, tick } from 'svelte';
9+
import { onDestroy, tick } from 'svelte';
1010
1111
/** @type {import('fractal-components/types/api').DatasetV2} */
1212
export let dataset;
@@ -37,7 +37,7 @@
3737
3838
let reloading = false;
3939
/** @type {{ [key: string]: Array<string | number | boolean> | null}} */
40-
let attributeFilters = getAttributeFilterBaseValues(imagePage);
40+
let attributeFilters = {};
4141
4242
export function getAttributeFilters() {
4343
return removeNullValues(attributeFilters);
@@ -48,7 +48,7 @@
4848
}
4949
5050
/** @type {{ [key: string]: boolean | null }}} */
51-
let typeFilters = getTypeFilterBaseValues(imagePage);
51+
let typeFilters = {};
5252
/** @type {import('$lib/components/common/StandardErrorAlert.svelte').default|undefined} */
5353
let errorAlert = undefined;
5454
@@ -150,9 +150,17 @@
150150
reloading = false;
151151
}
152152
153-
onMount(() => {
154-
loadAttributesSelectors();
155-
loadTypesSelector();
153+
onDestroy(() => {
154+
for (const selector of Object.values(attributesSelectors)) {
155+
selector.destroy();
156+
}
157+
for (const selector of Object.values(typesSelectors)) {
158+
selector.destroy();
159+
}
160+
attributesSelectors = {};
161+
typesSelectors = {};
162+
attributeFilters = {};
163+
typeFilters = {};
156164
});
157165
158166
function loadAttributesSelectors() {
@@ -233,6 +241,7 @@
233241
throw new Error(`Unable to find selector element with key ${key}`);
234242
}
235243
selectElement.classList.remove('invisible');
244+
selectElement.setAttribute('multiple', 'multiple');
236245
const selector = new SlimSelect({
237246
select: `#${elementId}`,
238247
settings: {
@@ -577,11 +586,7 @@
577586
<div class="row">
578587
<div class="col">
579588
<div class="attribute-select-wrapper mb-1">
580-
<select
581-
id="attribute-{getIdFromValue(attributeKey)}"
582-
class="invisible"
583-
multiple
584-
/>
589+
<select id="attribute-{getIdFromValue(attributeKey)}" class="invisible" />
585590
</div>
586591
</div>
587592
</div>

src/lib/components/v2/workflow/RunWorkflowModal.svelte

Lines changed: 99 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
} from '$lib/common/job_utilities';
88
import BooleanIcon from 'fractal-components/common/BooleanIcon.svelte';
99
import Modal from '$lib/components/common/Modal.svelte';
10-
import { onMount } from 'svelte';
10+
import { onMount, tick } from 'svelte';
1111
import DatasetImagesTable from '../projects/datasets/DatasetImagesTable.svelte';
1212
1313
/** @type {import('fractal-components/types/api').DatasetV2[]} */
@@ -291,24 +291,22 @@
291291
imagePage = await response.json();
292292
}
293293
datasetImagesLoading = false;
294+
await tick();
295+
datasetImagesTable?.reload();
296+
}
297+
298+
async function cancel() {
299+
checkingConfiguration = false;
300+
await tick();
301+
datasetImagesTable?.reload();
294302
}
295303
296304
onMount(async () => {
297305
await loadSlurmAccounts();
298306
});
299-
300-
let opened = false;
301307
</script>
302308
303-
<Modal
304-
id="runWorkflowModal"
305-
centered={true}
306-
bind:this={modal}
307-
size="xl"
308-
onOpen={() => (opened = true)}
309-
onClose={() => (opened = false)}
310-
scrollable={true}
311-
>
309+
<Modal id="runWorkflowModal" centered={true} bind:this={modal} size="xl" scrollable={true}>
312310
<svelte:fragment slot="header">
313311
<h5 class="modal-title">
314312
{#if mode === 'run'}
@@ -424,117 +422,114 @@
424422
{/each}
425423
</select>
426424
</div>
427-
{#key opened}
428-
<div class="accordion" id="accordion-run-workflow">
425+
<div class="accordion" id="accordion-run-workflow">
426+
<div class="accordion-item">
427+
<h2 class="accordion-header">
428+
<button
429+
class="accordion-button collapsed"
430+
type="button"
431+
data-bs-toggle="collapse"
432+
data-bs-target="#collapse-workflow-advanced-options"
433+
aria-expanded="false"
434+
aria-controls="collapse-workflow-advanced-options"
435+
>
436+
Advanced options
437+
</button>
438+
</h2>
439+
<div
440+
id="collapse-workflow-advanced-options"
441+
class="accordion-collapse collapse"
442+
data-bs-parent="#accordion-run-workflow"
443+
>
444+
<div class="accordion-body">
445+
<div class="mb-3">
446+
<label for="workerInit" class="form-label">Worker initialization (Optional)</label>
447+
<textarea
448+
name="workerInit"
449+
id="workerInit"
450+
class="form-control font-monospace"
451+
rows="5"
452+
disabled={checkingConfiguration}
453+
bind:value={workerInitControl}
454+
/>
455+
</div>
456+
{#if slurmAccounts.length > 0}
457+
<div class="mb-3">
458+
<div class="form-check">
459+
<input
460+
class="form-check-input"
461+
type="checkbox"
462+
id="setSlurmAccount"
463+
bind:checked={setSlurmAccount}
464+
/>
465+
<label class="form-check-label" for="setSlurmAccount">
466+
Set SLURM account
467+
</label>
468+
</div>
469+
</div>
470+
{#if setSlurmAccount}
471+
<div class="mb-3">
472+
<label for="slurmAccount" class="form-label">SLURM account</label>
473+
<select
474+
name="slurmAccount"
475+
id="slurmAccount"
476+
class="form-select"
477+
disabled={checkingConfiguration}
478+
bind:value={slurmAccount}
479+
>
480+
{#each slurmAccounts as account}
481+
<option>{account}</option>
482+
{/each}
483+
</select>
484+
</div>
485+
{/if}
486+
{/if}
487+
</div>
488+
</div>
489+
</div>
490+
{#if selectedDataset && imagePage && imagePage.images.length > 0 && firstTaskIndex !== undefined && mode !== 'restart'}
429491
<div class="accordion-item">
430492
<h2 class="accordion-header">
431493
<button
432494
class="accordion-button collapsed"
433495
type="button"
434496
data-bs-toggle="collapse"
435-
data-bs-target="#collapse-workflow-advanced-options"
497+
data-bs-target="#collapse-workflow-image-list"
436498
aria-expanded="false"
437-
aria-controls="collapse-workflow-advanced-options"
499+
aria-controls="collapse-workflow-image-list"
438500
>
439-
Advanced options
501+
Image list
440502
</button>
441503
</h2>
442504
<div
443-
id="collapse-workflow-advanced-options"
505+
id="collapse-workflow-image-list"
444506
class="accordion-collapse collapse"
445507
data-bs-parent="#accordion-run-workflow"
446508
>
447509
<div class="accordion-body">
448-
<div class="mb-3">
449-
<label for="workerInit" class="form-label">Worker initialization (Optional)</label
450-
>
451-
<textarea
452-
name="workerInit"
453-
id="workerInit"
454-
class="form-control font-monospace"
455-
rows="5"
456-
disabled={checkingConfiguration}
457-
bind:value={workerInitControl}
510+
{#if checkingConfiguration}
511+
This job will process {imagePage.total_count}
512+
{imagePage.total_count === 1 ? 'image' : 'images'}.
513+
{:else}
514+
<DatasetImagesTable
515+
bind:this={datasetImagesTable}
516+
dataset={selectedDataset}
517+
bind:imagePage
518+
{initialFilterValues}
519+
{attributeFiltersEnabled}
520+
useDatasetFilters={false}
521+
vizarrViewerUrl={null}
522+
runWorkflowModal={true}
458523
/>
459-
</div>
460-
{#if slurmAccounts.length > 0}
461-
<div class="mb-3">
462-
<div class="form-check">
463-
<input
464-
class="form-check-input"
465-
type="checkbox"
466-
id="setSlurmAccount"
467-
bind:checked={setSlurmAccount}
468-
/>
469-
<label class="form-check-label" for="setSlurmAccount">
470-
Set SLURM account
471-
</label>
472-
</div>
473-
</div>
474-
{#if setSlurmAccount}
475-
<div class="mb-3">
476-
<label for="slurmAccount" class="form-label">SLURM account</label>
477-
<select
478-
name="slurmAccount"
479-
id="slurmAccount"
480-
class="form-select"
481-
disabled={checkingConfiguration}
482-
bind:value={slurmAccount}
483-
>
484-
{#each slurmAccounts as account}
485-
<option>{account}</option>
486-
{/each}
487-
</select>
488-
</div>
489-
{/if}
490524
{/if}
491525
</div>
492526
</div>
493527
</div>
494-
{#if selectedDataset && imagePage && imagePage.images.length > 0 && firstTaskIndex !== undefined && mode !== 'restart'}
495-
<div class="accordion-item">
496-
<h2 class="accordion-header">
497-
<button
498-
class="accordion-button collapsed"
499-
type="button"
500-
data-bs-toggle="collapse"
501-
data-bs-target="#collapse-workflow-image-list"
502-
aria-expanded="false"
503-
aria-controls="collapse-workflow-image-list"
504-
>
505-
Image list
506-
</button>
507-
</h2>
508-
<div
509-
id="collapse-workflow-image-list"
510-
class="accordion-collapse collapse"
511-
data-bs-parent="#accordion-run-workflow"
512-
>
513-
<div class="accordion-body">
514-
{#if checkingConfiguration}
515-
This job will process {imagePage.total_count}
516-
{imagePage.total_count === 1 ? 'image' : 'images'}.
517-
{:else}
518-
<DatasetImagesTable
519-
bind:this={datasetImagesTable}
520-
dataset={selectedDataset}
521-
bind:imagePage
522-
{initialFilterValues}
523-
{attributeFiltersEnabled}
524-
useDatasetFilters={false}
525-
vizarrViewerUrl={null}
526-
runWorkflowModal={true}
527-
/>
528-
{/if}
529-
</div>
530-
</div>
531-
</div>
532-
{/if}
533-
{#if datasetImagesLoading}
534-
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true" />
535-
{/if}
536-
</div>
537-
{/key}
528+
{/if}
529+
{#if datasetImagesLoading}
530+
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true" />
531+
{/if}
532+
</div>
538533
{#if checkingConfiguration}
539534
<hr />
540535
<h6 class="mt-3">Applied filters</h6>
@@ -561,9 +556,7 @@
561556
</svelte:fragment>
562557
<svelte:fragment slot="footer">
563558
{#if checkingConfiguration}
564-
<button class="btn btn-warning" on:click={() => (checkingConfiguration = false)}>
565-
Cancel
566-
</button>
559+
<button class="btn btn-warning" on:click={cancel}> Cancel </button>
567560
<button
568561
class="btn btn-primary"
569562
on:click|preventDefault={handleApplyWorkflow}

src/routes/v2/projects/[projectId]/datasets/[datasetId]/+page.svelte

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import { env } from '$env/dynamic/public';
66
import DatasetImagesTable from '$lib/components/v2/projects/datasets/DatasetImagesTable.svelte';
77
import { displayStandardErrorAlert, getAlertErrorFromResponse } from '$lib/common/errors';
8+
import { onMount } from 'svelte';
89
910
const vizarrViewerUrl = env.PUBLIC_FRACTAL_VIZARR_VIEWER_URL
1011
? env.PUBLIC_FRACTAL_VIZARR_VIEWER_URL.replace(/\/$|$/, '/')
@@ -156,6 +157,10 @@
156157
linkElement.click();
157158
}
158159
}
160+
161+
onMount(() => {
162+
imagesTable.reload();
163+
});
159164
</script>
160165
161166
<div class="d-flex justify-content-between align-items-center">

tests/utils.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,32 @@ export async function selectSlimSelect(page, selector, optionValue, multiple = f
8989
);
9090
}
9191

92+
/**
93+
* @param {import('@playwright/test').Page} page
94+
* @param {import('@playwright/test').Locator} selector
95+
* @returns {Promise<string | string[] | null>}
96+
*/
97+
export async function getSlimSelectValues(page, selector) {
98+
const dataId = await selector.getAttribute('data-id');
99+
if (dataId === null) {
100+
throw new Error(`Unable to retrieve slim select data-id`);
101+
}
102+
const dropdown = page.locator(`select[data-id="${dataId}"]`);
103+
const id = await dropdown.getAttribute('id');
104+
if (id === null) {
105+
throw new Error(`Unable to retrieve slim select id`);
106+
}
107+
108+
return await page.evaluate((id) => {
109+
const element = document.getElementById(id);
110+
if (element && 'slim' in element) {
111+
const slimSelect = /** @type {any} */ (element.slim);
112+
return slimSelect.getSelected();
113+
}
114+
return null;
115+
}, id);
116+
}
117+
92118
/**
93119
* @param {import('@playwright/test').Page} page
94120
* @param {string} email

0 commit comments

Comments
 (0)