Skip to content

Commit 10c9909

Browse files
authored
fix(spans-migration): Lock down discover transactions tab completely (#95880)
As part of the spans migration, we're locking down the transactions dataset in discover completely. This will not allow users to select the transactions dataset and save changes to existing transaction queries. I had to make changes to the `TabList.Item` component to allow passing in tooltip props so i can display the deprecation message. Closes [ENG-4633](https://linear.app/getsentry/issue/ENG-4633/lock-existing-discover-query-edit-and-transaction-tab)
1 parent dc7f19f commit 10c9909

File tree

7 files changed

+136
-28
lines changed

7 files changed

+136
-28
lines changed

static/app/components/core/tabs/item.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@ import {Item as _Item} from '@react-stately/collections';
22
import type {ItemProps} from '@react-types/shared';
33
import type {LocationDescriptor} from 'history';
44

5+
import type {TooltipProps} from 'sentry/components/core/tooltip';
6+
57
export interface TabListItemProps extends ItemProps<any> {
68
key: string | number;
79
disabled?: boolean;
810
hidden?: boolean;
911
to?: LocationDescriptor;
12+
tooltip?: TooltipProps;
1013
}
1114

1215
export const TabListItem = _Item as (props: TabListItemProps) => React.JSX.Element;

static/app/components/core/tabs/tab.tsx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import type {Node, Orientation} from '@react-types/shared';
99

1010
import InteractionStateLayer from 'sentry/components/core/interactionStateLayer';
1111
import {Link} from 'sentry/components/core/link';
12+
import {Tooltip, type TooltipProps} from 'sentry/components/core/tooltip';
1213
import {space} from 'sentry/styles/space';
1314
import {isChonkTheme, withChonk} from 'sentry/utils/theme/withChonk';
1415

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

@@ -156,6 +158,7 @@ export function Tab({
156158
variant,
157159
size,
158160
as = 'li',
161+
tooltipProps,
159162
}: TabProps) {
160163
const objectRef = useObjectRef(ref);
161164

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

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

173+
if (tooltipProps) {
174+
return (
175+
<Tooltip {...tooltipProps}>
176+
<BaseTab
177+
tabProps={tabProps}
178+
isSelected={isSelected}
179+
to={to}
180+
hidden={hidden}
181+
disabled={disabled}
182+
orientation={orientation}
183+
overflowing={overflowing}
184+
ref={objectRef}
185+
variant={variant}
186+
as={as}
187+
size={size}
188+
>
189+
{rendered}
190+
</BaseTab>
191+
</Tooltip>
192+
);
193+
}
194+
170195
return (
171196
<BaseTab
172197
tabProps={tabProps}

static/app/components/core/tabs/tabList.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ function BaseTabList({
221221
value: key,
222222
label: item.props.children,
223223
disabled: item.props.disabled,
224+
tooltip: item.props.tooltip,
224225
textValue: item.textValue,
225226
};
226227
});
@@ -243,6 +244,7 @@ function BaseTabList({
243244
orientation={orientation}
244245
size={size}
245246
overflowing={orientation === 'horizontal' && overflowTabs.includes(item.key)}
247+
tooltipProps={item.props.tooltip}
246248
ref={element => {
247249
tabItemsRef.current[item.key] = element;
248250
}}

static/app/views/discover/savedQuery/datasetSelectorTabs.spec.tsx

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ const EVENT_VIEW_CONSTRUCTOR_PROPS: EventViewOptions = {
2323
};
2424

2525
describe('Discover DatasetSelector', function () {
26-
const {router} = initializeOrg({
26+
const {router, organization} = initializeOrg({
2727
organization: {features: ['performance-view']},
2828
});
2929

@@ -121,4 +121,35 @@ describe('Discover DatasetSelector', function () {
121121
})
122122
);
123123
});
124+
125+
it('disables transactions dataset if org has deprecation feature', function () {
126+
const eventView = new EventView({
127+
...EVENT_VIEW_CONSTRUCTOR_PROPS,
128+
dataset: DiscoverDatasets.ERRORS,
129+
id: '1',
130+
});
131+
132+
const org = {
133+
...organization,
134+
features: [...organization.features, 'discover-saved-queries-deprecation'],
135+
};
136+
137+
render(
138+
<DatasetSelectorTabs
139+
isHomepage={false}
140+
savedQuery={undefined}
141+
eventView={eventView}
142+
/>,
143+
{
144+
router,
145+
organization: org,
146+
deprecatedRouterMocks: true,
147+
}
148+
);
149+
150+
expect(screen.getByRole('tab', {name: 'Transactions'})).toHaveAttribute(
151+
'aria-disabled',
152+
'true'
153+
);
154+
});
124155
});

static/app/views/discover/savedQuery/datasetSelectorTabs.tsx

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ import useOrganization from 'sentry/utils/useOrganization';
1919
import {
2020
getDatasetFromLocationOrSavedQueryDataset,
2121
getSavedQueryDataset,
22+
getTransactionDeprecationMessage,
2223
} from 'sentry/views/discover/savedQuery/utils';
24+
import {getExploreUrl} from 'sentry/views/explore/utils';
2325

2426
export const DATASET_PARAM = 'queryDataset';
2527

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

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

112+
const deprecatingTransactionsDataset = organization.features.includes(
113+
'discover-saved-queries-deprecation'
114+
);
115+
116+
const tracesUrl = getExploreUrl({
117+
organization,
118+
query: 'is_transaction:true',
119+
});
120+
110121
const options = [
111122
{
112123
value: SavedQueryDatasets.ERRORS,
@@ -115,6 +126,13 @@ export function DatasetSelectorTabs(props: Props) {
115126
{
116127
value: SavedQueryDatasets.TRANSACTIONS,
117128
label: DATASET_LABEL_MAP[SavedQueryDatasets.TRANSACTIONS],
129+
disabled: deprecatingTransactionsDataset,
130+
tooltip: deprecatingTransactionsDataset
131+
? {
132+
title: getTransactionDeprecationMessage(tracesUrl),
133+
isHoverable: true,
134+
}
135+
: undefined,
118136
},
119137
];
120138

@@ -153,7 +171,13 @@ export function DatasetSelectorTabs(props: Props) {
153171
>
154172
<TabList hideBorder>
155173
{options.map(option => (
156-
<TabList.Item key={option.value}>{option.label}</TabList.Item>
174+
<TabList.Item
175+
key={option.value}
176+
disabled={option.disabled}
177+
tooltip={option.tooltip}
178+
>
179+
{option.label}
180+
</TabList.Item>
157181
))}
158182
</TabList>
159183
</Layout.HeaderTabs>

static/app/views/discover/savedQuery/index.tsx

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,14 @@ import {ButtonBar} from 'sentry/components/core/button/buttonBar';
1616
import {LinkButton} from 'sentry/components/core/button/linkButton';
1717
import {Input} from 'sentry/components/core/input';
1818
import {Flex} from 'sentry/components/core/layout';
19-
import {Link} from 'sentry/components/core/link';
2019
import {Tooltip} from 'sentry/components/core/tooltip';
2120
import {CreateAlertFromViewButton} from 'sentry/components/createAlertButton';
2221
import type {MenuItemProps} from 'sentry/components/dropdownMenu';
2322
import {DropdownMenu} from 'sentry/components/dropdownMenu';
2423
import {Hovercard} from 'sentry/components/hovercard';
2524
import {Overlay, PositionWrapper} from 'sentry/components/overlay';
2625
import {IconBookmark, IconDelete, IconEllipsis, IconStar} from 'sentry/icons';
27-
import {t, tct} from 'sentry/locale';
26+
import {t} from 'sentry/locale';
2827
import {space} from 'sentry/styles/space';
2928
import type {InjectedRouter} from 'sentry/types/legacyReactRouter';
3029
import type {Organization, SavedQuery} from 'sentry/types/organization';
@@ -52,6 +51,7 @@ import {deprecateTransactionAlerts} from 'sentry/views/insights/common/utils/has
5251
import {
5352
getDatasetFromLocationOrSavedQueryDataset,
5453
getSavedQueryDataset,
54+
getTransactionDeprecationMessage,
5555
handleCreateQuery,
5656
handleDeleteQuery,
5757
handleResetHomepageQuery,
@@ -374,12 +374,7 @@ class SavedQueryButtonGroup extends PureComponent<Props, State> {
374374
!organization.features.includes('discover-saved-queries-deprecation')
375375
}
376376
isHoverable
377-
title={tct(
378-
'Discover\u2192Transactions is going to be merged into Explore\u2192Traces soon. Please save any transaction related queries from [traces:Explore\u2192Traces]',
379-
{
380-
traces: <Link to={tracesUrl} />,
381-
}
382-
)}
377+
title={getTransactionDeprecationMessage(tracesUrl)}
383378
>
384379
<SaveAsDropdown
385380
queryName={queryName}
@@ -393,23 +388,46 @@ class SavedQueryButtonGroup extends PureComponent<Props, State> {
393388

394389
renderButtonSave(disabled: boolean) {
395390
const {isNewQuery, isEditingQuery} = this.state;
391+
const {organization, savedQuery, location} = this.props;
392+
393+
const currentDataset = getDatasetFromLocationOrSavedQueryDataset(
394+
location,
395+
savedQuery?.queryDataset
396+
);
397+
398+
const deprecatingTransactionsDataset =
399+
currentDataset === DiscoverDatasets.TRANSACTIONS &&
400+
organization.features.includes('discover-saved-queries-deprecation');
396401

397402
if (!isNewQuery && !isEditingQuery) {
398403
return null;
399404
}
400405
// Existing query with edits, show save and save as.
401406
if (!isNewQuery && isEditingQuery) {
407+
const tracesUrl = getExploreUrl({
408+
organization,
409+
query: 'is_transaction:true',
410+
});
411+
402412
return (
403413
<Fragment>
404-
<Button
405-
onClick={this.handleUpdateQuery}
406-
data-test-id="discover2-savedquery-button-update"
407-
disabled={disabled}
408-
size="sm"
414+
<Tooltip
415+
title={
416+
deprecatingTransactionsDataset &&
417+
getTransactionDeprecationMessage(tracesUrl)
418+
}
419+
isHoverable
409420
>
410-
<IconUpdate />
411-
{t('Save Changes')}
412-
</Button>
421+
<Button
422+
onClick={this.handleUpdateQuery}
423+
data-test-id="discover2-savedquery-button-update"
424+
disabled={disabled || deprecatingTransactionsDataset}
425+
size="sm"
426+
>
427+
<IconUpdate />
428+
{t('Save Changes')}
429+
</Button>
430+
</Tooltip>
413431
{this.renderButtonSaveAs(disabled)}
414432
</Fragment>
415433
);
@@ -622,7 +640,7 @@ class SavedQueryButtonGroup extends PureComponent<Props, State> {
622640
savedQuery?.queryDataset
623641
);
624642

625-
const deprecatingAddToDashboard =
643+
const deprecatingTransactionsDataset =
626644
currentDataset === DiscoverDatasets.TRANSACTIONS &&
627645
organization.features.includes('discover-saved-queries-deprecation');
628646

@@ -637,15 +655,10 @@ class SavedQueryButtonGroup extends PureComponent<Props, State> {
637655
contextMenuItems.push({
638656
key: 'add-to-dashboard',
639657
label: t('Add to Dashboard'),
640-
disabled: deprecatingAddToDashboard,
658+
disabled: deprecatingTransactionsDataset,
659+
tooltipOptions: {isHoverable: true},
641660
tooltip:
642-
deprecatingAddToDashboard &&
643-
tct(
644-
'Discover\u2192Transactions is going to be merged into Explore\u2192Traces soon. Please save any transaction related queries from [traces:Explore\u2192Traces]',
645-
{
646-
traces: <Link to={tracesUrl} />,
647-
}
648-
),
661+
deprecatingTransactionsDataset && getTransactionDeprecationMessage(tracesUrl),
649662
onAction: () => {
650663
handleAddQueryToDashboard({
651664
organization,

static/app/views/discover/savedQuery/utils.tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ import {
1111
} from 'sentry/actionCreators/discoverSavedQueries';
1212
import {addErrorMessage, addSuccessMessage} from 'sentry/actionCreators/indicator';
1313
import type {Client} from 'sentry/api';
14-
import {t} from 'sentry/locale';
14+
import {Link} from 'sentry/components/core/link';
15+
import {t, tct} from 'sentry/locale';
1516
import type {NewQuery, Organization, SavedQuery} from 'sentry/types/organization';
1617
import {trackAnalytics} from 'sentry/utils/analytics';
1718
import type {SaveQueryEventParameters} from 'sentry/utils/analytics/discoverAnalyticsEvents';
@@ -347,3 +348,12 @@ export function getSavedQueryDatasetFromLocationOrDataset(
347348
return undefined;
348349
}
349350
}
351+
352+
export function getTransactionDeprecationMessage(tracesUrl: string) {
353+
return tct(
354+
'Discover\u2192Transactions is going to be merged into Explore\u2192Traces soon. Please save any transaction related queries from [traces:Explore\u2192Traces]',
355+
{
356+
traces: <Link to={tracesUrl} />,
357+
}
358+
);
359+
}

0 commit comments

Comments
 (0)