{"version":3,"file":"FlameGraphTopTableContainer.mjs","sources":["../../../src/TopTable/FlameGraphTopTableContainer.tsx"],"sourcesContent":["import { css } from '@emotion/css';\nimport { memo, useMemo, useState } from 'react';\nimport AutoSizer from 'react-virtualized-auto-sizer';\n\nimport {\n  applyFieldOverrides,\n  DataFrame,\n  DataLinkClickEvent,\n  Field,\n  FieldType,\n  GrafanaTheme2,\n  MappingType,\n} from '@grafana/data';\nimport {\n  IconButton,\n  Table,\n  TableCellDisplayMode,\n  TableCustomCellOptions,\n  TableFieldOptions,\n  TableSortByFieldState,\n  useStyles2,\n  useTheme2,\n} from '@grafana/ui';\n\nimport { diffColorBlindColors, diffDefaultColors } from '../FlameGraph/colors';\nimport { FlameGraphDataContainer } from '../FlameGraph/dataTransform';\nimport { TOP_TABLE_COLUMN_WIDTH } from '../constants';\nimport { ColorScheme, ColorSchemeDiff, TableData } from '../types';\n\ntype Props = {\n  data: FlameGraphDataContainer;\n  onSymbolClick: (symbol: string) => void;\n  // This is used for highlighting the search button in case there is exact match.\n  search?: string;\n  // We use these to filter out rows in the table if users is doing text search.\n  matchedLabels?: Set<string>;\n  sandwichItem?: string;\n  onSearch: (str: string) => void;\n  onSandwich: (str?: string) => void;\n  onTableSort?: (sort: string) => void;\n  colorScheme: ColorScheme | ColorSchemeDiff;\n};\n\nconst FlameGraphTopTableContainer = memo(\n  ({\n    data,\n    onSymbolClick,\n    search,\n    matchedLabels,\n    onSearch,\n    sandwichItem,\n    onSandwich,\n    onTableSort,\n    colorScheme,\n  }: Props) => {\n    const table = useMemo(() => {\n      // Group the data by label, we show only one row per label and sum the values\n      // TODO: should be by filename + funcName + linenumber?\n      let filteredTable: { [key: string]: TableData } = {};\n      for (let i = 0; i < data.data.length; i++) {\n        const value = data.getValue(i);\n        const valueRight = data.getValueRight(i);\n        const self = data.getSelf(i);\n        const label = data.getLabel(i);\n\n        // If user is doing text search we filter out labels in the same way we highlight them in flame graph.\n        if (!matchedLabels || matchedLabels.has(label)) {\n          filteredTable[label] = filteredTable[label] || {};\n          filteredTable[label].self = filteredTable[label].self ? filteredTable[label].self + self : self;\n          filteredTable[label].total = filteredTable[label].total ? filteredTable[label].total + value : value;\n          filteredTable[label].totalRight = filteredTable[label].totalRight\n            ? filteredTable[label].totalRight + valueRight\n            : valueRight;\n        }\n      }\n      return filteredTable;\n    }, [data, matchedLabels]);\n\n    const styles = useStyles2(getStyles);\n    const theme = useTheme2();\n\n    const [sort, setSort] = useState<TableSortByFieldState[]>([{ displayName: 'Self', desc: true }]);\n\n    return (\n      <div className={styles.topTableContainer} data-testid=\"topTable\">\n        <AutoSizer style={{ width: '100%' }}>\n          {({ width, height }) => {\n            if (width < 3 || height < 3) {\n              return null;\n            }\n\n            const frame = buildTableDataFrame(\n              data,\n              table,\n              width,\n              onSymbolClick,\n              onSearch,\n              onSandwich,\n              theme,\n              colorScheme,\n              search,\n              sandwichItem\n            );\n            return (\n              <Table\n                initialSortBy={sort}\n                onSortByChange={(s) => {\n                  if (s && s.length) {\n                    onTableSort?.(s[0].displayName + '_' + (s[0].desc ? 'desc' : 'asc'));\n                  }\n                  setSort(s);\n                }}\n                data={frame}\n                width={width}\n                height={height}\n              />\n            );\n          }}\n        </AutoSizer>\n      </div>\n    );\n  }\n);\n\nFlameGraphTopTableContainer.displayName = 'FlameGraphTopTableContainer';\n\nfunction buildTableDataFrame(\n  data: FlameGraphDataContainer,\n  table: { [key: string]: TableData },\n  width: number,\n  onSymbolClick: (str: string) => void,\n  onSearch: (str: string) => void,\n  onSandwich: (str?: string) => void,\n  theme: GrafanaTheme2,\n  colorScheme: ColorScheme | ColorSchemeDiff,\n  search?: string,\n  sandwichItem?: string\n): DataFrame {\n  const actionField: Field = createActionField(onSandwich, onSearch, search, sandwichItem);\n\n  const symbolField: Field = {\n    type: FieldType.string,\n    name: 'Symbol',\n    values: [],\n    config: {\n      custom: { width: width - actionColumnWidth - TOP_TABLE_COLUMN_WIDTH * 2 },\n      links: [\n        {\n          title: 'Highlight symbol',\n          url: '',\n          onClick: (e: DataLinkClickEvent) => {\n            const field: Field = e.origin.field;\n            const value = field.values[e.origin.rowIndex];\n            onSymbolClick(value);\n          },\n        },\n      ],\n    },\n  };\n\n  let frame;\n\n  if (data.isDiffFlamegraph()) {\n    symbolField.config.custom.width = width - actionColumnWidth - TOP_TABLE_COLUMN_WIDTH * 3;\n\n    const baselineField = createNumberField('Baseline', 'percent');\n    const comparisonField = createNumberField('Comparison', 'percent');\n    const diffField = createNumberField('Diff', 'percent');\n    diffField.config.custom.cellOptions.type = TableCellDisplayMode.ColorText;\n\n    const [removeColor, addColor] =\n      colorScheme === ColorSchemeDiff.DiffColorBlind\n        ? [diffColorBlindColors[0], diffColorBlindColors[2]]\n        : [diffDefaultColors[0], diffDefaultColors[2]];\n\n    diffField.config.mappings = [\n      { type: MappingType.ValueToText, options: { [Infinity]: { text: 'new', color: addColor } } },\n      { type: MappingType.ValueToText, options: { [-100]: { text: 'removed', color: removeColor } } },\n      { type: MappingType.RangeToText, options: { from: 0, to: Infinity, result: { color: addColor } } },\n      { type: MappingType.RangeToText, options: { from: -Infinity, to: 0, result: { color: removeColor } } },\n    ];\n\n    // For this we don't really consider sandwich view even though you can switch it on.\n    const levels = data.getLevels();\n    const totalTicks = levels.length ? levels[0][0].value : 0;\n    const totalTicksRight = levels.length ? levels[0][0].valueRight : undefined;\n\n    for (let key in table) {\n      actionField.values.push(null);\n      symbolField.values.push(key);\n\n      const ticksLeft = table[key].total;\n      const ticksRight = table[key].totalRight;\n\n      // We are iterating over table of the data so totalTicksRight needs to be defined\n      const totalTicksLeft = totalTicks - totalTicksRight!;\n\n      const percentageLeft = Math.round((10000 * ticksLeft) / totalTicksLeft) / 100;\n      const percentageRight = Math.round((10000 * ticksRight) / totalTicksRight!) / 100;\n\n      const diff = ((percentageRight - percentageLeft) / percentageLeft) * 100;\n\n      diffField.values.push(diff);\n      baselineField.values.push(percentageLeft);\n      comparisonField.values.push(percentageRight);\n    }\n\n    frame = {\n      fields: [actionField, symbolField, baselineField, comparisonField, diffField],\n      length: symbolField.values.length,\n    };\n  } else {\n    const selfField = createNumberField('Self', data.selfField.config.unit);\n    const totalField = createNumberField('Total', data.valueField.config.unit);\n\n    for (let key in table) {\n      actionField.values.push(null);\n      symbolField.values.push(key);\n      selfField.values.push(table[key].self);\n      totalField.values.push(table[key].total);\n    }\n\n    frame = { fields: [actionField, symbolField, selfField, totalField], length: symbolField.values.length };\n  }\n\n  const dataFrames = applyFieldOverrides({\n    data: [frame],\n    fieldConfig: {\n      defaults: {},\n      overrides: [],\n    },\n    replaceVariables: (value: string) => value,\n    theme,\n  });\n\n  return dataFrames[0];\n}\n\nfunction createNumberField(name: string, unit?: string): Field {\n  const tableFieldOptions: TableFieldOptions = {\n    width: TOP_TABLE_COLUMN_WIDTH,\n    align: 'auto',\n    inspect: false,\n    cellOptions: { type: TableCellDisplayMode.Auto },\n  };\n\n  return {\n    type: FieldType.number,\n    name,\n    values: [],\n    config: {\n      unit,\n      custom: tableFieldOptions,\n    },\n  };\n}\n\nconst actionColumnWidth = 61;\n\nfunction createActionField(\n  onSandwich: (str?: string) => void,\n  onSearch: (str: string) => void,\n  search?: string,\n  sandwichItem?: string\n): Field {\n  const options: TableCustomCellOptions = {\n    type: TableCellDisplayMode.Custom,\n    cellComponent: (props) => {\n      return (\n        <ActionCell\n          frame={props.frame}\n          onSandwich={onSandwich}\n          onSearch={onSearch}\n          search={search}\n          sandwichItem={sandwichItem}\n          rowIndex={props.rowIndex}\n        />\n      );\n    },\n  };\n\n  const actionFieldTableConfig: TableFieldOptions = {\n    filterable: false,\n    width: actionColumnWidth,\n    hideHeader: true,\n    inspect: false,\n    align: 'auto',\n    cellOptions: options,\n  };\n\n  return {\n    type: FieldType.number,\n    name: 'actions',\n    values: [],\n    config: {\n      custom: actionFieldTableConfig,\n    },\n  };\n}\n\ntype ActionCellProps = {\n  frame: DataFrame;\n  rowIndex: number;\n  search?: string;\n  sandwichItem?: string;\n  onSearch: (symbol: string) => void;\n  onSandwich: (symbol: string) => void;\n};\n\nfunction ActionCell(props: ActionCellProps) {\n  const styles = getStylesActionCell();\n  const symbol = props.frame.fields.find((f: Field) => f.name === 'Symbol')?.values[props.rowIndex];\n  const isSearched = props.search === symbol;\n  const isSandwiched = props.sandwichItem === symbol;\n\n  return (\n    <div className={styles.actionCellWrapper}>\n      <IconButton\n        className={styles.actionCellButton}\n        name={'search'}\n        variant={isSearched ? 'primary' : 'secondary'}\n        tooltip={isSearched ? 'Clear from search' : 'Search for symbol'}\n        aria-label={isSearched ? 'Clear from search' : 'Search for symbol'}\n        onClick={() => {\n          props.onSearch(isSearched ? '' : symbol);\n        }}\n      />\n      <IconButton\n        className={styles.actionCellButton}\n        name={'gf-show-context'}\n        tooltip={isSandwiched ? 'Remove from sandwich view' : 'Show in sandwich view'}\n        variant={isSandwiched ? 'primary' : 'secondary'}\n        aria-label={isSandwiched ? 'Remove from sandwich view' : 'Show in sandwich view'}\n        onClick={() => {\n          props.onSandwich(isSandwiched ? undefined : symbol);\n        }}\n      />\n    </div>\n  );\n}\n\nconst getStyles = (theme: GrafanaTheme2) => {\n  return {\n    topTableContainer: css({\n      label: 'topTableContainer',\n      padding: theme.spacing(1),\n      backgroundColor: theme.colors.background.secondary,\n      height: '100%',\n    }),\n  };\n};\n\nconst getStylesActionCell = () => {\n  return {\n    actionCellWrapper: css({\n      label: 'actionCellWrapper',\n      display: 'flex',\n      height: '24px',\n    }),\n    actionCellButton: css({\n      label: 'actionCellButton',\n      marginRight: 0,\n      width: '24px',\n    }),\n  };\n};\n\nexport default FlameGraphTopTableContainer;\n"],"names":[],"mappings":"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"}