From 24d7d071606add8d73cfe1c90b459d9d0e30c198 Mon Sep 17 00:00:00 2001 From: Vimal Kumar Date: Thu, 25 Jun 2026 15:42:03 +0530 Subject: [PATCH] OLS-3277: display approver identity on proposal detail page Show spec.approver username and approvedAt timestamp on the Overview tab after approval. Data is injected by the mutating admission webhook and read from the ProposalApproval CR watch. Co-Authored-By: Claude Opus 4.6 Signed-off-by: Vimal Kumar --- .../proposals/ProposalDetailPage.tsx | 384 ++++++++++-------- src/hooks/useStageApproval.ts | 12 +- src/models/proposal.ts | 7 + 3 files changed, 229 insertions(+), 174 deletions(-) diff --git a/src/components/proposals/ProposalDetailPage.tsx b/src/components/proposals/ProposalDetailPage.tsx index 1a34574..cc7fd1f 100644 --- a/src/components/proposals/ProposalDetailPage.tsx +++ b/src/components/proposals/ProposalDetailPage.tsx @@ -217,8 +217,12 @@ const ApprovalCard: React.FC<{ )} - } - isInline - title={t('Action failed')} - variant="danger" + + - {actionError} - - )} + + + + + + + {proposal.metadata.name} + + + + + + + -
- {visibleTabs.map((id) => ( - - ))} -
-
- {effectiveTab === 'overview' && ( - setEscalateOpen(false)} proposal={proposal} - latestExecutionResult={latestExecutionResult} - latestVerificationResult={latestVerificationResult} /> )} - {effectiveTab === 'proposal' && ( - - )} - {effectiveTab === 'result' && ( - - )} - {effectiveTab === 'verification' && ( - setEscalateOpen(true)} - proposal={proposal} - verificationApproval={verificationApproval} - /> - )} - {effectiveTab === 'escalation' && ( - + + {actionError && ( + + {t('Close')} + + } + isInline + title={t('Action failed')} + variant="danger" + > + {actionError} + )} -
-
+ +
+ {visibleTabs.map((id) => ( + + ))} +
+
+ {effectiveTab === 'overview' && ( + + )} + {effectiveTab === 'proposal' && ( + + )} + {effectiveTab === 'result' && ( + + )} + {effectiveTab === 'verification' && ( + setEscalateOpen(true)} + proposal={proposal} + verificationApproval={verificationApproval} + /> + )} + {effectiveTab === 'escalation' && ( + + )} +
+ ); }; diff --git a/src/hooks/useStageApproval.ts b/src/hooks/useStageApproval.ts index ae7c250..9f892ec 100644 --- a/src/hooks/useStageApproval.ts +++ b/src/hooks/useStageApproval.ts @@ -91,5 +91,15 @@ export function useStageApproval( const clearError = React.useCallback(() => setError(null), []); - return { needsApproval: needs, stageStatus: status, approve, deny, inProgress, error, clearError, canApprove, canApproveLoading }; + return { + needsApproval: needs, + stageStatus: status, + approve, + deny, + inProgress, + error, + clearError, + canApprove, + canApproveLoading, + }; } diff --git a/src/models/proposal.ts b/src/models/proposal.ts index f8eebd1..7a3f2b7 100644 --- a/src/models/proposal.ts +++ b/src/models/proposal.ts @@ -215,7 +215,14 @@ export type ApprovalStageStatus = { conditions?: ProposalCondition[]; }; +export type ApproverInfo = { + username?: string; + uid?: string; + approvedAt?: string; +}; + export type ProposalApprovalSpec = { + approver?: ApproverInfo; stages?: ApprovalStage[]; };