Browse Source

feat(starfish): add some pagination (#50751)

1. Add pagination to modules, span summary, and span samples pages.
2. Also a bit of cleanup to make it easier to get pagination
Dominik Buszowiecki 1 year ago
parent
commit
7a4f0691f2

+ 5 - 1
static/app/utils/discover/discoverQuery.tsx

@@ -81,12 +81,16 @@ export function useDiscoverQuery(props: Omit<DiscoverQueryComponentProps, 'child
     };
   };
 
-  return useGenericDiscoverQuery<TableData, DiscoverQueryPropsWithThresholds>({
+  const res = useGenericDiscoverQuery<TableData, DiscoverQueryPropsWithThresholds>({
     route: 'events',
     shouldRefetchData,
     afterFetch,
     ...props,
   });
+
+  const pageLinks = res.response?.getResponseHeader('Link') ?? undefined;
+
+  return {...res, pageLinks};
 }
 
 export default DiscoverQuery;

+ 11 - 6
static/app/utils/discover/genericDiscoverQuery.tsx

@@ -420,16 +420,21 @@ export function useGenericDiscoverQuery<T, P>(props: Props<T, P>) {
   const url = `/organizations/${orgSlug}/${route}/`;
   const apiPayload = getPayload<T, P>(props);
 
-  return useQuery<T, QueryError>(
+  const res = useQuery<[T, string | undefined, ResponseMeta<T> | undefined], QueryError>(
     [route, apiPayload],
-    async () => {
-      const [resp] = await doDiscoverQuery<T>(api, url, apiPayload, {
+    () =>
+      doDiscoverQuery<T>(api, url, apiPayload, {
         queryBatching: props.queryBatching,
-      });
-      return resp;
-    },
+      }),
     options
   );
+
+  return {
+    ...res,
+    data: res.data?.[0] ?? undefined,
+    statusCode: res.data?.[1] ?? undefined,
+    response: res.data?.[2] ?? undefined,
+  };
 }
 
 export default GenericDiscoverQuery;

+ 2 - 2
static/app/views/starfish/queries/useSpanList.tsx

@@ -62,7 +62,7 @@ export const useSpanList = (
   );
 
   // TODO: Add referrer
-  const {isLoading, data} = useSpansQuery<SpanMetrics[]>({
+  const {isLoading, data, pageLinks} = useSpansQuery<SpanMetrics[]>({
     eventView,
     queryString: query,
     initialData: [],
@@ -71,7 +71,7 @@ export const useSpanList = (
     referrer,
   });
 
-  return {isLoading, data};
+  return {isLoading, data, pageLinks};
 };
 
 function getQuery(

+ 2 - 1
static/app/views/starfish/queries/useSpanSamples.tsx

@@ -53,6 +53,7 @@ export function useSpanSamples(
   });
 
   const data = (response.data?.data ?? []) as unknown as IndexedSpan[];
+  const pageLinks = response.pageLinks;
 
-  return {...response, data};
+  return {...response, data, pageLinks};
 }

+ 2 - 2
static/app/views/starfish/queries/useSpanTransactionMetrics.tsx

@@ -36,14 +36,14 @@ export const useSpanTransactionMetrics = (
     : '';
   const eventView = span ? getEventView(span, location, transactions ?? []) : undefined;
 
-  const {isLoading, data} = useSpansQuery<SpanTransactionMetrics[]>({
+  const {isLoading, data, pageLinks} = useSpansQuery<SpanTransactionMetrics[]>({
     eventView,
     queryString: query,
     initialData: [],
     enabled: Boolean(query),
   });
 
-  return {isLoading, data};
+  return {isLoading, data, pageLinks};
 };
 
 function getQuery(

+ 11 - 3
static/app/views/starfish/utils/useSpansQuery.tsx

@@ -15,7 +15,11 @@ import {useStarfishOptions} from 'sentry/views/starfish/utils/useStarfishOptions
 const DATE_FORMAT = 'YYYY-MM-DDTHH:mm:ss';
 
 // Setting return type since I'd rather not know if its discover query or not
-export type UseSpansQueryReturnType<T> = {data: T; isLoading: boolean};
+export type UseSpansQueryReturnType<T> = {
+  data: T;
+  isLoading: boolean;
+  pageLinks?: string;
+};
 
 export function useSpansQuery<T = any[]>({
   eventView,
@@ -152,14 +156,18 @@ export function useWrappedDiscoverQuery({
 }) {
   const location = useLocation();
   const organization = useOrganization();
-  const {isLoading, data} = useDiscoverQuery({
+  const {isLoading, data, pageLinks} = useDiscoverQuery({
     eventView,
     orgSlug: organization.slug,
     location,
     referrer,
     limit,
   });
-  return {isLoading, data: isLoading && initialData ? initialData : data?.data};
+  return {
+    isLoading,
+    data: isLoading && initialData ? initialData : data?.data,
+    pageLinks,
+  };
 }
 
 function getQueryFunction({

+ 20 - 11
static/app/views/starfish/views/spanSummaryPage/sampleList/sampleTable/sampleTable.tsx

@@ -1,5 +1,7 @@
+import {Fragment} from 'react';
 import keyBy from 'lodash/keyBy';
 
+import Pagination from 'sentry/components/pagination';
 import {SpanSamplesTable} from 'sentry/views/starfish/components/samplesTable/spanSamplesTable';
 import {useSpanMetrics} from 'sentry/views/starfish/queries/useSpanMetrics';
 import {useSpanSamples} from 'sentry/views/starfish/queries/useSpanSamples';
@@ -19,7 +21,11 @@ function SampleTable({groupId, transactionName}: Props) {
     'span-summary-panel-samples-table-p95'
   );
 
-  const {data: spans, isLoading: areSpanSamplesLoading} = useSpanSamples(
+  const {
+    data: spans,
+    isLoading: areSpanSamplesLoading,
+    pageLinks,
+  } = useSpanSamples(
     groupId,
     transactionName,
     undefined,
@@ -35,16 +41,19 @@ function SampleTable({groupId, transactionName}: Props) {
   const transactionsById = keyBy(transactions, 'id');
 
   return (
-    <SpanSamplesTable
-      data={spans.map(sample => {
-        return {
-          ...sample,
-          transaction: transactionsById[sample.transaction_id],
-        };
-      })}
-      isLoading={areSpanSamplesLoading || areTransactionsLoading}
-      p95={spanMetrics?.['p95(span.duration)']}
-    />
+    <Fragment>
+      <SpanSamplesTable
+        data={spans.map(sample => {
+          return {
+            ...sample,
+            transaction: transactionsById[sample.transaction_id],
+          };
+        })}
+        isLoading={areSpanSamplesLoading || areTransactionsLoading}
+        p95={spanMetrics?.['p95(span.duration)']}
+      />
+      <Pagination pageLinks={pageLinks} />
+    </Fragment>
   );
 }
 

+ 20 - 15
static/app/views/starfish/views/spanSummaryPage/spanTransactionsTable.tsx

@@ -6,6 +6,7 @@ import GridEditable, {
   GridColumnHeader,
 } from 'sentry/components/gridEditable';
 import Link from 'sentry/components/links/link';
+import Pagination from 'sentry/components/pagination';
 import Truncate from 'sentry/components/truncate';
 import {useLocation} from 'sentry/utils/useLocation';
 import DurationCell from 'sentry/views/starfish/components/tableCells/durationCell';
@@ -45,10 +46,11 @@ export function SpanTransactionsTable({
 }: Props) {
   const location = useLocation();
 
-  const {data: spanTransactionMetrics, isLoading} = useSpanTransactionMetrics(
-    span,
-    endpoint ? [endpoint] : undefined
-  );
+  const {
+    data: spanTransactionMetrics,
+    isLoading,
+    pageLinks,
+  } = useSpanTransactionMetrics(span, endpoint ? [endpoint] : undefined);
 
   const spanTransactionsWithMetrics = spanTransactionMetrics.map(row => {
     return {
@@ -75,17 +77,20 @@ export function SpanTransactionsTable({
   };
 
   return (
-    <GridEditable
-      isLoading={isLoading}
-      data={spanTransactionsWithMetrics}
-      columnOrder={COLUMN_ORDER}
-      columnSortBy={[]}
-      grid={{
-        renderHeadCell,
-        renderBodyCell,
-      }}
-      location={location}
-    />
+    <Fragment>
+      <GridEditable
+        isLoading={isLoading}
+        data={spanTransactionsWithMetrics}
+        columnOrder={COLUMN_ORDER}
+        columnSortBy={[]}
+        grid={{
+          renderHeadCell,
+          renderBodyCell,
+        }}
+        location={location}
+      />
+      <Pagination pageLinks={pageLinks} />
+    </Fragment>
   );
 }
 

+ 30 - 17
static/app/views/starfish/views/spans/spansTable.tsx

@@ -1,3 +1,4 @@
+import {Fragment} from 'react';
 import styled from '@emotion/styled';
 import {urlEncode} from '@sentry/utils';
 
@@ -7,22 +8,24 @@ import GridEditable, {
 } from 'sentry/components/gridEditable';
 import SortLink from 'sentry/components/gridEditable/sortLink';
 import Link from 'sentry/components/links/link';
+import Pagination from 'sentry/components/pagination';
 import {useLocation} from 'sentry/utils/useLocation';
 import {TableColumnSort} from 'sentry/views/discover/table/types';
 import DurationCell from 'sentry/views/starfish/components/tableCells/durationCell';
 import ThroughputCell from 'sentry/views/starfish/components/tableCells/throughputCell';
 import {TimeSpentCell} from 'sentry/views/starfish/components/tableCells/timeSpentCell';
+import {useSpanList} from 'sentry/views/starfish/queries/useSpanList';
 import {ModuleName} from 'sentry/views/starfish/types';
 import {DataTitles} from 'sentry/views/starfish/views/spans/types';
 
 type Props = {
-  isLoading: boolean;
   moduleName: ModuleName;
   onSetOrderBy: (orderBy: string) => void;
   orderBy: string;
-  spansData: SpanDataRow[];
   columnOrder?: TableColumnHeader[];
   endpoint?: string;
+  limit?: number;
+  spanCategory?: string;
 };
 
 export type SpanDataRow = {
@@ -51,29 +54,39 @@ export type TableColumnHeader = GridColumnHeader<Keys>;
 
 export default function SpansTable({
   moduleName,
-  spansData,
   orderBy,
   onSetOrderBy,
-  isLoading,
   columnOrder,
+  spanCategory,
   endpoint,
+  limit = 25,
 }: Props) {
   const location = useLocation();
+  const {isLoading, data, pageLinks} = useSpanList(
+    moduleName ?? ModuleName.ALL,
+    undefined,
+    spanCategory,
+    orderBy,
+    limit
+  );
 
   return (
-    <GridEditable
-      isLoading={isLoading}
-      data={spansData}
-      columnOrder={columnOrder ?? getColumns(moduleName)}
-      columnSortBy={
-        orderBy ? [] : [{key: orderBy, order: 'desc'} as TableColumnSort<Keys>]
-      }
-      grid={{
-        renderHeadCell: getRenderHeadCell(orderBy, onSetOrderBy),
-        renderBodyCell: (column, row) => renderBodyCell(column, row, endpoint),
-      }}
-      location={location}
-    />
+    <Fragment>
+      <GridEditable
+        isLoading={isLoading}
+        data={data}
+        columnOrder={columnOrder ?? getColumns(moduleName)}
+        columnSortBy={
+          orderBy ? [] : [{key: orderBy, order: 'desc'} as TableColumnSort<Keys>]
+        }
+        grid={{
+          renderHeadCell: getRenderHeadCell(orderBy, onSetOrderBy),
+          renderBodyCell: (column, row) => renderBodyCell(column, row, endpoint),
+        }}
+        location={location}
+      />
+      <Pagination pageLinks={pageLinks} />
+    </Fragment>
   );
 }
 

+ 2 - 11
static/app/views/starfish/views/spans/spansView.tsx

@@ -4,7 +4,6 @@ import styled from '@emotion/styled';
 import DatePageFilter from 'sentry/components/datePageFilter';
 import {space} from 'sentry/styles/space';
 import {useLocation} from 'sentry/utils/useLocation';
-import {useSpanList} from 'sentry/views/starfish/queries/useSpanList';
 import {ModuleName} from 'sentry/views/starfish/types';
 import {ActionSelector} from 'sentry/views/starfish/views/spans/selectors/actionSelector';
 import {DomainSelector} from 'sentry/views/starfish/views/spans/selectors/domainSelector';
@@ -38,14 +37,6 @@ export default function SpansView(props: Props) {
 
   const {orderBy} = state;
 
-  const {isLoading: areSpansLoading, data: spansData} = useSpanList(
-    props.moduleName ?? ModuleName.ALL,
-    undefined,
-    props.spanCategory,
-    orderBy,
-    LIMIT
-  );
-
   return (
     <Fragment>
       <FilterOptionsContainer>
@@ -77,10 +68,10 @@ export default function SpansView(props: Props) {
       <PaddedContainer>
         <SpansTable
           moduleName={props.moduleName || ModuleName.ALL}
-          isLoading={areSpansLoading}
-          spansData={spansData}
           orderBy={orderBy}
+          spanCategory={props.spanCategory}
           onSetOrderBy={newOrderBy => setState({orderBy: newOrderBy})}
+          limit={LIMIT}
         />
       </PaddedContainer>
     </Fragment>

Some files were not shown because too many files changed in this diff