diff --git a/ui/src/app/applications/components/application-resource-tree/application-resource-tree.tsx b/ui/src/app/applications/components/application-resource-tree/application-resource-tree.tsx index 0dcbfc956ea92..e97ad62609bea 100644 --- a/ui/src/app/applications/components/application-resource-tree/application-resource-tree.tsx +++ b/ui/src/app/applications/components/application-resource-tree/application-resource-tree.tsx @@ -7,11 +7,11 @@ import * as moment from 'moment'; import * as models from '../../../shared/models'; -import { EmptyState } from '../../../shared/components'; -import { AppContext, Consumer } from '../../../shared/context'; -import { ApplicationURLs } from '../application-urls'; -import { ResourceIcon } from '../resource-icon'; -import { ResourceLabel } from '../resource-label'; +import {EmptyState} from '../../../shared/components'; +import {AppContext, Consumer} from '../../../shared/context'; +import {ApplicationURLs} from '../application-urls'; +import {ResourceIcon} from '../resource-icon'; +import {ResourceLabel} from '../resource-label'; import { BASE_COLORS, ComparisonStatusIcon, @@ -26,12 +26,12 @@ import { PodHealthIcon, getUsrMsgKeyToDisplay } from '../utils'; -import { NodeUpdateAnimation } from './node-update-animation'; -import { PodGroup } from '../application-pod-view/pod-view'; +import {NodeUpdateAnimation} from './node-update-animation'; +import {PodGroup} from '../application-pod-view/pod-view'; import './application-resource-tree.scss'; -import { ArrowConnector } from './arrow-connector'; +import {ArrowConnector} from './arrow-connector'; -function treeNodeKey(node: NodeId & { uid?: string }) { +function treeNodeKey(node: NodeId & {uid?: string}) { return node.uid || nodeKey(node); } @@ -77,8 +77,7 @@ export interface ApplicationResourceTreeProps extends AbstractApplicationResourc podGroupCount: number; } -export interface ApplicationSetResourceTreeProps extends AbstractApplicationResourceTreeProps { -} +export interface ApplicationSetResourceTreeProps extends AbstractApplicationResourceTreeProps {} interface Line { x1: number; @@ -112,14 +111,14 @@ const TRAFFIC_COLORS = [0, 0.25, 0.4, 0.6] ) .reduce((first, second) => first.concat(second), []); -function getGraphSize(nodes: dagre.Node[]): { width: number; height: number } { +function getGraphSize(nodes: dagre.Node[]): {width: number; height: number} { let width = 0; let height = 0; nodes.forEach(node => { width = Math.max(node.x + node.width, width); height = Math.max(node.y + node.height, height); }); - return { width, height }; + return {width, height}; } function groupNodes(nodes: ResourceTreeNode[], graph: dagre.graphlib.Graph) { @@ -133,7 +132,7 @@ function groupNodes(nodes: ResourceTreeNode[], graph: dagre.graphlib.Graph) { }; } - function filterNoChildNode(nodeInfo: { childIds: dagre.Node[] }) { + function filterNoChildNode(nodeInfo: {childIds: dagre.Node[]}) { return nodeInfo.childIds.length === 0; } @@ -154,8 +153,8 @@ function groupNodes(nodes: ResourceTreeNode[], graph: dagre.graphlib.Graph) { const groupedNodesArr = siblingNodesArr .map(eachLevel => { return eachLevel.reduce( - (groupedNodesInfo: { kind: string; nodeIds?: string[]; parentIds?: dagre.Node[] }[], currentNodeInfo: { kind: string; nodeId: string; parentIds: dagre.Node[] }) => { - const index = groupedNodesInfo.findIndex((nodeInfo: { kind: string }) => currentNodeInfo.kind === nodeInfo.kind); + (groupedNodesInfo: {kind: string; nodeIds?: string[]; parentIds?: dagre.Node[]}[], currentNodeInfo: {kind: string; nodeId: string; parentIds: dagre.Node[]}) => { + const index = groupedNodesInfo.findIndex((nodeInfo: {kind: string}) => currentNodeInfo.kind === nodeInfo.kind); if (index > -1) { groupedNodesInfo[index].nodeIds.push(currentNodeInfo.nodeId); } @@ -179,12 +178,12 @@ function groupNodes(nodes: ResourceTreeNode[], graph: dagre.graphlib.Graph) { .reduce((flattedNodesGroup, groupedNodes) => { return flattedNodesGroup.concat(groupedNodes); }, []) - .filter((eachArr: { nodeIds: string[] }) => eachArr.nodeIds.length > 1); + .filter((eachArr: {nodeIds: string[]}) => eachArr.nodeIds.length > 1); // update graph if (groupedNodesArr.length > 0) { - groupedNodesArr.forEach((obj: { kind: string; nodeIds: string[]; parentIds: dagre.Node[] }) => { - const { nodeIds, kind, parentIds } = obj; + groupedNodesArr.forEach((obj: {kind: string; nodeIds: string[]; parentIds: dagre.Node[]}) => { + const {nodeIds, kind, parentIds} = obj; const groupedNodeIds: string[] = []; const podGroupIds: string[] = []; nodeIds.forEach((nodeId: string) => { @@ -258,10 +257,10 @@ export function compareNodes(first: ResourceTreeNode, second: ResourceTreeNode) } function appNodeKey(app: models.AbstractApplication) { - return nodeKey({ group: 'argoproj.io', kind: app.kind, name: app.metadata.name, namespace: app.metadata.namespace }); + return nodeKey({group: 'argoproj.io', kind: app.kind, name: app.metadata.name, namespace: app.metadata.namespace}); } -function renderFilteredNode(node: { count: number } & dagre.Node, onClearFilter: () => any) { +function renderFilteredNode(node: {count: number} & dagre.Node, onClearFilter: () => any) { const indicators = new Array(); let count = Math.min(node.count - 1, 3); while (count > 0) { @@ -269,7 +268,7 @@ function renderFilteredNode(node: { count: number } & dagre.Node, onClearFilter: } return ( -
+
@@ -283,14 +282,14 @@ function renderFilteredNode(node: { count: number } & dagre.Node, onClearFilter:
))} ); } -function renderGroupedNodes(props: ApplicationResourceTreeProps, node: { count: number } & dagre.Node & ResourceTreeNode) { +function renderGroupedNodes(props: ApplicationResourceTreeProps, node: {count: number} & dagre.Node & ResourceTreeNode) { const indicators = new Array(); let count = Math.min(node.count - 1, 3); while (count > 0) { @@ -298,18 +297,18 @@ function renderGroupedNodes(props: ApplicationResourceTreeProps, node: { count: } return ( -
+

-
{ResourceLabel({ kind: node.kind })}
+
{ResourceLabel({kind: node.kind})}
props.onGroupdNodeClick && props.onGroupdNodeClick(node.groupedNodeIds)} title={`Click to see details of ${node.count} collapsed ${node.kind} and doesn't contains any active pods`}> {node.kind} - + {node.kind === 'ReplicaSet' ? ( ))} @@ -335,15 +334,15 @@ function renderGroupedNodes(props: ApplicationResourceTreeProps, node: { count: function renderTrafficNode(node: dagre.Node) { return ( -
-
+
+
); } -function renderLoadBalancerNode(node: dagre.Node & { label: string; color: string }) { +function renderLoadBalancerNode(node: dagre.Node & {label: string; color: string}) { return (
- +
{node.label} @@ -395,8 +394,8 @@ function processPodGroup(targetPodGroup: ResourceTreeNode, child: ResourceTreeNo const p: models.Pod = { ...child, fullName: nodeKey(child), - metadata: { name: child.name }, - spec: { nodeName: 'Unknown' }, + metadata: {name: child.name}, + spec: {nodeName: 'Unknown'}, health: child.health ? child.health.status : 'Unknown' } as models.Pod; @@ -479,7 +478,7 @@ function renderPodGroup(props: ApplicationResourceTreeProps, id: string, node: R })}>
- {!rootNode &&
{ResourceLabel({ kind: node.kind })}
} + {!rootNode &&
{ResourceLabel({kind: node.kind})}
}

{ expandCollapse(node, props); @@ -589,7 +588,7 @@ function renderPodGroupByStatus(props: ApplicationResourceTreeProps, node: any, {pods.length !== 0 && showPodGroupByStatus ? (
- +
@@ -640,13 +639,13 @@ function renderPodGroupByStatus(props: ApplicationResourceTreeProps, node: any, } }} key={pod.metadata.name}> -
+
{isYoungerThanXMinutes(pod, 30) && ( )}
- +
@@ -667,7 +666,7 @@ function renderPodGroupByStatus(props: ApplicationResourceTreeProps, node: any, ), action: () => { - props.appContext.apis.navigation.goto('.', { node: pod.fullName, tab: 'logs' }, { replace: true }); + props.appContext.apis.navigation.goto('.', {node: pod.fullName, tab: 'logs'}, {replace: true}); } }, { @@ -694,7 +693,7 @@ function expandCollapse(node: ResourceTreeNode, props: ApplicationResourceTreePr props.setNodeExpansion(node.uid, isExpanded); } -function NodeInfoDetails({ tag: tag, kind: kind }: { tag: models.InfoItem; kind: string }) { +function NodeInfoDetails({tag: tag, kind: kind}: {tag: models.InfoItem; kind: string}) { if (kind === 'Pod') { const val = `${tag.name}`; if (val === 'Status Reason') { @@ -782,7 +781,7 @@ function renderResourceNode(props: ApplicationResourceTreeProps, id: string, nod })}>
- {!rootNode &&
{ResourceLabel({ kind: node.kind })}
} + {!rootNode &&
{ResourceLabel({kind: node.kind})}
}
{ const graph = new dagre.graphlib.Graph(); - graph.setGraph({ nodesep: 25, rankdir: 'LR', marginy: 45, marginx: -100, ranksep: 80 }); + graph.setGraph({nodesep: 25, rankdir: 'LR', marginy: 45, marginx: -100, ranksep: 80}); graph.setDefaultEdgeLabel(() => ({})); const overridesCount = getAppOverridesCount(props.app); const appNode = { @@ -905,11 +904,11 @@ export const ApplicationResourceTree = (props: AbstractApplicationResourceTreePr info: overridesCount > 0 ? [ - { - name: 'Parameter overrides', - value: `${overridesCount} parameter override(s)` - } - ] + { + name: 'Parameter overrides', + value: `${overridesCount} parameter override(s)` + } + ] : [] }; @@ -919,11 +918,11 @@ export const ApplicationResourceTree = (props: AbstractApplicationResourceTreePr } const nodeByKey = new Map(); props.tree.nodes - .map(node => ({ ...node, orphaned: false })) - .concat(((props.showOrphanedResources && props.tree.orphanedNodes) || []).map(node => ({ ...node, orphaned: true }))) + .map(node => ({...node, orphaned: false})) + .concat(((props.showOrphanedResources && props.tree.orphanedNodes) || []).map(node => ({...node, orphaned: true}))) .forEach(node => { const status = statusByKey.get(nodeKey(node)); - const resourceNode: ResourceTreeNode = { ...node }; + const resourceNode: ResourceTreeNode = {...node}; if (status) { resourceNode.health = status.health; resourceNode.status = status.status; @@ -951,7 +950,7 @@ export const ApplicationResourceTree = (props: AbstractApplicationResourceTreePr if (isApp(props.app)) { const podCount = nodes.filter(node => node.kind === 'Pod').length; - const { podGroupCount, userMsgs, updateUsrHelpTipMsgs, setShowCompactNodes } = props as ApplicationResourceTreeProps; + const {podGroupCount, userMsgs, updateUsrHelpTipMsgs, setShowCompactNodes} = props as ApplicationResourceTreeProps; React.useEffect(() => { if (podCount > podGroupCount) { const userMsg = getUsrMsgKeyToDisplay(appNode.name, 'groupNodes', userMsgs); @@ -983,7 +982,7 @@ export const ApplicationResourceTree = (props: AbstractApplicationResourceTreePr } }); if (filtered) { - graphNodesFilter.setNode(FILTERED_INDICATOR_NODE, { height: NODE_HEIGHT, width: NODE_WIDTH, count: filtered, type: NODE_TYPES.filteredIndicator }); + graphNodesFilter.setNode(FILTERED_INDICATOR_NODE, {height: NODE_HEIGHT, width: NODE_WIDTH, count: filtered, type: NODE_TYPES.filteredIndicator}); graphNodesFilter.setEdge(filteredIndicatorParent, FILTERED_INDICATOR_NODE); } } @@ -1040,7 +1039,7 @@ export const ApplicationResourceTree = (props: AbstractApplicationResourceTreePr sources.forEach((key, i) => colorsBySource.set(key, TRAFFIC_COLORS[i % TRAFFIC_COLORS.length])); if (externalRoots.length > 0) { - graph.setNode(EXTERNAL_TRAFFIC_NODE, { height: NODE_HEIGHT, width: 30, type: NODE_TYPES.externalTraffic }); + graph.setNode(EXTERNAL_TRAFFIC_NODE, {height: NODE_HEIGHT, width: 30, type: NODE_TYPES.externalTraffic}); externalRoots.sort(compareNodes).forEach(root => { const loadBalancers = root.networkingInfo.ingress.map(ingress => ingress.hostname || ingress.ip); const colorByService = new Map(); @@ -1051,11 +1050,11 @@ export const ApplicationResourceTree = (props: AbstractApplicationResourceTreePr if (root.podGroup && props.showCompactNodes) { setPodGroupNode(root, root); } else { - graph.setNode(treeNodeKey(root), { ...root, width: NODE_WIDTH, height: NODE_HEIGHT, root }); + graph.setNode(treeNodeKey(root), {...root, width: NODE_WIDTH, height: NODE_HEIGHT, root}); } (childrenByParentKey.get(treeNodeKey(root)) || []).forEach(child => { if (root.namespace === child.namespace) { - graph.setEdge(treeNodeKey(root), treeNodeKey(child), { colors: [colorByService.get(treeNodeKey(child))] }); + graph.setEdge(treeNodeKey(root), treeNodeKey(child), {colors: [colorByService.get(treeNodeKey(child))]}); } }); loadBalancers.forEach(key => { @@ -1067,14 +1066,14 @@ export const ApplicationResourceTree = (props: AbstractApplicationResourceTreePr label: key, color: colorsBySource.get(key) }); - graph.setEdge(loadBalancerNodeKey, treeNodeKey(root), { colors: [colorsBySource.get(key)] }); - graph.setEdge(EXTERNAL_TRAFFIC_NODE, loadBalancerNodeKey, { colors: [colorsBySource.get(key)] }); + graph.setEdge(loadBalancerNodeKey, treeNodeKey(root), {colors: [colorsBySource.get(key)]}); + graph.setEdge(EXTERNAL_TRAFFIC_NODE, loadBalancerNodeKey, {colors: [colorsBySource.get(key)]}); }); }); } if (internalRoots.length > 0) { - graph.setNode(INTERNAL_TRAFFIC_NODE, { height: NODE_HEIGHT, width: 30, type: NODE_TYPES.internalTraffic }); + graph.setNode(INTERNAL_TRAFFIC_NODE, {height: NODE_HEIGHT, width: 30, type: NODE_TYPES.internalTraffic}); internalRoots.forEach(root => { processNode(root, root, [colorsBySource.get(treeNodeKey(root))]); graph.setEdge(INTERNAL_TRAFFIC_NODE, treeNodeKey(root)); @@ -1138,7 +1137,7 @@ export const ApplicationResourceTree = (props: AbstractApplicationResourceTreePr orphans.sort(compareNodes).forEach(node => { processNode(node, node); }); - graph.setNode(appNodeKey(props.app), { ...appNode, width: NODE_WIDTH, height: NODE_HEIGHT }); + graph.setNode(appNodeKey(props.app), {...appNode, width: NODE_WIDTH, height: NODE_HEIGHT}); if (props.nodeFilter) { filterGraph(props.app, appNodeKey(props.app), graph, props.nodeFilter); } @@ -1149,28 +1148,28 @@ export const ApplicationResourceTree = (props: AbstractApplicationResourceTreePr function setPodGroupNode(node: ResourceTreeNode, root: ResourceTreeNode) { const numberOfRows = Math.ceil(node.podGroup.pods.length / 8); - graph.setNode(treeNodeKey(node), { ...node, type: NODE_TYPES.podGroup, width: NODE_WIDTH, height: POD_NODE_HEIGHT + 30 * numberOfRows, root }); + graph.setNode(treeNodeKey(node), {...node, type: NODE_TYPES.podGroup, width: NODE_WIDTH, height: POD_NODE_HEIGHT + 30 * numberOfRows, root}); } function processNode(node: ResourceTreeNode, root: ResourceTreeNode, colors?: string[]) { if (props.showCompactNodes && node.podGroup) { setPodGroupNode(node, root); } else { - graph.setNode(treeNodeKey(node), { ...node, width: NODE_WIDTH, height: NODE_HEIGHT, root }); + graph.setNode(treeNodeKey(node), {...node, width: NODE_WIDTH, height: NODE_HEIGHT, root}); } (childrenByParentKey.get(treeNodeKey(node)) || []).sort(compareNodes).forEach(child => { if (treeNodeKey(child) === treeNodeKey(root)) { return; } if (node.namespace === child.namespace) { - graph.setEdge(treeNodeKey(node), treeNodeKey(child), { colors }); + graph.setEdge(treeNodeKey(node), treeNodeKey(child), {colors}); } processNode(child, root, colors); }); } dagre.layout(graph); - const edges: { from: string; to: string; lines: Line[]; backgroundImage?: string; color?: string; colors?: string | { [key: string]: any } }[] = []; + const edges: {from: string; to: string; lines: Line[]; backgroundImage?: string; color?: string; colors?: string | {[key: string]: any}}[] = []; const nodeOffset = new Map(); const reverseEdge = new Map(); graph.edges().forEach(edgeInfo => { @@ -1211,7 +1210,7 @@ export const ApplicationResourceTree = (props: AbstractApplicationResourceTreePr const endNodeLeft = 140; let spaceForExpansionIcon = 0; if (edgeInfo.v.startsWith(EXTERNAL_TRAFFIC_NODE) && !edgeInfo.v.startsWith(EXTERNAL_TRAFFIC_NODE + ':')) { - lines.push({ x1: startNode.x + 10, y1: startNode.y, x2: endNode.x - endNodeLeft, y2: endNode.y }); + lines.push({x1: startNode.x + 10, y1: startNode.y, x2: endNode.x - endNodeLeft, y2: endNode.y}); } else { if (edgeInfo.v.startsWith(EXTERNAL_TRAFFIC_NODE + ':')) { startNodeRight = 152; @@ -1225,14 +1224,14 @@ export const ApplicationResourceTree = (props: AbstractApplicationResourceTreePr startNodeRight + (endNode.x - startNode.x - startNodeRight - endNodeLeft) / len + ((endNode.x - startNode.x - startNodeRight - endNodeLeft) / len) * offset; - lines.push({ x1: startNode.x + startNodeRight, y1: startNode.y, x2: firstBend, y2: startNode.y }); + lines.push({x1: startNode.x + startNodeRight, y1: startNode.y, x2: firstBend, y2: startNode.y}); if (startNode.y - yEnd >= 1 || yEnd - startNode.y >= 1) { - lines.push({ x1: firstBend, y1: startNode.y, x2: firstBend, y2: yEnd }); + lines.push({x1: firstBend, y1: startNode.y, x2: firstBend, y2: yEnd}); } - lines.push({ x1: firstBend, y1: yEnd, x2: endNode.x - endNodeLeft, y2: yEnd }); + lines.push({x1: firstBend, y1: yEnd, x2: endNode.x - endNodeLeft, y2: yEnd}); } } - edges.push({ from: edgeInfo.v, to: edgeInfo.w, lines, backgroundImage, colors: [{ colors }] }); + edges.push({from: edgeInfo.v, to: edgeInfo.w, lines, backgroundImage, colors: [{colors}]}); }); const graphNodes = graph.nodes(); const size = getGraphSize(graphNodes.map(id => graph.node(id))); @@ -1244,8 +1243,8 @@ export const ApplicationResourceTree = (props: AbstractApplicationResourceTreePr )) || (
+ className={classNames('application-resource-tree', {'application-resource-tree--network': props.useNetworkingHierarchy})} + style={{width: size.width + 150, height: size.height + 250, transformOrigin: '0% 0%', transform: `scale(${props.zoom})`}}> {graphNodes.map(key => { const node = graph.node(key); const nodeType = node.type; @@ -1261,9 +1260,17 @@ export const ApplicationResourceTree = (props: AbstractApplicationResourceTreePr case NODE_TYPES.groupedNodes: return {renderGroupedNodes(props as ApplicationResourceTreeProps, node as any)}; case NODE_TYPES.podGroup: - return {renderPodGroup(props as ApplicationResourceTreeProps, key, node as ResourceTreeNode & dagre.Node, childrenMap)}; + return ( + + {renderPodGroup(props as ApplicationResourceTreeProps, key, node as ResourceTreeNode & dagre.Node, childrenMap)} + + ); default: - return {renderResourceNode(props as ApplicationResourceTreeProps, key, node as ResourceTreeNode & dagre.Node, nodesHavingChildren)}; + return ( + + {renderResourceNode(props as ApplicationResourceTreeProps, key, node as ResourceTreeNode & dagre.Node, nodesHavingChildren)} + + ); } })} {edges.map(edge => (