123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180 |
- import {useState} from 'react';
- import {browserHistory} from 'react-router';
- 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 {IconReleases} from 'sentry/icons/iconReleases';
- import {t, tn} from 'sentry/locale';
- import {space} from 'sentry/styles/space';
- import {defined} from 'sentry/utils';
- import {getFormattedDate} from 'sentry/utils/dates';
- import {useLocation} from 'sentry/utils/useLocation';
- import {
- useReleases,
- useReleaseSelection,
- } from 'sentry/views/starfish/queries/useReleases';
- import {formatVersionAndCenterTruncate} from 'sentry/views/starfish/utils/centerTruncate';
- export const PRIMARY_RELEASE_ALIAS = 'R1';
- export const SECONDARY_RELEASE_ALIAS = 'R2';
- type Props = {
- selectorKey: string;
- selectorName?: string;
- selectorValue?: string;
- triggerLabelPrefix?: string;
- };
- export function ReleaseSelector({selectorKey, selectorValue, triggerLabelPrefix}: Props) {
- const [searchTerm, setSearchTerm] = useState<string | undefined>(undefined);
- const {data, isLoading} = useReleases(searchTerm);
- const {primaryRelease, secondaryRelease} = useReleaseSelection();
- const location = useLocation();
- const options: SelectOption<string>[] = [];
- if (defined(selectorValue)) {
- const index = data?.findIndex(({version}) => version === selectorValue);
- const selectedRelease = defined(index) ? data?.[index] : undefined;
- let selectedReleaseSessionCount: number | undefined = undefined;
- let selectedReleaseDateCreated: string | undefined = undefined;
- if (defined(selectedRelease)) {
- selectedReleaseSessionCount = selectedRelease.count;
- selectedReleaseDateCreated = selectedRelease.dateCreated;
- }
- options.push({
- value: selectorValue,
- label: selectorValue,
- details: (
- <LabelDetails
- screenCount={selectedReleaseSessionCount}
- dateCreated={selectedReleaseDateCreated}
- />
- ),
- });
- }
- data
- ?.filter(({version}) => ![primaryRelease, secondaryRelease].includes(version))
- .forEach(release => {
- const option = {
- value: release.version,
- label: release.version,
- details: (
- <LabelDetails screenCount={release.count} dateCreated={release.dateCreated} />
- ),
- };
- options.push(option);
- });
- const triggerLabelContent = selectorValue
- ? formatVersionAndCenterTruncate(selectorValue, 16)
- : selectorValue;
- return (
- <StyledCompactSelect
- triggerProps={{
- icon: <IconReleases />,
- title: selectorValue,
- prefix: triggerLabelPrefix,
- }}
- triggerLabel={triggerLabelContent}
- menuTitle={t('Filter Release')}
- loading={isLoading}
- searchable
- value={selectorValue}
- options={[
- {
- value: '_releases',
- label: t('Sorted by date created'),
- options,
- },
- ]}
- onSearch={debounce(val => {
- setSearchTerm(val);
- }, DEFAULT_DEBOUNCE_DURATION)}
- onChange={newValue => {
- browserHistory.push({
- ...location,
- query: {
- ...location.query,
- [selectorKey]: newValue.value,
- },
- });
- }}
- onClose={() => {
- setSearchTerm(undefined);
- }}
- />
- );
- }
- type LabelDetailsProps = {
- dateCreated?: string;
- screenCount?: number;
- };
- function LabelDetails(props: LabelDetailsProps) {
- return (
- <DetailsContainer>
- <div>
- {defined(props.screenCount)
- ? tn('%s event', '%s events', props.screenCount)
- : t('No screens')}
- </div>
- <div>
- {defined(props.dateCreated)
- ? getFormattedDate(props.dateCreated, 'MMM D, YYYY')
- : null}
- </div>
- </DetailsContainer>
- );
- }
- export function ReleaseComparisonSelector() {
- const {primaryRelease, secondaryRelease} = useReleaseSelection();
- return (
- <StyledPageSelector condensed>
- <ReleaseSelector
- selectorKey="primaryRelease"
- selectorValue={primaryRelease}
- selectorName={t('Release 1')}
- key="primaryRelease"
- triggerLabelPrefix={PRIMARY_RELEASE_ALIAS}
- />
- <ReleaseSelector
- selectorKey="secondaryRelease"
- selectorName={t('Release 2')}
- selectorValue={secondaryRelease}
- key="secondaryRelease"
- triggerLabelPrefix={SECONDARY_RELEASE_ALIAS}
- />
- </StyledPageSelector>
- );
- }
- const StyledCompactSelect = styled(CompactSelect)`
- @media (min-width: ${p => p.theme.breakpoints.medium}) {
- max-width: 275px;
- }
- `;
- const StyledPageSelector = styled(PageFilterBar)`
- & > * {
- min-width: 135px;
- &:last-child {
- min-width: 135px;
- }
- }
- `;
- const DetailsContainer = styled('div')`
- display: flex;
- flex-direction: row;
- justify-content: space-between;
- gap: ${space(1)};
- min-width: 200px;
- `;
|