Skip to content

Commit

Permalink
feat(discover): discover add to dashboard button uses y axis from que…
Browse files Browse the repository at this point in the history
…ry (#29046)

Updated discover add to dashboard widget to prefill Y-Axis fields with Y-Axis and Column values from the discover query based on the visualization type.
  • Loading branch information
edwardgou-sentry authored Oct 5, 2021
1 parent d59717d commit 49b672c
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 11 deletions.
29 changes: 25 additions & 4 deletions static/app/components/modals/addDashboardWidgetModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ export type DashboardWidgetModalOptions = {
onAddWidget?: (data: Widget) => void;
widget?: Widget;
onUpdateWidget?: (nextWidget: Widget) => void;
defaultQuery?: string;
defaultWidgetQuery?: WidgetQuery;
defaultTableColumns?: readonly string[];
defaultTitle?: string;
fromDiscover?: boolean;
start?: DateString;
Expand Down Expand Up @@ -87,6 +88,7 @@ type State = {
errors?: Record<string, any>;
dashboards: DashboardListItem[];
selectedDashboard?: SelectValue<string>;
userHasModified: boolean;
};

const newQuery = {
Expand All @@ -99,17 +101,18 @@ class AddDashboardWidgetModal extends React.Component<Props, State> {
constructor(props: Props) {
super(props);

const {widget, defaultQuery, defaultTitle, fromDiscover} = props;
const {widget, defaultWidgetQuery, defaultTitle, fromDiscover} = props;

if (!widget) {
this.state = {
title: defaultTitle ?? '',
displayType: DisplayType.LINE,
interval: '5m',
queries: [{...newQuery, ...(defaultQuery ? {conditions: defaultQuery} : {})}],
queries: [defaultWidgetQuery ? {...defaultWidgetQuery} : {...newQuery}],
errors: undefined,
loading: !!fromDiscover,
dashboards: [],
userHasModified: false,
};
return;
}
Expand All @@ -122,6 +125,7 @@ class AddDashboardWidgetModal extends React.Component<Props, State> {
errors: undefined,
loading: false,
dashboards: [],
userHasModified: false,
};
}

Expand Down Expand Up @@ -230,13 +234,29 @@ class AddDashboardWidgetModal extends React.Component<Props, State> {
};

handleFieldChange = (field: string) => (value: string) => {
const {defaultWidgetQuery, defaultTableColumns} = this.props;
this.setState(prevState => {
const newState = cloneDeep(prevState);
set(newState, field, value);

if (field === 'displayType') {
const displayType = value as Widget['displayType'];
set(newState, 'queries', normalizeQueries(displayType, prevState.queries));
const normalized = normalizeQueries(displayType, prevState.queries);

// If switching to Table visualization, use saved query fields for Y-Axis if user has not made query changes
if (defaultWidgetQuery && defaultTableColumns && !prevState.userHasModified) {
if (displayType === DisplayType.TABLE) {
normalized.forEach(query => {
query.fields = [...defaultTableColumns];
});
} else {
normalized.forEach(query => {
query.fields = [...defaultWidgetQuery.fields];
});
}
}

set(newState, 'queries', normalized);
}

return {...newState, errors: undefined};
Expand All @@ -247,6 +267,7 @@ class AddDashboardWidgetModal extends React.Component<Props, State> {
this.setState(prevState => {
const newState = cloneDeep(prevState);
set(newState, `queries.${index}`, widgetQuery);
set(newState, 'userHasModified', true);

return {...newState, errors: undefined};
});
Expand Down
16 changes: 14 additions & 2 deletions static/app/views/eventsV2/queryList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import EventView from 'app/utils/discover/eventView';
import parseLinkHeader from 'app/utils/parseLinkHeader';
import {decodeList} from 'app/utils/queryString';
import withApi from 'app/utils/withApi';
import {WidgetQuery} from 'app/views/dashboardsV2/types';

import {handleCreateQuery, handleDeleteQuery} from './savedQuery/utils';
import MiniGraph from './miniGraph';
Expand Down Expand Up @@ -93,14 +94,25 @@ class QueryList extends React.Component<Props> {
const {organization} = this.props;
event.preventDefault();
event.stopPropagation();

const defaultWidgetQuery: WidgetQuery = {
name: '',
fields: savedQuery?.yAxis ?? ['count()'],
conditions: eventView.query,
orderby: '',
};

openAddDashboardWidgetModal({
organization,
defaultQuery: eventView.query,
start: eventView.start,
end: eventView.end,
statsPeriod: eventView.statsPeriod,
fromDiscover: true,
defaultTitle: savedQuery?.name ?? eventView.name,
defaultWidgetQuery,
defaultTableColumns: eventView.fields.map(({field}) => field),
defaultTitle:
savedQuery?.name ??
(eventView.name !== 'All Events' ? eventView.name : undefined),
});
};

Expand Down
18 changes: 14 additions & 4 deletions static/app/views/eventsV2/savedQuery/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import EventView from 'app/utils/discover/eventView';
import {getDiscoverLandingUrl} from 'app/utils/discover/urls';
import withApi from 'app/utils/withApi';
import withProjects from 'app/utils/withProjects';
import {WidgetQuery} from 'app/views/dashboardsV2/types';
import InputControl from 'app/views/settings/components/forms/controls/input';

import DiscoverQueryMenu from './discoverQueryMenu';
Expand Down Expand Up @@ -224,13 +225,22 @@ class SavedQueryButtonGroup extends React.PureComponent<Props, State> {
};

handleAddDashboardWidget = () => {
const {organization, eventView, savedQuery} = this.props;
const {organization, eventView, savedQuery, yAxis} = this.props;
const defaultWidgetQuery: WidgetQuery = {
name: '',
fields: yAxis ?? ['count()'],
conditions: eventView.query,
orderby: '',
};

openAddDashboardWidgetModal({
organization,
defaultQuery: eventView.query,
defaultTitle:
savedQuery?.name ?? eventView.name !== 'All Events' ? eventView.name : undefined,
fromDiscover: true,
defaultWidgetQuery,
defaultTableColumns: eventView.fields.map(({field}) => field),
defaultTitle:
savedQuery?.name ??
(eventView.name !== 'All Events' ? eventView.name : undefined),
});
};

Expand Down
34 changes: 33 additions & 1 deletion tests/js/spec/components/modals/addDashboardWidgetModal.spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,14 @@ import * as types from 'app/views/dashboardsV2/types';

const stubEl = props => <div>{props.children}</div>;

function mountModal({initialData, onAddWidget, onUpdateWidget, widget, fromDiscover}) {
function mountModal({
initialData,
onAddWidget,
onUpdateWidget,
widget,
fromDiscover,
defaultWidgetQuery,
}) {
return mountWithTheme(
<AddDashboardWidgetModal
Header={stubEl}
Expand All @@ -23,6 +30,7 @@ function mountModal({initialData, onAddWidget, onUpdateWidget, widget, fromDisco
widget={widget}
closeModal={() => void 0}
fromDiscover={fromDiscover}
defaultWidgetQuery={defaultWidgetQuery}
/>,
initialData.routerContext
);
Expand Down Expand Up @@ -865,4 +873,28 @@ describe('Modals -> AddDashboardWidgetModal', function () {

wrapper.unmount();
});

it('should use defaultWidgetQuery Y-Axis and Conditions if given a defaultWidgetQuery', async function () {
const wrapper = mountModal({
initialData,
onAddWidget: () => undefined,
onUpdateWidget: () => undefined,
widget: undefined,
fromDiscover: true,
defaultWidgetQuery: {
name: '',
fields: ['count()', 'failure_count()', 'count_unique(user)'],
conditions: 'tag:value',
orderby: '',
},
});

expect(wrapper.find('SearchBar').props().query).toEqual('tag:value');
const queryFields = wrapper.find('QueryField');
expect(queryFields.length).toEqual(3);
expect(queryFields.at(0).props().fieldValue.function[0]).toEqual('count');
expect(queryFields.at(1).props().fieldValue.function[0]).toEqual('failure_count');
expect(queryFields.at(2).props().fieldValue.function[0]).toEqual('count_unique');
wrapper.unmount();
});
});

0 comments on commit 49b672c

Please sign in to comment.