Skip to content

Commit

Permalink
feat(discover): added add to discover button to saved discover queries (
Browse files Browse the repository at this point in the history
#28158)

Added Add to Discover Button to Discover landing page in prebuilt/saved queries context menu
  • Loading branch information
edwardgou-sentry authored and shruthilayaj committed Sep 7, 2021
1 parent 7024348 commit 322f4df
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 3 deletions.
25 changes: 22 additions & 3 deletions static/app/components/modals/addDashboardWidgetModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,14 @@ import SelectControl from 'app/components/forms/selectControl';
import {PanelAlert} from 'app/components/panels';
import {t} from 'app/locale';
import space from 'app/styles/space';
import {GlobalSelection, Organization, SelectValue, TagCollection} from 'app/types';
import {
DateString,
GlobalSelection,
Organization,
RelativePeriod,
SelectValue,
TagCollection,
} from 'app/types';
import Measurements from 'app/utils/measurements/measurements';
import withApi from 'app/utils/withApi';
import withGlobalSelection from 'app/utils/withGlobalSelection';
Expand Down Expand Up @@ -49,6 +56,9 @@ export type DashboardWidgetModalOptions = {
defaultQuery?: string;
defaultTitle?: string;
fromDiscover?: boolean;
start?: DateString;
end?: DateString;
statsPeriod?: RelativePeriod | string;
};

type Props = ModalRenderProps &
Expand Down Expand Up @@ -340,10 +350,19 @@ class AddDashboardWidgetModal extends React.Component<Props, State> {
fromDiscover,
onUpdateWidget,
widget: previousWidget,
start,
end,
statsPeriod,
} = this.props;
const state = this.state;
const errors = state.errors;

// Construct GlobalSelection object using statsPeriod/start/end props so we can render widget graph using saved timeframe from Saved/Prebuilt Query
const querySelection: GlobalSelection = statsPeriod
? {...selection, datetime: {start: null, end: null, period: statsPeriod, utc: null}}
: start && end
? {...selection, datetime: {start, end, period: '', utc: null}}
: selection;
const fieldOptions = (measurementKeys: string[]) =>
generateFieldOptions({
organization,
Expand Down Expand Up @@ -417,7 +436,7 @@ class AddDashboardWidgetModal extends React.Component<Props, State> {
return (
<WidgetQueriesForm
organization={organization}
selection={selection}
selection={querySelection}
fieldOptions={amendedFieldOptions}
displayType={state.displayType}
queries={state.queries}
Expand All @@ -435,7 +454,7 @@ class AddDashboardWidgetModal extends React.Component<Props, State> {
<WidgetCard
api={api}
organization={organization}
selection={selection}
selection={querySelection}
widget={this.state}
isEditing={false}
onDelete={() => undefined}
Expand Down
55 changes: 55 additions & 0 deletions static/app/views/eventsV2/queryList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import {Location, Query} from 'history';
import moment from 'moment';

import {resetGlobalSelection} from 'app/actionCreators/globalSelection';
import {openAddDashboardWidgetModal} from 'app/actionCreators/modal';
import {Client} from 'app/api';
import Feature from 'app/components/acl/feature';
import DropdownMenu from 'app/components/dropdownMenu';
import EmptyStateWarning from 'app/components/emptyStateWarning';
import MenuItem from 'app/components/menuItem';
Expand Down Expand Up @@ -83,6 +85,23 @@ class QueryList extends React.Component<Props> {
});
};

handleAddQueryToDashboard =
(eventView: EventView, savedQuery?: SavedQuery) =>
(event: React.MouseEvent<Element>) => {
const {organization} = this.props;
event.preventDefault();
event.stopPropagation();
openAddDashboardWidgetModal({
organization,
defaultQuery: eventView.query,
start: eventView.start,
end: eventView.end,
statsPeriod: eventView.statsPeriod,
fromDiscover: true,
defaultTitle: savedQuery?.name ?? eventView.name,
});
};

renderQueries() {
const {pageLinks, renderPrebuilt} = this.props;
const links = parseLinkHeader(pageLinks || '');
Expand Down Expand Up @@ -158,6 +177,27 @@ class QueryList extends React.Component<Props> {
query_name: eventView.name,
});
}}
renderContextMenu={() => (
<Feature
organization={organization}
features={['connect-discover-and-dashboards', 'dashboards-edit']}
>
{({hasFeature}) => {
return (
hasFeature && (
<ContextMenu>
<MenuItem
data-test-id="add-query-to-dashboard"
onClick={this.handleAddQueryToDashboard(eventView)}
>
{t('Add to Dashboard')}
</MenuItem>
</ContextMenu>
)
);
}}
</Feature>
)}
/>
);
});
Expand Down Expand Up @@ -208,6 +248,21 @@ class QueryList extends React.Component<Props> {
)}
renderContextMenu={() => (
<ContextMenu>
<Feature
organization={organization}
features={['connect-discover-and-dashboards', 'dashboards-edit']}
>
{({hasFeature}) =>
hasFeature && (
<MenuItem
data-test-id="add-query-to-dashboard"
onClick={this.handleAddQueryToDashboard(eventView, savedQuery)}
>
{t('Add to Dashboard')}
</MenuItem>
)
}
</Feature>
<MenuItem
data-test-id="delete-query"
onClick={this.handleDeleteQuery(eventView)}
Expand Down
46 changes: 46 additions & 0 deletions tests/js/spec/views/eventsV2/queryList.spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -194,4 +194,50 @@ describe('EventsV2 > QueryList', function () {
query: {cursor: undefined, statsPeriod: '14d'},
});
});

it('renders Add to Dashboard in context menu with feature flag', async function () {
const featuredOrganization = TestStubs.Organization({
features: ['connect-discover-and-dashboards', 'dashboards-edit'],
});
const wrapper = mountWithTheme(
<QueryList
organization={featuredOrganization}
savedQueries={savedQueries.slice(1)}
pageLinks=""
onQueryChange={queryChangeMock}
location={location}
/>,
TestStubs.routerContext()
);
const card = wrapper.find('QueryCard').last();
openContextMenu(card);
wrapper.update();

const menuItems = wrapper.find('MenuItem');
expect(menuItems.length).toEqual(3);
expect(menuItems.at(0).find('span').children().html()).toEqual('Add to Dashboard');
expect(menuItems.at(1).find('span').children().html()).toEqual('Delete Query');
expect(menuItems.at(2).find('span').children().html()).toEqual('Duplicate Query');
});

it('only renders Delete Query and Duplicate Query in context menu', async function () {
const wrapper = mountWithTheme(
<QueryList
organization={organization}
savedQueries={savedQueries.slice(1)}
pageLinks=""
onQueryChange={queryChangeMock}
location={location}
/>,
TestStubs.routerContext()
);
const card = wrapper.find('QueryCard').last();
openContextMenu(card);
wrapper.update();

const menuItems = wrapper.find('MenuItem');
expect(menuItems.length).toEqual(2);
expect(menuItems.at(0).find('span').children().html()).toEqual('Delete Query');
expect(menuItems.at(1).find('span').children().html()).toEqual('Duplicate Query');
});
});

0 comments on commit 322f4df

Please sign in to comment.