diff --git a/src/components/Playbooks/Runs/Submit/PlaybooksDropdownMenu.tsx b/src/components/Playbooks/Runs/Submit/PlaybooksDropdownMenu.tsx index 996890123..66e73f854 100644 --- a/src/components/Playbooks/Runs/Submit/PlaybooksDropdownMenu.tsx +++ b/src/components/Playbooks/Runs/Submit/PlaybooksDropdownMenu.tsx @@ -1,14 +1,9 @@ import { AuthorizationAccessCheck } from "@flanksource-ui/components/Permissions/AuthorizationAccessCheck"; +import CollapsiblePanel from "@flanksource-ui/ui/CollapsiblePanel/CollapsiblePanel"; import { Icon } from "@flanksource-ui/ui/Icons/Icon"; -import { - Menu, - MenuButton, - MenuItem, - MenuItems, - Transition -} from "@headlessui/react"; +import { Popover, PopoverButton, PopoverPanel } from "@headlessui/react"; import { ChevronDownIcon } from "@heroicons/react/solid"; -import { Fragment, useState } from "react"; +import { useMemo, useState } from "react"; import { useGetPlaybooksToRun } from "../../../../api/query-hooks/playbooks"; import { RunnablePlaybook } from "../../../../api/types/playbooks"; import PlaybookSpecIcon from "../../Settings/PlaybookSpecIcon"; @@ -43,47 +38,79 @@ export default function PlaybooksDropdownMenu({ config_id }); + const playbooksGroupedByCategory = useMemo( + () => + playbooks?.reduce( + (acc, playbook) => { + const category = playbook.spec?.category || "Uncategorized"; + if (!acc[category]) { + acc[category] = []; + } + acc[category].push(playbook); + return acc; + }, + {} as Record< + string, + (RunnablePlaybook & { + spec: any; + })[] + > + ), + [playbooks] + ); + if (error || playbooks?.length === 0 || isLoading) { return null; } return ( -
- - + <> + + - Playbooks - - - {/* @ts-ignore */} - + + - - {playbooks?.map((playbook) => ( - setSelectedPlaybookSpec(playbook)} - key={playbook.id} - > - - - ))} - - - + {playbooksGroupedByCategory && ( + <> + {Object.entries(playbooksGroupedByCategory).map( + ([category, playbooks]) => ( + + {category} +
+ } + iconClassName="h-4 w-4" + isCollapsed + > +
+ {playbooks.map((playbook) => ( +
{ + setSelectedPlaybookSpec(playbook); + }} + className={`flex cursor-pointer flex-col justify-between gap-1 px-4 py-2 text-sm`} + > + +
+ ))} +
+ + ) + )} + + )} + + {selectedPlaybookSpec && ( )} - +
); }