From 58d35e8da21dded5868e1661f24855a2f8784f1f Mon Sep 17 00:00:00 2001 From: Priscila Oliveira Date: Mon, 25 Oct 2021 15:29:41 +0200 Subject: [PATCH 01/15] ref(interface-files): Move files to appropriate folder --- .../interfaces/crashContent/exception/index.tsx | 4 ++-- .../exception/rawContent.tsx} | 7 ++++--- .../crashContent/exception/stackTrace.tsx | 10 +++++----- .../events/interfaces/crashContent/index.tsx | 2 +- .../stackTrace/content.tsx} | 4 ++-- .../stackTrace/contentV2.tsx} | 8 ++++---- .../{stacktrace.tsx => stackTrace/index.tsx} | 15 ++++++--------- .../stackTrace/rawContent.tsx} | 0 .../{cspContent.tsx => csp/content.tsx} | 4 ++-- .../help}/effectiveDirectives.tsx | 0 .../interfaces/{cspHelp => csp/help}/index.tsx | 0 .../interfaces/{csp.tsx => csp/index.tsx} | 13 ++++++++----- .../interfaces/{ => debugMeta}/imageForBar.tsx | 0 .../events/interfaces/debugMeta/index.tsx | 2 +- .../events/interfaces/{ => frame}/assembly.tsx | 0 .../events/interfaces/frame/context.tsx | 16 +++++++++------- .../interfaces/{ => frame}/contextLine.tsx | 0 .../{ => frame}/frameRegisters/index.tsx | 0 .../{ => frame}/frameRegisters/registers.tsx | 0 .../{ => frame}/frameRegisters/utils.tsx | 0 .../{ => frame}/frameRegisters/value.tsx | 0 .../interfaces/{ => frame}/frameVariables.tsx | 3 ++- .../components/events/interfaces/frame/line.tsx | 17 +++++++---------- .../events/interfaces/frame/lineV2/index.tsx | 4 ++-- .../events/interfaces/frame/lineV2/native.tsx | 12 ++++++------ .../{ => frame}/openInContextLine.tsx | 0 .../interfaces/{ => frame}/packageLink.tsx | 0 .../interfaces/{ => frame}/packageStatus.tsx | 4 ++-- .../interfaces/{ => frame}/stacktraceLink.tsx | 0 .../{ => frame}/stacktraceLinkModal.tsx | 0 .../interfaces/{ => frame}/togglableAddress.tsx | 9 +++++---- .../events/interfaces/frame/utils.tsx | 3 ++- static/app/components/stacktracePreview.tsx | 4 ++-- static/app/utils/getStacktraceBody.tsx | 2 +- .../crashContent/index.spec.jsx} | 0 .../stackTrace/content.spec.tsx} | 2 +- .../stackTrace/rawContent.spec.jsx} | 2 +- .../interfaces/{ => frame}/contexts.spec.jsx | 0 .../interfaces/frame/frameRegisters.spec.jsx | 4 ++-- .../{ => frame}/openInContextLine.spec.jsx | 2 +- .../{ => frame}/stacktraceLink.spec.jsx | 2 +- .../{ => frame}/stacktraceLinkModal.spec.jsx | 2 +- 42 files changed, 80 insertions(+), 77 deletions(-) rename static/app/components/events/interfaces/{rawExceptionContent.tsx => crashContent/exception/rawContent.tsx} (95%) rename static/app/components/events/interfaces/{stacktraceContent.tsx => crashContent/stackTrace/content.tsx} (98%) rename static/app/components/events/interfaces/{stacktraceContentV2.tsx => crashContent/stackTrace/contentV2.tsx} (98%) rename static/app/components/events/interfaces/crashContent/{stacktrace.tsx => stackTrace/index.tsx} (78%) rename static/app/components/events/interfaces/{rawStacktraceContent.tsx => crashContent/stackTrace/rawContent.tsx} (100%) rename static/app/components/events/interfaces/{cspContent.tsx => csp/content.tsx} (88%) rename static/app/components/events/interfaces/{cspHelp => csp/help}/effectiveDirectives.tsx (100%) rename static/app/components/events/interfaces/{cspHelp => csp/help}/index.tsx (100%) rename static/app/components/events/interfaces/{csp.tsx => csp/index.tsx} (86%) rename static/app/components/events/interfaces/{ => debugMeta}/imageForBar.tsx (100%) rename static/app/components/events/interfaces/{ => frame}/assembly.tsx (100%) rename static/app/components/events/interfaces/{ => frame}/contextLine.tsx (100%) rename static/app/components/events/interfaces/{ => frame}/frameRegisters/index.tsx (100%) rename static/app/components/events/interfaces/{ => frame}/frameRegisters/registers.tsx (100%) rename static/app/components/events/interfaces/{ => frame}/frameRegisters/utils.tsx (100%) rename static/app/components/events/interfaces/{ => frame}/frameRegisters/value.tsx (100%) rename static/app/components/events/interfaces/{ => frame}/frameVariables.tsx (93%) rename static/app/components/events/interfaces/{ => frame}/openInContextLine.tsx (100%) rename static/app/components/events/interfaces/{ => frame}/packageLink.tsx (100%) rename static/app/components/events/interfaces/{ => frame}/packageStatus.tsx (95%) rename static/app/components/events/interfaces/{ => frame}/stacktraceLink.tsx (100%) rename static/app/components/events/interfaces/{ => frame}/stacktraceLinkModal.tsx (100%) rename static/app/components/events/interfaces/{ => frame}/togglableAddress.tsx (96%) rename tests/js/spec/components/events/{crashContent.spec.jsx => interfaces/crashContent/index.spec.jsx} (100%) rename tests/js/spec/components/events/interfaces/{stacktrace.spec.tsx => crashContent/stackTrace/content.spec.tsx} (99%) rename tests/js/spec/components/events/interfaces/{rawStacktraceContent.spec.jsx => crashContent/stackTrace/rawContent.spec.jsx} (96%) rename tests/js/spec/components/events/interfaces/{ => frame}/contexts.spec.jsx (100%) rename tests/js/spec/components/events/interfaces/{ => frame}/openInContextLine.spec.jsx (98%) rename tests/js/spec/components/events/interfaces/{ => frame}/stacktraceLink.spec.jsx (98%) rename tests/js/spec/components/events/interfaces/{ => frame}/stacktraceLinkModal.spec.jsx (98%) diff --git a/static/app/components/events/interfaces/crashContent/exception/index.tsx b/static/app/components/events/interfaces/crashContent/exception/index.tsx index af37792e2a32f8..1744478fb1b378 100644 --- a/static/app/components/events/interfaces/crashContent/exception/index.tsx +++ b/static/app/components/events/interfaces/crashContent/exception/index.tsx @@ -1,10 +1,10 @@ import ErrorBoundary from 'app/components/errorBoundary'; -import RawExceptionContent from 'app/components/events/interfaces/rawExceptionContent'; import {ExceptionType, Group, PlatformType, Project} from 'app/types'; import {Event} from 'app/types/event'; import {STACK_TYPE, STACK_VIEW} from 'app/types/stacktrace'; import Content from './content'; +import RawContent from './rawContent'; type Props = { stackType: STACK_TYPE; @@ -30,7 +30,7 @@ const Exception = ({ }: Props) => ( {stackView === STACK_VIEW.RAW ? ( - { +class RawContent extends React.Component { state: State = { loading: false, error: false, @@ -177,7 +178,7 @@ class RawExceptionContent extends React.Component { } } -export default withApi(withOrganization(RawExceptionContent)); +export default withApi(withOrganization(RawContent)); const DownloadBtnWrapper = styled('div')` display: flex; diff --git a/static/app/components/events/interfaces/crashContent/exception/stackTrace.tsx b/static/app/components/events/interfaces/crashContent/exception/stackTrace.tsx index 299bad4e67d8a1..2631a66e5e08dc 100644 --- a/static/app/components/events/interfaces/crashContent/exception/stackTrace.tsx +++ b/static/app/components/events/interfaces/crashContent/exception/stackTrace.tsx @@ -7,8 +7,8 @@ import {STACK_VIEW} from 'app/types/stacktrace'; import {defined} from 'app/utils'; import EmptyMessage from 'app/views/settings/components/emptyMessage'; -import StacktraceContent from '../../stacktraceContent'; -import StacktraceContentV2 from '../../stacktraceContentV2'; +import StacktraceContent from '../stackTrace/content'; +import StacktraceContentV2 from '../stackTrace/contentV2'; type Props = { data: ExceptionValue['stacktrace']; @@ -23,7 +23,7 @@ type Props = { newestFirst?: boolean; }; -const StackTrace = ({ +function StackTrace({ stackView, stacktrace, chainedException, @@ -34,7 +34,7 @@ const StackTrace = ({ data, expandFirstFrame, event, -}: Props) => { +}: Props) { if (!defined(stacktrace)) { return null; } @@ -99,6 +99,6 @@ const StackTrace = ({ event={event} /> ); -}; +} export default StackTrace; diff --git a/static/app/components/events/interfaces/crashContent/index.tsx b/static/app/components/events/interfaces/crashContent/index.tsx index 347c83bf4975eb..2184ef3e3093c7 100644 --- a/static/app/components/events/interfaces/crashContent/index.tsx +++ b/static/app/components/events/interfaces/crashContent/index.tsx @@ -3,7 +3,7 @@ import * as React from 'react'; import {ExceptionType, ExceptionValue, PlatformType} from 'app/types'; import Exception from './exception'; -import Stacktrace from './stacktrace'; +import Stacktrace from './stackTrace'; type ExceptionProps = React.ComponentProps; type Props = Pick< diff --git a/static/app/components/events/interfaces/stacktraceContent.tsx b/static/app/components/events/interfaces/crashContent/stackTrace/content.tsx similarity index 98% rename from static/app/components/events/interfaces/stacktraceContent.tsx rename to static/app/components/events/interfaces/crashContent/stackTrace/content.tsx index 6d9675d48e736b..4ef891a6543db6 100644 --- a/static/app/components/events/interfaces/stacktraceContent.tsx +++ b/static/app/components/events/interfaces/crashContent/stackTrace/content.tsx @@ -36,7 +36,7 @@ type State = { showCompleteFunctionName: boolean; }; -class StacktraceContent extends React.Component { +class Content extends React.Component { static defaultProps: DefaultProps = { includeSystemFrames: true, expandFirstFrame: true, @@ -272,7 +272,7 @@ class StacktraceContent extends React.Component { } } -export default withOrganization(StacktraceContent); +export default withOrganization(Content); const Wrapper = styled('div')` position: relative; diff --git a/static/app/components/events/interfaces/stacktraceContentV2.tsx b/static/app/components/events/interfaces/crashContent/stackTrace/contentV2.tsx similarity index 98% rename from static/app/components/events/interfaces/stacktraceContentV2.tsx rename to static/app/components/events/interfaces/crashContent/stackTrace/contentV2.tsx index 3c0d2b9da44c34..bfac2c187febfb 100644 --- a/static/app/components/events/interfaces/stacktraceContentV2.tsx +++ b/static/app/components/events/interfaces/crashContent/stackTrace/contentV2.tsx @@ -10,8 +10,8 @@ import {Frame, Group, PlatformType} from 'app/types'; import {Event} from 'app/types/event'; import {StacktraceType} from 'app/types/stacktrace'; -import Line from './frame/lineV2'; -import {getImageRange, parseAddress, stackTracePlatformIcon} from './utils'; +import Line from '../../frame/lineV2'; +import {getImageRange, parseAddress, stackTracePlatformIcon} from '../../utils'; type Props = { data: StacktraceType; @@ -25,7 +25,7 @@ type Props = { expandFirstFrame?: boolean; }; -function StackTraceContent({ +function Content({ data, platform, event, @@ -251,7 +251,7 @@ function StackTraceContent({ ); } -export default StackTraceContent; +export default Content; const Wrapper = styled('div')` position: relative; diff --git a/static/app/components/events/interfaces/crashContent/stacktrace.tsx b/static/app/components/events/interfaces/crashContent/stackTrace/index.tsx similarity index 78% rename from static/app/components/events/interfaces/crashContent/stacktrace.tsx rename to static/app/components/events/interfaces/crashContent/stackTrace/index.tsx index b03bc245572b4b..7d011ccb94dccf 100644 --- a/static/app/components/events/interfaces/crashContent/stacktrace.tsx +++ b/static/app/components/events/interfaces/crashContent/stackTrace/index.tsx @@ -1,16 +1,13 @@ import ErrorBoundary from 'app/components/errorBoundary'; -import rawStacktraceContent from 'app/components/events/interfaces/rawStacktraceContent'; import {PlatformType} from 'app/types'; import {Event} from 'app/types/event'; import {STACK_VIEW, StacktraceType} from 'app/types/stacktrace'; -import StacktraceContent from '../stacktraceContent'; -import StacktraceContentV2 from '../stacktraceContentV2'; +import Content from './content'; +import ContentV2 from './contentV2'; +import rawStacktraceContent from './rawContent'; -type Props = Pick< - React.ComponentProps, - 'groupingCurrentLevel' -> & { +type Props = Pick, 'groupingCurrentLevel'> & { stacktrace: StacktraceType; event: Event; newestFirst: boolean; @@ -35,7 +32,7 @@ const Stacktrace = ({ {rawStacktraceContent(stacktrace, event.platform)} ) : hasHierarchicalGrouping ? ( - ) : ( - ; }; -function CSPContent({data}: Props) { +function Content({data}: Props) { return (

@@ -24,4 +24,4 @@ function CSPContent({data}: Props) { ); } -export default CSPContent; +export default Content; diff --git a/static/app/components/events/interfaces/cspHelp/effectiveDirectives.tsx b/static/app/components/events/interfaces/csp/help/effectiveDirectives.tsx similarity index 100% rename from static/app/components/events/interfaces/cspHelp/effectiveDirectives.tsx rename to static/app/components/events/interfaces/csp/help/effectiveDirectives.tsx diff --git a/static/app/components/events/interfaces/cspHelp/index.tsx b/static/app/components/events/interfaces/csp/help/index.tsx similarity index 100% rename from static/app/components/events/interfaces/cspHelp/index.tsx rename to static/app/components/events/interfaces/csp/help/index.tsx diff --git a/static/app/components/events/interfaces/csp.tsx b/static/app/components/events/interfaces/csp/index.tsx similarity index 86% rename from static/app/components/events/interfaces/csp.tsx rename to static/app/components/events/interfaces/csp/index.tsx index 472234eceab806..cf9cea2480ee34 100644 --- a/static/app/components/events/interfaces/csp.tsx +++ b/static/app/components/events/interfaces/csp/index.tsx @@ -3,19 +3,20 @@ import {Component} from 'react'; import Button from 'app/components/button'; import ButtonBar from 'app/components/buttonBar'; import EventDataSection from 'app/components/events/eventDataSection'; -import CSPContent from 'app/components/events/interfaces/cspContent'; -import CSPHelp from 'app/components/events/interfaces/cspHelp'; import {t} from 'app/locale'; import {Event} from 'app/types/event'; +import Content from './content'; +import Help from './help'; + function getView(view, data) { switch (view) { case 'report': - return ; + return ; case 'raw': return
{JSON.stringify({'csp-report': data}, null, 2)}
; case 'help': - return ; + return ; default: throw new TypeError(`Invalid view: ${view}`); } @@ -30,7 +31,7 @@ type State = { view: string; }; -export default class CspInterface extends Component { +class CspInterface extends Component { state: State = {view: 'report'}; toggleView = value => { @@ -84,3 +85,5 @@ export default class CspInterface extends Component { ); } } + +export default CspInterface; diff --git a/static/app/components/events/interfaces/imageForBar.tsx b/static/app/components/events/interfaces/debugMeta/imageForBar.tsx similarity index 100% rename from static/app/components/events/interfaces/imageForBar.tsx rename to static/app/components/events/interfaces/debugMeta/imageForBar.tsx diff --git a/static/app/components/events/interfaces/debugMeta/index.tsx b/static/app/components/events/interfaces/debugMeta/index.tsx index 313ae7b73e6f79..6c87e4bb6aee2a 100644 --- a/static/app/components/events/interfaces/debugMeta/index.tsx +++ b/static/app/components/events/interfaces/debugMeta/index.tsx @@ -14,7 +14,6 @@ import GuideAnchor from 'app/components/assistant/guideAnchor'; import Button from 'app/components/button'; import Checkbox from 'app/components/checkbox'; import EventDataSection from 'app/components/events/eventDataSection'; -import ImageForBar from 'app/components/events/interfaces/imageForBar'; import {getImageRange, parseAddress} from 'app/components/events/interfaces/utils'; import {Panel, PanelBody} from 'app/components/panels'; import SearchBar from 'app/components/searchBar'; @@ -29,6 +28,7 @@ import EmptyMessage from 'app/views/settings/components/emptyMessage'; import {shouldSkipSection} from '../debugMeta-v2/utils'; import DebugImage from './debugImage'; +import ImageForBar from './imageForBar'; import {getFileName} from './utils'; const MIN_FILTER_LEN = 3; diff --git a/static/app/components/events/interfaces/assembly.tsx b/static/app/components/events/interfaces/frame/assembly.tsx similarity index 100% rename from static/app/components/events/interfaces/assembly.tsx rename to static/app/components/events/interfaces/frame/assembly.tsx diff --git a/static/app/components/events/interfaces/frame/context.tsx b/static/app/components/events/interfaces/frame/context.tsx index ec849044648d52..c59e55b27e178a 100644 --- a/static/app/components/events/interfaces/frame/context.tsx +++ b/static/app/components/events/interfaces/frame/context.tsx @@ -2,13 +2,6 @@ import styled from '@emotion/styled'; import ClippedBox from 'app/components/clippedBox'; import ErrorBoundary from 'app/components/errorBoundary'; -import {Assembly} from 'app/components/events/interfaces/assembly'; -import ContextLine from 'app/components/events/interfaces/contextLine'; -import FrameRegisters from 'app/components/events/interfaces/frameRegisters'; -import FrameVariables from 'app/components/events/interfaces/frameVariables'; -import {OpenInContextLine} from 'app/components/events/interfaces/openInContextLine'; -import StacktraceLink from 'app/components/events/interfaces/stacktraceLink'; -import {parseAssembly} from 'app/components/events/interfaces/utils'; import {IconFlag} from 'app/icons'; import {t} from 'app/locale'; import space from 'app/styles/space'; @@ -17,6 +10,15 @@ import {Event} from 'app/types/event'; import {defined} from 'app/utils'; import withOrganization from 'app/utils/withOrganization'; +import {parseAssembly} from '../utils'; + +import {Assembly} from './assembly'; +import ContextLine from './contextLine'; +import FrameRegisters from './frameRegisters'; +import FrameVariables from './frameVariables'; +import {OpenInContextLine} from './openInContextLine'; +import StacktraceLink from './stacktraceLink'; + type Props = { frame: Frame; event: Event; diff --git a/static/app/components/events/interfaces/contextLine.tsx b/static/app/components/events/interfaces/frame/contextLine.tsx similarity index 100% rename from static/app/components/events/interfaces/contextLine.tsx rename to static/app/components/events/interfaces/frame/contextLine.tsx diff --git a/static/app/components/events/interfaces/frameRegisters/index.tsx b/static/app/components/events/interfaces/frame/frameRegisters/index.tsx similarity index 100% rename from static/app/components/events/interfaces/frameRegisters/index.tsx rename to static/app/components/events/interfaces/frame/frameRegisters/index.tsx diff --git a/static/app/components/events/interfaces/frameRegisters/registers.tsx b/static/app/components/events/interfaces/frame/frameRegisters/registers.tsx similarity index 100% rename from static/app/components/events/interfaces/frameRegisters/registers.tsx rename to static/app/components/events/interfaces/frame/frameRegisters/registers.tsx diff --git a/static/app/components/events/interfaces/frameRegisters/utils.tsx b/static/app/components/events/interfaces/frame/frameRegisters/utils.tsx similarity index 100% rename from static/app/components/events/interfaces/frameRegisters/utils.tsx rename to static/app/components/events/interfaces/frame/frameRegisters/utils.tsx diff --git a/static/app/components/events/interfaces/frameRegisters/value.tsx b/static/app/components/events/interfaces/frame/frameRegisters/value.tsx similarity index 100% rename from static/app/components/events/interfaces/frameRegisters/value.tsx rename to static/app/components/events/interfaces/frame/frameRegisters/value.tsx diff --git a/static/app/components/events/interfaces/frameVariables.tsx b/static/app/components/events/interfaces/frame/frameVariables.tsx similarity index 93% rename from static/app/components/events/interfaces/frameVariables.tsx rename to static/app/components/events/interfaces/frame/frameVariables.tsx index 1457a89dc402ce..abc4afd02cf1da 100644 --- a/static/app/components/events/interfaces/frameVariables.tsx +++ b/static/app/components/events/interfaces/frame/frameVariables.tsx @@ -1,9 +1,10 @@ import * as React from 'react'; -import KeyValueList from 'app/components/events/interfaces/keyValueList'; import {getMeta} from 'app/components/events/meta/metaProxy'; import {KeyValueListData} from 'app/types'; +import KeyValueList from '../keyValueList'; + type Props = { data: Record; }; diff --git a/static/app/components/events/interfaces/frame/line.tsx b/static/app/components/events/interfaces/frame/line.tsx index e1c494af2128c9..1b87ad41846670 100644 --- a/static/app/components/events/interfaces/frame/line.tsx +++ b/static/app/components/events/interfaces/frame/line.tsx @@ -4,16 +4,6 @@ import classNames from 'classnames'; import scrollToElement from 'scroll-to-element'; import Button from 'app/components/button'; -import DebugImage from 'app/components/events/interfaces/debugMeta/debugImage'; -import {combineStatus} from 'app/components/events/interfaces/debugMeta/utils'; -import PackageLink from 'app/components/events/interfaces/packageLink'; -import PackageStatus, { - PackageStatusIcon, -} from 'app/components/events/interfaces/packageStatus'; -import TogglableAddress, { - AddressToggleIcon, -} from 'app/components/events/interfaces/togglableAddress'; -import {SymbolicatorStatus} from 'app/components/events/interfaces/types'; import {STACKTRACE_PREVIEW_TOOLTIP_DELAY} from 'app/components/stacktracePreview'; import StrictClick from 'app/components/strictClick'; import {IconChevron, IconRefresh} from 'app/icons'; @@ -26,9 +16,16 @@ import {Event} from 'app/types/event'; import withOrganization from 'app/utils/withOrganization'; import withSentryAppComponents from 'app/utils/withSentryAppComponents'; +import DebugImage from '../debugMeta/debugImage'; +import {combineStatus} from '../debugMeta/utils'; +import {SymbolicatorStatus} from '../types'; + import Context from './context'; import DefaultTitle from './defaultTitle'; +import PackageLink from './packageLink'; +import PackageStatus, {PackageStatusIcon} from './packageStatus'; import Symbol, {FunctionNameToggleIcon} from './symbol'; +import TogglableAddress, {AddressToggleIcon} from './togglableAddress'; import { getPlatform, hasAssembly, diff --git a/static/app/components/events/interfaces/frame/lineV2/index.tsx b/static/app/components/events/interfaces/frame/lineV2/index.tsx index b2977b649e0994..22a1d4067e3386 100644 --- a/static/app/components/events/interfaces/frame/lineV2/index.tsx +++ b/static/app/components/events/interfaces/frame/lineV2/index.tsx @@ -2,15 +2,15 @@ import {useState} from 'react'; import styled from '@emotion/styled'; import classNames from 'classnames'; -import {PackageStatusIcon} from 'app/components/events/interfaces/packageStatus'; -import {AddressToggleIcon} from 'app/components/events/interfaces/togglableAddress'; import StrictClick from 'app/components/strictClick'; import {PlatformType, SentryAppComponent} from 'app/types'; import {Event} from 'app/types/event'; import withSentryAppComponents from 'app/utils/withSentryAppComponents'; import Context from '../context'; +import {PackageStatusIcon} from '../packageStatus'; import {FunctionNameToggleIcon} from '../symbol'; +import {AddressToggleIcon} from '../togglableAddress'; import { getPlatform, hasAssembly, diff --git a/static/app/components/events/interfaces/frame/lineV2/native.tsx b/static/app/components/events/interfaces/frame/lineV2/native.tsx index 740f9c89b1ab10..981229f7ab4a32 100644 --- a/static/app/components/events/interfaces/frame/lineV2/native.tsx +++ b/static/app/components/events/interfaces/frame/lineV2/native.tsx @@ -2,18 +2,18 @@ import {MouseEvent, MouseEventHandler} from 'react'; import styled from '@emotion/styled'; import scrollToElement from 'scroll-to-element'; -import DebugImage from 'app/components/events/interfaces/debugMeta/debugImage'; -import {combineStatus} from 'app/components/events/interfaces/debugMeta/utils'; -import PackageLink from 'app/components/events/interfaces/packageLink'; -import PackageStatus from 'app/components/events/interfaces/packageStatus'; -import TogglableAddress from 'app/components/events/interfaces/togglableAddress'; -import {SymbolicatorStatus} from 'app/components/events/interfaces/types'; import {t} from 'app/locale'; import {DebugMetaActions} from 'app/stores/debugMetaStore'; import space from 'app/styles/space'; import {Frame} from 'app/types'; +import DebugImage from '../../debugMeta/debugImage'; +import {combineStatus} from '../../debugMeta/utils'; +import {SymbolicatorStatus} from '../../types'; +import PackageLink from '../packageLink'; +import PackageStatus from '../packageStatus'; import Symbol from '../symbol'; +import TogglableAddress from '../togglableAddress'; import {getPlatform} from '../utils'; import Expander from './expander'; diff --git a/static/app/components/events/interfaces/openInContextLine.tsx b/static/app/components/events/interfaces/frame/openInContextLine.tsx similarity index 100% rename from static/app/components/events/interfaces/openInContextLine.tsx rename to static/app/components/events/interfaces/frame/openInContextLine.tsx diff --git a/static/app/components/events/interfaces/packageLink.tsx b/static/app/components/events/interfaces/frame/packageLink.tsx similarity index 100% rename from static/app/components/events/interfaces/packageLink.tsx rename to static/app/components/events/interfaces/frame/packageLink.tsx diff --git a/static/app/components/events/interfaces/packageStatus.tsx b/static/app/components/events/interfaces/frame/packageStatus.tsx similarity index 95% rename from static/app/components/events/interfaces/packageStatus.tsx rename to static/app/components/events/interfaces/frame/packageStatus.tsx index cfa90a4daf94e9..bc0be1c62d9c97 100644 --- a/static/app/components/events/interfaces/packageStatus.tsx +++ b/static/app/components/events/interfaces/frame/packageStatus.tsx @@ -9,7 +9,7 @@ type Props = { tooltip?: string; }; -const PackageStatus = ({status, tooltip}: Props) => { +function PackageStatus({status, tooltip}: Props) { const getIcon = () => { switch (status) { case 'success': @@ -37,7 +37,7 @@ const PackageStatus = ({status, tooltip}: Props) => { {icon} ); -}; +} const StyledTooltip = styled(Tooltip)` margin-left: ${space(0.75)}; diff --git a/static/app/components/events/interfaces/stacktraceLink.tsx b/static/app/components/events/interfaces/frame/stacktraceLink.tsx similarity index 100% rename from static/app/components/events/interfaces/stacktraceLink.tsx rename to static/app/components/events/interfaces/frame/stacktraceLink.tsx diff --git a/static/app/components/events/interfaces/stacktraceLinkModal.tsx b/static/app/components/events/interfaces/frame/stacktraceLinkModal.tsx similarity index 100% rename from static/app/components/events/interfaces/stacktraceLinkModal.tsx rename to static/app/components/events/interfaces/frame/stacktraceLinkModal.tsx diff --git a/static/app/components/events/interfaces/togglableAddress.tsx b/static/app/components/events/interfaces/frame/togglableAddress.tsx similarity index 96% rename from static/app/components/events/interfaces/togglableAddress.tsx rename to static/app/components/events/interfaces/frame/togglableAddress.tsx index 2a44133df6a93d..4731c7773bd933 100644 --- a/static/app/components/events/interfaces/togglableAddress.tsx +++ b/static/app/components/events/interfaces/frame/togglableAddress.tsx @@ -1,7 +1,6 @@ import * as React from 'react'; import styled from '@emotion/styled'; -import {formatAddress, parseAddress} from 'app/components/events/interfaces/utils'; import {STACKTRACE_PREVIEW_TOOLTIP_DELAY} from 'app/components/stacktracePreview'; import Tooltip from 'app/components/tooltip'; import {IconFilter} from 'app/icons'; @@ -9,6 +8,8 @@ import {t} from 'app/locale'; import space from 'app/styles/space'; import {Theme} from 'app/utils/theme'; +import {formatAddress, parseAddress} from '../utils'; + type Props = { address: string; startingAddress: string | null; @@ -24,7 +25,7 @@ type Props = { className?: string; }; -const TogglableAddress = ({ +function TogglableAddress({ startingAddress, address, relativeAddressMaxlength, @@ -34,7 +35,7 @@ const TogglableAddress = ({ onToggle, isHoverPreviewed, className, -}: Props) => { +}: Props) { const convertAbsoluteAddressToRelative = () => { if (!startingAddress) { return ''; @@ -96,7 +97,7 @@ const TogglableAddress = ({ ); -}; +} const AddressIconTooltip = styled(Tooltip)` align-items: center; diff --git a/static/app/components/events/interfaces/frame/utils.tsx b/static/app/components/events/interfaces/frame/utils.tsx index c3b2ae2ba400a0..a6f1538daa774b 100644 --- a/static/app/components/events/interfaces/frame/utils.tsx +++ b/static/app/components/events/interfaces/frame/utils.tsx @@ -1,9 +1,10 @@ -import {SymbolicatorStatus} from 'app/components/events/interfaces/types'; import {IconQuestion, IconWarning} from 'app/icons'; import {t} from 'app/locale'; import {Frame, PlatformType} from 'app/types'; import {defined, objectIsEmpty} from 'app/utils'; +import {SymbolicatorStatus} from '../types'; + export function trimPackage(pkg: string) { const pieces = pkg.split(/^([a-z]:\\|\\\\)/i.test(pkg) ? '\\' : '/'); const filename = pieces[pieces.length - 1] || pieces[pieces.length - 2] || pkg; diff --git a/static/app/components/stacktracePreview.tsx b/static/app/components/stacktracePreview.tsx index a8608acbcaf576..5638be4f462be4 100644 --- a/static/app/components/stacktracePreview.tsx +++ b/static/app/components/stacktracePreview.tsx @@ -3,9 +3,9 @@ import {withTheme} from '@emotion/react'; import styled from '@emotion/styled'; import {Client} from 'app/api'; +import StacktraceContent from 'app/components/events/interfaces/crashContent/stackTrace/content'; +import StacktraceContentV2 from 'app/components/events/interfaces/crashContent/stackTrace/contentV2'; import {isStacktraceNewestFirst} from 'app/components/events/interfaces/stacktrace'; -import StacktraceContent from 'app/components/events/interfaces/stacktraceContent'; -import StacktraceContentV2 from 'app/components/events/interfaces/stacktraceContentV2'; import Hovercard, {Body} from 'app/components/hovercard'; import LoadingIndicator from 'app/components/loadingIndicator'; import {t} from 'app/locale'; diff --git a/static/app/utils/getStacktraceBody.tsx b/static/app/utils/getStacktraceBody.tsx index 98b7de9a174b18..d0c2a61eb51118 100644 --- a/static/app/utils/getStacktraceBody.tsx +++ b/static/app/utils/getStacktraceBody.tsx @@ -1,4 +1,4 @@ -import rawStacktraceContent from 'app/components/events/interfaces/rawStacktraceContent'; +import rawStacktraceContent from 'app/components/events/interfaces/crashContent/stackTrace/rawContent'; import {Event} from 'app/types/event'; export default function getStacktraceBody(event: Event) { diff --git a/tests/js/spec/components/events/crashContent.spec.jsx b/tests/js/spec/components/events/interfaces/crashContent/index.spec.jsx similarity index 100% rename from tests/js/spec/components/events/crashContent.spec.jsx rename to tests/js/spec/components/events/interfaces/crashContent/index.spec.jsx diff --git a/tests/js/spec/components/events/interfaces/stacktrace.spec.tsx b/tests/js/spec/components/events/interfaces/crashContent/stackTrace/content.spec.tsx similarity index 99% rename from tests/js/spec/components/events/interfaces/stacktrace.spec.tsx rename to tests/js/spec/components/events/interfaces/crashContent/stackTrace/content.spec.tsx index 40323b73e313a9..3f6abe820c957f 100644 --- a/tests/js/spec/components/events/interfaces/stacktrace.spec.tsx +++ b/tests/js/spec/components/events/interfaces/crashContent/stackTrace/content.spec.tsx @@ -1,6 +1,6 @@ import {fireEvent, mountWithTheme, screen} from 'sentry-test/reactTestingLibrary'; -import StacktraceContent from 'app/components/events/interfaces/stacktraceContent'; +import StacktraceContent from 'app/components/events/interfaces/crashContent/stackTrace/content'; import {StacktraceType} from 'app/types/stacktrace'; // @ts-expect-error diff --git a/tests/js/spec/components/events/interfaces/rawStacktraceContent.spec.jsx b/tests/js/spec/components/events/interfaces/crashContent/stackTrace/rawContent.spec.jsx similarity index 96% rename from tests/js/spec/components/events/interfaces/rawStacktraceContent.spec.jsx rename to tests/js/spec/components/events/interfaces/crashContent/stackTrace/rawContent.spec.jsx index c15a0d0e21894f..728b405de9e3a3 100644 --- a/tests/js/spec/components/events/interfaces/rawStacktraceContent.spec.jsx +++ b/tests/js/spec/components/events/interfaces/crashContent/stackTrace/rawContent.spec.jsx @@ -1,7 +1,7 @@ import render, { getJavaFrame, getJavaPreamble, -} from 'app/components/events/interfaces/rawStacktraceContent'; +} from 'app/components/events/interfaces/crashContent/stackTrace/rawContent'; describe('RawStacktraceContent', function () { describe('getJavaFrame()', function () { diff --git a/tests/js/spec/components/events/interfaces/contexts.spec.jsx b/tests/js/spec/components/events/interfaces/frame/contexts.spec.jsx similarity index 100% rename from tests/js/spec/components/events/interfaces/contexts.spec.jsx rename to tests/js/spec/components/events/interfaces/frame/contexts.spec.jsx diff --git a/tests/js/spec/components/events/interfaces/frame/frameRegisters.spec.jsx b/tests/js/spec/components/events/interfaces/frame/frameRegisters.spec.jsx index 695f86742daf6c..fcb2495c443f56 100644 --- a/tests/js/spec/components/events/interfaces/frame/frameRegisters.spec.jsx +++ b/tests/js/spec/components/events/interfaces/frame/frameRegisters.spec.jsx @@ -1,7 +1,7 @@ import {mountWithTheme} from 'sentry-test/enzyme'; -import FrameRegisters from 'app/components/events/interfaces/frameRegisters'; -import FrameRegistersValue from 'app/components/events/interfaces/frameRegisters/value'; +import FrameRegisters from 'app/components/events/interfaces/frame/frameRegisters'; +import FrameRegistersValue from 'app/components/events/interfaces/frame/frameRegisters/value'; describe('FrameRegisters', () => { it('should render registers', () => { diff --git a/tests/js/spec/components/events/interfaces/openInContextLine.spec.jsx b/tests/js/spec/components/events/interfaces/frame/openInContextLine.spec.jsx similarity index 98% rename from tests/js/spec/components/events/interfaces/openInContextLine.spec.jsx rename to tests/js/spec/components/events/interfaces/frame/openInContextLine.spec.jsx index f93a69eddf34e0..c557b0ceaa340f 100644 --- a/tests/js/spec/components/events/interfaces/openInContextLine.spec.jsx +++ b/tests/js/spec/components/events/interfaces/frame/openInContextLine.spec.jsx @@ -1,6 +1,6 @@ import {mountWithTheme} from 'sentry-test/enzyme'; -import {OpenInContextLine} from 'app/components/events/interfaces/openInContextLine'; +import {OpenInContextLine} from 'app/components/events/interfaces/frame/openInContextLine'; import {addQueryParamsToExistingUrl} from 'app/utils/queryString'; describe('OpenInContextLine', function () { diff --git a/tests/js/spec/components/events/interfaces/stacktraceLink.spec.jsx b/tests/js/spec/components/events/interfaces/frame/stacktraceLink.spec.jsx similarity index 98% rename from tests/js/spec/components/events/interfaces/stacktraceLink.spec.jsx rename to tests/js/spec/components/events/interfaces/frame/stacktraceLink.spec.jsx index 41f8d2a658585a..fe15c0732d1e0a 100644 --- a/tests/js/spec/components/events/interfaces/stacktraceLink.spec.jsx +++ b/tests/js/spec/components/events/interfaces/frame/stacktraceLink.spec.jsx @@ -1,6 +1,6 @@ import {mountWithTheme} from 'sentry-test/enzyme'; -import {StacktraceLink} from 'app/components/events/interfaces/stacktraceLink'; +import {StacktraceLink} from 'app/components/events/interfaces/frame/stacktraceLink'; describe('StacktraceLink', function () { const org = TestStubs.Organization(); diff --git a/tests/js/spec/components/events/interfaces/stacktraceLinkModal.spec.jsx b/tests/js/spec/components/events/interfaces/frame/stacktraceLinkModal.spec.jsx similarity index 98% rename from tests/js/spec/components/events/interfaces/stacktraceLinkModal.spec.jsx rename to tests/js/spec/components/events/interfaces/frame/stacktraceLinkModal.spec.jsx index 89f4c83b5958e7..cdd9788112e5d8 100644 --- a/tests/js/spec/components/events/interfaces/stacktraceLinkModal.spec.jsx +++ b/tests/js/spec/components/events/interfaces/frame/stacktraceLinkModal.spec.jsx @@ -1,6 +1,6 @@ import {mountWithTheme} from 'sentry-test/enzyme'; -import StacktraceLinkModal from 'app/components/events/interfaces/stacktraceLinkModal'; +import StacktraceLinkModal from 'app/components/events/interfaces/frame/stacktraceLinkModal'; describe('StacktraceLinkModal', function () { const org = TestStubs.Organization(); From 74b8cbcff8f5e04455f23f78b0fb3aa4c3ab018b Mon Sep 17 00:00:00 2001 From: Priscila Oliveira Date: Fri, 22 Oct 2021 14:51:57 +0200 Subject: [PATCH 02/15] ref(crashContent): Move crash content related files to folder --- tests/js/spec/components/events/interfaces/crashContent/index.tsx | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/js/spec/components/events/interfaces/crashContent/index.tsx diff --git a/tests/js/spec/components/events/interfaces/crashContent/index.tsx b/tests/js/spec/components/events/interfaces/crashContent/index.tsx new file mode 100644 index 00000000000000..e69de29bb2d1d6 From 6b8361fefb99307e4bc857e8bab2fcd3186bb0ff Mon Sep 17 00:00:00 2001 From: Priscila Oliveira Date: Fri, 22 Oct 2021 15:36:36 +0200 Subject: [PATCH 03/15] removed unused file --- tests/js/spec/components/events/interfaces/crashContent/index.tsx | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 tests/js/spec/components/events/interfaces/crashContent/index.tsx diff --git a/tests/js/spec/components/events/interfaces/crashContent/index.tsx b/tests/js/spec/components/events/interfaces/crashContent/index.tsx deleted file mode 100644 index e69de29bb2d1d6..00000000000000 From a9dc5f663f1245b48258a076e6fafb82900bbd42 Mon Sep 17 00:00:00 2001 From: Priscila Oliveira Date: Fri, 22 Oct 2021 15:47:37 +0200 Subject: [PATCH 04/15] tests --- tests/js/spec/utils/withTeamsForUser.spec.jsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/js/spec/utils/withTeamsForUser.spec.jsx b/tests/js/spec/utils/withTeamsForUser.spec.jsx index 75ab3d238e665f..730dec3ab0ca1b 100644 --- a/tests/js/spec/utils/withTeamsForUser.spec.jsx +++ b/tests/js/spec/utils/withTeamsForUser.spec.jsx @@ -9,6 +9,8 @@ describe('withUserTeams HoC', function () { const organization = TestStubs.Organization(); delete organization.projects; + // console.log + beforeEach(function () { MockApiClient.clearMockResponses(); jest.spyOn(ProjectActions, 'loadProjects'); From 1710655c0e7e65a586605d1a23dec4010db70a68 Mon Sep 17 00:00:00 2001 From: Priscila Oliveira Date: Fri, 22 Oct 2021 15:48:52 +0200 Subject: [PATCH 05/15] tests2 --- tests/js/spec/utils/test.spec.jsx | 57 +++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 tests/js/spec/utils/test.spec.jsx diff --git a/tests/js/spec/utils/test.spec.jsx b/tests/js/spec/utils/test.spec.jsx new file mode 100644 index 00000000000000..730dec3ab0ca1b --- /dev/null +++ b/tests/js/spec/utils/test.spec.jsx @@ -0,0 +1,57 @@ +import {mountWithTheme} from 'sentry-test/enzyme'; + +import ProjectActions from 'app/actions/projectActions'; +import TeamActions from 'app/actions/teamActions'; +import withTeamsForUser from 'app/utils/withTeamsForUser'; + +describe('withUserTeams HoC', function () { + const api = new MockApiClient(); + const organization = TestStubs.Organization(); + delete organization.projects; + + // console.log + + beforeEach(function () { + MockApiClient.clearMockResponses(); + jest.spyOn(ProjectActions, 'loadProjects'); + jest.spyOn(TeamActions, 'loadTeams'); + }); + + it('forwards errors', async function () { + MockApiClient.addMockResponse({ + url: `/organizations/${organization.slug}/user-teams/`, + statusCode: 400, + }); + const MyComponent = () => null; + const Container = withTeamsForUser(MyComponent); + const wrapper = mountWithTheme(); + await tick(); + expect(wrapper.update().find('MyComponent').prop('error')).not.toBeNull(); + }); + + it('fetches teams and loads stores', async function () { + const mockProjectA = TestStubs.Project({slug: 'a', id: '1'}); + const mockProjectB = TestStubs.Project({slug: 'b', id: '2'}); + const mockTeams = [ + { + slug: 'sentry', + projects: [mockProjectB], + }, + { + slug: 'captainplanet', + projects: [mockProjectA, mockProjectB], + }, + ]; + + MockApiClient.addMockResponse({ + url: `/organizations/${organization.slug}/user-teams/`, + body: mockTeams, + }); + + const MyComponent = () => null; + const Container = withTeamsForUser(MyComponent); + const wrapper = mountWithTheme(); + await tick(); + expect(wrapper.update().find('MyComponent').prop('teams')).toEqual(mockTeams); + }); +}); From 2b9e6f3e8e87ea572e4b146b0098e5eaa51cc41f Mon Sep 17 00:00:00 2001 From: Priscila Oliveira Date: Wed, 20 Oct 2021 13:47:24 +0200 Subject: [PATCH 06/15] ref(threads-interface): Add threads interface V2 --- static/app/components/events/eventEntry.tsx | 1 + .../threads/{ => currentVersion}/content.tsx | 2 +- .../threads/currentVersion/index.tsx | 181 +++++++++++++++++ .../events/interfaces/threads/index.tsx | 184 ++--------------- .../interfaces/threads/newVersion/index.tsx | 185 ++++++++++++++++++ .../events/interfaces/threads.spec.jsx | 5 + 6 files changed, 386 insertions(+), 172 deletions(-) rename static/app/components/events/interfaces/threads/{ => currentVersion}/content.tsx (97%) create mode 100644 static/app/components/events/interfaces/threads/currentVersion/index.tsx create mode 100644 static/app/components/events/interfaces/threads/newVersion/index.tsx diff --git a/static/app/components/events/eventEntry.tsx b/static/app/components/events/eventEntry.tsx index 2a43edc64706ca..485aea52fa247b 100644 --- a/static/app/components/events/eventEntry.tsx +++ b/static/app/components/events/eventEntry.tsx @@ -110,6 +110,7 @@ function EventEntry({ projectId={projectSlug} groupingCurrentLevel={groupingCurrentLevel} hasHierarchicalGrouping={hasHierarchicalGrouping} + organization={organization as Organization} /> ); } diff --git a/static/app/components/events/interfaces/threads/content.tsx b/static/app/components/events/interfaces/threads/currentVersion/content.tsx similarity index 97% rename from static/app/components/events/interfaces/threads/content.tsx rename to static/app/components/events/interfaces/threads/currentVersion/content.tsx index eb1480adb486a2..ac9bd59352b3d2 100644 --- a/static/app/components/events/interfaces/threads/content.tsx +++ b/static/app/components/events/interfaces/threads/currentVersion/content.tsx @@ -10,7 +10,7 @@ import {Event} from 'app/types/event'; import {Thread} from 'app/types/events'; import {STACK_TYPE, STACK_VIEW} from 'app/types/stacktrace'; -import NoStackTraceMessage from '../noStackTraceMessage'; +import NoStackTraceMessage from '../../noStackTraceMessage'; type CrashContentProps = React.ComponentProps; diff --git a/static/app/components/events/interfaces/threads/currentVersion/index.tsx b/static/app/components/events/interfaces/threads/currentVersion/index.tsx new file mode 100644 index 00000000000000..4fbca85dc26d6a --- /dev/null +++ b/static/app/components/events/interfaces/threads/currentVersion/index.tsx @@ -0,0 +1,181 @@ +import {useState} from 'react'; + +import EventDataSection from 'app/components/events/eventDataSection'; +import CrashActions from 'app/components/events/interfaces/crashHeader/crashActions'; +import CrashTitle from 'app/components/events/interfaces/crashHeader/crashTitle'; +import {isStacktraceNewestFirst} from 'app/components/events/interfaces/stacktrace'; +import {t} from 'app/locale'; +import {Project} from 'app/types'; +import {Event} from 'app/types/event'; +import {Thread} from 'app/types/events'; +import {STACK_TYPE, STACK_VIEW} from 'app/types/stacktrace'; +import {defined} from 'app/utils'; + +import ThreadSelector from '../threadSelector'; +import findBestThread from '../threadSelector/findBestThread'; +import getThreadException from '../threadSelector/getThreadException'; +import getThreadStacktrace from '../threadSelector/getThreadStacktrace'; + +import Content from './content'; + +type Props = Pick< + React.ComponentProps, + 'groupingCurrentLevel' | 'hasHierarchicalGrouping' +> & { + event: Event; + projectId: Project['id']; + type: string; + data: { + values?: Array; + }; + hideGuide?: boolean; +}; + +type State = { + stackType: STACK_TYPE; + newestFirst: boolean; + activeThread?: Thread; + stackView?: STACK_VIEW; +}; + +function getIntendedStackView(thread: Thread, event: Event) { + const exception = getThreadException(event, thread); + if (exception) { + return !!exception.values.find(value => !!value.stacktrace?.hasSystemFrames) + ? STACK_VIEW.APP + : STACK_VIEW.FULL; + } + + const stacktrace = getThreadStacktrace(false, thread); + + return stacktrace?.hasSystemFrames ? STACK_VIEW.APP : STACK_VIEW.FULL; +} + +function Threads({ + data, + event, + projectId, + type, + hasHierarchicalGrouping, + groupingCurrentLevel, + hideGuide = false, +}: Props) { + const [state, setState] = useState(() => { + const thread = defined(data.values) ? findBestThread(data.values) : undefined; + return { + activeThread: thread, + stackView: thread ? getIntendedStackView(thread, event) : undefined, + stackType: STACK_TYPE.ORIGINAL, + newestFirst: isStacktraceNewestFirst(), + }; + }); + + if (!data.values) { + return null; + } + + function handleSelectNewThread(thread: Thread) { + setState({ + ...state, + activeThread: thread, + stackView: + state.stackView !== STACK_VIEW.RAW + ? getIntendedStackView(thread, event) + : state.stackView, + stackType: STACK_TYPE.ORIGINAL, + }); + } + + function handleChangeNewestFirst({newestFirst}: Pick) { + setState({...state, newestFirst}); + } + + function handleChangeStackView({ + stackView, + stackType, + }: Partial>) { + setState({ + ...state, + stackView: stackView ?? state.stackView, + stackType: stackType ?? state.stackType, + }); + } + + const threads = data.values; + const {stackView, stackType, newestFirst, activeThread} = state; + + const exception = getThreadException(event, activeThread); + + const stacktrace = !exception + ? getThreadStacktrace(stackType !== STACK_TYPE.ORIGINAL, activeThread) + : undefined; + + const stackTraceNotFound = !(exception || stacktrace); + const hasMoreThanOneThread = threads.length > 1; + + return ( + + ) + } + /> + ) : ( + + ) + } + actions={ + !stackTraceNotFound && ( + + ) + } + showPermalink={!hasMoreThanOneThread} + wrapTitle={false} + > + + + ); +} + +export default Threads; diff --git a/static/app/components/events/interfaces/threads/index.tsx b/static/app/components/events/interfaces/threads/index.tsx index 9fe0e7297901f9..ab9dfe3e49532d 100644 --- a/static/app/components/events/interfaces/threads/index.tsx +++ b/static/app/components/events/interfaces/threads/index.tsx @@ -1,180 +1,22 @@ -import {useState} from 'react'; +import {Organization} from 'app/types'; -import EventDataSection from 'app/components/events/eventDataSection'; -import CrashActions from 'app/components/events/interfaces/crashHeader/crashActions'; -import CrashTitle from 'app/components/events/interfaces/crashHeader/crashTitle'; -import {isStacktraceNewestFirst} from 'app/components/events/interfaces/stacktrace'; -import {t} from 'app/locale'; -import {Project} from 'app/types'; -import {Event} from 'app/types/event'; -import {Thread} from 'app/types/events'; -import {STACK_TYPE, STACK_VIEW} from 'app/types/stacktrace'; -import {defined} from 'app/utils'; +import CurrentVersion from './currentVersion'; +import NewVersion from './newVersion'; -import findBestThread from './threadSelector/findBestThread'; -import getThreadException from './threadSelector/getThreadException'; -import getThreadStacktrace from './threadSelector/getThreadStacktrace'; -import Content from './content'; -import ThreadSelector from './threadSelector'; - -type Props = Pick< - React.ComponentProps, - 'groupingCurrentLevel' | 'hasHierarchicalGrouping' -> & { - event: Event; - projectId: Project['id']; - type: string; - data: { - values?: Array; - }; - hideGuide?: boolean; -}; - -type State = { - stackType: STACK_TYPE; - newestFirst: boolean; - activeThread?: Thread; - stackView?: STACK_VIEW; +type Props = React.ComponentProps & { + organization: Organization; }; -function getIntendedStackView(thread: Thread, event: Event) { - const exception = getThreadException(event, thread); - if (exception) { - return !!exception.values.find(value => !!value.stacktrace?.hasSystemFrames) - ? STACK_VIEW.APP - : STACK_VIEW.FULL; - } - - const stacktrace = getThreadStacktrace(false, thread); - - return stacktrace?.hasSystemFrames ? STACK_VIEW.APP : STACK_VIEW.FULL; -} - -function Threads({ - data, - event, - projectId, - type, - hasHierarchicalGrouping, - groupingCurrentLevel, - hideGuide = false, -}: Props) { - const [state, setState] = useState(() => { - const thread = defined(data.values) ? findBestThread(data.values) : undefined; - return { - activeThread: thread, - stackView: thread ? getIntendedStackView(thread, event) : undefined, - stackType: STACK_TYPE.ORIGINAL, - newestFirst: isStacktraceNewestFirst(), - }; - }); - - if (!data.values) { - return null; - } - - function handleSelectNewThread(thread: Thread) { - setState({ - ...state, - activeThread: thread, - stackView: - state.stackView !== STACK_VIEW.RAW - ? getIntendedStackView(thread, event) - : state.stackView, - stackType: STACK_TYPE.ORIGINAL, - }); - } - - function handleChangeNewestFirst({newestFirst}: Pick) { - setState({...state, newestFirst}); - } +function ThreadsContainer({organization, ...props}: Props) { + const hasNativeStackTraceV2 = !!organization.features?.includes( + 'native-stack-trace-v2' + ); - function handleChangeStackView({ - stackView, - stackType, - }: Partial>) { - setState({ - ...state, - stackView: stackView ?? state.stackView, - stackType: stackType ?? state.stackType, - }); + if (hasNativeStackTraceV2) { + return ; } - const threads = data.values; - const {stackView, stackType, newestFirst, activeThread} = state; - - const exception = getThreadException(event, activeThread); - - const stacktrace = !exception - ? getThreadStacktrace(stackType !== STACK_TYPE.ORIGINAL, activeThread) - : undefined; - - const stackTraceNotFound = !(exception || stacktrace); - const hasMoreThanOneThread = threads.length > 1; - - return ( - - ) - } - /> - ) : ( - - ) - } - actions={ - !stackTraceNotFound && ( - - ) - } - showPermalink={!hasMoreThanOneThread} - wrapTitle={false} - > - - - ); + return ; } -export default Threads; +export default ThreadsContainer; diff --git a/static/app/components/events/interfaces/threads/newVersion/index.tsx b/static/app/components/events/interfaces/threads/newVersion/index.tsx new file mode 100644 index 00000000000000..8ef2720fe1f4a6 --- /dev/null +++ b/static/app/components/events/interfaces/threads/newVersion/index.tsx @@ -0,0 +1,185 @@ +import {Fragment, useState} from 'react'; +import styled from '@emotion/styled'; +import isNil from 'lodash/isNil'; + +import EventDataSection from 'app/components/events/eventDataSection'; +import CrashContent from 'app/components/events/interfaces/crashContent'; +import CrashTitle from 'app/components/events/interfaces/crashHeader/crashTitle'; +import {isStacktraceNewestFirst} from 'app/components/events/interfaces/stacktrace'; +import Pill from 'app/components/pill'; +import Pills from 'app/components/pills'; +import {t} from 'app/locale'; +import space from 'app/styles/space'; +import {Project} from 'app/types'; +import {Event} from 'app/types/event'; +import {Thread} from 'app/types/events'; +import {STACK_TYPE} from 'app/types/stacktrace'; +import {defined} from 'app/utils'; +import BooleanField from 'app/views/settings/components/forms/booleanField'; + +import NoStackTraceMessage from '../../noStackTraceMessage'; +import ThreadSelector from '../threadSelector'; +import findBestThread from '../threadSelector/findBestThread'; +import getThreadException from '../threadSelector/getThreadException'; +import getThreadStacktrace from '../threadSelector/getThreadStacktrace'; + +type CrashContentProps = React.ComponentProps; + +type Props = { + event: Event; + projectId: Project['id']; + type: string; + data: { + values?: Array; + }; + hideGuide?: boolean; +} & Pick; + +type State = { + stackType: STACK_TYPE; + newestFirst: boolean; + activeThread?: Thread; + rawStackTrace: boolean; +}; + +function Threads({ + event, + projectId, + type, + data, + groupingCurrentLevel, + hasHierarchicalGrouping, + hideGuide = false, +}: Props) { + const [state, setState] = useState(() => { + const thread = defined(data.values) ? findBestThread(data.values) : undefined; + return { + activeThread: thread, + stackType: STACK_TYPE.ORIGINAL, + newestFirst: isStacktraceNewestFirst(), + rawStackTrace: false, + }; + }); + + function handleChangeNewestFirst({newestFirst}: Pick) { + setState({...state, newestFirst}); + } + + function handleSelectNewThread(thread: Thread) { + setState({ + ...state, + activeThread: thread, + stackType: STACK_TYPE.ORIGINAL, + }); + } + + const threads = data.values ?? []; + const {rawStackTrace, stackType, newestFirst, activeThread} = state; + + const exception = getThreadException(event, activeThread); + + const stacktrace = !exception + ? getThreadStacktrace(stackType !== STACK_TYPE.ORIGINAL, activeThread) + : undefined; + + const stackTraceNotFound = !(exception || stacktrace); + const hasMoreThanOneThread = threads.length > 1; + + return ( + + ) : ( + + ) + } + actions={ + setState({...state, rawStackTrace: !rawStackTrace})} + /> + } + showPermalink={!hasMoreThanOneThread} + wrapTitle={false} + > + + {activeThread && ( + + + {(!isNil(activeThread?.id) || !!activeThread?.name) && ( + + {!isNil(activeThread.id) && ( + + )} + {!!activeThread.name?.trim() && ( + + )} + + + {activeThread.crashed ? t('yes') : t('no')} + + + )} + + )} + {stackTraceNotFound ? ( + + ) : ( + + )} + + + ); +} + +export default Threads; + +const RawToggler = styled(BooleanField)` + padding: 0; + display: grid; + grid-template-columns: auto max-content; + grid-gap: ${space(1)}; + + && { + > * { + padding: 0; + width: auto; + } + } +`; diff --git a/tests/js/spec/components/events/interfaces/threads.spec.jsx b/tests/js/spec/components/events/interfaces/threads.spec.jsx index cce234e98e9313..d22764e6bc52c6 100644 --- a/tests/js/spec/components/events/interfaces/threads.spec.jsx +++ b/tests/js/spec/components/events/interfaces/threads.spec.jsx @@ -3,6 +3,7 @@ import {mountWithTheme} from 'sentry-test/enzyme'; import Threads from 'app/components/events/interfaces/threads'; describe('Threads', () => { + const organization = TestStubs.Organization(); const entries = TestStubs.Entries()[0]; const event = TestStubs.Event({entries}); const exceptionEntry = entries[0]; @@ -55,6 +56,7 @@ describe('Threads', () => { orgId="org-slug" projectId="project-id" event={newEvent} + organization={organization} /> ); @@ -87,6 +89,7 @@ describe('Threads', () => { event.entries[2], ], }} + organization={organization} /> ); @@ -105,6 +108,7 @@ describe('Threads', () => { orgId="org-slug" projectId="project-id" event={event} + organization={organization} /> ); @@ -133,6 +137,7 @@ describe('Threads', () => { event.entries[2], ], }} + organization={organization} /> ); From e65a69d5552a87a175e02391958880caa1eae242 Mon Sep 17 00:00:00 2001 From: Priscila Oliveira Date: Thu, 21 Oct 2021 09:19:51 +0200 Subject: [PATCH 07/15] wip --- static/app/components/events/eventEntry.tsx | 9 +- .../interfaces/threads/newVersion/index.tsx | 66 +++++---- .../events/interfaces/trace/index.tsx | 131 ++++++++++++++++++ .../events/interfaces/crashContent/index.tsx | 0 4 files changed, 178 insertions(+), 28 deletions(-) create mode 100644 static/app/components/events/interfaces/trace/index.tsx create mode 100644 tests/js/spec/components/events/interfaces/crashContent/index.tsx diff --git a/static/app/components/events/eventEntry.tsx b/static/app/components/events/eventEntry.tsx index 485aea52fa247b..25afd9084e4a7c 100644 --- a/static/app/components/events/eventEntry.tsx +++ b/static/app/components/events/eventEntry.tsx @@ -12,6 +12,7 @@ import Spans from 'app/components/events/interfaces/spans'; import Stacktrace from 'app/components/events/interfaces/stacktrace'; import Template from 'app/components/events/interfaces/template'; import Threads from 'app/components/events/interfaces/threads'; +import Trace from 'app/components/events/interfaces/trace'; import {Group, Organization, Project, SharedViewOrganization} from 'app/types'; import {Entry, EntryType, Event, EventTransaction} from 'app/types/event'; @@ -36,6 +37,10 @@ function EventEntry({ !!organization.features?.includes('grouping-stacktrace-ui') && !!(event.metadata.current_tree_label || event.metadata.finest_tree_label); + const hasNativeStackTraceV2 = !!organization.features?.includes( + 'native-stack-trace-v2' + ); + const groupingCurrentLevel = group?.metadata?.current_level; switch (entry.type) { @@ -102,7 +107,9 @@ function EventEntry({ } case EntryType.THREADS: { const {data, type} = entry; - return ( + return hasNativeStackTraceV2 ? ( + + ) : ( + ) + } /> ) : ( - {activeThread && ( - - - {(!isNil(activeThread?.id) || !!activeThread?.name) && ( - - {!isNil(activeThread.id) && ( - - )} - {!!activeThread.name?.trim() && ( - - )} - - - {activeThread.crashed ? t('yes') : t('no')} - - +
+ + {SORT_OPTIONS.map(({label, value}) => ( + + {label} + + ))} + +
+ {activeThread && (!isNil(activeThread?.id) || !!activeThread?.name) && ( + + {!isNil(activeThread.id) && ( + )} -
+ {!!activeThread.name?.trim() && ( + + )} + + + {activeThread.crashed ? t('yes') : t('no')} + + )} {stackTraceNotFound ? ( [] = [ + {label: t('Recent first'), value: SortOption.RECENT_FIRST}, + {label: t('Recent last'), value: SortOption.RECENT_LAST}, +]; + +type Props = { + type: EntryType.THREADS | EntryType.EXCEPTION | EntryType.STACKTRACE; + event: Event; +}; + +type State = { + raw: boolean; + activeSort: SortOption; +}; + +function Trace({type, event}: Props) { + const [state, setState] = useState({ + raw: false, + activeSort: SortOption.RECENT_FIRST, + }); + + function getTitle() { + switch (type) { + case EntryType.EXCEPTION: + return ( + +

{t('Exception')}

+
+ ); + case EntryType.STACKTRACE: + return ( + +

{t('Stack Trace')}

+
+ ); + case EntryType.THREADS: + return ( + {}} + exception={{}} + /> + ); + default: + return ''; + } + } + + function handleSortChange(value: SortOption) { + setState({...state, activeSort: value}); + } + + const {raw, activeSort} = state; + + const activeSortOption = + SORT_OPTIONS.find(sortOption => sortOption.value === activeSort) ?? SORT_OPTIONS[0]; + + return ( + + setState({...state, raw: !raw})} + /> + + {SORT_OPTIONS.map(({label, value}) => ( + + {label} + + ))} + +

+ } + > + {null} + + ); +} + +export default Trace; + +const RawToggler = styled(BooleanField)` + padding: 0; + display: grid; + grid-template-columns: auto max-content; + grid-gap: ${space(1)}; + + && { + > * { + padding: 0; + width: auto; + } + } +`; diff --git a/tests/js/spec/components/events/interfaces/crashContent/index.tsx b/tests/js/spec/components/events/interfaces/crashContent/index.tsx new file mode 100644 index 00000000000000..e69de29bb2d1d6 From cc3e798a7bf19842fca0a80bd451ba6d688898b2 Mon Sep 17 00:00:00 2001 From: Priscila Oliveira Date: Thu, 21 Oct 2021 16:43:14 +0200 Subject: [PATCH 08/15] added traceEventDataSection --- .../components/events/eventDataSection.tsx | 2 +- static/app/components/events/eventEntry.tsx | 12 +- .../threads/{currentVersion => }/content.tsx | 2 +- .../threads/currentVersion/index.tsx | 181 --------------- .../events/interfaces/threads/index.tsx | 184 ++++++++++++++-- .../interfaces/threads/newVersion/index.tsx | 197 ----------------- .../threads/threadSelector/index.tsx | 62 +++--- .../events/interfaces/threadsV2/index.tsx | 206 ++++++++++++++++++ .../events/interfaces/trace/index.tsx | 131 ----------- .../traceEventDataSection/displayOptions.tsx | 181 +++++++++++++++ .../events/traceEventDataSection/index.tsx | 175 +++++++++++++++ .../traceEventDataSection/sortOptions.tsx | 63 ++++++ 12 files changed, 842 insertions(+), 554 deletions(-) rename static/app/components/events/interfaces/threads/{currentVersion => }/content.tsx (97%) delete mode 100644 static/app/components/events/interfaces/threads/currentVersion/index.tsx delete mode 100644 static/app/components/events/interfaces/threads/newVersion/index.tsx create mode 100644 static/app/components/events/interfaces/threadsV2/index.tsx delete mode 100644 static/app/components/events/interfaces/trace/index.tsx create mode 100644 static/app/components/events/traceEventDataSection/displayOptions.tsx create mode 100644 static/app/components/events/traceEventDataSection/index.tsx create mode 100644 static/app/components/events/traceEventDataSection/sortOptions.tsx diff --git a/static/app/components/events/eventDataSection.tsx b/static/app/components/events/eventDataSection.tsx index a77b0743ef62b2..392159dd5f00b0 100644 --- a/static/app/components/events/eventDataSection.tsx +++ b/static/app/components/events/eventDataSection.tsx @@ -81,7 +81,7 @@ class EventDataSection extends React.Component { {titleNode} ) : ( -
{titleNode}
+ titleNode )} {type === 'extra' && ( diff --git a/static/app/components/events/eventEntry.tsx b/static/app/components/events/eventEntry.tsx index 25afd9084e4a7c..42161e35c8e127 100644 --- a/static/app/components/events/eventEntry.tsx +++ b/static/app/components/events/eventEntry.tsx @@ -12,7 +12,7 @@ import Spans from 'app/components/events/interfaces/spans'; import Stacktrace from 'app/components/events/interfaces/stacktrace'; import Template from 'app/components/events/interfaces/template'; import Threads from 'app/components/events/interfaces/threads'; -import Trace from 'app/components/events/interfaces/trace'; +import ThreadsV2 from 'app/components/events/interfaces/threadsV2'; import {Group, Organization, Project, SharedViewOrganization} from 'app/types'; import {Entry, EntryType, Event, EventTransaction} from 'app/types/event'; @@ -108,7 +108,14 @@ function EventEntry({ case EntryType.THREADS: { const {data, type} = entry; return hasNativeStackTraceV2 ? ( - + ) : ( ); } diff --git a/static/app/components/events/interfaces/threads/currentVersion/content.tsx b/static/app/components/events/interfaces/threads/content.tsx similarity index 97% rename from static/app/components/events/interfaces/threads/currentVersion/content.tsx rename to static/app/components/events/interfaces/threads/content.tsx index ac9bd59352b3d2..eb1480adb486a2 100644 --- a/static/app/components/events/interfaces/threads/currentVersion/content.tsx +++ b/static/app/components/events/interfaces/threads/content.tsx @@ -10,7 +10,7 @@ import {Event} from 'app/types/event'; import {Thread} from 'app/types/events'; import {STACK_TYPE, STACK_VIEW} from 'app/types/stacktrace'; -import NoStackTraceMessage from '../../noStackTraceMessage'; +import NoStackTraceMessage from '../noStackTraceMessage'; type CrashContentProps = React.ComponentProps; diff --git a/static/app/components/events/interfaces/threads/currentVersion/index.tsx b/static/app/components/events/interfaces/threads/currentVersion/index.tsx deleted file mode 100644 index 4fbca85dc26d6a..00000000000000 --- a/static/app/components/events/interfaces/threads/currentVersion/index.tsx +++ /dev/null @@ -1,181 +0,0 @@ -import {useState} from 'react'; - -import EventDataSection from 'app/components/events/eventDataSection'; -import CrashActions from 'app/components/events/interfaces/crashHeader/crashActions'; -import CrashTitle from 'app/components/events/interfaces/crashHeader/crashTitle'; -import {isStacktraceNewestFirst} from 'app/components/events/interfaces/stacktrace'; -import {t} from 'app/locale'; -import {Project} from 'app/types'; -import {Event} from 'app/types/event'; -import {Thread} from 'app/types/events'; -import {STACK_TYPE, STACK_VIEW} from 'app/types/stacktrace'; -import {defined} from 'app/utils'; - -import ThreadSelector from '../threadSelector'; -import findBestThread from '../threadSelector/findBestThread'; -import getThreadException from '../threadSelector/getThreadException'; -import getThreadStacktrace from '../threadSelector/getThreadStacktrace'; - -import Content from './content'; - -type Props = Pick< - React.ComponentProps, - 'groupingCurrentLevel' | 'hasHierarchicalGrouping' -> & { - event: Event; - projectId: Project['id']; - type: string; - data: { - values?: Array; - }; - hideGuide?: boolean; -}; - -type State = { - stackType: STACK_TYPE; - newestFirst: boolean; - activeThread?: Thread; - stackView?: STACK_VIEW; -}; - -function getIntendedStackView(thread: Thread, event: Event) { - const exception = getThreadException(event, thread); - if (exception) { - return !!exception.values.find(value => !!value.stacktrace?.hasSystemFrames) - ? STACK_VIEW.APP - : STACK_VIEW.FULL; - } - - const stacktrace = getThreadStacktrace(false, thread); - - return stacktrace?.hasSystemFrames ? STACK_VIEW.APP : STACK_VIEW.FULL; -} - -function Threads({ - data, - event, - projectId, - type, - hasHierarchicalGrouping, - groupingCurrentLevel, - hideGuide = false, -}: Props) { - const [state, setState] = useState(() => { - const thread = defined(data.values) ? findBestThread(data.values) : undefined; - return { - activeThread: thread, - stackView: thread ? getIntendedStackView(thread, event) : undefined, - stackType: STACK_TYPE.ORIGINAL, - newestFirst: isStacktraceNewestFirst(), - }; - }); - - if (!data.values) { - return null; - } - - function handleSelectNewThread(thread: Thread) { - setState({ - ...state, - activeThread: thread, - stackView: - state.stackView !== STACK_VIEW.RAW - ? getIntendedStackView(thread, event) - : state.stackView, - stackType: STACK_TYPE.ORIGINAL, - }); - } - - function handleChangeNewestFirst({newestFirst}: Pick) { - setState({...state, newestFirst}); - } - - function handleChangeStackView({ - stackView, - stackType, - }: Partial>) { - setState({ - ...state, - stackView: stackView ?? state.stackView, - stackType: stackType ?? state.stackType, - }); - } - - const threads = data.values; - const {stackView, stackType, newestFirst, activeThread} = state; - - const exception = getThreadException(event, activeThread); - - const stacktrace = !exception - ? getThreadStacktrace(stackType !== STACK_TYPE.ORIGINAL, activeThread) - : undefined; - - const stackTraceNotFound = !(exception || stacktrace); - const hasMoreThanOneThread = threads.length > 1; - - return ( - - ) - } - /> - ) : ( - - ) - } - actions={ - !stackTraceNotFound && ( - - ) - } - showPermalink={!hasMoreThanOneThread} - wrapTitle={false} - > - - - ); -} - -export default Threads; diff --git a/static/app/components/events/interfaces/threads/index.tsx b/static/app/components/events/interfaces/threads/index.tsx index ab9dfe3e49532d..9fe0e7297901f9 100644 --- a/static/app/components/events/interfaces/threads/index.tsx +++ b/static/app/components/events/interfaces/threads/index.tsx @@ -1,22 +1,180 @@ -import {Organization} from 'app/types'; +import {useState} from 'react'; -import CurrentVersion from './currentVersion'; -import NewVersion from './newVersion'; +import EventDataSection from 'app/components/events/eventDataSection'; +import CrashActions from 'app/components/events/interfaces/crashHeader/crashActions'; +import CrashTitle from 'app/components/events/interfaces/crashHeader/crashTitle'; +import {isStacktraceNewestFirst} from 'app/components/events/interfaces/stacktrace'; +import {t} from 'app/locale'; +import {Project} from 'app/types'; +import {Event} from 'app/types/event'; +import {Thread} from 'app/types/events'; +import {STACK_TYPE, STACK_VIEW} from 'app/types/stacktrace'; +import {defined} from 'app/utils'; -type Props = React.ComponentProps & { - organization: Organization; +import findBestThread from './threadSelector/findBestThread'; +import getThreadException from './threadSelector/getThreadException'; +import getThreadStacktrace from './threadSelector/getThreadStacktrace'; +import Content from './content'; +import ThreadSelector from './threadSelector'; + +type Props = Pick< + React.ComponentProps, + 'groupingCurrentLevel' | 'hasHierarchicalGrouping' +> & { + event: Event; + projectId: Project['id']; + type: string; + data: { + values?: Array; + }; + hideGuide?: boolean; }; -function ThreadsContainer({organization, ...props}: Props) { - const hasNativeStackTraceV2 = !!organization.features?.includes( - 'native-stack-trace-v2' - ); +type State = { + stackType: STACK_TYPE; + newestFirst: boolean; + activeThread?: Thread; + stackView?: STACK_VIEW; +}; + +function getIntendedStackView(thread: Thread, event: Event) { + const exception = getThreadException(event, thread); + if (exception) { + return !!exception.values.find(value => !!value.stacktrace?.hasSystemFrames) + ? STACK_VIEW.APP + : STACK_VIEW.FULL; + } + + const stacktrace = getThreadStacktrace(false, thread); + + return stacktrace?.hasSystemFrames ? STACK_VIEW.APP : STACK_VIEW.FULL; +} + +function Threads({ + data, + event, + projectId, + type, + hasHierarchicalGrouping, + groupingCurrentLevel, + hideGuide = false, +}: Props) { + const [state, setState] = useState(() => { + const thread = defined(data.values) ? findBestThread(data.values) : undefined; + return { + activeThread: thread, + stackView: thread ? getIntendedStackView(thread, event) : undefined, + stackType: STACK_TYPE.ORIGINAL, + newestFirst: isStacktraceNewestFirst(), + }; + }); + + if (!data.values) { + return null; + } + + function handleSelectNewThread(thread: Thread) { + setState({ + ...state, + activeThread: thread, + stackView: + state.stackView !== STACK_VIEW.RAW + ? getIntendedStackView(thread, event) + : state.stackView, + stackType: STACK_TYPE.ORIGINAL, + }); + } + + function handleChangeNewestFirst({newestFirst}: Pick) { + setState({...state, newestFirst}); + } - if (hasNativeStackTraceV2) { - return ; + function handleChangeStackView({ + stackView, + stackType, + }: Partial>) { + setState({ + ...state, + stackView: stackView ?? state.stackView, + stackType: stackType ?? state.stackType, + }); } - return ; + const threads = data.values; + const {stackView, stackType, newestFirst, activeThread} = state; + + const exception = getThreadException(event, activeThread); + + const stacktrace = !exception + ? getThreadStacktrace(stackType !== STACK_TYPE.ORIGINAL, activeThread) + : undefined; + + const stackTraceNotFound = !(exception || stacktrace); + const hasMoreThanOneThread = threads.length > 1; + + return ( + + ) + } + /> + ) : ( + + ) + } + actions={ + !stackTraceNotFound && ( + + ) + } + showPermalink={!hasMoreThanOneThread} + wrapTitle={false} + > + + + ); } -export default ThreadsContainer; +export default Threads; diff --git a/static/app/components/events/interfaces/threads/newVersion/index.tsx b/static/app/components/events/interfaces/threads/newVersion/index.tsx deleted file mode 100644 index 61d1f756a81c5d..00000000000000 --- a/static/app/components/events/interfaces/threads/newVersion/index.tsx +++ /dev/null @@ -1,197 +0,0 @@ -import {Fragment, useState} from 'react'; -import styled from '@emotion/styled'; -import isNil from 'lodash/isNil'; - -import DropdownControl, {DropdownItem} from 'app/components/dropdownControl'; -import EventDataSection from 'app/components/events/eventDataSection'; -import CrashContent from 'app/components/events/interfaces/crashContent'; -import CrashTitle from 'app/components/events/interfaces/crashHeader/crashTitle'; -import {isStacktraceNewestFirst} from 'app/components/events/interfaces/stacktrace'; -import Pill from 'app/components/pill'; -import Pills from 'app/components/pills'; -import {t} from 'app/locale'; -import space from 'app/styles/space'; -import {Project} from 'app/types'; -import {Event} from 'app/types/event'; -import {Thread} from 'app/types/events'; -import {STACK_TYPE} from 'app/types/stacktrace'; -import {defined} from 'app/utils'; -import BooleanField from 'app/views/settings/components/forms/booleanField'; - -import NoStackTraceMessage from '../../noStackTraceMessage'; -import ThreadSelector from '../threadSelector'; -import findBestThread from '../threadSelector/findBestThread'; -import getThreadException from '../threadSelector/getThreadException'; -import getThreadStacktrace from '../threadSelector/getThreadStacktrace'; - -type CrashContentProps = React.ComponentProps; - -type Props = { - event: Event; - projectId: Project['id']; - type: string; - data: { - values?: Array; - }; - hideGuide?: boolean; -} & Pick; - -type State = { - stackType: STACK_TYPE; - newestFirst: boolean; - activeThread?: Thread; - rawStackTrace: boolean; -}; - -function Threads({ - event, - projectId, - type, - data, - groupingCurrentLevel, - hasHierarchicalGrouping, - hideGuide = false, -}: Props) { - const [state, setState] = useState(() => { - const thread = defined(data.values) ? findBestThread(data.values) : undefined; - return { - activeThread: thread, - stackType: STACK_TYPE.ORIGINAL, - newestFirst: isStacktraceNewestFirst(), - rawStackTrace: false, - }; - }); - - function handleChangeNewestFirst({newestFirst}: Pick) { - setState({...state, newestFirst}); - } - - function handleSelectNewThread(thread: Thread) { - setState({ - ...state, - activeThread: thread, - stackType: STACK_TYPE.ORIGINAL, - }); - } - - const threads = data.values ?? []; - const {rawStackTrace, stackType, newestFirst, activeThread} = state; - - const exception = getThreadException(event, activeThread); - - const stacktrace = !exception - ? getThreadStacktrace(stackType !== STACK_TYPE.ORIGINAL, activeThread) - : undefined; - - const stackTraceNotFound = !(exception || stacktrace); - const hasMoreThanOneThread = threads.length > 1; - - return ( - - ) - } - /> - ) : ( - - ) - } - actions={ - setState({...state, rawStackTrace: !rawStackTrace})} - /> - } - showPermalink={!hasMoreThanOneThread} - wrapTitle={false} - > - -
- - {SORT_OPTIONS.map(({label, value}) => ( - - {label} - - ))} - -
- {activeThread && (!isNil(activeThread?.id) || !!activeThread?.name) && ( - - {!isNil(activeThread.id) && ( - - )} - {!!activeThread.name?.trim() && ( - - )} - - - {activeThread.crashed ? t('yes') : t('no')} - - - )} - {stackTraceNotFound ? ( - - ) : ( - - )} -
-
- ); -} - -export default Threads; - -const RawToggler = styled(BooleanField)` - padding: 0; - display: grid; - grid-template-columns: auto max-content; - grid-gap: ${space(1)}; - - && { - > * { - padding: 0; - width: auto; - } - } -`; diff --git a/static/app/components/events/interfaces/threads/threadSelector/index.tsx b/static/app/components/events/interfaces/threads/threadSelector/index.tsx index 9dd026953e7655..0c8c65209e5c4c 100644 --- a/static/app/components/events/interfaces/threads/threadSelector/index.tsx +++ b/static/app/components/events/interfaces/threads/threadSelector/index.tsx @@ -1,3 +1,4 @@ +import {ClassNames} from '@emotion/react'; import styled from '@emotion/styled'; import partition from 'lodash/partition'; @@ -56,35 +57,42 @@ const ThreadSelector = ({threads, event, exception, activeThread, onChange}: Pro }; return ( - { - handleChange(item.thread); - }} - maxHeight={DROPDOWN_MAX_HEIGHT} - searchPlaceholder={t('Filter Threads')} - emptyMessage={t('You have no threads')} - noResultsMessage={t('No threads found')} - menuHeader={
} - closeOnSelect - emptyHidesInput - > - {({isOpen, selectedItem}) => ( - - {selectedItem ? ( - - ) : ( - + + {({css}) => ( + { + handleChange(item.thread); + }} + maxHeight={DROPDOWN_MAX_HEIGHT} + searchPlaceholder={t('Filter Threads')} + emptyMessage={t('You have no threads')} + noResultsMessage={t('No threads found')} + menuHeader={
} + rootClassName={css` + width: 100%; + `} + closeOnSelect + emptyHidesInput + > + {({isOpen, selectedItem}) => ( + + {selectedItem ? ( + + ) : ( + + )} + )} - + )} - + ); }; diff --git a/static/app/components/events/interfaces/threadsV2/index.tsx b/static/app/components/events/interfaces/threadsV2/index.tsx new file mode 100644 index 00000000000000..f27a91a0a29624 --- /dev/null +++ b/static/app/components/events/interfaces/threadsV2/index.tsx @@ -0,0 +1,206 @@ +import {Fragment, useState} from 'react'; +import isNil from 'lodash/isNil'; + +import {isStacktraceNewestFirst} from 'app/components/events/interfaces/stacktrace'; +import Pill from 'app/components/pill'; +import Pills from 'app/components/pills'; +import {t} from 'app/locale'; +import {PlatformType, Project} from 'app/types'; +import {Event} from 'app/types/event'; +import {Thread} from 'app/types/events'; +import {STACK_TYPE, STACK_VIEW} from 'app/types/stacktrace'; +import {defined} from 'app/utils'; + +import TraceEventDataSection from '../../traceEventDataSection'; +import {DisplayOption} from '../../traceEventDataSection/displayOptions'; +import Exception from '../crashContent/exception'; +import StackTrace from '../crashContent/stacktrace'; +import NoStackTraceMessage from '../noStackTraceMessage'; +import ThreadSelector from '../threads/threadSelector'; +import findBestThread from '../threads/threadSelector/findBestThread'; +import getThreadException from '../threads/threadSelector/getThreadException'; +import getThreadStacktrace from '../threads/threadSelector/getThreadStacktrace'; + +type ExceptionProps = React.ComponentProps; + +type Props = Pick & { + event: Event; + projectId: Project['id']; + type: string; + data: { + values?: Array; + }; +}; + +type State = { + stackType: STACK_TYPE; + activeThread?: Thread; +}; + +function getIntendedStackView(thread: Thread, event: Event) { + const exception = getThreadException(event, thread); + if (exception) { + return !!exception.values.find(value => !!value.stacktrace?.hasSystemFrames) + ? STACK_VIEW.APP + : STACK_VIEW.FULL; + } + + const stacktrace = getThreadStacktrace(false, thread); + + return stacktrace?.hasSystemFrames ? STACK_VIEW.APP : STACK_VIEW.FULL; +} + +function Threads({ + data, + event, + projectId, + type, + hasHierarchicalGrouping, + groupingCurrentLevel, +}: Props) { + const [state, setState] = useState(() => { + const thread = defined(data.values) ? findBestThread(data.values) : undefined; + return { + activeThread: thread, + stackType: STACK_TYPE.ORIGINAL, + }; + }); + + if (!data.values) { + return null; + } + + const threads = data.values; + const {stackType, activeThread} = state; + + const platform = (event.platform ?? 'other') as PlatformType; + const hasMoreThanOneThread = threads.length > 1; + const exception = getThreadException(event, activeThread); + const stackView = activeThread ? getIntendedStackView(activeThread, event) : undefined; + + function renderPills() { + const {id, name, current, crashed} = activeThread ?? {}; + + if (isNil(id) || !name) { + return null; + } + + return ( + + {!isNil(id) && } + {!!name?.trim() && } + {current !== undefined && } + {crashed !== undefined && ( + + {crashed ? t('yes') : t('no')} + + )} + + ); + } + + function renderContent({ + recentFirst, + raw, + activeDisplayOptions, + }: Parameters['children']>[0]) { + if (exception) { + return ( + + ); + } + + const stacktrace = getThreadStacktrace( + stackType !== STACK_TYPE.ORIGINAL, + activeThread + ); + + if (stacktrace) { + return ( + + ); + } + + return ( + + ); + } + + function getTitle() { + if (hasMoreThanOneThread && activeThread) { + return ( + { + setState({ + ...state, + activeThread: thread, + stackType: STACK_TYPE.ORIGINAL, + }); + }} + exception={exception} + /> + ); + } + + return t('Stack Trace'); + } + + return ( + + {childrenProps => ( + + {renderPills()} + {renderContent(childrenProps)} + + )} + + ); +} + +export default Threads; diff --git a/static/app/components/events/interfaces/trace/index.tsx b/static/app/components/events/interfaces/trace/index.tsx deleted file mode 100644 index b8ca13449261a2..00000000000000 --- a/static/app/components/events/interfaces/trace/index.tsx +++ /dev/null @@ -1,131 +0,0 @@ -import {useState} from 'react'; -import styled from '@emotion/styled'; - -import GuideAnchor from 'app/components/assistant/guideAnchor'; -import DropdownControl, {DropdownItem} from 'app/components/dropdownControl'; -import EventDataSection from 'app/components/events/eventDataSection'; -import {t} from 'app/locale'; -import space from 'app/styles/space'; -import {SelectValue} from 'app/types'; -import {EntryType, Event} from 'app/types/event'; -import BooleanField from 'app/views/settings/components/forms/booleanField'; - -import ThreadSelector from '../threads/threadSelector'; - -enum SortOption { - RECENT_FIRST = 'recent-first', - RECENT_LAST = 'recent-last', -} - -const SORT_OPTIONS: SelectValue[] = [ - {label: t('Recent first'), value: SortOption.RECENT_FIRST}, - {label: t('Recent last'), value: SortOption.RECENT_LAST}, -]; - -type Props = { - type: EntryType.THREADS | EntryType.EXCEPTION | EntryType.STACKTRACE; - event: Event; -}; - -type State = { - raw: boolean; - activeSort: SortOption; -}; - -function Trace({type, event}: Props) { - const [state, setState] = useState({ - raw: false, - activeSort: SortOption.RECENT_FIRST, - }); - - function getTitle() { - switch (type) { - case EntryType.EXCEPTION: - return ( - -

{t('Exception')}

-
- ); - case EntryType.STACKTRACE: - return ( - -

{t('Stack Trace')}

-
- ); - case EntryType.THREADS: - return ( - {}} - exception={{}} - /> - ); - default: - return ''; - } - } - - function handleSortChange(value: SortOption) { - setState({...state, activeSort: value}); - } - - const {raw, activeSort} = state; - - const activeSortOption = - SORT_OPTIONS.find(sortOption => sortOption.value === activeSort) ?? SORT_OPTIONS[0]; - - return ( - - setState({...state, raw: !raw})} - /> - - {SORT_OPTIONS.map(({label, value}) => ( - - {label} - - ))} - - - } - > - {null} - - ); -} - -export default Trace; - -const RawToggler = styled(BooleanField)` - padding: 0; - display: grid; - grid-template-columns: auto max-content; - grid-gap: ${space(1)}; - - && { - > * { - padding: 0; - width: auto; - } - } -`; diff --git a/static/app/components/events/traceEventDataSection/displayOptions.tsx b/static/app/components/events/traceEventDataSection/displayOptions.tsx new file mode 100644 index 00000000000000..87a49909e469ab --- /dev/null +++ b/static/app/components/events/traceEventDataSection/displayOptions.tsx @@ -0,0 +1,181 @@ +import styled from '@emotion/styled'; + +import CheckboxFancy from 'app/components/checkboxFancy/checkboxFancy'; +import DropdownButton from 'app/components/dropdownButton'; +import DropdownControl, {Content} from 'app/components/dropdownControl'; +import List from 'app/components/list'; +import ListItem from 'app/components/list/listItem'; +import {t, tct} from 'app/locale'; +import space from 'app/styles/space'; +import {SelectValue} from 'app/types'; + +export enum DisplayOption { + UNSYMBOLICATED = 'unsymbolicated', + ABSOLUTE_ADDRESSES = 'absolute-addresses', + ABSOLUTE_FILE_PATHS = 'absolute-file-paths', + VERBOSE_FUNCTION_NAMES = 'verbose-function-names', + FULL_STACK_TRACE = 'full-stack-trace', +} + +const DISPLAY_OPTIONS: SelectValue[] = [ + {label: t('Unsymbolicated'), value: DisplayOption.UNSYMBOLICATED}, + {label: t('Absolute Addresses'), value: DisplayOption.ABSOLUTE_ADDRESSES}, + {label: t('Absolute File Paths'), value: DisplayOption.ABSOLUTE_FILE_PATHS}, + {label: t('Verbose Function Names'), value: DisplayOption.VERBOSE_FUNCTION_NAMES}, + {label: t('Full Stack Trace'), value: DisplayOption.FULL_STACK_TRACE}, +]; + +type Props = { + activeDisplayOptions: DisplayOption[]; + onChange: (activeDisplayOptions: DisplayOption[]) => void; +}; + +function DisplayOptions({activeDisplayOptions, onChange}: Props) { + function handleChange(value: DisplayOption) { + const newActiveDisplayOptions = activeDisplayOptions.includes(value) + ? activeDisplayOptions.filter(activeDisplayOption => activeDisplayOption !== value) + : [...activeDisplayOptions, value]; + + onChange(newActiveDisplayOptions); + } + return ( + ( + + {tct('[activeOptionsQuantity] Active', { + activeOptionsQuantity: activeDisplayOptions.length, + })} + + )} + > + {({getMenuProps, isOpen}) => ( + + + {DISPLAY_OPTIONS.map(({label, value}) => { + const displayOption = value as DisplayOption; + const isChecked = activeDisplayOptions.includes(displayOption); + return ( + { + event.stopPropagation(); + handleChange(displayOption); + }} + isChecked={isChecked} + > + {label} + + + ); + })} + + + )} + + ); +} + +export default DisplayOptions; + +const Wrapper = styled(DropdownControl)` + z-index: 1; + &, + button { + width: 100%; + } + grid-column: 1/-1; + grid-row: 3/3; + + @media (min-width: ${p => p.theme.breakpoints[0]}) { + grid-column: 2/2; + grid-row: 2/2; + } + + @media (min-width: ${p => p.theme.breakpoints[3]}) { + grid-column: auto; + grid-row: auto; + } +`; + +const StyledContent = styled(Content)` + top: calc(100% + ${space(0.5)} - 1px); + border-radius: ${p => p.theme.borderRadius}; + > ul:last-child { + > li:last-child { + border-bottom: none; + } + } +`; + +const StyledDropdownButton = styled(DropdownButton)` + z-index: ${p => p.theme.zIndex.dropdownAutocomplete.actor}; + border-radius: ${p => p.theme.borderRadius}; + max-width: 200px; + white-space: nowrap; + + ${p => + p.isOpen && + ` + :before, + :after { + position: absolute; + bottom: calc(${space(0.5)} + 1px); + right: 32px; + content: ''; + width: 16px; + border: 8px solid transparent; + transform: translateY(calc(50% + 2px)); + right: 13px; + border-bottom-color: ${p.theme.backgroundSecondary}; + } + + :before { + transform: translateY(calc(50% + 1px)); + border-bottom-color: ${p.theme.border}; + } + `} +`; + +const StyledList = styled(List)` + grid-gap: 0; +`; + +const StyledListItem = styled(ListItem)<{isChecked: boolean}>` + display: grid; + grid-template-columns: 1fr max-content; + grid-column-gap: ${space(1)}; + padding: ${space(1)} ${space(2)}; + border-bottom: 1px solid ${p => p.theme.border}; + align-items: center; + cursor: pointer; + font-size: ${p => p.theme.fontSizeMedium}; + + ${CheckboxFancy} { + opacity: ${p => (p.isChecked ? 1 : 0.3)}; + } + + :hover { + background-color: ${p => p.theme.backgroundSecondary}; + ${CheckboxFancy} { + opacity: 1; + } + span { + color: ${p => p.theme.blue300}; + text-decoration: underline; + } + } +`; diff --git a/static/app/components/events/traceEventDataSection/index.tsx b/static/app/components/events/traceEventDataSection/index.tsx new file mode 100644 index 00000000000000..ca219fa1bbe489 --- /dev/null +++ b/static/app/components/events/traceEventDataSection/index.tsx @@ -0,0 +1,175 @@ +import {Fragment, useEffect, useState} from 'react'; +import styled from '@emotion/styled'; + +import Button from 'app/components/button'; +import {t} from 'app/locale'; +import space from 'app/styles/space'; +import {PlatformType, Project} from 'app/types'; +import {Event} from 'app/types/event'; +import {STACK_TYPE} from 'app/types/stacktrace'; +import {isNativePlatform} from 'app/utils/platform'; +import useApi from 'app/utils/useApi'; +import {useOrganization} from 'app/utils/useOrganization'; +import BooleanField from 'app/views/settings/components/forms/booleanField'; + +import EventDataSection from '../eventDataSection'; + +import DisplayOptions, {DisplayOption} from './displayOptions'; +import SortOptions, {SortOption} from './sortOptions'; + +type Props = { + title: React.ReactNode; + type: string; + recentFirst: boolean; + fullStackTrace: boolean; + children: (childProps: State) => React.ReactNode; + projectId: Project['id']; + eventId: Event['id']; + stackType: STACK_TYPE; + platform: PlatformType; + wrapTitle?: boolean; + showPermalink?: boolean; +}; + +type State = { + raw: boolean; + recentFirst: boolean; + activeDisplayOptions: DisplayOption[]; +}; + +function TraceEventDataSection({ + title, + type, + children, + projectId, + eventId, + stackType, + platform, + showPermalink, + wrapTitle, + ...defaultStateProps +}: Props) { + const api = useApi(); + const organization = useOrganization(); + + const [state, setState] = useState(() => { + const {recentFirst, fullStackTrace} = defaultStateProps; + return { + raw: false, + recentFirst, + activeDisplayOptions: fullStackTrace ? [DisplayOption.FULL_STACK_TRACE] : [], + }; + }); + + const {recentFirst, raw, activeDisplayOptions} = state; + + useEffect(() => { + if (raw || activeDisplayOptions.includes(DisplayOption.FULL_STACK_TRACE)) { + return; + } + + setState({ + ...state, + activeDisplayOptions: [...activeDisplayOptions, DisplayOption.FULL_STACK_TRACE], + }); + }, [defaultStateProps.fullStackTrace]); + + function getDownloadHref() { + const minified = stackType === STACK_TYPE.MINIFIED; + // Apple crash report endpoint + const endpoint = `/projects/${organization.slug}/${projectId}/events/${eventId}/apple-crash-report?minified=${minified}`; + return `${api.baseUrl}${endpoint}&download=1`; + } + + return ( + + {title} + setState({...state, raw: !raw})} + /> + {raw ? ( + + ) : ( + + + setState({ + ...state, + recentFirst: newSortOption === SortOption.RECENT_FIRST, + }) + } + /> + + setState({ + ...state, + activeDisplayOptions: newActiveDisplayOptions, + }) + } + /> + + )} +
+ } + showPermalink={showPermalink} + wrapTitle={wrapTitle} + > + {children({recentFirst, raw, activeDisplayOptions})} + + ); +} + +export default TraceEventDataSection; + +const Header = styled('div')` + display: grid; + grid-template-columns: repeat(2, 1fr); + grid-template-rows: repeat(3, 1fr); + grid-gap: ${space(2)}; + flex: 1; + align-items: center; + justify-items: flex-end; + z-index: 3; + + @media (min-width: ${p => p.theme.breakpoints[0]}) { + grid-template-rows: repeat(2, 1fr); + grid-template-rows: repeat(2, 1fr); + } + + @media (min-width: ${p => p.theme.breakpoints[3]}) { + grid-template-columns: 1fr repeat(3, max-content); + grid-template-rows: 1fr; + } +`; + +const RawToggler = styled(BooleanField)` + padding: 0; + display: grid; + grid-template-columns: repeat(2, max-content); + grid-gap: ${space(1)}; + border-bottom: none; + + && { + > * { + padding: 0; + width: auto; + } + } +`; diff --git a/static/app/components/events/traceEventDataSection/sortOptions.tsx b/static/app/components/events/traceEventDataSection/sortOptions.tsx new file mode 100644 index 00000000000000..0db793937c6e7a --- /dev/null +++ b/static/app/components/events/traceEventDataSection/sortOptions.tsx @@ -0,0 +1,63 @@ +import styled from '@emotion/styled'; + +import DropdownControl, {DropdownItem} from 'app/components/dropdownControl'; +import {t} from 'app/locale'; +import {SelectValue} from 'app/types'; + +export enum SortOption { + RECENT_FIRST = 'recent-first', + RECENT_LAST = 'recent-last', +} + +const SORT_OPTIONS: SelectValue[] = [ + {label: t('Recent first'), value: SortOption.RECENT_FIRST}, + {label: t('Recent last'), value: SortOption.RECENT_LAST}, +]; + +type Props = { + activeSortOption: SortOption; + onChange: (sortOption: SortOption) => void; +}; + +function SortOptions({activeSortOption, onChange}: Props) { + const {label: currentLabel, value: currentValue} = + SORT_OPTIONS.find(sortOption => sortOption.value === activeSortOption) ?? + SORT_OPTIONS[0]; + + return ( + + {SORT_OPTIONS.map(({label, value}) => ( + onChange(sortOption)} + > + {label} + + ))} + + ); +} + +export default SortOptions; + +const Wrapper = styled(DropdownControl)` + z-index: 2; + &, + button { + width: 100%; + } + grid-column: 1/-1; + grid-row: 2/3; + + @media (min-width: ${p => p.theme.breakpoints[0]}) { + grid-column: 1/2; + grid-row: 2/2; + } + + @media (min-width: ${p => p.theme.breakpoints[2]}) { + grid-column: auto; + grid-row: auto; + } +`; From e5f2033e3aed317a326cfb3148c83dd03029ce67 Mon Sep 17 00:00:00 2001 From: Priscila Oliveira Date: Fri, 22 Oct 2021 14:44:06 +0200 Subject: [PATCH 09/15] revert test --- tests/js/spec/components/events/interfaces/threads.spec.jsx | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/js/spec/components/events/interfaces/threads.spec.jsx b/tests/js/spec/components/events/interfaces/threads.spec.jsx index d22764e6bc52c6..cce234e98e9313 100644 --- a/tests/js/spec/components/events/interfaces/threads.spec.jsx +++ b/tests/js/spec/components/events/interfaces/threads.spec.jsx @@ -3,7 +3,6 @@ import {mountWithTheme} from 'sentry-test/enzyme'; import Threads from 'app/components/events/interfaces/threads'; describe('Threads', () => { - const organization = TestStubs.Organization(); const entries = TestStubs.Entries()[0]; const event = TestStubs.Event({entries}); const exceptionEntry = entries[0]; @@ -56,7 +55,6 @@ describe('Threads', () => { orgId="org-slug" projectId="project-id" event={newEvent} - organization={organization} /> ); @@ -89,7 +87,6 @@ describe('Threads', () => { event.entries[2], ], }} - organization={organization} /> ); @@ -108,7 +105,6 @@ describe('Threads', () => { orgId="org-slug" projectId="project-id" event={event} - organization={organization} /> ); @@ -137,7 +133,6 @@ describe('Threads', () => { event.entries[2], ], }} - organization={organization} /> ); From 876b0f9b74792117860b0439d77453e833188437 Mon Sep 17 00:00:00 2001 From: Priscila Oliveira Date: Fri, 22 Oct 2021 16:06:30 +0200 Subject: [PATCH 10/15] removed repeat css --- static/app/components/events/traceEventDataSection/index.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/static/app/components/events/traceEventDataSection/index.tsx b/static/app/components/events/traceEventDataSection/index.tsx index ca219fa1bbe489..fdf50035550d12 100644 --- a/static/app/components/events/traceEventDataSection/index.tsx +++ b/static/app/components/events/traceEventDataSection/index.tsx @@ -150,7 +150,6 @@ const Header = styled('div')` @media (min-width: ${p => p.theme.breakpoints[0]}) { grid-template-rows: repeat(2, 1fr); - grid-template-rows: repeat(2, 1fr); } @media (min-width: ${p => p.theme.breakpoints[3]}) { From 0bad552f2e1d9845843bd065f6094e0bf9fe4407 Mon Sep 17 00:00:00 2001 From: Priscila Oliveira Date: Fri, 22 Oct 2021 16:07:56 +0200 Subject: [PATCH 11/15] remove comment --- tests/js/spec/utils/withTeamsForUser.spec.jsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/js/spec/utils/withTeamsForUser.spec.jsx b/tests/js/spec/utils/withTeamsForUser.spec.jsx index 730dec3ab0ca1b..75ab3d238e665f 100644 --- a/tests/js/spec/utils/withTeamsForUser.spec.jsx +++ b/tests/js/spec/utils/withTeamsForUser.spec.jsx @@ -9,8 +9,6 @@ describe('withUserTeams HoC', function () { const organization = TestStubs.Organization(); delete organization.projects; - // console.log - beforeEach(function () { MockApiClient.clearMockResponses(); jest.spyOn(ProjectActions, 'loadProjects'); From 5a06f24606e78ae41d1b9909e7c5f26d97938105 Mon Sep 17 00:00:00 2001 From: Priscila Oliveira Date: Fri, 22 Oct 2021 16:08:39 +0200 Subject: [PATCH 12/15] remove test test file --- .../events/interfaces/crashContent/index.tsx | 0 tests/js/spec/utils/test.spec.jsx | 57 ------------------- 2 files changed, 57 deletions(-) delete mode 100644 tests/js/spec/components/events/interfaces/crashContent/index.tsx delete mode 100644 tests/js/spec/utils/test.spec.jsx diff --git a/tests/js/spec/components/events/interfaces/crashContent/index.tsx b/tests/js/spec/components/events/interfaces/crashContent/index.tsx deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/tests/js/spec/utils/test.spec.jsx b/tests/js/spec/utils/test.spec.jsx deleted file mode 100644 index 730dec3ab0ca1b..00000000000000 --- a/tests/js/spec/utils/test.spec.jsx +++ /dev/null @@ -1,57 +0,0 @@ -import {mountWithTheme} from 'sentry-test/enzyme'; - -import ProjectActions from 'app/actions/projectActions'; -import TeamActions from 'app/actions/teamActions'; -import withTeamsForUser from 'app/utils/withTeamsForUser'; - -describe('withUserTeams HoC', function () { - const api = new MockApiClient(); - const organization = TestStubs.Organization(); - delete organization.projects; - - // console.log - - beforeEach(function () { - MockApiClient.clearMockResponses(); - jest.spyOn(ProjectActions, 'loadProjects'); - jest.spyOn(TeamActions, 'loadTeams'); - }); - - it('forwards errors', async function () { - MockApiClient.addMockResponse({ - url: `/organizations/${organization.slug}/user-teams/`, - statusCode: 400, - }); - const MyComponent = () => null; - const Container = withTeamsForUser(MyComponent); - const wrapper = mountWithTheme(); - await tick(); - expect(wrapper.update().find('MyComponent').prop('error')).not.toBeNull(); - }); - - it('fetches teams and loads stores', async function () { - const mockProjectA = TestStubs.Project({slug: 'a', id: '1'}); - const mockProjectB = TestStubs.Project({slug: 'b', id: '2'}); - const mockTeams = [ - { - slug: 'sentry', - projects: [mockProjectB], - }, - { - slug: 'captainplanet', - projects: [mockProjectA, mockProjectB], - }, - ]; - - MockApiClient.addMockResponse({ - url: `/organizations/${organization.slug}/user-teams/`, - body: mockTeams, - }); - - const MyComponent = () => null; - const Container = withTeamsForUser(MyComponent); - const wrapper = mountWithTheme(); - await tick(); - expect(wrapper.update().find('MyComponent').prop('teams')).toEqual(mockTeams); - }); -}); From d32b8ed60c305bc01f021b090b9dbd7039fb547b Mon Sep 17 00:00:00 2001 From: Priscila Oliveira Date: Fri, 22 Oct 2021 16:30:40 +0200 Subject: [PATCH 13/15] update thread selector --- .../threads/threadSelector/index.tsx | 20 +++++++++++++++---- .../events/interfaces/threadsV2/index.tsx | 1 + 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/static/app/components/events/interfaces/threads/threadSelector/index.tsx b/static/app/components/events/interfaces/threads/threadSelector/index.tsx index 0c8c65209e5c4c..89e2e069caed3e 100644 --- a/static/app/components/events/interfaces/threads/threadSelector/index.tsx +++ b/static/app/components/events/interfaces/threads/threadSelector/index.tsx @@ -19,13 +19,21 @@ type Props = { threads: Array; activeThread: Thread; event: Event; + fullWidth?: boolean; exception?: Required; onChange?: (thread: Thread) => void; }; const DROPDOWN_MAX_HEIGHT = 400; -const ThreadSelector = ({threads, event, exception, activeThread, onChange}: Props) => { +const ThreadSelector = ({ + threads, + event, + exception, + activeThread, + onChange, + fullWidth = false, +}: Props) => { const getDropDownItem = (thread: Thread) => { const {label, filename, crashedInfo} = filterThreadInfo(event, thread, exception); const threadInfo = {label, filename}; @@ -69,9 +77,13 @@ const ThreadSelector = ({threads, event, exception, activeThread, onChange}: Pro emptyMessage={t('You have no threads')} noResultsMessage={t('No threads found')} menuHeader={
} - rootClassName={css` - width: 100%; - `} + rootClassName={ + fullWidth + ? css` + width: 100%; + ` + : undefined + } closeOnSelect emptyHidesInput > diff --git a/static/app/components/events/interfaces/threadsV2/index.tsx b/static/app/components/events/interfaces/threadsV2/index.tsx index f27a91a0a29624..2c5a8ffdaad404 100644 --- a/static/app/components/events/interfaces/threadsV2/index.tsx +++ b/static/app/components/events/interfaces/threadsV2/index.tsx @@ -173,6 +173,7 @@ function Threads({ }); }} exception={exception} + fullWidth /> ); } From 5aa142a7eb878b1c3da14243ab0f2a0a4ab44f19 Mon Sep 17 00:00:00 2001 From: Priscila Oliveira Date: Fri, 22 Oct 2021 16:45:47 +0200 Subject: [PATCH 14/15] fixed event section title for non thread --- static/app/components/events/eventDataSection.tsx | 1 + .../events/interfaces/threadsV2/index.tsx | 7 ++++++- .../events/traceEventDataSection/index.tsx | 14 +++++--------- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/static/app/components/events/eventDataSection.tsx b/static/app/components/events/eventDataSection.tsx index 392159dd5f00b0..feb6852c9ca58f 100644 --- a/static/app/components/events/eventDataSection.tsx +++ b/static/app/components/events/eventDataSection.tsx @@ -123,6 +123,7 @@ const StyledIconAnchor = styled(IconAnchor)` `; const Permalink = styled('a')` + width: 100%; :hover ${StyledIconAnchor} { display: block; color: ${p => p.theme.gray300}; diff --git a/static/app/components/events/interfaces/threadsV2/index.tsx b/static/app/components/events/interfaces/threadsV2/index.tsx index 2c5a8ffdaad404..b32f5697e5df7c 100644 --- a/static/app/components/events/interfaces/threadsV2/index.tsx +++ b/static/app/components/events/interfaces/threadsV2/index.tsx @@ -1,4 +1,5 @@ import {Fragment, useState} from 'react'; +import styled from '@emotion/styled'; import isNil from 'lodash/isNil'; import {isStacktraceNewestFirst} from 'app/components/events/interfaces/stacktrace'; @@ -178,7 +179,7 @@ function Threads({ ); } - return t('Stack Trace'); + return {t('Stack Trace')}; } return ( @@ -205,3 +206,7 @@ function Threads({ } export default Threads; + +const Title = styled('h3')` + margin-bottom: 0; +`; diff --git a/static/app/components/events/traceEventDataSection/index.tsx b/static/app/components/events/traceEventDataSection/index.tsx index fdf50035550d12..2c00743b4b5280 100644 --- a/static/app/components/events/traceEventDataSection/index.tsx +++ b/static/app/components/events/traceEventDataSection/index.tsx @@ -95,13 +95,11 @@ function TraceEventDataSection({ onChange={() => setState({...state, raw: !raw})} /> {raw ? ( - + isNativePlatform(platform) && ( + + ) ) : ( p.theme.breakpoints[0]}) { From a70da97b007691b43c118a4e0b49e07c301f5edb Mon Sep 17 00:00:00 2001 From: Priscila Oliveira Date: Mon, 25 Oct 2021 16:00:37 +0200 Subject: [PATCH 15/15] fix lint issue --- static/app/components/events/interfaces/threadsV2/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/app/components/events/interfaces/threadsV2/index.tsx b/static/app/components/events/interfaces/threadsV2/index.tsx index b32f5697e5df7c..f7e7a45de6fa09 100644 --- a/static/app/components/events/interfaces/threadsV2/index.tsx +++ b/static/app/components/events/interfaces/threadsV2/index.tsx @@ -15,7 +15,7 @@ import {defined} from 'app/utils'; import TraceEventDataSection from '../../traceEventDataSection'; import {DisplayOption} from '../../traceEventDataSection/displayOptions'; import Exception from '../crashContent/exception'; -import StackTrace from '../crashContent/stacktrace'; +import StackTrace from '../crashContent/stackTrace'; import NoStackTraceMessage from '../noStackTraceMessage'; import ThreadSelector from '../threads/threadSelector'; import findBestThread from '../threads/threadSelector/findBestThread';