diff --git a/apps/studio/components/interfaces/Account/Preferences/DeleteAccountButton.tsx b/apps/studio/components/interfaces/Account/Preferences/DeleteAccountButton.tsx
index 91306f2d191..90e9c00edb2 100644
--- a/apps/studio/components/interfaces/Account/Preferences/DeleteAccountButton.tsx
+++ b/apps/studio/components/interfaces/Account/Preferences/DeleteAccountButton.tsx
@@ -5,6 +5,8 @@ import { useForm } from 'react-hook-form'
import { toast } from 'sonner'
import * as z from 'zod'
+import { LOCAL_STORAGE_KEYS } from 'common'
+import { NO_PROJECT_MARKER } from 'components/interfaces/Support/SupportForm.utils'
import { useSendSupportTicketMutation } from 'data/feedback/support-ticket-send'
import { useOrganizationsQuery } from 'data/organizations/organizations-query'
import { useProfile } from 'lib/profile'
@@ -26,7 +28,6 @@ import {
Input_Shadcn_,
Separator,
} from 'ui'
-import { LOCAL_STORAGE_KEYS } from 'common'
const setDeletionRequestFlag = () => {
const expiryDate = new Date()
@@ -92,7 +93,7 @@ export const DeleteAccountButton = () => {
severity: 'Low',
allowSupportAccess: false,
verified: true,
- projectRef: 'no-project',
+ projectRef: NO_PROJECT_MARKER,
}
submitSupportTicket(payload)
diff --git a/apps/studio/components/interfaces/Billing/Payment/PaymentMethods/CurrentPaymentMethod.tsx b/apps/studio/components/interfaces/Billing/Payment/PaymentMethods/CurrentPaymentMethod.tsx
index 1dd9201fcf3..5b5deccf3c0 100644
--- a/apps/studio/components/interfaces/Billing/Payment/PaymentMethods/CurrentPaymentMethod.tsx
+++ b/apps/studio/components/interfaces/Billing/Payment/PaymentMethods/CurrentPaymentMethod.tsx
@@ -3,6 +3,7 @@ import { CreditCardIcon } from 'lucide-react'
import Link from 'next/link'
import { useParams } from 'common'
+import { SupportLink } from 'components/interfaces/Support/SupportLink'
import ShimmeringLoader from 'components/ui/ShimmeringLoader'
import { useOrganizationPaymentMethodsQuery } from 'data/organizations/organization-payment-methods-query'
import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query'
@@ -66,11 +67,14 @@ const CurrentPaymentMethod = () => {
- For larger discounted credit packages, please{' '}
-
- reach out.
-
+ support
+
+ .
diff --git a/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/Subscription.tsx b/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/Subscription.tsx
index b6c3173f9e4..2e9a052a10e 100644
--- a/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/Subscription.tsx
+++ b/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/Subscription.tsx
@@ -1,7 +1,8 @@
-import { PermissionAction } from '@supabase/shared-types/out/constants'
+import { PermissionAction, SupportCategories } from '@supabase/shared-types/out/constants'
import Link from 'next/link'
import { useFlag, useParams } from 'common'
+import { SupportLink } from 'components/interfaces/Support/SupportLink'
import {
ScaffoldSection,
ScaffoldSectionContent,
@@ -109,15 +110,16 @@ const Subscription = () => {
variant="info"
title={`Unable to update plan from ${planName}`}
actions={[
-
-
-
- Contact support
-
-
-
,
+
+
+ Contact support
+
+ ,
]}
>
Please contact us if you'd like to change your plan.
diff --git a/apps/studio/components/interfaces/Organization/Documents/Documents.tsx b/apps/studio/components/interfaces/Organization/Documents/Documents.tsx
index 1b35df888dc..7190771e207 100644
--- a/apps/studio/components/interfaces/Organization/Documents/Documents.tsx
+++ b/apps/studio/components/interfaces/Organization/Documents/Documents.tsx
@@ -1,6 +1,6 @@
-import Link from 'next/link'
-
+import { SupportLink } from 'components/interfaces/Support/SupportLink'
import { ScaffoldContainer, ScaffoldDivider, ScaffoldSection } from 'components/layouts/Scaffold'
+import { InlineLinkClassName } from 'components/ui/InlineLink'
import { useCustomContent } from 'hooks/custom-content/useCustomContent'
import { Fragment } from 'react'
import { CustomDocument } from './CustomDocument'
@@ -59,10 +59,8 @@ const Documents = () => {
-
- Submit a support request
- {' '}
- if you require additional documents for financial or tax reasons, such as a W-9 form.
+ Submit a support request if
+ you require additional documents for financial or tax reasons, such as a W-9 form.
diff --git a/apps/studio/components/interfaces/Settings/Addons/Addons.tsx b/apps/studio/components/interfaces/Settings/Addons/Addons.tsx
index 0b200b9a810..79b65204074 100644
--- a/apps/studio/components/interfaces/Settings/Addons/Addons.tsx
+++ b/apps/studio/components/interfaces/Settings/Addons/Addons.tsx
@@ -5,6 +5,7 @@ import Image from 'next/image'
import Link from 'next/link'
import { useMemo } from 'react'
+import { SupportCategories } from '@supabase/shared-types/out/constants'
import { useFlag, useParams } from 'common'
import {
getAddons,
@@ -12,6 +13,7 @@ import {
} from 'components/interfaces/Billing/Subscription/Subscription.utils'
import { NoticeBar } from 'components/interfaces/DiskManagement/ui/NoticeBar'
import ProjectUpdateDisabledTooltip from 'components/interfaces/Organization/BillingSettings/ProjectUpdateDisabledTooltip'
+import { SupportLink } from 'components/interfaces/Support/SupportLink'
import { useIsProjectActive } from 'components/layouts/ProjectLayout/ProjectContext'
import {
ScaffoldContainer,
@@ -446,7 +448,7 @@ export const Addons = () => {
- Contact support
+ Contact support
@@ -487,11 +489,15 @@ export const Addons = () => {
Reach out to us via support if you're interested
-
Contact support
-
+
diff --git a/apps/studio/components/interfaces/Settings/Addons/PITRSidePanel.tsx b/apps/studio/components/interfaces/Settings/Addons/PITRSidePanel.tsx
index 172f0c9966c..8e655eeb145 100644
--- a/apps/studio/components/interfaces/Settings/Addons/PITRSidePanel.tsx
+++ b/apps/studio/components/interfaces/Settings/Addons/PITRSidePanel.tsx
@@ -7,6 +7,7 @@ import { toast } from 'sonner'
import { useParams } from 'common'
import { subscriptionHasHipaaAddon } from 'components/interfaces/Billing/Subscription/Subscription.utils'
+import { SupportLink } from 'components/interfaces/Support/SupportLink'
import { UpgradePlanButton } from 'components/ui/UpgradePlanButton'
import { useProjectSettingsV2Query } from 'data/config/project-settings-v2-query'
import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query'
@@ -258,7 +259,7 @@ const PITRSidePanel = () => {
- Contact support
+ Contact support
diff --git a/apps/studio/components/interfaces/Settings/Database/DiskSizeConfigurationModal.tsx b/apps/studio/components/interfaces/Settings/Database/DiskSizeConfigurationModal.tsx
index 58e6fd8d413..46e1bd6e09a 100644
--- a/apps/studio/components/interfaces/Settings/Database/DiskSizeConfigurationModal.tsx
+++ b/apps/studio/components/interfaces/Settings/Database/DiskSizeConfigurationModal.tsx
@@ -7,6 +7,7 @@ import { toast } from 'sonner'
import { number, object } from 'yup'
import { useParams } from 'common'
+import { SupportLink } from 'components/interfaces/Support/SupportLink'
import { useProjectDiskResizeMutation } from 'data/config/project-disk-resize-mutation'
import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query'
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
@@ -118,11 +119,15 @@ const DiskSizeConfigurationModal = ({
need more than this, contact us via support for help.
-
Contact support
-
+
diff --git a/apps/studio/components/interfaces/Settings/Database/SSLConfiguration.tsx b/apps/studio/components/interfaces/Settings/Database/SSLConfiguration.tsx
index 570e054c8cf..b7d786ce547 100644
--- a/apps/studio/components/interfaces/Settings/Database/SSLConfiguration.tsx
+++ b/apps/studio/components/interfaces/Settings/Database/SSLConfiguration.tsx
@@ -1,16 +1,17 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { template } from 'lodash'
import { Download, Loader2 } from 'lucide-react'
-import Link from 'next/link'
import { useEffect, useMemo, useState } from 'react'
import { toast } from 'sonner'
import { useParams } from 'common'
+import { SupportLink } from 'components/interfaces/Support/SupportLink'
import { ButtonTooltip } from 'components/ui/ButtonTooltip'
import { DocsButton } from 'components/ui/DocsButton'
import { FormHeader } from 'components/ui/Forms/FormHeader'
import { FormPanel } from 'components/ui/Forms/FormPanel'
import { FormSection, FormSectionContent, FormSectionLabel } from 'components/ui/Forms/FormSection'
+import { InlineLinkClassName } from 'components/ui/InlineLink'
import { useProjectSettingsV2Query } from 'data/config/project-settings-v2-query'
import { useSSLEnforcementQuery } from 'data/ssl-enforcement/ssl-enforcement-query'
import { useSSLEnforcementUpdateMutation } from 'data/ssl-enforcement/ssl-enforcement-update-mutation'
@@ -109,15 +110,8 @@ const SSLConfiguration = () => {
title="SSL enforcement was not updated successfully"
>
Please try updating again, or contact{' '}
-
- support
- {' '}
- if this error persists
+ support if this
+ error persists
)}
diff --git a/apps/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainConfig.tsx b/apps/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainConfig.tsx
index f3ee01982a2..06bd6f23fcd 100644
--- a/apps/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainConfig.tsx
+++ b/apps/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainConfig.tsx
@@ -1,13 +1,15 @@
import { AlertCircle } from 'lucide-react'
-import Link from 'next/link'
+import { SupportCategories } from '@supabase/shared-types/out/constants'
import { useFlag, useParams } from 'common'
+import { SupportLink } from 'components/interfaces/Support/SupportLink'
import { FormHeader } from 'components/ui/Forms/FormHeader'
+import { InlineLinkClassName } from 'components/ui/InlineLink'
import Panel from 'components/ui/Panel'
import UpgradeToPro from 'components/ui/UpgradeToPro'
import {
- type CustomDomainsData,
useCustomDomainsQuery,
+ type CustomDomainsData,
} from 'data/custom-domains/custom-domains-query'
import { useProjectAddonsQuery } from 'data/subscriptions/project-addons-query'
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
@@ -91,9 +93,12 @@ export const CustomDomainConfig = () => {
Failed to retrieve custom domain configuration. Please try again later or{' '}
-
+
contact support
-
+
.
diff --git a/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/DeployNewReplicaPanel.tsx b/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/DeployNewReplicaPanel.tsx
index e6f55fac5b2..3d975a76961 100644
--- a/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/DeployNewReplicaPanel.tsx
+++ b/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/DeployNewReplicaPanel.tsx
@@ -3,6 +3,7 @@ import Link from 'next/link'
import { useEffect, useMemo, useState } from 'react'
import { toast } from 'sonner'
+import { SupportCategories } from '@supabase/shared-types/out/constants'
import { useParams } from 'common'
import {
calculateIOPSPrice,
@@ -12,6 +13,7 @@ import {
DISK_PRICING,
DiskType,
} from 'components/interfaces/DiskManagement/ui/DiskManagement.constants'
+import { SupportLink } from 'components/interfaces/Support/SupportLink'
import { DocsButton } from 'components/ui/DocsButton'
import { useDiskAttributesQuery } from 'data/config/disk-attributes-query'
import { useEnablePhysicalBackupsMutation } from 'data/database/enable-physical-backups-mutation'
@@ -287,13 +289,16 @@ const DeployNewReplicaPanel = ({
-
Contact support
-
+
diff --git a/apps/studio/components/interfaces/SignIn/SessionTimeoutModal.tsx b/apps/studio/components/interfaces/SignIn/SessionTimeoutModal.tsx
index c4e05cf8bd5..ddca9ff4c61 100644
--- a/apps/studio/components/interfaces/SignIn/SessionTimeoutModal.tsx
+++ b/apps/studio/components/interfaces/SignIn/SessionTimeoutModal.tsx
@@ -1,9 +1,10 @@
import * as Sentry from '@sentry/nextjs'
import { useEffect } from 'react'
-import { InlineLink } from 'components/ui/InlineLink'
-import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal'
+import { InlineLink, InlineLinkClassName } from 'components/ui/InlineLink'
import { toast } from 'sonner'
+import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal'
+import { SupportLink } from '../Support/SupportLink'
interface SessionTimeoutModalProps {
visible: boolean
@@ -60,9 +61,12 @@ export const SessionTimeoutModal = ({
If none of these steps work, please{' '}
-
+
Contact support
-
+
.
diff --git a/apps/studio/components/interfaces/SignIn/SignInMfaForm.tsx b/apps/studio/components/interfaces/SignIn/SignInMfaForm.tsx
index 31e22f38b25..199cb417e00 100644
--- a/apps/studio/components/interfaces/SignIn/SignInMfaForm.tsx
+++ b/apps/studio/components/interfaces/SignIn/SignInMfaForm.tsx
@@ -8,6 +8,7 @@ import { useEffect, useState } from 'react'
import { SubmitHandler, useForm } from 'react-hook-form'
import z from 'zod'
+import { SupportCategories } from '@supabase/shared-types/out/constants'
import { useAuthError } from 'common'
import AlertError from 'components/ui/AlertError'
import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader'
@@ -17,6 +18,7 @@ import { useSignOut } from 'lib/auth'
import { getReturnToPath } from 'lib/gotrue'
import { Button, Form_Shadcn_, FormControl_Shadcn_, FormField_Shadcn_, Input_Shadcn_ } from 'ui'
import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
+import { SupportLink } from '../Support/SupportLink'
const schema = z.object({
code: z.string().min(1, 'MFA Code is required'),
@@ -200,14 +202,15 @@ export const SignInMfaForm = ({ context = 'sign-in' }: SignInMfaFormProps) => {
-
Reach out to us via support
-
+
diff --git a/apps/studio/components/interfaces/Storage/StorageBucketsError.tsx b/apps/studio/components/interfaces/Storage/StorageBucketsError.tsx
index 6105523fcca..a13720a5ff2 100644
--- a/apps/studio/components/interfaces/Storage/StorageBucketsError.tsx
+++ b/apps/studio/components/interfaces/Storage/StorageBucketsError.tsx
@@ -1,7 +1,8 @@
+import { SupportCategories } from '@supabase/shared-types/out/constants'
import { useParams } from 'common'
-import Link from 'next/link'
import type { ResponseError } from 'types'
import { Alert, Button } from 'ui'
+import { SupportLink } from '../Support/SupportLink'
export interface StorageBucketsErrorProps {
error: ResponseError
@@ -19,11 +20,15 @@ const StorageBucketsError = ({ error }: StorageBucketsErrorProps) => {
title="Failed to fetch buckets"
actions={[
-
Contact support
-
+
,
]}
>
diff --git a/apps/studio/components/interfaces/Support/CategoryAndSeverityInfo.tsx b/apps/studio/components/interfaces/Support/CategoryAndSeverityInfo.tsx
index ae10f3997b0..d8bc51dd936 100644
--- a/apps/studio/components/interfaces/Support/CategoryAndSeverityInfo.tsx
+++ b/apps/studio/components/interfaces/Support/CategoryAndSeverityInfo.tsx
@@ -22,6 +22,7 @@ import {
SEVERITY_OPTIONS,
} from './Support.constants'
import type { SupportFormValues } from './SupportForm.schema'
+import { NO_PROJECT_MARKER } from './SupportForm.utils'
interface CategoryAndSeverityInfoProps {
form: UseFormReturn
@@ -148,7 +149,7 @@ function SeveritySelector({ form }: SeveritySelectorProps) {
}
const IssueSuggestion = ({ category, projectRef }: { category: string; projectRef?: string }) => {
- const baseUrl = `/project/${projectRef === 'no-project' ? '_' : projectRef}`
+ const baseUrl = `/project/${projectRef === NO_PROJECT_MARKER ? '_' : projectRef}`
const className = 'col-span-2 mb-0'
diff --git a/apps/studio/components/interfaces/Support/DashboardLogsToggle.tsx b/apps/studio/components/interfaces/Support/DashboardLogsToggle.tsx
new file mode 100644
index 00000000000..02a97920497
--- /dev/null
+++ b/apps/studio/components/interfaces/Support/DashboardLogsToggle.tsx
@@ -0,0 +1,74 @@
+import { ChevronRight } from 'lucide-react'
+import { useMemo, useState } from 'react'
+import type { UseFormReturn } from 'react-hook-form'
+
+import {
+ Collapsible_Shadcn_,
+ CollapsibleContent_Shadcn_,
+ CollapsibleTrigger_Shadcn_,
+ FormField_Shadcn_,
+ Switch,
+} from 'ui'
+import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
+import type { SupportFormValues } from './SupportForm.schema'
+import { DASHBOARD_LOG_CATEGORIES, getSanitizedBreadcrumbs } from './dashboard-logs'
+
+interface DashboardLogsToggleProps {
+ form: UseFormReturn
+}
+
+export function DashboardLogsToggle({ form }: DashboardLogsToggleProps) {
+ const sanitizedLogJson = useMemo(() => JSON.stringify(getSanitizedBreadcrumbs(), null, 2), [])
+
+ const [isPreviewOpen, setIsPreviewOpen] = useState(false)
+
+ if (!DASHBOARD_LOG_CATEGORIES.includes(form.getValues('category'))) return
+
+ return (
+ (
+
+ Include dashboard activity log
+
+ }
+ description={
+
+
+ Share sanitized logs of recent dashboard actions to help reproduce the issue.
+
+
+
+
+ Preview log
+
+
+