|
29 | 29 | /** @type {(import('fractal-components/types/api').Pagination<import('fractal-components/types/api').HistoryUnit>)|undefined} */ |
30 | 30 | let data = undefined; |
31 | 31 |
|
| 32 | + /** @type {import('fractal-components/types/api').HistoryUnit|undefined} */ |
| 33 | + let selectedUnit = undefined; |
| 34 | +
|
32 | 35 | let loadingLogs = false; |
33 | | - /** @type {number|undefined} */ |
34 | | - let selectedLogUnit = undefined; |
35 | 36 | /** @type {Array<{text: string, highlight: boolean}>} */ |
36 | 37 | let logParts = []; |
37 | 38 | let loadedLogsStatus = ''; |
38 | 39 |
|
| 40 | + let showLogs = false; |
| 41 | + let showZarrUrls = false; |
| 42 | +
|
39 | 43 | let statusFilter = ''; |
40 | 44 | /** @type {SlimSelect|undefined} */ |
41 | 45 | let statusFilterSelector = undefined; |
|
60 | 64 | datasetId = _datasetId; |
61 | 65 | workflowTaskId = _workflowTaskId; |
62 | 66 | historyRunIndex = _historyRunIndex; |
| 67 | + selectedUnit = undefined; |
| 68 | + showLogs = false; |
| 69 | + showZarrUrls = false; |
63 | 70 | data = undefined; |
64 | 71 | page = 1; |
65 | 72 | pageSize = 10; |
|
101 | 108 | } |
102 | 109 |
|
103 | 110 | /** |
104 | | - * @param {number} unitId |
105 | | - * @param {string} status |
| 111 | + * @param {import('fractal-components/types/api').HistoryUnit} unit |
106 | 112 | */ |
107 | | - async function loadLogs(unitId, status) { |
| 113 | + async function loadLogs(unit) { |
108 | 114 | unsetStatusFilterSelector(); |
109 | 115 | loadingLogs = true; |
110 | 116 | const response = await fetch( |
111 | | - `/api/v2/project/${projectId}/status/unit-log?history_run_id=${historyRunId}&history_unit_id=${unitId}&workflowtask_id=${workflowTaskId}&dataset_id=${datasetId}`, |
| 117 | + `/api/v2/project/${projectId}/status/unit-log?history_run_id=${historyRunId}&history_unit_id=${unit.id}&workflowtask_id=${workflowTaskId}&dataset_id=${datasetId}`, |
112 | 118 | { |
113 | 119 | method: 'GET' |
114 | 120 | } |
|
119 | 125 | return; |
120 | 126 | } |
121 | 127 | const log = await response.json(); |
122 | | - loadedLogsStatus = status; |
123 | | - if (status === 'failed') { |
| 128 | + loadedLogsStatus = unit.status; |
| 129 | + if (unit.status === 'failed') { |
124 | 130 | logParts = extractJobErrorParts(log, false, true); |
125 | 131 | } else { |
126 | 132 | logParts = [{ text: log, highlight: false }]; |
127 | 133 | } |
128 | | - selectedLogUnit = unitId; |
| 134 | + selectedUnit = unit; |
129 | 135 | loadingLogs = false; |
| 136 | + showLogs = true; |
| 137 | + } |
| 138 | +
|
| 139 | + /** |
| 140 | + * @param {import('fractal-components/types/api').HistoryUnit} unit |
| 141 | + */ |
| 142 | + async function displayZarrUrls(unit) { |
| 143 | + unsetStatusFilterSelector(); |
| 144 | + showZarrUrls = true; |
| 145 | + selectedUnit = unit; |
| 146 | + await tick(); |
| 147 | + restoreModalFocus(); |
130 | 148 | } |
131 | 149 |
|
132 | 150 | async function back() { |
133 | | - selectedLogUnit = undefined; |
| 151 | + showZarrUrls = false; |
| 152 | + showLogs = false; |
| 153 | + selectedUnit = undefined; |
134 | 154 | await tick(); |
135 | 155 | setStatusFilterSelector(); |
136 | 156 | } |
|
181 | 201 | page = 1; |
182 | 202 | await loadRun(page, pageSize); |
183 | 203 | } |
| 204 | +
|
| 205 | + /** |
| 206 | + * Restore focus on modal, otherwise it will not be possible to close it using the esc key |
| 207 | + */ |
| 208 | + function restoreModalFocus() { |
| 209 | + const modal = document.querySelector('.modal.show'); |
| 210 | + if (modal instanceof HTMLElement) { |
| 211 | + modal.focus(); |
| 212 | + } |
| 213 | + } |
184 | 214 | </script> |
185 | 215 |
|
186 | 216 | <Modal id="runStatusModal" bind:this={modal} fullscreen={true} bodyCss="p-0" {onClose}> |
187 | 217 | <svelte:fragment slot="header"> |
188 | 218 | <h1 class="modal-title fs-5"> |
189 | | - {#if selectedLogUnit && !loadingLogs} |
190 | | - Run {historyRunIndex} - Logs for unit #{selectedLogUnit} |
| 219 | + {#if showLogs && !loadingLogs} |
| 220 | + Run {historyRunIndex} - Logs for unit #{selectedUnit?.id} |
| 221 | + {:else if showZarrUrls} |
| 222 | + Run {historyRunIndex} - Zarr URLs for unit #{selectedUnit?.id} |
191 | 223 | {:else} |
192 | 224 | Run {historyRunIndex} |
193 | 225 | {/if} |
|
197 | 229 | <div id="errorAlert-runStatusModal" class="mb-2" /> |
198 | 230 | {#if loading && !data} |
199 | 231 | <span class="spinner-border spinner-border-sm" role="status" aria-hidden="true" /> |
200 | | - {:else if selectedLogUnit && !loadingLogs} |
| 232 | + {:else if showLogs && !loadingLogs} |
201 | 233 | <div class="row"> |
202 | 234 | <div class="col"> |
203 | 235 | <ExpandableLog bind:logParts highlight={loadedLogsStatus === 'failed'} /> |
|
208 | 240 | <button class="m-2 ms-3 btn btn-primary" on:click={back}> Back </button> |
209 | 241 | </div> |
210 | 242 | </div> |
| 243 | + {:else if showZarrUrls && selectedUnit} |
| 244 | + <div class="row"> |
| 245 | + <div class="col"> |
| 246 | + <table class="table table-striped"> |
| 247 | + <tbody> |
| 248 | + {#each selectedUnit.zarr_urls as zarrUrl} |
| 249 | + <tr> |
| 250 | + <td>{zarrUrl}</td> |
| 251 | + </tr> |
| 252 | + {/each} |
| 253 | + </tbody> |
| 254 | + </table> |
| 255 | + </div> |
| 256 | + </div> |
| 257 | + <div class="row"> |
| 258 | + <div class="col"> |
| 259 | + <button class="m-2 ms-3 btn btn-primary" on:click={back}> Back </button> |
| 260 | + </div> |
| 261 | + </div> |
211 | 262 | {:else if data} |
212 | 263 | <table class="table table-striped"> |
213 | 264 | <colgroup> |
|
230 | 281 | </tr> |
231 | 282 | </thead> |
232 | 283 | <tbody> |
233 | | - {#each data.items as run} |
| 284 | + {#each data.items as unit} |
234 | 285 | <tr> |
235 | | - <td>{run.id}</td> |
236 | | - <td>{run.status || '-'}</td> |
| 286 | + <td>{unit.id}</td> |
| 287 | + <td>{unit.status || '-'}</td> |
237 | 288 | <td> |
238 | | - <button class="btn btn-light" on:click={() => loadLogs(run.id, run.status)}> |
| 289 | + <button |
| 290 | + class="btn btn-light me-2" |
| 291 | + on:click={() => loadLogs(unit)} |
| 292 | + disabled={loadingLogs} |
| 293 | + > |
239 | 294 | {#if loadingLogs} |
240 | 295 | <span |
241 | 296 | class="spinner-border spinner-border-sm" |
|
245 | 300 | {/if} |
246 | 301 | <i class="bi-list-columns-reverse" /> Logs |
247 | 302 | </button> |
| 303 | + <button class="btn btn-light" on:click={() => displayZarrUrls(unit)}> |
| 304 | + <i class="bi bi-list-task" /> Zarr URLs |
| 305 | + </button> |
248 | 306 | </td> |
249 | 307 | </tr> |
250 | 308 | {/each} |
|
0 commit comments