feat(design): terminal-SOC aesthetic refresh (sprint 7) #10
@@ -257,7 +257,7 @@ export function SimulationFormPage(): JSX.Element {
|
||||
updateMutation.isPending || transitionMutation.isPending || deleteMutation.isPending;
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-xl max-w-3xl">
|
||||
<div className="flex flex-col gap-xl">
|
||||
<header className="flex items-start justify-between gap-md">
|
||||
<div className="flex flex-col gap-sm">
|
||||
<Link to={`/engagements/${engagementId}`} className="btn-text-link text-[14px]">
|
||||
@@ -298,140 +298,143 @@ export function SimulationFormPage(): JSX.Element {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Red Team card */}
|
||||
<form
|
||||
id="rt-form"
|
||||
onSubmit={canEditRT && !isDone ? onSaveRT : (e) => e.preventDefault()}
|
||||
noValidate
|
||||
className="card-product flex flex-col gap-md"
|
||||
>
|
||||
<h2 className="text-[20px] font-medium text-ink">Red Team</h2>
|
||||
{/* 2-column grid: RT left, SOC right. Stacks vertically below lg. */}
|
||||
<div className="grid gap-xl lg:grid-cols-2 items-start">
|
||||
{/* Red Team card */}
|
||||
<form
|
||||
id="rt-form"
|
||||
onSubmit={canEditRT && !isDone ? onSaveRT : (e) => e.preventDefault()}
|
||||
noValidate
|
||||
className="card-product flex flex-col gap-md"
|
||||
>
|
||||
<h2 className="text-[20px] font-medium text-ink">Red Team</h2>
|
||||
|
||||
<FormField label="Name" htmlFor="sim-name" required error={nameError}>
|
||||
<TextInput
|
||||
id="sim-name"
|
||||
name="name"
|
||||
value={rt.name}
|
||||
onChange={(e) => setRt({ ...rt, name: e.target.value })}
|
||||
disabled={rtDisabled}
|
||||
required
|
||||
/>
|
||||
</FormField>
|
||||
<FormField label="Name" htmlFor="sim-name" required error={nameError}>
|
||||
<TextInput
|
||||
id="sim-name"
|
||||
name="name"
|
||||
value={rt.name}
|
||||
onChange={(e) => setRt({ ...rt, name: e.target.value })}
|
||||
disabled={rtDisabled}
|
||||
required
|
||||
/>
|
||||
</FormField>
|
||||
|
||||
<div className="flex flex-col gap-xs">
|
||||
<span className="text-[14px] font-medium text-ink">MITRE Techniques & Tactics</span>
|
||||
<MitreTechniquesField
|
||||
value={simulation?.techniques ?? []}
|
||||
tactics={simulation?.tactics ?? []}
|
||||
simulationId={simulationId as number}
|
||||
engagementId={engagementId as number}
|
||||
disabled={rtDisabled}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col gap-xs">
|
||||
<span className="text-[14px] font-medium text-ink">MITRE Techniques & Tactics</span>
|
||||
<MitreTechniquesField
|
||||
value={simulation?.techniques ?? []}
|
||||
tactics={simulation?.tactics ?? []}
|
||||
simulationId={simulationId as number}
|
||||
engagementId={engagementId as number}
|
||||
disabled={rtDisabled}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<FormField label="Description" htmlFor="sim-description">
|
||||
<TextArea
|
||||
id="sim-description"
|
||||
name="description"
|
||||
value={rt.description}
|
||||
onChange={(e) => setRt({ ...rt, description: e.target.value })}
|
||||
disabled={rtDisabled}
|
||||
/>
|
||||
</FormField>
|
||||
<FormField label="Description" htmlFor="sim-description">
|
||||
<TextArea
|
||||
id="sim-description"
|
||||
name="description"
|
||||
value={rt.description}
|
||||
onChange={(e) => setRt({ ...rt, description: e.target.value })}
|
||||
disabled={rtDisabled}
|
||||
/>
|
||||
</FormField>
|
||||
|
||||
<FormField label="Commands" htmlFor="sim-commands" hint="One command per line">
|
||||
<TextArea
|
||||
id="sim-commands"
|
||||
name="commands"
|
||||
value={rt.commands}
|
||||
onChange={(e) => setRt({ ...rt, commands: e.target.value })}
|
||||
disabled={rtDisabled}
|
||||
className="min-h-[160px] font-mono text-[14px]"
|
||||
/>
|
||||
</FormField>
|
||||
<FormField label="Commands" htmlFor="sim-commands" hint="One command per line">
|
||||
<TextArea
|
||||
id="sim-commands"
|
||||
name="commands"
|
||||
value={rt.commands}
|
||||
onChange={(e) => setRt({ ...rt, commands: e.target.value })}
|
||||
disabled={rtDisabled}
|
||||
className="min-h-[160px] font-mono text-[14px]"
|
||||
/>
|
||||
</FormField>
|
||||
|
||||
<FormField label="Prerequisites" htmlFor="sim-prerequisites">
|
||||
<TextArea
|
||||
id="sim-prerequisites"
|
||||
name="prerequisites"
|
||||
value={rt.prerequisites}
|
||||
onChange={(e) => setRt({ ...rt, prerequisites: e.target.value })}
|
||||
disabled={rtDisabled}
|
||||
/>
|
||||
</FormField>
|
||||
<FormField label="Prerequisites" htmlFor="sim-prerequisites">
|
||||
<TextArea
|
||||
id="sim-prerequisites"
|
||||
name="prerequisites"
|
||||
value={rt.prerequisites}
|
||||
onChange={(e) => setRt({ ...rt, prerequisites: e.target.value })}
|
||||
disabled={rtDisabled}
|
||||
/>
|
||||
</FormField>
|
||||
|
||||
<FormField label="Executed at" htmlFor="sim-executed-at">
|
||||
<TextInput
|
||||
id="sim-executed-at"
|
||||
type="datetime-local"
|
||||
name="executed_at"
|
||||
value={rt.executed_at}
|
||||
onChange={(e) => setRt({ ...rt, executed_at: e.target.value })}
|
||||
disabled={rtDisabled}
|
||||
/>
|
||||
</FormField>
|
||||
<FormField label="Executed at" htmlFor="sim-executed-at">
|
||||
<TextInput
|
||||
id="sim-executed-at"
|
||||
type="datetime-local"
|
||||
name="executed_at"
|
||||
value={rt.executed_at}
|
||||
onChange={(e) => setRt({ ...rt, executed_at: e.target.value })}
|
||||
disabled={rtDisabled}
|
||||
/>
|
||||
</FormField>
|
||||
|
||||
<FormField label="Execution result" htmlFor="sim-exec-result">
|
||||
<TextArea
|
||||
id="sim-exec-result"
|
||||
name="execution_result"
|
||||
value={rt.execution_result}
|
||||
onChange={(e) => setRt({ ...rt, execution_result: e.target.value })}
|
||||
disabled={rtDisabled}
|
||||
rows={5}
|
||||
/>
|
||||
</FormField>
|
||||
</form>
|
||||
<FormField label="Execution result" htmlFor="sim-exec-result">
|
||||
<TextArea
|
||||
id="sim-exec-result"
|
||||
name="execution_result"
|
||||
value={rt.execution_result}
|
||||
onChange={(e) => setRt({ ...rt, execution_result: e.target.value })}
|
||||
disabled={rtDisabled}
|
||||
rows={5}
|
||||
/>
|
||||
</FormField>
|
||||
</form>
|
||||
|
||||
{/* SOC card */}
|
||||
<form
|
||||
id="soc-form"
|
||||
onSubmit={canSaveSoc ? onSaveSOC : (e) => e.preventDefault()}
|
||||
noValidate
|
||||
className="card-product flex flex-col gap-md"
|
||||
>
|
||||
<h2 className="text-[20px] font-medium text-ink">SOC</h2>
|
||||
{/* SOC card */}
|
||||
<form
|
||||
id="soc-form"
|
||||
onSubmit={canSaveSoc ? onSaveSOC : (e) => e.preventDefault()}
|
||||
noValidate
|
||||
className="card-product flex flex-col gap-md"
|
||||
>
|
||||
<h2 className="text-[20px] font-medium text-ink">SOC</h2>
|
||||
|
||||
<FormField label="Log source" htmlFor="sim-log-source">
|
||||
<TextInput
|
||||
id="sim-log-source"
|
||||
name="log_source"
|
||||
value={soc.log_source}
|
||||
onChange={(e) => setSoc({ ...soc, log_source: e.target.value })}
|
||||
disabled={socDisabled}
|
||||
/>
|
||||
</FormField>
|
||||
<FormField label="Log source" htmlFor="sim-log-source">
|
||||
<TextInput
|
||||
id="sim-log-source"
|
||||
name="log_source"
|
||||
value={soc.log_source}
|
||||
onChange={(e) => setSoc({ ...soc, log_source: e.target.value })}
|
||||
disabled={socDisabled}
|
||||
/>
|
||||
</FormField>
|
||||
|
||||
<FormField label="Logs" htmlFor="sim-logs">
|
||||
<TextArea
|
||||
id="sim-logs"
|
||||
name="logs"
|
||||
value={soc.logs}
|
||||
onChange={(e) => setSoc({ ...soc, logs: e.target.value })}
|
||||
disabled={socDisabled}
|
||||
/>
|
||||
</FormField>
|
||||
<FormField label="Logs" htmlFor="sim-logs">
|
||||
<TextArea
|
||||
id="sim-logs"
|
||||
name="logs"
|
||||
value={soc.logs}
|
||||
onChange={(e) => setSoc({ ...soc, logs: e.target.value })}
|
||||
disabled={socDisabled}
|
||||
/>
|
||||
</FormField>
|
||||
|
||||
<FormField label="SOC comment" htmlFor="sim-soc-comment">
|
||||
<TextArea
|
||||
id="sim-soc-comment"
|
||||
name="soc_comment"
|
||||
value={soc.soc_comment}
|
||||
onChange={(e) => setSoc({ ...soc, soc_comment: e.target.value })}
|
||||
disabled={socDisabled}
|
||||
/>
|
||||
</FormField>
|
||||
<FormField label="SOC comment" htmlFor="sim-soc-comment">
|
||||
<TextArea
|
||||
id="sim-soc-comment"
|
||||
name="soc_comment"
|
||||
value={soc.soc_comment}
|
||||
onChange={(e) => setSoc({ ...soc, soc_comment: e.target.value })}
|
||||
disabled={socDisabled}
|
||||
/>
|
||||
</FormField>
|
||||
|
||||
<FormField label="Incident number" htmlFor="sim-incident">
|
||||
<TextInput
|
||||
id="sim-incident"
|
||||
name="incident_number"
|
||||
value={soc.incident_number}
|
||||
onChange={(e) => setSoc({ ...soc, incident_number: e.target.value })}
|
||||
disabled={socDisabled}
|
||||
/>
|
||||
</FormField>
|
||||
</form>
|
||||
<FormField label="Incident number" htmlFor="sim-incident">
|
||||
<TextInput
|
||||
id="sim-incident"
|
||||
name="incident_number"
|
||||
value={soc.incident_number}
|
||||
onChange={(e) => setSoc({ ...soc, incident_number: e.target.value })}
|
||||
disabled={socDisabled}
|
||||
/>
|
||||
</FormField>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{submitError ? (
|
||||
<div role="alert" className="text-[14px] text-bloom-deep">{submitError}</div>
|
||||
|
||||
Reference in New Issue
Block a user