Browse Source

ref(ui): Convert metric alert related transactions to funcional (#53486)

Scott Cooper 1 year ago
parent
commit
66dddf7169

+ 68 - 108
static/app/views/alerts/rules/metric/details/relatedTransactions.tsx

@@ -1,4 +1,4 @@
-import {Component, Fragment} from 'react';
+import {useState} from 'react';
 import styled from '@emotion/styled';
 import type {Location} from 'history';
 
@@ -8,12 +8,11 @@ import GridEditable, {
 } from 'sentry/components/gridEditable';
 import type {Alignments} from 'sentry/components/gridEditable/sortLink';
 import Link from 'sentry/components/links/link';
-import {Organization, Project} from 'sentry/types';
+import type {Organization, Project} from 'sentry/types';
 import DiscoverQuery, {
   TableData,
   TableDataRow,
 } from 'sentry/utils/discover/discoverQuery';
-import EventView from 'sentry/utils/discover/eventView';
 import {getFieldRenderer} from 'sentry/utils/discover/fieldRenderers';
 import {fieldAlignment} from 'sentry/utils/discover/fields';
 import type {MetricRule} from 'sentry/views/alerts/rules/metric/types';
@@ -24,29 +23,36 @@ import {getProjectID} from 'sentry/views/performance/utils';
 
 import type {TimePeriodType} from './constants';
 
-type TableProps = {
-  eventView: EventView;
+interface RelatedTransactionsProps {
+  filter: string;
   location: Location;
   organization: Organization;
   projects: Project[];
-  summaryConditions: string;
-};
-
-type TableState = {
-  widths: number[];
-};
-class Table extends Component<TableProps, TableState> {
-  state: TableState = {
-    widths: [],
-  };
+  rule: MetricRule;
+  timePeriod: TimePeriodType;
+}
 
-  renderBodyCell(
+function RelatedTransactions({
+  organization,
+  projects,
+  timePeriod,
+  rule,
+  filter,
+  location,
+}: RelatedTransactionsProps) {
+  const [widths, setWidths] = useState<number[]>([]);
+  const eventView = getMetricRuleDiscoverQuery({
+    rule,
+    timePeriod,
+    projects,
+  });
+  const summaryConditions = `${rule.query} ${filter}`;
+
+  function renderBodyCell(
     tableData: TableData | null,
     column: TableColumn<keyof TableDataRow>,
     dataRow: TableDataRow
   ): React.ReactNode {
-    const {eventView, organization, projects, location, summaryConditions} = this.props;
-
     if (!tableData || !tableData.meta) {
       return dataRow[column.key];
     }
@@ -58,7 +64,7 @@ class Table extends Component<TableProps, TableState> {
 
     if (field === 'transaction') {
       const projectID = getProjectID(dataRow, projects);
-      const summaryView = eventView.clone();
+      const summaryView = eventView!.clone();
       summaryView.query = summaryConditions;
 
       const target = transactionSummaryRouteWithQuery({
@@ -74,14 +80,14 @@ class Table extends Component<TableProps, TableState> {
     return rendered;
   }
 
-  renderBodyCellWithData = (tableData: TableData | null) => {
+  const renderBodyCellWithData = (tableData: TableData | null) => {
     return (
       column: TableColumn<keyof TableDataRow>,
       dataRow: TableDataRow
-    ): React.ReactNode => this.renderBodyCell(tableData, column, dataRow);
+    ): React.ReactNode => renderBodyCell(tableData, column, dataRow);
   };
 
-  renderHeadCell(
+  function renderHeadCell(
     tableMeta: TableData['meta'],
     column: TableColumn<keyof TableDataRow>,
     title: React.ReactNode
@@ -92,107 +98,61 @@ class Table extends Component<TableProps, TableState> {
     return <HeaderCell align={align}>{title || field.field}</HeaderCell>;
   }
 
-  renderHeadCellWithMeta = (tableMeta: TableData['meta'], columnName: string) => {
+  const renderHeadCellWithMeta = (tableMeta: TableData['meta'], columnName: string) => {
     const columnTitles = ['transactions', 'project', columnName, 'users', 'user misery'];
 
     return (column: TableColumn<keyof TableDataRow>, index: number): React.ReactNode =>
-      this.renderHeadCell(tableMeta, column, columnTitles[index]);
+      renderHeadCell(tableMeta, column, columnTitles[index]);
   };
 
-  handleResizeColumn = (columnIndex: number, nextColumn: GridColumn) => {
-    const widths: number[] = [...this.state.widths];
-    widths[columnIndex] = nextColumn.width
+  const handleResizeColumn = (columnIndex: number, nextColumn: GridColumn) => {
+    const newWidths: number[] = [...widths];
+    newWidths[columnIndex] = nextColumn.width
       ? Number(nextColumn.width)
       : COL_WIDTH_UNDEFINED;
-    this.setState({widths});
+    setWidths(newWidths);
   };
 
-  getSortedEventView() {
-    const {eventView} = this.props;
-    return eventView.withSorts([...eventView.sorts]);
-  }
-
-  render() {
-    const {eventView, organization, location} = this.props;
-
-    const {widths} = this.state;
-    const columnOrder = eventView
-      .getColumns()
-      .map((col: TableColumn<React.ReactText>, i: number) => {
-        if (typeof widths[i] === 'number') {
-          return {...col, width: widths[i]};
-        }
-        return col;
-      });
-
-    const sortedEventView = this.getSortedEventView();
-    const columnSortBy = sortedEventView.getSorts();
-
-    return (
-      <Fragment>
-        <DiscoverQuery
-          eventView={sortedEventView}
-          orgSlug={organization.slug}
-          location={location}
-        >
-          {({isLoading, tableData}) => (
-            <GridEditable
-              isLoading={isLoading}
-              data={tableData ? tableData.data.slice(0, 5) : []}
-              columnOrder={columnOrder}
-              columnSortBy={columnSortBy}
-              grid={{
-                onResizeColumn: this.handleResizeColumn,
-                renderHeadCell: this.renderHeadCellWithMeta(
-                  tableData?.meta,
-                  columnOrder[2].name as string
-                ) as any,
-                renderBodyCell: this.renderBodyCellWithData(tableData) as any,
-              }}
-              location={location}
-            />
-          )}
-        </DiscoverQuery>
-      </Fragment>
-    );
-  }
-}
-
-interface Props {
-  filter: string;
-  location: Location;
-  organization: Organization;
-  projects: Project[];
-  rule: MetricRule;
-  timePeriod: TimePeriodType;
-}
-
-function RelatedTransactions({
-  rule,
-  projects,
-  filter,
-  location,
-  organization,
-  timePeriod,
-}: Props) {
-  const eventView = getMetricRuleDiscoverQuery({
-    rule,
-    timePeriod,
-    projects,
-  });
-
   if (!eventView) {
     return null;
   }
 
+  const columnOrder = eventView
+    .getColumns()
+    .map((col: TableColumn<React.ReactText>, i: number) => {
+      if (typeof widths[i] === 'number') {
+        return {...col, width: widths[i]};
+      }
+      return col;
+    });
+
+  const sortedEventView = eventView.withSorts([...eventView.sorts]);
+  const columnSortBy = sortedEventView.getSorts();
+
   return (
-    <Table
-      eventView={eventView}
-      projects={projects}
-      organization={organization}
+    <DiscoverQuery
+      eventView={sortedEventView}
+      orgSlug={organization.slug}
       location={location}
-      summaryConditions={`${rule.query} ${filter}`}
-    />
+    >
+      {({isLoading, tableData}) => (
+        <GridEditable
+          isLoading={isLoading}
+          data={tableData ? tableData.data.slice(0, 5) : []}
+          columnOrder={columnOrder}
+          columnSortBy={columnSortBy}
+          grid={{
+            onResizeColumn: handleResizeColumn,
+            renderHeadCell: renderHeadCellWithMeta(
+              tableData?.meta,
+              columnOrder[2]!.name
+            ) as any,
+            renderBodyCell: renderBodyCellWithData(tableData) as any,
+          }}
+          location={location}
+        />
+      )}
+    </DiscoverQuery>
   );
 }
 

+ 3 - 2
static/app/views/alerts/utils/getMetricRuleDiscoverUrl.spec.tsx

@@ -1,5 +1,6 @@
 import {Dataset} from 'sentry/views/alerts/rules/metric/types';
-import {getMetricRuleDiscoverQuery} from 'sentry/views/alerts/utils/getMetricRuleDiscoverUrl';
+
+import {getMetricRuleDiscoverQuery} from './getMetricRuleDiscoverUrl';
 
 describe('getMetricRuleDiscoverQuery', () => {
   it('should use metric aggregate in discover query', () => {
@@ -18,7 +19,7 @@ describe('getMetricRuleDiscoverQuery', () => {
         end: new Date().toISOString(),
       },
     });
-    expect(query.valueOf()).toEqual(
+    expect(query!.valueOf()).toEqual(
       expect.objectContaining({
         statsPeriod: '7d',
         fields: [

+ 1 - 1
static/app/views/alerts/utils/getMetricRuleDiscoverUrl.tsx

@@ -48,7 +48,7 @@ export function getMetricRuleDiscoverQuery({
   extraQueryParams,
 }: Omit<MetricRuleDiscoverUrlOptions, 'orgSlug'>) {
   if (!projects || !projects.length || !rule) {
-    return '';
+    return null;
   }
 
   const aggregateAlias = getAggregateAlias(rule.aggregate);