From 00002321d12bc6eb62bd0cc335929ded85844515 Mon Sep 17 00:00:00 2001 From: Lyn Nagara Date: Tue, 11 Jun 2019 18:22:42 -0700 Subject: [PATCH 1/2] feat(events-v2): Add filtering to heatmaps Filters heatmaps by project, environment, time and query --- .../app/views/organizationEventsV2/data.jsx | 2 ++ .../app/views/organizationEventsV2/events.jsx | 5 +++-- .../app/views/organizationEventsV2/tags.jsx | 22 ++++++++++--------- .../app/views/organizationEventsV2/utils.jsx | 7 ++++-- .../views/organizationEventsV2/tags.spec.jsx | 2 +- 5 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/sentry/static/sentry/app/views/organizationEventsV2/data.jsx b/src/sentry/static/sentry/app/views/organizationEventsV2/data.jsx index 543c809d70dbac..bc961d0982ac5e 100644 --- a/src/sentry/static/sentry/app/views/organizationEventsV2/data.jsx +++ b/src/sentry/static/sentry/app/views/organizationEventsV2/data.jsx @@ -12,6 +12,8 @@ import DateTime from 'app/components/dateTime'; import {QueryLink} from './styles'; +export const MODAL_QUERY_KEYS = ['eventSlug', 'groupSlug']; + export const ALL_VIEWS = deepFreeze([ { id: 'all', diff --git a/src/sentry/static/sentry/app/views/organizationEventsV2/events.jsx b/src/sentry/static/sentry/app/views/organizationEventsV2/events.jsx index 9a6087d8d649b6..5afd8fa4cf5154 100644 --- a/src/sentry/static/sentry/app/views/organizationEventsV2/events.jsx +++ b/src/sentry/static/sentry/app/views/organizationEventsV2/events.jsx @@ -16,6 +16,7 @@ import {getParams} from 'app/views/organizationEvents/utils/getParams'; import Table from './table'; import Tags from './tags'; import {getQuery} from './utils'; +import {MODAL_QUERY_KEYS} from './data'; const CHART_AXIS_OPTIONS = [ {label: 'Count', value: 'event_count'}, @@ -35,8 +36,8 @@ export default class Events extends AsyncComponent { componentDidUpdate(prevProps, prevContext) { // Do not update if we are just opening/closing the modal const locationHasChanged = !isEqual( - omit(prevProps.location.query, 'eventSlug'), - omit(this.props.location.query, 'eventSlug') + omit(prevProps.location.query, MODAL_QUERY_KEYS), + omit(this.props.location.query, MODAL_QUERY_KEYS) ); if (locationHasChanged) { diff --git a/src/sentry/static/sentry/app/views/organizationEventsV2/tags.jsx b/src/sentry/static/sentry/app/views/organizationEventsV2/tags.jsx index 1f295a8c39a8e4..3e42b57160d8ea 100644 --- a/src/sentry/static/sentry/app/views/organizationEventsV2/tags.jsx +++ b/src/sentry/static/sentry/app/views/organizationEventsV2/tags.jsx @@ -1,20 +1,19 @@ import React from 'react'; import PropTypes from 'prop-types'; import styled from 'react-emotion'; -import {isEqual} from 'lodash'; +import {isEqual, omit} from 'lodash'; import SentryTypes from 'app/sentryTypes'; import TagDistributionMeter from 'app/components/tagDistributionMeter'; import withApi from 'app/utils/withApi'; -import withGlobalSelection from 'app/utils/withGlobalSelection'; import {fetchTags, getEventTagSearchUrl} from './utils'; +import {MODAL_QUERY_KEYS} from './data'; class Tags extends React.Component { static propTypes = { api: PropTypes.object.isRequired, organization: SentryTypes.Organization.isRequired, view: SentryTypes.EventView.isRequired, - selection: SentryTypes.GlobalSelection.isRequired, location: PropTypes.object.isRequired, }; @@ -28,19 +27,22 @@ class Tags extends React.Component { } componentDidUpdate(prevProps) { - if ( - this.props.view.id !== prevProps.view.id || - !isEqual(this.props.selection, prevProps.selection) - ) { + // Do not update if we are just opening/closing the modal + const locationHasChanged = !isEqual( + omit(prevProps.location.query, MODAL_QUERY_KEYS), + omit(this.props.location.query, MODAL_QUERY_KEYS) + ); + + if (this.props.view.id !== prevProps.view.id || locationHasChanged) { this.fetchData(); } } fetchData = async () => { - const {api, organization, view} = this.props; + const {api, organization, view, location} = this.props; try { - const tags = await fetchTags(api, organization.slug, view.tags); + const tags = await fetchTags(api, organization.slug, view.tags, location.query); this.setState({tags, isLoading: false}); } catch (err) { this.setState({tags: {}, isLoading: false}); @@ -87,4 +89,4 @@ const Placeholder = styled('div')` `; export {Tags}; -export default withApi(withGlobalSelection(Tags)); +export default withApi(Tags); diff --git a/src/sentry/static/sentry/app/views/organizationEventsV2/utils.jsx b/src/sentry/static/sentry/app/views/organizationEventsV2/utils.jsx index ead6c4f1aee9fa..7f813b50a1f683 100644 --- a/src/sentry/static/sentry/app/views/organizationEventsV2/utils.jsx +++ b/src/sentry/static/sentry/app/views/organizationEventsV2/utils.jsx @@ -1,6 +1,7 @@ import {pick} from 'lodash'; import {DEFAULT_PER_PAGE} from 'app/constants'; +import {URL_PARAM} from 'app/components/organizations/globalSelectionHeader/constants'; import {ALL_VIEWS, SPECIAL_FIELDS} from './data'; /** @@ -91,10 +92,12 @@ export function getEventTagSearchUrl(tagKey, tagValue, location) { * @param {Array} tagList * @returns {Promise} */ -export function fetchTags(api, orgSlug, tagList) { +export function fetchTags(api, orgSlug, tagList, query) { + const urlParams = pick(query, Object.values(URL_PARAM)); + return api .requestPromise(`/organizations/${orgSlug}/events-heatmap/`, { - query: {keys: tagList}, + query: {...urlParams, keys: tagList, query: query.query}, }) .then(resp => { const tags = {}; diff --git a/tests/js/spec/views/organizationEventsV2/tags.spec.jsx b/tests/js/spec/views/organizationEventsV2/tags.spec.jsx index f8d67666d1657e..017e1ece5e3c22 100644 --- a/tests/js/spec/views/organizationEventsV2/tags.spec.jsx +++ b/tests/js/spec/views/organizationEventsV2/tags.spec.jsx @@ -44,7 +44,7 @@ describe('Tags', function() { api={api} organization={org} selection={{projects: [], environments: [], datetime: {}}} - location={{}} + location={{query: {}}} /> ); From 0643577aae4b52d88405381d6f7bb68c6c7a0598 Mon Sep 17 00:00:00 2001 From: Lyn Nagara Date: Wed, 12 Jun 2019 09:51:30 -0700 Subject: [PATCH 2/2] update constants path --- .../components/organizations/globalSelectionHeader/index.jsx | 5 +---- .../components/organizations/globalSelectionHeader/utils.jsx | 2 +- .../constants.jsx => constants/globalSelectionHeader.jsx} | 0 src/sentry/static/sentry/app/stores/globalSelectionStore.jsx | 2 +- .../static/sentry/app/views/organizationEventsV2/utils.jsx | 2 +- .../sentry/app/views/organizationReleases/detail/index.jsx | 2 +- .../views/organizationReleases/detail/releaseArtifacts.jsx | 2 +- .../app/views/organizationReleases/detail/releaseCommits.jsx | 2 +- .../sentry/app/views/organizationReleases/list/utils.jsx | 2 +- src/sentry/static/sentry/app/views/userFeedback/utils.jsx | 2 +- 10 files changed, 9 insertions(+), 12 deletions(-) rename src/sentry/static/sentry/app/{components/organizations/globalSelectionHeader/constants.jsx => constants/globalSelectionHeader.jsx} (100%) diff --git a/src/sentry/static/sentry/app/components/organizations/globalSelectionHeader/index.jsx b/src/sentry/static/sentry/app/components/organizations/globalSelectionHeader/index.jsx index bfb4fb6704a722..1707ae82cf11cb 100644 --- a/src/sentry/static/sentry/app/components/organizations/globalSelectionHeader/index.jsx +++ b/src/sentry/static/sentry/app/components/organizations/globalSelectionHeader/index.jsx @@ -4,10 +4,7 @@ import PropTypes from 'prop-types'; import React from 'react'; import styled from 'react-emotion'; -import { - DATE_TIME_KEYS, - URL_PARAM, -} from 'app/components/organizations/globalSelectionHeader/constants'; +import {DATE_TIME_KEYS, URL_PARAM} from 'app/constants/globalSelectionHeader'; import {DEFAULT_STATS_PERIOD} from 'app/constants'; import {callIfFunction} from 'app/utils/callIfFunction'; import {isEqualWithDates} from 'app/utils/isEqualWithDates'; diff --git a/src/sentry/static/sentry/app/components/organizations/globalSelectionHeader/utils.jsx b/src/sentry/static/sentry/app/components/organizations/globalSelectionHeader/utils.jsx index af56e7ee002afa..afc48039fa0a9b 100644 --- a/src/sentry/static/sentry/app/components/organizations/globalSelectionHeader/utils.jsx +++ b/src/sentry/static/sentry/app/components/organizations/globalSelectionHeader/utils.jsx @@ -3,7 +3,7 @@ import {pick, pickBy, identity} from 'lodash'; import {defined} from 'app/utils'; import {getUtcToLocalDateObject} from 'app/utils/dates'; -import {URL_PARAM} from './constants'; +import {URL_PARAM} from 'app/constants/globalSelectionHeader'; // Parses URL query parameters for values relevant to global selection header export function getStateFromQuery(query) { diff --git a/src/sentry/static/sentry/app/components/organizations/globalSelectionHeader/constants.jsx b/src/sentry/static/sentry/app/constants/globalSelectionHeader.jsx similarity index 100% rename from src/sentry/static/sentry/app/components/organizations/globalSelectionHeader/constants.jsx rename to src/sentry/static/sentry/app/constants/globalSelectionHeader.jsx diff --git a/src/sentry/static/sentry/app/stores/globalSelectionStore.jsx b/src/sentry/static/sentry/app/stores/globalSelectionStore.jsx index b12e64d3b92304..a58585388baa68 100644 --- a/src/sentry/static/sentry/app/stores/globalSelectionStore.jsx +++ b/src/sentry/static/sentry/app/stores/globalSelectionStore.jsx @@ -5,7 +5,7 @@ import { DATE_TIME, URL_PARAM, LOCAL_STORAGE_KEY, -} from 'app/components/organizations/globalSelectionHeader/constants'; +} from 'app/constants/globalSelectionHeader'; import {getStateFromQuery} from 'app/components/organizations/globalSelectionHeader/utils'; import {isEqualWithDates} from 'app/utils/isEqualWithDates'; import OrganizationsStore from 'app/stores/organizationsStore'; diff --git a/src/sentry/static/sentry/app/views/organizationEventsV2/utils.jsx b/src/sentry/static/sentry/app/views/organizationEventsV2/utils.jsx index 7f813b50a1f683..015755f36ea974 100644 --- a/src/sentry/static/sentry/app/views/organizationEventsV2/utils.jsx +++ b/src/sentry/static/sentry/app/views/organizationEventsV2/utils.jsx @@ -1,7 +1,7 @@ import {pick} from 'lodash'; import {DEFAULT_PER_PAGE} from 'app/constants'; -import {URL_PARAM} from 'app/components/organizations/globalSelectionHeader/constants'; +import {URL_PARAM} from 'app/constants/globalSelectionHeader'; import {ALL_VIEWS, SPECIAL_FIELDS} from './data'; /** diff --git a/src/sentry/static/sentry/app/views/organizationReleases/detail/index.jsx b/src/sentry/static/sentry/app/views/organizationReleases/detail/index.jsx index 2dbabf866ef603..9a611c15921108 100644 --- a/src/sentry/static/sentry/app/views/organizationReleases/detail/index.jsx +++ b/src/sentry/static/sentry/app/views/organizationReleases/detail/index.jsx @@ -6,7 +6,7 @@ import SentryTypes from 'app/sentryTypes'; import LoadingError from 'app/components/loadingError'; import LoadingIndicator from 'app/components/loadingIndicator'; import GlobalSelectionHeader from 'app/components/organizations/globalSelectionHeader'; -import {URL_PARAM} from 'app/components/organizations/globalSelectionHeader/constants'; +import {URL_PARAM} from 'app/constants/globalSelectionHeader'; import withOrganization from 'app/utils/withOrganization'; import AsyncView from 'app/views/asyncView'; import {PageContent} from 'app/styles/organization'; diff --git a/src/sentry/static/sentry/app/views/organizationReleases/detail/releaseArtifacts.jsx b/src/sentry/static/sentry/app/views/organizationReleases/detail/releaseArtifacts.jsx index 6eb764b723594c..474ecefe3c9dd9 100644 --- a/src/sentry/static/sentry/app/views/organizationReleases/detail/releaseArtifacts.jsx +++ b/src/sentry/static/sentry/app/views/organizationReleases/detail/releaseArtifacts.jsx @@ -4,7 +4,7 @@ import PropTypes from 'prop-types'; import React from 'react'; import {Panel, PanelHeader, PanelBody, PanelItem} from 'app/components/panels'; -import {URL_PARAM} from 'app/components/organizations/globalSelectionHeader/constants'; +import {URL_PARAM} from 'app/constants/globalSelectionHeader'; import {t} from 'app/locale'; import EmptyStateWarning from 'app/components/emptyStateWarning'; import FileSize from 'app/components/fileSize'; diff --git a/src/sentry/static/sentry/app/views/organizationReleases/detail/releaseCommits.jsx b/src/sentry/static/sentry/app/views/organizationReleases/detail/releaseCommits.jsx index 583aa36043581e..e1f219e812d688 100644 --- a/src/sentry/static/sentry/app/views/organizationReleases/detail/releaseCommits.jsx +++ b/src/sentry/static/sentry/app/views/organizationReleases/detail/releaseCommits.jsx @@ -4,7 +4,7 @@ import React from 'react'; import createReactClass from 'create-react-class'; import {Panel, PanelHeader, PanelBody} from 'app/components/panels'; -import {URL_PARAM} from 'app/components/organizations/globalSelectionHeader/constants'; +import {URL_PARAM} from 'app/constants/globalSelectionHeader'; import {t} from 'app/locale'; import withApi from 'app/utils/withApi'; import CommitRow from 'app/components/commitRow'; diff --git a/src/sentry/static/sentry/app/views/organizationReleases/list/utils.jsx b/src/sentry/static/sentry/app/views/organizationReleases/list/utils.jsx index 6cab310e98283f..fecd1829a9b6fa 100644 --- a/src/sentry/static/sentry/app/views/organizationReleases/list/utils.jsx +++ b/src/sentry/static/sentry/app/views/organizationReleases/list/utils.jsx @@ -1,5 +1,5 @@ import {pick} from 'lodash'; -import {URL_PARAM} from 'app/components/organizations/globalSelectionHeader/constants'; +import {URL_PARAM} from 'app/constants/globalSelectionHeader'; /** * Get query term for API given location.query diff --git a/src/sentry/static/sentry/app/views/userFeedback/utils.jsx b/src/sentry/static/sentry/app/views/userFeedback/utils.jsx index 4a25b70bc2ed01..22e023cff0a7b1 100644 --- a/src/sentry/static/sentry/app/views/userFeedback/utils.jsx +++ b/src/sentry/static/sentry/app/views/userFeedback/utils.jsx @@ -1,7 +1,7 @@ import {pick} from 'lodash'; import qs from 'query-string'; -import {URL_PARAM} from 'app/components/organizations/globalSelectionHeader/constants'; +import {URL_PARAM} from 'app/constants/globalSelectionHeader'; const DEFAULT_STATUS = 'unresolved';