-
Notifications
You must be signed in to change notification settings - Fork 18
feat: open single plan result from url #1034
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,20 @@ | ||||||||||||||||||||
| import { useSearchParams } from "react-router"; | ||||||||||||||||||||
|
|
||||||||||||||||||||
| export function usePlanResultParam() { | ||||||||||||||||||||
| const [searchParams, setSearchParams] = useSearchParams(); | ||||||||||||||||||||
| const resultId = searchParams.get("resultId") ?? undefined; | ||||||||||||||||||||
|
|
||||||||||||||||||||
| const openResult = (id: string) => { | ||||||||||||||||||||
|
Comment on lines
+5
to
+7
|
||||||||||||||||||||
| const resultId = searchParams.get("resultId") ?? undefined; | |
| const openResult = (id: string) => { | |
| const resultId = searchParams.get("resultId") || undefined; | |
| const openResult = (id: string) => { | |
| if (!id) { | |
| return; | |
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -26,6 +26,7 @@ import { useDeployment } from "./_components/DeploymentProvider"; | |
| import { DeploymentsNavbarTabs } from "./_components/DeploymentsNavbarTabs"; | ||
| import { PlanDiffDialog } from "./_components/plans/PlanDiffDialog"; | ||
| import { PlanStatusBadge } from "./_components/plans/PlanStatusBadge"; | ||
| import { usePlanResultParam } from "./_hooks/usePlanResultParam"; | ||
|
|
||
| export function meta() { | ||
| return [ | ||
|
|
@@ -36,12 +37,16 @@ export function meta() { | |
|
|
||
| type Result = RouterOutputs["deployment"]["plans"]["results"][number]; | ||
|
|
||
| function resultTitle(result: Result) { | ||
| return `${result.environment.name} · ${result.resource.name} · ${result.agent.name}`; | ||
| } | ||
|
|
||
| function ChangesCell({ | ||
| result, | ||
| deploymentId, | ||
| onViewDiff, | ||
| }: { | ||
| result: Result; | ||
| deploymentId: string; | ||
| onViewDiff: (resultId: string) => void; | ||
| }) { | ||
| if (result.status === "computing") | ||
| return <span className="text-muted-foreground">—</span>; | ||
|
|
@@ -58,19 +63,14 @@ function ChangesCell({ | |
| return <span className="text-muted-foreground">Unsupported</span>; | ||
| if (result.hasChanges === true) | ||
| return ( | ||
| <PlanDiffDialog | ||
| deploymentId={deploymentId} | ||
| resultId={result.resultId} | ||
| title={`${result.environment.name} · ${result.resource.name} · ${result.agent.name}`} | ||
| <Button | ||
| variant="outline" | ||
| size="sm" | ||
| className="h-6 cursor-pointer hover:bg-accent hover:text-accent-foreground" | ||
| onClick={() => onViewDiff(result.resultId)} | ||
| > | ||
| <Button | ||
| variant="outline" | ||
| size="sm" | ||
| className="h-6 cursor-pointer hover:bg-accent hover:text-accent-foreground" | ||
| > | ||
| View diff | ||
| </Button> | ||
| </PlanDiffDialog> | ||
| View diff | ||
| </Button> | ||
| ); | ||
| if (result.hasChanges === false) | ||
| return <span className="text-muted-foreground">No changes</span>; | ||
|
|
@@ -93,10 +93,10 @@ function ResultsTableHeader() { | |
|
|
||
| function ResultsTableRow({ | ||
| result, | ||
| deploymentId, | ||
| onViewDiff, | ||
| }: { | ||
| result: Result; | ||
| deploymentId: string; | ||
| onViewDiff: (resultId: string) => void; | ||
| }) { | ||
| return ( | ||
| <TableRow className="hover:bg-muted/50"> | ||
|
|
@@ -107,7 +107,7 @@ function ResultsTableRow({ | |
| <PlanStatusBadge status={result.status} /> | ||
| </TableCell> | ||
| <TableCell> | ||
| <ChangesCell result={result} deploymentId={deploymentId} /> | ||
| <ChangesCell result={result} onViewDiff={onViewDiff} /> | ||
| </TableCell> | ||
| </TableRow> | ||
| ); | ||
|
|
@@ -135,13 +135,15 @@ export default function DeploymentPlanDetail() { | |
| const { workspace } = useWorkspace(); | ||
| const { deployment } = useDeployment(); | ||
| const { planId } = useParams<{ planId: string }>(); | ||
| const { resultId, openResult, closeResult } = usePlanResultParam(); | ||
|
|
||
| const resultsQuery = trpc.deployment.plans.results.useQuery( | ||
| { deploymentId: deployment.id, planId: planId! }, | ||
| { enabled: !!planId, refetchInterval: 5000 }, | ||
| ); | ||
|
|
||
| const results = resultsQuery.data ?? []; | ||
| const activeResult = results.find((r) => r.resultId === resultId); | ||
|
|
||
| return ( | ||
| <> | ||
|
|
@@ -192,12 +194,22 @@ export default function DeploymentPlanDetail() { | |
| <ResultsTableRow | ||
| key={r.resultId} | ||
| result={r} | ||
| deploymentId={deployment.id} | ||
| onViewDiff={openResult} | ||
| /> | ||
| ))} | ||
| </TableBody> | ||
| </Table> | ||
| )} | ||
|
|
||
| <PlanDiffDialog | ||
| deploymentId={deployment.id} | ||
| resultId={resultId} | ||
| title={activeResult ? resultTitle(activeResult) : ""} | ||
| open={resultId != null} | ||
|
Comment on lines
+206
to
+208
|
||
| onOpenChange={(o) => { | ||
| if (!o) closeResult(); | ||
| }} | ||
| /> | ||
| </> | ||
| ); | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
enabled: open && resultId != nullwill still run the query whenresultIdis an empty string (e.g. URL?resultId=). That will call the API withresultId: ""due toresultId ?? "". Tighten the guard to require a non-empty id (e.g.!!resultId) and avoid passing a placeholder empty string as the query input.