Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
Original file line number Diff line number Diff line change
Expand Up @@ -684,7 +684,7 @@ export function IconUI({ width = 16, height = 16, className }: HomeMenuIcon) {
height="14.72"
rx="1.92"
stroke="currentColor"
stroke-width="1.28"
strokeWidth="1.28"
/>
<path
d="M8.56519 4.69238H9.74564V8.94966C9.74564 9.41632 9.63534 9.82678 9.41473 10.181C9.19625 10.5353 8.88867 10.8121 8.492 11.0115C8.09534 11.2087 7.63185 11.3074 7.10155 11.3074C6.56913 11.3074 6.10458 11.2087 5.70791 11.0115C5.31125 10.8121 5.00367 10.5353 4.78519 10.181C4.5667 9.82678 4.45746 9.41632 4.45746 8.94966V4.69238H5.63791V8.85102C5.63791 9.12253 5.69731 9.36435 5.81609 9.57647C5.937 9.7886 6.1067 9.95511 6.32519 10.076C6.54367 10.1948 6.80246 10.2542 7.10155 10.2542C7.40064 10.2542 7.65943 10.1948 7.87791 10.076C8.09852 9.95511 8.26822 9.7886 8.387 9.57647C8.50579 9.36435 8.56519 9.12253 8.56519 8.85102V4.69238Z"
Expand Down
28 changes: 14 additions & 14 deletions apps/studio/components/interfaces/App/CommandMenu/Support.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { LifeBuoy } from 'lucide-react'
import { LifeBuoy, Activity } from 'lucide-react'
import { useMemo } from 'react'

import { IS_PLATFORM } from 'common'
Expand All @@ -10,26 +10,26 @@ const useSupportCommands = () => {
const commands = useMemo(
() =>
[
{
id: 'support',
name: 'Support',
route: 'https://www.supabase.com/support',
icon: () => <LifeBuoy />,
},
{
id: 'system-status',
name: 'System Status',
value: 'Support: System Status',
name: 'View system status',
value: 'Support: View system status',
route: 'https://status.supabase.com',
icon: () => <Activity />,
},
{
id: 'discord-community',
name: 'Ask Discord community',
value: 'Support: Ask Discord community',
route: 'https://discord.supabase.com',
icon: () => <LifeBuoy />,
},
{
id: 'github-discussions',
name: 'GitHub Discussions',
value: 'Support: GitHub Discussions',
route: 'https://github.com/orgs/supabase/discussions',
id: 'support-team',
name: 'Contact support',
value: 'Support: Contact support',
route: 'https://www.supabase.com/support',
icon: () => <LifeBuoy />,
defaultHidden: true,
},
] as Array<ICommand>,
[]
Expand Down
17 changes: 12 additions & 5 deletions apps/studio/components/interfaces/Auth/AuthTemplatesValidation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ const CONFIRMATION: FormSchema = {
$schema: JSON_SCHEMA_VERSION,
id: 'CONFIRMATION',
type: 'object',
title: 'Confirm signup',
title: 'Confirm sign up',
purpose: 'Email verification for new user registrations',
properties: {
MAILER_SUBJECTS_CONFIRMATION: {
title: 'Subject heading',
Expand All @@ -20,7 +21,7 @@ const CONFIRMATION: FormSchema = {
descriptionOptional: 'HTML body of your email',
type: 'code',
description: `
- \`{{ .ConfirmationURL }}\` : URL to confirm the e-mail address for the new account
- \`{{ .ConfirmationURL }}\` : URL to confirm the email address for the new account
- \`{{ .Token }}\` : The 6-digit numeric email OTP
- \`{{ .TokenHash }}\` : The hashed token used in the URL
- \`{{ .SiteURL }}\` : The URL of the site
Expand All @@ -45,6 +46,7 @@ const INVITE: FormSchema = {
id: 'INVITE',
type: 'object',
title: 'Invite user',
purpose: "Allows administrators to invite users who don't have accounts yet",
properties: {
MAILER_SUBJECTS_INVITE: {
title: 'Subject heading',
Expand Down Expand Up @@ -79,7 +81,8 @@ const MAGIC_LINK: FormSchema = {
$schema: JSON_SCHEMA_VERSION,
id: 'MAGIC_LINK',
type: 'object',
title: 'Magic Link',
title: 'Magic link',
purpose: 'Passwordless login using email links',
properties: {
MAILER_SUBJECTS_MAGIC_LINK: {
title: 'Subject heading',
Expand Down Expand Up @@ -114,7 +117,8 @@ const EMAIL_CHANGE: FormSchema = {
$schema: JSON_SCHEMA_VERSION,
id: 'EMAIL_CHANGE',
type: 'object',
title: 'Change Email Address',
title: 'Change email address',
purpose: 'Verification for email address changes',
properties: {
MAILER_SUBJECTS_EMAIL_CHANGE: {
title: 'Subject heading',
Expand Down Expand Up @@ -150,7 +154,8 @@ const RECOVERY: FormSchema = {
$schema: JSON_SCHEMA_VERSION,
id: 'RECOVERY',
type: 'object',
title: 'Reset Password',
title: 'Reset password',
purpose: 'Password recovery flow for users who forgot their password',
properties: {
MAILER_SUBJECTS_RECOVERY: {
title: 'Subject heading',
Expand Down Expand Up @@ -185,6 +190,8 @@ const REAUTHENTICATION: FormSchema = {
id: 'REAUTHENTICATION',
type: 'object',
title: 'Reauthentication',
purpose:
'Additional verification for sensitive actions (like changing password, deleting account)',
properties: {
MAILER_SUBJECTS_REAUTHENTICATION: {
title: 'Subject heading',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,28 @@ import Link from 'next/link'
import { useParams } from 'common'
import { InlineLink } from 'components/ui/InlineLink'
import { DOCS_URL } from 'lib/constants'
import {
AlertDescription_Shadcn_,
AlertTitle_Shadcn_,
Alert_Shadcn_,
Button,
WarningIcon,
} from 'ui'
import { Button } from 'ui'
import { Admonition } from 'ui-patterns/admonition'

export function EmailRateLimitsAlert() {
const { ref } = useParams()

return (
<Alert_Shadcn_ variant="warning">
<WarningIcon />
<AlertTitle_Shadcn_>Email rate-limits and restrictions</AlertTitle_Shadcn_>
<AlertDescription_Shadcn_>
You're using the built-in email service. The service has rate limits and it's not meant to
be used for production apps. Check the{' '}
<Admonition
type="warning"
title="Set up custom SMTP"
className="bg-warning-200 border-warning-400"
>
<p>
You’re using the built-in email service. This service has rate limits and is not meant to be
used for production apps.{' '}
<InlineLink href={`${DOCS_URL}/guides/platform/going-into-prod#auth-rate-limits`}>
documentation
Learn more
</InlineLink>{' '}
for an up-to-date information on the current rate limits.
</AlertDescription_Shadcn_>
<AlertDescription_Shadcn_ className="mt-2">
<Button asChild type="default">
<Link href={`/project/${ref}/auth/smtp`}>Set up custom SMTP server</Link>
</Button>
</AlertDescription_Shadcn_>
</Alert_Shadcn_>
</p>
<Button asChild type="default" className="mt-2">
<Link href={`/project/${ref}/auth/smtp`}>Set up SMTP</Link>
</Button>
</Admonition>
)
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,26 @@
import { useParams } from 'common'
import { useIsSecurityNotificationsEnabled } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext'
import { ScaffoldSection } from 'components/layouts/Scaffold'
import AlertError from 'components/ui/AlertError'
import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader'
import { useAuthConfigQuery } from 'data/auth/auth-config-query'
import { Card, Tabs_Shadcn_, TabsContent_Shadcn_, TabsList_Shadcn_, TabsTrigger_Shadcn_ } from 'ui'
import { ChevronRight } from 'lucide-react'
import Link from 'next/link'
import {
Card,
CardContent,
Tabs_Shadcn_,
TabsContent_Shadcn_,
TabsList_Shadcn_,
TabsTrigger_Shadcn_,
} from 'ui'
import { TEMPLATES_SCHEMAS } from '../AuthTemplatesValidation'
import EmailRateLimitsAlert from '../EmailRateLimitsAlert'
import { slugifyTitle } from './EmailTemplates.utils'
import TemplateEditor from './TemplateEditor'

export const EmailTemplates = () => {
const isSecurityNotificationsEnabled = useIsSecurityNotificationsEnabled()
const { ref: projectRef } = useParams()
const {
data: authConfig,
Expand All @@ -23,7 +36,7 @@ export const EmailTemplates = () => {
(!authConfig.SMTP_HOST || !authConfig.SMTP_USER || !authConfig.SMTP_PASS)

return (
<div className="w-full">
<ScaffoldSection isFullWidth className="!pt-0">
{isError && (
<AlertError
className="mt-12"
Expand All @@ -43,32 +56,59 @@ export const EmailTemplates = () => {
<EmailRateLimitsAlert />
</div>
) : null}
<Card>
<Tabs_Shadcn_ defaultValue={TEMPLATES_SCHEMAS[0].title.trim().replace(/\s+/g, '-')}>
<TabsList_Shadcn_ className="pt-2 px-6 gap-5 mb-0 overflow-x-scroll no-scrollbar mb-4">
{TEMPLATES_SCHEMAS.map((template) => {
return (
<TabsTrigger_Shadcn_
key={`${template.id}`}
value={template.title.trim().replace(/\s+/g, '-')}
>
{template.title}
</TabsTrigger_Shadcn_>
)
})}
</TabsList_Shadcn_>
{isSecurityNotificationsEnabled ? (
<Card>
{TEMPLATES_SCHEMAS.map((template) => {
const panelId = template.title.trim().replace(/\s+/g, '-')
const templateSlug = slugifyTitle(template.title)
return (
<TabsContent_Shadcn_ key={panelId} value={panelId} className="mt-0">
<TemplateEditor key={template.title} template={template} />
</TabsContent_Shadcn_>
<CardContent key={`${template.id}`} className="p-0">
<Link
href={`/project/${projectRef}/auth/templates/${templateSlug}`}
className="flex items-center justify-between hover:bg-surface-200 transition-colors py-4 px-6 w-full h-full"
>
<div className="flex flex-col">
<h3 className="text-sm text-foreground">{template.title}</h3>
{template.purpose && (
<p className="text-sm text-foreground-lighter">{template.purpose}</p>
)}
</div>
<ChevronRight
size={16}
className="text-foreground-muted group-hover:text-foreground transition-colors"
/>
</Link>
</CardContent>
)
})}
</Tabs_Shadcn_>
</Card>
</Card>
) : (
<Card>
<Tabs_Shadcn_ defaultValue={slugifyTitle(TEMPLATES_SCHEMAS[0].title)}>
<TabsList_Shadcn_ className="pt-2 px-6 gap-5 mb-0 overflow-x-scroll no-scrollbar mb-4">
{TEMPLATES_SCHEMAS.map((template) => {
return (
<TabsTrigger_Shadcn_
key={`${template.id}`}
value={slugifyTitle(template.title)}
>
{template.title}
</TabsTrigger_Shadcn_>
)
})}
</TabsList_Shadcn_>
{TEMPLATES_SCHEMAS.map((template) => {
const panelId = slugifyTitle(template.title)
return (
<TabsContent_Shadcn_ key={panelId} value={panelId} className="mt-0">
<TemplateEditor key={template.title} template={template} />
</TabsContent_Shadcn_>
)
})}
</Tabs_Shadcn_>
</Card>
)}
</div>
)}
</div>
</ScaffoldSection>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* Convert template title to URL-friendly slug
* Shared function to ensure slug matching works correctly across multiple files
* Necessary because TEMPLATES_SCHEMAS does not provide a slug for each template
*/
export const slugifyTitle = (title: string) => {
return title.trim().replace(/\s+/g, '-').toLowerCase()
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,11 @@ export const useCloudMarketplaceOnboardingInfoQuery = <TData = CloudMarketplaceO
> = {}
) => {
const { profile } = useProfile()
return useQuery<CloudMarketplaceOnboardingInfo, CloudMarketplaceOnboardingInfoError, TData>(
cloudMarketplaceKeys.onboardingInfo(buyerId),
({ signal }) => getCloudMarketplaceOnboardingInfo({ buyerId }, signal),
{ enabled: enabled && profile !== undefined, ...options, staleTime: 30 * 60 * 1000 }
)
return useQuery<CloudMarketplaceOnboardingInfo, CloudMarketplaceOnboardingInfoError, TData>({
queryKey: cloudMarketplaceKeys.onboardingInfo(buyerId),
queryFn: ({ signal }) => getCloudMarketplaceOnboardingInfo({ buyerId }, signal),
enabled: enabled && profile !== undefined,
...options,
staleTime: 30 * 60 * 1000,
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ export const HeaderBanner = ({
</span>
</div>
{link && (
<a
<Link
href={link}
className={cn(
'lg:block hidden',
Expand All @@ -108,7 +108,7 @@ export const HeaderBanner = ({
)}
>
View Details
</a>
</Link>
)}
</div>
</motion.div>
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { UseFormReturn } from 'react-hook-form'
import { DocsButton } from 'components/ui/DocsButton'
import Panel from 'components/ui/Panel'
import { DOCS_URL } from 'lib/constants'
import { CreateProjectForm } from 'pages/new/[slug]'
import {
Badge,
cn,
Expand All @@ -19,6 +18,7 @@ import {
} from 'ui'
import { Admonition } from 'ui-patterns'
import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
import { CreateProjectForm } from './ProjectCreation.schema'

interface AdvancedConfigurationProps {
form: UseFormReturn<CreateProjectForm>
Expand Down
Loading
Loading