-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(explore): Adding visualize to explore toolbar. (#76631)
![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
Showing
4 changed files
with
161 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
`; |