import type {InjectedRouter} from 'react-router'; import type {Location} from 'history'; import type {Client} from 'sentry/api'; import DeprecatedAsyncComponent from 'sentry/components/deprecatedAsyncComponent'; import PageFiltersContainer from 'sentry/components/organizations/pageFilters/container'; import { getDatetimeFromState, normalizeDateTimeString, } from 'sentry/components/organizations/pageFilters/parse'; import {getPageFilterStorage} from 'sentry/components/organizations/pageFilters/persistence'; import type {Organization, PageFilters, SavedQuery} from 'sentry/types'; import {browserHistory} from 'sentry/utils/browserHistory'; import EventView from 'sentry/utils/discover/eventView'; import withApi from 'sentry/utils/withApi'; import withOrganization from 'sentry/utils/withOrganization'; import withPageFilters from 'sentry/utils/withPageFilters'; import {getSavedQueryWithDataset} from 'sentry/views/discover/savedQuery/utils'; import {Results} from './results'; type Props = { api: Client; loading: boolean; location: Location; organization: Organization; router: InjectedRouter; selection: PageFilters; setSavedQuery: (savedQuery: SavedQuery) => void; }; type HomepageQueryState = DeprecatedAsyncComponent['state'] & { savedQuery?: SavedQuery | null; starfishResult?: null; }; class HomepageQueryAPI extends DeprecatedAsyncComponent { shouldReload = true; componentDidUpdate(_, prevState) { const hasFetchedSavedQuery = !prevState.savedQuery && this.state.savedQuery; const hasInitiallyLoaded = prevState.loading && !this.state.loading; const sidebarClicked = this.state.savedQuery && this.props.location.search === ''; const hasValidEventViewInURL = EventView.fromLocation(this.props.location).isValid(); if ( this.state.savedQuery && ((hasInitiallyLoaded && hasFetchedSavedQuery && !hasValidEventViewInURL) || sidebarClicked) ) { const eventView = EventView.fromSavedQuery(this.state.savedQuery); const pageFilterState = getPageFilterStorage(this.props.organization.slug); let query = { ...eventView.generateQueryStringObject(), }; // Handle locked filters explicitly because we can't expect // PageFilterContainer to properly overwrite stored filters // when pushing the homepage query to the URL if (pageFilterState?.pinnedFilters) { pageFilterState.pinnedFilters.forEach(pinnedFilter => { if (pinnedFilter === 'projects') { query.project = pageFilterState.state.project?.map(String); } else if (pinnedFilter === 'datetime') { const {period, start, end, utc} = getDatetimeFromState(pageFilterState.state); query = { ...query, statsPeriod: period ?? undefined, utc: utc?.toString(), start: normalizeDateTimeString(start), end: normalizeDateTimeString(end), }; } else { query[pinnedFilter] = pageFilterState.state[pinnedFilter]; } }); } browserHistory.replace({ ...this.props.location, query: { ...query, queryDataset: this.state.savedQuery?.queryDataset, }, }); } } getEndpoints(): ReturnType { const {organization} = this.props; const endpoints: ReturnType = []; if (organization.features.includes('discover-query')) { endpoints.push([ 'savedQuery', `/organizations/${organization.slug}/discover/homepage/`, ]); } return endpoints; } onRequestSuccess({stateKey, data}) { const {organization} = this.props; // No homepage query results in a 204, returning an empty string if (stateKey === 'savedQuery' && data === '') { this.setState({savedQuery: null}); return; } if (stateKey === 'savedQuery') { this.setState({ savedQuery: organization.features.includes( 'performance-discover-dataset-selector' ) ? getSavedQueryWithDataset(data) : data, }); } } setSavedQuery = (newSavedQuery?: SavedQuery) => { const {organization} = this.props; this.setState({ savedQuery: organization.features.includes('performance-discover-dataset-selector') ? (getSavedQueryWithDataset(newSavedQuery) as SavedQuery) : newSavedQuery, }); }; renderBody(): React.ReactNode { const {savedQuery, loading} = this.state; return ( ); } } function HomepageContainer(props: Props) { return ( ); } export default withApi(withOrganization(withPageFilters(HomepageContainer)));