Browse Source

feat(replays): Add sorting timestamp (#33658)

### Description

- Add sorting in the Replay Index for the "Timestamp" column:

Closes #33275 

### Screenshots

<img width="707" alt="163623319-e9a8bbff-db8b-4d49-8a0f-1b0a51dca8c7" src="https://user-images.githubusercontent.com/14813235/163816903-4c289fdd-90f7-430e-b151-ab03dba04245.png">
Daian Scuarissi 2 years ago
parent
commit
2a9eae302a
1 changed files with 55 additions and 4 deletions
  1. 55 4
      static/app/views/replays/replays.tsx

+ 55 - 4
static/app/views/replays/replays.tsx

@@ -11,7 +11,7 @@ import PageHeading from 'sentry/components/pageHeading';
 import Pagination from 'sentry/components/pagination';
 import {PanelTable} from 'sentry/components/panels';
 import TimeSince from 'sentry/components/timeSince';
-import {IconCalendar} from 'sentry/icons';
+import {IconArrow, IconCalendar} from 'sentry/icons';
 import {t} from 'sentry/locale';
 import {PageContent, PageHeader} from 'sentry/styles/organization';
 import space from 'sentry/styles/space';
@@ -37,12 +37,14 @@ type Props = AsyncView['props'] &
 class Replays extends React.Component<Props> {
   getEventView() {
     const {location, selection} = this.props;
+    const {query} = location;
+
     const eventQueryParams: NewQuery = {
       id: '',
       name: '',
       version: 2,
       fields: ['eventID', 'project', 'timestamp', 'user.display', 'url'],
-      orderby: '-timestamp',
+      orderby: query.sort || '-timestamp',
       environment: selection.environments,
       projects: selection.projects,
       query: 'transaction:sentry-replay', // future: change to replay event
@@ -105,7 +107,19 @@ class Replays extends React.Component<Props> {
   }
 
   render() {
-    const {organization} = this.props;
+    const {organization, location} = this.props;
+    const {query} = location;
+    const {cursor: _cursor, page: _page, ...currentQuery} = query;
+
+    const sort: {
+      field: string;
+    } = {
+      field: query.sort || '-timestamp',
+    };
+
+    const arrowDirection = sort.field.startsWith('-') ? 'down' : 'up';
+    const sortArrow = <IconArrow color="gray300" size="xs" direction={arrowDirection} />;
+
     return (
       <React.Fragment>
         <StyledPageHeader>
@@ -129,7 +143,32 @@ class Replays extends React.Component<Props> {
                     <PanelTable
                       isLoading={data.isLoading}
                       isEmpty={data.tableData?.data.length === 0}
-                      headers={[t('Session'), t('Project'), t('Timestamp')]}
+                      headers={[
+                        t('Session'),
+                        t('Project'),
+                        <SortLink
+                          key="timestamp"
+                          role="columnheader"
+                          aria-sort={
+                            !sort.field.endsWith('timestamp')
+                              ? 'none'
+                              : sort.field === '-timestamp'
+                              ? 'descending'
+                              : 'ascending'
+                          }
+                          to={{
+                            pathname: location.pathname,
+                            query: {
+                              ...currentQuery,
+                              // sort by timestamp should start by ascending on first click
+                              sort:
+                                sort.field === '-timestamp' ? 'timestamp' : '-timestamp',
+                            },
+                          }}
+                        >
+                          {t('Timestamp')} {sort.field.endsWith('timestamp') && sortArrow}
+                        </SortLink>,
+                      ]}
                     >
                       {data.tableData
                         ? this.renderTable(data.tableData.data as Replay[])
@@ -182,4 +221,16 @@ const StyledIconCalendarWrapper = styled(IconCalendar)`
   top: -1px;
 `;
 
+const SortLink = styled(Link)`
+  color: inherit;
+
+  :hover {
+    color: inherit;
+  }
+
+  svg {
+    vertical-align: top;
+  }
+`;
+
 export default withRouter(withPageFilters(withOrganization(Replays)));