Browse Source

feat(discover): Show top 5 indicator in table rows (#19685)

Visually indicate the top 5 results in the table and their corresponding color
in the graph. This relies on the fact that the top 5 results graphed correspond
to the top 5 rows in the table.
Tony 4 years ago
parent
commit
6af41afd13

+ 6 - 2
src/sentry/static/sentry/app/components/gridEditable/index.tsx

@@ -66,7 +66,9 @@ type GridEditableProps<DataRow, ColumnKey> = {
     ) => React.ReactNode;
     renderBodyCell?: (
       column: GridColumnOrder<ColumnKey>,
-      dataRow: DataRow
+      dataRow: DataRow,
+      rowIndex: number,
+      columnIndex: number
     ) => React.ReactNode;
     onResizeColumn?: (
       columnIndex: number,
@@ -331,7 +333,9 @@ class GridEditable<
           ))}
         {columnOrder.map((col, i) => (
           <GridBodyCell key={`${col.key}${i}`}>
-            {grid.renderBodyCell ? grid.renderBodyCell(col, dataRow) : dataRow[col.key]}
+            {grid.renderBodyCell
+              ? grid.renderBodyCell(col, dataRow, row, i)
+              : dataRow[col.key]}
           </GridBodyCell>
         ))}
       </GridRow>

+ 2 - 0
src/sentry/static/sentry/app/utils/discover/types.tsx

@@ -1,6 +1,8 @@
 import {t} from 'app/locale';
 import {SelectValue} from 'app/types';
 
+export const TOP_N = 5;
+
 export enum DisplayModes {
   DEFAULT = 'default',
   PREVIOUS = 'previous',

+ 2 - 2
src/sentry/static/sentry/app/views/eventsV2/resultsChart.tsx

@@ -12,7 +12,7 @@ import {getParams} from 'app/components/organizations/globalSelectionHeader/getP
 import {Panel} from 'app/components/panels';
 import getDynamicText from 'app/utils/getDynamicText';
 import EventView from 'app/utils/discover/eventView';
-import {DisplayModes} from 'app/utils/discover/types';
+import {TOP_N, DisplayModes} from 'app/utils/discover/types';
 import {decodeScalar} from 'app/utils/queryString';
 import withApi from 'app/utils/withApi';
 
@@ -82,7 +82,7 @@ class ResultsChart extends React.Component<ResultsChartProps> {
               field={isTopEvents ? apiPayload.field : undefined}
               interval={eventView.interval}
               showDaily={isDaily}
-              topEvents={isTopEvents ? 5 : undefined}
+              topEvents={isTopEvents ? TOP_N : undefined}
               orderby={isTopEvents ? decodeScalar(apiPayload.sort) : undefined}
               utc={utc === 'true'}
               confirmedQuery={confirmedQuery}

+ 45 - 9
src/sentry/static/sentry/app/views/eventsV2/table/tableView.tsx

@@ -22,6 +22,7 @@ import EventView, {
 import {Column} from 'app/utils/discover/fields';
 import {getFieldRenderer} from 'app/utils/discover/fieldRenderers';
 import {generateEventSlug, eventDetailsRouteWithEventView} from 'app/utils/discover/urls';
+import {TOP_N, DisplayModes} from 'app/utils/discover/types';
 import withProjects from 'app/utils/withProjects';
 import {tokenizeSearch, stringifyQueryObject} from 'app/utils/tokenizeSearch';
 import {transactionSummaryRouteWithQuery} from 'app/views/performance/transactionSummary/utils';
@@ -192,23 +193,36 @@ class TableView extends React.Component<TableViewProps> {
 
   _renderGridBodyCell = (
     column: TableColumn<keyof TableDataRow>,
-    dataRow: TableDataRow
+    dataRow: TableDataRow,
+    rowIndex: number,
+    columnIndex: number
   ): React.ReactNode => {
-    const {location, organization, tableData} = this.props;
+    const {eventView, location, organization, tableData} = this.props;
 
     if (!tableData || !tableData.meta) {
       return dataRow[column.key];
     }
     const fieldRenderer = getFieldRenderer(String(column.key), tableData.meta);
 
+    const isTopEvents =
+      eventView.display === DisplayModes.TOP5 ||
+      eventView.display === DisplayModes.DAILYTOP5;
+
+    const count = Math.min(tableData?.data?.length ?? TOP_N, TOP_N);
+
     return (
-      <CellAction
-        column={column}
-        dataRow={dataRow}
-        handleCellAction={this.handleCellAction(dataRow, column)}
-      >
-        {fieldRenderer(dataRow, {organization, location})}
-      </CellAction>
+      <React.Fragment>
+        {isTopEvents && rowIndex < TOP_N && columnIndex === 0 ? (
+          <TopResultsIndicator count={count} index={rowIndex} />
+        ) : null}
+        <CellAction
+          column={column}
+          dataRow={dataRow}
+          handleCellAction={this.handleCellAction(dataRow, column)}
+        >
+          {fieldRenderer(dataRow, {organization, location})}
+        </CellAction>
+      </React.Fragment>
     );
   };
 
@@ -446,4 +460,26 @@ const StyledIcon = styled(IconStack)`
   vertical-align: middle;
 `;
 
+type TopResultsIndicatorProps = {
+  count: number;
+  index: number;
+};
+
+const TopResultsIndicator = styled('div')<TopResultsIndicatorProps>`
+  position: absolute;
+  left: -1px;
+  margin-top: 4.5px;
+  width: 9px;
+  height: 15px;
+  border-radius: 0 3px 3px 0;
+
+  background-color: ${p => {
+    // this background color needs to match the colors used in
+    // app/components/charts/eventsChart so that the ordering matches
+
+    // the color pallete contains n + 2 colors, so we subtract 2 here
+    return p.theme.charts.getColorPalette(p.count - 2)[p.index];
+  }};
+`;
+
 export default withProjects(TableView);