diff --git a/apps/studio/components/interfaces/Support/IncidentAdmonition.tsx b/apps/studio/components/interfaces/Support/IncidentAdmonition.tsx index 129570067f1..e7caa76a708 100644 --- a/apps/studio/components/interfaces/Support/IncidentAdmonition.tsx +++ b/apps/studio/components/interfaces/Support/IncidentAdmonition.tsx @@ -54,7 +54,8 @@ const getStatusDescription = ( } export function IncidentAdmonition({ isActive }: IncidentAdmonitionProps) { - const { data: incidents, isLoading, isError } = useIncidentStatusQuery() + const { data: allStatusPageEvents = [], isLoading, isError } = useIncidentStatusQuery() + const incidents = allStatusPageEvents.filter((x) => x.impact !== 'maintenance') // Don't render anything while loading, on error, or if no incidents if (isLoading || isError || !incidents || incidents.length === 0) { diff --git a/apps/studio/components/interfaces/Support/SupportForm.utils.tsx b/apps/studio/components/interfaces/Support/SupportForm.utils.tsx index 853600d4d76..9889aad22ea 100644 --- a/apps/studio/components/interfaces/Support/SupportForm.utils.tsx +++ b/apps/studio/components/interfaces/Support/SupportForm.utils.tsx @@ -27,24 +27,23 @@ export const formatMessage = ({ message, attachments = [], error, - commit, - dashboardLogUrl, }: { message: string - attachments?: string[] + attachments?: Array error: string | null | undefined - commit: { commitSha: string; commitTime: string } | undefined - dashboardLogUrl?: string }) => { const errorString = error != null ? `\n\nError: ${error}` : '' const attachmentsString = attachments.length > 0 ? `\n\nAttachments:\n${attachments.join('\n')}` : '' - const commitString = - commit != undefined - ? `\n\n---\nSupabase Studio version: SHA ${commit.commitSha} deployed at ${commit.commitTime === 'unknown' ? 'unknown time' : dayjs(commit.commitTime).format('YYYY-MM-DD HH:mm:ss Z')}` - : '' - const logString = dashboardLogUrl ? `\nDashboard logs: ${dashboardLogUrl}` : '' - return `${message}${errorString}${attachmentsString}${commitString}${logString}` + return `${message}${errorString}${attachmentsString}` +} + +export const formatStudioVersion = (commit: { commitSha: string; commitTime: string }): string => { + const formattedTime = + commit.commitTime === 'unknown' + ? 'unknown time' + : dayjs(commit.commitTime).format('YYYY-MM-DD HH:mm:ss Z') + return `SHA ${commit.commitSha} deployed at ${formattedTime}` } export function getPageIcon(page: Page) { diff --git a/apps/studio/components/interfaces/Support/SupportFormV2.tsx b/apps/studio/components/interfaces/Support/SupportFormV2.tsx index 91959f7be6e..38e928934a7 100644 --- a/apps/studio/components/interfaces/Support/SupportFormV2.tsx +++ b/apps/studio/components/interfaces/Support/SupportFormV2.tsx @@ -32,6 +32,7 @@ import type { SupportFormValues } from './SupportForm.schema' import type { SupportFormActions, SupportFormState } from './SupportForm.state' import { formatMessage, + formatStudioVersion, getOrgSubscriptionPlan, NO_ORG_MARKER, NO_PROJECT_MARKER, @@ -141,8 +142,6 @@ export const SupportFormV2 = ({ form, initialError, state, dispatch }: SupportFo message: values.message, attachments, error: initialError, - commit, - dashboardLogUrl: dashboardLogUrl?.[0], }), verified: true, tags: ['dashboard-support-form'], @@ -155,6 +154,8 @@ export const SupportFormV2 = ({ form, initialError, state, dispatch }: SupportFo .map((x) => x.trim().replace(/ /g, '_').toLowerCase()) .join(';'), browserInformation: detectBrowser(), + dashboardLogs: dashboardLogUrl?.[0], + dashboardStudioVersion: commit ? formatStudioVersion(commit) : undefined, } if (values.projectRef !== NO_PROJECT_MARKER) { diff --git a/apps/studio/components/interfaces/Support/__tests__/SupportFormPage.test.tsx b/apps/studio/components/interfaces/Support/__tests__/SupportFormPage.test.tsx index 95aafd1b5b4..c64257e678d 100644 --- a/apps/studio/components/interfaces/Support/__tests__/SupportFormPage.test.tsx +++ b/apps/studio/components/interfaces/Support/__tests__/SupportFormPage.test.tsx @@ -86,9 +86,7 @@ const { mockCommitSha, mockCommitTime, mockUseDeploymentCommitQuery } = vi.hoist } }) -const supportVersionInfo = `\n\n---\nSupabase Studio version: SHA ${mockCommitSha} deployed at ${dayjs( - mockCommitTime -).format('YYYY-MM-DD HH:mm:ss Z')}` +const mockStudioVersion = `SHA ${mockCommitSha} deployed at ${dayjs(mockCommitTime).format('YYYY-MM-DD HH:mm:ss Z')}` vi.mock('react-inlinesvg', () => ({ __esModule: true, @@ -810,10 +808,9 @@ describe('SupportFormPage', () => { siteUrl: 'https://project-1.example.com', additionalRedirectUrls: 'https://project-1.example.com/callbacks', browserInformation: 'Chrome', + dashboardStudioVersion: mockStudioVersion, }) - const expectedMessage = - 'Requests return status 500 when calling the RPC endpoint' + supportVersionInfo - expect(payload.message).toBe(expectedMessage) + expect(payload.message).toBe('Requests return status 500 when calling the RPC endpoint') await waitFor(() => { expect(screen.getByRole('heading', { name: /support request sent/i })).toBeInTheDocument() @@ -901,9 +898,9 @@ describe('SupportFormPage', () => { siteUrl: 'https://project-2.supabase.dev', additionalRedirectUrls: 'https://project-2.supabase.dev/redirect', browserInformation: 'Chrome', + dashboardStudioVersion: mockStudioVersion, }) - const expectedMessage = 'MFA challenge fails with an unknown error code' + supportVersionInfo - expect(payload.message).toBe(expectedMessage) + expect(payload.message).toBe('MFA challenge fails with an unknown error code') await waitFor(() => { expect(screen.getByRole('heading', { name: /support request sent/i })).toBeInTheDocument() @@ -1002,10 +999,10 @@ describe('SupportFormPage', () => { siteUrl: 'https://project-3.apps.supabase.co', additionalRedirectUrls: 'https://project-3.apps.supabase.co/auth', browserInformation: 'Chrome', + dashboardStudioVersion: mockStudioVersion, }) expect(payload.message).toBe( - 'Connections time out after 30 seconds\n\nError: Connection timeout detected' + - supportVersionInfo + 'Connections time out after 30 seconds\n\nError: Connection timeout detected' ) await waitFor(() => { @@ -1381,10 +1378,9 @@ describe('SupportFormPage', () => { }) const payload = submitSpy.mock.calls[0]?.[0] - expect(payload.message).toContain('Navigation menu does not respond after latest deploy') - expect(payload.message).toMatch( - /Dashboard logs: https:\/\/storage\.example\.com\/signed\/.+\.json/ - ) + expect(payload.message).toBe('Navigation menu does not respond after latest deploy') + expect(payload.dashboardLogs).toMatch(/^https:\/\/storage\.example\.com\/signed\/.+\.json$/) + expect(payload.dashboardStudioVersion).toBe(mockStudioVersion) }) test('shows toast on submission error and allows form re-editing and resubmission', async () => { @@ -1455,10 +1451,9 @@ describe('SupportFormPage', () => { const payload = submitSpy.mock.calls[0]?.[0] expect(payload.subject).toBe('Cannot access settings') - expect(payload.message).toMatch( - 'Settings page shows 500 error - updated description' + supportVersionInfo - ) - expect(payload.message).toMatch(/Dashboard logs: https:\/\/storage\.example\.com\/.+\.json/) + expect(payload.message).toBe('Settings page shows 500 error - updated description') + expect(payload.dashboardLogs).toMatch(/^https:\/\/storage\.example\.com\/signed\/.+\.json$/) + expect(payload.dashboardStudioVersion).toBe(mockStudioVersion) await waitFor(() => { expect(toastSuccessSpy).toHaveBeenCalledWith('Support request sent. Thank you!') @@ -1684,9 +1679,9 @@ describe('SupportFormPage', () => { verified: true, tags: ['dashboard-support-form'], browserInformation: 'Chrome', + dashboardStudioVersion: mockStudioVersion, }) - const expectedMessage = 'I need help accessing my Supabase account' + supportVersionInfo - expect(payload.message).toBe(expectedMessage) + expect(payload.message).toBe('I need help accessing my Supabase account') await waitFor(() => { expect(screen.getByRole('heading', { name: /support request sent/i })).toBeInTheDocument() diff --git a/apps/studio/data/feedback/support-ticket-send.ts b/apps/studio/data/feedback/support-ticket-send.ts index 91ce4b2f932..bebf3168f4b 100644 --- a/apps/studio/data/feedback/support-ticket-send.ts +++ b/apps/studio/data/feedback/support-ticket-send.ts @@ -20,6 +20,8 @@ export type sendSupportTicketVariables = { siteUrl?: string additionalRedirectUrls?: string dashboardSentryIssueId?: string + dashboardLogs?: string + dashboardStudioVersion?: string } export async function sendSupportTicket({ @@ -36,6 +38,8 @@ export async function sendSupportTicket({ siteUrl, additionalRedirectUrls, dashboardSentryIssueId, + dashboardLogs, + dashboardStudioVersion, }: sendSupportTicketVariables) { const { data, error } = await post('/platform/feedback/send', { body: { @@ -54,6 +58,8 @@ export async function sendSupportTicket({ browserInformation, allowSupportAccess, dashboardSentryIssueId, + dashboardLogs, + dashboardStudioVersion, }, })