Browse Source

feat(ddm): table sort url peristence (#57807)

Ogi 1 year ago
parent
commit
1eec5323dd

+ 5 - 0
static/app/views/ddm/constants.tsx

@@ -1,3 +1,8 @@
 export const DDM_CHART_GROUP = 'ddm_chart_group';
 
 export const MIN_WIDGET_WIDTH = 400;
+
+export const DEFAULT_SORT_STATE = {
+  name: 'name',
+  order: 'asc',
+};

+ 1 - 0
static/app/views/ddm/metricsExplorer.tsx

@@ -15,6 +15,7 @@ export default function MetricsExplorer() {
     powerUserMode: true,
     showSummaryTable: true,
     onChange: () => {},
+    sort: {name: 'name', order: 'asc'},
   });
 
   return (

+ 26 - 30
static/app/views/ddm/summaryTable.tsx

@@ -1,4 +1,4 @@
-import {Fragment, useCallback, useState} from 'react';
+import {Fragment, useCallback} from 'react';
 import styled from '@emotion/styled';
 import colorFn from 'color';
 
@@ -13,63 +13,59 @@ import {formatMetricsUsingUnitAndOp, getNameFromMRI} from 'sentry/utils/metrics'
 import useOrganization from 'sentry/utils/useOrganization';
 import usePageFilters from 'sentry/utils/usePageFilters';
 import useRouter from 'sentry/utils/useRouter';
-import {Series} from 'sentry/views/ddm/widget';
+import {DEFAULT_SORT_STATE} from 'sentry/views/ddm/constants';
+import {MetricWidgetDisplayConfig, Series} from 'sentry/views/ddm/widget';
 import {transactionSummaryRouteWithQuery} from 'sentry/views/performance/transactionSummary/utils';
 
-type SortState = {
-  name: 'name' | 'avg' | 'min' | 'max' | 'sum';
-  order: 'asc' | 'desc';
-};
-
-const DEFAULT_SORT_STATE: SortState = {
-  name: 'name',
-  order: 'asc',
-};
+type SortState = MetricWidgetDisplayConfig['sort'];
 
 export function SummaryTable({
   series,
   operation,
-  onClick,
+  onRowClick,
+  onSortChange,
+  sort = DEFAULT_SORT_STATE as SortState,
   setHoveredLegend,
 }: {
-  onClick: (seriesName: string) => void;
+  onRowClick: (seriesName: string) => void;
+  onSortChange: (sortState: SortState) => void;
   series: Series[];
   setHoveredLegend: React.Dispatch<React.SetStateAction<string>> | undefined;
   operation?: string;
+  sort?: SortState;
 }) {
   const {selection} = usePageFilters();
   const {slug} = useOrganization();
-  const [sortState, setSortState] = useState<SortState>(DEFAULT_SORT_STATE);
 
   const hasActions = series.some(s => s.release || s.transaction);
 
   const router = useRouter();
   const {start, end, statsPeriod, project, environment} = router.location.query;
 
-  const sort = useCallback(
+  const changeSort = useCallback(
     (name: SortState['name']) => {
-      if (sortState.name === name) {
-        if (sortState.order === 'desc') {
-          setSortState(DEFAULT_SORT_STATE);
-        } else if (sortState.order === 'asc') {
-          setSortState({
+      if (sort.name === name) {
+        if (sort.order === 'desc') {
+          onSortChange(DEFAULT_SORT_STATE as SortState);
+        } else if (sort.order === 'asc') {
+          onSortChange({
             name,
             order: 'desc',
           });
         } else {
-          setSortState({
+          onSortChange({
             name,
             order: 'asc',
           });
         }
       } else {
-        setSortState({
+        onSortChange({
           name,
           order: 'asc',
         });
       }
     },
-    [sortState]
+    [sort, onSortChange]
   );
 
   const releaseTo = (release: string) => {
@@ -112,7 +108,7 @@ export function SummaryTable({
       };
     })
     .sort((a, b) => {
-      const {name, order} = sortState;
+      const {name, order} = sort;
 
       if (name === 'name') {
         return order === 'asc'
@@ -128,19 +124,19 @@ export function SummaryTable({
   return (
     <SummaryTableWrapper hasActions={hasActions}>
       <HeaderCell disabled />
-      <SortableHeaderCell onClick={sort} sortState={sortState} name="name">
+      <SortableHeaderCell onClick={changeSort} sortState={sort} name="name">
         {t('Name')}
       </SortableHeaderCell>
-      <SortableHeaderCell onClick={sort} sortState={sortState} name="avg" right>
+      <SortableHeaderCell onClick={changeSort} sortState={sort} name="avg" right>
         {t('Avg')}
       </SortableHeaderCell>
-      <SortableHeaderCell onClick={sort} sortState={sortState} name="min" right>
+      <SortableHeaderCell onClick={changeSort} sortState={sort} name="min" right>
         {t('Min')}
       </SortableHeaderCell>
-      <SortableHeaderCell onClick={sort} sortState={sortState} name="max" right>
+      <SortableHeaderCell onClick={changeSort} sortState={sort} name="max" right>
         {t('Max')}
       </SortableHeaderCell>
-      <SortableHeaderCell onClick={sort} sortState={sortState} name="sum" right>
+      <SortableHeaderCell onClick={changeSort} sortState={sort} name="sum" right>
         {t('Sum')}
       </SortableHeaderCell>
       {hasActions && (
@@ -166,7 +162,7 @@ export function SummaryTable({
           return (
             <Fragment key={seriesName}>
               <CellWrapper
-                onClick={() => onClick(seriesName)}
+                onClick={() => onRowClick(seriesName)}
                 onMouseEnter={() => setHoveredLegend?.(seriesName)}
                 onMouseLeave={() => setHoveredLegend?.('')}
               >

+ 15 - 2
static/app/views/ddm/widget.tsx

@@ -31,7 +31,12 @@ import {MetricChart} from 'sentry/views/ddm/chart';
 import {QueryBuilder} from 'sentry/views/ddm/queryBuilder';
 import {SummaryTable} from 'sentry/views/ddm/summaryTable';
 
-import {MIN_WIDGET_WIDTH} from './constants';
+import {DEFAULT_SORT_STATE, MIN_WIDGET_WIDTH} from './constants';
+
+type SortState = {
+  name: 'name' | 'avg' | 'min' | 'max' | 'sum';
+  order: 'asc' | 'desc';
+};
 
 const emptyWidget = {
   mri: '',
@@ -39,12 +44,14 @@ const emptyWidget = {
   query: '',
   groupBy: [],
   displayType: defaultMetricDisplayType,
+  sort: DEFAULT_SORT_STATE,
 };
 
 export type MetricWidgetDisplayConfig = {
   displayType: MetricDisplayType;
   onChange: (data: Partial<MetricWidgetProps>) => void;
   position: number;
+  sort: SortState;
   focusedSeries?: string;
   powerUserMode?: boolean;
   showSummaryTable?: boolean;
@@ -72,6 +79,7 @@ export function useMetricWidgets() {
         showSummaryTable: widget.showSummaryTable ?? true, // temporary default
         position: widget.position ?? i,
         powerUserMode: widget.powerUserMode,
+        sort: widget.sort ?? DEFAULT_SORT_STATE,
       };
     }
   );
@@ -157,6 +165,7 @@ function MetricWidgetBody({
   onChange,
   displayType,
   focusedSeries,
+  sort,
   ...metricsQuery
 }: MetricWidgetProps & PageFilters) {
   const {mri, op, query, groupBy, projects, environments, datetime} = metricsQuery;
@@ -226,8 +235,12 @@ function MetricWidgetBody({
       {metricsQuery.showSummaryTable && (
         <SummaryTable
           series={chartSeries}
+          onSortChange={newSort => {
+            onChange({sort: newSort});
+          }}
+          sort={sort}
           operation={metricsQuery.op}
-          onClick={toggleSeriesVisibility}
+          onRowClick={toggleSeriesVisibility}
           setHoveredLegend={focusedSeries ? undefined : setHoveredLegend}
         />
       )}