Skip to content

chore(ts): Initial typescript conversion in preparation of discover v2 #14345

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 27 commits into from
Aug 22, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
d77c788
src/sentry/static/sentry/app/views/organizationEventsV2/data.tsx
dashed Aug 15, 2019
a1b6c1d
src/sentry/static/sentry/app/views/organizationEventsV2/utils.tsx
dashed Aug 15, 2019
324660f
src/sentry/static/sentry/app/views/organizationEventsV2/events.tsx
dashed Aug 10, 2019
eee80c7
src/sentry/static/sentry/app/views/organizationEventsV2/linkedIssuePr…
dashed Aug 10, 2019
7cc11ae
src/sentry/static/sentry/app/views/organizationEventsV2/eventModalCon…
dashed Aug 10, 2019
b307b86
src/sentry/static/sentry/app/views/organizationEventsV2/table.tsx
dashed Aug 10, 2019
31bce2b
src/sentry/static/sentry/app/views/organizationEventsV2/modalPaginati…
dashed Aug 10, 2019
5b7cec3
src/sentry/static/sentry/app/views/organizationEventsV2/relatedEvents…
dashed Aug 10, 2019
0a34af6
src/sentry/static/sentry/app/views/organizationEventsV2/index.tsx
dashed Aug 10, 2019
4fd036d
src/sentry/static/sentry/app/views/organizationEventsV2/eventDetails.tsx
dashed Aug 10, 2019
aa8bcbd
src/sentry/static/sentry/app/views/organizationEventsV2/modalLineGrap…
dashed Aug 10, 2019
60886de
src/sentry/static/sentry/app/views/organizationEventsV2/tags.tsx
dashed Aug 10, 2019
87677b3
src/sentry/static/sentry/app/views/organizationEventsV2/tagsTable.tsx
dashed Aug 10, 2019
761aa6b
src/sentry/static/sentry/app/views/organizationEventsV2/sortLink.tsx
dashed Aug 10, 2019
92b78e7
src/sentry/static/sentry/app/views/organizationEventsV2/eventInterfac…
dashed Aug 10, 2019
279659b
src/sentry/static/sentry/app/views/organizationEventsV2/eventDetails.tsx
dashed Aug 10, 2019
1896511
src/sentry/static/sentry/app/views/organizationEventsV2/styles.tsx
dashed Aug 10, 2019
75744c2
src/sentry/static/sentry/app/types/index.tsx
dashed Aug 10, 2019
c930a6c
src/sentry/static/sentry/app/views/events/utils/eventsRequest.tsx
dashed Aug 10, 2019
a75d953
src/sentry/static/sentry/app/utils.tsx
dashed Aug 10, 2019
7b1b48b
adjust transactionview types
dashed Aug 13, 2019
5fd41f6
replace react router stuffs
dashed Aug 21, 2019
825894a
update @type/history
dashed Aug 22, 2019
110d7a5
add getFirstQueryString
dashed Aug 22, 2019
4d29c41
update index.tsx
dashed Aug 22, 2019
7a619b2
src/sentry/static/sentry/app/views/organizationEventsV2/modalPaginati…
dashed Aug 22, 2019
dd7d010
per_page
dashed Aug 22, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 104 additions & 3 deletions src/sentry/static/sentry/app/types/index.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import {SpanEntry} from 'app/views/organizationEventsV2/transactionView/types';

export type Organization = {
id: string;
slug: string;
Expand Down Expand Up @@ -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 = {
Expand Down Expand Up @@ -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: {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Longer term, I want to fold down data as this extra layer isn't providing any value.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep. I'll try to do this in #14403

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[];
};
2 changes: 1 addition & 1 deletion src/sentry/static/sentry/app/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ export function isWebpackChunkLoadingError(error: Error): boolean {
);
}

export function deepFreeze(object: {[x: string]: any}) {
export function deepFreeze<T>(object: T) {
// Retrieve the property names defined on object
const propNames = Object.getOwnPropertyNames(object);
// Freeze properties before freezing self
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ class EventsRequest extends React.PureComponent<EventsRequestProps, EventsReques
? this.transformPreviousPeriodData(current, previous)
: null;
const timeAggregatedData = includeTimeAggregation
? this.transformAggregatedTimeseries(current, timeAggregationSeriesName)
? this.transformAggregatedTimeseries(current, timeAggregationSeriesName || '')
: {};
return {
data: transformedData,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<Array<EventView>> = deepFreeze([
{
id: 'all',
name: t('All Events'),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
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';
import {css} from 'react-emotion';
Expand All @@ -11,15 +13,20 @@ 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 EventModalContent from './eventModalContent';
import {getQuery} from './utils';
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;
Expand All @@ -38,15 +45,27 @@ const modalStyles = css`
}
`;

class EventDetails extends AsyncComponent {
static propTypes = {
type Props = {
organization: Organization;
location: Location;
eventSlug: string;
view: EventView;
params: Params;
};

type State = {
event: Event;
};

class EventDetails extends AsyncComponent<Props, State & AsyncComponent['state']> {
static propTypes: any = {
organization: SentryTypes.Organization.isRequired,
eventSlug: slugValidator,
location: PropTypes.object.isRequired,
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}/`;
Expand Down Expand Up @@ -78,7 +97,6 @@ class EventDetails extends AsyncComponent {
return (
<ModalDialog onDismiss={this.onDismiss} className={modalStyles}>
<EventModalContent
onTabChange={this.handleTabChange}
event={event}
projectId={this.projectId}
organization={organization}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,31 @@ 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,
packages: EventPackageData,
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 (
<Component
Expand All @@ -50,7 +57,11 @@ const ActiveTab = props => {
console.error('Unregistered interface: ' + activeTab);

return (
<EventDataSection event={event} type={entry.type} title={entry.type}>
<EventDataSection
event={event}
type={entry && entry.type}
title={entry && entry.type}
>
<p>{t('There was an error rendering this data.')}</p>
</EventDataSection>
);
Expand All @@ -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,
Expand All @@ -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 (
<li key={type} className={classname}>
<a
Expand All @@ -108,7 +130,7 @@ class EventInterfaces extends React.Component {
if (objectIsEmpty(event[section])) {
return null;
}
const classname = section === activeTab ? 'active' : null;
const classname = section === activeTab ? 'active' : undefined;
return (
<li key={section} className={classname}>
<a
Expand Down
Loading