|
1 | 1 | <script> |
2 | 2 | import { page } from '$app/stores'; |
3 | | - import { displayStandardErrorAlert } from '$lib/common/errors'; |
| 3 | + import { AlertError, displayStandardErrorAlert } from '$lib/common/errors'; |
| 4 | + import Modal from '$lib/components/common/Modal.svelte'; |
4 | 5 | import JobsList from '$lib/components/jobs/JobsList.svelte'; |
5 | 6 |
|
6 | 7 | let searched = false; |
|
48 | 49 | } |
49 | 50 | } |
50 | 51 | jobs = jobs.map((j) => { |
| 52 | + if (j.status === 'failed') { |
| 53 | + // The admin has manually updated the job status while the AJAX call was in progress |
| 54 | + return j; |
| 55 | + } |
51 | 56 | const updatedJob = updatedJobs.find((uj) => uj.id === j.id); |
52 | 57 | return updatedJob ?? j; |
53 | 58 | }); |
|
218 | 223 | downloader.setAttribute('download', filename); |
219 | 224 | downloader.click(); |
220 | 225 | } |
| 226 | +
|
| 227 | + /** @type {Modal} */ |
| 228 | + let statusModal; |
| 229 | + /** @type {import('$lib/types').ApplyWorkflow|undefined} */ |
| 230 | + let jobInEditing; |
| 231 | +
|
| 232 | + /** |
| 233 | + * @param {import('$lib/types').ApplyWorkflow} row |
| 234 | + */ |
| 235 | + function openEditStatusModal(row) { |
| 236 | + jobInEditing = row; |
| 237 | + statusModal.show(); |
| 238 | + } |
| 239 | +
|
| 240 | + let updatingStatus = false; |
| 241 | +
|
| 242 | + async function updateJobStatus() { |
| 243 | + statusModal.confirmAndHide(async () => { |
| 244 | + updatingStatus = true; |
| 245 | + try { |
| 246 | + const jobId = /** @type {import('$lib/types').ApplyWorkflow} */ (jobInEditing).id; |
| 247 | +
|
| 248 | + const headers = new Headers(); |
| 249 | + headers.append('Content-Type', 'application/json'); |
| 250 | +
|
| 251 | + const response = await fetch(`/api/admin/job/${jobId}`, { |
| 252 | + method: 'PATCH', |
| 253 | + credentials: 'include', |
| 254 | + headers, |
| 255 | + body: JSON.stringify({ status: 'failed' }) |
| 256 | + }); |
| 257 | +
|
| 258 | + if (!response.ok) { |
| 259 | + throw new AlertError(await response.json()); |
| 260 | + } |
| 261 | +
|
| 262 | + jobs = jobs.map((j) => (j.id === jobId ? { ...j, status: 'failed' } : j)); |
| 263 | + jobsListComponent.setJobs(jobs); |
| 264 | + } finally { |
| 265 | + updatingStatus = false; |
| 266 | + } |
| 267 | + }); |
| 268 | + } |
221 | 269 | </script> |
222 | 270 |
|
223 | 271 | <div class="container"> |
|
367 | 415 | <div id="searchError" class="mt-3" /> |
368 | 416 |
|
369 | 417 | <div class:d-none={!searched}> |
370 | | - <JobsList {jobUpdater} bind:this={jobsListComponent} showFilters={false} hideCancelJobButton={true}> |
| 418 | + <JobsList {jobUpdater} bind:this={jobsListComponent} admin={true}> |
371 | 419 | <svelte:fragment slot="buttons"> |
372 | 420 | <button class="btn btn-outline-secondary" on:click={downloadCSV}> |
373 | 421 | <i class="bi-download" /> Download CSV |
374 | 422 | </button> |
375 | 423 | </svelte:fragment> |
| 424 | + <svelte:fragment slot="edit-status" let:row> |
| 425 | + {#if row.status !== 'failed'} |
| 426 | + |
| 427 | + <button class="btn btn-link p-0" on:click={() => openEditStatusModal(row)}> |
| 428 | + <i class="bi bi-pencil" /> |
| 429 | + </button> |
| 430 | + {/if} |
| 431 | + </svelte:fragment> |
376 | 432 | </JobsList> |
377 | 433 | </div> |
378 | 434 | </div> |
379 | 435 |
|
| 436 | +<Modal id="editJobStatusModal" bind:this={statusModal} centered={true} size="md"> |
| 437 | + <svelte:fragment slot="header"> |
| 438 | + {#if jobInEditing} |
| 439 | + <h1 class="h5 modal-title flex-grow-1">Editing job #{jobInEditing.id}</h1> |
| 440 | + {/if} |
| 441 | + </svelte:fragment> |
| 442 | + <svelte:fragment slot="body"> |
| 443 | + <div id="errorAlert-editJobStatusModal" /> |
| 444 | + <div class="alert alert-warning"> |
| 445 | + <i class="bi bi-exclamation-triangle" /> |
| 446 | + <strong>Warning</strong>: this operation will not cancel job execution but only modify its |
| 447 | + status in the database |
| 448 | + </div> |
| 449 | + <div class="d-flex justify-content-center"> |
| 450 | + <button class="btn btn-danger" on:click={updateJobStatus} disabled={updatingStatus}> |
| 451 | + Set status to failed |
| 452 | + </button> |
| 453 | + |
| 454 | + <button class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button> |
| 455 | + </div> |
| 456 | + </svelte:fragment> |
| 457 | +</Modal> |
| 458 | +
|
380 | 459 | <style> |
381 | 460 | input[type='date'] { |
382 | 461 | min-width: 190px; |
|
0 commit comments