From d77c7884af8c0aeef6583b8a794bfb2cd4fbfa5a Mon Sep 17 00:00:00 2001 From: Alberto Leal Date: Thu, 15 Aug 2019 03:15:37 -0400 Subject: [PATCH 01/27] src/sentry/static/sentry/app/views/organizationEventsV2/data.tsx --- .../app/views/organizationEventsV2/{data.jsx => data.tsx} | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) rename src/sentry/static/sentry/app/views/organizationEventsV2/{data.jsx => data.tsx} (95%) diff --git a/src/sentry/static/sentry/app/views/organizationEventsV2/data.jsx b/src/sentry/static/sentry/app/views/organizationEventsV2/data.tsx similarity index 95% rename from src/sentry/static/sentry/app/views/organizationEventsV2/data.jsx rename to src/sentry/static/sentry/app/views/organizationEventsV2/data.tsx index 037d0c45bb5a63..4fd861e18e34cb 100644 --- a/src/sentry/static/sentry/app/views/organizationEventsV2/data.jsx +++ b/src/sentry/static/sentry/app/views/organizationEventsV2/data.tsx @@ -12,14 +12,19 @@ import getDynamicText from 'app/utils/getDynamicText'; import overflowEllipsis from 'app/styles/overflowEllipsis'; import pinIcon from 'app/../images/location-pin.png'; import space from 'app/styles/space'; +import {EventView} from 'app/types'; import {QueryLink} from './styles'; +// TODO(ts): add as const after babel upgrade export const MODAL_QUERY_KEYS = ['eventSlug']; export const PIN_ICON = `image://${pinIcon}`; +// TODO(ts): add as const after babel upgrade export const AGGREGATE_ALIASES = ['last_seen', 'latest_event']; -export const ALL_VIEWS = deepFreeze([ +// TODO(ts): eventually defer to TS compile-time check to ensure this is readonly instead +// of deepfreezing it in runtime +export const ALL_VIEWS: Readonly> = deepFreeze([ { id: 'all', name: t('All Events'), From a1b6c1d65af505f243aef15978cceea866446ed3 Mon Sep 17 00:00:00 2001 From: Alberto Leal Date: Thu, 15 Aug 2019 03:15:47 -0400 Subject: [PATCH 02/27] src/sentry/static/sentry/app/views/organizationEventsV2/utils.tsx --- .../{utils.jsx => utils.tsx} | 108 ++++++++++++++---- 1 file changed, 85 insertions(+), 23 deletions(-) rename src/sentry/static/sentry/app/views/organizationEventsV2/{utils.jsx => utils.tsx} (60%) diff --git a/src/sentry/static/sentry/app/views/organizationEventsV2/utils.jsx b/src/sentry/static/sentry/app/views/organizationEventsV2/utils.tsx similarity index 60% rename from src/sentry/static/sentry/app/views/organizationEventsV2/utils.jsx rename to src/sentry/static/sentry/app/views/organizationEventsV2/utils.tsx index 35efb27e5b7986..1b4a00708e6499 100644 --- a/src/sentry/static/sentry/app/views/organizationEventsV2/utils.jsx +++ b/src/sentry/static/sentry/app/views/organizationEventsV2/utils.tsx @@ -1,5 +1,8 @@ import {partial, pick, get} from 'lodash'; +import {ReactRouterLocation} from 'app/types/reactRouter'; +import {Client} from 'app/api'; +import {EventView} from 'app/types'; import {DEFAULT_PER_PAGE} from 'app/constants'; import {URL_PARAM} from 'app/constants/globalSelectionHeader'; import {ALL_VIEWS, AGGREGATE_ALIASES, SPECIAL_FIELDS, FIELD_FORMATTERS} from './data'; @@ -11,10 +14,17 @@ import {ALL_VIEWS, AGGREGATE_ALIASES, SPECIAL_FIELDS, FIELD_FORMATTERS} from './ * @returns {Object} * */ -export function getCurrentView(requestedView) { +export function getCurrentView(requestedView?: string): EventView { return ALL_VIEWS.find(view => view.id === requestedView) || ALL_VIEWS[0]; } +export type EventQuery = { + field: Array; + project?: string; + sort?: string | string[]; + query: string; +}; + /** * Takes a view and determines if there are any aggregate fields in it. * @@ -37,11 +47,21 @@ export function hasAggregateField(view) { * @param {Object} view * @returns {Object} */ -export function getQuery(view, location) { - const groupby = view.data.groupby ? [...view.data.groupby] : []; - const fields = get(view, 'data.fields', []); +export function getQuery(view: EventView, location: ReactRouterLocation) { + const fields: Array = get(view, 'data.fields', []); + + type LocationQuery = { + project?: string; + environment?: string; + start?: string; + end?: string; + utc?: string; + statsPeriod?: string; + cursor?: string; + sort?: string; + }; - const data = pick(location.query, [ + const picked = pick(location.query, [ 'project', 'environment', 'start', @@ -52,13 +72,12 @@ export function getQuery(view, location) { 'sort', ]); - data.field = [...new Set(fields)]; - data.groupby = groupby; - if (!data.sort) { - data.sort = view.data.sort; - } - data.per_page = DEFAULT_PER_PAGE; - data.query = getQueryString(view, location); + const data: EventQuery = Object.assign(picked, { + field: [...new Set(fields)], + sort: picked.sort ? picked.sort : view.data.sort, + per_page: DEFAULT_PER_PAGE, + query: getQueryString(view, location), + }); return data; } @@ -72,13 +91,23 @@ export function getQuery(view, location) { * @param {Object} view defaults containing `.data.query` * @param {Location} browser location */ -export function getQueryString(view, location) { - const queryParts = []; +export function getQueryString(view: EventView, location: ReactRouterLocation): string { + const queryParts: Array = []; if (view.data.query) { queryParts.push(view.data.query); } if (location.query && location.query.query) { - queryParts.push(location.query.query); + // there may be duplicate query in the query string + // e.g. query=hello&query=world + if (Array.isArray(location.query.query)) { + location.query.query.forEach(query => { + queryParts.push(query); + }); + } + + if (typeof location.query.query === 'string') { + queryParts.push(location.query.query); + } } return queryParts.join(' '); @@ -93,7 +122,11 @@ export function getQueryString(view, location) { * @param {Object} browser location object. * @return {Object} router target */ -export function getEventTagSearchUrl(tagKey, tagValue, location) { +export function getEventTagSearchUrl( + tagKey: string, + tagValue: string, + location: ReactRouterLocation +) { const query = {...location.query}; // Add tag key/value to search if (query.query) { @@ -110,20 +143,39 @@ export function getEventTagSearchUrl(tagKey, tagValue, location) { }; } +export type TagTopValue = { + url: { + pathname: string; + query: any; + }; + value: string; +}; + +export type Tag = { + topValues: Array; +}; + /** * Fetches tag distributions for a single tag key * * @param {Object} api * @param {String} orgSlug * @param {String} key - * @param {string} query + * @param {String} query * @returns {Promise} */ -export function fetchTagDistribution(api, orgSlug, key, query) { +export function fetchTagDistribution( + api: Client, + orgSlug: string, + key: string, + query: EventQuery +): Promise { const urlParams = pick(query, Object.values(URL_PARAM)); + const queryOption = {...urlParams, key, query: query.query}; + return api.requestPromise(`/organizations/${orgSlug}/events-distribution/`, { - query: {...urlParams, key, query: query.query}, + query: queryOption, }); } @@ -135,14 +187,24 @@ export function fetchTagDistribution(api, orgSlug, key, query) { * @param {string} query * @returns {Promise} */ -export function fetchTotalCount(api, orgSlug, query) { +export function fetchTotalCount( + api: Client, + orgSlug: String, + query: EventQuery +): Promise { const urlParams = pick(query, Object.values(URL_PARAM)); + const queryOption = {...urlParams, query: query.query}; + + type Response = { + count: number; + }; + return api .requestPromise(`/organizations/${orgSlug}/events-meta/`, { - query: {...urlParams, query: query.query}, + query: queryOption, }) - .then(res => res.count); + .then((res: Response) => res.count); } /** @@ -152,7 +214,7 @@ export function fetchTotalCount(api, orgSlug, query) { * @param {object} metadata mapping. * @returns {Function} */ -export function getFieldRenderer(field, meta) { +export function getFieldRenderer(field: string, meta) { if (SPECIAL_FIELDS.hasOwnProperty(field)) { return SPECIAL_FIELDS[field].renderFunc; } From 324660fd8ef170a835a56622a7c01e1d0ffd4413 Mon Sep 17 00:00:00 2001 From: Alberto Leal Date: Fri, 9 Aug 2019 22:47:23 -0400 Subject: [PATCH 03/27] src/sentry/static/sentry/app/views/organizationEventsV2/events.tsx --- .../{events.jsx => events.tsx} | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) rename src/sentry/static/sentry/app/views/organizationEventsV2/{events.jsx => events.tsx} (83%) diff --git a/src/sentry/static/sentry/app/views/organizationEventsV2/events.jsx b/src/sentry/static/sentry/app/views/organizationEventsV2/events.tsx similarity index 83% rename from src/sentry/static/sentry/app/views/organizationEventsV2/events.jsx rename to src/sentry/static/sentry/app/views/organizationEventsV2/events.tsx index f316dfb66fcf31..9ce48c9ac174db 100644 --- a/src/sentry/static/sentry/app/views/organizationEventsV2/events.jsx +++ b/src/sentry/static/sentry/app/views/organizationEventsV2/events.tsx @@ -2,6 +2,10 @@ import React from 'react'; import PropTypes from 'prop-types'; import styled from 'react-emotion'; import {omit, isEqual} from 'lodash'; +import * as ReactRouter from 'react-router'; +import {ReactRouterLocation} from 'app/types/reactRouter'; + +import {Organization, EventView} from 'app/types'; import SentryTypes from 'app/sentryTypes'; import space from 'app/styles/space'; import SearchBar from 'app/views/events/searchBar'; @@ -15,7 +19,7 @@ import {getParams} from 'app/views/events/utils/getParams'; import Table from './table'; import Tags from './tags'; -import {getQuery} from './utils'; +import {getQuery, EventQuery} from './utils'; import {MODAL_QUERY_KEYS} from './data'; const CHART_AXIS_OPTIONS = [ @@ -23,7 +27,14 @@ const CHART_AXIS_OPTIONS = [ {label: 'Users', value: 'user_count'}, ]; -export default class Events extends React.Component { +type EventsProps = { + router: ReactRouter.InjectedRouter; + location: ReactRouterLocation; + organization: Organization; + view: EventView; +}; + +export default class Events extends React.Component { static propTypes = { router: PropTypes.object.isRequired, location: PropTypes.object.isRequired, @@ -81,7 +92,13 @@ export default class Events extends React.Component { } } -class EventsTable extends AsyncComponent { +type EventsTableProps = { + location: ReactRouterLocation; + organization: Organization; + view: EventView; +}; + +class EventsTable extends AsyncComponent { static propTypes = { location: PropTypes.object.isRequired, organization: SentryTypes.Organization.isRequired, @@ -90,7 +107,7 @@ class EventsTable extends AsyncComponent { shouldReload = false; - componentDidUpdate(prevProps, prevContext) { + componentDidUpdate(prevProps: EventsTableProps, prevContext) { // Do not update if we are just opening/closing the modal const locationHasChanged = !isEqual( omit(prevProps.location.query, MODAL_QUERY_KEYS), @@ -102,7 +119,7 @@ class EventsTable extends AsyncComponent { } } - getEndpoints() { + getEndpoints(): Array<[string, string, {query: EventQuery}]> { const {location, organization, view} = this.props; return [ [ From eee80c79570cba6c3afa457c6517cf299c63cdca Mon Sep 17 00:00:00 2001 From: Alberto Leal Date: Fri, 9 Aug 2019 22:47:42 -0400 Subject: [PATCH 04/27] src/sentry/static/sentry/app/views/organizationEventsV2/linkedIssuePreview.tsx --- ...dIssuePreview.jsx => linkedIssuePreview.tsx} | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) rename src/sentry/static/sentry/app/views/organizationEventsV2/{linkedIssuePreview.jsx => linkedIssuePreview.tsx} (91%) diff --git a/src/sentry/static/sentry/app/views/organizationEventsV2/linkedIssuePreview.jsx b/src/sentry/static/sentry/app/views/organizationEventsV2/linkedIssuePreview.tsx similarity index 91% rename from src/sentry/static/sentry/app/views/organizationEventsV2/linkedIssuePreview.jsx rename to src/sentry/static/sentry/app/views/organizationEventsV2/linkedIssuePreview.tsx index d93f111dd4ea05..e9cce5177c8937 100644 --- a/src/sentry/static/sentry/app/views/organizationEventsV2/linkedIssuePreview.jsx +++ b/src/sentry/static/sentry/app/views/organizationEventsV2/linkedIssuePreview.tsx @@ -13,14 +13,27 @@ import SeenByList from 'app/components/seenByList'; import ShortId from 'app/components/shortId'; import Times from 'app/components/group/times'; import space from 'app/styles/space'; +import {Group} from 'app/types'; -class LinkedIssuePreview extends AsyncComponent { +type Props = { + groupId: string; + eventId: string; +}; + +type State = { + group: Group; +}; + +class LinkedIssuePreview extends AsyncComponent< + Props & AsyncComponent['props'], + State & AsyncComponent['state'] +> { static propTypes = { groupId: PropTypes.string.isRequired, eventId: PropTypes.string.isRequired, }; - getEndpoints() { + getEndpoints(): Array<[string, string]> { const {groupId} = this.props; const groupUrl = `/issues/${groupId}/`; From 7cc11ae5ef8d951af80f4e0ee0672fe0f03edaa2 Mon Sep 17 00:00:00 2001 From: Alberto Leal Date: Fri, 9 Aug 2019 22:43:19 -0400 Subject: [PATCH 05/27] src/sentry/static/sentry/app/views/organizationEventsV2/eventModalContent.tsx --- ...ModalContent.jsx => eventModalContent.tsx} | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) rename src/sentry/static/sentry/app/views/organizationEventsV2/{eventModalContent.jsx => eventModalContent.tsx} (87%) diff --git a/src/sentry/static/sentry/app/views/organizationEventsV2/eventModalContent.jsx b/src/sentry/static/sentry/app/views/organizationEventsV2/eventModalContent.tsx similarity index 87% rename from src/sentry/static/sentry/app/views/organizationEventsV2/eventModalContent.jsx rename to src/sentry/static/sentry/app/views/organizationEventsV2/eventModalContent.tsx index c38b1fc8ea6f7c..0ad0214486fdc9 100644 --- a/src/sentry/static/sentry/app/views/organizationEventsV2/eventModalContent.jsx +++ b/src/sentry/static/sentry/app/views/organizationEventsV2/eventModalContent.tsx @@ -10,6 +10,8 @@ import overflowEllipsis from 'app/styles/overflowEllipsis'; import space from 'app/styles/space'; import getDynamicText from 'app/utils/getDynamicText'; import {getMessage, getTitle} from 'app/utils/events'; +import {Event, Organization, EventView} from 'app/types'; +import {ReactRouterLocation} from 'app/types/reactRouter'; import EventInterfaces from './eventInterfaces'; import LinkedIssuePreview from './linkedIssuePreview'; @@ -19,12 +21,21 @@ import RelatedEvents from './relatedEvents'; import TagsTable from './tagsTable'; import TransanctionView from './transactionView'; import {hasAggregateField} from './utils'; +import {SentryTransactionEvent} from './transactionView/types'; + +type EventModalContentProps = { + event: Event; + projectId: string; + organization: Organization; + location: ReactRouterLocation; + view: EventView; +}; /** * Render the columns and navigation elements inside the event modal view. * Controlled by the EventDetails View. */ -const EventModalContent = props => { +const EventModalContent = (props: EventModalContentProps) => { const {event, projectId, organization, location, view} = props; // Having an aggregate field means we want to show pagination/graphs @@ -53,7 +64,7 @@ const EventModalContent = props => { {event.type === 'transaction' ? ( - + ) : ( )} @@ -100,7 +111,7 @@ EventHeader.propTypes = { /** * Render metadata about the event and provide a link to the JSON blob */ -const EventMetadata = props => { +const EventMetadata = (props: {event: Event; eventJsonUrl: string}) => { const {event, eventJsonUrl} = props; return ( @@ -109,7 +120,7 @@ const EventMetadata = props => { @@ -166,7 +177,7 @@ const SidebarColumn = styled('div')` grid-column: 2 / 3; `; -const SidebarBlock = styled('div')` +const SidebarBlock = styled('div')<{withSeparator?: boolean; theme?: any}>` margin: 0 0 ${space(2)} 0; padding: 0 0 ${space(2)} 0; ${p => (p.withSeparator ? `border-bottom: 1px solid ${p.theme.borderLight};` : '')} From b307b8612d918b7eeed1c1824d367d97cdc023f0 Mon Sep 17 00:00:00 2001 From: Alberto Leal Date: Fri, 9 Aug 2019 22:48:59 -0400 Subject: [PATCH 06/27] src/sentry/static/sentry/app/views/organizationEventsV2/table.tsx --- .../{table.jsx => table.tsx} | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) rename src/sentry/static/sentry/app/views/organizationEventsV2/{table.jsx => table.tsx} (85%) diff --git a/src/sentry/static/sentry/app/views/organizationEventsV2/table.jsx b/src/sentry/static/sentry/app/views/organizationEventsV2/table.tsx similarity index 85% rename from src/sentry/static/sentry/app/views/organizationEventsV2/table.jsx rename to src/sentry/static/sentry/app/views/organizationEventsV2/table.tsx index 35b978c71418c1..4b70e08ee8433b 100644 --- a/src/sentry/static/sentry/app/views/organizationEventsV2/table.jsx +++ b/src/sentry/static/sentry/app/views/organizationEventsV2/table.tsx @@ -9,12 +9,23 @@ import EmptyStateWarning from 'app/components/emptyStateWarning'; import LoadingContainer from 'app/components/loading/loadingContainer'; import {t} from 'app/locale'; import space from 'app/styles/space'; +import {EventView, Organization} from 'app/types'; +import {ReactRouterLocation} from 'app/types/reactRouter'; import {FIELD_FORMATTERS, SPECIAL_FIELDS} from './data'; import {getFieldRenderer} from './utils'; import SortLink from './sortLink'; -export default class Table extends React.Component { +type Props = { + view: EventView; + isLoading: boolean; + location: ReactRouterLocation; + organization: Organization; + // TODO(ts): adjust this type + data: any; +}; + +export default class Table extends React.Component { static propTypes = { view: SentryTypes.EventView.isRequired, data: PropTypes.object, @@ -61,14 +72,14 @@ export default class Table extends React.Component { {fields.map((field, i) => { const title = columnNames[i] || field; - let sortKey = field; + let sortKey: string | null = field; if (SPECIAL_FIELDS.hasOwnProperty(field)) { - sortKey = SPECIAL_FIELDS[field].sortField; + sortKey = SPECIAL_FIELDS[field].sortField || null; } else if (FIELD_FORMATTERS.hasOwnProperty(field)) { - sortKey = FIELD_FORMATTERS[field].sortField ? field : false; + sortKey = FIELD_FORMATTERS[field].sortField ? field : null; } - if (sortKey === false) { + if (sortKey === null) { return {title}; } @@ -123,9 +134,10 @@ const Cell = styled('div')` overflow: hidden; `; +// TODO(ts): adjust types const StyledPanelBody = styled(props => { const otherProps = omit(props, 'isLoading'); return ; })` - ${p => p.isLoading && 'min-height: 240px;'}; + ${(p: {isLoading: boolean}) => p.isLoading && 'min-height: 240px;'}; `; From 31bce2bb6ad62fe8a6b7777b4f20c7306b5a330b Mon Sep 17 00:00:00 2001 From: Alberto Leal Date: Fri, 9 Aug 2019 22:48:03 -0400 Subject: [PATCH 07/27] src/sentry/static/sentry/app/views/organizationEventsV2/modalPagination.tsx --- ...odalPagination.jsx => modalPagination.tsx} | 30 +++++++++++++++---- 1 file changed, 24 insertions(+), 6 deletions(-) rename src/sentry/static/sentry/app/views/organizationEventsV2/{modalPagination.jsx => modalPagination.tsx} (82%) diff --git a/src/sentry/static/sentry/app/views/organizationEventsV2/modalPagination.jsx b/src/sentry/static/sentry/app/views/organizationEventsV2/modalPagination.tsx similarity index 82% rename from src/sentry/static/sentry/app/views/organizationEventsV2/modalPagination.jsx rename to src/sentry/static/sentry/app/views/organizationEventsV2/modalPagination.tsx index d506c0f1213782..038f930bf05aed 100644 --- a/src/sentry/static/sentry/app/views/organizationEventsV2/modalPagination.jsx +++ b/src/sentry/static/sentry/app/views/organizationEventsV2/modalPagination.tsx @@ -9,24 +9,35 @@ import Link from 'app/components/links/link'; import SentryTypes from 'app/sentryTypes'; import InlineSvg from 'app/components/inlineSvg'; import space from 'app/styles/space'; +import {ReactRouterLocation} from 'app/types/reactRouter'; +import {Event} from 'app/types'; import {MODAL_QUERY_KEYS} from './data'; +type LinksType = { + oldest: null; + latest: null; + + next: {}; + previous: {}; +}; + /** * Generate a mapping of link names => link targets for pagination */ -function buildTargets(event, location) { +function buildTargets(event: Event, location: ReactRouterLocation): LinksType { // Remove slug related keys as we need to create new ones const baseQuery = omit(location.query, MODAL_QUERY_KEYS); - const urlMap = { + const urlMap: {[k in keyof LinksType]: string | undefined | null} = { previous: event.previousEventID, next: event.nextEventID, oldest: event.oldestEventID, latest: event.latestEventID, }; - const links = {}; + const links: {[k in keyof LinksType]?: any} = {}; + Object.entries(urlMap).forEach(([key, value]) => { // If the urlMap has no value we want to skip this link as it is 'disabled'; if (!value) { @@ -42,10 +53,15 @@ function buildTargets(event, location) { } }); - return links; + return links as LinksType; } -const ModalPagination = props => { +type Props = { + event: Event; + location: ReactRouterLocation; +}; + +const ModalPagination = (props: Props) => { const {event, location} = props; const links = buildTargets(event, location); @@ -88,7 +104,9 @@ ModalPagination.propTypes = { event: SentryTypes.Event.isRequired, }; -const StyledLink = styled(Link, {shouldForwardProp: isPropValid})` +const StyledLink = styled(Link, { + shouldForwardProp: isPropValid, +})<{theme: any; disabled: boolean; fontSizeMedium: string; isLast: boolean}>` color: ${p => (p.disabled ? p.theme.disabled : p.theme.gray3)}; font-size: ${p => p.fontSizeMedium}; text-align: center; From 5b7cec36c77ff798d98e5e846a84e3eeecca4df2 Mon Sep 17 00:00:00 2001 From: Alberto Leal Date: Fri, 9 Aug 2019 22:48:13 -0400 Subject: [PATCH 08/27] src/sentry/static/sentry/app/views/organizationEventsV2/relatedEvents.tsx --- .../{relatedEvents.jsx => relatedEvents.tsx} | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) rename src/sentry/static/sentry/app/views/organizationEventsV2/{relatedEvents.jsx => relatedEvents.tsx} (87%) diff --git a/src/sentry/static/sentry/app/views/organizationEventsV2/relatedEvents.jsx b/src/sentry/static/sentry/app/views/organizationEventsV2/relatedEvents.tsx similarity index 87% rename from src/sentry/static/sentry/app/views/organizationEventsV2/relatedEvents.jsx rename to src/sentry/static/sentry/app/views/organizationEventsV2/relatedEvents.tsx index f5ba0790afd014..3af58954012b5b 100644 --- a/src/sentry/static/sentry/app/views/organizationEventsV2/relatedEvents.jsx +++ b/src/sentry/static/sentry/app/views/organizationEventsV2/relatedEvents.tsx @@ -2,7 +2,9 @@ import React from 'react'; import styled from 'react-emotion'; import PropTypes from 'prop-types'; import {omit} from 'lodash'; +import {ReactRouterLocation} from 'app/types/reactRouter'; +import {Organization, EventView, Event, Project} from 'app/types'; import {t} from 'app/locale'; import SentryTypes from 'app/sentryTypes'; import AsyncComponent from 'app/components/asyncComponent'; @@ -17,16 +19,25 @@ import overflowEllipsis from 'app/styles/overflowEllipsis'; import withProjects from 'app/utils/withProjects'; import {MODAL_QUERY_KEYS} from './data'; - -class RelatedEvents extends AsyncComponent { - static propTypes = { +import {EventQuery} from './utils'; + +type Props = { + location: ReactRouterLocation; + organization: Organization; + view: EventView; + event: Event; + projects: Array; +}; + +class RelatedEvents extends AsyncComponent { + static propTypes: any = { event: SentryTypes.Event.isRequired, location: PropTypes.object.isRequired, organization: SentryTypes.Organization.isRequired, projects: PropTypes.arrayOf(SentryTypes.Project), }; - getEndpoints() { + getEndpoints(): Array<[string, string, {query: EventQuery}]> { // TODO what happens when global-views feature is not on the org? const {event, organization} = this.props; const eventsUrl = `/organizations/${organization.slug}/eventsv2/`; @@ -36,7 +47,7 @@ class RelatedEvents extends AsyncComponent { return []; } - const params = { + const params: {query: EventQuery} = { query: { field: [ 'project.name', @@ -106,7 +117,7 @@ const Container = styled('div')` position: relative; `; -const Card = styled('div')` +const Card = styled('div')<{isCurrent?: boolean; theme?: any}>` display: flex; flex-direction: column; border: 1px solid ${p => (p.isCurrent ? p.theme.purpleLight : p.theme.borderLight)}; From 0a34af609c7bb3cb1aea52d06d7f569bf43a476d Mon Sep 17 00:00:00 2001 From: Alberto Leal Date: Fri, 9 Aug 2019 22:47:31 -0400 Subject: [PATCH 09/27] src/sentry/static/sentry/app/views/organizationEventsV2/index.tsx --- .../{index.jsx => index.tsx} | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) rename src/sentry/static/sentry/app/views/organizationEventsV2/{index.jsx => index.tsx} (88%) diff --git a/src/sentry/static/sentry/app/views/organizationEventsV2/index.jsx b/src/sentry/static/sentry/app/views/organizationEventsV2/index.tsx similarity index 88% rename from src/sentry/static/sentry/app/views/organizationEventsV2/index.jsx rename to src/sentry/static/sentry/app/views/organizationEventsV2/index.tsx index 13434845d7f570..2dc5fc9d67eb22 100644 --- a/src/sentry/static/sentry/app/views/organizationEventsV2/index.jsx +++ b/src/sentry/static/sentry/app/views/organizationEventsV2/index.tsx @@ -1,7 +1,11 @@ import React from 'react'; import DocumentTitle from 'react-document-title'; import PropTypes from 'prop-types'; +import * as ReactRouter from 'react-router'; +import {Params} from 'react-router/lib/Router'; +import {Location} from 'history'; +import {Organization} from 'app/types'; import {t} from 'app/locale'; import SentryTypes from 'app/sentryTypes'; import GlobalSelectionHeader from 'app/components/organizations/globalSelectionHeader'; @@ -19,14 +23,21 @@ import EventDetails from './eventDetails'; import {ALL_VIEWS} from './data'; import {getCurrentView} from './utils'; -class OrganizationEventsV2 extends React.Component { - static propTypes = { +type Props = { + organization: Organization; + location: Location; + router: ReactRouter.InjectedRouter; + params: Params; +}; + +class OrganizationEventsV2 extends React.Component { + static propTypes: any = { organization: SentryTypes.Organization.isRequired, location: PropTypes.object.isRequired, router: PropTypes.object.isRequired, }; - renderTabs() { + renderTabs(): React.ReactNode { const {location} = this.props; const currentView = getCurrentView(location.query.view); From 4fd036d4e966628570fa37f8d499602b5ebe2262 Mon Sep 17 00:00:00 2001 From: Alberto Leal Date: Fri, 9 Aug 2019 22:42:51 -0400 Subject: [PATCH 10/27] src/sentry/static/sentry/app/views/organizationEventsV2/eventDetails.tsx --- .../{eventDetails.jsx => eventDetails.tsx} | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) rename src/sentry/static/sentry/app/views/organizationEventsV2/{eventDetails.jsx => eventDetails.tsx} (86%) diff --git a/src/sentry/static/sentry/app/views/organizationEventsV2/eventDetails.jsx b/src/sentry/static/sentry/app/views/organizationEventsV2/eventDetails.tsx similarity index 86% rename from src/sentry/static/sentry/app/views/organizationEventsV2/eventDetails.jsx rename to src/sentry/static/sentry/app/views/organizationEventsV2/eventDetails.tsx index 2f1be0b3034019..b9027ab7c90515 100644 --- a/src/sentry/static/sentry/app/views/organizationEventsV2/eventDetails.jsx +++ b/src/sentry/static/sentry/app/views/organizationEventsV2/eventDetails.tsx @@ -11,9 +11,11 @@ import NotFound from 'app/components/errors/notFound'; import withApi from 'app/utils/withApi'; import theme from 'app/utils/theme'; import space from 'app/styles/space'; +import {Organization, EventView, Event} from 'app/types'; +import {ReactRouterLocation} from 'app/types/reactRouter'; import EventModalContent from './eventModalContent'; -import {getQuery} from './utils'; +import {EventQuery, getQuery} from './utils'; const slugValidator = function(props, propName, componentName) { const value = props[propName]; @@ -38,8 +40,20 @@ const modalStyles = css` } `; -class EventDetails extends AsyncComponent { - static propTypes = { +type Props = { + organization: Organization; + location: ReactRouterLocation; + eventSlug: string; + view: EventView; + params: any; +}; + +type State = { + event: Event; +}; + +class EventDetails extends AsyncComponent { + static propTypes: any = { organization: SentryTypes.Organization.isRequired, eventSlug: slugValidator, location: PropTypes.object.isRequired, From aa8bcbd6c68eba1244843678b21aa9c7c6b61d92 Mon Sep 17 00:00:00 2001 From: Alberto Leal Date: Fri, 9 Aug 2019 22:47:53 -0400 Subject: [PATCH 11/27] src/sentry/static/sentry/app/views/organizationEventsV2/modalLineGraph.tsx --- ...{modalLineGraph.jsx => modalLineGraph.tsx} | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) rename src/sentry/static/sentry/app/views/organizationEventsV2/{modalLineGraph.jsx => modalLineGraph.tsx} (91%) diff --git a/src/sentry/static/sentry/app/views/organizationEventsV2/modalLineGraph.jsx b/src/sentry/static/sentry/app/views/organizationEventsV2/modalLineGraph.tsx similarity index 91% rename from src/sentry/static/sentry/app/views/organizationEventsV2/modalLineGraph.jsx rename to src/sentry/static/sentry/app/views/organizationEventsV2/modalLineGraph.tsx index 033897af96b996..a16e5387a1fd65 100644 --- a/src/sentry/static/sentry/app/views/organizationEventsV2/modalLineGraph.jsx +++ b/src/sentry/static/sentry/app/views/organizationEventsV2/modalLineGraph.tsx @@ -3,6 +3,7 @@ import PropTypes from 'prop-types'; import {browserHistory} from 'react-router'; import {omit} from 'lodash'; +import {Client} from 'app/api'; import {t} from 'app/locale'; import SentryTypes from 'app/sentryTypes'; import {getInterval, useShortInterval} from 'app/components/charts/utils'; @@ -18,6 +19,8 @@ import {Panel} from 'app/components/panels'; import withApi from 'app/utils/withApi'; import withGlobalSelection from 'app/utils/withGlobalSelection'; import theme from 'app/utils/theme'; +import {Event, Organization, EventView} from 'app/types'; +import {ReactRouterLocation} from 'app/types/reactRouter'; import {MODAL_QUERY_KEYS, PIN_ICON} from './data'; import {getQueryString} from './utils'; @@ -26,10 +29,10 @@ import {getQueryString} from './utils'; * Generate the data to display a vertical line for the current * event on the graph. */ -const getCurrentEventMarker = currentEvent => { +const getCurrentEventMarker = (currentEvent: Event) => { const title = t('Current Event'); const eventTime = +new Date( - currentEvent.dateCreated || currentEvent.endTimestamp * 1000 + currentEvent.dateCreated || (currentEvent.endTimestamp || 0) * 1000 ); return { @@ -88,7 +91,7 @@ const handleClick = async function( // Get events that match the clicked timestamp // taking into account the group and current environment & query - const query = { + const query: any = { environment: selection.environments, start: getUtcDateString(value), end: getUtcDateString(value + intervalToMilliseconds(interval)), @@ -127,10 +130,20 @@ const handleClick = async function( }); }; +type ModalLineGraphProps = { + api: Client; + organization: Organization; + location: ReactRouterLocation; + currentEvent: Event; + view: EventView; + // TODO(ts): adjust + selection: any; +}; + /** * Render a graph of event volumes for the current group + event. */ -const ModalLineGraph = props => { +const ModalLineGraph = (props: ModalLineGraphProps) => { const {api, organization, location, selection, currentEvent, view} = props; const isUtc = selection.datetime.utc; @@ -215,6 +228,6 @@ ModalLineGraph.propTypes = { organization: SentryTypes.Organization.isRequired, selection: PropTypes.object.isRequired, view: PropTypes.object.isRequired, -}; +} as any; export default withGlobalSelection(withApi(ModalLineGraph)); From 60886de126707047f536641f84401c768986ca11 Mon Sep 17 00:00:00 2001 From: Alberto Leal Date: Fri, 9 Aug 2019 22:49:08 -0400 Subject: [PATCH 12/27] src/sentry/static/sentry/app/views/organizationEventsV2/tags.tsx --- .../{tags.jsx => tags.tsx} | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) rename src/sentry/static/sentry/app/views/organizationEventsV2/{tags.jsx => tags.tsx} (84%) diff --git a/src/sentry/static/sentry/app/views/organizationEventsV2/tags.jsx b/src/sentry/static/sentry/app/views/organizationEventsV2/tags.tsx similarity index 84% rename from src/sentry/static/sentry/app/views/organizationEventsV2/tags.jsx rename to src/sentry/static/sentry/app/views/organizationEventsV2/tags.tsx index c377156943228f..d033932e5301a6 100644 --- a/src/sentry/static/sentry/app/views/organizationEventsV2/tags.jsx +++ b/src/sentry/static/sentry/app/views/organizationEventsV2/tags.tsx @@ -4,27 +4,45 @@ import styled from 'react-emotion'; import {isEqual, omit} from 'lodash'; import * as Sentry from '@sentry/browser'; +import {Client} from 'app/api'; import SentryTypes from 'app/sentryTypes'; import Placeholder from 'app/components/placeholder'; import TagDistributionMeter from 'app/components/tagDistributionMeter'; import withApi from 'app/utils/withApi'; +import {Organization, EventView} from 'app/types'; +import {ReactRouterLocation} from 'app/types/reactRouter'; + import { fetchTagDistribution, fetchTotalCount, getEventTagSearchUrl, getQuery, + Tag, + TagTopValue, } from './utils'; import {MODAL_QUERY_KEYS} from './data'; -class Tags extends React.Component { - static propTypes = { +type Props = { + api: Client; + organization: Organization; + view: EventView; + location: ReactRouterLocation; +}; + +type State = { + tags: {[key: string]: Tag}; + totalValues: null | number; +}; + +class Tags extends React.Component { + static propTypes: any = { api: PropTypes.object.isRequired, organization: SentryTypes.Organization.isRequired, view: SentryTypes.EventView.isRequired, location: PropTypes.object.isRequired, }; - state = { + state: State = { tags: {}, totalValues: null, }; @@ -81,7 +99,8 @@ class Tags extends React.Component { const {location} = this.props; const {tags, totalValues} = this.state; const isLoading = !tags[tag] || totalValues === null; - let segments = []; + + let segments: Array = []; if (!isLoading) { segments = tags[tag].topValues; From 87677b3ce6712e5992d8a7a84d4bdde16998b74d Mon Sep 17 00:00:00 2001 From: Alberto Leal Date: Fri, 9 Aug 2019 22:49:15 -0400 Subject: [PATCH 13/27] src/sentry/static/sentry/app/views/organizationEventsV2/tagsTable.tsx --- .../{tagsTable.jsx => tagsTable.tsx} | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) rename src/sentry/static/sentry/app/views/organizationEventsV2/{tagsTable.jsx => tagsTable.tsx} (86%) diff --git a/src/sentry/static/sentry/app/views/organizationEventsV2/tagsTable.jsx b/src/sentry/static/sentry/app/views/organizationEventsV2/tagsTable.tsx similarity index 86% rename from src/sentry/static/sentry/app/views/organizationEventsV2/tagsTable.jsx rename to src/sentry/static/sentry/app/views/organizationEventsV2/tagsTable.tsx index 9b9b92119a3cb3..ef3f5d0b055613 100644 --- a/src/sentry/static/sentry/app/views/organizationEventsV2/tagsTable.jsx +++ b/src/sentry/static/sentry/app/views/organizationEventsV2/tagsTable.tsx @@ -1,16 +1,23 @@ import React from 'react'; import styled from 'react-emotion'; import PropTypes from 'prop-types'; -import {withRouter} from 'react-router'; +import * as ReactRouter from 'react-router'; +import {ReactRouterLocation} from 'app/types/reactRouter'; import Link from 'app/components/links/link'; import Tooltip from 'app/components/tooltip'; import {t} from 'app/locale'; import space from 'app/styles/space'; import overflowEllipsis from 'app/styles/overflowEllipsis'; +import {EventTag} from 'app/types'; + import {getEventTagSearchUrl} from './utils'; -const TagsTable = props => { +type Props = { + tags: Array; +} & ReactRouter.WithRouterProps; + +const TagsTable = (props: Props) => { const {location, tags} = props; return (
@@ -45,7 +52,7 @@ const TagsTable = props => { TagsTable.propTypes = { tags: PropTypes.array.isRequired, location: PropTypes.object, -}; +} as any; const StyledTable = styled('table')` table-layout: fixed; @@ -77,4 +84,4 @@ const TagValue = styled(TagKey)` ${overflowEllipsis}; `; -export default withRouter(TagsTable); +export default ReactRouter.withRouter(TagsTable); From 761aa6bc57983ae5cc67c4593129a71a8bd7d6d9 Mon Sep 17 00:00:00 2001 From: Alberto Leal Date: Fri, 9 Aug 2019 22:48:40 -0400 Subject: [PATCH 14/27] src/sentry/static/sentry/app/views/organizationEventsV2/sortLink.tsx --- .../{sortLink.jsx => sortLink.tsx} | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) rename src/sentry/static/sentry/app/views/organizationEventsV2/{sortLink.jsx => sortLink.tsx} (87%) diff --git a/src/sentry/static/sentry/app/views/organizationEventsV2/sortLink.jsx b/src/sentry/static/sentry/app/views/organizationEventsV2/sortLink.tsx similarity index 87% rename from src/sentry/static/sentry/app/views/organizationEventsV2/sortLink.jsx rename to src/sentry/static/sentry/app/views/organizationEventsV2/sortLink.tsx index 480c47d59ebb02..944b69adc6c955 100644 --- a/src/sentry/static/sentry/app/views/organizationEventsV2/sortLink.jsx +++ b/src/sentry/static/sentry/app/views/organizationEventsV2/sortLink.tsx @@ -1,11 +1,19 @@ import React from 'react'; import PropTypes from 'prop-types'; import styled from 'react-emotion'; +import {ReactRouterLocation} from 'app/types/reactRouter'; import InlineSvg from 'app/components/inlineSvg'; import Link from 'app/components/links/link'; -class SortLink extends React.Component { +type Props = { + title: string; + sortKey: string; + defaultSort: string | null; + location: ReactRouterLocation; +}; + +class SortLink extends React.Component { static propTypes = { title: PropTypes.string.isRequired, sortKey: PropTypes.string.isRequired, From 92b78e72fbdc34913c37c74bd579d0067cb755ca Mon Sep 17 00:00:00 2001 From: Alberto Leal Date: Fri, 9 Aug 2019 22:43:06 -0400 Subject: [PATCH 15/27] src/sentry/static/sentry/app/views/organizationEventsV2/eventInterfaces.tsx --- ...ventInterfaces.jsx => eventInterfaces.tsx} | 36 +++++++++++++++---- 1 file changed, 29 insertions(+), 7 deletions(-) rename src/sentry/static/sentry/app/views/organizationEventsV2/{eventInterfaces.jsx => eventInterfaces.tsx} (84%) diff --git a/src/sentry/static/sentry/app/views/organizationEventsV2/eventInterfaces.jsx b/src/sentry/static/sentry/app/views/organizationEventsV2/eventInterfaces.tsx similarity index 84% rename from src/sentry/static/sentry/app/views/organizationEventsV2/eventInterfaces.jsx rename to src/sentry/static/sentry/app/views/organizationEventsV2/eventInterfaces.tsx index 9ee1ee01fba3a0..31db665f6d23c2 100644 --- a/src/sentry/static/sentry/app/views/organizationEventsV2/eventInterfaces.jsx +++ b/src/sentry/static/sentry/app/views/organizationEventsV2/eventInterfaces.tsx @@ -11,6 +11,7 @@ import EventExtraData from 'app/components/events/extraData'; import EventPackageData from 'app/components/events/packageData'; import NavTabs from 'app/components/navTabs'; import {objectIsEmpty, toTitleCase} from 'app/utils'; +import {Event} from 'app/types'; const OTHER_SECTIONS = { context: EventExtraData, @@ -18,17 +19,23 @@ const OTHER_SECTIONS = { device: EventDevice, }; +type ActiveTabProps = { + projectId: string; + event: Event; + activeTab: string; +}; + /** * Render the currently active event interface tab. * Some but not all interface elements require a projectId. */ -const ActiveTab = props => { +const ActiveTab = (props: ActiveTabProps) => { const {projectId, event, activeTab} = props; if (!activeTab) { return null; } const entry = event.entries.find(item => item.type === activeTab); - if (INTERFACES[activeTab]) { + if (INTERFACES[activeTab] && entry) { const Component = INTERFACES[activeTab]; return ( { console.error('Unregistered interface: ' + activeTab); return ( - +

{t('There was an error rendering this data.')}

); @@ -62,13 +73,24 @@ ActiveTab.propTypes = { projectId: PropTypes.string.isRequired, }; -class EventInterfaces extends React.Component { +type EventInterfacesProps = { + event: Event; + projectId: string; +}; +type EventInterfacesState = { + activeTab: string; +}; + +class EventInterfaces extends React.Component< + EventInterfacesProps, + EventInterfacesState +> { static propTypes = { event: SentryTypes.Event.isRequired, projectId: PropTypes.string.isRequired, }; - constructor(props) { + constructor(props: EventInterfacesProps) { super(props); this.state = { activeTab: props.event.entries[0].type, @@ -89,7 +111,7 @@ class EventInterfaces extends React.Component { return null; } const type = entry.type; - const classname = type === activeTab ? 'active' : null; + const classname = type === activeTab ? 'active' : undefined; return (
  • Date: Sat, 10 Aug 2019 02:56:56 -0400 Subject: [PATCH 16/27] src/sentry/static/sentry/app/views/organizationEventsV2/eventDetails.tsx --- .../views/organizationEventsV2/eventDetails.tsx | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/sentry/static/sentry/app/views/organizationEventsV2/eventDetails.tsx b/src/sentry/static/sentry/app/views/organizationEventsV2/eventDetails.tsx index b9027ab7c90515..c88c5392ffbaee 100644 --- a/src/sentry/static/sentry/app/views/organizationEventsV2/eventDetails.tsx +++ b/src/sentry/static/sentry/app/views/organizationEventsV2/eventDetails.tsx @@ -1,5 +1,6 @@ import React from 'react'; import {browserHistory} from 'react-router'; +import {Params} from 'react-router/lib/Router'; import PropTypes from 'prop-types'; import {omit} from 'lodash'; import {css} from 'react-emotion'; @@ -17,11 +18,15 @@ import {ReactRouterLocation} from 'app/types/reactRouter'; import EventModalContent from './eventModalContent'; import {EventQuery, getQuery} from './utils'; -const slugValidator = function(props, propName, componentName) { +const slugValidator = function( + props: {[key: string]: any}, + propName: string, + componentName: string +) { const value = props[propName]; // Accept slugs that look like: // * project-slug:deadbeef - if (value && !/^(?:[^:]+):(?:[a-f0-9]+)$/.test(value)) { + if (value && typeof value === 'string' && !/^(?:[^:]+):(?:[a-f0-9]+)$/.test(value)) { return new Error(`Invalid value for ${propName} provided to ${componentName}.`); } return null; @@ -45,14 +50,14 @@ type Props = { location: ReactRouterLocation; eventSlug: string; view: EventView; - params: any; + params: Params; }; type State = { event: Event; }; -class EventDetails extends AsyncComponent { +class EventDetails extends AsyncComponent { static propTypes: any = { organization: SentryTypes.Organization.isRequired, eventSlug: slugValidator, @@ -60,7 +65,7 @@ class EventDetails extends AsyncComponent { view: PropTypes.object.isRequired, }; - getEndpoints() { + getEndpoints(): Array<[string, string, {query: EventQuery}]> { const {organization, eventSlug, view, location} = this.props; const query = getQuery(view, location); const url = `/organizations/${organization.slug}/events/${eventSlug}/`; @@ -92,7 +97,6 @@ class EventDetails extends AsyncComponent { return ( Date: Fri, 9 Aug 2019 22:48:50 -0400 Subject: [PATCH 17/27] src/sentry/static/sentry/app/views/organizationEventsV2/styles.tsx --- .../app/views/organizationEventsV2/{styles.jsx => styles.tsx} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/sentry/static/sentry/app/views/organizationEventsV2/{styles.jsx => styles.tsx} (100%) diff --git a/src/sentry/static/sentry/app/views/organizationEventsV2/styles.jsx b/src/sentry/static/sentry/app/views/organizationEventsV2/styles.tsx similarity index 100% rename from src/sentry/static/sentry/app/views/organizationEventsV2/styles.jsx rename to src/sentry/static/sentry/app/views/organizationEventsV2/styles.tsx From 75744c2ab56d9d0f3ea1e346cb5c599191ecc154 Mon Sep 17 00:00:00 2001 From: Alberto Leal Date: Sat, 10 Aug 2019 01:24:19 -0400 Subject: [PATCH 18/27] src/sentry/static/sentry/app/types/index.tsx --- src/sentry/static/sentry/app/types/index.tsx | 107 ++++++++++++++++++- 1 file changed, 104 insertions(+), 3 deletions(-) diff --git a/src/sentry/static/sentry/app/types/index.tsx b/src/sentry/static/sentry/app/types/index.tsx index aa4c5c4c0afed2..09a09f480d8f14 100644 --- a/src/sentry/static/sentry/app/types/index.tsx +++ b/src/sentry/static/sentry/app/types/index.tsx @@ -1,3 +1,5 @@ +import {SpanEntry} from 'app/views/organizationEventsV2/transactionView/types'; + export type Organization = { id: string; slug: string; @@ -64,19 +66,50 @@ export type EventAttachment = { type: string; }; -// This type is incomplete -export type Event = { +type EntryType = { + data: {[key: string]: any} | any[]; + type: string; +}; + +export type EventTag = {key: string; value: string}; + +type SentryEventBase = { id: string; eventID: string; groupID?: string; - type: string; title: string; culprit: string; metadata: EventMetadata; message: string; platform?: string; + dateCreated?: string; + endTimestamp?: number; + entries: EntryType[]; + + previousEventID?: string; + nextEventID?: string; + projectSlug: string; + + tags: EventTag[]; + + size: number; + + location: string; + + oldestEventID: string | null; + latestEventID: string | null; }; +// This type is incomplete +export type Event = + | ({type: string} & SentryEventBase) + | { + type: 'transaction'; + entries: SpanEntry[]; + startTimestamp: number; + endTimestamp: number; + } & SentryEventBase; + export type EventsStatsData = [number, {count: number}[]][]; export type EventsStats = { @@ -190,3 +223,71 @@ export type Config = { }; distPrefix: string; }; + +type Metadata = { + value: string; + message: string; + directive: string; + type: string; + title: string; + uri: string; +}; + +type EventOrGroupType = [ + 'error', + 'csp', + 'hpkp', + 'expectct', + 'expectstaple', + 'default', + 'transaction' +]; + +// TODO(ts): incomplete +export type Group = { + id: string; + annotations: string[]; + assignedTo: User; + count: string; + culprit: string; + firstSeen: string; + hasSeen: boolean; + isBookmarked: boolean; + isPublic: boolean; + isSubscribed: boolean; + lastSeen: string; + level: string; + logger: string; + metadata: Metadata; + numComments: number; + permalink: string; + project: { + name: string; + slug: string; + }; + shareId: string; + shortId: string; + status: string; + statusDetails: {}; + title: string; + type: EventOrGroupType; + userCount: number; + seenBy: User[]; +}; + +export type EventView = { + id: string; + name: string; + data: { + fields: string[]; + columnNames: string[]; + sort: string[]; + query?: string; + + // TODO: removed as of https://github.com/getsentry/sentry/pull/14321 + // groupby: string[]; + // orderby: string[]; + }; + tags: string[]; + columnWidths: string[]; +}; From c930a6cca56f437ea21cca7507c4e0694bca847a Mon Sep 17 00:00:00 2001 From: Alberto Leal Date: Sat, 10 Aug 2019 15:18:43 -0400 Subject: [PATCH 19/27] src/sentry/static/sentry/app/views/events/utils/eventsRequest.tsx --- .../static/sentry/app/views/events/utils/eventsRequest.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sentry/static/sentry/app/views/events/utils/eventsRequest.tsx b/src/sentry/static/sentry/app/views/events/utils/eventsRequest.tsx index c6f550b8488502..86d7e715c49ddb 100644 --- a/src/sentry/static/sentry/app/views/events/utils/eventsRequest.tsx +++ b/src/sentry/static/sentry/app/views/events/utils/eventsRequest.tsx @@ -318,7 +318,7 @@ class EventsRequest extends React.PureComponent Date: Fri, 9 Aug 2019 23:46:10 -0400 Subject: [PATCH 20/27] src/sentry/static/sentry/app/utils.tsx --- src/sentry/static/sentry/app/utils.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sentry/static/sentry/app/utils.tsx b/src/sentry/static/sentry/app/utils.tsx index 7eed2f0192b55e..29383b3c067d11 100644 --- a/src/sentry/static/sentry/app/utils.tsx +++ b/src/sentry/static/sentry/app/utils.tsx @@ -238,7 +238,7 @@ export function isWebpackChunkLoadingError(error: Error): boolean { ); } -export function deepFreeze(object: {[x: string]: any}) { +export function deepFreeze(object: T) { // Retrieve the property names defined on object const propNames = Object.getOwnPropertyNames(object); // Freeze properties before freezing self From 7b1b48ba3f7fc493096ad6c580f0c5bdc5fbc903 Mon Sep 17 00:00:00 2001 From: Alberto Leal Date: Tue, 13 Aug 2019 04:14:17 -0400 Subject: [PATCH 21/27] adjust transactionview types --- .../app/views/organizationEventsV2/transactionView/index.tsx | 4 ++-- .../views/organizationEventsV2/transactionView/traceView.tsx | 4 ++-- .../app/views/organizationEventsV2/transactionView/types.tsx | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/sentry/static/sentry/app/views/organizationEventsV2/transactionView/index.tsx b/src/sentry/static/sentry/app/views/organizationEventsV2/transactionView/index.tsx index 57d5ae902c0d91..71a531abe3d980 100644 --- a/src/sentry/static/sentry/app/views/organizationEventsV2/transactionView/index.tsx +++ b/src/sentry/static/sentry/app/views/organizationEventsV2/transactionView/index.tsx @@ -5,11 +5,11 @@ import SentryTypes from 'app/sentryTypes'; import {Panel, PanelHeader, PanelBody} from 'app/components/panels'; -import {SentryEvent} from './types'; +import {SentryTransactionEvent} from './types'; import TraceView from './traceView'; type PropType = { - event: SentryEvent; + event: SentryTransactionEvent; }; class TransanctionView extends React.Component { diff --git a/src/sentry/static/sentry/app/views/organizationEventsV2/transactionView/traceView.tsx b/src/sentry/static/sentry/app/views/organizationEventsV2/transactionView/traceView.tsx index 36702cb70ff403..bdcfd23c8f842f 100644 --- a/src/sentry/static/sentry/app/views/organizationEventsV2/transactionView/traceView.tsx +++ b/src/sentry/static/sentry/app/views/organizationEventsV2/transactionView/traceView.tsx @@ -6,7 +6,7 @@ import EmptyStateWarning from 'app/components/emptyStateWarning'; import DragManager, {DragManagerChildrenProps} from './dragManager'; import SpanTree from './spanTree'; -import {SpanType, SpanEntry, SentryEvent, ParsedTraceType} from './types'; +import {SpanType, SpanEntry, SentryTransactionEvent, ParsedTraceType} from './types'; import {isValidSpanID} from './utils'; import TraceViewMinimap from './minimap'; import * as CursorGuideHandler from './cursorGuideHandler'; @@ -18,7 +18,7 @@ type TraceContextType = { }; type PropType = { - event: Readonly; + event: Readonly; }; class TraceView extends React.Component { diff --git a/src/sentry/static/sentry/app/views/organizationEventsV2/transactionView/types.tsx b/src/sentry/static/sentry/app/views/organizationEventsV2/transactionView/types.tsx index 289e8b8a3e47b8..baa4045b7c3568 100644 --- a/src/sentry/static/sentry/app/views/organizationEventsV2/transactionView/types.tsx +++ b/src/sentry/static/sentry/app/views/organizationEventsV2/transactionView/types.tsx @@ -15,7 +15,7 @@ export type SpanEntry = { data: Array; }; -export type SentryEvent = { +export type SentryTransactionEvent = { entries: Array; startTimestamp: number; endTimestamp: number; From 5fd41f620c2b765b38a9a9f9e1ff50757c226c8e Mon Sep 17 00:00:00 2001 From: Alberto Leal Date: Wed, 21 Aug 2019 17:40:33 -0400 Subject: [PATCH 22/27] replace react router stuffs --- .../app/views/organizationEventsV2/eventDetails.tsx | 4 ++-- .../app/views/organizationEventsV2/eventModalContent.tsx | 4 ++-- .../sentry/app/views/organizationEventsV2/events.tsx | 6 +++--- .../app/views/organizationEventsV2/modalLineGraph.tsx | 4 ++-- .../app/views/organizationEventsV2/modalPagination.tsx | 6 +++--- .../app/views/organizationEventsV2/relatedEvents.tsx | 4 ++-- .../sentry/app/views/organizationEventsV2/sortLink.tsx | 4 ++-- .../sentry/app/views/organizationEventsV2/table.tsx | 4 ++-- .../static/sentry/app/views/organizationEventsV2/tags.tsx | 4 ++-- .../sentry/app/views/organizationEventsV2/tagsTable.tsx | 1 - .../sentry/app/views/organizationEventsV2/utils.tsx | 8 ++++---- 11 files changed, 24 insertions(+), 25 deletions(-) diff --git a/src/sentry/static/sentry/app/views/organizationEventsV2/eventDetails.tsx b/src/sentry/static/sentry/app/views/organizationEventsV2/eventDetails.tsx index c88c5392ffbaee..37aedff98ea871 100644 --- a/src/sentry/static/sentry/app/views/organizationEventsV2/eventDetails.tsx +++ b/src/sentry/static/sentry/app/views/organizationEventsV2/eventDetails.tsx @@ -1,5 +1,6 @@ import React from 'react'; import {browserHistory} from 'react-router'; +import {Location} from 'history'; import {Params} from 'react-router/lib/Router'; import PropTypes from 'prop-types'; import {omit} from 'lodash'; @@ -13,7 +14,6 @@ import withApi from 'app/utils/withApi'; import theme from 'app/utils/theme'; import space from 'app/styles/space'; import {Organization, EventView, Event} from 'app/types'; -import {ReactRouterLocation} from 'app/types/reactRouter'; import EventModalContent from './eventModalContent'; import {EventQuery, getQuery} from './utils'; @@ -47,7 +47,7 @@ const modalStyles = css` type Props = { organization: Organization; - location: ReactRouterLocation; + location: Location; eventSlug: string; view: EventView; params: Params; diff --git a/src/sentry/static/sentry/app/views/organizationEventsV2/eventModalContent.tsx b/src/sentry/static/sentry/app/views/organizationEventsV2/eventModalContent.tsx index 0ad0214486fdc9..eee8eb7e840527 100644 --- a/src/sentry/static/sentry/app/views/organizationEventsV2/eventModalContent.tsx +++ b/src/sentry/static/sentry/app/views/organizationEventsV2/eventModalContent.tsx @@ -11,7 +11,7 @@ import space from 'app/styles/space'; import getDynamicText from 'app/utils/getDynamicText'; import {getMessage, getTitle} from 'app/utils/events'; import {Event, Organization, EventView} from 'app/types'; -import {ReactRouterLocation} from 'app/types/reactRouter'; +import {Location} from 'history'; import EventInterfaces from './eventInterfaces'; import LinkedIssuePreview from './linkedIssuePreview'; @@ -27,7 +27,7 @@ type EventModalContentProps = { event: Event; projectId: string; organization: Organization; - location: ReactRouterLocation; + location: Location; view: EventView; }; diff --git a/src/sentry/static/sentry/app/views/organizationEventsV2/events.tsx b/src/sentry/static/sentry/app/views/organizationEventsV2/events.tsx index 9ce48c9ac174db..76e077ddbd71f1 100644 --- a/src/sentry/static/sentry/app/views/organizationEventsV2/events.tsx +++ b/src/sentry/static/sentry/app/views/organizationEventsV2/events.tsx @@ -3,7 +3,7 @@ import PropTypes from 'prop-types'; import styled from 'react-emotion'; import {omit, isEqual} from 'lodash'; import * as ReactRouter from 'react-router'; -import {ReactRouterLocation} from 'app/types/reactRouter'; +import {Location} from 'history'; import {Organization, EventView} from 'app/types'; import SentryTypes from 'app/sentryTypes'; @@ -29,7 +29,7 @@ const CHART_AXIS_OPTIONS = [ type EventsProps = { router: ReactRouter.InjectedRouter; - location: ReactRouterLocation; + location: Location; organization: Organization; view: EventView; }; @@ -93,7 +93,7 @@ export default class Events extends React.Component { } type EventsTableProps = { - location: ReactRouterLocation; + location: Location; organization: Organization; view: EventView; }; diff --git a/src/sentry/static/sentry/app/views/organizationEventsV2/modalLineGraph.tsx b/src/sentry/static/sentry/app/views/organizationEventsV2/modalLineGraph.tsx index a16e5387a1fd65..6f19dfb6a815da 100644 --- a/src/sentry/static/sentry/app/views/organizationEventsV2/modalLineGraph.tsx +++ b/src/sentry/static/sentry/app/views/organizationEventsV2/modalLineGraph.tsx @@ -1,6 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import {browserHistory} from 'react-router'; +import {Location} from 'history'; import {omit} from 'lodash'; import {Client} from 'app/api'; @@ -20,7 +21,6 @@ import withApi from 'app/utils/withApi'; import withGlobalSelection from 'app/utils/withGlobalSelection'; import theme from 'app/utils/theme'; import {Event, Organization, EventView} from 'app/types'; -import {ReactRouterLocation} from 'app/types/reactRouter'; import {MODAL_QUERY_KEYS, PIN_ICON} from './data'; import {getQueryString} from './utils'; @@ -133,7 +133,7 @@ const handleClick = async function( type ModalLineGraphProps = { api: Client; organization: Organization; - location: ReactRouterLocation; + location: Location; currentEvent: Event; view: EventView; // TODO(ts): adjust diff --git a/src/sentry/static/sentry/app/views/organizationEventsV2/modalPagination.tsx b/src/sentry/static/sentry/app/views/organizationEventsV2/modalPagination.tsx index 038f930bf05aed..8492138d560e4e 100644 --- a/src/sentry/static/sentry/app/views/organizationEventsV2/modalPagination.tsx +++ b/src/sentry/static/sentry/app/views/organizationEventsV2/modalPagination.tsx @@ -3,13 +3,13 @@ import PropTypes from 'prop-types'; import styled from 'react-emotion'; import isPropValid from '@emotion/is-prop-valid'; import {omit} from 'lodash'; +import {Location} from 'history'; import {t} from 'app/locale'; import Link from 'app/components/links/link'; import SentryTypes from 'app/sentryTypes'; import InlineSvg from 'app/components/inlineSvg'; import space from 'app/styles/space'; -import {ReactRouterLocation} from 'app/types/reactRouter'; import {Event} from 'app/types'; import {MODAL_QUERY_KEYS} from './data'; @@ -25,7 +25,7 @@ type LinksType = { /** * Generate a mapping of link names => link targets for pagination */ -function buildTargets(event: Event, location: ReactRouterLocation): LinksType { +function buildTargets(event: Event, location: Location): LinksType { // Remove slug related keys as we need to create new ones const baseQuery = omit(location.query, MODAL_QUERY_KEYS); @@ -58,7 +58,7 @@ function buildTargets(event: Event, location: ReactRouterLocation): LinksType { type Props = { event: Event; - location: ReactRouterLocation; + location: Location; }; const ModalPagination = (props: Props) => { diff --git a/src/sentry/static/sentry/app/views/organizationEventsV2/relatedEvents.tsx b/src/sentry/static/sentry/app/views/organizationEventsV2/relatedEvents.tsx index 3af58954012b5b..5e8d9eb91f1fe1 100644 --- a/src/sentry/static/sentry/app/views/organizationEventsV2/relatedEvents.tsx +++ b/src/sentry/static/sentry/app/views/organizationEventsV2/relatedEvents.tsx @@ -2,7 +2,7 @@ import React from 'react'; import styled from 'react-emotion'; import PropTypes from 'prop-types'; import {omit} from 'lodash'; -import {ReactRouterLocation} from 'app/types/reactRouter'; +import {Location} from 'history'; import {Organization, EventView, Event, Project} from 'app/types'; import {t} from 'app/locale'; @@ -22,7 +22,7 @@ import {MODAL_QUERY_KEYS} from './data'; import {EventQuery} from './utils'; type Props = { - location: ReactRouterLocation; + location: Location; organization: Organization; view: EventView; event: Event; diff --git a/src/sentry/static/sentry/app/views/organizationEventsV2/sortLink.tsx b/src/sentry/static/sentry/app/views/organizationEventsV2/sortLink.tsx index 944b69adc6c955..6ad1c15d1acd03 100644 --- a/src/sentry/static/sentry/app/views/organizationEventsV2/sortLink.tsx +++ b/src/sentry/static/sentry/app/views/organizationEventsV2/sortLink.tsx @@ -1,7 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import styled from 'react-emotion'; -import {ReactRouterLocation} from 'app/types/reactRouter'; +import {Location} from 'history'; import InlineSvg from 'app/components/inlineSvg'; import Link from 'app/components/links/link'; @@ -10,7 +10,7 @@ type Props = { title: string; sortKey: string; defaultSort: string | null; - location: ReactRouterLocation; + location: Location; }; class SortLink extends React.Component { diff --git a/src/sentry/static/sentry/app/views/organizationEventsV2/table.tsx b/src/sentry/static/sentry/app/views/organizationEventsV2/table.tsx index 4b70e08ee8433b..b05b59819f3242 100644 --- a/src/sentry/static/sentry/app/views/organizationEventsV2/table.tsx +++ b/src/sentry/static/sentry/app/views/organizationEventsV2/table.tsx @@ -2,6 +2,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import styled, {css} from 'react-emotion'; import {omit} from 'lodash'; +import {Location} from 'history'; import SentryTypes from 'app/sentryTypes'; import {Panel, PanelHeader, PanelBody, PanelItem} from 'app/components/panels'; @@ -10,7 +11,6 @@ import LoadingContainer from 'app/components/loading/loadingContainer'; import {t} from 'app/locale'; import space from 'app/styles/space'; import {EventView, Organization} from 'app/types'; -import {ReactRouterLocation} from 'app/types/reactRouter'; import {FIELD_FORMATTERS, SPECIAL_FIELDS} from './data'; import {getFieldRenderer} from './utils'; @@ -19,7 +19,7 @@ import SortLink from './sortLink'; type Props = { view: EventView; isLoading: boolean; - location: ReactRouterLocation; + location: Location; organization: Organization; // TODO(ts): adjust this type data: any; diff --git a/src/sentry/static/sentry/app/views/organizationEventsV2/tags.tsx b/src/sentry/static/sentry/app/views/organizationEventsV2/tags.tsx index d033932e5301a6..d96c9b5b24fa97 100644 --- a/src/sentry/static/sentry/app/views/organizationEventsV2/tags.tsx +++ b/src/sentry/static/sentry/app/views/organizationEventsV2/tags.tsx @@ -2,6 +2,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import styled from 'react-emotion'; import {isEqual, omit} from 'lodash'; +import {Location} from 'history'; import * as Sentry from '@sentry/browser'; import {Client} from 'app/api'; @@ -10,7 +11,6 @@ import Placeholder from 'app/components/placeholder'; import TagDistributionMeter from 'app/components/tagDistributionMeter'; import withApi from 'app/utils/withApi'; import {Organization, EventView} from 'app/types'; -import {ReactRouterLocation} from 'app/types/reactRouter'; import { fetchTagDistribution, @@ -26,7 +26,7 @@ type Props = { api: Client; organization: Organization; view: EventView; - location: ReactRouterLocation; + location: Location; }; type State = { diff --git a/src/sentry/static/sentry/app/views/organizationEventsV2/tagsTable.tsx b/src/sentry/static/sentry/app/views/organizationEventsV2/tagsTable.tsx index ef3f5d0b055613..4a077600eb9e28 100644 --- a/src/sentry/static/sentry/app/views/organizationEventsV2/tagsTable.tsx +++ b/src/sentry/static/sentry/app/views/organizationEventsV2/tagsTable.tsx @@ -3,7 +3,6 @@ import styled from 'react-emotion'; import PropTypes from 'prop-types'; import * as ReactRouter from 'react-router'; -import {ReactRouterLocation} from 'app/types/reactRouter'; import Link from 'app/components/links/link'; import Tooltip from 'app/components/tooltip'; import {t} from 'app/locale'; diff --git a/src/sentry/static/sentry/app/views/organizationEventsV2/utils.tsx b/src/sentry/static/sentry/app/views/organizationEventsV2/utils.tsx index 1b4a00708e6499..bab44b15628da1 100644 --- a/src/sentry/static/sentry/app/views/organizationEventsV2/utils.tsx +++ b/src/sentry/static/sentry/app/views/organizationEventsV2/utils.tsx @@ -1,5 +1,5 @@ import {partial, pick, get} from 'lodash'; -import {ReactRouterLocation} from 'app/types/reactRouter'; +import {Location} from 'history'; import {Client} from 'app/api'; import {EventView} from 'app/types'; @@ -47,7 +47,7 @@ export function hasAggregateField(view) { * @param {Object} view * @returns {Object} */ -export function getQuery(view: EventView, location: ReactRouterLocation) { +export function getQuery(view: EventView, location: Location) { const fields: Array = get(view, 'data.fields', []); type LocationQuery = { @@ -91,7 +91,7 @@ export function getQuery(view: EventView, location: ReactRouterLocation) { * @param {Object} view defaults containing `.data.query` * @param {Location} browser location */ -export function getQueryString(view: EventView, location: ReactRouterLocation): string { +export function getQueryString(view: EventView, location: Location): string { const queryParts: Array = []; if (view.data.query) { queryParts.push(view.data.query); @@ -125,7 +125,7 @@ export function getQueryString(view: EventView, location: ReactRouterLocation): export function getEventTagSearchUrl( tagKey: string, tagValue: string, - location: ReactRouterLocation + location: Location ) { const query = {...location.query}; // Add tag key/value to search From 825894a34f5dea73bd73bcd628c982ac31215726 Mon Sep 17 00:00:00 2001 From: Alberto Leal Date: Thu, 22 Aug 2019 12:36:51 -0400 Subject: [PATCH 23/27] update @type/history --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 4beb37e25837ea..13fcb3e50b1380 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1746,9 +1746,9 @@ "@types/node" "*" "@types/history@^3": - version "3.2.3" - resolved "https://registry.yarnpkg.com/@types/history/-/history-3.2.3.tgz#2416fee5cac641da2d05a905de5af5cb50162f60" - integrity sha512-s4SNWd31cmFP52ilv3LKCh344ayIXmfmcfExsegGspgnk/pQh75Yo6v49uzSE1oFMXp+Sz4GVnesL7rgybX9tQ== + version "3.2.4" + resolved "https://registry.yarnpkg.com/@types/history/-/history-3.2.4.tgz#0b6c62240d1fac020853aa5608758991d9f6ef3d" + integrity sha512-q7x8QeCRk2T6DR2UznwYW//mpN5uNlyajkewH2xd1s1ozCS4oHFRg2WMusxwLFlE57EkUYsd/gCapLBYzV3ffg== "@types/invariant@^2.2.29": version "2.2.29" From 110d7a54354ad4cc670a194aa48efa36b0336e80 Mon Sep 17 00:00:00 2001 From: Alberto Leal Date: Thu, 22 Aug 2019 12:40:01 -0400 Subject: [PATCH 24/27] add getFirstQueryString --- .../app/views/organizationEventsV2/utils.tsx | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/sentry/static/sentry/app/views/organizationEventsV2/utils.tsx b/src/sentry/static/sentry/app/views/organizationEventsV2/utils.tsx index bab44b15628da1..977fc5ed6c8c6e 100644 --- a/src/sentry/static/sentry/app/views/organizationEventsV2/utils.tsx +++ b/src/sentry/static/sentry/app/views/organizationEventsV2/utils.tsx @@ -226,3 +226,30 @@ export function getFieldRenderer(field: string, meta) { } return partial(FIELD_FORMATTERS.string.renderFunc, fieldName); } + +/** + * Get the first query string of a given name if there are multiple occurrences of it + * e.g. foo=42&foo=bar ==> foo=42 is the first occurrence for 'foo' and "42" will be returned. + * + * @param query query string map + * @param name name of the query string field + */ +export function getFirstQueryString( + query: {[key: string]: string | string[] | null | undefined}, + name: string, + defaultValue?: string +): string | undefined { + const needle = query[name]; + + if (typeof needle === 'string') { + return needle; + } + + if (Array.isArray(needle) && needle.length > 0) { + if (typeof needle[0] === 'string') { + return needle[0]; + } + } + + return defaultValue; +} From 4d29c4105361b952df0049cb5b3b3925d39d5772 Mon Sep 17 00:00:00 2001 From: Alberto Leal Date: Thu, 22 Aug 2019 12:40:30 -0400 Subject: [PATCH 25/27] update index.tsx --- .../sentry/app/views/organizationEventsV2/index.tsx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/sentry/static/sentry/app/views/organizationEventsV2/index.tsx b/src/sentry/static/sentry/app/views/organizationEventsV2/index.tsx index 2dc5fc9d67eb22..982d3fd8da3ccb 100644 --- a/src/sentry/static/sentry/app/views/organizationEventsV2/index.tsx +++ b/src/sentry/static/sentry/app/views/organizationEventsV2/index.tsx @@ -21,7 +21,7 @@ import withOrganization from 'app/utils/withOrganization'; import Events from './events'; import EventDetails from './eventDetails'; import {ALL_VIEWS} from './data'; -import {getCurrentView} from './utils'; +import {getCurrentView, getFirstQueryString} from './utils'; type Props = { organization: Organization; @@ -39,7 +39,8 @@ class OrganizationEventsV2 extends React.Component { renderTabs(): React.ReactNode { const {location} = this.props; - const currentView = getCurrentView(location.query.view); + const firstView = getFirstQueryString(location.query, 'view'); + const currentView = getCurrentView(firstView); return ( @@ -66,8 +67,10 @@ class OrganizationEventsV2 extends React.Component { render() { const {organization, location, router} = this.props; - const {eventSlug} = location.query; - const currentView = getCurrentView(location.query.view); + const eventSlug = getFirstQueryString(location.query, 'eventSlug'); + const view = getFirstQueryString(location.query, 'view'); + + const currentView = getCurrentView(view); return ( From 7a619b25613e0cdf11750b7877ed795c56a7fd83 Mon Sep 17 00:00:00 2001 From: Alberto Leal Date: Thu, 22 Aug 2019 15:55:53 -0400 Subject: [PATCH 26/27] src/sentry/static/sentry/app/views/organizationEventsV2/modalPagination.tsx --- .../sentry/app/views/organizationEventsV2/modalPagination.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sentry/static/sentry/app/views/organizationEventsV2/modalPagination.tsx b/src/sentry/static/sentry/app/views/organizationEventsV2/modalPagination.tsx index 8492138d560e4e..9400cbd95a5de1 100644 --- a/src/sentry/static/sentry/app/views/organizationEventsV2/modalPagination.tsx +++ b/src/sentry/static/sentry/app/views/organizationEventsV2/modalPagination.tsx @@ -106,9 +106,9 @@ ModalPagination.propTypes = { const StyledLink = styled(Link, { shouldForwardProp: isPropValid, -})<{theme: any; disabled: boolean; fontSizeMedium: string; isLast: boolean}>` +})<{theme: any; disabled: boolean; isLast: boolean}>` color: ${p => (p.disabled ? p.theme.disabled : p.theme.gray3)}; - font-size: ${p => p.fontSizeMedium}; + font-size: ${p => p.theme.fontSizeMedium}; text-align: center; padding: ${space(0.5)} ${space(1.5)}; ${p => (p.isLast ? '' : `border-right: 1px solid ${p.theme.borderDark};`)} From dd7d0101b8f07e9c6101bd2da3ec3ac1068a9e25 Mon Sep 17 00:00:00 2001 From: Alberto Leal Date: Thu, 22 Aug 2019 15:58:56 -0400 Subject: [PATCH 27/27] per_page --- .../static/sentry/app/views/organizationEventsV2/utils.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sentry/static/sentry/app/views/organizationEventsV2/utils.tsx b/src/sentry/static/sentry/app/views/organizationEventsV2/utils.tsx index 977fc5ed6c8c6e..f688c977dd068c 100644 --- a/src/sentry/static/sentry/app/views/organizationEventsV2/utils.tsx +++ b/src/sentry/static/sentry/app/views/organizationEventsV2/utils.tsx @@ -23,6 +23,7 @@ export type EventQuery = { project?: string; sort?: string | string[]; query: string; + per_page?: number; }; /**