Frontend checkbox fixes

This commit is contained in:
sriram
2026-09-01 11:27:08 +05:30
parent 21642c172b
commit b677ddf9e6
2 changed files with 170 additions and 62 deletions

View File

@@ -140,6 +140,11 @@ export function InboxPanel({ onBatchStarted }) {
const submissions = data?.submissions || [];
const pending = data?.pending_count ?? 0;
// Nothing ticked means "Start selected" cannot fire, which makes the two
// stage toggles below inert. On a deployment running UPLOAD_AUTORUN=true that
// is the permanent state - this inbox never fills - so they stay greyed, which
// is exactly the point: they must not read as settings that govern uploads.
const stagesIdle = !selected.size;
return (
<div className="space-y-6">
@@ -150,10 +155,12 @@ export function InboxPanel({ onBatchStarted }) {
<Inbox className="h-5 w-5 text-amber-500" /> Review Inbox
</h2>
<p className="text-xs text-slate-500 leading-relaxed max-w-3xl">
Spreadsheets sent in by a colleague through the upload API. Nothing here has run
yet &mdash; tick the files you want and press <strong>Start selected</strong> to
send them through the 11-stage pipeline as one batch. Files from different drops
can go in the same batch.
Where spreadsheets wait <strong>when <code className="font-mono">UPLOAD_AUTORUN</code>
{' '}is off</strong>. Nothing here has run yet &mdash; tick the files you want and
press <strong>Start selected</strong> to send them through the 11-stage pipeline as
one batch. Files from different drops can go in the same batch. With autorun on,
uploads start on arrival and this stays empty; watch them under{' '}
<strong>Dagster Orchestration</strong> instead.
</p>
</div>
<button
@@ -197,34 +204,66 @@ export function InboxPanel({ onBatchStarted }) {
</span>
</div>
{/* Same defaults and the same warning as the batch tab. */}
<div className="mt-4 flex flex-col gap-2">
<label className="flex items-start gap-2 text-[11px] text-slate-600 cursor-pointer">
<input
type="checkbox"
checked={fetchImages}
onChange={(e) => setFetchImages(e.target.checked)}
className="mt-0.5 accent-amber-500 cursor-pointer"
/>
<span>
<span className="font-bold text-ink-950">Search for product images</span>
{' '}&mdash; much slower, and makes outbound requests for every row.
</span>
</label>
<label className="flex items-start gap-2 text-[11px] text-slate-600 cursor-pointer">
<input
type="checkbox"
checked={useLlm}
onChange={(e) => setUseLlm(e.target.checked)}
className="mt-0.5 accent-amber-500 cursor-pointer"
/>
<span>
<span className="font-bold text-ink-950">Use the LLM for missing descriptions</span>
{' '}&mdash; fills blank descriptions where an Ollama server is reachable. It is not
in production, so rows there simply keep the description the sheet gave them.
</span>
</label>
</div>
{/* THESE TWO GOVERN THE MANUAL START ABOVE, AND NOTHING ELSE.
An upload that ran itself never passed through here: POST
/api/uploads/catalog reads UPLOAD_AUTORUN_FETCH_IMAGES and
UPLOAD_AUTORUN_USE_LLM on the server and ignores whatever the
request asked for. What a given run actually used is on its own row
under Dagster Orchestration -> Recent runs. */}
<fieldset
disabled={stagesIdle}
className={`mt-4 rounded-xl border border-ink-900/10 bg-white p-3 transition ${
stagesIdle ? 'opacity-40' : ''
}`}
>
<legend className="px-1 text-[10px] font-bold uppercase tracking-wide text-slate-400">
Applies to Start selected
{stagesIdle && (
<span className="font-normal normal-case"> &mdash; tick a file below first</span>
)}
</legend>
<div className="flex flex-col gap-2">
<label
className={`flex items-start gap-2 text-[11px] text-slate-600 ${
stagesIdle ? 'cursor-not-allowed' : 'cursor-pointer'
}`}
>
<input
type="checkbox"
checked={fetchImages}
disabled={stagesIdle}
onChange={(e) => setFetchImages(e.target.checked)}
className={`mt-0.5 accent-amber-500 ${
stagesIdle ? 'cursor-not-allowed' : 'cursor-pointer'
}`}
/>
<span>
<span className="font-bold text-ink-950">Search for product images</span>
{' '}&mdash; much slower, and makes outbound requests for every row.
</span>
</label>
<label
className={`flex items-start gap-2 text-[11px] text-slate-600 ${
stagesIdle ? 'cursor-not-allowed' : 'cursor-pointer'
}`}
>
<input
type="checkbox"
checked={useLlm}
disabled={stagesIdle}
onChange={(e) => setUseLlm(e.target.checked)}
className={`mt-0.5 accent-amber-500 ${
stagesIdle ? 'cursor-not-allowed' : 'cursor-pointer'
}`}
/>
<span>
<span className="font-bold text-ink-950">Use the LLM for missing descriptions</span>
{' '}&mdash; fills blank descriptions where an Ollama server is reachable. It is not
in production, so rows there simply keep the description the sheet gave them.
</span>
</label>
</div>
</fieldset>
{notice && (
<div className="mt-4 rounded-lg bg-emerald-500/5 border border-emerald-500/20 p-3 text-xs text-emerald-700 flex items-start gap-2">
@@ -243,8 +282,13 @@ export function InboxPanel({ onBatchStarted }) {
<div className="rounded-2xl border border-ink-900/10 bg-paper-50 p-10 text-center">
<Inbox className="h-8 w-8 text-slate-300 mx-auto mb-3" />
<p className="text-xs text-slate-500">
Nothing waiting. Files sent to <code className="font-mono">/api/uploads/catalog</code>{' '}
appear here for review.
Nothing waiting &mdash; files sent to{' '}
<code className="font-mono">/api/uploads/catalog</code> start on their own and appear
under <strong>Dagster Orchestration &rarr; Recent runs</strong>.
</p>
<p className="text-[11px] text-slate-400 mt-2">
Set <code className="font-mono">UPLOAD_AUTORUN=false</code> to hold them here for a
decision instead.
</p>
</div>
)}

View File

@@ -48,6 +48,16 @@ const FILE_TONE = {
cancelled: 'bg-ink-100 text-slate-500 border-ink-900/10',
};
// The two optional network stages, rendered per run under Recent runs. A run
// that started on its own took these from the SERVER settings
// (UPLOAD_AUTORUN_FETCH_IMAGES / UPLOAD_AUTORUN_USE_LLM), never from the
// checkboxes on this page, so reading them back off the manifest is the only
// honest report of what a colleague's upload actually did.
const STAGE_FLAGS = [
{ key: 'fetch_images', label: 'img', title: 'Product image search' },
{ key: 'use_llm', label: 'llm', title: 'LLM description fill' },
];
const FILE_ICON = {
done: CheckCircle2,
failed: XCircle,
@@ -226,6 +236,11 @@ export function OrchestrationPanel() {
// orchestrator is not running, or its sensor has not ticked yet.
const awaitingOrchestrator =
batch && batch.runner === 'dagster' && batch.status === 'queued';
// Nothing ticked means "Start selected" cannot fire, which makes the two
// stage toggles below inert. On a deployment running UPLOAD_AUTORUN=true that
// is the permanent state - the inbox never fills - so they stay greyed, which
// is exactly the point: they must not read as settings that govern uploads.
const stagesIdle = !selected.size;
return (
<div className="space-y-6">
@@ -274,34 +289,66 @@ export function OrchestrationPanel() {
</span>
</div>
{/* Same defaults and the same warnings as the other ingestion tabs. */}
<div className="mt-4 flex flex-col gap-2">
<label className="flex items-start gap-2 text-[11px] text-slate-600 cursor-pointer">
<input
type="checkbox"
checked={fetchImages}
onChange={(e) => setFetchImages(e.target.checked)}
className="mt-0.5 accent-amber-500 cursor-pointer"
/>
<span>
<span className="font-bold text-ink-950">Search for product images</span>
{' '}&mdash; much slower, and makes outbound requests for every row.
</span>
</label>
<label className="flex items-start gap-2 text-[11px] text-slate-600 cursor-pointer">
<input
type="checkbox"
checked={useLlm}
onChange={(e) => setUseLlm(e.target.checked)}
className="mt-0.5 accent-amber-500 cursor-pointer"
/>
<span>
<span className="font-bold text-ink-950">Use the LLM for missing descriptions</span>
{' '}&mdash; fills blank descriptions where an Ollama server is reachable. It is not
in production, so rows there simply keep the description the sheet gave them.
</span>
</label>
</div>
{/* THESE TWO GOVERN THE MANUAL START BELOW, AND NOTHING ELSE.
An upload that ran itself never passed through here: POST
/api/uploads/catalog reads UPLOAD_AUTORUN_FETCH_IMAGES and
UPLOAD_AUTORUN_USE_LLM on the server and ignores whatever the
request asked for. What a given run actually used is on its own row
under Recent runs. */}
<fieldset
disabled={stagesIdle}
className={`mt-4 rounded-xl border border-ink-900/10 bg-white p-3 transition ${
stagesIdle ? 'opacity-40' : ''
}`}
>
<legend className="px-1 text-[10px] font-bold uppercase tracking-wide text-slate-400">
Applies to Start selected
{stagesIdle && (
<span className="font-normal normal-case"> &mdash; tick a file below first</span>
)}
</legend>
<div className="flex flex-col gap-2">
<label
className={`flex items-start gap-2 text-[11px] text-slate-600 ${
stagesIdle ? 'cursor-not-allowed' : 'cursor-pointer'
}`}
>
<input
type="checkbox"
checked={fetchImages}
disabled={stagesIdle}
onChange={(e) => setFetchImages(e.target.checked)}
className={`mt-0.5 accent-amber-500 ${
stagesIdle ? 'cursor-not-allowed' : 'cursor-pointer'
}`}
/>
<span>
<span className="font-bold text-ink-950">Search for product images</span>
{' '}&mdash; much slower, and makes outbound requests for every row.
</span>
</label>
<label
className={`flex items-start gap-2 text-[11px] text-slate-600 ${
stagesIdle ? 'cursor-not-allowed' : 'cursor-pointer'
}`}
>
<input
type="checkbox"
checked={useLlm}
disabled={stagesIdle}
onChange={(e) => setUseLlm(e.target.checked)}
className={`mt-0.5 accent-amber-500 ${
stagesIdle ? 'cursor-not-allowed' : 'cursor-pointer'
}`}
/>
<span>
<span className="font-bold text-ink-950">Use the LLM for missing descriptions</span>
{' '}&mdash; fills blank descriptions where an Ollama server is reachable. It is not
in production, so rows there simply keep the description the sheet gave them.
</span>
</label>
</div>
</fieldset>
{notice && (
<div className="mt-4 rounded-lg bg-emerald-500/5 border border-emerald-500/20 p-3 text-xs text-emerald-700 flex items-start gap-2">
@@ -350,6 +397,23 @@ export function OrchestrationPanel() {
{run.files_total} file(s)
{run.submitted_by ? ` from ${run.submitted_by}` : ''}
</span>
{/* Read off the manifest, not assumed from .env, so it stays
true if a setting is changed without a redeploy. */}
<span className="shrink-0 hidden sm:flex items-center gap-1">
{STAGE_FLAGS.map(({ key, label, title }) => (
<span
key={key}
title={`${title}: ${run[key] ? 'ran' : 'skipped'}`}
className={`px-1.5 py-0.5 rounded border font-mono text-[10px] font-bold ${
run[key]
? 'border-amber-500/20 bg-amber-500/10 text-amber-700'
: 'border-ink-900/10 bg-paper-100 text-slate-400 line-through'
}`}
>
{label}
</span>
))}
</span>
<span
className={`shrink-0 px-2 py-0.5 rounded-md border text-[10px] font-bold ${
FILE_TONE[run.status] || FILE_TONE.queued