feat: disable project homepage features (#37990)

* feat: disable logs features

* feat: disable project homepage features

* Minor nit fixes

* Fix TS

* Rename profile:update to profile:show_information

---------

Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
This commit is contained in:
Alaister YoungandJoshen Lim authored and GitHub committed 2025-08-18 15:59:24 +08:00
1 parent 71ba2126a5
commit be45baf6c4
10 files changed
+198 -98

No files matched your search

@@ -10,6 +10,7 @@ import { getKeys, useAPIKeysQuery } from 'data/api-keys/api-keys-query'
import { useJwtSecretUpdatingStatusQuery } from 'data/config/jwt-secret-updating-status-query'
import { useProjectSettingsV2Query } from 'data/config/project-settings-v2-query'
import { useAsyncCheckProjectPermissions } from 'hooks/misc/useCheckPermissions'
import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled'
import { Input, SimpleCodeBlock } from 'ui'
const generateInitSnippet = (endpoint: string) => ({
@@ -29,12 +30,20 @@ Future<void> main() async {
}`,
})
const APIKeys = () => {
export const APIKeys = () => {
const { ref: projectRef } = useParams()
const {
projectConnectionJavascriptExample: javascriptExampleEnabled,
projectConnectionDartExample: dartExampleEnabled,
} = useIsFeatureEnabled([
'project_connection:javascript_example',
'project_connection:dart_example',
])
const availableLanguages = [
{ name: 'Javascript', key: 'js' },
{ name: 'Dart', key: 'dart' },
...(javascriptExampleEnabled ? [{ name: 'Javascript', key: 'js' }] : []),
...(dartExampleEnabled ? [{ name: 'Dart', key: 'dart' }] : []),
]
const [selectedLanguage, setSelectedLanguage] = useState(availableLanguages[0])
@@ -78,7 +87,9 @@ const APIKeys = () => {
const apiUrl = `${protocol}://${endpoint ?? '-'}`
const clientInitSnippet: any = generateInitSnippet(apiUrl)
const selectedLanguageSnippet = clientInitSnippet[selectedLanguage.key] ?? 'No snippet available'
const selectedLanguageSnippet = !!selectedLanguage
? clientInitSnippet[selectedLanguage.key]
: 'No snippet available'
return (
<Panel
@@ -177,34 +188,34 @@ const APIKeys = () => {
}
/>
</Panel.Content>
<div className="border-t border-panel-border-interior-light dark:border-panel-border-interior-dark">
<div className="flex items-center bg-studio">
{availableLanguages.map((language) => {
const isSelected = selectedLanguage.key === language.key
return (
<div
key={language.key}
className={[
'px-3 py-1 text-sm cursor-pointer transition',
`${!isSelected ? 'bg-studio text-foreground-light' : 'bg-surface-100'}`,
].join(' ')}
onClick={() => setSelectedLanguage(language)}
>
{language.name}
</div>
)
})}
{availableLanguages.length > 0 && (
<div className="border-t border-panel-border-interior-light dark:border-panel-border-interior-dark">
<div className="flex items-center bg-studio">
{availableLanguages.map((language) => {
const isSelected = selectedLanguage.key === language.key
return (
<div
key={language.key}
className={[
'px-3 py-1 text-sm cursor-pointer transition',
`${!isSelected ? 'bg-studio text-foreground-light' : 'bg-surface-100'}`,
].join(' ')}
onClick={() => setSelectedLanguage(language)}
>
{language.name}
</div>
)
})}
</div>
<div className="bg-surface-100 px-4 py-6 min-h-[200px]">
<SimpleCodeBlock className={selectedLanguage.key}>
{selectedLanguageSnippet}
</SimpleCodeBlock>
</div>
</div>
<div className="bg-surface-100 px-4 py-6 min-h-[200px]">
<SimpleCodeBlock className={selectedLanguage.key}>
{selectedLanguageSnippet}
</SimpleCodeBlock>
</div>
</div>
)}
</>
)}
</Panel>
)
}
export default APIKeys
@@ -31,7 +31,7 @@ const Row = ({
</div>
)
const GetStartedHero = () => {
export const GetStartedHero = () => {
return (
<div className="w-full max-w-[500px] h-full pb-10 lg:pb-0 relative pointer-events-none">
<div
@@ -105,5 +105,3 @@ const GetStartedHero = () => {
</div>
)
}
export default GetStartedHero
@@ -7,10 +7,10 @@ import { EditorIndexPageLink } from 'data/prefetchers/project.$ref.editor'
import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled'
import { Auth, EdgeFunctions, Realtime, SqlEditor, Storage, TableEditor } from 'icons'
import { Button } from 'ui'
import APIKeys from './APIKeys'
import GetStartedHero from './GetStartedHero'
import { APIKeys } from './APIKeys'
import { GetStartedHero } from './GetStartedHero'
const NewProjectPanel = () => {
export const NewProjectPanel = () => {
const { ref } = useParams()
const {
@@ -261,5 +261,3 @@ const NewProjectPanel = () => {
</div>
)
}
export default NewProjectPanel
@@ -1,3 +1,2 @@
export { default as ClientLibrary } from './ClientLibrary'
export { default as ExampleProject } from './ExampleProject'
export { default as NewProjectPanel } from './NewProjectPanel/NewProjectPanel'
@@ -1,6 +1,7 @@
import { useQueryClient } from '@tanstack/react-query'
import { ArrowRight, Loader2 } from 'lucide-react'
import Link from 'next/link'
import { useMemo } from 'react'
import { useParams } from 'common'
import ClientLibrary from 'components/interfaces/Home/ClientLibrary'
@@ -10,6 +11,7 @@ import { DisplayApiSettings, DisplayConfigSettings } from 'components/ui/Project
import { invalidateProjectDetailsQuery } from 'data/projects/project-detail-query'
import { useProjectStatusQuery } from 'data/projects/project-status-query'
import { invalidateProjectsQuery } from 'data/projects/projects-query'
import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled'
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
import { PROJECT_STATUS } from 'lib/constants'
import { Badge, Button } from 'ui'
@@ -19,6 +21,21 @@ const BuildingState = () => {
const { data: project } = useSelectedProjectQuery()
const queryClient = useQueryClient()
const {
projectHomepageShowAllClientLibraries: showAllClientLibraries,
projectHomepageShowExamples: showExamples,
} = useIsFeatureEnabled([
'project_homepage:show_all_client_libraries',
'project_homepage:show_examples',
])
const clientLibraries = useMemo(() => {
if (showAllClientLibraries) {
return CLIENT_LIBRARIES
}
return CLIENT_LIBRARIES.filter((library) => library.language === 'JavaScript')
}, [showAllClientLibraries])
useProjectStatusQuery(
{ projectRef: ref },
{
@@ -125,21 +142,23 @@ const BuildingState = () => {
<h4 className="text-lg">Client libraries</h4>
</div>
<div className="grid grid-cols-2 gap-x-8 gap-y-8 md:gap-12 mx-6 mb-12 md:grid-cols-3">
{CLIENT_LIBRARIES.map((library) => (
{clientLibraries.map((library) => (
<ClientLibrary key={library.language} {...library} />
))}
</div>
</div>
<div className="space-y-8">
<div className="mx-6">
<h5>Example projects</h5>
{showExamples && (
<div className="space-y-8">
<div className="mx-6">
<h5>Example projects</h5>
</div>
<div className="mx-6 grid gap-2 md:gap-8 md:grid-cols-2 lg:grid-cols-3">
{EXAMPLE_PROJECTS.map((project) => (
<ExampleProject key={project.url} {...project} />
))}
</div>
</div>
<div className="mx-6 grid gap-2 md:gap-8 md:grid-cols-2 lg:grid-cols-3">
{EXAMPLE_PROJECTS.map((project) => (
<ExampleProject key={project.url} {...project} />
))}
</div>
</div>
)}
</div>
)}
</div>
+3 -3
View File
@@ -1,7 +1,7 @@
import { AccountConnections } from 'components/interfaces/Account/Preferences/AccountConnections'
import { AccountDeletion } from 'components/interfaces/Account/Preferences/AccountDeletion'
import { AccountIdentities } from 'components/interfaces/Account/Preferences/AccountIdentities'
import { AnalyticsSettings } from 'components/interfaces/Account/Preferences/AnalyticsSettings'
import { AccountConnections } from 'components/interfaces/Account/Preferences/AccountConnections'
import { ProfileInformation } from 'components/interfaces/Account/Preferences/ProfileInformation'
import { ThemeSettings } from 'components/interfaces/Account/Preferences/ThemeSettings'
import AccountLayout from 'components/layouts/AccountLayout/AccountLayout'
@@ -35,7 +35,7 @@ User.getLayout = (page) => (
export default User
const ProfileCard = () => {
const profileUpdateEnabled = useIsFeatureEnabled('profile:update')
const profileShowInformation = useIsFeatureEnabled('profile:show_information')
const { error, isLoading, isError, isSuccess } = useProfile()
return (
@@ -56,7 +56,7 @@ const ProfileCard = () => {
)}
{isSuccess && (
<>
{profileUpdateEnabled && isSuccess ? <ProfileInformation /> : null}
{profileShowInformation && isSuccess ? <ProfileInformation /> : null}
<AccountIdentities />
</>
)}
+7 -2
View File
@@ -47,6 +47,7 @@ import {
import { useProjectsQuery } from 'data/projects/projects-query'
import { useSendEventMutation } from 'data/telemetry/send-event-mutation'
import { useCheckPermissions } from 'hooks/misc/useCheckPermissions'
import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled'
import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage'
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
import { withAuth } from 'hooks/misc/withAuth'
@@ -136,6 +137,8 @@ const Wizard: NextPageWithLayout = () => {
''
)
const showAdvancedConfig = useIsFeatureEnabled('project_creation:show_advanced_config')
// This is to make the database.new redirect work correctly. The database.new redirect should be set to supabase.com/dashboard/new/last-visited-org
if (slug === 'last-visited-org') {
if (lastVisitedOrganization) {
@@ -303,7 +306,7 @@ const Wizard: NextPageWithLayout = () => {
dbRegion,
organizationSlug: organization,
},
{ enabled: currentOrg != null && !isManagedByVercel }
{ enabled: currentOrg !== null && !isManagedByVercel }
)
// [kevin] This will eventually all be provided by a new API endpoint to preview and validate project creation, this is just for kaizen now
@@ -908,7 +911,9 @@ const Wizard: NextPageWithLayout = () => {
)}
<SecurityOptions form={form} />
{!!availableOrioleVersion && <AdvancedConfiguration form={form} />}
{showAdvancedConfig && !!availableOrioleVersion && (
<AdvancedConfiguration form={form} />
)}
</>
)}
+64 -41
View File
@@ -1,11 +1,12 @@
import dayjs from 'dayjs'
import Link from 'next/link'
import { useEffect, useRef } from 'react'
import { useEffect, useMemo, useRef } from 'react'
import { useParams } from 'common'
import { ClientLibrary, ExampleProject, NewProjectPanel } from 'components/interfaces/Home'
import { ClientLibrary, ExampleProject } from 'components/interfaces/Home'
import { AdvisorWidget } from 'components/interfaces/Home/AdvisorWidget'
import { CLIENT_LIBRARIES, EXAMPLE_PROJECTS } from 'components/interfaces/Home/Home.constants'
import { NewProjectPanel } from 'components/interfaces/Home/NewProjectPanel/NewProjectPanel'
import { ProjectUsageSection } from 'components/interfaces/Home/ProjectUsageSection'
import { ServiceStatus } from 'components/interfaces/Home/ServiceStatus'
import DefaultLayout from 'components/layouts/DefaultLayout'
@@ -18,6 +19,7 @@ import { useBranchesQuery } from 'data/branches/branches-query'
import { useEdgeFunctionsQuery } from 'data/edge-functions/edge-functions-query'
import { useReadReplicasQuery } from 'data/read-replicas/replicas-query'
import { useTablesQuery } from 'data/tables/tables-query'
import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled'
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
import {
useIsOrioleDb,
@@ -48,6 +50,23 @@ const Home: NextPageWithLayout = () => {
const snap = useAppStateSnapshot()
const { ref, enableBranching } = useParams()
const {
projectHomepageShowAllClientLibraries: showAllClientLibraries,
projectHomepageShowInstanceSize: showInstanceSize,
projectHomepageShowExamples: showExamples,
} = useIsFeatureEnabled([
'project_homepage:show_all_client_libraries',
'project_homepage:show_instance_size',
'project_homepage:show_examples',
])
const clientLibraries = useMemo(() => {
if (showAllClientLibraries) {
return CLIENT_LIBRARIES
}
return CLIENT_LIBRARIES.filter((library) => library.language === 'JavaScript')
}, [showAllClientLibraries])
const hasShownEnableBranchingModalRef = useRef(false)
const isPaused = project?.status === PROJECT_STATUS.INACTIVE
const isNewProject = dayjs(project?.inserted_at).isAfter(dayjs().subtract(2, 'day'))
@@ -125,14 +144,16 @@ const Home: NextPageWithLayout = () => {
</TooltipContent>
</Tooltip>
)}
<ComputeBadgeWrapper
project={{
ref: project?.ref,
organization_slug: organization?.slug,
cloud_provider: project?.cloud_provider,
infra_compute_size: project?.infra_compute_size,
}}
/>
{showInstanceSize && (
<ComputeBadgeWrapper
project={{
ref: project?.ref,
organization_slug: organization?.slug,
cloud_provider: project?.cloud_provider,
infra_compute_size: project?.infra_compute_size,
}}
/>
)}
</div>
</div>
<div className="flex items-center">
@@ -221,42 +242,44 @@ const Home: NextPageWithLayout = () => {
<div className="space-y-8">
<h2 className="text-lg">Client libraries</h2>
<div className="grid grid-cols-2 gap-x-8 gap-y-8 md:gap-12 mb-12 md:grid-cols-3">
{CLIENT_LIBRARIES.map((library) => (
{clientLibraries.map((library) => (
<ClientLibrary key={library.language} {...library} />
))}
</div>
</div>
<div className="space-y-8">
<h4 className="text-lg">Example projects</h4>
<div className="flex justify-center">
<Tabs_Shadcn_ defaultValue="app" className="w-full">
<TabsList_Shadcn_ className="flex gap-4 mb-8">
<TabsTrigger_Shadcn_ value="app">App Frameworks</TabsTrigger_Shadcn_>
<TabsTrigger_Shadcn_ value="mobile">
Mobile Frameworks
</TabsTrigger_Shadcn_>
</TabsList_Shadcn_>
<TabsContent_Shadcn_ value="app">
<div className="grid gap-2 md:gap-8 md:grid-cols-2 lg:grid-cols-3">
{EXAMPLE_PROJECTS.filter((project) => project.type === 'app')
.sort((a, b) => a.title.localeCompare(b.title))
.map((project) => (
<ExampleProject key={project.url} {...project} />
))}
</div>
</TabsContent_Shadcn_>
<TabsContent_Shadcn_ value="mobile">
<div className="grid gap-2 md:gap-8 md:grid-cols-2 lg:grid-cols-3">
{EXAMPLE_PROJECTS.filter((project) => project.type === 'mobile')
.sort((a, b) => a.title.localeCompare(b.title))
.map((project) => (
<ExampleProject key={project.url} {...project} />
))}
</div>
</TabsContent_Shadcn_>
</Tabs_Shadcn_>
{showExamples && (
<div className="space-y-8">
<h4 className="text-lg">Example projects</h4>
<div className="flex justify-center">
<Tabs_Shadcn_ defaultValue="app" className="w-full">
<TabsList_Shadcn_ className="flex gap-4 mb-8">
<TabsTrigger_Shadcn_ value="app">App Frameworks</TabsTrigger_Shadcn_>
<TabsTrigger_Shadcn_ value="mobile">
Mobile Frameworks
</TabsTrigger_Shadcn_>
</TabsList_Shadcn_>
<TabsContent_Shadcn_ value="app">
<div className="grid gap-2 md:gap-8 md:grid-cols-2 lg:grid-cols-3">
{EXAMPLE_PROJECTS.filter((project) => project.type === 'app')
.sort((a, b) => a.title.localeCompare(b.title))
.map((project) => (
<ExampleProject key={project.url} {...project} />
))}
</div>
</TabsContent_Shadcn_>
<TabsContent_Shadcn_ value="mobile">
<div className="grid gap-2 md:gap-8 md:grid-cols-2 lg:grid-cols-3">
{EXAMPLE_PROJECTS.filter((project) => project.type === 'mobile')
.sort((a, b) => a.title.localeCompare(b.title))
.map((project) => (
<ExampleProject key={project.url} {...project} />
))}
</div>
</TabsContent_Shadcn_>
</Tabs_Shadcn_>
</div>
</div>
</div>
)}
</>
)}
</div>
@@ -5,5 +5,14 @@
"logs:collections": true,
"profile:show_email": true,
"profile:update": true
"profile:show_information": true,
"project_connection:javascript_example": true,
"project_connection:dart_example": true,
"project_creation:show_advanced_config": true,
"project_homepage:show_all_client_libraries": true,
"project_homepage:show_instance_size": true,
"project_homepage:show_examples": true
}
@@ -19,11 +19,49 @@
"type": "boolean",
"description": "Show the user's email address in the toolbar"
},
"profile:update": {
"profile:show_information": {
"type": "boolean",
"description": "Allow the user to change their profile information (first name, last name)"
"description": "Shows the user's profile information (first name, last name) in account preferences"
},
"project_connection:javascript_example": {
"type": "boolean",
"description": "Show the javascript example in the project connection settings"
},
"project_connection:dart_example": {
"type": "boolean",
"description": "Show the dart example in the project connection settings"
},
"project_creation:show_advanced_config": {
"type": "boolean",
"description": "Show the advanced configuration option in the project creation flow"
},
"project_homepage:show_instance_size": {
"type": "boolean",
"description": "Show the instance size badge in the project homepage"
},
"project_homepage:show_examples": {
"type": "boolean",
"description": "Show the example projects in the project homepage"
},
"project_homepage:show_all_client_libraries": {
"type": "boolean",
"description": "Show all client libraries examples in the project homepage. When false, all client library examples will be hidden except the JavaScript client library."
}
},
"required": ["profile:show_email", "profile:update", "logs:templates", "logs:collections"],
"required": [
"profile:show_email",
"profile:show_information",
"logs:templates",
"logs:collections",
"project_creation:show_advanced_config",
"project_homepage:show_instance_size",
"project_homepage:show_examples",
"project_homepage:show_all_client_libraries",
"project_connection:javascript_example",
"project_connection:dart_example"
],
"additionalProperties": false
}