From cb9e0ae252bdf609a82e665b1e0799e4bb79fae4 Mon Sep 17 00:00:00 2001 From: mbecker20 Date: Sun, 21 Apr 2024 00:18:47 -0700 Subject: [PATCH] sortable resource table --- .../components/resources/alerter/index.tsx | 52 ++--------------- .../components/resources/alerter/table.tsx | 51 +++++++++++++++++ .../src/components/resources/build/table.tsx | 13 +++-- .../components/resources/builder/index.tsx | 46 ++------------- .../components/resources/builder/table.tsx | 57 +++++++++++++++++++ .../components/resources/procedure/table.tsx | 4 +- .../src/components/resources/repo/index.tsx | 56 ++---------------- .../src/components/resources/repo/table.tsx | 55 ++++++++++++++++++ .../src/components/resources/server/table.tsx | 30 ++++++++-- 9 files changed, 210 insertions(+), 154 deletions(-) create mode 100644 frontend/src/components/resources/alerter/table.tsx create mode 100644 frontend/src/components/resources/builder/table.tsx create mode 100644 frontend/src/components/resources/repo/table.tsx diff --git a/frontend/src/components/resources/alerter/index.tsx b/frontend/src/components/resources/alerter/index.tsx index 018ecb6fc..33cd88dc7 100644 --- a/frontend/src/components/resources/alerter/index.tsx +++ b/frontend/src/components/resources/alerter/index.tsx @@ -1,5 +1,5 @@ import { NewLayout } from "@components/layouts"; -import { useRead, useTagsFilter, useWrite } from "@lib/hooks"; +import { useRead, useWrite } from "@lib/hooks"; import { Types } from "@monitor/client"; import { Select, @@ -13,12 +13,11 @@ import { RequiredResourceComponents } from "@types"; import { Input } from "@ui/input"; import { AlarmClock } from "lucide-react"; import { useState } from "react"; -import { DataTable, SortableHeader } from "@ui/data-table"; import { Link } from "react-router-dom"; import { Card, CardDescription, CardHeader, CardTitle } from "@ui/card"; import { AlerterConfig } from "./config"; -import { TagsWithBadge } from "@components/tags"; -import { DeleteResource, ResourceLink } from "../common"; +import { DeleteResource } from "../common"; +import { AlerterTable } from "./table"; const useAlerter = (id?: string) => useRead("ListAlerters", {}).data?.find((d) => d.id === id); @@ -85,50 +84,7 @@ export const AlerterComponents: RequiredResourceComponents = { ); }, - Table: ({ search }) => { - const tags = useTagsFilter(); - const alerters = useRead("ListAlerters", {}).data; - const searchSplit = search?.split(" ") || []; - return ( - - tags.every((tag) => resource.tags.includes(tag)) && - (searchSplit.length > 0 - ? searchSplit.every((search) => resource.name.includes(search)) - : true) - ) ?? [] - } - columns={[ - { - accessorKey: "name", - header: ({ column }) => ( - - ), - cell: ({ row }) => ( - - ), - }, - { - header: "Type", - accessorKey: "info.alerter_type", - }, - { - header: "Tags", - cell: ({ row }) => { - return ( -
- -
- ); - }, - }, - ]} - /> - ); - }, + Table: AlerterTable, Name: ({ id }: { id: string }) => <>{useAlerter(id)?.name}, name: (id) => useAlerter(id)?.name, diff --git a/frontend/src/components/resources/alerter/table.tsx b/frontend/src/components/resources/alerter/table.tsx new file mode 100644 index 000000000..482f494de --- /dev/null +++ b/frontend/src/components/resources/alerter/table.tsx @@ -0,0 +1,51 @@ +import { useRead, useTagsFilter } from "@lib/hooks"; +import { DataTable, SortableHeader } from "@ui/data-table"; +import { ResourceLink } from "../common"; +import { TagsWithBadge } from "@components/tags"; + +export const AlerterTable = ({ search }: { search?: string }) => { + const tags = useTagsFilter(); + const alerters = useRead("ListAlerters", {}).data; + const searchSplit = search?.split(" ") || []; + return ( + + tags.every((tag) => resource.tags.includes(tag)) && + (searchSplit.length > 0 + ? searchSplit.every((search) => resource.name.includes(search)) + : true) + ) ?? [] + } + columns={[ + { + accessorKey: "name", + header: ({ column }) => ( + + ), + cell: ({ row }) => ( + + ), + }, + { + accessorKey: "info.alerter_type", + header: ({ column }) => ( + + ), + }, + { + header: "Tags", + cell: ({ row }) => { + return ( +
+ +
+ ); + }, + }, + ]} + /> + ); +}; diff --git a/frontend/src/components/resources/build/table.tsx b/frontend/src/components/resources/build/table.tsx index 5187297f3..610d75293 100644 --- a/frontend/src/components/resources/build/table.tsx +++ b/frontend/src/components/resources/build/table.tsx @@ -26,20 +26,23 @@ export const BuildTable = ({ search }: { search?: string }) => { header: ({ column }) => ( ), - cell: ({ row }) => ( - - ), + cell: ({ row }) => , }, { header: "Version", accessorFn: ({ info }) => fmt_version(info.version), }, { - header: "Repo", accessorKey: "info.repo", + header: ({ column }) => ( + + ), }, { - header: "Last Built", + accessorKey: "info.last_built_at", + header: ({ column }) => ( + + ), accessorFn: ({ info: { last_built_at } }) => { if (last_built_at > 0) { return fmt_date_with_minutes(new Date(last_built_at)); diff --git a/frontend/src/components/resources/builder/index.tsx b/frontend/src/components/resources/builder/index.tsx index 18c12f8ef..631693bf3 100644 --- a/frontend/src/components/resources/builder/index.tsx +++ b/frontend/src/components/resources/builder/index.tsx @@ -1,9 +1,8 @@ import { NewLayout } from "@components/layouts"; -import { useRead, useTagsFilter, useWrite } from "@lib/hooks"; +import { useRead, useWrite } from "@lib/hooks"; import { Types } from "@monitor/client"; import { RequiredResourceComponents } from "@types"; import { Card, CardDescription, CardHeader, CardTitle } from "@ui/card"; -import { DataTable, SortableHeader } from "@ui/data-table"; import { Input } from "@ui/input"; import { Select, @@ -17,7 +16,8 @@ import { Cloud, Bot, Factory } from "lucide-react"; import { useState } from "react"; import { Link } from "react-router-dom"; import { BuilderConfig } from "./config"; -import { DeleteResource, ResourceLink } from "../common"; +import { DeleteResource } from "../common"; +import { BuidlerTable } from "./table"; const useBuilder = (id?: string) => useRead("ListBuilders", {}).data?.find((d) => d.id === id); @@ -84,45 +84,7 @@ export const BuilderComponents: RequiredResourceComponents = { ); }, - Table: ({ search }) => { - const tags = useTagsFilter(); - const builders = useRead("ListBuilders", {}).data; - const searchSplit = search?.split(" ") || []; - return ( - - tags.every((tag) => resource.tags.includes(tag)) && - (searchSplit.length > 0 - ? searchSplit.every((search) => resource.name.includes(search)) - : true) - ) ?? [] - } - columns={[ - { - accessorKey: "name", - header: ({ column }) => ( - - ), - cell: ({ row }) => ( - - ), - }, - { - header: "Provider", - accessorKey: "info.provider", - }, - { - header: "Instance Type", - accessorKey: "info.instance_type", - }, - { header: "Tags", accessorFn: ({ tags }) => tags.join(", ") }, - ]} - /> - ); - }, + Table: BuidlerTable, Name: ({ id }: { id: string }) => <>{useBuilder(id)?.name}, name: (id) => useBuilder(id)?.name, diff --git a/frontend/src/components/resources/builder/table.tsx b/frontend/src/components/resources/builder/table.tsx new file mode 100644 index 000000000..b3b2f9cd3 --- /dev/null +++ b/frontend/src/components/resources/builder/table.tsx @@ -0,0 +1,57 @@ +import { useRead, useTagsFilter } from "@lib/hooks"; +import { DataTable, SortableHeader } from "@ui/data-table"; +import { ResourceLink } from "../common"; +import { TagsWithBadge } from "@components/tags"; + +export const BuidlerTable = ({ search }: { search?: string }) => { + const tags = useTagsFilter(); + const builders = useRead("ListBuilders", {}).data; + const searchSplit = search?.split(" ") || []; + return ( + + tags.every((tag) => resource.tags.includes(tag)) && + (searchSplit.length > 0 + ? searchSplit.every((search) => resource.name.includes(search)) + : true) + ) ?? [] + } + columns={[ + { + accessorKey: "name", + header: ({ column }) => ( + + ), + cell: ({ row }) => ( + + ), + }, + { + accessorKey: "info.provider", + header: ({ column }) => ( + + ), + }, + { + accessorKey: "info.instance_type", + header: ({ column }) => ( + + ), + }, + { + header: "Tags", + cell: ({ row }) => { + return ( +
+ +
+ ); + }, + }, + ]} + /> + ); +}; diff --git a/frontend/src/components/resources/procedure/table.tsx b/frontend/src/components/resources/procedure/table.tsx index cfaa36c2e..089f0c17b 100644 --- a/frontend/src/components/resources/procedure/table.tsx +++ b/frontend/src/components/resources/procedure/table.tsx @@ -30,8 +30,10 @@ export const ProcedureTable = ({ search }: { search?: string }) => { ), }, { - header: "Type", accessorKey: "info.procedure_type", + header: ({ column }) => ( + + ), }, { header: "Tags", diff --git a/frontend/src/components/resources/repo/index.tsx b/frontend/src/components/resources/repo/index.tsx index 081fac91f..647c93afc 100644 --- a/frontend/src/components/resources/repo/index.tsx +++ b/frontend/src/components/resources/repo/index.tsx @@ -1,13 +1,12 @@ -import { TagsWithBadge } from "@components/tags"; -import { useRead, useTagsFilter } from "@lib/hooks"; +import { useRead } from "@lib/hooks"; import { RequiredResourceComponents } from "@types"; import { Card, CardDescription, CardHeader, CardTitle } from "@ui/card"; -import { DataTable, SortableHeader } from "@ui/data-table"; import { FolderGit, GitBranch } from "lucide-react"; import { Link } from "react-router-dom"; import { RepoConfig } from "./config"; import { CloneRepo, PullRepo } from "./actions"; -import { DeleteResource, NewResource, ResourceLink } from "../common"; +import { DeleteResource, NewResource } from "../common"; +import { RepoTable } from "./table"; const useRepo = (id?: string) => useRead("ListRepos", {}).data?.find((d) => d.id === id); @@ -34,54 +33,7 @@ export const RepoComponents: RequiredResourceComponents = { New: () => , - Table: ({ search }) => { - const tags = useTagsFilter(); - const repos = useRead("ListRepos", {}).data; - const searchSplit = search?.split(" ") || []; - return ( - - tags.every((tag) => resource.tags.includes(tag)) && - (searchSplit.length > 0 - ? searchSplit.every((search) => resource.name.includes(search)) - : true) - ) ?? [] - } - columns={[ - { - accessorKey: "name", - header: ({ column }) => ( - - ), - cell: ({ row }) => ( - - ), - }, - { - header: "Repo", - accessorKey: "info.repo", - }, - { - header: "Branch", - accessorKey: "info.branch", - }, - { - header: "Tags", - cell: ({ row }) => { - return ( -
- -
- ); - }, - }, - ]} - /> - ); - }, + Table: RepoTable, Name: ({ id }: { id: string }) => <>{useRepo(id)?.name}, name: (id) => useRepo(id)?.name, diff --git a/frontend/src/components/resources/repo/table.tsx b/frontend/src/components/resources/repo/table.tsx new file mode 100644 index 000000000..545bf3cec --- /dev/null +++ b/frontend/src/components/resources/repo/table.tsx @@ -0,0 +1,55 @@ +import { useRead, useTagsFilter } from "@lib/hooks"; +import { DataTable, SortableHeader } from "@ui/data-table"; +import { ResourceLink } from "../common"; +import { TagsWithBadge } from "@components/tags"; + +export const RepoTable = ({ search }: { search?: string }) => { + const tags = useTagsFilter(); + const repos = useRead("ListRepos", {}).data; + const searchSplit = search?.split(" ") || []; + return ( + + tags.every((tag) => resource.tags.includes(tag)) && + (searchSplit.length > 0 + ? searchSplit.every((search) => resource.name.includes(search)) + : true) + ) ?? [] + } + columns={[ + { + accessorKey: "name", + header: ({ column }) => ( + + ), + cell: ({ row }) => , + }, + { + accessorKey: "info.repo", + header: ({ column }) => ( + + ), + }, + { + accessorKey: "info.branch", + header: ({ column }) => ( + + ), + }, + { + header: "Tags", + cell: ({ row }) => { + return ( +
+ +
+ ); + }, + }, + ]} + /> + ); +}; diff --git a/frontend/src/components/resources/server/table.tsx b/frontend/src/components/resources/server/table.tsx index 28c2ac1d4..674ad1622 100644 --- a/frontend/src/components/resources/server/table.tsx +++ b/frontend/src/components/resources/server/table.tsx @@ -31,7 +31,22 @@ export const ServerTable = ({ search }: { search?: string }) => { ), }, { - header: "Deployments", + accessorKey: "id", + sortingFn: (a, b) => { + const sa = useDeploymentCount(a.original.id); + const sb = useDeploymentCount(b.original.id); + + if (!sa && !sb) return 0; + if (!sa) return -1; + if (!sb) return 1; + + if (sa > sb) return 1; + else if (sa < sb) return -1; + else return 0; + }, + header: ({ column }) => ( + + ), cell: ({ row }) => , }, { @@ -69,9 +84,12 @@ export const ServerTable = ({ search }: { search?: string }) => { }; const DeploymentCountOnServer = ({ id }: { id: string }) => { - const { data } = useRead("ListDeployments", { - query: { specific: { server_ids: [id] } }, - }); - - return <>{data?.length ?? 0}; + const count = useDeploymentCount(id); + return <>{count ?? 0}; +}; + +const useDeploymentCount = (id: string) => { + return useRead("ListDeployments", {}).data?.filter( + (d) => d.info.server_id === id + ).length; };