-
Notifications
You must be signed in to change notification settings - Fork 207
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[GEN-1710]: add scroll to overview sources (#1978)
This pull request introduces several updates to the frontend web application, primarily focused on refactoring components and adding new functionalities to the overview data flow. The key changes include converting components to named exports, building nodes for various entity types, and constructing edges for data flow visualization. ### Component Refactoring: * [`frontend/webapp/containers/main/overview/multi-source-control/index.tsx`](diffhunk://#diff-cdd99a8fcd0484b24586f22b1f7b1bcf8d964bead53eeb0b2c07646c7301af70L27-R27): Converted `MultiSourceControl` to a named export. [[1]](diffhunk://#diff-cdd99a8fcd0484b24586f22b1f7b1bcf8d964bead53eeb0b2c07646c7301af70L27-R27) [[2]](diffhunk://#diff-cdd99a8fcd0484b24586f22b1f7b1bcf8d964bead53eeb0b2c07646c7301af70L91-L92) * [`frontend/webapp/containers/main/overview/overview-actions-menu/index.tsx`](diffhunk://#diff-d5bd2313f84205e47d83344e7ac50ad55a85f3bad2fba1ca4b0288484584f0dfL21-R21): Converted `OverviewActionsMenu` to a named export. [[1]](diffhunk://#diff-d5bd2313f84205e47d83344e7ac50ad55a85f3bad2fba1ca4b0288484584f0dfL21-R21) [[2]](diffhunk://#diff-d5bd2313f84205e47d83344e7ac50ad55a85f3bad2fba1ca4b0288484584f0dfL35-R35) ### Node Building for Overview Data Flow: * [`frontend/webapp/containers/main/overview/overview-data-flow/build-action-nodes.ts`](diffhunk://#diff-2a2957e6035bd001e3c0c52f29f01f4473b6b99a8ce4381a08e9de504916c3b1R1-R97): Added functionality to build nodes for actions in the overview data flow. * [`frontend/webapp/containers/main/overview/overview-data-flow/build-destination-nodes.ts`](diffhunk://#diff-aa30a6b7893a9d1393f196b9846b1fdc19956c7c07f4099570cb25ff2f77fa43R1-R81): Added functionality to build nodes for destinations in the overview data flow. * [`frontend/webapp/containers/main/overview/overview-data-flow/build-rule-nodes.ts`](diffhunk://#diff-a37edc5ed2e31d0b06f407f3d1d5b155d499c689f95609db388f0e8246a1800bR1-R81): Added functionality to build nodes for instrumentation rules in the overview data flow. * [`frontend/webapp/containers/main/overview/overview-data-flow/build-source-nodes.ts`](diffhunk://#diff-278da68d858c88d202c10e2011bc1263fe6c0b543dc9d0fc4995a0f0675d3db1R1-R115): Added functionality to build nodes for sources in the overview data flow. ### Edge Building for Data Flow: * [`frontend/webapp/containers/main/overview/overview-data-flow/build-edges.ts`](diffhunk://#diff-39cdfd27eadcda95cac1b52b794dc8feae0d0d46bb5f29ac1a39f96473eab483R1-R80): Added functionality to build edges for connecting nodes in the overview data flow. ### Utility Functions: * [`frontend/webapp/containers/main/overview/overview-data-flow/get-entity-counts.ts`](diffhunk://#diff-9180e7735f3b0a44ca96a2b3211d3f6adf63d412713f4f6e6b8cfe4566eb0e86R1-R18): Added a utility function to get entity counts for different types in the overview data flow. * [`frontend/webapp/containers/main/overview/overview-data-flow/get-node-positions.ts`](diffhunk://#diff-76a303d4463294b366faf6aa5f23672be0bbbc7907480ec7a19868ad114a6f59R1-R48): Added a utility function to calculate node positions based on container width.
- Loading branch information
1 parent
ea35774
commit ced6950
Showing
27 changed files
with
947 additions
and
552 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
97 changes: 97 additions & 0 deletions
97
frontend/webapp/containers/main/overview/overview-data-flow/build-action-nodes.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
import { type Node } from '@xyflow/react'; | ||
import nodeConfig from './node-config.json'; | ||
import { type EntityCounts } from './get-entity-counts'; | ||
import { type NodePositions } from './get-node-positions'; | ||
import { getActionIcon, getEntityIcon, getEntityLabel } from '@/utils'; | ||
import { OVERVIEW_ENTITY_TYPES, OVERVIEW_NODE_TYPES, STATUSES, type ComputePlatformMapped } from '@/types'; | ||
|
||
interface Params { | ||
entities: ComputePlatformMapped['computePlatform']['actions']; | ||
positions: NodePositions; | ||
unfilteredCounts: EntityCounts; | ||
} | ||
|
||
const { nodeWidth, nodeHeight, framePadding } = nodeConfig; | ||
|
||
const mapToNodeData = (entity: Params['entities'][0]) => { | ||
return { | ||
nodeWidth, | ||
id: entity.id, | ||
type: OVERVIEW_ENTITY_TYPES.ACTION, | ||
status: STATUSES.HEALTHY, | ||
title: getEntityLabel(entity, OVERVIEW_ENTITY_TYPES.ACTION, { prioritizeDisplayName: true }), | ||
subTitle: entity.type, | ||
imageUri: getActionIcon(entity.type), | ||
monitors: entity.spec.signals, | ||
isActive: !entity.spec.disabled, | ||
raw: entity, | ||
}; | ||
}; | ||
|
||
export const buildActionNodes = ({ entities, positions, unfilteredCounts }: Params) => { | ||
const nodes: Node[] = []; | ||
const position = positions[OVERVIEW_ENTITY_TYPES.ACTION]; | ||
const unfilteredCount = unfilteredCounts[OVERVIEW_ENTITY_TYPES.ACTION]; | ||
|
||
nodes.push({ | ||
id: 'action-header', | ||
type: 'header', | ||
position: { | ||
x: positions[OVERVIEW_ENTITY_TYPES.ACTION]['x'], | ||
y: 0, | ||
}, | ||
data: { | ||
nodeWidth, | ||
title: 'Actions', | ||
icon: getEntityIcon(OVERVIEW_ENTITY_TYPES.ACTION), | ||
tagValue: unfilteredCounts[OVERVIEW_ENTITY_TYPES.ACTION], | ||
}, | ||
}); | ||
|
||
if (!entities.length) { | ||
nodes.push({ | ||
id: 'action-add', | ||
type: 'add', | ||
position: { | ||
x: position['x'], | ||
y: position['y'](), | ||
}, | ||
data: { | ||
nodeWidth, | ||
type: OVERVIEW_NODE_TYPES.ADD_ACTION, | ||
status: STATUSES.HEALTHY, | ||
title: 'ADD ACTION', | ||
subTitle: `Add ${!!unfilteredCount ? 'a new' : 'first'} action to modify the OpenTelemetry data`, | ||
}, | ||
}); | ||
} else { | ||
nodes.push({ | ||
id: 'action-frame', | ||
type: 'frame', | ||
position: { | ||
x: position['x'] - framePadding, | ||
y: position['y']() - framePadding, | ||
}, | ||
data: { | ||
nodeWidth: nodeWidth + 2 * framePadding, | ||
nodeHeight: nodeHeight * entities.length + framePadding, | ||
}, | ||
}); | ||
|
||
entities.forEach((action, idx) => { | ||
nodes.push({ | ||
id: `action-${idx}`, | ||
type: 'base', | ||
extent: 'parent', | ||
parentId: 'action-frame', | ||
position: { | ||
x: framePadding, | ||
y: position['y'](idx) - (nodeHeight - framePadding), | ||
}, | ||
data: mapToNodeData(action), | ||
}); | ||
}); | ||
} | ||
|
||
return nodes; | ||
}; |
81 changes: 81 additions & 0 deletions
81
frontend/webapp/containers/main/overview/overview-data-flow/build-destination-nodes.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import { type Node } from '@xyflow/react'; | ||
import nodeConfig from './node-config.json'; | ||
import { type EntityCounts } from './get-entity-counts'; | ||
import { type NodePositions } from './get-node-positions'; | ||
import { extractMonitors, getEntityIcon, getEntityLabel, getHealthStatus } from '@/utils'; | ||
import { OVERVIEW_ENTITY_TYPES, OVERVIEW_NODE_TYPES, STATUSES, type ComputePlatformMapped } from '@/types'; | ||
|
||
interface Params { | ||
entities: ComputePlatformMapped['computePlatform']['destinations']; | ||
positions: NodePositions; | ||
unfilteredCounts: EntityCounts; | ||
} | ||
|
||
const { nodeWidth } = nodeConfig; | ||
|
||
const mapToNodeData = (entity: Params['entities'][0]) => { | ||
return { | ||
nodeWidth, | ||
id: entity.id, | ||
type: OVERVIEW_ENTITY_TYPES.DESTINATION, | ||
status: getHealthStatus(entity), | ||
title: getEntityLabel(entity, OVERVIEW_ENTITY_TYPES.DESTINATION, { prioritizeDisplayName: true }), | ||
subTitle: entity.destinationType.displayName, | ||
imageUri: entity.destinationType.imageUrl || '/brand/odigos-icon.svg', | ||
monitors: extractMonitors(entity.exportedSignals), | ||
raw: entity, | ||
}; | ||
}; | ||
|
||
export const buildDestinationNodes = ({ entities, positions, unfilteredCounts }: Params) => { | ||
const nodes: Node[] = []; | ||
const position = positions[OVERVIEW_ENTITY_TYPES.DESTINATION]; | ||
const unfilteredCount = unfilteredCounts[OVERVIEW_ENTITY_TYPES.DESTINATION]; | ||
|
||
nodes.push({ | ||
id: 'destination-header', | ||
type: 'header', | ||
position: { | ||
x: positions[OVERVIEW_ENTITY_TYPES.DESTINATION]['x'], | ||
y: 0, | ||
}, | ||
data: { | ||
nodeWidth, | ||
title: 'Destinations', | ||
icon: getEntityIcon(OVERVIEW_ENTITY_TYPES.DESTINATION), | ||
tagValue: unfilteredCounts[OVERVIEW_ENTITY_TYPES.DESTINATION], | ||
}, | ||
}); | ||
|
||
if (!entities.length) { | ||
nodes.push({ | ||
id: 'destination-add', | ||
type: 'add', | ||
position: { | ||
x: position['x'], | ||
y: position['y'](), | ||
}, | ||
data: { | ||
nodeWidth, | ||
type: OVERVIEW_NODE_TYPES.ADD_DESTIONATION, | ||
status: STATUSES.HEALTHY, | ||
title: 'ADD DESTIONATION', | ||
subTitle: `Add ${!!unfilteredCount ? 'a new' : 'first'} destination to monitor the OpenTelemetry data`, | ||
}, | ||
}); | ||
} else { | ||
entities.forEach((destination, idx) => { | ||
nodes.push({ | ||
id: `destination-${idx}`, | ||
type: 'base', | ||
position: { | ||
x: position['x'], | ||
y: position['y'](idx), | ||
}, | ||
data: mapToNodeData(destination), | ||
}); | ||
}); | ||
} | ||
|
||
return nodes; | ||
}; |
80 changes: 80 additions & 0 deletions
80
frontend/webapp/containers/main/overview/overview-data-flow/build-edges.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
import theme from '@/styles/theme'; | ||
import { formatBytes } from '@/utils'; | ||
import { type Edge, type Node } from '@xyflow/react'; | ||
import { OVERVIEW_ENTITY_TYPES, STATUSES, WorkloadId, type OverviewMetricsResponse } from '@/types'; | ||
import nodeConfig from './node-config.json'; | ||
|
||
interface Params { | ||
nodes: Node[]; | ||
metrics?: OverviewMetricsResponse; | ||
containerHeight: number; | ||
} | ||
|
||
const { nodeHeight, framePadding } = nodeConfig; | ||
|
||
const createEdge = (edgeId: string, params?: { label?: string; isMultiTarget?: boolean; isError?: boolean; animated?: boolean }): Edge => { | ||
const { label, isMultiTarget, isError, animated } = params || {}; | ||
const [sourceNodeId, targetNodeId] = edgeId.split('-to-'); | ||
|
||
return { | ||
id: edgeId, | ||
type: !!label ? 'labeled' : 'default', | ||
source: sourceNodeId, | ||
target: targetNodeId, | ||
animated, | ||
data: { label, isMultiTarget, isError }, | ||
style: { stroke: isError ? theme.colors.dark_red : theme.colors.border }, | ||
}; | ||
}; | ||
|
||
export const buildEdges = ({ nodes, metrics, containerHeight }: Params) => { | ||
const edges: Edge[] = []; | ||
const actionNodeId = nodes.find(({ id: nodeId }) => ['action-frame', 'action-add'].includes(nodeId))?.id; | ||
|
||
nodes.forEach(({ type: nodeType, id: nodeId, data: { type: entityType, id: entityId, status }, position }) => { | ||
if (nodeType === 'base') { | ||
switch (entityType) { | ||
case OVERVIEW_ENTITY_TYPES.SOURCE: { | ||
const { namespace, name, kind } = entityId as WorkloadId; | ||
const metric = metrics?.getOverviewMetrics.sources.find((m) => m.kind === kind && m.name === name && m.namespace === namespace); | ||
|
||
const topLimit = -nodeHeight / 2 + framePadding; | ||
const bottomLimit = containerHeight - nodeHeight + framePadding * 2 + topLimit; | ||
|
||
if (position.y >= topLimit && position.y <= bottomLimit) { | ||
edges.push( | ||
createEdge(`${nodeId}-to-${actionNodeId}`, { | ||
animated: false, | ||
isMultiTarget: false, | ||
label: formatBytes(metric?.throughput), | ||
isError: status === STATUSES.UNHEALTHY, | ||
}), | ||
); | ||
} | ||
|
||
break; | ||
} | ||
|
||
case OVERVIEW_ENTITY_TYPES.DESTINATION: { | ||
const metric = metrics?.getOverviewMetrics.destinations.find((m) => m.id === entityId); | ||
|
||
edges.push( | ||
createEdge(`${actionNodeId}-to-${nodeId}`, { | ||
animated: false, | ||
isMultiTarget: true, | ||
label: formatBytes(metric?.throughput), | ||
isError: status === STATUSES.UNHEALTHY, | ||
}), | ||
); | ||
|
||
break; | ||
} | ||
|
||
default: | ||
break; | ||
} | ||
} | ||
}); | ||
|
||
return edges; | ||
}; |
81 changes: 81 additions & 0 deletions
81
frontend/webapp/containers/main/overview/overview-data-flow/build-rule-nodes.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import { type Node } from '@xyflow/react'; | ||
import nodeConfig from './node-config.json'; | ||
import { type EntityCounts } from './get-entity-counts'; | ||
import { type NodePositions } from './get-node-positions'; | ||
import { getEntityIcon, getEntityLabel, getRuleIcon } from '@/utils'; | ||
import { OVERVIEW_ENTITY_TYPES, OVERVIEW_NODE_TYPES, STATUSES, type ComputePlatformMapped } from '@/types'; | ||
|
||
interface Params { | ||
entities: ComputePlatformMapped['computePlatform']['instrumentationRules']; | ||
positions: NodePositions; | ||
unfilteredCounts: EntityCounts; | ||
} | ||
|
||
const { nodeWidth } = nodeConfig; | ||
|
||
const mapToNodeData = (entity: Params['entities'][0]) => { | ||
return { | ||
nodeWidth, | ||
id: entity.ruleId, | ||
type: OVERVIEW_ENTITY_TYPES.RULE, | ||
status: STATUSES.HEALTHY, | ||
title: getEntityLabel(entity, OVERVIEW_ENTITY_TYPES.RULE, { prioritizeDisplayName: true }), | ||
subTitle: entity.type, | ||
imageUri: getRuleIcon(entity.type), | ||
isActive: !entity.disabled, | ||
raw: entity, | ||
}; | ||
}; | ||
|
||
export const buildRuleNodes = ({ entities, positions, unfilteredCounts }: Params) => { | ||
const nodes: Node[] = []; | ||
const position = positions[OVERVIEW_ENTITY_TYPES.RULE]; | ||
const unfilteredCount = unfilteredCounts[OVERVIEW_ENTITY_TYPES.RULE]; | ||
|
||
nodes.push({ | ||
id: 'rule-header', | ||
type: 'header', | ||
position: { | ||
x: positions[OVERVIEW_ENTITY_TYPES.RULE]['x'], | ||
y: 0, | ||
}, | ||
data: { | ||
nodeWidth, | ||
title: 'Instrumentation Rules', | ||
icon: getEntityIcon(OVERVIEW_ENTITY_TYPES.RULE), | ||
tagValue: unfilteredCounts[OVERVIEW_ENTITY_TYPES.RULE], | ||
}, | ||
}); | ||
|
||
if (!entities.length) { | ||
nodes.push({ | ||
id: 'rule-add', | ||
type: 'add', | ||
position: { | ||
x: position['x'], | ||
y: position['y'](), | ||
}, | ||
data: { | ||
nodeWidth, | ||
type: OVERVIEW_NODE_TYPES.ADD_RULE, | ||
status: STATUSES.HEALTHY, | ||
title: 'ADD RULE', | ||
subTitle: `Add ${!!unfilteredCount ? 'a new' : 'first'} rule to modify the OpenTelemetry data`, | ||
}, | ||
}); | ||
} else { | ||
entities.forEach((rule, idx) => { | ||
nodes.push({ | ||
id: `rule-${idx}`, | ||
type: 'base', | ||
position: { | ||
x: position['x'], | ||
y: position['y'](idx), | ||
}, | ||
data: mapToNodeData(rule), | ||
}); | ||
}); | ||
} | ||
|
||
return nodes; | ||
}; |
Oops, something went wrong.