From 17398fc9325781fa659d01f2401835e44cbf2929 Mon Sep 17 00:00:00 2001 From: mbecker20 Date: Thu, 18 Apr 2024 03:17:57 -0700 Subject: [PATCH] fix tags filter --- frontend/src/components/alert/details.tsx | 43 +++++++++++++++---- frontend/src/components/alert/table.tsx | 5 --- .../components/resources/alerter/index.tsx | 15 ++++--- .../src/components/resources/build/table.tsx | 15 ++++--- .../components/resources/builder/index.tsx | 14 +++--- .../components/resources/deployment/table.tsx | 15 ++++--- .../components/resources/procedure/table.tsx | 15 ++++--- .../src/components/resources/repo/index.tsx | 15 ++++--- .../src/components/resources/server/table.tsx | 15 ++++--- frontend/src/components/tags/index.tsx | 14 ++---- frontend/src/lib/color.ts | 10 ++--- frontend/src/lib/hooks.ts | 11 ++++- frontend/src/pages/home/all_resources.tsx | 18 ++++++-- frontend/src/pages/home/dashboard.tsx | 12 +++--- frontend/src/pages/home/tree.tsx | 4 +- frontend/src/pages/resources.tsx | 35 ++------------- 16 files changed, 136 insertions(+), 120 deletions(-) diff --git a/frontend/src/components/alert/details.tsx b/frontend/src/components/alert/details.tsx index 3b9f5d8a7..15306c803 100644 --- a/frontend/src/components/alert/details.tsx +++ b/frontend/src/components/alert/details.tsx @@ -6,6 +6,11 @@ import { Dialog, DialogContent, DialogHeader, DialogTrigger } from "@ui/dialog"; import { useState } from "react"; import { AlertLevel } from "."; import { fmt_date_with_minutes } from "@lib/formatting"; +import { DialogDescription } from "@radix-ui/react-dialog"; +import { + alert_level_intention, + text_color_class_by_intention, +} from "@lib/color"; export const AlertDetailsDialog = ({ id }: { id: string }) => { const [open, set] = useState(false); @@ -23,20 +28,42 @@ export const AlertDetailsDialog = ({ id }: { id: string }) => { {alert && ( <> -
- - -
+
{fmt_date_with_minutes(new Date(alert.ts))}
)}
-
{JSON.stringify(alert.data, undefined, 2)}
+ +
+
+
+
status:
{" "} +
+ {alert.resolved ? "RESOLVED" : "OPEN"} +
+
+
+
type:
{" "} + {alert.data.type} +
+
+ level: +
+
+
{JSON.stringify(alert.data.data, undefined, 2)}
+
+
)} diff --git a/frontend/src/components/alert/table.tsx b/frontend/src/components/alert/table.tsx index 1ce5949a1..228e6e4e6 100644 --- a/frontend/src/components/alert/table.tsx +++ b/frontend/src/components/alert/table.tsx @@ -1,4 +1,3 @@ -import { fmt_date_with_minutes } from "@lib/formatting"; import { Types } from "@monitor/client"; import { DataTable } from "@ui/data-table"; import { AlertLevel } from "."; @@ -33,10 +32,6 @@ export const AlertsTable = ({ alerts }: { alerts: Types.Alert[] }) => { header: "Alert Type", accessorKey: "variant", }, - { - header: "Opened", - accessorFn: ({ ts }) => fmt_date_with_minutes(new Date(ts)), - }, ]} /> ); diff --git a/frontend/src/components/resources/alerter/index.tsx b/frontend/src/components/resources/alerter/index.tsx index 773282b37..35dd30c64 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, useWrite } from "@lib/hooks"; +import { useRead, useTagsFilter, useWrite } from "@lib/hooks"; import { Types } from "@monitor/client"; import { Select, @@ -17,7 +17,7 @@ import { DataTable } from "@ui/data-table"; import { Link } from "react-router-dom"; import { Card, CardDescription, CardHeader, CardTitle } from "@ui/card"; import { AlerterConfig } from "./config"; -import { TagsWithBadge, useTagsFilter } from "@components/tags"; +import { TagsWithBadge } from "@components/tags"; import { DeleteResource, ResourceLink } from "../common"; const useAlerter = (id?: string) => @@ -92,11 +92,12 @@ export const AlerterComponents: RequiredResourceComponents = { return ( - tags.every((tag) => resource.tags.includes(tag)) && - searchSplit.length > 0 - ? searchSplit.every((search) => resource.name.includes(search)) - : true + alerters?.filter( + (resource) => + tags.every((tag) => resource.tags.includes(tag)) && + (searchSplit.length > 0 + ? searchSplit.every((search) => resource.name.includes(search)) + : true) ) ?? [] } columns={[ diff --git a/frontend/src/components/resources/build/table.tsx b/frontend/src/components/resources/build/table.tsx index ba784fe23..55e73c22f 100644 --- a/frontend/src/components/resources/build/table.tsx +++ b/frontend/src/components/resources/build/table.tsx @@ -1,5 +1,5 @@ -import { TagsWithBadge, useTagsFilter } from "@components/tags"; -import { useRead } from "@lib/hooks"; +import { TagsWithBadge } from "@components/tags"; +import { useRead, useTagsFilter } from "@lib/hooks"; import { DataTable } from "@ui/data-table"; import { fmt_date_with_minutes, fmt_version } from "@lib/formatting"; import { ResourceLink } from "../common"; @@ -11,11 +11,12 @@ export const BuildTable = ({ search }: { search?: string }) => { return ( - tags.every((tag) => resource.tags.includes(tag)) && - searchSplit.length > 0 - ? searchSplit.every((search) => resource.name.includes(search)) - : true + builds?.filter( + (resource) => + tags.every((tag) => resource.tags.includes(tag)) && + (searchSplit.length > 0 + ? searchSplit.every((search) => resource.name.includes(search)) + : true) ) ?? [] } columns={[ diff --git a/frontend/src/components/resources/builder/index.tsx b/frontend/src/components/resources/builder/index.tsx index 444cedf33..affc1d2c4 100644 --- a/frontend/src/components/resources/builder/index.tsx +++ b/frontend/src/components/resources/builder/index.tsx @@ -1,6 +1,5 @@ import { NewLayout } from "@components/layouts"; -import { useTagsFilter } from "@components/tags"; -import { useRead, useWrite } from "@lib/hooks"; +import { useRead, useTagsFilter, useWrite } from "@lib/hooks"; import { Types } from "@monitor/client"; import { RequiredResourceComponents } from "@types"; import { Card, CardDescription, CardHeader, CardTitle } from "@ui/card"; @@ -92,11 +91,12 @@ export const BuilderComponents: RequiredResourceComponents = { return ( - tags.every((tag) => resource.tags.includes(tag)) && - searchSplit.length > 0 - ? searchSplit.every((search) => resource.name.includes(search)) - : true + builders?.filter( + (resource) => + tags.every((tag) => resource.tags.includes(tag)) && + (searchSplit.length > 0 + ? searchSplit.every((search) => resource.name.includes(search)) + : true) ) ?? [] } columns={[ diff --git a/frontend/src/components/resources/deployment/table.tsx b/frontend/src/components/resources/deployment/table.tsx index d040c3253..a4aaedb83 100644 --- a/frontend/src/components/resources/deployment/table.tsx +++ b/frontend/src/components/resources/deployment/table.tsx @@ -1,7 +1,7 @@ -import { TagsWithBadge, useTagsFilter } from "@components/tags"; +import { TagsWithBadge } from "@components/tags"; import { Types } from "@monitor/client"; import { DataTable } from "@ui/data-table"; -import { useRead } from "@lib/hooks"; +import { useRead, useTagsFilter } from "@lib/hooks"; import { ResourceLink } from "../common"; import { DeploymentComponents } from "."; @@ -17,11 +17,12 @@ export const DeploymentTable = ({ return ( - tags.every((tag) => resource.tags.includes(tag)) && - searchSplit.length > 0 - ? searchSplit.every((search) => resource.name.includes(search)) - : true + deployments?.filter( + (resource) => + tags.every((tag) => resource.tags.includes(tag)) && + (searchSplit.length > 0 + ? searchSplit.every((search) => resource.name.includes(search)) + : true) ) ?? [] } columns={[ diff --git a/frontend/src/components/resources/procedure/table.tsx b/frontend/src/components/resources/procedure/table.tsx index 21b35b1ae..7d6e4e141 100644 --- a/frontend/src/components/resources/procedure/table.tsx +++ b/frontend/src/components/resources/procedure/table.tsx @@ -1,6 +1,6 @@ -import { useRead } from "@lib/hooks"; +import { useRead, useTagsFilter } from "@lib/hooks"; import { DataTable } from "@ui/data-table"; -import { TagsWithBadge, useTagsFilter } from "@components/tags"; +import { TagsWithBadge } from "@components/tags"; import { ResourceLink } from "../common"; export const ProcedureTable = ({ search }: { search?: string }) => { @@ -10,11 +10,12 @@ export const ProcedureTable = ({ search }: { search?: string }) => { return ( - tags.every((tag) => resource.tags.includes(tag)) && - searchSplit.length > 0 - ? searchSplit.every((search) => resource.name.includes(search)) - : true + procedures?.filter( + (resource) => + tags.every((tag) => resource.tags.includes(tag)) && + (searchSplit.length > 0 + ? searchSplit.every((search) => resource.name.includes(search)) + : true) ) ?? [] } columns={[ diff --git a/frontend/src/components/resources/repo/index.tsx b/frontend/src/components/resources/repo/index.tsx index f5078d270..989ef1983 100644 --- a/frontend/src/components/resources/repo/index.tsx +++ b/frontend/src/components/resources/repo/index.tsx @@ -1,5 +1,5 @@ -import { TagsWithBadge, useTagsFilter } from "@components/tags"; -import { useRead } from "@lib/hooks"; +import { TagsWithBadge } from "@components/tags"; +import { useRead, useTagsFilter } from "@lib/hooks"; import { RequiredResourceComponents } from "@types"; import { Card, CardDescription, CardHeader, CardTitle } from "@ui/card"; import { DataTable } from "@ui/data-table"; @@ -41,11 +41,12 @@ export const RepoComponents: RequiredResourceComponents = { return ( - tags.every((tag) => resource.tags.includes(tag)) && - searchSplit.length > 0 - ? searchSplit.every((search) => resource.name.includes(search)) - : true + repos?.filter( + (resource) => + tags.every((tag) => resource.tags.includes(tag)) && + (searchSplit.length > 0 + ? searchSplit.every((search) => resource.name.includes(search)) + : true) ) ?? [] } columns={[ diff --git a/frontend/src/components/resources/server/table.tsx b/frontend/src/components/resources/server/table.tsx index 28a91c6f9..c1607b6dc 100644 --- a/frontend/src/components/resources/server/table.tsx +++ b/frontend/src/components/resources/server/table.tsx @@ -1,5 +1,5 @@ -import { TagsWithBadge, useTagsFilter } from "@components/tags"; -import { useRead } from "@lib/hooks"; +import { TagsWithBadge } from "@components/tags"; +import { useRead, useTagsFilter } from "@lib/hooks"; import { DataTable } from "@ui/data-table"; import { ServerComponents } from "."; import { ResourceLink } from "../common"; @@ -11,11 +11,12 @@ export const ServerTable = ({ search }: { search?: string }) => { return ( - tags.every((tag) => resource.tags.includes(tag)) && - searchSplit.length > 0 - ? searchSplit.every((search) => resource.name.includes(search)) - : true + servers?.filter( + (resource) => + tags.every((tag) => resource.tags.includes(tag)) && + (searchSplit.length > 0 + ? searchSplit.every((search) => resource.name.includes(search)) + : true) ) ?? [] } columns={[ diff --git a/frontend/src/components/tags/index.tsx b/frontend/src/components/tags/index.tsx index b47e0ef9c..1632fa9f1 100644 --- a/frontend/src/components/tags/index.tsx +++ b/frontend/src/components/tags/index.tsx @@ -1,4 +1,4 @@ -import { useInvalidate, useRead, useWrite } from "@lib/hooks"; +import { tagsAtom, useInvalidate, useRead, useWrite } from "@lib/hooks"; import { cn } from "@lib/utils"; import { Types } from "@monitor/client"; import { Badge } from "@ui/badge"; @@ -14,19 +14,11 @@ import { import { Popover, PopoverContent, PopoverTrigger } from "@ui/popover"; import { useToast } from "@ui/use-toast"; import { useAtom } from "jotai"; -import { atomWithStorage } from "jotai/utils"; import { MinusCircle, PlusCircle, SearchX, Tag } from "lucide-react"; import { ReactNode, useEffect, useState } from "react"; type TargetExcludingSystem = Exclude; -const tagsAtom = atomWithStorage("tags-v0", []); - -export const useTagsFilter = () => { - const [tags] = useAtom(tagsAtom); - return tags; -}; - export const TagsFilter = () => { const [open, setOpen] = useState(false); const [search, setSearch] = useState(""); @@ -104,7 +96,7 @@ export const TagsFilterTags = ({ {tag_ids?.map((tag_id) => ( onBadgeClick && onBadgeClick(tag_id)} > @@ -125,12 +117,14 @@ export const ResourceTags = ({ click_to_delete?: boolean; className?: string; }) => { + const { toast } = useToast(); const inv = useInvalidate(); const { type, id } = target; const resource = useRead(`List${type}s`, {}).data?.find((d) => d.id === id); const { mutate } = useWrite("UpdateTagsOnResource", { onSuccess: () => { inv([`List${type}s`]); + toast({ title: "Removed tag" }); }, }); diff --git a/frontend/src/lib/color.ts b/frontend/src/lib/color.ts index 5fe706cfe..c49bdfabb 100644 --- a/frontend/src/lib/color.ts +++ b/frontend/src/lib/color.ts @@ -55,15 +55,15 @@ export const stroke_color_class_by_intention = (intention: ColorIntention) => { export const bg_color_class_by_intention = (intention: ColorIntention) => { switch (intention) { case "Good": - return "bg-green-500"; + return "bg-green-400 dark:bg-green-700"; case "Neutral": - return "bg-blue-500"; + return "bg-blue-400 dark:bg-blue-700"; case "Warning": - return "bg-orange-500"; + return "bg-orange-400 dark:bg-orange-700"; case "Critical": - return "bg-red-500"; + return "bg-red-400 dark:bg-red-700"; case "Unknown": - return "bg-purple-500"; + return "bg-purple-400 dark:bg-purple-700"; case "None": return ""; } diff --git a/frontend/src/lib/hooks.ts b/frontend/src/lib/hooks.ts index 5163289cb..a39bebc4d 100644 --- a/frontend/src/lib/hooks.ts +++ b/frontend/src/lib/hooks.ts @@ -15,6 +15,8 @@ import { } from "@tanstack/react-query"; import { UsableResource } from "@types"; import { useToast } from "@ui/use-toast"; +import { useAtom } from "jotai"; +import { atomWithStorage } from "jotai/utils"; import { useEffect } from "react"; import { useParams } from "react-router-dom"; @@ -174,4 +176,11 @@ export const useSetTitle = (more?: string) => { document.title = title; } }, [title]); -} \ No newline at end of file +} + +export const tagsAtom = atomWithStorage("tags-v0", []); + +export const useTagsFilter = () => { + const [tags] = useAtom(tagsAtom); + return tags; +}; \ No newline at end of file diff --git a/frontend/src/pages/home/all_resources.tsx b/frontend/src/pages/home/all_resources.tsx index c83036adf..3de7869d8 100644 --- a/frontend/src/pages/home/all_resources.tsx +++ b/frontend/src/pages/home/all_resources.tsx @@ -1,8 +1,8 @@ import { OpenAlerts } from "@components/alert"; import { Page, Section } from "@components/layouts"; import { ResourceComponents } from "@components/resources"; -import { TagsFilter, useTagsFilter } from "@components/tags"; -import { useRead } from "@lib/hooks"; +import { TagsFilter } from "@components/tags"; +import { useRead, useTagsFilter } from "@lib/hooks"; import { RequiredResourceComponents, UsableResource } from "@types"; import { Input } from "@ui/input"; import { useState } from "react"; @@ -28,7 +28,12 @@ export const AllResources = () => { > {Object.entries(ResourceComponents).map(([type, Components]) => ( - + ))} ); @@ -44,8 +49,13 @@ const TableSection = ({ search?: string; }) => { const tags = useTagsFilter(); + const searchSplit = search?.split(" ") || []; const count = useRead(`List${type as UsableResource}s`, {}).data?.filter( - (resource) => tags.every((tag) => resource.tags.includes(tag)) + (resource) => + tags.every((tag) => resource.tags.includes(tag)) && + (searchSplit.length > 0 + ? searchSplit.every((search) => resource.name.includes(search)) + : true) ).length; if (!count) return; diff --git a/frontend/src/pages/home/dashboard.tsx b/frontend/src/pages/home/dashboard.tsx index a1fde9a4b..207e4682e 100644 --- a/frontend/src/pages/home/dashboard.tsx +++ b/frontend/src/pages/home/dashboard.tsx @@ -8,6 +8,7 @@ import { ResourceComponents } from "@components/resources"; import { OpenAlerts } from "@components/alert"; import { useUser } from "@lib/hooks"; import { ResourceLink } from "@components/resources/common"; +import { Fragment } from "react"; export const Dashboard = () => { return ( @@ -59,9 +60,9 @@ const RecentlyViewed = () => { actions="" >
- {recently_viewed?.slice(0, 6).map( - ({ type, id }) => - type !== "System" && ( + {recently_viewed?.slice(0, 6).map(({ type, id }) => ( + + {type !== "System" && ( nav(`/${type.toLowerCase()}s/${id}`)} className="px-3 py-2 h-fit hover:bg-accent/50 group-focus:bg-accent/50 transition-colors cursor-pointer" @@ -71,8 +72,9 @@ const RecentlyViewed = () => { {type} - ) - )} + )} + + ))}
); diff --git a/frontend/src/pages/home/tree.tsx b/frontend/src/pages/home/tree.tsx index 7b0f2bbd7..a84fecc26 100644 --- a/frontend/src/pages/home/tree.tsx +++ b/frontend/src/pages/home/tree.tsx @@ -3,8 +3,8 @@ import { Page, Section } from "@components/layouts"; import { ResourceComponents } from "@components/resources"; import { DeploymentTable } from "@components/resources/deployment/table"; import { ServerComponents } from "@components/resources/server"; -import { TagsFilter, TagsWithBadge, useTagsFilter } from "@components/tags"; -import { useRead } from "@lib/hooks"; +import { TagsFilter, TagsWithBadge } from "@components/tags"; +import { useRead, useTagsFilter } from "@lib/hooks"; import { Button } from "@ui/button"; import { Card, CardHeader, CardTitle } from "@ui/card"; import { Fragment, useState } from "react"; diff --git a/frontend/src/pages/resources.tsx b/frontend/src/pages/resources.tsx index 1fc8e9c81..061f7f04e 100644 --- a/frontend/src/pages/resources.tsx +++ b/frontend/src/pages/resources.tsx @@ -1,26 +1,15 @@ -import { Page, Section, ResourceCard } from "@components/layouts"; +import { Page, Section } from "@components/layouts"; import { ResourceComponents } from "@components/resources"; -import { TagsFilter, useTagsFilter } from "@components/tags"; -import { useRead, useResourceParamType, useSetTitle } from "@lib/hooks"; -import { Button } from "@ui/button"; +import { TagsFilter } from "@components/tags"; +import { useResourceParamType, useSetTitle } from "@lib/hooks"; import { Input } from "@ui/input"; import { useState } from "react"; -import { atomWithStorage } from "jotai/utils"; -import { useAtom } from "jotai"; - -const viewAtom = atomWithStorage<"cards" | "table">("list-show-as-v0", "table"); export const Resources = () => { const type = useResourceParamType()!; useSetTitle(type + "s"); const Components = ResourceComponents[type]; - - const tags = useTagsFilter(); - - const list = useRead(`List${type}s`, { query: { tags } }).data; - const [search, set] = useState(""); - const [view, setView] = useAtom(viewAtom); return ( { actions={
- set(e.target.value)} @@ -49,15 +30,7 @@ export const Resources = () => { } >
- {view === "cards" ? ( -
- {list?.map(({ id }) => ( - - ))} -
- ) : ( - - )} +
);