feat(assign): let leads manually assign operators + sync Jira; send platform as Jira label
Aegis CI / lint-and-test (push) Has been cancelled
Snyk Security Scan / Python vulnerabilities (backend) (push) Has been cancelled
Snyk Security Scan / npm vulnerabilities (frontend) (push) Has been cancelled
Snyk Security Scan / Docker image vulnerabilities (backend) (push) Has been cancelled
Aegis CI / lint-and-test (push) Has been cancelled
Snyk Security Scan / Python vulnerabilities (backend) (push) Has been cancelled
Snyk Security Scan / npm vulnerabilities (frontend) (push) Has been cancelled
Snyk Security Scan / Docker image vulnerabilities (backend) (push) Has been cancelled
Adds GET /users/operators (leads+admin) and wires a lead-only assign
control into the test detail header, calling the existing but
previously unreachable POST /tests/{id}/assign endpoint. Manual
assignment now also pushes the Jira ticket assignee immediately
instead of waiting for the operator to start execution.
Also adds test.platform as a kebab-case label on Jira ticket creation.
This commit is contained in:
@@ -19,8 +19,10 @@ import {
|
||||
import { useMutation } from "@tanstack/react-query";
|
||||
import { requestDiscussion } from "../../api/tests";
|
||||
import type { Test, TestState, User, DataClassification } from "../../types/models";
|
||||
import type { OperatorOut } from "../../api/users";
|
||||
import LiveTimer from "./LiveTimer";
|
||||
import DataClassificationBadge from "./DataClassificationBadge";
|
||||
import AssigneeControl from "./AssigneeControl";
|
||||
|
||||
// ── Progress steps ─────────────────────────────────────────────────
|
||||
|
||||
@@ -90,6 +92,9 @@ interface TestDetailHeaderProps {
|
||||
isTogglingHold: boolean;
|
||||
onUpdateClassification: (value: DataClassification) => void;
|
||||
isUpdatingClassification: boolean;
|
||||
operators: OperatorOut[];
|
||||
onAssignOperator: (side: "red" | "blue", userId: string | null) => void;
|
||||
isAssigningOperator: boolean;
|
||||
}
|
||||
|
||||
// ── Component ──────────────────────────────────────────────────────
|
||||
@@ -114,6 +119,9 @@ export default function TestDetailHeader({
|
||||
isTogglingHold,
|
||||
onUpdateClassification,
|
||||
isUpdatingClassification,
|
||||
operators,
|
||||
onAssignOperator,
|
||||
isAssigningOperator,
|
||||
}: TestDetailHeaderProps) {
|
||||
const role = user?.role ?? "";
|
||||
const currentIdx = STATE_INDEX[test.state];
|
||||
@@ -539,6 +547,24 @@ export default function TestDetailHeader({
|
||||
<p className="mt-1 text-sm text-gray-400">
|
||||
Created {formatDate(test.created_at)}
|
||||
</p>
|
||||
<div className="mt-1.5 flex items-center gap-1.5">
|
||||
<AssigneeControl
|
||||
side="red"
|
||||
assigneeId={test.red_tech_assignee}
|
||||
operators={operators}
|
||||
canEdit={role === "red_lead" || role === "admin"}
|
||||
isSaving={isAssigningOperator}
|
||||
onAssign={(userId) => onAssignOperator("red", userId)}
|
||||
/>
|
||||
<AssigneeControl
|
||||
side="blue"
|
||||
assigneeId={test.blue_tech_assignee}
|
||||
operators={operators}
|
||||
canEdit={role === "blue_lead" || role === "admin"}
|
||||
isSaving={isAssigningOperator}
|
||||
onAssign={(userId) => onAssignOperator("blue", userId)}
|
||||
/>
|
||||
</div>
|
||||
{renderValidationIndicators()}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user