-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(insights): Introduce sort by selector for releases #82302
Changes from all commits
5d2c93f
1bb7e0e
09200be
83010ca
e759a34
33db74b
1e23dc9
3bd0add
63adbb9
f536bf6
2cc8153
e2ec015
1e8b624
7d54fb5
c2d43bf
795676d
4f1c30c
8ea04e8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
export enum ReleasesSortOption { | ||
CRASH_FREE_USERS = 'crash_free_users', | ||
CRASH_FREE_SESSIONS = 'crash_free_sessions', | ||
USERS_24_HOURS = 'users_24h', | ||
SESSIONS_24_HOURS = 'sessions_24h', | ||
SESSIONS = 'sessions', | ||
DATE = 'date', | ||
BUILD = 'build', | ||
SEMVER = 'semver', | ||
ADOPTION = 'adoption', | ||
Comment on lines
+2
to
+10
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @philipphofmann can you confirm that we would like to provide all these sort by options? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would remove crash-free-users and crash-free-session, as we are filtering releases for performance data, and I don't think that is relevant. I would keep the rest. |
||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -1,18 +1,27 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import {useState} from 'react'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import {useEffect, useState} from 'react'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import styled from '@emotion/styled'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import debounce from 'lodash/debounce'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import type {SelectOption} from 'sentry/components/compactSelect'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import {CompactSelect} from 'sentry/components/compactSelect'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import PageFilterBar from 'sentry/components/organizations/pageFilterBar'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import {DEFAULT_DEBOUNCE_DURATION} from 'sentry/constants'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import {ReleasesSortOption} from 'sentry/constants/releases'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import {IconReleases} from 'sentry/icons/iconReleases'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import {t, tn} from 'sentry/locale'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import {t, tct, tn} from 'sentry/locale'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import {space} from 'sentry/styles/space'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import {defined} from 'sentry/utils'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import {getFormattedDate} from 'sentry/utils/dates'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import {decodeScalar} from 'sentry/utils/queryString'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import {useLocalStorageState} from 'sentry/utils/useLocalStorageState'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import {useLocation} from 'sentry/utils/useLocation'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import {useNavigate} from 'sentry/utils/useNavigate'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import usePageFilters from 'sentry/utils/usePageFilters'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ReleasesSort, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
type ReleasesSortByOption, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
SORT_BY_OPTIONS, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} from 'sentry/views/insights/common/components/releasesSort'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
useReleases, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
useReleaseSelection, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -24,19 +33,25 @@ export const SECONDARY_RELEASE_ALIAS = 'R2'; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
type Props = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
selectorKey: string; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
sortBy: ReleasesSortByOption; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
selectorName?: string; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
selectorValue?: string; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
triggerLabelPrefix?: string; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
export function ReleaseSelector({selectorKey, selectorValue, triggerLabelPrefix}: Props) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
export function ReleaseSelector({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
selectorKey, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
selectorValue, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
triggerLabelPrefix, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
sortBy, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}: Props) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const [searchTerm, setSearchTerm] = useState<string | undefined>(undefined); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const {data, isLoading} = useReleases(searchTerm); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const {data, isLoading} = useReleases(searchTerm, sortBy); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const {primaryRelease, secondaryRelease} = useReleaseSelection(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const navigate = useNavigate(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const location = useLocation(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const options: SelectOption<string>[] = []; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const options: (SelectOption<string> & {count?: number})[] = []; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (defined(selectorValue)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const index = data?.findIndex(({version}) => version === selectorValue); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const selectedRelease = defined(index) ? data?.[index] : undefined; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -49,6 +64,7 @@ export function ReleaseSelector({selectorKey, selectorValue, triggerLabelPrefix} | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
options.push({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
value: selectorValue, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
count: selectedReleaseSessionCount, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
label: selectorValue, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
details: ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<LabelDetails | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -58,12 +74,14 @@ export function ReleaseSelector({selectorKey, selectorValue, triggerLabelPrefix} | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
data | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
?.filter(({version}) => ![primaryRelease, secondaryRelease].includes(version)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.forEach(release => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const option = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
value: release.version, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
label: release.version, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
count: release.count, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
details: ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<LabelDetails screenCount={release.count} dateCreated={release.dateCreated} /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -88,10 +106,19 @@ export function ReleaseSelector({selectorKey, selectorValue, triggerLabelPrefix} | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
searchable | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
value={selectorValue} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
options={[ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
value: '_selected_release', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// We do this because the selected/default release might not be sorted, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// but instead could have been added to the top of options list. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
options: options.slice(0, 1), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
value: '_releases', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
label: t('Sorted by date created'), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
options, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
label: tct('Sorted by [sortBy]', { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
sortBy: SORT_BY_OPTIONS[sortBy].label, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Display other releases sorted by the selected option | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
options: options.slice(1), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
]} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
onSearch={debounce(val => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -135,8 +162,76 @@ function LabelDetails(props: LabelDetailsProps) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
function getReleasesSortBy( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
sort: ReleasesSortByOption, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
environments: string[] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
): ReleasesSortByOption { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Require 1 environment for date adopted | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (sort === ReleasesSortOption.ADOPTION && environments.length !== 1) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return ReleasesSortOption.DATE; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (sort in SORT_BY_OPTIONS) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return sort; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// We could give a visual feedback to the user, saying that the sort by is invalid but | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// since this UI will be refactored, maybe we just don't do anything now. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// This is the same fallback as the one used in static/app/views/insights/common/queries/useReleases.tsx. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return ReleasesSortOption.DATE; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
export function ReleaseComparisonSelector() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const {primaryRelease, secondaryRelease} = useReleaseSelection(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const location = useLocation(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const navigate = useNavigate(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const {selection} = usePageFilters(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const [localStoragedReleaseBy, setLocalStoragedReleaseBy] = | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
useLocalStorageState<ReleasesSortByOption>( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
'insightsReleasesSortBy', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ReleasesSortOption.DATE | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const urlStoragedReleaseBy = decodeScalar( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
location.query.sortReleasesBy | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) as ReleasesSortByOption; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+196
to
+198
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would add a runtime type guard here as opposed to a cast and log sentry errors if we end up seeing invalid values. That way in case this ever breaks or some link ends up sending us bad values, we can identify and fix it There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Users have the option to modify the URL, though I don't expect many to do so. However, if they do, we have a fallback in place: sentry/static/app/views/insights/common/components/releaseSelector.tsx Lines 171 to 173 in e2ec015
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes they can, which is why it's good to validate :) You can always just logMessage instead of throw and error btw, because it should still be unexpected behavior |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
useEffect(() => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (urlStoragedReleaseBy === localStoragedReleaseBy) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// this is useful in case the user shares the url with another user | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// and the user has a different sort by in their local storage | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (!urlStoragedReleaseBy) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
navigate( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
...location, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
query: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
...location.query, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
sortReleasesBy: localStoragedReleaseBy, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{replace: true} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
setLocalStoragedReleaseBy(urlStoragedReleaseBy); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, [ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
urlStoragedReleaseBy, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+200
to
+222
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can just inline this without an effect
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hmmm but isn't updating the URL a side effect? side effects should live inside a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is an effect, but that doesn't mean it needs to be inside a useEffect :) What will happens here is that because useEffect is async, the UI might flicker with the old value for a split second, before it gets replaced as the result of the effect run, which I think is something you want to avoid There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have a question about this! React documentation is very explicit that renders must be pure (though I guess in this case, it's not a huge deal). Maybe this is a good case for |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
localStoragedReleaseBy, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
setLocalStoragedReleaseBy, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
location, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
navigate, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
]); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const sortReleasesBy = getReleasesSortBy( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
localStoragedReleaseBy, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
selection.environments | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<StyledPageSelector condensed> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<ReleaseSelector | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -145,13 +240,28 @@ export function ReleaseComparisonSelector() { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
selectorName={t('Release 1')} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
key="primaryRelease" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
triggerLabelPrefix={PRIMARY_RELEASE_ALIAS} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
sortBy={sortReleasesBy} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<ReleaseSelector | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
selectorKey="secondaryRelease" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
selectorName={t('Release 2')} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
selectorValue={secondaryRelease} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
key="secondaryRelease" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
triggerLabelPrefix={SECONDARY_RELEASE_ALIAS} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
sortBy={sortReleasesBy} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<ReleasesSort | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
sortBy={sortReleasesBy} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
environments={selection.environments} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
onChange={value => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
navigate({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
...location, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
query: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
...location.query, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
sortReleasesBy: value, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
</StyledPageSelector> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -167,7 +277,10 @@ const StyledPageSelector = styled(PageFilterBar)` | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
& > * { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
min-width: 135px; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
&:last-child { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
min-width: 135px; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
min-width: auto; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
> button[aria-haspopup] { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
padding-right: ${space(1.5)}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
`; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import {Button} from 'sentry/components/button'; | ||
import {CompositeSelect} from 'sentry/components/compactSelect/composite'; | ||
import {ReleasesSortOption} from 'sentry/constants/releases'; | ||
import {IconSort} from 'sentry/icons'; | ||
import {t} from 'sentry/locale'; | ||
|
||
export const SORT_BY_OPTIONS = { | ||
[ReleasesSortOption.SESSIONS_24_HOURS]: {label: t('Active Sessions')}, | ||
[ReleasesSortOption.USERS_24_HOURS]: {label: t('Active Users')}, | ||
[ReleasesSortOption.ADOPTION]: {label: t('Adoption')}, | ||
[ReleasesSortOption.BUILD]: {label: t('Build Number')}, | ||
[ReleasesSortOption.DATE]: {label: t('Date Created')}, | ||
[ReleasesSortOption.SEMVER]: {label: t('Semantic Version')}, | ||
[ReleasesSortOption.SESSIONS]: {label: t('Total Sessions')}, | ||
}; | ||
|
||
export type ReleasesSortByOption = keyof typeof SORT_BY_OPTIONS; | ||
|
||
interface Props { | ||
environments: string[]; | ||
onChange: (sortBy: string) => void; | ||
sortBy: ReleasesSortByOption; | ||
} | ||
|
||
export function ReleasesSort({environments, sortBy, onChange}: Props) { | ||
return ( | ||
<CompositeSelect | ||
trigger={triggerProps => ( | ||
<Button | ||
{...triggerProps} | ||
size="xs" | ||
icon={<IconSort />} | ||
title={t('Sort Releases')} | ||
aria-label={t('Sort Releases')} | ||
/> | ||
)} | ||
> | ||
<CompositeSelect.Region | ||
label={t('Sort By')} | ||
value={sortBy} | ||
onChange={selection => { | ||
onChange(selection.value); | ||
}} | ||
options={Object.entries(SORT_BY_OPTIONS).map(([name, filter]) => { | ||
if (name !== ReleasesSortOption.ADOPTION) { | ||
return { | ||
label: filter.label, | ||
value: name, | ||
}; | ||
} | ||
|
||
const isNotSingleEnvironment = environments.length !== 1; | ||
return { | ||
label: filter.label, | ||
value: name, | ||
disabled: isNotSingleEnvironment, | ||
tooltip: isNotSingleEnvironment | ||
? t('Select one environment to use this sort option.') | ||
: undefined, | ||
}; | ||
})} | ||
/> | ||
</CompositeSelect> | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this enum was just moved from
sentry/static/app/views/releases/list/releasesSortOptions.tsx
Lines 8 to 18 in 5078825