feat(frontend): streamline job creation actions
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { Plus, RotateCcw } from "lucide-react";
|
||||
import { Eye, Plus, RotateCcw } from "lucide-react";
|
||||
import { FormEvent, useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { toast } from "sonner";
|
||||
@@ -93,6 +93,7 @@ export function JobsPage() {
|
||||
max_attempts: nextMaxAttempts
|
||||
});
|
||||
await refresh();
|
||||
setCreateOpen(false);
|
||||
toast.success("Demo job created.");
|
||||
} catch (caught) {
|
||||
toast.error(caught instanceof Error ? caught.message : String(caught));
|
||||
@@ -115,6 +116,7 @@ export function JobsPage() {
|
||||
try {
|
||||
await Promise.all(batch.map(([type, nextPriority]) => api.createJob({ type, payload: demoPayload(type), priority: nextPriority, max_attempts: 3 })));
|
||||
await refresh();
|
||||
setCreateOpen(false);
|
||||
toast.success("Batch created.");
|
||||
} catch (caught) {
|
||||
toast.error(caught instanceof Error ? caught.message : String(caught));
|
||||
@@ -135,29 +137,6 @@ export function JobsPage() {
|
||||
</button>
|
||||
</header>
|
||||
|
||||
<section className="panel">
|
||||
<div className="row-actions">
|
||||
<button type="button" onClick={() => void createDemo("demo.success", 60)}>
|
||||
Success
|
||||
</button>
|
||||
<button type="button" onClick={() => void createDemo("demo.fail", 50, 2)}>
|
||||
Failing
|
||||
</button>
|
||||
<button type="button" onClick={() => void createDemo("demo.slow", 80)}>
|
||||
Slow
|
||||
</button>
|
||||
<button type="button" onClick={() => void createDemo("demo.timeout", 70, 2)}>
|
||||
Timeout
|
||||
</button>
|
||||
<button type="button" onClick={() => void createDemo("demo.flaky", 75, 3)}>
|
||||
Flaky Retry
|
||||
</button>
|
||||
<button type="button" onClick={() => void createBatch()}>
|
||||
<RotateCcw size={16} /> 10 Mixed
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="panel">
|
||||
<div className="toolbar">
|
||||
<SelectField value={statusFilter} options={statusOptions} onChange={(value) => setStatusFilter(value as JobStatus | "all")} />
|
||||
@@ -182,7 +161,9 @@ export function JobsPage() {
|
||||
<td>
|
||||
<StatusBadge status={job.status} />
|
||||
</td>
|
||||
<td>{job.type}</td>
|
||||
<td>
|
||||
<code className="inline-code">{job.type}</code>
|
||||
</td>
|
||||
<td>{job.priority}</td>
|
||||
<td>
|
||||
{job.attempts}/{job.max_attempts}
|
||||
@@ -192,8 +173,8 @@ export function JobsPage() {
|
||||
</td>
|
||||
<td>{job.locked_by ?? "-"}</td>
|
||||
<td>
|
||||
<Link className="secondary-button" to={`/jobs/${job.id}`}>
|
||||
Detail
|
||||
<Link className="icon-button" aria-label={`view ${job.type}`} title="View job" to={`/jobs/${job.id}`}>
|
||||
<Eye size={18} />
|
||||
</Link>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -207,6 +188,26 @@ export function JobsPage() {
|
||||
{createOpen && (
|
||||
<Modal title="Create Job" onClose={() => setCreateOpen(false)}>
|
||||
<form className="modal-form" onSubmit={createJob}>
|
||||
<div className="preset-grid">
|
||||
<button className="secondary-button" type="button" onClick={() => setType("demo.success")}>
|
||||
Success
|
||||
</button>
|
||||
<button className="secondary-button" type="button" onClick={() => setType("demo.fail")}>
|
||||
Failing
|
||||
</button>
|
||||
<button className="secondary-button" type="button" onClick={() => setType("demo.slow")}>
|
||||
Slow
|
||||
</button>
|
||||
<button className="secondary-button" type="button" onClick={() => setType("demo.timeout")}>
|
||||
Timeout
|
||||
</button>
|
||||
<button className="secondary-button" type="button" onClick={() => setType("demo.flaky")}>
|
||||
Flaky Retry
|
||||
</button>
|
||||
<button className="secondary-button" type="button" onClick={() => void createBatch()}>
|
||||
<RotateCcw size={16} /> 10 Mixed
|
||||
</button>
|
||||
</div>
|
||||
<SelectField label="Job type" value={jobType} options={jobTypeOptions} onChange={setType} />
|
||||
<JsonField label="Payload JSON" value={payload} onChange={setPayload} />
|
||||
<label>
|
||||
@@ -226,6 +227,9 @@ export function JobsPage() {
|
||||
<input value={idempotencyKey} onChange={(event) => setIdempotencyKey(event.target.value)} />
|
||||
</label>
|
||||
<div className="modal-actions">
|
||||
<button className="secondary-button" type="button" onClick={() => void createDemo(jobType, priority, maxAttempts)}>
|
||||
Quick Create
|
||||
</button>
|
||||
<button className="secondary-button" type="button" onClick={() => setCreateOpen(false)}>
|
||||
Cancel
|
||||
</button>
|
||||
|
||||
@@ -992,6 +992,12 @@ code {
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.inline-code {
|
||||
max-width: 100%;
|
||||
padding: 4px 7px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.action-grid {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
@@ -1004,6 +1010,12 @@ code {
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.preset-grid {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.checkbox-row {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
@@ -1164,6 +1176,7 @@ code {
|
||||
|
||||
.modal-backdrop {
|
||||
align-items: center;
|
||||
backdrop-filter: blur(10px);
|
||||
background: rgb(0 0 0 / 48%);
|
||||
display: flex;
|
||||
inset: 0;
|
||||
|
||||
Reference in New Issue
Block a user