feat(c2): integrate Mythic command and control (sprint 8) #11
@@ -124,7 +124,7 @@ export function EngagementFormPage(): JSX.Element {
|
|||||||
const submitting = createMutation.isPending || patchMutation.isPending;
|
const submitting = createMutation.isPending || patchMutation.isPending;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-xl max-w-2xl">
|
<div className="flex flex-col gap-xl">
|
||||||
<header>
|
<header>
|
||||||
<h1 className="text-[32px] font-medium leading-none">
|
<h1 className="text-[32px] font-medium leading-none">
|
||||||
{editing ? 'Edit engagement' : 'New engagement'}
|
{editing ? 'Edit engagement' : 'New engagement'}
|
||||||
@@ -136,91 +136,99 @@ export function EngagementFormPage(): JSX.Element {
|
|||||||
</p>
|
</p>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<form onSubmit={onSubmit} noValidate className="card-product flex flex-col gap-md">
|
<div
|
||||||
<FormField label="Name" htmlFor="eng-name" required error={errors.name}>
|
className={
|
||||||
<TextInput
|
editing && canEditEngagements
|
||||||
id="eng-name"
|
? 'grid grid-cols-1 lg:grid-cols-2 gap-xl items-start'
|
||||||
name="name"
|
: 'max-w-2xl'
|
||||||
value={form.name}
|
}
|
||||||
onChange={(e) => setForm({ ...form, name: e.target.value })}
|
>
|
||||||
required
|
<form onSubmit={onSubmit} noValidate className="card-product flex flex-col gap-md">
|
||||||
/>
|
<FormField label="Name" htmlFor="eng-name" required error={errors.name}>
|
||||||
</FormField>
|
|
||||||
|
|
||||||
<FormField label="Description" htmlFor="eng-description">
|
|
||||||
<TextArea
|
|
||||||
id="eng-description"
|
|
||||||
name="description"
|
|
||||||
value={form.description}
|
|
||||||
onChange={(e) => setForm({ ...form, description: e.target.value })}
|
|
||||||
/>
|
|
||||||
</FormField>
|
|
||||||
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-md">
|
|
||||||
<FormField
|
|
||||||
label="Start date"
|
|
||||||
htmlFor="eng-start"
|
|
||||||
required
|
|
||||||
error={errors.start_date}
|
|
||||||
>
|
|
||||||
<TextInput
|
<TextInput
|
||||||
id="eng-start"
|
id="eng-name"
|
||||||
type="date"
|
name="name"
|
||||||
name="start_date"
|
value={form.name}
|
||||||
value={form.start_date}
|
onChange={(e) => setForm({ ...form, name: e.target.value })}
|
||||||
onChange={(e) => setForm({ ...form, start_date: e.target.value })}
|
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</FormField>
|
</FormField>
|
||||||
|
|
||||||
<FormField
|
<FormField label="Description" htmlFor="eng-description">
|
||||||
label="End date"
|
<TextArea
|
||||||
htmlFor="eng-end"
|
id="eng-description"
|
||||||
hint="Leave empty to clear / leave open-ended"
|
name="description"
|
||||||
error={errors.end_date}
|
value={form.description}
|
||||||
>
|
onChange={(e) => setForm({ ...form, description: e.target.value })}
|
||||||
<TextInput
|
|
||||||
id="eng-end"
|
|
||||||
type="date"
|
|
||||||
name="end_date"
|
|
||||||
value={form.end_date}
|
|
||||||
onChange={(e) => setForm({ ...form, end_date: e.target.value })}
|
|
||||||
/>
|
/>
|
||||||
</FormField>
|
</FormField>
|
||||||
</div>
|
|
||||||
|
|
||||||
<FormField label="Status" htmlFor="eng-status" required>
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-md">
|
||||||
<Select
|
<FormField
|
||||||
id="eng-status"
|
label="Start date"
|
||||||
name="status"
|
htmlFor="eng-start"
|
||||||
value={form.status}
|
required
|
||||||
onChange={(e) => setForm({ ...form, status: e.target.value as EngagementStatus })}
|
error={errors.start_date}
|
||||||
options={STATUS_OPTIONS}
|
>
|
||||||
/>
|
<TextInput
|
||||||
</FormField>
|
id="eng-start"
|
||||||
|
type="date"
|
||||||
|
name="start_date"
|
||||||
|
value={form.start_date}
|
||||||
|
onChange={(e) => setForm({ ...form, start_date: e.target.value })}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</FormField>
|
||||||
|
|
||||||
{submitError ? (
|
<FormField
|
||||||
<div role="alert" className="text-[14px] text-bloom-deep">
|
label="End date"
|
||||||
{submitError}
|
htmlFor="eng-end"
|
||||||
|
hint="Leave empty to clear / leave open-ended"
|
||||||
|
error={errors.end_date}
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
id="eng-end"
|
||||||
|
type="date"
|
||||||
|
name="end_date"
|
||||||
|
value={form.end_date}
|
||||||
|
onChange={(e) => setForm({ ...form, end_date: e.target.value })}
|
||||||
|
/>
|
||||||
|
</FormField>
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
|
||||||
|
|
||||||
<div className="flex items-center gap-md pt-sm">
|
<FormField label="Status" htmlFor="eng-status" required>
|
||||||
<button type="submit" className="btn-primary" disabled={submitting}>
|
<Select
|
||||||
{submitting ? 'Saving…' : editing ? 'Save changes' : 'Create engagement'}
|
id="eng-status"
|
||||||
</button>
|
name="status"
|
||||||
<Link
|
value={form.status}
|
||||||
to={editing && numericId ? `/engagements/${numericId}` : '/engagements'}
|
onChange={(e) => setForm({ ...form, status: e.target.value as EngagementStatus })}
|
||||||
className="btn-outline-ink"
|
options={STATUS_OPTIONS}
|
||||||
>
|
/>
|
||||||
Cancel
|
</FormField>
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
{editing && numericId && canEditEngagements && (
|
{submitError ? (
|
||||||
<C2ConfigCard engagementId={numericId} />
|
<div role="alert" className="text-[14px] text-bloom-deep">
|
||||||
)}
|
{submitError}
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
|
||||||
|
<div className="flex items-center gap-md pt-sm">
|
||||||
|
<button type="submit" className="btn-primary" disabled={submitting}>
|
||||||
|
{submitting ? 'Saving…' : editing ? 'Save changes' : 'Create engagement'}
|
||||||
|
</button>
|
||||||
|
<Link
|
||||||
|
to={editing && numericId ? `/engagements/${numericId}` : '/engagements'}
|
||||||
|
className="btn-outline-ink"
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{editing && numericId && canEditEngagements && (
|
||||||
|
<C2ConfigCard engagementId={numericId} />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user