Skip to content

Commit 068e497

Browse files
feat(dashboards): Adds action menu to prebuilt dashboard widgets (#103976)
- Removes `Widget` title wrapper usage in `VisualizationWidget` - Reuse `WidgetFrame` wrapper on `VisualizationWidget` call site. This primarily enables the context menu for widgets using the new time series visualization component - Also wraps `VisualizationWidget` in `VisuallyCompleteWithData` for telemetry - Updates the common `SortableWidget` component to conditionally `showContextMenu` depending on if the dashboard `isEmbedded`.
1 parent ebf1635 commit 068e497

File tree

6 files changed

+97
-26
lines changed

6 files changed

+97
-26
lines changed

static/app/views/dashboards/dashboard.spec.tsx

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,45 @@ describe('Dashboards > Dashboard', () => {
289289
expect(mockOnUpdate).toHaveBeenCalledWith(expectedWidgets);
290290
});
291291

292+
it('hides widget context menu when dashboard is embedded', async () => {
293+
const dashboardWithOneWidget = {
294+
...mockDashboard,
295+
widgets: [
296+
WidgetFixture({
297+
id: '1',
298+
title: 'Test Widget',
299+
layout: {
300+
h: 1,
301+
w: 1,
302+
x: 0,
303+
y: 0,
304+
minH: 1,
305+
},
306+
}),
307+
],
308+
};
309+
310+
render(
311+
<OrganizationContext value={initialData.organization}>
312+
<MEPSettingProvider forceTransactions={false}>
313+
<Dashboard
314+
dashboard={dashboardWithOneWidget}
315+
isEditingDashboard={false}
316+
onUpdate={() => undefined}
317+
handleUpdateWidgetList={() => undefined}
318+
handleAddCustomWidget={() => undefined}
319+
widgetLimitReached={false}
320+
isEmbedded
321+
widgetLegendState={widgetLegendState}
322+
/>
323+
</MEPSettingProvider>
324+
</OrganizationContext>
325+
);
326+
327+
await screen.findByText('Test Widget');
328+
expect(screen.queryByLabelText('Widget actions')).not.toBeInTheDocument();
329+
});
330+
292331
describe('Issue Widgets', () => {
293332
beforeEach(() => {
294333
MemberListStore.init();

static/app/views/dashboards/dashboard.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ type Props = {
8181
widgetLegendState: WidgetLegendSelectionState;
8282
widgetLimitReached: boolean;
8383
handleChangeSplitDataset?: (widget: Widget, index: number) => void;
84+
isEmbedded?: boolean;
8485
isPreview?: boolean;
8586
newWidget?: Widget;
8687
newlyAddedWidget?: Widget;
@@ -104,6 +105,7 @@ function Dashboard({
104105
onUpdate,
105106
widgetLegendState,
106107
widgetLimitReached,
108+
isEmbedded,
107109
isPreview,
108110
newWidget,
109111
newlyAddedWidget,
@@ -426,6 +428,7 @@ function Dashboard({
426428
onEdit={handleEditWidget(index)}
427429
onDuplicate={handleDuplicateWidget(widget)}
428430
onSetTransactionsDataset={() => handleChangeSplitDataset(widget, index)}
431+
isEmbedded={isEmbedded}
429432
isPreview={isPreview}
430433
dashboardFilters={getDashboardFiltersFromURL(location) ?? dashboard.filters}
431434
dashboardPermissions={dashboard.permissions}

static/app/views/dashboards/detail.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -986,6 +986,7 @@ class DashboardDetail extends Component<Props, State> {
986986
onUpdate={this.onUpdateWidget}
987987
handleUpdateWidgetList={this.handleUpdateWidgetList}
988988
handleAddCustomWidget={this.handleAddCustomWidget}
989+
isEmbedded={this.isEmbedded}
989990
isPreview={this.isPreview}
990991
widgetLegendState={this.state.widgetLegendState}
991992
/>
@@ -1269,6 +1270,7 @@ class DashboardDetail extends Component<Props, State> {
12691270
onAddWidget={this.onAddWidget}
12701271
newWidget={newWidget}
12711272
onSetNewWidget={onSetNewWidget}
1273+
isEmbedded={this.isEmbedded}
12721274
isPreview={this.isPreview}
12731275
widgetLegendState={this.state.widgetLegendState}
12741276
onEditWidget={this.onEditWidget}

static/app/views/dashboards/sortableWidget.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ type Props = {
4040
dashboardCreator?: User;
4141
dashboardFilters?: DashboardFilters;
4242
dashboardPermissions?: DashboardPermissions;
43+
isEmbedded?: boolean;
4344
isMobile?: boolean;
4445
isPreview?: boolean;
4546
newlyAddedWidget?: Widget;
@@ -60,6 +61,7 @@ function SortableWidget(props: Props) {
6061
onEdit,
6162
onDuplicate,
6263
onSetTransactionsDataset,
64+
isEmbedded,
6365
isPreview,
6466
isMobile,
6567
windowWidth,
@@ -120,7 +122,7 @@ function SortableWidget(props: Props) {
120122
onEdit,
121123
onDuplicate,
122124
onSetTransactionsDataset,
123-
showContextMenu: true,
125+
showContextMenu: !isEmbedded,
124126
isPreview,
125127
index,
126128
dashboardFilters,

static/app/views/dashboards/widgetCard/index.tsx

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -315,17 +315,45 @@ function WidgetCard(props: Props) {
315315
<ErrorBoundary
316316
customComponent={() => <ErrorCard>{t('Error loading widget data')}</ErrorCard>}
317317
>
318-
<VisualizationWidget
319-
widget={widget}
320-
selection={selection}
321-
dashboardFilters={dashboardFilters}
322-
onDataFetched={onDataFetched}
323-
onWidgetTableSort={onWidgetTableSort}
324-
onWidgetTableResizeColumn={onWidgetTableResizeColumn}
325-
renderErrorMessage={renderErrorMessage}
326-
onDataFetchStart={onDataFetchStart}
327-
tableItemLimit={tableItemLimit}
328-
/>
318+
<VisuallyCompleteWithData
319+
id="DashboardList-FirstWidgetCard"
320+
hasData={
321+
((data?.tableResults?.length || data?.timeseriesResults?.length) ?? 0) > 0
322+
}
323+
disabled={Number(props.index) !== 0}
324+
>
325+
<WidgetFrame
326+
title={widget.title}
327+
description={widget.description}
328+
badgeProps={badges}
329+
warnings={warnings}
330+
actionsDisabled={actionsDisabled}
331+
error={widgetQueryError}
332+
actionsMessage={actionsMessage}
333+
actions={actions}
334+
onFullScreenViewClick={
335+
disableFullscreen
336+
? undefined
337+
: currentDashboardId
338+
? onFullScreenViewClick
339+
: undefined
340+
}
341+
borderless={props.borderless}
342+
revealTooltip={props.forceDescriptionTooltip ? 'always' : undefined}
343+
>
344+
<VisualizationWidget
345+
widget={widget}
346+
selection={selection}
347+
dashboardFilters={dashboardFilters}
348+
onDataFetched={onDataFetched}
349+
onWidgetTableSort={onWidgetTableSort}
350+
onWidgetTableResizeColumn={onWidgetTableResizeColumn}
351+
renderErrorMessage={renderErrorMessage}
352+
onDataFetchStart={onDataFetchStart}
353+
tableItemLimit={tableItemLimit}
354+
/>
355+
</WidgetFrame>
356+
</VisuallyCompleteWithData>
329357
</ErrorBoundary>
330358
);
331359
}

static/app/views/dashboards/widgetCard/visualizationWidget.tsx

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import {useReleaseStats} from 'sentry/utils/useReleaseStats';
66
import type {DashboardFilters, Widget} from 'sentry/views/dashboards/types';
77
import type {TabularColumn} from 'sentry/views/dashboards/widgets/common/types';
88
import {TimeSeriesWidgetVisualization} from 'sentry/views/dashboards/widgets/timeSeriesWidget/timeSeriesWidgetVisualization';
9-
import {Widget as CommonWidget} from 'sentry/views/dashboards/widgets/widget/widget';
109
import type {LoadableChartWidgetProps} from 'sentry/views/insights/common/components/widgets/types';
1110

1211
import {WidgetCardDataLoader} from './widgetCardDataLoader';
@@ -69,20 +68,18 @@ export function VisualizationWidget({
6968
const errorDisplay =
7069
renderErrorMessage && errorMessage ? renderErrorMessage(errorMessage) : null;
7170

71+
if (loading) {
72+
return <TimeSeriesWidgetVisualization.LoadingPlaceholder />;
73+
}
74+
if (errorDisplay) {
75+
return errorDisplay;
76+
}
77+
7278
return (
73-
<CommonWidget
74-
Title={<CommonWidget.WidgetTitle title={widget.title} />}
75-
Visualization={
76-
errorDisplay || loading ? (
77-
errorDisplay
78-
) : (
79-
<TimeSeriesWidgetVisualization
80-
plottables={plottables}
81-
releases={releases}
82-
showReleaseAs={showReleaseAs}
83-
/>
84-
)
85-
}
79+
<TimeSeriesWidgetVisualization
80+
plottables={plottables}
81+
releases={releases}
82+
showReleaseAs={showReleaseAs}
8683
/>
8784
);
8885
}}

0 commit comments

Comments
 (0)