Skip to content

Commit

Permalink
feat(widget-builder): Add Dataset to hook (#81437)
Browse files Browse the repository at this point in the history
Adds the dataset property to the hook. This one doesn't need any special
updates other than providing a decoder to cast the field into a
`WidgetType`.
  • Loading branch information
narsaynorath authored Nov 28, 2024
1 parent f1e85f5 commit 4fcef49
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import styled from '@emotion/styled';

import RadioGroup from 'sentry/components/forms/controls/radioGroup';
import SelectField from 'sentry/components/forms/fields/selectField';
import Input from 'sentry/components/input';
import {space} from 'sentry/styles/space';
import {DisplayType} from 'sentry/views/dashboards/types';
import {DisplayType, WidgetType} from 'sentry/views/dashboards/types';
import useWidgetBuilderState, {
BuilderStateAction,
} from 'sentry/views/dashboards/widgetBuilder/hooks/useWidgetBuilderState';
Expand Down Expand Up @@ -55,6 +56,28 @@ function DevBuilder() {
style={{width: '200px'}}
/>
</Section>
<Section>
<h1>Dataset:</h1>
<div>{state.dataset}</div>
<RadioGroup
label="Dataset"
value={state.dataset ?? null}
choices={[
[WidgetType.DISCOVER, 'Discover'],
[WidgetType.ISSUE, 'Issue'],
[WidgetType.RELEASE, 'Release'],
[WidgetType.METRICS, 'Metrics'],
[WidgetType.ERRORS, 'Errors'],
[WidgetType.TRANSACTIONS, 'Transactions'],
]}
onChange={newValue =>
dispatch({
type: BuilderStateAction.SET_DATASET,
payload: newValue,
})
}
/>
</Section>
</Body>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {act, renderHook} from 'sentry-test/reactTestingLibrary';

import {useLocation} from 'sentry/utils/useLocation';
import {useNavigate} from 'sentry/utils/useNavigate';
import {DisplayType} from 'sentry/views/dashboards/types';
import {DisplayType, WidgetType} from 'sentry/views/dashboards/types';
import useWidgetBuilderState, {
BuilderStateAction,
} from 'sentry/views/dashboards/widgetBuilder/hooks/useWidgetBuilderState';
Expand Down Expand Up @@ -119,4 +119,46 @@ describe('useWidgetBuilderState', () => {
);
});
});

describe('dataset', () => {
it('returns the dataset from the query params', () => {
mockedUsedLocation.mockReturnValue(
LocationFixture({query: {dataset: WidgetType.ISSUE}})
);

const {result} = renderHook(() => useWidgetBuilderState());

expect(result.current.state.dataset).toBe(WidgetType.ISSUE);
});

it('sets the dataset in the query params', () => {
const mockNavigate = jest.fn();
mockedUseNavigate.mockReturnValue(mockNavigate);

const {result} = renderHook(() => useWidgetBuilderState());

act(() => {
result.current.dispatch({
type: BuilderStateAction.SET_DATASET,
payload: WidgetType.METRICS,
});
});

jest.runAllTimers();

expect(mockNavigate).toHaveBeenCalledWith(
expect.objectContaining({
query: expect.objectContaining({dataset: WidgetType.METRICS}),
})
);
});

it('returns errors as the default dataset', () => {
mockedUsedLocation.mockReturnValue(LocationFixture({query: {dataset: 'invalid'}}));

const {result} = renderHook(() => useWidgetBuilderState());

expect(result.current.state.dataset).toBe(WidgetType.ERRORS);
});
});
});
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
import {useCallback, useMemo} from 'react';

import {DisplayType} from 'sentry/views/dashboards/types';
import {DisplayType, WidgetType} from 'sentry/views/dashboards/types';
import {useQueryParamState} from 'sentry/views/dashboards/widgetBuilder/hooks/useQueryParamState';

export const BuilderStateAction = {
SET_TITLE: 'SET_TITLE',
SET_DESCRIPTION: 'SET_DESCRIPTION',
SET_DISPLAY_TYPE: 'SET_DISPLAY_TYPE',
SET_DATASET: 'SET_DATASET',
} as const;

type WidgetAction =
| {payload: string; type: typeof BuilderStateAction.SET_TITLE}
| {payload: string; type: typeof BuilderStateAction.SET_DESCRIPTION}
| {payload: DisplayType; type: typeof BuilderStateAction.SET_DISPLAY_TYPE};
| {payload: DisplayType; type: typeof BuilderStateAction.SET_DISPLAY_TYPE}
| {payload: WidgetType; type: typeof BuilderStateAction.SET_DATASET};

interface WidgetBuilderState {
dataset?: WidgetType;
description?: string;
displayType?: DisplayType;
title?: string;
Expand All @@ -32,10 +35,14 @@ function useWidgetBuilderState(): {
fieldName: 'displayType',
decoder: decodeDisplayType,
});
const [dataset, setDataset] = useQueryParamState<WidgetType>({
fieldName: 'dataset',
decoder: decodeDataset,
});

const state = useMemo(
() => ({title, description, displayType}),
[title, description, displayType]
() => ({title, description, displayType, dataset}),
[title, description, displayType, dataset]
);

const dispatch = useCallback(
Expand All @@ -50,11 +57,14 @@ function useWidgetBuilderState(): {
case BuilderStateAction.SET_DISPLAY_TYPE:
setDisplayType(action.payload);
break;
case BuilderStateAction.SET_DATASET:
setDataset(action.payload);
break;
default:
break;
}
},
[setTitle, setDescription, setDisplayType]
[setTitle, setDescription, setDisplayType, setDataset]
);

return {
Expand All @@ -74,4 +84,15 @@ function decodeDisplayType(value: string): DisplayType {
return DisplayType.TABLE;
}

/**
* Decodes the dataset from the query params
* Returns the default dataset if the value is not a valid dataset
*/
function decodeDataset(value: string): WidgetType {
if (Object.values(WidgetType).includes(value as WidgetType)) {
return value as WidgetType;
}
return WidgetType.ERRORS;
}

export default useWidgetBuilderState;

0 comments on commit 4fcef49

Please sign in to comment.