Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2174-Merge-topology-and-catalog-pages #2216

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 58 additions & 9 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import {
SchemaResourceType,
schemaResourceTypes
} from "./components/SchemaResourcePage/resourceTypes";
import { TopologyPageWrapper } from "./components/Topology/TopologyPageWrapper";
import { ConfigPageContextProvider } from "./context/ConfigPageContext";
import { useFeatureFlagsContext } from "./context/FeatureFlagsContext";
import { HealthPageContextProvider } from "./context/HealthPageContext";
Expand Down Expand Up @@ -266,15 +267,63 @@ export function IncidentManagerRoutes({ sidebar }: { sidebar: ReactNode }) {
/>

<Route path="topology" element={sidebar}>
<Route
path=":id"
element={withAuthorizationAccessCheck(
<TopologyPage />,
tables.database,
"read",
true
)}
/>
<Route path=":id">
<Route
index
element={withAuthorizationAccessCheck(
<TopologyPage></TopologyPage>,
tables.database,
"read",
true
)}
/>

<Route
path="changes"
element={withAuthorizationAccessCheck(
<TopologyPageWrapper catalogTab="Changes" />,
tables.database,
"read",
true
)}
/>
<Route
path="insights"
element={withAuthorizationAccessCheck(
<TopologyPageWrapper catalogTab="Insights" />,
tables.database,
"read",
true
)}
/>
<Route
path="relationships"
element={withAuthorizationAccessCheck(
<TopologyPageWrapper catalogTab="Relationships" />,
tables.database,
"read",
true
)}
/>
<Route
path="playbooks"
element={withAuthorizationAccessCheck(
<TopologyPageWrapper catalogTab="Playbooks" />,
tables.database,
"read",
true
)}
/>
<Route
path="checks"
element={withAuthorizationAccessCheck(
<TopologyPageWrapper catalogTab="Checks" />,
tables.database,
"read"
)}
/>
</Route>

<Route
index
element={withAuthorizationAccessCheck(
Expand Down
66 changes: 66 additions & 0 deletions src/api/query-hooks/useTopologyPageQuery.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { useQuery } from "@tanstack/react-query";
import { useRef } from "react";
import { useParams, useSearchParams } from "react-router-dom";
import { LoadingBarRef } from "react-top-loading-bar";
import { getTopology } from "../services/topology";

export default function useTopologyPageQuery() {
const { id } = useParams();

const [searchParams] = useSearchParams({
sortBy: "status",
sortOrder: "desc"
});

const selectedLabel = searchParams.get("labels") ?? "All";
const team = searchParams.get("team") ?? "All";
const topologyType = searchParams.get("type") ?? "All";
const healthStatus = searchParams.get("status") ?? "All";
const sortBy = searchParams.get("sortBy") ?? "status";
const sortOrder = searchParams.get("sortOrder") ?? "desc";
const agentId = searchParams.get("agent_id") ?? undefined;
const showHiddenComponents =
searchParams.get("showHiddenComponents") ?? undefined;

const loadingBarRef = useRef<LoadingBarRef>(null);

return useQuery(
[
"topologies",
id,
healthStatus,
team,
selectedLabel,
topologyType,
showHiddenComponents,
sortBy,
sortOrder,
agentId
],
() => {
loadingBarRef.current?.continuousStart();
const apiParams = {
id,
status: healthStatus,
type: topologyType,
team: team,
labels: selectedLabel,
sortBy,
sortOrder,
// only flatten, if topology type is set
...(topologyType &&
topologyType.toString().toLowerCase() !== "all" && {
flatten: true
}),
hidden: showHiddenComponents === "no" ? false : undefined,
agent_id: agentId
};
return getTopology(apiParams);
},
{
onSettled: () => {
loadingBarRef.current?.complete();
}
}
);
}
3 changes: 2 additions & 1 deletion src/api/services/configs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
ConfigChange,
ConfigHealthCheckView,
ConfigItem,
ConfigItemDetails,
ConfigSummary,
ConfigTypeRelationships
} from "../types/configs";
Expand Down Expand Up @@ -138,7 +139,7 @@ export const getAllChanges = (
};

export const getConfig = (id: string) =>
resolvePostGrestRequestWithPagination<ConfigItem[]>(
resolvePostGrestRequestWithPagination<ConfigItemDetails[]>(
ConfigDB.get(`/config_detail?id=eq.${id}&select=*,config_scrapers(id,name)`)
);

Expand Down
19 changes: 12 additions & 7 deletions src/api/types/configs.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Agent, Avatar, CreatedAt, Timestamped } from "../traits";
import { HealthCheckSummary } from "./health";
import { Topology } from "./topology";

export interface ConfigChange extends CreatedAt {
id: string;
Expand Down Expand Up @@ -69,13 +70,6 @@ export interface ConfigItem extends Timestamped, Avatar, Agent, Costs {
id: string;
name: string;
};
summary?: {
relationships?: number;
analysis?: number;
changes?: number;
playbook_runs?: number;
checks?: number;
};
properties?: {
icon: string;
name: string;
Expand All @@ -87,6 +81,17 @@ export interface ConfigItem extends Timestamped, Avatar, Agent, Costs {
last_scraped_time?: string;
}

export interface ConfigItemDetails extends ConfigItem {
summary?: {
relationships?: number;
analysis?: number;
changes?: number;
playbook_runs?: number;
checks?: number;
};
components?: Topology[];
}

export interface ConfigItemGraphData extends ConfigItem {
expanded?: boolean;
expandable?: boolean;
Expand Down
56 changes: 35 additions & 21 deletions src/components/Configs/ConfigDetailsTabs.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { SearchLayout } from "@flanksource-ui/ui/Layout/SearchLayout";
import IncidentDetailsPageSkeletonLoader from "@flanksource-ui/ui/SkeletonLoader/IncidentDetailsPageSkeletonLoader";
import clsx from "clsx";
import { useAtom } from "jotai";
import { ReactNode } from "react";
Expand All @@ -9,21 +10,24 @@ import { Head } from "../../ui/Head";
import { refreshButtonClickedTrigger } from "../../ui/SlidingSideBar/SlidingSideBar";
import TabbedLinks from "../../ui/Tabs/TabbedLinks";
import { ErrorBoundary } from "../ErrorBoundary";
import { TopologyCard } from "../Topology/TopologyCard";
import { useConfigDetailsTabs } from "./ConfigTabsLinks";
import ConfigSidebar from "./Sidebar/ConfigSidebar";

type ConfigDetailsTabsProps = {
export type ConfigTab =
| "Catalog"
| "Changes"
| "Insights"
| "Relationships"
| "Playbooks"
| "Checks";

export type ConfigDetailsTabsProps = {
refetch?: () => void;
children: ReactNode;
isLoading?: boolean;
pageTitlePrefix: string;
activeTabName:
| "Catalog"
| "Changes"
| "Insights"
| "Relationships"
| "Playbooks"
| "Checks";
activeTabName: ConfigTab;
className?: string;
};

Expand Down Expand Up @@ -69,21 +73,31 @@ export function ConfigDetailsTabs({
loading={isLoading}
contentClass="p-0 h-full overflow-y-hidden"
>
<div className={`flex h-full flex-row`}>
<div className="flex flex-1 flex-col">
<TabbedLinks
activeTabName={activeTabName}
tabLinks={configTabList}
contentClassName={clsx(
"bg-white border border-t-0 border-gray-300 flex-1 overflow-y-auto",
className
{isLoadingConfig ? (
<IncidentDetailsPageSkeletonLoader />
) : (
<div className={`flex h-full flex-row bg-gray-100`}>
<div className="flex flex-1 flex-col">
{configItem?.components && configItem.components.length === 1 && (
<div className="flex w-full flex-row items-center justify-between p-4">
<TopologyCard topology={configItem.components[0]} />
</div>
)}
>
<ErrorBoundary>{children}</ErrorBoundary>
</TabbedLinks>

<TabbedLinks
activeTabName={activeTabName}
tabLinks={configTabList}
contentClassName={clsx(
"bg-white border border-t-0 border-gray-300 flex-1 overflow-y-auto",
className
)}
>
<ErrorBoundary>{children}</ErrorBoundary>
</TabbedLinks>
</div>
<ConfigSidebar />
</div>
<ConfigSidebar />
</div>
)}
</SearchLayout>
</>
);
Expand Down
19 changes: 11 additions & 8 deletions src/components/Configs/ConfigTabsLinks.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import { Badge } from "@flanksource-ui/ui/Badge/Badge";
import { useParams } from "react-router-dom";
import { ConfigItem } from "../../api/types/configs";
import { ConfigItemDetails } from "../../api/types/configs";

export function useConfigDetailsTabs(countSummary?: ConfigItem["summary"]) {
export function useConfigDetailsTabs(
countSummary?: ConfigItemDetails["summary"],
basePath: `/${string}` = "/catalog"
) {
const { id } = useParams<{ id: string }>();

return [
{ label: "Config", key: "Catalog", path: `/catalog/${id}` },
{ label: "Config", key: "Catalog", path: `${basePath}/${id}` },
{
label: (
<>
Expand All @@ -15,7 +18,7 @@ export function useConfigDetailsTabs(countSummary?: ConfigItem["summary"]) {
</>
),
key: "Changes",
path: `/catalog/${id}/changes`
path: `${basePath}/${id}/changes`
},
{
label: (
Expand All @@ -25,7 +28,7 @@ export function useConfigDetailsTabs(countSummary?: ConfigItem["summary"]) {
</>
),
key: "Insights",
path: `/catalog/${id}/insights`
path: `${basePath}/${id}/insights`
},
{
label: (
Expand All @@ -35,7 +38,7 @@ export function useConfigDetailsTabs(countSummary?: ConfigItem["summary"]) {
</>
),
key: "Relationships",
path: `/catalog/${id}/relationships`
path: `${basePath}/${id}/relationships`
},
{
label: (
Expand All @@ -45,7 +48,7 @@ export function useConfigDetailsTabs(countSummary?: ConfigItem["summary"]) {
</>
),
key: "Playbooks",
path: `/catalog/${id}/playbooks`
path: `${basePath}/${id}/playbooks`
},
{
label: (
Expand All @@ -55,7 +58,7 @@ export function useConfigDetailsTabs(countSummary?: ConfigItem["summary"]) {
</>
),
key: "Checks",
path: `/catalog/${id}/checks`
path: `${basePath}/${id}/checks`
}
];
}
Loading
Loading