Skip to content

Commit

Permalink
[GEN-1798]: show total counts when filters are active (#1870)
Browse files Browse the repository at this point in the history
  • Loading branch information
BenElferink authored Nov 27, 2024
1 parent f75e804 commit 6bf3e28
Show file tree
Hide file tree
Showing 9 changed files with 134 additions and 131 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,10 @@ import { ToastList } from '@/components';
import MultiSourceControl from '../multi-source-control';
import { OverviewActionMenuContainer } from '../overview-actions-menu';
import { buildNodesAndEdges, NodeBaseDataFlow } from '@/reuseable-components';
import { useMetrics, useContainerSize, useNodeDataFlowHandlers, useSourceCRUD, useDestinationCRUD, useInstrumentationRuleCRUD, useActionCRUD } from '@/hooks';
import { useComputePlatform, useContainerSize, useMetrics, useNodeDataFlowHandlers } from '@/hooks';

const AllDrawers = dynamic(() => import('../all-drawers'), {
ssr: false,
});

const AllModals = dynamic(() => import('../all-modals'), {
ssr: false,
});
const AllDrawers = dynamic(() => import('../all-drawers'), { ssr: false });
const AllModals = dynamic(() => import('../all-modals'), { ssr: false });

export const OverviewDataFlowWrapper = styled.div`
width: 100%;
Expand All @@ -26,40 +21,29 @@ const NODE_WIDTH = 255;
const NODE_HEIGHT = 80;

export default function OverviewDataFlowContainer() {
const { metrics } = useMetrics();
const { sources } = useSourceCRUD();
const { actions } = useActionCRUD();
const { destinations } = useDestinationCRUD();
const { instrumentationRules } = useInstrumentationRuleCRUD();
const { containerRef, containerWidth, containerHeight } = useContainerSize();

const { handleNodeClick } = useNodeDataFlowHandlers({
rules: instrumentationRules,
sources,
actions,
destinations,
});
const { handleNodeClick } = useNodeDataFlowHandlers();
const { data, filteredData } = useComputePlatform();
const { metrics } = useMetrics();

// Memoized node and edge builder to improve performance
const { nodes, edges } = useMemo(() => {
return buildNodesAndEdges({
rules: instrumentationRules,
sources,
actions,
destinations,
computePlatform: data?.computePlatform,
computePlatformFiltered: filteredData?.computePlatform,
metrics,
containerWidth,
containerHeight,
nodeWidth: NODE_WIDTH,
nodeHeight: NODE_HEIGHT,
});
}, [instrumentationRules, sources, actions, destinations, metrics, containerWidth, containerHeight]);
}, [data, filteredData, metrics, containerWidth, containerHeight]);

return (
<OverviewDataFlowWrapper ref={containerRef}>
<OverviewActionMenuContainer />
<NodeBaseDataFlow nodes={nodes} edges={edges} onNodeClick={handleNodeClick} nodeWidth={NODE_WIDTH} />
<MultiSourceControl />
<NodeBaseDataFlow nodes={nodes} edges={edges} nodeWidth={NODE_WIDTH} onNodeClick={handleNodeClick} />

<AllDrawers />
<AllModals />
Expand Down
11 changes: 3 additions & 8 deletions frontend/webapp/hooks/actions/useActionCRUD.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import { useMutation } from '@apollo/client';
import { useNotificationStore } from '@/store';
import { useNotify } from '../notification/useNotify';
import { useComputePlatform } from '../compute-platform';
import { ACTION, getSseTargetFromId, NOTIFICATION, safeJsonParse } from '@/utils';
import { ACTION, getSseTargetFromId, NOTIFICATION } from '@/utils';
import { CREATE_ACTION, DELETE_ACTION, UPDATE_ACTION } from '@/graphql/mutations';
import { type ActionItem, OVERVIEW_ENTITY_TYPES, type ActionInput, type ActionsType, type NotificationType } from '@/types';
import { OVERVIEW_ENTITY_TYPES, type ActionInput, type ActionsType, type NotificationType } from '@/types';

interface UseActionCrudParams {
onSuccess?: (type: string) => void;
Expand Down Expand Up @@ -68,12 +68,7 @@ export const useActionCRUD = (params?: UseActionCrudParams) => {

return {
loading: cState.loading || uState.loading || dState.loading,
actions:
data?.computePlatform?.actions?.map((item) => {
const parsedSpec = typeof item.spec === 'string' ? safeJsonParse(item.spec, {} as ActionItem) : item.spec;

return { ...item, spec: parsedSpec };
}) || [],
actions: data?.computePlatform.actions || [],

createAction: (action: ActionInput) => createAction({ variables: { action } }),
updateAction: (id: string, action: ActionInput) => updateAction({ variables: { id, action } }),
Expand Down
49 changes: 32 additions & 17 deletions frontend/webapp/hooks/compute-platform/useComputePlatform.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { useCallback, useEffect, useMemo } from 'react';
import { BACKEND_BOOLEAN, safeJsonParse } from '@/utils';
import { useQuery } from '@apollo/client';
import { useBooleanStore } from '@/store';
import type { ComputePlatform } from '@/types';
import { GET_COMPUTE_PLATFORM } from '@/graphql';
import { useFilterStore } from '@/store/useFilterStore';
import { BACKEND_BOOLEAN, deriveTypeFromRule, safeJsonParse } from '@/utils';
import type { ActionItem, ComputePlatform, ComputePlatformMapped } from '@/types';

type UseComputePlatformHook = {
data?: ComputePlatform;
data?: ComputePlatformMapped;
filteredData?: ComputePlatformMapped;
loading: boolean;
error?: Error;
refetch: () => void;
Expand Down Expand Up @@ -40,12 +41,32 @@ export const useComputePlatform = (): UseComputePlatformHook => {
startPolling();
}, []);

const filteredData = useMemo(() => {
const mappedData = useMemo(() => {
if (!data) return undefined;

let k8sActualSources = [...data.computePlatform.k8sActualSources];
let destinations = [...data.computePlatform.destinations];
let actions = [...data.computePlatform.actions];
return {
computePlatform: {
...data.computePlatform,
actions: data.computePlatform.actions.map((item) => {
const parsedSpec = typeof item.spec === 'string' ? safeJsonParse(item.spec, {} as ActionItem) : item.spec;

return { ...item, spec: parsedSpec };
}),
instrumentationRules: data.computePlatform.instrumentationRules.map((item) => {
const type = deriveTypeFromRule(item);

return { ...item, type };
}),
},
};
}, [data]);

const filteredData = useMemo(() => {
if (!mappedData) return undefined;

let k8sActualSources = [...mappedData.computePlatform.k8sActualSources];
let destinations = [...mappedData.computePlatform.destinations];
let actions = [...mappedData.computePlatform.actions];

if (!!filters.namespace) {
k8sActualSources = k8sActualSources.filter((source) => filters.namespace?.id === source.namespace);
Expand All @@ -66,24 +87,18 @@ export const useComputePlatform = (): UseComputePlatformHook => {
}
if (!!filters.monitors.length) {
destinations = destinations.filter((destination) => !!filters.monitors.find((metric) => destination.exportedSignals[metric.id]));
actions = actions.filter(
(action) =>
!!filters.monitors.find((metric) => {
const { signals } = safeJsonParse(action.spec as string, { signals: [] as string[] });
return signals.find((str) => str.toLowerCase() === metric.id);
}),
);
actions = actions.filter((action) => !!filters.monitors.find((metric) => action.spec.signals.find((str) => str.toLowerCase() === metric.id)));
}

return {
computePlatform: {
...data.computePlatform,
...mappedData.computePlatform,
k8sActualSources,
destinations,
actions,
},
};
}, [data, filters]);
}, [mappedData, filters]);

return { data: filteredData, loading, error, refetch, startPolling };
return { data: mappedData, filteredData, loading, error, refetch, startPolling };
};
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,7 @@ export const useInstrumentationRuleCRUD = (params?: Params) => {

return {
loading: cState.loading || uState.loading || dState.loading,
instrumentationRules:
data?.computePlatform?.instrumentationRules?.map((item) => {
const type = deriveTypeFromRule(item);

return { ...item, type };
}) || [],
instrumentationRules: data?.computePlatform.instrumentationRules || [],

createInstrumentationRule: (instrumentationRule: InstrumentationRuleInput) => createInstrumentationRule({ variables: { instrumentationRule } }),
updateInstrumentationRule: (ruleId: string, instrumentationRule: InstrumentationRuleInput) => updateInstrumentationRule({ variables: { ruleId, instrumentationRule } }),
Expand Down
47 changes: 36 additions & 11 deletions frontend/webapp/hooks/overview/useNodeDataFlowHandlers.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,61 @@
// src/hooks/useNodeDataFlowHandlers.ts
import { useCallback } from 'react';
import { useSourceCRUD } from '../sources';
import { useActionCRUD } from '../actions';
import { useDestinationCRUD } from '../destinations';
import { useDrawerStore, useModalStore } from '@/store';
import { K8sActualSource, ActualDestination, ActionDataParsed, OVERVIEW_ENTITY_TYPES, OVERVIEW_NODE_TYPES, InstrumentationRuleSpec } from '@/types';
import { OVERVIEW_ENTITY_TYPES, OVERVIEW_NODE_TYPES, WorkloadId } from '@/types';
import { useInstrumentationRuleCRUD } from '../instrumentation-rules';
import { Node } from '@xyflow/react';

export function useNodeDataFlowHandlers() {
const { sources } = useSourceCRUD();
const { actions } = useActionCRUD();
const { destinations } = useDestinationCRUD();
const { instrumentationRules } = useInstrumentationRuleCRUD();

export function useNodeDataFlowHandlers(params: { rules: InstrumentationRuleSpec[]; sources: K8sActualSource[]; actions: ActionDataParsed[]; destinations: ActualDestination[] }) {
const { setCurrentModal } = useModalStore();
const setSelectedItem = useDrawerStore(({ setSelectedItem }) => setSelectedItem);

const handleNodeClick = useCallback(
(_: unknown, object: { data: { id: any; type: any } }) => {
(
_: React.MouseEvent,
object: Node<
{
id: string | WorkloadId;
type: OVERVIEW_ENTITY_TYPES | OVERVIEW_NODE_TYPES;
},
'add'
>,
) => {
const {
data: { id, type },
} = object;

const entities = {
sources,
actions,
destinations,
rules: instrumentationRules,
};

if (type === OVERVIEW_ENTITY_TYPES.SOURCE) {
const selectedDrawerItem = params['sources'].find(({ kind, name, namespace }) => kind === id.kind && name === id.name && namespace === id.namespace);
const { kind, name, namespace } = id as WorkloadId;
const selectedDrawerItem = entities['sources'].find((item) => item.kind === kind && item.name === name && item.namespace === namespace);
if (!selectedDrawerItem) return;

const { kind, name, namespace } = selectedDrawerItem;

setSelectedItem({
id: { kind, name, namespace },
id,
type,
item: selectedDrawerItem,
});
} else if ([OVERVIEW_ENTITY_TYPES.RULE, OVERVIEW_ENTITY_TYPES.ACTION, OVERVIEW_ENTITY_TYPES.DESTINATION].includes(type)) {
const selectedDrawerItem = params[`${type}s`].find((item) => id && [item.id, item.ruleId].includes(id));
} else if ([OVERVIEW_ENTITY_TYPES.RULE, OVERVIEW_ENTITY_TYPES.ACTION, OVERVIEW_ENTITY_TYPES.DESTINATION].includes(type as OVERVIEW_ENTITY_TYPES)) {
const selectedDrawerItem = entities[`${type}s`].find((item) => id && [item.id, item.ruleId].includes(id));
if (!selectedDrawerItem) return;

setSelectedItem({
id,
type,
type: type as OVERVIEW_ENTITY_TYPES,
item: selectedDrawerItem,
});
} else if (type === OVERVIEW_NODE_TYPES.ADD_RULE) {
Expand All @@ -43,7 +68,7 @@ export function useNodeDataFlowHandlers(params: { rules: InstrumentationRuleSpec
setCurrentModal(OVERVIEW_ENTITY_TYPES.DESTINATION);
}
},
[params, setSelectedItem, setCurrentModal],
[sources, actions, destinations, instrumentationRules, setSelectedItem, setCurrentModal],
);

return {
Expand Down
Loading

0 comments on commit 6bf3e28

Please sign in to comment.