123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- import {Fragment, useMemo} from 'react';
- import {browserHistory, RouteComponentProps} from 'react-router';
- import {useTheme} from '@emotion/react';
- import styled from '@emotion/styled';
- import DetailedError from 'sentry/components/errors/detailedError';
- import PageFiltersContainer from 'sentry/components/organizations/pageFilters/container';
- import PageHeading from 'sentry/components/pageHeading';
- import Pagination from 'sentry/components/pagination';
- import ReplaysFeatureBadge from 'sentry/components/replays/replaysFeatureBadge';
- import {t} from 'sentry/locale';
- import {PageContent, PageHeader} from 'sentry/styles/organization';
- import space from 'sentry/styles/space';
- import EventView from 'sentry/utils/discover/eventView';
- import {decodeScalar} from 'sentry/utils/queryString';
- import useReplayList, {
- DEFAULT_SORT,
- REPLAY_LIST_FIELDS,
- } from 'sentry/utils/replays/hooks/useReplayList';
- import {MutableSearch} from 'sentry/utils/tokenizeSearch';
- import useMedia from 'sentry/utils/useMedia';
- import useOrganization from 'sentry/utils/useOrganization';
- import ReplaysFilters from 'sentry/views/replays/filters';
- import ReplayTable from 'sentry/views/replays/replayTable';
- import type {ReplayListLocationQuery} from 'sentry/views/replays/types';
- type Props = RouteComponentProps<{orgId: string}, {}, any, ReplayListLocationQuery>;
- function Replays({location}: Props) {
- const organization = useOrganization();
- const theme = useTheme();
- const minWidthIsSmall = useMedia(`(min-width: ${theme.breakpoints.small})`);
- const eventView = useMemo(() => {
- const query = decodeScalar(location.query.query, '');
- const conditions = new MutableSearch(query);
- return EventView.fromNewQueryWithLocation(
- {
- id: '',
- name: '',
- version: 2,
- fields: REPLAY_LIST_FIELDS,
- projects: [],
- query: conditions.formatString(),
- orderby: decodeScalar(location.query.sort, DEFAULT_SORT),
- },
- location
- );
- }, [location]);
- const {pathname, query} = location;
- const {replays, pageLinks, isFetching, fetchError} = useReplayList({
- organization,
- eventView,
- });
- if (fetchError && !isFetching) {
- const reasons = [
- t('The search parameters you selected are invalid in some way'),
- t('There is an internal systems error or active issue'),
- ];
- return (
- <DetailedError
- hideSupportLinks
- heading={t('Sorry, the list of replays could not be found.')}
- message={
- <div>
- <p>{t('This could be due to a handful of reasons:')}</p>
- <ol className="detailed-error-list">
- {reasons.map((reason, i) => (
- <li key={i}>{reason}</li>
- ))}
- </ol>
- </div>
- }
- />
- );
- }
- return (
- <Fragment>
- <StyledPageHeader>
- <HeaderTitle>
- <div>
- {t('Replays')} <ReplaysFeatureBadge />
- </div>
- </HeaderTitle>
- </StyledPageHeader>
- <PageFiltersContainer>
- <StyledPageContent>
- <ReplaysFilters
- query={query.query || ''}
- organization={organization}
- handleSearchQuery={searchQuery => {
- browserHistory.push({
- pathname,
- query: {
- ...query,
- cursor: undefined,
- query: searchQuery.trim(),
- },
- });
- }}
- />
- <ReplayTable
- isFetching={isFetching}
- replays={replays}
- showProjectColumn={minWidthIsSmall}
- sort={eventView.sorts[0]}
- />
- <Pagination
- pageLinks={pageLinks}
- onCursor={(cursor, path, searchQuery) => {
- browserHistory.push({
- pathname: path,
- query: {...searchQuery, cursor},
- });
- }}
- />
- </StyledPageContent>
- </PageFiltersContainer>
- </Fragment>
- );
- }
- const StyledPageHeader = styled(PageHeader)`
- background-color: ${p => p.theme.surface100};
- min-width: max-content;
- margin: ${space(3)} ${space(0)} ${space(4)} ${space(4)};
- `;
- const StyledPageContent = styled(PageContent)`
- box-shadow: 0px 0px 1px ${p => p.theme.gray200};
- background-color: ${p => p.theme.background};
- `;
- const HeaderTitle = styled(PageHeading)`
- display: flex;
- align-items: center;
- justify-content: space-between;
- flex: 1;
- `;
- export default Replays;
|