Skip to content

Commit 8758666

Browse files
authored
[UI v2] Variables table - part 1 (#15985)
1 parent 1bed197 commit 8758666

File tree

15 files changed

+874
-212
lines changed

15 files changed

+874
-212
lines changed

ui-v2/src/api/service.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,17 @@ const throwOnError: Middleware = {
99
}
1010
},
1111
};
12+
13+
let client: ReturnType<typeof createClient<paths>> | null = null;
14+
1215
// TODO: Make the baseUrl configurable
13-
export const createQueryService = () => {
14-
const client = createClient<paths>({
15-
baseUrl: "http://localhost:4200/api",
16-
});
17-
client.use(throwOnError);
16+
export const getQueryService = () => {
17+
if (!client) {
18+
client = createClient<paths>({
19+
baseUrl:
20+
(import.meta.env.VITE_API_URL as string) ?? "http://localhost:4200/api",
21+
});
22+
client.use(throwOnError);
23+
}
1824
return client;
1925
};

ui-v2/src/components/flows/data-table.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { components } from "@/api/prefect";
1+
import type { components } from "@/api/prefect";
22
import { Button } from "@/components/ui/button";
33
import { DataTable } from "@/components/ui/data-table";
44
import {

ui-v2/src/components/flows/detail/cells.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { components } from "@/api/prefect";
2-
import { createQueryService } from "@/api/service";
1+
import type { components } from "@/api/prefect";
2+
import { getQueryService } from "@/api/service";
33
import { useQuery } from "@tanstack/react-query";
44

55
type FlowRun = components["schemas"]["FlowRun"];
@@ -9,7 +9,7 @@ export const DeploymentCell = ({ row }: { row: { original: FlowRun } }) => {
99
const { data: deployment } = useQuery({
1010
queryKey: ["deployment", deploymentId],
1111
queryFn: () =>
12-
createQueryService().GET("/deployments/{id}", {
12+
getQueryService().GET("/deployments/{id}", {
1313
params: { path: { id: deploymentId as string } },
1414
}),
1515
enabled: !!deploymentId,
@@ -22,7 +22,7 @@ export const WorkPoolCell = ({ row }: { row: { original: FlowRun } }) => {
2222
const { data: deployment } = useQuery({
2323
queryKey: ["deployment", deploymentId],
2424
queryFn: () =>
25-
createQueryService().GET("/deployments/{id}", {
25+
getQueryService().GET("/deployments/{id}", {
2626
params: { path: { id: deploymentId as string } },
2727
}),
2828
enabled: !!deploymentId,

ui-v2/src/components/flows/queries.tsx

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { components } from "@/api/prefect";
2-
import { createQueryService } from "@/api/service";
2+
import { getQueryService } from "@/api/service";
33
import {
44
MutationFunction,
55
QueryFunction,
@@ -18,7 +18,7 @@ export const flowQueryParams = (
1818
...queryParams,
1919
queryKey: ["flows", flowId] as const,
2020
queryFn: async (): Promise<components["schemas"]["Flow"]> => {
21-
const response = await createQueryService()
21+
const response = await getQueryService()
2222
.GET("/flows/{id}", {
2323
params: { path: { id: flowId } },
2424
})
@@ -38,7 +38,7 @@ export const flowRunsQueryParams = (
3838
...queryParams,
3939
queryKey: ["flowRun", JSON.stringify({ flowId: id, ...body })] as const,
4040
queryFn: async () => {
41-
const response = await createQueryService()
41+
const response = await getQueryService()
4242
.POST("/flow_runs/filter", {
4343
body: {
4444
...body,
@@ -73,7 +73,7 @@ export const getLatestFlowRunsQueryParams = (
7373
}),
7474
] as const,
7575
queryFn: async () => {
76-
const response = await createQueryService()
76+
const response = await getQueryService()
7777
.POST("/flow_runs/filter", {
7878
body: {
7979
flows: { operator: "and_" as const, id: { any_: [id] } },
@@ -113,7 +113,7 @@ export const getNextFlowRunsQueryParams = (
113113
}),
114114
] as const,
115115
queryFn: async () => {
116-
const response = await createQueryService()
116+
const response = await getQueryService()
117117
.POST("/flow_runs/filter", {
118118
body: {
119119
flows: { operator: "and_" as const, id: { any_: [id] } },
@@ -144,7 +144,7 @@ export const flowRunsCountQueryParams = (
144144
...queryParams,
145145
queryKey: ["flowRunCount", JSON.stringify({ flowId: id, ...body })] as const,
146146
queryFn: async () => {
147-
const response = await createQueryService()
147+
const response = await getQueryService()
148148
.POST("/flow_runs/count", {
149149
body: {
150150
...body,
@@ -178,7 +178,7 @@ export const deploymentsQueryParams = (
178178
...queryParams,
179179
queryKey: ["deployments", JSON.stringify({ ...body, flowId: id })] as const,
180180
queryFn: async () => {
181-
const response = await createQueryService()
181+
const response = await getQueryService()
182182
.POST("/deployments/filter", {
183183
body: {
184184
...body,
@@ -204,7 +204,7 @@ export const deploymentsCountQueryParams = (
204204
...queryParams,
205205
queryKey: ["deploymentsCount", JSON.stringify({ flowId: id })] as const,
206206
queryFn: async () => {
207-
const response = await createQueryService()
207+
const response = await getQueryService()
208208
.POST("/deployments/count", {
209209
body: { flows: { operator: "and_" as const, id: { any_: [id] } } },
210210
})
@@ -219,7 +219,7 @@ export const deleteFlowMutation = (
219219
mutationFn: MutationFunction<void>;
220220
} => ({
221221
mutationFn: async () => {
222-
await createQueryService().DELETE("/flows/{id}", {
222+
await getQueryService().DELETE("/flows/{id}", {
223223
params: { path: { id } },
224224
});
225225
},

ui-v2/src/components/ui/data-table.tsx

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,18 @@ import {
66
TableHeader,
77
TableRow,
88
} from "@/components/ui/table";
9-
import { Table as TanstackTable, flexRender } from "@tanstack/react-table";
9+
import { type Table as TanstackTable, flexRender } from "@tanstack/react-table";
1010

1111
import {
1212
Pagination,
1313
PaginationContent,
14-
PaginationEllipsis,
1514
PaginationItem,
16-
PaginationLink,
17-
PaginationNext,
18-
PaginationPrevious,
15+
PaginationNextButton,
16+
PaginationPreviousButton,
17+
PaginationFirstButton,
18+
PaginationLastButton,
1919
} from "@/components/ui/pagination";
20+
import { cn } from "@/lib/utils";
2021

2122
export function DataTable<TData>({
2223
table,
@@ -73,46 +74,47 @@ export function DataTable<TData>({
7374
</TableBody>
7475
</Table>
7576
</div>
76-
<DataTablePagination
77-
table={table}
78-
onPageChange={(page) => {
79-
table.setPageIndex(page - 1);
80-
}}
81-
/>
77+
<DataTablePagination table={table} />
8278
</>
8379
);
8480
}
8581

8682
interface DataTablePaginationProps<TData> {
8783
table: TanstackTable<TData>;
88-
onPageChange: (page: number) => void;
84+
className?: string;
8985
}
9086

9187
export function DataTablePagination<TData>({
9288
table,
93-
onPageChange,
89+
className,
9490
}: DataTablePaginationProps<TData>) {
9591
return (
96-
<Pagination className="mt-4 justify-end">
92+
<Pagination className={cn("justify-end", className)}>
9793
<PaginationContent>
9894
<PaginationItem>
99-
<PaginationPrevious
100-
onClick={() =>
101-
onPageChange(Math.max(1, table.getState().pagination.pageIndex))
102-
}
95+
<PaginationFirstButton
96+
onClick={() => table.firstPage()}
97+
disabled={!table.getCanPreviousPage()}
98+
/>
99+
<PaginationPreviousButton
100+
onClick={() => table.previousPage()}
101+
disabled={!table.getCanPreviousPage()}
103102
/>
104103
</PaginationItem>
105-
<PaginationItem>
106-
<PaginationLink onClick={() => onPageChange(1)}>1</PaginationLink>
104+
<PaginationItem className="text-sm">
105+
Page {Math.ceil(table.getState().pagination.pageIndex + 1)} of{" "}
106+
{table.getPageCount()}
107107
</PaginationItem>
108108
<PaginationItem>
109-
<PaginationEllipsis />
109+
<PaginationNextButton
110+
onClick={() => table.nextPage()}
111+
disabled={!table.getCanNextPage()}
112+
/>
110113
</PaginationItem>
111114
<PaginationItem>
112-
<PaginationNext
113-
onClick={() =>
114-
onPageChange(table.getState().pagination.pageIndex + 2)
115-
}
115+
<PaginationLastButton
116+
onClick={() => table.lastPage()}
117+
disabled={!table.getCanNextPage()}
116118
/>
117119
</PaginationItem>
118120
</PaginationContent>

ui-v2/src/components/ui/pagination.tsx

Lines changed: 89 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,25 @@
1+
import { DotsHorizontalIcon } from "@radix-ui/react-icons";
12
import {
2-
ChevronLeftIcon,
3-
ChevronRightIcon,
4-
DotsHorizontalIcon,
5-
} from "@radix-ui/react-icons";
3+
ChevronsLeft,
4+
ChevronsRight,
5+
ChevronLeft,
6+
ChevronRight,
7+
} from "lucide-react";
68
import * as React from "react";
7-
8-
import { ButtonProps, buttonVariants } from "@/components/ui/button";
9+
import {
10+
Button,
11+
type ButtonProps,
12+
buttonVariants,
13+
} from "@/components/ui/button";
914
import { cn } from "@/lib/utils";
10-
import { Link, LinkProps } from "@tanstack/react-router";
15+
import { Link, type LinkProps } from "@tanstack/react-router";
1116

1217
type PaginationProps = React.ComponentProps<"nav"> & {
1318
className?: string;
1419
};
1520

1621
const Pagination = ({ className, ...props }: PaginationProps) => (
1722
<nav
18-
role="navigation"
1923
aria-label="pagination"
2024
className={cn("mx-auto flex w-full justify-center", className)}
2125
{...props}
@@ -79,46 +83,66 @@ const PaginationPrevious = ({
7983
className,
8084
...props
8185
}: React.ComponentProps<typeof PaginationLink> & LinkProps) => (
82-
<Link
86+
<PaginationLink
8387
aria-label="Go to previous page"
84-
className={cn(
85-
buttonVariants({
86-
variant: "ghost",
87-
size: "default",
88-
}),
89-
"gap-1 pl-2.5",
90-
className,
91-
)}
88+
size="default"
89+
className={cn("gap-1 pl-2.5", className)}
9290
{...props}
9391
>
94-
<ChevronLeftIcon className="h-4 w-4" />
92+
<ChevronLeft className="h-4 w-4" />
9593
<span>Previous</span>
96-
</Link>
94+
</PaginationLink>
9795
);
9896
PaginationPrevious.displayName = "PaginationPrevious";
9997

98+
const PaginationPreviousButton = ({
99+
className,
100+
...props
101+
}: React.ComponentProps<typeof Button> & { className?: string }) => (
102+
<Button
103+
aria-label="Go to previous page"
104+
size="default"
105+
variant="ghost"
106+
className={cn("gap-1 pl-2.5", className)}
107+
{...props}
108+
>
109+
<ChevronLeft className="h-4 w-4" />
110+
</Button>
111+
);
112+
PaginationPreviousButton.displayName = "PaginationPreviousButton";
113+
100114
const PaginationNext = ({
101115
className,
102116
...props
103117
}: React.ComponentProps<typeof PaginationLink> & LinkProps) => (
104-
<Link
118+
<PaginationLink
105119
aria-label="Go to next page"
106-
className={cn(
107-
buttonVariants({
108-
variant: "ghost",
109-
size: "default",
110-
}),
111-
"gap-1 pr-2.5",
112-
className,
113-
)}
120+
size="default"
121+
className={cn("gap-1 pr-2.5", className)}
114122
{...props}
115123
>
116124
<span>Next</span>
117-
<ChevronRightIcon className="h-4 w-4" />
118-
</Link>
125+
<ChevronRight className="h-4 w-4" />
126+
</PaginationLink>
119127
);
120128
PaginationNext.displayName = "PaginationNext";
121129

130+
const PaginationNextButton = ({
131+
className,
132+
...props
133+
}: React.ComponentProps<typeof Button> & { className?: string }) => (
134+
<Button
135+
aria-label="Go to next page"
136+
variant="ghost"
137+
size="default"
138+
className={cn("gap-1 pr-2.5", className)}
139+
{...props}
140+
>
141+
<ChevronRight className="h-4 w-4" />
142+
</Button>
143+
);
144+
PaginationNextButton.displayName = "PaginationNextButton";
145+
122146
type PaginationEllipsisProps = React.ComponentProps<"span"> & {
123147
className?: string;
124148
};
@@ -138,6 +162,37 @@ const PaginationEllipsis = ({
138162
);
139163
PaginationEllipsis.displayName = "PaginationEllipsis";
140164

165+
const PaginationFirstButton = ({
166+
className,
167+
...props
168+
}: React.ComponentProps<typeof Button> & { className?: string }) => (
169+
<Button
170+
aria-label="Go to first page"
171+
variant="ghost"
172+
size="default"
173+
className={cn("gap-1 pl-2.5", className)}
174+
{...props}
175+
>
176+
<ChevronsLeft className="h-4 w-4" />
177+
</Button>
178+
);
179+
PaginationFirstButton.displayName = "PaginationFirstButton";
180+
181+
const PaginationLastButton = ({
182+
className,
183+
...props
184+
}: React.ComponentProps<typeof Button> & { className?: string }) => (
185+
<Button
186+
aria-label="Go to last page"
187+
variant="ghost"
188+
size="default"
189+
className={cn("gap-1 pr-2.5", className)}
190+
{...props}
191+
>
192+
<ChevronsRight className="h-4 w-4" />
193+
</Button>
194+
);
195+
141196
export {
142197
Pagination,
143198
PaginationContent,
@@ -146,4 +201,8 @@ export {
146201
PaginationPrevious,
147202
PaginationNext,
148203
PaginationEllipsis,
204+
PaginationPreviousButton,
205+
PaginationNextButton,
206+
PaginationFirstButton,
207+
PaginationLastButton,
149208
};

0 commit comments

Comments
 (0)