diff --git a/frontend/src/components/layouts.tsx b/frontend/src/components/layouts.tsx index 27843d199..32722433a 100644 --- a/frontend/src/components/layouts.tsx +++ b/frontend/src/components/layouts.tsx @@ -63,17 +63,27 @@ export const Layout = () => { interface PageProps { title?: ReactNode; + titleRight?: ReactNode; children?: ReactNode; subtitle?: ReactNode; actions?: ReactNode; } -export const Page = ({ title, subtitle, actions, children }: PageProps) => ( +export const Page = ({ + title, + titleRight, + subtitle, + actions, + children, +}: PageProps) => (
{(title || subtitle || actions) && (
-

{title}

+
+

{title}

+ {titleRight} +
{subtitle}
{actions} diff --git a/frontend/src/components/tags/index.tsx b/frontend/src/components/tags/index.tsx index 8104472fb..48d8665b9 100644 --- a/frontend/src/components/tags/index.tsx +++ b/frontend/src/components/tags/index.tsx @@ -2,7 +2,6 @@ import { useInvalidate, useRead, useWrite } from "@lib/hooks"; import { Types } from "@monitor/client"; import { Badge } from "@ui/badge"; import { Button } from "@ui/button"; -import { Checkbox } from "@ui/checkbox"; import { Command, CommandEmpty, @@ -20,7 +19,7 @@ import { import { Popover, PopoverContent, PopoverTrigger } from "@ui/popover"; import { useToast } from "@ui/use-toast"; import { atom, useAtom } from "jotai"; -import { Pen, PlusCircle } from "lucide-react"; +import { PlusCircle } from "lucide-react"; import { useEffect, useState } from "react"; type TargetExcludingSystem = Exclude; @@ -68,11 +67,34 @@ export const TagsFilter = () => { ); }; -export const ResourceTags = ({ target }: { target: TargetExcludingSystem }) => { +export const ResourceTags = ({ + target, + click_to_delete, +}: { + target: TargetExcludingSystem; + click_to_delete?: boolean; +}) => { + 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`]); + }, + }); - return ; + return ( + { + if (!click_to_delete) return; + mutate({ + target, + tags: resource!.tags.filter((tag) => tag !== tag_id), + }); + }} + /> + ); }; export const TagsWithBadge = ({ @@ -101,47 +123,48 @@ export const TagsWithBadge = ({ ); }; -export const ManageTags = ({ target }: { target: TargetExcludingSystem }) => { +export const AddTags = ({ target }: { target: TargetExcludingSystem }) => { const { type, id } = target; const resource = useRead(`List${type}s`, {}).data?.find((d) => d.id === id); const [open, setOpen] = useState(false); const [input, setInput] = useState(""); - const [tags, setTags] = useState(resource?.tags); const all_tags = useRead("ListTags", {}).data; const inv = useInvalidate(); + const { mutate: update } = useWrite("UpdateTagsOnResource", { - onSuccess: () => inv([`List${type}s`]), + onSuccess: () => { + inv([`List${type}s`]); + setOpen(false); + }, }); const { mutateAsync: create } = useWrite("CreateTag", { onSuccess: () => inv([`ListTags`]), }); - useEffect(() => { - if (!open && !!resource && !!tags) update({ target, tags }); - }, [target, open, resource, tags, update]); + // useEffect(() => { + // if (!open && !!resource && !!tags) update({ target, tags }); + // }, [target, open, resource, tags, update]); - useEffect(() => { - if (resource && !tags) setTags(resource.tags); - }, [resource, tags]); + // useEffect(() => { + // if (resource && !tags) setTags(resource.tags); + // }, [resource, tags]); useEffect(() => { if (open) setInput(""); }, [open]); - const update_tags = (tag: Types.CustomTag) => { - const exists = tags?.some((id) => id === tag._id?.$oid); - if (exists) return setTags((t) => t?.filter((id) => id !== tag._id?.$oid)); - else return setTags((t) => [...(t ?? []), tag._id?.$oid as string]); - }; - const { toast } = useToast(); const create_tag = async () => { if (!input) return toast({ title: "Must provide tag name in input" }); - update_tags(await create({ name: input })); + const tag = await create({ name: input }); + update({ + target, + tags: [...(resource?.tags ?? []), tag._id!.$oid], + }); setOpen(false); }; @@ -149,12 +172,12 @@ export const ManageTags = ({ target }: { target: TargetExcludingSystem }) => { return ( - - - Edit Tags - + + - + { - {all_tags?.map((tag) => ( - update_tags(tag)} - className="flex items-center justify-between" - > - {tag.name} - - - ))} + {all_tags + ?.filter((tag) => !resource?.tags.includes(tag._id!.$oid)) + .map((tag) => ( + + update({ + target, + tags: [...(resource?.tags ?? []), tag._id!.$oid], + }) + } + className="flex items-center justify-between" + > +
{tag.name}
+
+ ))}
diff --git a/frontend/src/pages/resource.tsx b/frontend/src/pages/resource.tsx index d3756ed1e..9fa248fc5 100644 --- a/frontend/src/pages/resource.tsx +++ b/frontend/src/pages/resource.tsx @@ -1,7 +1,6 @@ import { Page } from "@components/layouts"; -import { ResourcePermissions } from "@components/permissions"; import { ResourceComponents } from "@components/resources"; -import { ManageTags, ResourceTags } from "@components/tags"; +import { AddTags, ResourceTags } from "@components/tags"; import { ResourceUpdates } from "@components/updates/resource"; import { usePushRecentlyViewed, useResourceParamType } from "@lib/hooks"; import { useParams } from "react-router-dom"; @@ -18,6 +17,12 @@ export const Resource = () => { return ( } + titleRight={ +
+ + +
+ } subtitle={
@@ -27,16 +32,12 @@ export const Resource = () => {
-
- - -
} actions={} > - + {/* */} {Object.keys(Components.Page).map((section) => { const Component = Components.Page[section]; return ;