diff --git a/src/App.tsx b/src/App.tsx index 8aa1e17cf..fd8836c76 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -7,7 +7,13 @@ import React, { ReactNode, useEffect, useState, useMemo } from "react"; import { IconType } from "react-icons"; import { AiFillHeart } from "react-icons/ai"; import { BsLink, BsToggles } from "react-icons/bs"; -import { FaArchive, FaBell, FaCrosshairs, FaTasks } from "react-icons/fa"; +import { + FaArchive, + FaBell, + FaCrosshairs, + FaPlug, + FaTasks +} from "react-icons/fa"; import { HiUser } from "react-icons/hi"; import { ImLifebuoy } from "react-icons/im"; import { @@ -184,6 +190,12 @@ const ConnectionsPage = dynamic(() => ) ); +const PluginsPage = dynamic(() => + import("@flanksource-ui/pages/Settings/PluginsPage").then( + (m) => m.PluginsPage + ) +); + const EventQueueStatusPage = dynamic(() => import("@flanksource-ui/pages/Settings/EventQueueStatus").then( (m) => m.EventQueueStatusPage @@ -507,6 +519,13 @@ const settingsNav: SettingsNavigationItems = { featureName: features["settings.integrations"], resourceName: tables.database }, + { + name: "Plugins", + href: "/settings/plugins", + icon: FaPlug, + featureName: features["settings.plugins"], + resourceName: tables.plugins + }, { name: "Views", href: "/settings/views", @@ -938,6 +957,16 @@ export function IncidentManagerRoutes({ sidebar }: { sidebar: ReactNode }) { + , + tables.plugins, + "read", + true + )} + /> + ("/plugins"); +} diff --git a/src/context/UserAccessContext/permissions.ts b/src/context/UserAccessContext/permissions.ts index 67abba003..20f4dd867 100644 --- a/src/context/UserAccessContext/permissions.ts +++ b/src/context/UserAccessContext/permissions.ts @@ -17,6 +17,7 @@ export const tables = { feature_flags: "properties", logging_backends: "logging_backends", integrations: "integrations", + plugins: "plugins", notifications: "notifications", playbooks: "playbooks", playbook_runs: "playbook_runs", diff --git a/src/pages/Settings/PluginsPage.tsx b/src/pages/Settings/PluginsPage.tsx new file mode 100644 index 000000000..28c311da1 --- /dev/null +++ b/src/pages/Settings/PluginsPage.tsx @@ -0,0 +1,101 @@ +import { + getPlugins, + PluginListing +} from "@flanksource-ui/api/services/plugins"; +import { + BreadcrumbNav, + BreadcrumbRoot +} from "@flanksource-ui/ui/BreadcrumbNav"; +import { Head } from "@flanksource-ui/ui/Head"; +import { SearchLayout } from "@flanksource-ui/ui/Layout/SearchLayout"; +import MRTDataTable from "@flanksource-ui/ui/MRTDataTable/MRTDataTable"; +import { useQuery } from "@tanstack/react-query"; +import clsx from "clsx"; +import { MRT_ColumnDef } from "mantine-react-table"; + +const columns: MRT_ColumnDef[] = [ + { + header: "Name", + accessorKey: "name", + maxSize: 50, + enableResizing: true + }, + { + header: "Description", + accessorKey: "description", + enableResizing: true + }, + { + header: "Version", + accessorKey: "version", + maxSize: 100, + enableResizing: true + }, + { + header: "Agent", + id: "agent", + accessorFn: (row) => row.agent?.name ?? "", + maxSize: 100, + enableResizing: true + } +]; + +function PluginsList({ + data, + isLoading, + className +}: { + data: PluginListing[]; + isLoading?: boolean; + className?: string; +}) { + return ( +
+ +
+ ); +} + +export function PluginsPage() { + const { + isLoading: loading, + data: plugins, + refetch + } = useQuery({ + queryKey: ["plugins", "all"], + queryFn: async () => { + const response = await getPlugins(); + return response.data ?? []; + } + }); + + return ( + <> + + + Plugins + + ]} + /> + } + onRefresh={() => { + refetch(); + }} + contentClass="p-0 h-full" + loading={loading} + > +
+ +
+
+ + ); +} diff --git a/src/services/permissions/features.ts b/src/services/permissions/features.ts index d11c05b36..dc7d628ac 100644 --- a/src/services/permissions/features.ts +++ b/src/services/permissions/features.ts @@ -24,6 +24,7 @@ export const features = { "settings.notifications": "settings.notifications", "settings.playbooks": "settings.playbooks", "settings.integrations": "settings.integrations", + "settings.plugins": "settings.plugins", "settings.permissions": "settings.permissions", "settings.mcp": "settings.mcp", "settings.artifacts": "settings.artifacts"