|
@@ -9,8 +9,8 @@ import {
|
|
import {browserHistory, RouteComponentProps} from 'react-router';
|
|
import {browserHistory, RouteComponentProps} from 'react-router';
|
|
import styled from '@emotion/styled';
|
|
import styled from '@emotion/styled';
|
|
import * as Sentry from '@sentry/react';
|
|
import * as Sentry from '@sentry/react';
|
|
-import isEmpty from 'lodash/isEmpty';
|
|
|
|
|
|
|
|
|
|
+import {fetchOrganizationEnvironments} from 'sentry/actionCreators/environments';
|
|
import LoadingError from 'sentry/components/loadingError';
|
|
import LoadingError from 'sentry/components/loadingError';
|
|
import LoadingIndicator from 'sentry/components/loadingIndicator';
|
|
import LoadingIndicator from 'sentry/components/loadingIndicator';
|
|
import PageFiltersContainer from 'sentry/components/organizations/pageFilters/container';
|
|
import PageFiltersContainer from 'sentry/components/organizations/pageFilters/container';
|
|
@@ -54,7 +54,6 @@ import {
|
|
getGroupReprocessingStatus,
|
|
getGroupReprocessingStatus,
|
|
markEventSeen,
|
|
markEventSeen,
|
|
ReprocessingStatus,
|
|
ReprocessingStatus,
|
|
- useEnvironmentsFromUrl,
|
|
|
|
useFetchIssueTagsForDetailsPage,
|
|
useFetchIssueTagsForDetailsPage,
|
|
} from './utils';
|
|
} from './utils';
|
|
|
|
|
|
@@ -65,6 +64,8 @@ type RouteProps = RouteComponentProps<RouterParams, {}>;
|
|
|
|
|
|
type GroupDetailsProps = {
|
|
type GroupDetailsProps = {
|
|
children: React.ReactNode;
|
|
children: React.ReactNode;
|
|
|
|
+ environments: string[];
|
|
|
|
+ isGlobalSelectionReady: boolean;
|
|
organization: Organization;
|
|
organization: Organization;
|
|
projects: Project[];
|
|
projects: Project[];
|
|
};
|
|
};
|
|
@@ -88,9 +89,12 @@ interface GroupDetailsContentProps extends GroupDetailsProps, FetchGroupDetailsS
|
|
project: Project;
|
|
project: Project;
|
|
}
|
|
}
|
|
|
|
|
|
-function getGroupQuery({environments}: {environments: string[]}) {
|
|
|
|
|
|
+function getGroupQuery({
|
|
|
|
+ environments,
|
|
|
|
+}: Pick<GroupDetailsProps, 'environments'>): Record<string, string | string[]> {
|
|
|
|
+ // Note, we do not want to include the environment key at all if there are no environments
|
|
const query: Record<string, string | string[]> = {
|
|
const query: Record<string, string | string[]> = {
|
|
- ...(!isEmpty(environments) ? {environment: environments} : {}),
|
|
|
|
|
|
+ ...(environments ? {environment: environments} : {}),
|
|
expand: ['inbox', 'owners'],
|
|
expand: ['inbox', 'owners'],
|
|
collapse: ['release', 'tags'],
|
|
collapse: ['release', 'tags'],
|
|
};
|
|
};
|
|
@@ -98,12 +102,6 @@ function getGroupQuery({environments}: {environments: string[]}) {
|
|
return query;
|
|
return query;
|
|
}
|
|
}
|
|
|
|
|
|
-function getEventQuery({environments}: {environments: string[]}) {
|
|
|
|
- const query = !isEmpty(environments) ? {environment: environments} : {};
|
|
|
|
-
|
|
|
|
- return query;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
function getFetchDataRequestErrorType(status?: number | null): Error {
|
|
function getFetchDataRequestErrorType(status?: number | null): Error {
|
|
if (!status) {
|
|
if (!status) {
|
|
return null;
|
|
return null;
|
|
@@ -243,8 +241,14 @@ function useRefetchGroupForReprocessing({
|
|
}
|
|
}
|
|
|
|
|
|
function useFetchOnMount({fetchData}: Pick<FetchGroupDetailsState, 'fetchData'>) {
|
|
function useFetchOnMount({fetchData}: Pick<FetchGroupDetailsState, 'fetchData'>) {
|
|
|
|
+ const api = useApi();
|
|
|
|
+ const organization = useOrganization();
|
|
|
|
+
|
|
useEffect(() => {
|
|
useEffect(() => {
|
|
fetchData();
|
|
fetchData();
|
|
|
|
+
|
|
|
|
+ // Fetch environments early - used in GroupEventDetailsContainer
|
|
|
|
+ fetchOrganizationEnvironments(api, organization.slug);
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, []);
|
|
}, []);
|
|
}
|
|
}
|
|
@@ -269,7 +273,13 @@ function useEventApiQuery(
|
|
return isLatest ? latestEventQuery : otherEventQuery;
|
|
return isLatest ? latestEventQuery : otherEventQuery;
|
|
}
|
|
}
|
|
|
|
|
|
-function useFetchGroupDetails(): FetchGroupDetailsState {
|
|
|
|
|
|
+function useFetchGroupDetails({
|
|
|
|
+ isGlobalSelectionReady,
|
|
|
|
+ environments,
|
|
|
|
+}: Pick<
|
|
|
|
+ GroupDetailsProps,
|
|
|
|
+ 'isGlobalSelectionReady' | 'environments'
|
|
|
|
+>): FetchGroupDetailsState {
|
|
const api = useApi();
|
|
const api = useApi();
|
|
const organization = useOrganization();
|
|
const organization = useOrganization();
|
|
const router = useRouter();
|
|
const router = useRouter();
|
|
@@ -285,8 +295,6 @@ function useFetchGroupDetails(): FetchGroupDetailsState {
|
|
const [errorType, setErrorType] = useState<Error | null>(null);
|
|
const [errorType, setErrorType] = useState<Error | null>(null);
|
|
const [event, setEvent] = useState<Event | null>(null);
|
|
const [event, setEvent] = useState<Event | null>(null);
|
|
|
|
|
|
- const environments = useEnvironmentsFromUrl();
|
|
|
|
-
|
|
|
|
const groupId = params.groupId;
|
|
const groupId = params.groupId;
|
|
const eventId = params.eventId ?? 'latest';
|
|
const eventId = params.eventId ?? 'latest';
|
|
|
|
|
|
@@ -302,7 +310,7 @@ function useFetchGroupDetails(): FetchGroupDetailsState {
|
|
isLoading: loadingEvent,
|
|
isLoading: loadingEvent,
|
|
isError,
|
|
isError,
|
|
refetch: refetchEvent,
|
|
refetch: refetchEvent,
|
|
- } = useEventApiQuery(eventId, [eventUrl, {query: getEventQuery({environments})}]);
|
|
|
|
|
|
+ } = useEventApiQuery(eventId, [eventUrl, {query: eventQuery}]);
|
|
|
|
|
|
useEffect(() => {
|
|
useEffect(() => {
|
|
if (eventData) {
|
|
if (eventData) {
|
|
@@ -327,6 +335,10 @@ function useFetchGroupDetails(): FetchGroupDetailsState {
|
|
|
|
|
|
const fetchData = useCallback(async () => {
|
|
const fetchData = useCallback(async () => {
|
|
// Need to wait for global selection store to be ready before making request
|
|
// Need to wait for global selection store to be ready before making request
|
|
|
|
+ if (!isGlobalSelectionReady) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
try {
|
|
try {
|
|
const groupResponse = await api.requestPromise(`/issues/${params.groupId}/`, {
|
|
const groupResponse = await api.requestPromise(`/issues/${params.groupId}/`, {
|
|
query: getGroupQuery({environments}),
|
|
query: getGroupQuery({environments}),
|
|
@@ -393,6 +405,7 @@ function useFetchGroupDetails(): FetchGroupDetailsState {
|
|
environments,
|
|
environments,
|
|
fetchGroupReleases,
|
|
fetchGroupReleases,
|
|
handleError,
|
|
handleError,
|
|
|
|
+ isGlobalSelectionReady,
|
|
location,
|
|
location,
|
|
organization,
|
|
organization,
|
|
params,
|
|
params,
|
|
@@ -606,6 +619,7 @@ function GroupDetailsContentError({
|
|
}
|
|
}
|
|
|
|
|
|
function GroupDetailsContent({
|
|
function GroupDetailsContent({
|
|
|
|
+ environments,
|
|
children,
|
|
children,
|
|
group,
|
|
group,
|
|
project,
|
|
project,
|
|
@@ -620,8 +634,6 @@ function GroupDetailsContent({
|
|
const {currentTab, baseUrl} = getCurrentRouteInfo({group, event, router, organization});
|
|
const {currentTab, baseUrl} = getCurrentRouteInfo({group, event, router, organization});
|
|
const groupReprocessingStatus = getGroupReprocessingStatus(group);
|
|
const groupReprocessingStatus = getGroupReprocessingStatus(group);
|
|
|
|
|
|
- const environments = useEnvironmentsFromUrl();
|
|
|
|
-
|
|
|
|
useEffect(() => {
|
|
useEffect(() => {
|
|
if (
|
|
if (
|
|
currentTab === Tab.DETAILS &&
|
|
currentTab === Tab.DETAILS &&
|
|
@@ -705,25 +717,28 @@ function GroupDetails(props: GroupDetailsProps) {
|
|
const location = useLocation();
|
|
const location = useLocation();
|
|
const router = useRouter();
|
|
const router = useRouter();
|
|
|
|
|
|
- const {fetchData, project, group, ...fetchGroupDetailsProps} = useFetchGroupDetails();
|
|
|
|
|
|
+ const {fetchData, project, group, ...fetchGroupDetailsProps} =
|
|
|
|
+ useFetchGroupDetails(props);
|
|
|
|
|
|
const previousPathname = usePrevious(location.pathname);
|
|
const previousPathname = usePrevious(location.pathname);
|
|
const previousEventId = usePrevious(router.params.eventId);
|
|
const previousEventId = usePrevious(router.params.eventId);
|
|
-
|
|
|
|
- const environments = useEnvironmentsFromUrl();
|
|
|
|
|
|
+ const previousIsGlobalSelectionReady = usePrevious(props.isGlobalSelectionReady);
|
|
|
|
|
|
const {data} = useFetchIssueTagsForDetailsPage(
|
|
const {data} = useFetchIssueTagsForDetailsPage(
|
|
{
|
|
{
|
|
groupId: router.params.groupId,
|
|
groupId: router.params.groupId,
|
|
- environment: environments,
|
|
|
|
|
|
+ environment: props.environments,
|
|
},
|
|
},
|
|
// Don't want this query to take precedence over the main requests
|
|
// Don't want this query to take precedence over the main requests
|
|
- {enabled: defined(group)}
|
|
|
|
|
|
+ {enabled: props.isGlobalSelectionReady && defined(group)}
|
|
);
|
|
);
|
|
const isSampleError = data?.some(tag => tag.key === 'sample_event') ?? false;
|
|
const isSampleError = data?.some(tag => tag.key === 'sample_event') ?? false;
|
|
|
|
|
|
useEffect(() => {
|
|
useEffect(() => {
|
|
- if (location.pathname !== previousPathname) {
|
|
|
|
|
|
+ const globalSelectionReadyChanged =
|
|
|
|
+ previousIsGlobalSelectionReady !== props.isGlobalSelectionReady;
|
|
|
|
+
|
|
|
|
+ if (globalSelectionReadyChanged || location.pathname !== previousPathname) {
|
|
fetchData();
|
|
fetchData();
|
|
}
|
|
}
|
|
}, [
|
|
}, [
|
|
@@ -731,7 +746,9 @@ function GroupDetails(props: GroupDetailsProps) {
|
|
group,
|
|
group,
|
|
location.pathname,
|
|
location.pathname,
|
|
previousEventId,
|
|
previousEventId,
|
|
|
|
+ previousIsGlobalSelectionReady,
|
|
previousPathname,
|
|
previousPathname,
|
|
|
|
+ props.isGlobalSelectionReady,
|
|
router.params.eventId,
|
|
router.params.eventId,
|
|
]);
|
|
]);
|
|
|
|
|