This commit is contained in:
@@ -17,8 +17,10 @@ export function EditStepModal({ open, step, onClose }: { open: boolean; step: Wo
|
||||
const [busy, setBusy] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
|
||||
|
||||
// Default steps are re-seeded from the image on every boot, so the server
|
||||
// refuses to update or delete them. The form mirrors that rather than
|
||||
// offering buttons that can only 409.
|
||||
const locked = step?.source === "default";
|
||||
|
||||
const save = async () => {
|
||||
setBusy(true); setError(null);
|
||||
@@ -47,24 +49,30 @@ export function EditStepModal({ open, step, onClose }: { open: boolean; step: Wo
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal open={open} onClose={onClose} title={step ? "Edit base step" : "New step"} wide>
|
||||
<Modal open={open} onClose={onClose} title={locked ? "Default step" : step ? "Edit base step" : "New step"} wide>
|
||||
<div className="space-y-4">
|
||||
{error && <div className="rounded border border-danger/30 bg-danger/10 px-3 py-2 text-sm text-danger">{error}</div>}
|
||||
<p className="text-xs text-text-secondary">Reusable steps are shared across all workflows. Editing here changes it everywhere.</p>
|
||||
{locked ? (
|
||||
<p className="rounded border border-border bg-surface-2 px-3 py-2 text-xs text-text-secondary">
|
||||
This step ships with Vantage and is read-only. It is re-seeded on every upgrade. Export it and import a copy to make your own version.
|
||||
</p>
|
||||
) : (
|
||||
<p className="text-xs text-text-secondary">Reusable steps are shared across all workflows. Editing here changes it everywhere.</p>
|
||||
)}
|
||||
<div>
|
||||
<label className="mb-1 block text-xs uppercase text-text-secondary">Name</label>
|
||||
<input className={inputClass} value={name} onChange={(e) => setName(e.target.value)} />
|
||||
<input className={inputClass} value={name} readOnly={locked} onChange={(e) => setName(e.target.value)} />
|
||||
</div>
|
||||
<div>
|
||||
<label className="mb-1 block text-xs uppercase text-text-secondary">Interpreter</label>
|
||||
<select className={inputClass} value={interpreter} onChange={(e) => setInterpreter(e.target.value as "bash" | "powershell")}>
|
||||
<select className={inputClass} value={interpreter} disabled={locked} onChange={(e) => setInterpreter(e.target.value as "bash" | "powershell")}>
|
||||
<option value="bash">bash</option>
|
||||
<option value="powershell">powershell</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label className="mb-1 block text-xs uppercase text-text-secondary">Script</label>
|
||||
<textarea className={`${inputClass} h-40 font-mono text-xs`} value={script} onChange={(e) => setScript(e.target.value)} />
|
||||
<textarea className={`${inputClass} h-40 font-mono text-xs`} value={script} readOnly={locked} onChange={(e) => setScript(e.target.value)} />
|
||||
<p className="mt-1 text-xs text-text-secondary">Write <code className="text-signal">KEY=value</code> to <code className="text-signal">$WORKFLOW_ENV</code> to expose it to later steps.</p>
|
||||
</div>
|
||||
<div>
|
||||
@@ -86,20 +94,22 @@ export function EditStepModal({ open, step, onClose }: { open: boolean; step: Wo
|
||||
<div className="space-y-2">
|
||||
{inputs.map((inp, i) => (
|
||||
<div key={i} className="flex gap-2">
|
||||
<input className={inputClass} placeholder="name" value={inp.name} onChange={(e) => setInputs(inputs.map((x, j) => j === i ? { ...x, name: e.target.value } : x))} />
|
||||
<input className={inputClass} placeholder="default" value={inp.default} onChange={(e) => setInputs(inputs.map((x, j) => j === i ? { ...x, default: e.target.value } : x))} />
|
||||
<input className={inputClass} placeholder="description" value={inp.description} onChange={(e) => setInputs(inputs.map((x, j) => j === i ? { ...x, description: e.target.value } : x))} />
|
||||
<Button variant="ghost" size="sm" onClick={() => setInputs(inputs.filter((_, j) => j !== i))}>✕</Button>
|
||||
<input className={inputClass} readOnly={locked} placeholder="name" value={inp.name} onChange={(e) => setInputs(inputs.map((x, j) => j === i ? { ...x, name: e.target.value } : x))} />
|
||||
<input className={inputClass} readOnly={locked} placeholder="default" value={inp.default} onChange={(e) => setInputs(inputs.map((x, j) => j === i ? { ...x, default: e.target.value } : x))} />
|
||||
<input className={inputClass} readOnly={locked} placeholder="description" value={inp.description} onChange={(e) => setInputs(inputs.map((x, j) => j === i ? { ...x, description: e.target.value } : x))} />
|
||||
{!locked && <Button variant="ghost" size="sm" onClick={() => setInputs(inputs.filter((_, j) => j !== i))}>✕</Button>}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<Button variant="ghost" size="sm" className="mt-2" onClick={() => setInputs([...inputs, { name: "", default: "", description: "" }])}>Add input</Button>
|
||||
{!locked && (
|
||||
<Button variant="ghost" size="sm" className="mt-2" onClick={() => setInputs([...inputs, { name: "", default: "", description: "" }])}>Add input</Button>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center justify-between pt-2">
|
||||
{step ? <Button variant="danger" onClick={del} loading={busy}>Delete step</Button> : <span />}
|
||||
{step && !locked ? <Button variant="danger" onClick={del} loading={busy}>Delete step</Button> : <span />}
|
||||
<div className="flex gap-2">
|
||||
<Button variant="ghost" onClick={onClose}>Cancel</Button>
|
||||
<Button variant="primary" onClick={save} loading={busy} disabled={!name.trim()}>Save</Button>
|
||||
<Button variant="ghost" onClick={onClose}>{locked ? "Close" : "Cancel"}</Button>
|
||||
{!locked && <Button variant="primary" onClick={save} loading={busy} disabled={!name.trim()}>Save</Button>}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user