From 3395a4765e9288f3798fba61057b145c89173777 Mon Sep 17 00:00:00 2001 From: Dominik Buszowiecki Date: Wed, 8 Oct 2025 16:20:51 -0400 Subject: [PATCH 1/2] add create link button in dashboards edit view --- static/app/actionCreators/modal.tsx | 12 ++++++++++ .../views/dashboards/createLimitWrapper.tsx | 9 +++++++- .../components/visualize/index.tsx | 23 +++++++++++++++---- .../visualize/visualizeGhostField.tsx | 3 +-- 4 files changed, 40 insertions(+), 7 deletions(-) diff --git a/static/app/actionCreators/modal.tsx b/static/app/actionCreators/modal.tsx index 9c0b7c26b690b7..ecfcd82d0ad93d 100644 --- a/static/app/actionCreators/modal.tsx +++ b/static/app/actionCreators/modal.tsx @@ -11,6 +11,7 @@ import type {PrivateGamingSdkAccessModalProps} from 'sentry/components/modals/pr import type {ReprocessEventModalOptions} from 'sentry/components/modals/reprocessEventModal'; import type {TokenRegenerationConfirmationModalProps} from 'sentry/components/modals/tokenRegenerationConfirmationModal'; import type {AddToDashboardModalProps} from 'sentry/components/modals/widgetBuilder/addToDashboardModal'; +import type {LinkToDashboardModalProps} from 'sentry/components/modals/widgetBuilder/linkToDashboardModal'; import type {OverwriteWidgetModalProps} from 'sentry/components/modals/widgetBuilder/overwriteWidgetModal'; import type {WidgetViewerModalOptions} from 'sentry/components/modals/widgetViewerModal'; import type {ConsoleModalProps} from 'sentry/components/onboarding/consoleModal'; @@ -278,6 +279,17 @@ export async function openAddToDashboardModal(options: AddToDashboardModalProps) }); } +export async function openLinkToDashboardModal(options: LinkToDashboardModalProps) { + const {LinkToDashboardModal, modalCss} = await import( + 'sentry/components/modals/widgetBuilder/linkToDashboardModal' + ); + + openModal(deps => , { + closeEvents: 'escape-key', + modalCss, + }); +} + export async function openImportDashboardFromFileModal( options: ImportDashboardFromFileModalProps ) { diff --git a/static/app/views/dashboards/createLimitWrapper.tsx b/static/app/views/dashboards/createLimitWrapper.tsx index 82ed78fd4c7c53..8b7095193d35a0 100644 --- a/static/app/views/dashboards/createLimitWrapper.tsx +++ b/static/app/views/dashboards/createLimitWrapper.tsx @@ -1,5 +1,12 @@ import HookOrDefault from 'sentry/components/hookOrDefault'; +export type DashboardCreateLimitWrapperResult = { + dashboardsLimit: number; + hasReachedDashboardLimit: boolean; + isLoading: boolean; + limitMessage: string | null; +}; + export const DashboardCreateLimitWrapper = HookOrDefault({ hookName: 'component:dashboards-limit-provider', defaultComponent: ({children}) => @@ -9,6 +16,6 @@ export const DashboardCreateLimitWrapper = HookOrDefault({ dashboardsLimit: 0, isLoading: false, limitMessage: null, - }) + } satisfies DashboardCreateLimitWrapperResult) : children, }); diff --git a/static/app/views/dashboards/widgetBuilder/components/visualize/index.tsx b/static/app/views/dashboards/widgetBuilder/components/visualize/index.tsx index 0eb644c12d35cd..94ec5b182c17cc 100644 --- a/static/app/views/dashboards/widgetBuilder/components/visualize/index.tsx +++ b/static/app/views/dashboards/widgetBuilder/components/visualize/index.tsx @@ -5,6 +5,7 @@ import {css} from '@emotion/react'; import styled from '@emotion/styled'; import cloneDeep from 'lodash/cloneDeep'; +import {openLinkToDashboardModal} from 'sentry/actionCreators/modal'; import {Tag, type TagProps} from 'sentry/components/core/badge/tag'; import {Button} from 'sentry/components/core/button'; import {CompactSelect} from 'sentry/components/core/compactSelect'; @@ -13,7 +14,7 @@ import {Input} from 'sentry/components/core/input'; import {Radio} from 'sentry/components/core/radio'; import {RadioLineItem} from 'sentry/components/forms/controls/radioGroup'; import FieldGroup from 'sentry/components/forms/fieldGroup'; -import {IconDelete} from 'sentry/icons'; +import {IconDelete, IconLink} from 'sentry/icons'; import {t, tct} from 'sentry/locale'; import {space} from 'sentry/styles/space'; import type {SelectValue} from 'sentry/types/core'; @@ -34,6 +35,7 @@ import useCustomMeasurements from 'sentry/utils/useCustomMeasurements'; import useOrganization from 'sentry/utils/useOrganization'; import useTags from 'sentry/utils/useTags'; import {getDatasetConfig} from 'sentry/views/dashboards/datasetConfig/base'; +import {useHasDrillDownFlows} from 'sentry/views/dashboards/hooks/useHasDrillDownFlows'; import {DisplayType, WidgetType} from 'sentry/views/dashboards/types'; import {SectionHeader} from 'sentry/views/dashboards/widgetBuilder/components/common/sectionHeader'; import SortableVisualizeFieldWrapper from 'sentry/views/dashboards/widgetBuilder/components/common/sortableFieldWrapper'; @@ -272,6 +274,7 @@ function Visualize({error, setError}: VisualizeProps) { state.displayType !== DisplayType.TABLE && state.displayType !== DisplayType.BIG_NUMBER; const isBigNumberWidget = state.displayType === DisplayType.BIG_NUMBER; + const isTableWidget = state.displayType === DisplayType.TABLE; const {tags: numericSpanTags} = useTraceItemTags('number'); const {tags: stringSpanTags} = useTraceItemTags('string'); @@ -372,6 +375,7 @@ function Visualize({error, setError}: VisualizeProps) { const hasExploreEquations = organization.features.includes( 'visibility-explore-equations' ); + const hasDrillDownFlows = useHasDrillDownFlows(); return ( @@ -776,7 +780,20 @@ function Visualize({error, setError}: VisualizeProps) { }} /> )} - } + aria-label={t('Link field')} + size="zero" + onClick={() => { + openLinkToDashboardModal({ + source, + }); + }} + /> + )} +