From 5ca8a1c005e7d6f95969a5bd469f3ba75eba1351 Mon Sep 17 00:00:00 2001 From: potter Date: Thu, 14 May 2026 15:05:39 +0800 Subject: [PATCH] Remove legacy team home components --- .../src/pages/teams/LegacyTeamsHome.tsx | 252 ------------ .../src/pages/teams/TeamsHomeRosterV0.tsx | 275 ------------- .../src/pages/teams/teamsHomeShared.tsx | 364 ------------------ 3 files changed, 891 deletions(-) delete mode 100644 apps/aevatar-console-web/src/pages/teams/LegacyTeamsHome.tsx delete mode 100644 apps/aevatar-console-web/src/pages/teams/TeamsHomeRosterV0.tsx delete mode 100644 apps/aevatar-console-web/src/pages/teams/teamsHomeShared.tsx diff --git a/apps/aevatar-console-web/src/pages/teams/LegacyTeamsHome.tsx b/apps/aevatar-console-web/src/pages/teams/LegacyTeamsHome.tsx deleted file mode 100644 index 0bf7545c9..000000000 --- a/apps/aevatar-console-web/src/pages/teams/LegacyTeamsHome.tsx +++ /dev/null @@ -1,252 +0,0 @@ -import { - BranchesOutlined, - ClockCircleOutlined, - PauseCircleOutlined, -} from "@ant-design/icons"; -import { Alert, Button, Space, Typography } from "antd"; -import React from "react"; -import { history } from "@/shared/navigation/history"; -import { buildTeamWorkspaceRoute } from "@/shared/navigation/scopeRoutes"; -import { buildStudioWorkflowWorkspaceRoute } from "@/shared/studio/navigation"; -import { - AevatarPageShell, - AevatarPanel, - AevatarStatusTag, - AevatarTwoPaneLayout, -} from "@/shared/ui/aevatarPageShells"; -import { - SharedTeamsHomeProps, - SummaryCard, - renderHealthLabel, - summarizeLatestHandoff, - summarizeOwner, -} from "./teamsHomeShared"; - -const LegacyTeamsHome: React.FC = ({ - actorGraphUnavailable, - activityUnavailable, - lens, - resolvedScopeId, - teamSignalIssues, -}) => { - const latestRelationship = lens.graph.relationships[0]; - const currentRunSummary = lens.currentRun - ? `${lens.currentRun.runId} · ${lens.currentRun.completionStatus || "unknown"}` - : "No recent run is visible yet."; - const primaryActionLabel = - lens.healthStatus === "blocked" || lens.healthStatus === "human-overridden" - ? "Handle current blockage" - : lens.healthStatus === "degraded" || lens.healthStatus === "attention" - ? "Review current attention" - : "View current team"; - const stageProvenance = actorGraphUnavailable - ? { label: "Unavailable", status: "unavailable" } - : lens.graph.available - ? { label: "Live", status: "live" } - : { label: "Partial", status: "partial" }; - const activityProvenance = activityUnavailable - ? { label: "Unavailable", status: "unavailable" } - : lens.currentRun - ? { label: "Delayed", status: "delayed" } - : { label: "Partial", status: "partial" }; - - return ( - - - - - } - title={ - - Teams - - - } - titleHelp="Teams Home is the current-team workbench. It should tell users who owns the flow, what just happened, and what to do next without sending them straight into a builder." - > - {teamSignalIssues.length > 0 ? ( - - ) : null} - - - } - title="Recent activity summary" - titleHelp="This rail stays secondary on purpose. It explains what changed recently without taking over the team story." - > - -
- Current run - - {currentRunSummary} - -
-
- Latest change - - {lens.compare.summary} - -
-
- Current anomaly or risk - - {lens.playback.prompt || lens.healthSummary} - -
-
-
- 0 ? "Partial" : "Live"} - status={lens.partialSignals.length > 0 ? "partial" : "live"} - /> - } - title="Current team identity" - > - - - {lens.title} - - - {resolvedScopeId} - - - {lens.subtitle} - - - - - } - railWidth={340} - stage={ - - } - title="Current collaboration snapshot" - titleHelp="The first screen should answer who owns the flow, the latest visible handoff, and the current risk before the user decides where to click." - > -
- } - label="Current owner" - tone="info" - value={summarizeOwner( - lens.graph.focusActorId, - lens.currentRun?.actorId, - )} - /> - } - label="Latest handoff" - tone="default" - value={summarizeLatestHandoff( - latestRelationship?.fromActorId, - latestRelationship?.toActorId, - )} - /> - } - label="Current risk" - tone={lens.healthTone} - value={ - lens.playback.interactionLabel || - renderHealthLabel(lens.healthStatus) - } - /> -
-
- -
- Mission - - {lens.subtitle} - -
-
- Next best move - - {primaryActionLabel === "View current team" - ? "The team is stable enough to enter the team workspace." - : "The team needs operator attention before more changes are introduced."} - -
- {lens.partialSignals.length > 0 ? ( - - ) : null} -
-
- } - /> -
- ); -}; - -export default LegacyTeamsHome; diff --git a/apps/aevatar-console-web/src/pages/teams/TeamsHomeRosterV0.tsx b/apps/aevatar-console-web/src/pages/teams/TeamsHomeRosterV0.tsx deleted file mode 100644 index bc242557f..000000000 --- a/apps/aevatar-console-web/src/pages/teams/TeamsHomeRosterV0.tsx +++ /dev/null @@ -1,275 +0,0 @@ -import { Alert, Button, Grid, Space, Typography, theme } from "antd"; -import React from "react"; -import { history } from "@/shared/navigation/history"; -import { buildTeamWorkspaceRoute } from "@/shared/navigation/scopeRoutes"; -import { AevatarPageShell, AevatarPanel, AevatarStatusTag } from "@/shared/ui/aevatarPageShells"; -import { - RosterField, - SharedTeamsHomeProps, - deriveRosterReason, - formatFreshnessAge, - renderHealthLabel, - resolveFreshnessTimestamp, - summarizeOwner, -} from "./teamsHomeShared"; - -const TeamsHomeRosterV0: React.FC = ({ - lens, - resolvedScopeId, - teamSignalIssues, -}) => { - const { token } = theme.useToken(); - const screens = Grid.useBreakpoint(); - const reason = deriveRosterReason(lens); - const currentOwner = summarizeOwner( - lens.graph.focusActorId, - lens.currentRun?.actorId, - ); - const freshnessAge = formatFreshnessAge(resolveFreshnessTimestamp(lens)); - const rowTruthStatus = lens.partialSignals.length > 0 ? "partial" : "live"; - const rowTruthLabel = - lens.partialSignals.length > 0 ? "Partial truth" : "Live truth"; - const recentActivityLabel = - lens.recentRunCount === 1 ? "1 visible run" : `${lens.recentRunCount} visible runs`; - const whyNowBorderColor = - lens.healthStatus === "healthy" - ? token.colorInfoBorder - : token.colorWarningBorder; - const rosterGridTemplateColumns = screens.xxl - ? "minmax(220px, 1.1fr) minmax(260px, 1.35fr) minmax(200px, 0.95fr) minmax(180px, 0.9fr) minmax(152px, 0.7fr)" - : screens.xl - ? "minmax(220px, 1.1fr) minmax(260px, 1.35fr) minmax(200px, 0.95fr) minmax(180px, 0.9fr)" - : screens.md - ? "minmax(220px, 1fr) minmax(240px, 1.15fr)" - : "1fr"; - const actionFieldStyle = screens.xxl - ? { alignSelf: "start" as const } - : screens.md - ? { - alignItems: "flex-end" as const, - gridColumn: "1 / -1", - } - : undefined; - const actionButtonStyle = screens.xxl - ? { width: "100%" } - : screens.md - ? { minWidth: 168 } - : { width: "100%" }; - const actionHelperStyle: React.CSSProperties = { - maxWidth: screens.xxl ? 190 : screens.md ? 260 : undefined, - textAlign: screens.xxl ? "left" : screens.md ? "right" : "left", - }; - const technicalTextStyle: React.CSSProperties = { - overflowWrap: "anywhere", - wordBreak: "break-word", - }; - - return ( - -
-
-
- Reference roster - - This page uses roster grammar to preview the team currently exposed - by the active session. It does not rank multiple teams yet. - -
- - - - -
- - {teamSignalIssues.length > 0 ? ( - - ) : null} - - - - 0 ? "Partial truth" : "Live truth"} - status={lens.partialSignals.length > 0 ? "partial" : "live"} - /> - - } - title="Current session roster" - description="One team, read like a roster row. The question here is whether it is worth opening this team right now." - > -
- -
- - {lens.title} - - - {resolvedScopeId} - - - {lens.subtitle} - -
-
- - -
- - {reason.label} - - - {reason.detail} - - {reason.support.length > 0 ? ( -
- {reason.support.map((item) => ( - - {item} - - ))} -
- ) : null} -
-
- - -
-
- Current owner - - {currentOwner} - -
-
- Current focus - - {lens.graph.focusReason} - -
-
-
- - -
-
- Recent activity - - {recentActivityLabel} - -
-
- Freshness - - {freshnessAge} - -
- {lens.partialSignals.length > 0 ? ( -
- Missing signals - - {lens.partialSignals.join(" · ")} - -
- ) : null} -
-
- - -
- - - Open the full workspace for compare, topology, playback, and governance detail. - -
-
-
-
-
-
- ); -}; - -export default TeamsHomeRosterV0; diff --git a/apps/aevatar-console-web/src/pages/teams/teamsHomeShared.tsx b/apps/aevatar-console-web/src/pages/teams/teamsHomeShared.tsx deleted file mode 100644 index 0958e86e8..000000000 --- a/apps/aevatar-console-web/src/pages/teams/teamsHomeShared.tsx +++ /dev/null @@ -1,364 +0,0 @@ -import { Alert, Button, Empty, Skeleton, Space, Typography, theme } from "antd"; -import React from "react"; -import { history } from "@/shared/navigation/history"; -import { buildStudioWorkflowEditorRoute } from "@/shared/studio/navigation"; -import { - AevatarPageShell, - AevatarPanel, - AevatarStatusTag, -} from "@/shared/ui/aevatarPageShells"; -import { - buildAevatarMetricCardStyle, - resolveAevatarMetricVisual, - type AevatarSemanticTone, - type AevatarThemeSurfaceToken, -} from "@/shared/ui/aevatarWorkbench"; -import type { TeamRuntimeLens } from "./runtime/teamRuntimeLens"; - -export type SharedTeamsHomeProps = { - actorGraphUnavailable: boolean; - activityUnavailable: boolean; - lens: TeamRuntimeLens; - resolvedScopeId: string; - teamSignalIssues: string[]; -}; - -type SummaryCardProps = { - caption?: React.ReactNode; - icon?: React.ReactNode; - label: React.ReactNode; - tone?: AevatarSemanticTone; - value: React.ReactNode; -}; - -type RosterFieldProps = { - children: React.ReactNode; - style?: React.CSSProperties; - title: string; -}; - -export type RosterReason = { - detail: string; - label: string; - support: string[]; -}; - -export function renderHealthLabel(status: string): string { - switch (status) { - case "human-overridden": - return "Human Override"; - case "blocked": - return "Blocked"; - case "degraded": - return "Degraded"; - case "healthy": - return "Healthy"; - default: - return "Attention"; - } -} - -export function summarizeOwner( - focusActorId?: string, - fallbackActorId?: string, -): string { - const resolvedActorId = focusActorId?.trim() || fallbackActorId?.trim() || ""; - if (!resolvedActorId) { - return "No current owner visible"; - } - - return resolvedActorId; -} - -export function summarizeLatestHandoff( - fromActorId?: string, - toActorId?: string, -): string { - const from = fromActorId?.trim() || ""; - const to = toActorId?.trim() || ""; - if (!from || !to) { - return "No visible handoff yet"; - } - - return `${from} -> ${to}`; -} - -export function resolveFreshnessTimestamp(lens: TeamRuntimeLens): string | null { - const playbackStepTimestamp = - lens.playback.steps.find((step) => Boolean(step.timestamp))?.timestamp ?? null; - const playbackEventTimestamp = - lens.playback.events.find((event) => Boolean(event.timestamp))?.timestamp ?? null; - - return ( - lens.currentRun?.lastUpdatedAt || playbackStepTimestamp || playbackEventTimestamp - ); -} - -export function formatFreshnessAge(timestamp: string | null): string { - const parsed = Date.parse(timestamp || ""); - if (!Number.isFinite(parsed)) { - return "Not visible"; - } - - const ageMs = Math.max(0, Date.now() - parsed); - if (ageMs < 60_000) { - return "<1m ago"; - } - - const ageMinutes = Math.floor(ageMs / 60_000); - if (ageMinutes < 60) { - return `${ageMinutes}m ago`; - } - - const ageHours = Math.floor(ageMinutes / 60); - if (ageHours < 24) { - return `${ageHours}h ago`; - } - - const ageDays = Math.floor(ageHours / 24); - return `${ageDays}d ago`; -} - -export function deriveRosterReason(lens: TeamRuntimeLens): RosterReason { - const compareSummary = lens.compare.summary.trim(); - const missingSignals = - lens.partialSignals.length > 0 - ? `Missing signals: ${lens.partialSignals.join(" · ")}` - : ""; - - if ( - lens.healthStatus === "blocked" || - lens.healthStatus === "human-overridden" - ) { - return { - detail: lens.playback.prompt || lens.healthSummary, - label: "A recent run is waiting on human input", - support: [compareSummary].filter(Boolean).slice(0, 2), - }; - } - - if (lens.healthStatus === "degraded" || lens.healthStatus === "attention") { - return { - detail: lens.healthSummary, - label: "Current runtime health still needs attention", - support: [compareSummary].filter(Boolean).slice(0, 2), - }; - } - - if (lens.partialSignals.length > 0) { - return { - detail: missingSignals, - label: "Some runtime signals are incomplete", - support: [compareSummary].filter(Boolean).slice(0, 2), - }; - } - - if ((lens.recentRunCount ?? 0) === 0) { - return { - detail: - "No recent run is visible yet, so this page can only offer a reference read before you open the team workspace.", - label: "No recent runtime proof is visible", - support: [compareSummary].filter(Boolean).slice(0, 2), - }; - } - - return { - detail: - lens.healthSummary || - "Recent runtime signals look healthy enough to continue in the team workspace.", - label: "The current session team looks stable", - support: [compareSummary].filter(Boolean).slice(0, 2), - }; -} - -export function SummaryCard({ - caption, - icon, - label, - tone = "default", - value, -}: SummaryCardProps) { - const { token } = theme.useToken(); - const visual = resolveAevatarMetricVisual( - token as AevatarThemeSurfaceToken, - tone, - ); - - return ( -
- - {icon ? ( - - {icon} - - ) : null} - - {label} - - - - {value} - - {caption ? ( - - {caption} - - ) : null} -
- ); -} - -export function RosterField({ children, style, title }: RosterFieldProps) { - const { token } = theme.useToken(); - - return ( -
- - {title} - - {children} -
- ); -} - -export const TeamsHomeLoading: React.FC = () => { - return ( - - - } - title="Current session team" - > -
- - -
-
-
- ); -}; - -export const TeamContextUnavailable: React.FC<{ - authSessionErrored: boolean; - onRetry: () => void; - teamResolutionDescription: string; -}> = ({ authSessionErrored, onRetry, teamResolutionDescription }) => { - return ( - - - } - title="Team context unavailable" - > - - - The console could not resolve a current team from the active session. - Open Settings, retry, or start the first team from Studio. - - {authSessionErrored ? ( - - ) : null} - - - {authSessionErrored ? ( - - ) : ( - - )} - {authSessionErrored ? ( - - ) : null} - - - - - - ); -};