+ |
+
+ |
{formattedDate}
@@ -312,6 +320,7 @@ function ApprovalRow({ approval }: { approval: Approval }) {
export default function ApprovalsPage() {
const tEvidence = useTranslations("awooop.listEvidence");
+ const tStatusChain = useTranslations("awooop.statusChain");
const [approvals, setApprovals] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
@@ -554,6 +563,9 @@ export default function ApprovalsPage() {
|
{tEvidence("column")}
|
+
+ {tStatusChain("title")}
+ |
建立時間
|
@@ -566,7 +578,7 @@ export default function ApprovalsPage() {
{loading ? (
Array.from({ length: 5 }).map((_, i) => (
- {Array.from({ length: 7 }).map((_, j) => (
+ {Array.from({ length: 8 }).map((_, j) => (
|
|
diff --git a/apps/web/src/app/[locale]/awooop/work-items/page.tsx b/apps/web/src/app/[locale]/awooop/work-items/page.tsx
index 130539c0..cfcca891 100644
--- a/apps/web/src/app/[locale]/awooop/work-items/page.tsx
+++ b/apps/web/src/app/[locale]/awooop/work-items/page.tsx
@@ -27,6 +27,10 @@ import {
import { Link } from "@/i18n/routing";
import { IncidentEvidenceHeader } from "@/components/awooop/incident-evidence-header";
+import {
+ AwoooPStatusChainPanel,
+ type AwoooPStatusChain,
+} from "@/components/awooop/status-chain";
import { cn } from "@/lib/utils";
type WorkStatus = "live" | "in_progress" | "blocked" | "watching";
@@ -278,6 +282,7 @@ type Telemetry = {
slo: SloResponse | null;
remediationHistory: RemediationHistoryResponse | null;
driftFingerprintState: DriftFingerprintState | null;
+ statusChain: AwoooPStatusChain | null;
};
type WorkItem = {
@@ -371,6 +376,33 @@ function recurrenceOpenItems(recurrence: RecurrenceResponse | null) {
return (recurrence?.items ?? []).filter((item) => item.work_item?.status === "open");
}
+function firstIncidentId(...candidates: Array) {
+ return candidates.find((candidate) => Boolean(candidate?.trim()))?.trim() ?? null;
+}
+
+function selectStatusChainIncidentId(
+ focusedIncidentId: string | null,
+ remediationHistory: RemediationHistoryResponse | null,
+ recurrence: RecurrenceResponse | null
+) {
+ const latestRemediationIncident = remediationHistory?.items?.find(
+ (item) => Boolean(item.incident_id?.trim())
+ )?.incident_id;
+ const latestOpenRecurrence = recurrenceOpenItems(recurrence)[0] ?? null;
+ const latestRecurrenceIncident = recurrence?.items?.find(
+ (item) => Boolean(item.latest_incident_id?.trim() || item.work_item?.incident_id?.trim())
+ );
+
+ return firstIncidentId(
+ focusedIncidentId,
+ latestRemediationIncident,
+ latestOpenRecurrence?.latest_incident_id,
+ latestOpenRecurrence?.work_item?.incident_id,
+ latestRecurrenceIncident?.latest_incident_id,
+ latestRecurrenceIncident?.work_item?.incident_id
+ );
+}
+
function recurrenceRepairStatusKey(status?: string | null) {
if (
status === "auto_repair_verified" ||
@@ -1382,6 +1414,7 @@ export default function AwoooPWorkItemsPage() {
slo: null,
remediationHistory: null,
driftFingerprintState: null,
+ statusChain: null,
});
const [loading, setLoading] = useState(true);
const [lastUpdated, setLastUpdated] = useState(null);
@@ -1418,6 +1451,21 @@ export default function AwoooPWorkItemsPage() {
fetchJson(driftFingerprintUrl, 12000),
]);
+ const statusChainIncidentId = selectStatusChainIncidentId(
+ focusedIncidentId,
+ remediationHistory,
+ eventRecurrence
+ );
+ let statusChain: AwoooPStatusChain | null = null;
+ if (statusChainIncidentId) {
+ const statusChainParams = new URLSearchParams({ project_id: projectId });
+ statusChainParams.append("incident_id", statusChainIncidentId);
+ statusChain = await fetchJson(
+ `${API_BASE}/api/v1/platform/status-chain?${statusChainParams.toString()}`,
+ 12000
+ );
+ }
+
setTelemetry({
quality,
governanceEvents,
@@ -1427,10 +1475,11 @@ export default function AwoooPWorkItemsPage() {
slo,
remediationHistory,
driftFingerprintState,
+ statusChain,
});
setLastUpdated(new Date());
setLoading(false);
- }, [projectId]);
+ }, [focusedIncidentId, projectId]);
useEffect(() => {
fetchTelemetry();
@@ -1533,6 +1582,8 @@ export default function AwoooPWorkItemsPage() {
writesAutoRepairResult={latestRemediationHistory?.writes_auto_repair_result}
/>
+
+
|