Skip to content

Commit 5508a75

Browse files
llam36shaply
authored andcommitted
Files page (#65)
* feat: add and delete file config * fix: use projectId to delete * fix: add create config toast error * feat: init file page * feat: add lib methods * fix: make configId num * feat: create bucket table * fix: format * feat: provider dropdown * fix: sizing * feat: add provider table * feat: allow edit provider * fix: format * feat: add password boxes * fix: lint * fix: build error * fix: format
1 parent c215a55 commit 5508a75

19 files changed

Lines changed: 1558 additions & 37 deletions

File tree

‎bun.lock‎

Lines changed: 20 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
"@radix-ui/react-popover": "^1.1.6",
2222
"@radix-ui/react-select": "^2.1.6",
2323
"@radix-ui/react-separator": "^1.1.2",
24-
"@radix-ui/react-slot": "^1.1.2",
24+
"@radix-ui/react-slot": "^1.2.4",
2525
"@radix-ui/react-toast": "^1.2.6",
2626
"@radix-ui/react-tooltip": "^1.1.8",
2727
"@tanstack/react-query": "^5.90.5",

‎src/app/(dashboard)/projects/[projectId]/services/files/page.tsx‎

Lines changed: 109 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,114 @@
1+
"use client";
2+
3+
import { FileBucketTable } from "@/components/fileBucketTable/fileBucketTable";
4+
import { FileProviderTable } from "@/components/fileProviderTable/fileProviderTable";
5+
import {
6+
Breadcrumb,
7+
BreadcrumbItem,
8+
BreadcrumbLink,
9+
BreadcrumbList,
10+
BreadcrumbPage,
11+
BreadcrumbSeparator,
12+
} from "@/components/ui/breadcrumb";
13+
import { Skeleton } from "@/components/ui/skeleton";
14+
import { getProjectById } from "@/lib/project";
15+
import { getFileConfig } from "@/lib/settings";
16+
import { useQuery } from "@tanstack/react-query";
17+
import { ProjectResponse } from "juno-sdk/build/main/internal/api";
18+
import { useParams } from "next/navigation";
19+
import { useEffect } from "react";
20+
import { toast } from "sonner";
21+
22+
interface ProjectId {
23+
low: number;
24+
}
25+
126
const FileServicePage = () => {
27+
const { projectId } = useParams<{ projectId: string }>();
28+
29+
const {
30+
isLoading: isProjectLoading,
31+
isError: isProjectError,
32+
data: project,
33+
error: projectError,
34+
} = useQuery<ProjectResponse>({
35+
queryKey: ["project", projectId],
36+
queryFn: async () => {
37+
const result = await getProjectById(Number(projectId));
38+
if (!result.success) {
39+
throw new Error(result.error);
40+
}
41+
return result.project;
42+
},
43+
});
44+
45+
const {
46+
isLoading: isConfigLoading,
47+
isError: isConfigError,
48+
data: config,
49+
error: configError,
50+
} = useQuery({
51+
queryKey: ["fileConfig", projectId],
52+
queryFn: async () => await getFileConfig(projectId),
53+
});
54+
55+
const configId = config?.id
56+
? (config.id as unknown as ProjectId).low
57+
: undefined;
58+
59+
useEffect(() => {
60+
if (isProjectError) {
61+
toast.error("Error", {
62+
description: `Failed to fetch project: ${JSON.stringify(projectError)}`,
63+
});
64+
}
65+
66+
if (isConfigError) {
67+
toast.error("Error", {
68+
description: `Failed to fetch file config: ${JSON.stringify(configError)}`,
69+
});
70+
}
71+
}, [isProjectError, isConfigError, projectError, configError]);
72+
73+
const isLoading = isProjectLoading || isConfigLoading;
74+
275
return (
3-
<div className="p-6">
4-
TO BE FINISHED BY END OF SPRINT 5. This will have a place for you to
5-
register file providers and buckets for your file system.
6-
</div>
76+
<>
77+
{isLoading ? (
78+
<div className="flex flex-col gap-2">
79+
<Skeleton className="mx-10 my-10 h-4 w-60 rounded-xl" />
80+
<Skeleton className="mx-10 mb-2 h-4 w-60 rounded-xl" />
81+
<Skeleton className="mx-10 mb-8 h-20 w-[450px] rounded-xl" />
82+
<Skeleton className="mx-10 mb-2 h-4 w-60 rounded-xl" />
83+
<Skeleton className="mx-10 mb-8 h-20 w-[450px] rounded-xl" />
84+
</div>
85+
) : (
86+
<div className="container mx-auto px-10 py-10 md:w-[85vw] sm:w-full">
87+
<Breadcrumb className="mb-4">
88+
<BreadcrumbList>
89+
<BreadcrumbItem>
90+
<BreadcrumbLink href="/projects">Projects</BreadcrumbLink>
91+
</BreadcrumbItem>
92+
<BreadcrumbSeparator />
93+
<BreadcrumbItem>
94+
<BreadcrumbLink href={`/projects/${projectId}`}>
95+
{project?.name ?? "Unknown"}
96+
</BreadcrumbLink>
97+
</BreadcrumbItem>
98+
<BreadcrumbSeparator />
99+
<BreadcrumbItem>
100+
<BreadcrumbPage>Files</BreadcrumbPage>
101+
</BreadcrumbItem>
102+
</BreadcrumbList>
103+
</Breadcrumb>
104+
105+
<div className="flex flex-col gap-8">
106+
<FileProviderTable projectId={projectId} />
107+
<FileBucketTable projectId={projectId} configId={configId} />
108+
</div>
109+
</div>
110+
)}
111+
</>
7112
);
8113
};
9114

‎src/components/baseTable.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ export function BaseTable<TData, TValue>({
9595
table.resetRowSelection();
9696
}}
9797
>
98-
Delete {selectedRows.length} selected config
98+
Delete {selectedRows.length} selected item
9999
{selectedRows.length > 1 ? "s" : ""}
100100
</Button>
101101
)}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
"use client";
2+
3+
import { Checkbox } from "@/components/ui/checkbox";
4+
import { ColumnDef } from "@tanstack/react-table";
5+
import { ItemListCell } from "../item-list-cell";
6+
7+
export type FileBucketColumn = {
8+
name: string;
9+
configId: number;
10+
configEnv: string;
11+
providerName: string;
12+
fileNames: string[];
13+
};
14+
15+
export const columns: ColumnDef<FileBucketColumn>[] = [
16+
{
17+
id: "select",
18+
header: ({ table }) => (
19+
<Checkbox
20+
className="ms-2 align-middle mr-5"
21+
checked={table.getIsAllPageRowsSelected()}
22+
onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}
23+
/>
24+
),
25+
cell: ({ row }) => (
26+
<Checkbox
27+
className="ms-2 align-middle"
28+
checked={row.getIsSelected()}
29+
onCheckedChange={(value) => row.toggleSelected(!!value)}
30+
/>
31+
),
32+
size: 50,
33+
},
34+
{
35+
accessorKey: "name",
36+
header: "Bucket Name",
37+
},
38+
{
39+
accessorKey: "configId",
40+
header: "Config ID",
41+
},
42+
{
43+
accessorKey: "configEnv",
44+
header: "Config Env",
45+
},
46+
{
47+
accessorKey: "providerName",
48+
header: "Provider Name",
49+
},
50+
{
51+
accessorKey: "fileNames",
52+
header: "Files",
53+
cell: ({ row }) => (
54+
<ItemListCell
55+
itemNames={row.original.fileNames}
56+
badgeVariant="secondary"
57+
/>
58+
),
59+
},
60+
];

0 commit comments

Comments
 (0)