github.com/turbot/steampipe@v1.7.0-rc.0.0.20240517123944-7cef272d4458/ui/dashboard/src/components/dashboards/hierarchies/Hierarchy/index.tsx (about)

     1  import ErrorPanel from "../../Error";
     2  import merge from "lodash/merge";
     3  import useChartThemeColors from "../../../../hooks/useChartThemeColors";
     4  import useNodeAndEdgeData from "../../common/useNodeAndEdgeData";
     5  import {
     6    buildNodesAndEdges,
     7    buildTreeDataInputs,
     8    LeafNodeData,
     9  } from "../../common";
    10  import { Chart } from "../../charts/Chart";
    11  import { getHierarchyComponent } from "..";
    12  import { HierarchyProperties, HierarchyProps, HierarchyType } from "../types";
    13  import { NodesAndEdges } from "../../common/types";
    14  import { registerComponent } from "../../index";
    15  import { useDashboard } from "../../../../hooks/useDashboard";
    16  
    17  const getCommonBaseOptions = () => ({
    18    animation: false,
    19    tooltip: {
    20      trigger: "item",
    21      triggerOn: "mousemove",
    22    },
    23  });
    24  
    25  const getCommonBaseOptionsForHierarchyType = (type: HierarchyType = "tree") => {
    26    switch (type) {
    27      default:
    28        return {};
    29    }
    30  };
    31  
    32  const getSeriesForHierarchyType = (
    33    type: HierarchyType = "tree",
    34    data: LeafNodeData | undefined,
    35    properties: HierarchyProperties | undefined,
    36    nodesAndEdges: NodesAndEdges,
    37    themeColors
    38  ) => {
    39    if (!data) {
    40      return {};
    41    }
    42    const series: any[] = [];
    43    const seriesLength = 1;
    44    for (let seriesIndex = 0; seriesIndex < seriesLength; seriesIndex++) {
    45      switch (type) {
    46        case "tree": {
    47          const { data: treeData } = buildTreeDataInputs(nodesAndEdges);
    48          series.push({
    49            type: "tree",
    50            data: treeData,
    51            top: "1%",
    52            left: "7%",
    53            bottom: "1%",
    54            right: "20%",
    55            symbolSize: 7,
    56            label: {
    57              color: themeColors.foreground,
    58              position: "left",
    59              verticalAlign: "middle",
    60              align: "right",
    61            },
    62            leaves: {
    63              label: {
    64                position: "right",
    65                verticalAlign: "middle",
    66                align: "left",
    67              },
    68            },
    69            emphasis: {
    70              focus: "descendant",
    71            },
    72            expandAndCollapse: false,
    73            animationDuration: 550,
    74            animationDurationUpdate: 750,
    75          });
    76        }
    77      }
    78    }
    79  
    80    return { series };
    81  };
    82  
    83  const getOptionOverridesForHierarchyType = (
    84    type: HierarchyType = "tree",
    85    properties: HierarchyProperties | undefined
    86  ) => {
    87    if (!properties) {
    88      return {};
    89    }
    90  
    91    return {};
    92  };
    93  
    94  const buildHierarchyOptions = (props: HierarchyProps, themeColors) => {
    95    const nodesAndEdges = buildNodesAndEdges(
    96      props.categories,
    97      props.data,
    98      props.properties,
    99      themeColors
   100    );
   101  
   102    return merge(
   103      getCommonBaseOptions(),
   104      getCommonBaseOptionsForHierarchyType(props.display_type),
   105      getSeriesForHierarchyType(
   106        props.display_type,
   107        props.data,
   108        props.properties,
   109        nodesAndEdges,
   110        themeColors
   111      ),
   112      getOptionOverridesForHierarchyType(props.display_type, props.properties)
   113    );
   114  };
   115  
   116  const HierarchyWrapper = (props: HierarchyProps) => {
   117    const themeColors = useChartThemeColors();
   118    const {
   119      themeContext: { wrapperRef },
   120    } = useDashboard();
   121  
   122    const nodeAndEdgeData = useNodeAndEdgeData(
   123      props.data,
   124      props.properties,
   125      props.status
   126    );
   127  
   128    if (!wrapperRef) {
   129      return null;
   130    }
   131  
   132    if (
   133      !nodeAndEdgeData ||
   134      !nodeAndEdgeData.data ||
   135      !nodeAndEdgeData.data.rows ||
   136      nodeAndEdgeData.data.rows.length === 0
   137    ) {
   138      return null;
   139    }
   140  
   141    return (
   142      <Chart
   143        options={buildHierarchyOptions(
   144          {
   145            ...props,
   146            categories: nodeAndEdgeData.categories,
   147            data: nodeAndEdgeData.data,
   148            properties: nodeAndEdgeData.properties,
   149          },
   150          themeColors
   151        )}
   152        type={props.display_type || "tree"}
   153      />
   154    );
   155  };
   156  
   157  const renderHierarchy = (definition: HierarchyProps) => {
   158    // We default to tree diagram if not specified
   159    const { display_type = "tree" } = definition;
   160  
   161    const hierarchy = getHierarchyComponent(display_type);
   162  
   163    if (!hierarchy) {
   164      return <ErrorPanel error={`Unknown hierarchy type ${display_type}`} />;
   165    }
   166  
   167    const Component = hierarchy.component;
   168    return <Component {...definition} />;
   169  };
   170  
   171  const RenderHierarchy = (props: HierarchyProps) => {
   172    return renderHierarchy(props);
   173  };
   174  
   175  registerComponent("hierarchy", RenderHierarchy);
   176  
   177  export default HierarchyWrapper;