Skip to content

Commit 05d446e

Browse files
feat: components detail (#691)
1 parent feb697f commit 05d446e

File tree

31 files changed

+621
-229
lines changed

31 files changed

+621
-229
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
},
5252
"devDependencies": {
5353
"@playwright/test": "^1.48.1",
54+
"@tailwindcss/container-queries": "^0.1.1",
5455
"@tailwindcss/forms": "^0.5.7",
5556
"@tailwindcss/typography": "^0.5.10",
5657
"@types/lodash.debounce": "^4.0.9",

pnpm-lock.yaml

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { useParams } from "react-router-dom";
2+
import { StackComponentsDetailHeader } from "../../../components/stack-components/component-detail/Header";
3+
import { StackComponentTabs } from "@/components/stack-components/component-detail/Tabs";
4+
import { StackList } from "../../stacks/StackList";
5+
6+
export default function ComponentDetailPage() {
7+
const { componentId } = useParams() as { componentId: string };
8+
9+
return (
10+
<div className="@container">
11+
<StackComponentsDetailHeader isPanel={false} componentId={componentId} />
12+
<StackComponentTabs
13+
isPanel={false}
14+
stacksTabContent={<StackList fixedQueryParams={{ component_id: componentId }} />}
15+
componentId={componentId}
16+
/>
17+
</div>
18+
);
19+
}

src/app/components/columns.tsx

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { CopyButton } from "@/components/CopyButton";
22
import { DisplayDate } from "@/components/DisplayDate";
33
import { InlineAvatar } from "@/components/InlineAvatar";
4+
import { ComponentSheet } from "@/components/stack-components/component-sheet";
45
import { ComponentBadge } from "@/components/stack-components/ComponentBadge";
5-
import { ComponentFallbackDialog } from "@/components/stack-components/ComponentFallbackDialog";
66
import { snakeCaseToTitleCase } from "@/lib/strings";
77
import { sanitizeUrl } from "@/lib/url";
88
import { getUsername } from "@/lib/user";
@@ -29,18 +29,19 @@ export function getComponentList(): ColumnDef<StackComponent>[] {
2929
/>
3030
<div>
3131
<div className="flex items-center gap-1">
32-
<ComponentFallbackDialog
33-
name={name}
34-
type={row.original.body?.type || "orchestrator"}
35-
>
32+
<ComponentSheet componentId={id}>
3633
<button>
3734
<h2 className="text-text-md font-semibold">{name}</h2>
3835
</button>
39-
</ComponentFallbackDialog>
36+
</ComponentSheet>
4037
<CopyButton copyText={name} />
4138
</div>
4239
<div className="flex items-center gap-1">
43-
<p className="text-text-xs text-theme-text-secondary">{id.split("-")[0]}</p>
40+
<ComponentSheet componentId={id}>
41+
<button className="text-text-xs text-theme-text-secondary">
42+
{id.split("-")[0]}
43+
</button>
44+
</ComponentSheet>
4445
<CopyButton copyText={id} />
4546
</div>
4647
</div>

src/app/stacks/ResumeBanner.tsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { useState } from "react";
2+
import { parseWizardData } from "./create/new-infrastructure/persist";
3+
import { parseWizardData as parseTerraform } from "./create/terraform/persist";
4+
import { ResumeStackBanner } from "./ResumeStackBanner";
5+
import { ResumeTerraformBanner } from "./ResumeTerraformBanner";
6+
7+
export function ResumeBanners() {
8+
const [hasResumeableStack, setResumeableStack] = useState(parseWizardData().success);
9+
const [hasResumeableTerraform, setResumeableTerraform] = useState<boolean>(
10+
parseTerraform().success
11+
);
12+
13+
return (
14+
<div className="space-y-5">
15+
{hasResumeableStack && <ResumeStackBanner setHasResumeableStack={setResumeableStack} />}
16+
{hasResumeableTerraform && (
17+
<ResumeTerraformBanner setHasResumeableTerraform={setResumeableTerraform} />
18+
)}
19+
</div>
20+
);
21+
}

src/app/stacks/StackList.tsx

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,19 @@ import { stackQueries } from "@/data/stacks";
66
import { routes } from "@/router/routes";
77
import { useQuery } from "@tanstack/react-query";
88
import { Button, DataTable, Skeleton } from "@zenml-io/react-component-library";
9-
import { useState } from "react";
109
import { Link } from "react-router-dom";
1110
import { getStackColumns } from "./columns";
12-
import { parseWizardData } from "./create/new-infrastructure/persist";
13-
import { parseWizardData as parseTerraform } from "./create/terraform/persist";
14-
import { ResumeStackBanner } from "./ResumeStackBanner";
1511
import { useStacklistQueryParams } from "./service";
16-
import { ResumeTerraformBanner } from "./ResumeTerraformBanner";
12+
import { StackListQueryParams } from "../../types/stack";
1713

18-
export function StackList() {
19-
const [hasResumeableStack, setResumeableStack] = useState(parseWizardData().success);
20-
const [hasResumeableTerraform, setResumeableTerraform] = useState<boolean>(
21-
parseTerraform().success
22-
);
14+
type Props = {
15+
fixedQueryParams?: StackListQueryParams;
16+
};
17+
18+
export function StackList({ fixedQueryParams = {} }: Props) {
2319
const queryParams = useStacklistQueryParams();
2420
const { refetch, data } = useQuery({
25-
...stackQueries.stackList({ ...queryParams, sort_by: "desc:updated" }),
21+
...stackQueries.stackList({ ...queryParams, sort_by: "desc:updated", ...fixedQueryParams }),
2622
throwOnError: true
2723
});
2824

@@ -45,10 +41,6 @@ export function StackList() {
4541
</div>
4642
</div>
4743
<div className="flex flex-col items-center gap-5">
48-
{hasResumeableStack && <ResumeStackBanner setHasResumeableStack={setResumeableStack} />}
49-
{hasResumeableTerraform && (
50-
<ResumeTerraformBanner setHasResumeableTerraform={setResumeableTerraform} />
51-
)}
5244
<div className="w-full">
5345
{data ? (
5446
<DataTable columns={getStackColumns()} data={data.items} />

src/app/stacks/page.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { useTourContext } from "@/components/tour/TourContext";
22
import { useEffect } from "react";
33
import { StackList } from "./StackList";
4+
import { ResumeBanners } from "./ResumeBanner";
45

56
export default function StacksPage() {
67
const {
@@ -14,5 +15,10 @@ export default function StacksPage() {
1415
}
1516
}, [tourActive]);
1617

17-
return <StackList />;
18+
return (
19+
<div className="space-y-5">
20+
<ResumeBanners />
21+
<StackList />
22+
</div>
23+
);
1824
}

src/assets/icons/expand-full.svg

Lines changed: 4 additions & 0 deletions
Loading

src/components/Pagination.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,24 @@ import { useNavigate } from "react-router-dom";
1010
import { ResponsePage } from "@/types/common";
1111

1212
type Props = {
13+
inMemoryHandler?: (page: number) => void;
1314
// Maybe handle this with a generic?
1415
// eslint-disable-next-line @typescript-eslint/no-explicit-any
1516
searchParams: Record<string, any>;
1617
// eslint-disable-next-line @typescript-eslint/no-explicit-any
1718
paginate: Omit<ResponsePage<any>, "items">;
1819
};
1920

20-
export default function Pagination({ paginate, searchParams }: Props) {
21+
export default function Pagination({ paginate, searchParams, inMemoryHandler }: Props) {
2122
const navigate = useNavigate();
2223

2324
const { index, total_pages } = paginate;
2425

2526
function goToPage(page: number) {
27+
if (!!inMemoryHandler) {
28+
inMemoryHandler(page);
29+
return;
30+
}
2631
const queryParams = new URLSearchParams(objectToSearchParams(searchParams));
2732
queryParams.set("page", page.toString());
2833

src/components/SearchField.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { InputHTMLAttributes, forwardRef, useEffect, useMemo, useState } from "r
66
import { useNavigate, useSearchParams } from "react-router-dom";
77

88
type Props = {
9+
inMemoryHandler?: (val: string) => void;
910
searchContains?: boolean;
1011
// eslint-disable-next-line @typescript-eslint/no-explicit-any
1112
searchParams: Record<string, any>;
@@ -14,7 +15,7 @@ type Props = {
1415
export const SearchField = forwardRef<
1516
HTMLInputElement,
1617
InputHTMLAttributes<HTMLInputElement> & Props
17-
>(({ searchParams, searchContains = true, ...rest }, ref) => {
18+
>(({ searchParams, searchContains = true, inMemoryHandler, ...rest }, ref) => {
1819
const navigate = useNavigate();
1920
const [existingParams] = useSearchParams();
2021

@@ -35,6 +36,10 @@ export const SearchField = forwardRef<
3536
}, [debouncedSearch]);
3637

3738
function updateSearchQuery(value: string) {
39+
if (!!inMemoryHandler) {
40+
inMemoryHandler(value);
41+
return;
42+
}
3843
const queryParams = new URLSearchParams({
3944
...Object.fromEntries(existingParams),
4045
...objectToSearchParams(searchParams)

0 commit comments

Comments
 (0)