diff --git a/apps/web/messages/en.json b/apps/web/messages/en.json index 464bf9b8..6f3a52bf 100644 --- a/apps/web/messages/en.json +++ b/apps/web/messages/en.json @@ -2167,6 +2167,18 @@ "stage": "Stage: {stage}", "sourceEvent": "Source event: {event}", "sourceRefs": "Source refs: {refs} (Sentry {sentry} / SignOz {signoz})", + "sourceFlow": { + "label": "Source flow: {status}", + "detail": "refs={refs}; Sentry={sentry}; SignOz={signoz}; event={event}", + "statuses": { + "applied": "Applied", + "reviewed": "Review recorded", + "review": "Awaiting match review", + "evidence": "Source evidence found", + "provider": "Provider received", + "waiting": "Waiting for source" + } + }, "workItem": "Work item: {id}", "repair": "Repair status: {status}", "reason": "Reason: {reason}", diff --git a/apps/web/messages/zh-TW.json b/apps/web/messages/zh-TW.json index dd29eafc..5f344641 100644 --- a/apps/web/messages/zh-TW.json +++ b/apps/web/messages/zh-TW.json @@ -2168,6 +2168,18 @@ "stage": "階段:{stage}", "sourceEvent": "來源事件:{event}", "sourceRefs": "來源 refs:{refs}(Sentry {sentry} / SignOz {signoz})", + "sourceFlow": { + "label": "來源流程:{status}", + "detail": "refs={refs}; Sentry={sentry}; SignOz={signoz}; event={event}", + "statuses": { + "applied": "已套用", + "reviewed": "審核已記錄", + "review": "待審核配對", + "evidence": "來源證據已到", + "provider": "Provider 已接收", + "waiting": "等待來源" + } + }, "workItem": "Work item:{id}", "repair": "修復狀態:{status}", "reason": "原因:{reason}", 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 88b60c1e..dbab3613 100644 --- a/apps/web/src/app/[locale]/awooop/work-items/page.tsx +++ b/apps/web/src/app/[locale]/awooop/work-items/page.tsx @@ -247,6 +247,14 @@ type RecurrenceWorkItemActionState = { error?: string | null; }; +type RecurrenceSourceFlowStatus = + | "applied" + | "reviewed" + | "review" + | "evidence" + | "provider" + | "waiting"; + type SloResponse = { adr100?: { verification_coverage?: { @@ -936,6 +944,67 @@ function sourceApplyStatusKey(status?: string | null) { return "unknown"; } +function recurrenceSourceFlowStatus({ + item, + actionResult, + sourceApplyStatus, + sourceDecision, + reviewStatus, +}: { + item: RecurrenceItem; + actionResult?: RecurrenceWorkItemActionResult | null; + sourceApplyStatus: string; + sourceDecision: string; + reviewStatus: string; +}): RecurrenceSourceFlowStatus { + const hasAppliedLink = + sourceApplyStatus === "applied" || + sourceApplyStatus === "partial" || + Boolean( + actionResult?.source_event_provider_event_id || + item.source_correlation_apply?.source_event_provider_event_id + ); + if (hasAppliedLink) return "applied"; + + const hasRecordedReview = + sourceDecision !== "unknown" || + reviewStatus === "recorded" || + reviewStatus === "accepted" || + reviewStatus === "rejected" || + reviewStatus === "needs_more_evidence"; + if (hasRecordedReview) return "reviewed"; + + if (item.work_item?.kind === "source_correlation_review" || item.source_correlation_review) { + return "review"; + } + + const sourceRefTotal = + (item.source_ref_total ?? 0) + + (item.sentry_ref_total ?? 0) + + (item.signoz_ref_total ?? 0); + if (sourceRefTotal > 0) return "evidence"; + if (item.latest_provider_event_id) return "provider"; + return "waiting"; +} + +function recurrenceSourceFlowClass(status: RecurrenceSourceFlowStatus) { + if (status === "applied") return "border-[#9bc7a4] bg-[#f0faf2] text-[#17602a]"; + if (status === "reviewed") return "border-[#9bb6d9] bg-[#eef5ff] text-[#1f5b9b]"; + if (status === "review" || status === "evidence") { + return "border-[#d9b36f] bg-[#fff7e8] text-[#8a5a08]"; + } + if (status === "provider") return "border-[#d8d3c7] bg-[#faf9f3] text-[#5f5b52]"; + return "border-[#e0ddd4] bg-white text-[#77736a]"; +} + +function recurrenceSourceFlowIcon(status: RecurrenceSourceFlowStatus) { + if (status === "applied") return ShieldCheck; + if (status === "reviewed") return GitBranch; + if (status === "review" || status === "evidence") return SearchCheck; + if (status === "provider") return Network; + return Database; +} + function formatStaleRatio(value: number) { return `${(value * 100).toFixed(1)}%`; } @@ -1556,6 +1625,19 @@ function RecurrenceWorkQueuePanel({ ); const sourceApplyStatus = actionResult?.apply_status ?? sourceApply?.apply_status; const sourceApplyStatusKeyValue = sourceApplyStatusKey(sourceApplyStatus); + const sourceFlowStatus = recurrenceSourceFlowStatus({ + item, + actionResult, + sourceApplyStatus: sourceApplyStatusKeyValue, + sourceDecision: sourceDecisionKey, + reviewStatus: reviewRecordStatusKey, + }); + const SourceFlowIcon = recurrenceSourceFlowIcon(sourceFlowStatus); + const sourceFlowEvent = + actionResult?.source_event_provider_event_id ?? + sourceApply?.source_event_provider_event_id ?? + item.latest_provider_event_id ?? + "--"; const canApplySource = isSourceReview && sourceReview?.decision === "accepted" && @@ -1605,6 +1687,35 @@ function RecurrenceWorkQueuePanel({ signoz: item.signoz_ref_total ?? 0, })}

+
+ + +

+ {t("sourceFlow.detail", { + refs: item.source_ref_total ?? 0, + sentry: item.sentry_ref_total ?? 0, + signoz: item.signoz_ref_total ?? 0, + event: sourceFlowEvent, + })} +

+

{t("workItem", { id: workItem?.work_item_id ?? "--" })}

{t("repair", {