Skip to content

Commit

Permalink
feat(explore): Adding visualize to explore toolbar. (#76631)
Browse files Browse the repository at this point in the history
![Screenshot 2024-08-27 at 4 05
06 PM](https://github.com/user-attachments/assets/ccc5040f-e603-4761-aeb7-c9b7069eed70)

---------

Co-authored-by: Abdullah Khan <abdullahkhan@PG9Y57YDXQ.local>
  • Loading branch information
Abdkhan14 and Abdullah Khan committed Aug 27, 2024
1 parent 1a27c4e commit 8fe12c8
Show file tree
Hide file tree
Showing 4 changed files with 161 additions and 4 deletions.
42 changes: 42 additions & 0 deletions static/app/views/explore/hooks/useVisualize.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import {createMemoryHistory, Route, Router, RouterContext} from 'react-router';

import {act, render} from 'sentry-test/reactTestingLibrary';

import {useVisualize} from 'sentry/views/explore/hooks/useVisualize';
import {RouteContext} from 'sentry/views/routeContext';

describe('useVisualize', function () {
it('allows changing results mode', function () {
let visualize, setVisualize;

function TestPage() {
[visualize, setVisualize] = useVisualize();
return null;
}

const memoryHistory = createMemoryHistory();

render(
<Router
history={memoryHistory}
render={props => {
return (
<RouteContext.Provider value={props}>
<RouterContext {...props} />
</RouteContext.Provider>
);
}}
>
<Route path="/" component={TestPage} />
</Router>
);

expect(visualize).toEqual('count(span.duration)'); // default

act(() => setVisualize('p75(span.duration)'));
expect(visualize).toEqual('p75(span.duration)');

act(() => setVisualize('count(span.duration)'));
expect(visualize).toEqual('count(span.duration)');
});
});
54 changes: 54 additions & 0 deletions static/app/views/explore/hooks/useVisualize.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import {useCallback, useMemo} from 'react';
import type {Location} from 'history';

import {AggregationKey} from 'sentry/utils/fields';
import {decodeScalar} from 'sentry/utils/queryString';
import {useLocation} from 'sentry/utils/useLocation';
import {useNavigate} from 'sentry/utils/useNavigate';
import {SpanIndexedField} from 'sentry/views/insights/types';

interface Options {
location: Location;
navigate: ReturnType<typeof useNavigate>;
}

// TODO: Extend the two lists below with more options upon backend support
export const ALLOWED_VISUALIZE_FIELDS: SpanIndexedField[] = [
SpanIndexedField.SPAN_DURATION,
];

export const ALLOWED_VISUALIZE_AGGREGATES: AggregationKey[] = [AggregationKey.COUNT];

export const DEFAULT_VISUALIZATION = `${ALLOWED_VISUALIZE_AGGREGATES[0]}(${ALLOWED_VISUALIZE_FIELDS[0]})`;

export function useVisualize(): [string, (visualize: string) => void] {
const location = useLocation();
const navigate = useNavigate();
const options = {location, navigate};

return useVisualizeImpl(options);
}

function useVisualizeImpl({
location,
navigate,
}: Options): [string, (visualize: string) => void] {
const visualize: string | undefined = useMemo(() => {
return decodeScalar(location.query.visualize) ?? DEFAULT_VISUALIZATION;
}, [location.query.visualize]);

const setVisualize = useCallback(
(newVisualize: string) => {
navigate({
...location,
query: {
...location.query,
visualize: newVisualize,
},
});
},
[location, navigate]
);

return [visualize, setVisualize];
}
5 changes: 4 additions & 1 deletion static/app/views/explore/toolbar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import {ToolbarResults} from 'sentry/views/explore/toolbar/toolbarResults';
import {ToolbarSortBy} from 'sentry/views/explore/toolbar/toolbarSortBy';
import {ToolbarVisualize} from 'sentry/views/explore/toolbar/toolbarVisualize';

import {useVisualize} from '../hooks/useVisualize';

type Extras = 'dataset toggle';

interface ExploreToolbarProps {
Expand All @@ -20,14 +22,15 @@ export function ExploreToolbar({extras}: ExploreToolbarProps) {
const [resultMode, setResultMode] = useResultMode();
const [sampleFields] = useSampleFields();
const [sorts, setSorts] = useSorts({fields: sampleFields});
const [visualize, setVisualize] = useVisualize();

return (
<div>
{extras?.includes('dataset toggle') && (
<ToolbarDataset dataset={dataset} setDataset={setDataset} />
)}
<ToolbarResults resultMode={resultMode} setResultMode={setResultMode} />
<ToolbarVisualize />
<ToolbarVisualize visualize={visualize} setVisualize={setVisualize} />
<ToolbarSortBy fields={sampleFields} sorts={sorts} setSorts={setSorts} />
<ToolbarLimitTo />
<ToolbarGroupBy disabled />
Expand Down
64 changes: 61 additions & 3 deletions static/app/views/explore/toolbar/toolbarVisualize.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,71 @@
import {useMemo} from 'react';
import styled from '@emotion/styled';

import {CompactSelect, type SelectOption} from 'sentry/components/compactSelect';
import {t} from 'sentry/locale';
import {parseFunction} from 'sentry/utils/discover/fields';
import type {SpanIndexedField} from 'sentry/views/insights/types';

import {
ALLOWED_VISUALIZE_AGGREGATES,
ALLOWED_VISUALIZE_FIELDS,
} from '../hooks/useVisualize';

import {ToolbarHeading, ToolbarSection} from './styles';

interface ToolbarVisualizeProps {}
interface ToolbarVisualizeProps {
setVisualize: (visualize: string) => void;
visualize: string;
}

export function ToolbarVisualize({visualize, setVisualize}: ToolbarVisualizeProps) {
const parsedVisualize = useMemo(() => {
return parseFunction(visualize);
}, [visualize]);

const fieldOptions: SelectOption<SpanIndexedField>[] = ALLOWED_VISUALIZE_FIELDS.map(
field => {
return {
label: field,
value: field,
};
}
);

const aggregateOptions: SelectOption<string>[] = ALLOWED_VISUALIZE_AGGREGATES.map(
aggregate => {
return {
label: aggregate,
value: aggregate,
};
}
);

export function ToolbarVisualize({}: ToolbarVisualizeProps) {
return (
<ToolbarSection>
<ToolbarSection data-test-id="section-visualize">
<ToolbarHeading>{t('Visualize')}</ToolbarHeading>
<ToolbarContent>
<CompactSelect
size="md"
options={fieldOptions}
value={parsedVisualize?.arguments[0]}
onChange={newField =>
setVisualize(`${parsedVisualize?.name}(${newField.value})`)
}
/>
<CompactSelect
size="md"
options={aggregateOptions}
value={parsedVisualize?.name}
onChange={newAggregate =>
setVisualize(`${newAggregate.value}(${parsedVisualize?.arguments[0]})`)
}
/>
</ToolbarContent>
</ToolbarSection>
);
}

const ToolbarContent = styled('div')`
display: flex;
`;

0 comments on commit 8fe12c8

Please sign in to comment.