feat(recipe-studio): enforce run name validation for full runs and refine validation UI
This commit is contained in:
parent
3b1663b1e9
commit
f41a552c29
3 changed files with 25 additions and 13 deletions
|
|
@ -254,6 +254,8 @@ export function RunDialog({
|
|||
}: RunDialogProps): ReactElement {
|
||||
const [advancedOpen, setAdvancedOpen] = useState(false);
|
||||
const kindLabel = kind === "preview" ? "Preview" : "Full run";
|
||||
const normalizedFullRunName = fullRunName.trim();
|
||||
const isFullRunNameMissing = kind === "full" && normalizedFullRunName.length === 0;
|
||||
const rowHint =
|
||||
kind === "preview"
|
||||
? "How many sample rows to generate for a quick check."
|
||||
|
|
@ -376,7 +378,13 @@ export function RunDialog({
|
|||
value={fullRunName}
|
||||
onChange={(event) => onFullRunNameChange(event.target.value)}
|
||||
placeholder="Sprint dataset v2"
|
||||
aria-invalid={isFullRunNameMissing}
|
||||
/>
|
||||
{isFullRunNameMissing ? (
|
||||
<p className="text-xs text-destructive">
|
||||
Run name is required before starting a full run.
|
||||
</p>
|
||||
) : null}
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
|
@ -657,7 +665,12 @@ export function RunDialog({
|
|||
<HugeiconsIcon icon={TestTube01Icon} className="size-3.5" />
|
||||
{validateLoading ? "Validating..." : "Validate recipe"}
|
||||
</Button>
|
||||
<Button type="button" onClick={onRun} disabled={loading} className="corner-squircle">
|
||||
<Button
|
||||
type="button"
|
||||
onClick={onRun}
|
||||
disabled={loading || isFullRunNameMissing}
|
||||
className="corner-squircle"
|
||||
>
|
||||
<HugeiconsIcon icon={CookBookIcon} className="size-3.5" />
|
||||
{loading ? "Starting..." : `Start ${kindLabel.toLowerCase()}`}
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -324,19 +324,26 @@ export function useRecipeExecutions({
|
|||
rows: number,
|
||||
runName: string | null,
|
||||
): Promise<boolean> => {
|
||||
const trimmedRunName = typeof runName === "string" ? runName.trim() : "";
|
||||
if (kind === "full" && !trimmedRunName) {
|
||||
const message = "Run name required for full runs.";
|
||||
setRunErrors([message]);
|
||||
toastError("Run name required", message);
|
||||
return false;
|
||||
}
|
||||
|
||||
const payload = readExecutablePayload();
|
||||
if (!payload) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const normalizedRows = sanitizeExecutionRows(rows, kind);
|
||||
const normalizedRunName = kind === "full" ? normalizeRunName(runName) : null;
|
||||
const executionPayload = buildExecutionPayload({
|
||||
payload,
|
||||
kind,
|
||||
rows: normalizedRows,
|
||||
settings: runSettings,
|
||||
runName: normalizedRunName,
|
||||
runName,
|
||||
});
|
||||
|
||||
try {
|
||||
|
|
@ -361,7 +368,7 @@ export function useRecipeExecutions({
|
|||
payload,
|
||||
rows: normalizedRows,
|
||||
settings: runSettings,
|
||||
runName: normalizedRunName,
|
||||
runName,
|
||||
});
|
||||
},
|
||||
[readExecutablePayload, runExecution, runSettings, setRunErrors],
|
||||
|
|
|
|||
|
|
@ -604,21 +604,13 @@ export function DatasetSection() {
|
|||
Local dataset metadata
|
||||
</p>
|
||||
<p className="text-[10px] text-muted-foreground/80">
|
||||
Data Recipe output. Eval split unavailable for local datasets.
|
||||
Data Recipe output.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{uploadedFile ? (
|
||||
<div className="flex flex-col gap-3">
|
||||
<div className="rounded-md bg-background/60 px-2.5 py-2">
|
||||
<p className="mb-1 text-[10px] uppercase tracking-[0.12em] text-muted-foreground">
|
||||
Path
|
||||
</p>
|
||||
<p className="truncate font-mono text-[11px] text-foreground" title={uploadedFile}>
|
||||
{uploadedFile}
|
||||
</p>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-x-4 gap-y-2 text-xs">
|
||||
<MetadataRow
|
||||
label="Rows"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue