Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 42 additions & 23 deletions static/app/components/modals/addDashboardWidgetModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import {
TagCollection,
} from 'app/types';
import trackAdvancedAnalyticsEvent from 'app/utils/analytics/trackAdvancedAnalyticsEvent';
import {Aggregation} from 'app/utils/discover/fields';
import {Aggregation, parseFunction} from 'app/utils/discover/fields';
import Measurements from 'app/utils/measurements/measurements';
import withApi from 'app/utils/withApi';
import withGlobalSelection from 'app/utils/withGlobalSelection';
Expand Down Expand Up @@ -133,6 +133,7 @@ class AddDashboardWidgetModal extends React.Component<Props, State> {
componentDidMount() {
const {fromDiscover} = this.props;
if (fromDiscover) this.fetchDashboards();
this.handleDefaultFields();
}

handleSubmit = async (event: React.FormEvent) => {
Expand Down Expand Up @@ -245,33 +246,47 @@ class AddDashboardWidgetModal extends React.Component<Props, State> {
}
};

handleFieldChange = (field: string) => (value: string) => {
const {defaultWidgetQuery, defaultTableColumns, fromDiscover, organization} =
this.props;
handleDefaultFields = () => {
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'];
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];
});
}
const displayType = prevState.displayType as Widget['displayType'];
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 if (displayType === DisplayType.TOP_N) {
// Function columns not valid group bys for TOP_N display
const topNFields = [
...defaultTableColumns.filter(column => !parseFunction(column)),
...defaultWidgetQuery.fields,
];
normalized.forEach(query => {
query.fields = [...topNFields];
query.orderby = defaultWidgetQuery.orderby;
});
} else {
normalized.forEach(query => {
query.fields = [...defaultWidgetQuery.fields];
});
}

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

set(newState, 'queries', normalized);
return {...newState, errors: undefined};
});
};

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

trackAdvancedAnalyticsEvent('dashboards_views.add_widget_modal.change', {
from: fromDiscover ? 'discoverv2' : 'dashboards',
field,
Expand All @@ -281,6 +296,10 @@ class AddDashboardWidgetModal extends React.Component<Props, State> {

return {...newState, errors: undefined};
});

if (field === 'displayType') {
this.handleDefaultFields();
}
};

handleQueryChange = (widgetQuery: WidgetQuery, index: number) => {
Expand Down
2 changes: 2 additions & 0 deletions static/app/views/eventsV2/savedQuery/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,8 @@ export function displayModeToDisplayType(displayMode: DisplayModes): DisplayType
return DisplayType.BAR;
case DisplayModes.WORLDMAP:
return DisplayType.WORLD_MAP;
case DisplayModes.TOP5:
return DisplayType.TOP_N;
default:
return DisplayType.LINE;
}
Expand Down
22 changes: 22 additions & 0 deletions tests/js/spec/components/modals/addDashboardWidgetModal.spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -943,4 +943,26 @@ describe('Modals -> AddDashboardWidgetModal', function () {
expect(wrapper.find('SelectPicker').at(1).props().value.value).toEqual('bar');
wrapper.unmount();
});

it('correctly defaults fields and orderby when in Top N display', async function () {
const wrapper = mountModal({
initialData,
onAddWidget: () => undefined,
onUpdateWidget: () => undefined,
fromDiscover: true,
displayType: types.DisplayType.TOP_N,
defaultWidgetQuery: {fields: ['count_unique(user)'], orderby: '-count_unique_user'},
defaultTableColumns: ['title', 'count()', 'count_unique(user)'],
});

expect(wrapper.find('SelectPicker').at(1).props().value.value).toEqual('top_n');
expect(wrapper.find('WidgetQueriesForm').props().queries[0].fields).toEqual([
'title',
'count_unique(user)',
]);
expect(wrapper.find('WidgetQueriesForm').props().queries[0].orderby).toEqual(
'-count_unique_user'
);
wrapper.unmount();
});
});
8 changes: 5 additions & 3 deletions tests/js/spec/views/eventsV2/savedQuery/index.spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {mountWithTheme} from 'sentry-test/enzyme';
import {mountGlobalModal} from 'sentry-test/modal';

import EventView from 'app/utils/discover/eventView';
import {DisplayModes} from 'app/utils/discover/types';
import DiscoverBanner from 'app/views/eventsV2/banner';
import {ALL_VIEWS} from 'app/views/eventsV2/data';
import SavedQueryButtonGroup from 'app/views/eventsV2/savedQuery';
Expand Down Expand Up @@ -49,6 +50,7 @@ describe('EventsV2 > SaveQueryButtonGroup', function () {
const errorsQuery = {
...ALL_VIEWS.find(view => view.name === 'Errors by Title'),
yAxis: 'count()',
display: DisplayModes.DEFAULT,
};
const errorsView = EventView.fromSavedQuery(errorsQuery);

Expand Down Expand Up @@ -443,9 +445,9 @@ describe('EventsV2 > SaveQueryButtonGroup', function () {
await tick();
await tick();
const modal = await mountGlobalModal();
expect(modal.find('AddDashboardWidgetModal').find('h4').children().html()).toEqual(
'Add Widget to Dashboard'
);
expect(
modal.find('AddDashboardWidgetModal').find('h4').children().at(0).html()
).toEqual('Add Widget to Dashboard');
});

it('populates dashboard widget modal with saved query data if created from discover', async () => {
Expand Down