Skip to content

fix(spans-migration): Lock down discover transactions tab completely #95880

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

Merged
merged 4 commits into from
Jul 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions static/app/components/core/tabs/item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ import {Item as _Item} from '@react-stately/collections';
import type {ItemProps} from '@react-types/shared';
import type {LocationDescriptor} from 'history';

import type {TooltipProps} from 'sentry/components/core/tooltip';

export interface TabListItemProps extends ItemProps<any> {
key: string | number;
disabled?: boolean;
hidden?: boolean;
to?: LocationDescriptor;
tooltip?: TooltipProps;
}

export const TabListItem = _Item as (props: TabListItemProps) => React.JSX.Element;
Expand Down
25 changes: 25 additions & 0 deletions static/app/components/core/tabs/tab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import type {Node, Orientation} from '@react-types/shared';

import InteractionStateLayer from 'sentry/components/core/interactionStateLayer';
import {Link} from 'sentry/components/core/link';
import {Tooltip, type TooltipProps} from 'sentry/components/core/tooltip';
import {space} from 'sentry/styles/space';
import {isChonkTheme, withChonk} from 'sentry/utils/theme/withChonk';

Expand All @@ -33,6 +34,7 @@ interface TabProps extends AriaTabProps {
state: TabListState<any>;
as?: React.ElementType;
ref?: React.Ref<HTMLLIElement>;
tooltipProps?: TooltipProps;
variant?: BaseTabProps['variant'];
}

Expand Down Expand Up @@ -156,6 +158,7 @@ export function Tab({
variant,
size,
as = 'li',
tooltipProps,
}: TabProps) {
const objectRef = useObjectRef(ref);

Expand All @@ -167,6 +170,28 @@ export function Tab({

const {tabProps, isSelected} = useTab({key, isDisabled: hidden}, state, objectRef);

if (tooltipProps) {
return (
<Tooltip {...tooltipProps}>
<BaseTab
tabProps={tabProps}
isSelected={isSelected}
to={to}
hidden={hidden}
disabled={disabled}
orientation={orientation}
overflowing={overflowing}
ref={objectRef}
variant={variant}
as={as}
size={size}
>
{rendered}
</BaseTab>
</Tooltip>
);
}

return (
<BaseTab
tabProps={tabProps}
Expand Down
2 changes: 2 additions & 0 deletions static/app/components/core/tabs/tabList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ function BaseTabList({
value: key,
label: item.props.children,
disabled: item.props.disabled,
tooltip: item.props.tooltip,
textValue: item.textValue,
};
});
Expand All @@ -243,6 +244,7 @@ function BaseTabList({
orientation={orientation}
size={size}
overflowing={orientation === 'horizontal' && overflowTabs.includes(item.key)}
tooltipProps={item.props.tooltip}
ref={element => {
tabItemsRef.current[item.key] = element;
}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const EVENT_VIEW_CONSTRUCTOR_PROPS: EventViewOptions = {
};

describe('Discover DatasetSelector', function () {
const {router} = initializeOrg({
const {router, organization} = initializeOrg({
organization: {features: ['performance-view']},
});

Expand Down Expand Up @@ -121,4 +121,35 @@ describe('Discover DatasetSelector', function () {
})
);
});

it('disables transactions dataset if org has deprecation feature', function () {
const eventView = new EventView({
...EVENT_VIEW_CONSTRUCTOR_PROPS,
dataset: DiscoverDatasets.ERRORS,
id: '1',
});

const org = {
...organization,
features: [...organization.features, 'discover-saved-queries-deprecation'],
};

render(
<DatasetSelectorTabs
isHomepage={false}
savedQuery={undefined}
eventView={eventView}
/>,
{
router,
organization: org,
deprecatedRouterMocks: true,
}
);

expect(screen.getByRole('tab', {name: 'Transactions'})).toHaveAttribute(
'aria-disabled',
'true'
);
});
});
26 changes: 25 additions & 1 deletion static/app/views/discover/savedQuery/datasetSelectorTabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ import useOrganization from 'sentry/utils/useOrganization';
import {
getDatasetFromLocationOrSavedQueryDataset,
getSavedQueryDataset,
getTransactionDeprecationMessage,
} from 'sentry/views/discover/savedQuery/utils';
import {getExploreUrl} from 'sentry/views/explore/utils';

export const DATASET_PARAM = 'queryDataset';

Expand Down Expand Up @@ -107,6 +109,15 @@ export function DatasetSelectorTabs(props: Props) {

const value = getSavedQueryDataset(organization, location, savedQuery, splitDecision);

const deprecatingTransactionsDataset = organization.features.includes(
'discover-saved-queries-deprecation'
);

const tracesUrl = getExploreUrl({
organization,
query: 'is_transaction:true',
});

const options = [
{
value: SavedQueryDatasets.ERRORS,
Expand All @@ -115,6 +126,13 @@ export function DatasetSelectorTabs(props: Props) {
{
value: SavedQueryDatasets.TRANSACTIONS,
label: DATASET_LABEL_MAP[SavedQueryDatasets.TRANSACTIONS],
disabled: deprecatingTransactionsDataset,
tooltip: deprecatingTransactionsDataset
Comment on lines +129 to +130
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like when disabled: true, the tooltip hovering doesn't work. You may want to see if there's some kind of styling blocking cursor events 🤔

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this line is responsible. Maybe we can check if there's tooltip information in the styled component before blocking all pointer events, or maybe there's another setting that we can use.

? {
title: getTransactionDeprecationMessage(tracesUrl),
isHoverable: true,
}
: undefined,
},
];

Expand Down Expand Up @@ -153,7 +171,13 @@ export function DatasetSelectorTabs(props: Props) {
>
<TabList hideBorder>
{options.map(option => (
<TabList.Item key={option.value}>{option.label}</TabList.Item>
<TabList.Item
key={option.value}
disabled={option.disabled}
tooltip={option.tooltip}
>
{option.label}
</TabList.Item>
))}
</TabList>
</Layout.HeaderTabs>
Expand Down
63 changes: 38 additions & 25 deletions static/app/views/discover/savedQuery/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,14 @@ import {ButtonBar} from 'sentry/components/core/button/buttonBar';
import {LinkButton} from 'sentry/components/core/button/linkButton';
import {Input} from 'sentry/components/core/input';
import {Flex} from 'sentry/components/core/layout';
import {Link} from 'sentry/components/core/link';
import {Tooltip} from 'sentry/components/core/tooltip';
import {CreateAlertFromViewButton} from 'sentry/components/createAlertButton';
import type {MenuItemProps} from 'sentry/components/dropdownMenu';
import {DropdownMenu} from 'sentry/components/dropdownMenu';
import {Hovercard} from 'sentry/components/hovercard';
import {Overlay, PositionWrapper} from 'sentry/components/overlay';
import {IconBookmark, IconDelete, IconEllipsis, IconStar} from 'sentry/icons';
import {t, tct} from 'sentry/locale';
import {t} from 'sentry/locale';
import {space} from 'sentry/styles/space';
import type {InjectedRouter} from 'sentry/types/legacyReactRouter';
import type {Organization, SavedQuery} from 'sentry/types/organization';
Expand Down Expand Up @@ -52,6 +51,7 @@ import {deprecateTransactionAlerts} from 'sentry/views/insights/common/utils/has
import {
getDatasetFromLocationOrSavedQueryDataset,
getSavedQueryDataset,
getTransactionDeprecationMessage,
handleCreateQuery,
handleDeleteQuery,
handleResetHomepageQuery,
Expand Down Expand Up @@ -374,12 +374,7 @@ class SavedQueryButtonGroup extends PureComponent<Props, State> {
!organization.features.includes('discover-saved-queries-deprecation')
}
isHoverable
title={tct(
'Discover\u2192Transactions is going to be merged into Explore\u2192Traces soon. Please save any transaction related queries from [traces:Explore\u2192Traces]',
{
traces: <Link to={tracesUrl} />,
}
)}
title={getTransactionDeprecationMessage(tracesUrl)}
>
<SaveAsDropdown
queryName={queryName}
Expand All @@ -393,23 +388,46 @@ class SavedQueryButtonGroup extends PureComponent<Props, State> {

renderButtonSave(disabled: boolean) {
const {isNewQuery, isEditingQuery} = this.state;
const {organization, savedQuery, location} = this.props;

const currentDataset = getDatasetFromLocationOrSavedQueryDataset(
location,
savedQuery?.queryDataset
);

const deprecatingTransactionsDataset =
currentDataset === DiscoverDatasets.TRANSACTIONS &&
organization.features.includes('discover-saved-queries-deprecation');

if (!isNewQuery && !isEditingQuery) {
return null;
}
// Existing query with edits, show save and save as.
if (!isNewQuery && isEditingQuery) {
const tracesUrl = getExploreUrl({
organization,
query: 'is_transaction:true',
});

return (
<Fragment>
<Button
onClick={this.handleUpdateQuery}
data-test-id="discover2-savedquery-button-update"
disabled={disabled}
size="sm"
<Tooltip
title={
deprecatingTransactionsDataset &&
getTransactionDeprecationMessage(tracesUrl)
}
isHoverable
>
<IconUpdate />
{t('Save Changes')}
</Button>
<Button
onClick={this.handleUpdateQuery}
data-test-id="discover2-savedquery-button-update"
disabled={disabled || deprecatingTransactionsDataset}
size="sm"
>
<IconUpdate />
{t('Save Changes')}
</Button>
</Tooltip>
{this.renderButtonSaveAs(disabled)}
</Fragment>
);
Expand Down Expand Up @@ -622,7 +640,7 @@ class SavedQueryButtonGroup extends PureComponent<Props, State> {
savedQuery?.queryDataset
);

const deprecatingAddToDashboard =
const deprecatingTransactionsDataset =
currentDataset === DiscoverDatasets.TRANSACTIONS &&
organization.features.includes('discover-saved-queries-deprecation');

Expand All @@ -637,15 +655,10 @@ class SavedQueryButtonGroup extends PureComponent<Props, State> {
contextMenuItems.push({
key: 'add-to-dashboard',
label: t('Add to Dashboard'),
disabled: deprecatingAddToDashboard,
disabled: deprecatingTransactionsDataset,
tooltipOptions: {isHoverable: true},
tooltip:
deprecatingAddToDashboard &&
tct(
'Discover\u2192Transactions is going to be merged into Explore\u2192Traces soon. Please save any transaction related queries from [traces:Explore\u2192Traces]',
{
traces: <Link to={tracesUrl} />,
}
),
deprecatingTransactionsDataset && getTransactionDeprecationMessage(tracesUrl),
onAction: () => {
handleAddQueryToDashboard({
organization,
Expand Down
12 changes: 11 additions & 1 deletion static/app/views/discover/savedQuery/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import {
} from 'sentry/actionCreators/discoverSavedQueries';
import {addErrorMessage, addSuccessMessage} from 'sentry/actionCreators/indicator';
import type {Client} from 'sentry/api';
import {t} from 'sentry/locale';
import {Link} from 'sentry/components/core/link';
import {t, tct} from 'sentry/locale';
import type {NewQuery, Organization, SavedQuery} from 'sentry/types/organization';
import {trackAnalytics} from 'sentry/utils/analytics';
import type {SaveQueryEventParameters} from 'sentry/utils/analytics/discoverAnalyticsEvents';
Expand Down Expand Up @@ -347,3 +348,12 @@ export function getSavedQueryDatasetFromLocationOrDataset(
return undefined;
}
}

export function getTransactionDeprecationMessage(tracesUrl: string) {
return tct(
'Discover\u2192Transactions is going to be merged into Explore\u2192Traces soon. Please save any transaction related queries from [traces:Explore\u2192Traces]',
{
traces: <Link to={tracesUrl} />,
}
);
}
Loading