From 13a3fcf85cbb9b2fa693288ed269aaea0dbe0021 Mon Sep 17 00:00:00 2001 From: edwardgou-sentry <83961295+edwardgou-sentry@users.noreply.github.com> Date: Tue, 24 Mar 2026 11:59:29 -0400 Subject: [PATCH 01/38] feat(dashboards): Redesign dashboard generation initial prompt step (#111377) - Removes the initial dashboard generation prompt modal - Adds `CreateFromSeerPrompt` component to handle initial prompt which displays as a full screen page --- static/app/actionCreators/modal.tsx | 12 -- .../modals/generateDashboardFromSeerModal.tsx | 113 ------------------ .../analytics/dashboardsAnalyticsEvents.tsx | 3 + .../app/views/dashboards/createFromSeer.tsx | 3 +- .../dashboards/createFromSeerLoading.tsx | 2 +- .../views/dashboards/createFromSeerPrompt.tsx | 105 ++++++++++++++++ static/app/views/dashboards/manage/index.tsx | 27 +++-- 7 files changed, 126 insertions(+), 139 deletions(-) delete mode 100644 static/app/components/modals/generateDashboardFromSeerModal.tsx create mode 100644 static/app/views/dashboards/createFromSeerPrompt.tsx diff --git a/static/app/actionCreators/modal.tsx b/static/app/actionCreators/modal.tsx index dbd04aef8f47fe..f8637acebbe97f 100644 --- a/static/app/actionCreators/modal.tsx +++ b/static/app/actionCreators/modal.tsx @@ -3,7 +3,6 @@ import type {CreateReleaseIntegrationModalOptions} from 'sentry/components/modal import type {DashboardWidgetQuerySelectorModalOptions} from 'sentry/components/modals/dashboardWidgetQuerySelectorModal'; import type {DataWidgetViewerModalOptions} from 'sentry/components/modals/dataWidgetViewerModal'; import type {SaveQueryModalProps} from 'sentry/components/modals/explore/saveQueryModal'; -import type {GenerateDashboardFromSeerModalProps} from 'sentry/components/modals/generateDashboardFromSeerModal'; import type {ImportDashboardFromFileModalProps} from 'sentry/components/modals/importDashboardFromFileModal'; import type {InsightChartModalOptions} from 'sentry/components/modals/insightChartModal'; import type {InviteRow} from 'sentry/components/modals/inviteMembersModal/types'; @@ -274,17 +273,6 @@ export async function openImportDashboardFromFileModal( }); } -export async function openGenerateDashboardFromSeerModal( - options: GenerateDashboardFromSeerModalProps -) { - const {default: Modal} = - await import('sentry/components/modals/generateDashboardFromSeerModal'); - - openModal(deps => , { - closeEvents: 'escape-key', - }); -} - export async function openReprocessEventModal({ onClose, ...options diff --git a/static/app/components/modals/generateDashboardFromSeerModal.tsx b/static/app/components/modals/generateDashboardFromSeerModal.tsx deleted file mode 100644 index 93d4d1da6b5fc4..00000000000000 --- a/static/app/components/modals/generateDashboardFromSeerModal.tsx +++ /dev/null @@ -1,113 +0,0 @@ -import {Fragment, useCallback, useState} from 'react'; -import type {Location} from 'history'; - -import {Button} from '@sentry/scraps/button'; -import {Flex} from '@sentry/scraps/layout'; -import {TextArea} from '@sentry/scraps/textarea'; - -import {addErrorMessage} from 'sentry/actionCreators/indicator'; -import type {ModalRenderProps} from 'sentry/actionCreators/modal'; -import {IconSeer} from 'sentry/icons'; -import {t} from 'sentry/locale'; -import type {Organization} from 'sentry/types/organization'; -import {getApiUrl} from 'sentry/utils/api/getApiUrl'; -import {fetchMutation} from 'sentry/utils/queryClient'; -import {normalizeUrl} from 'sentry/utils/url/normalizeUrl'; -import type {ReactRouter3Navigate} from 'sentry/utils/useNavigate'; - -export interface GenerateDashboardFromSeerModalProps { - location: Location; - navigate: ReactRouter3Navigate; - organization: Organization; -} - -function GenerateDashboardFromSeerModal({ - Header, - Body, - Footer, - closeModal, - organization, - location, - navigate, -}: ModalRenderProps & GenerateDashboardFromSeerModalProps) { - const [prompt, setPrompt] = useState(''); - const [isGenerating, setIsGenerating] = useState(false); - - const handleGenerate = useCallback(async () => { - if (!prompt.trim()) { - return; - } - - setIsGenerating(true); - - try { - const url = getApiUrl('/organizations/$organizationIdOrSlug/dashboards/generate/', { - path: { - organizationIdOrSlug: organization.slug, - }, - }); - const response = await fetchMutation<{run_id: string}>({ - url, - method: 'POST', - data: {prompt: prompt.trim()}, - }); - - const runId = response.run_id; - if (!runId) { - addErrorMessage(t('Failed to start dashboard generation')); - setIsGenerating(false); - return; - } - - closeModal(); - - navigate( - normalizeUrl({ - pathname: `/organizations/${organization.slug}/dashboards/new/from-seer/`, - query: {...location.query, seerRunId: String(runId)}, - }) - ); - } catch (error) { - setIsGenerating(false); - addErrorMessage(t('Failed to start dashboard generation')); - } - }, [prompt, organization.slug, location.query, closeModal, navigate]); - - return ( - -
-

{t('Create Dashboard with Agent')}

-
- -

{t('Describe the dashboard you would like to be generated for you.')}

-