diff --git a/apps/studio/components/grid/components/footer/pagination/Pagination.tsx b/apps/studio/components/grid/components/footer/pagination/Pagination.tsx index ed6472e9ba0c9..8c0ff3af65754 100644 --- a/apps/studio/components/grid/components/footer/pagination/Pagination.tsx +++ b/apps/studio/components/grid/components/footer/pagination/Pagination.tsx @@ -149,6 +149,7 @@ const Pagination = () => { <>
+ {authenticationSignInProviders && ( + + )}
{isActive ? (
diff --git a/apps/studio/components/interfaces/Connect/Connect.constants.ts b/apps/studio/components/interfaces/Connect/Connect.constants.ts index 926d2151ce25b..80f82d9560ab9 100644 --- a/apps/studio/components/interfaces/Connect/Connect.constants.ts +++ b/apps/studio/components/interfaces/Connect/Connect.constants.ts @@ -64,6 +64,10 @@ export type ConnectionType = { label: string guideLink?: string children: ConnectionType[] + files?: { + name: string + content: string + }[] } export const FRAMEWORKS: ConnectionType[] = [ diff --git a/apps/studio/components/interfaces/Connect/Connect.tsx b/apps/studio/components/interfaces/Connect/Connect.tsx index 6d3065c670a87..cbbcd64a943b6 100644 --- a/apps/studio/components/interfaces/Connect/Connect.tsx +++ b/apps/studio/components/interfaces/Connect/Connect.tsx @@ -9,6 +9,7 @@ import { ButtonTooltip } from 'components/ui/ButtonTooltip' import Panel from 'components/ui/Panel' import { getKeys, useAPIKeysQuery } from 'data/api-keys/api-keys-query' import { useProjectSettingsV2Query } from 'data/config/project-settings-v2-query' +import { useCustomContent } from 'hooks/custom-content/useCustomContent' import { useAsyncCheckProjectPermissions } from 'hooks/misc/useCheckPermissions' import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { PROJECT_STATUS } from 'lib/constants' @@ -30,20 +31,31 @@ import { } from 'ui' import { CONNECTION_TYPES, ConnectionType, FRAMEWORKS, MOBILES, ORMS } from './Connect.constants' import { getContentFilePath } from './Connect.utils' -import ConnectDropdown from './ConnectDropdown' -import ConnectTabContent from './ConnectTabContent' +import { ConnectDropdown } from './ConnectDropdown' +import { ConnectTabContent } from './ConnectTabContent' +import { ConnectTabContentCustom } from './ConnectTabContentCustom' export const Connect = () => { const { ref: projectRef } = useParams() const { data: selectedProject } = useSelectedProjectQuery() const isActiveHealthy = selectedProject?.status === PROJECT_STATUS.ACTIVE_HEALTHY + const { connectFrameworks } = useCustomContent(['connect:frameworks']) + const connectionTypes = !connectFrameworks + ? CONNECTION_TYPES + : [ + { key: 'direct', label: 'Connection String', obj: [] }, + connectFrameworks, + { key: 'orms', label: 'ORMs', obj: ORMS }, + ] + const frameworks = !connectFrameworks ? FRAMEWORKS : connectFrameworks.obj + const [showConnect, setShowConnect] = useQueryState( 'showConnect', parseAsBoolean.withDefault(false) ) - const [connectionObject, setConnectionObject] = useState(FRAMEWORKS) + const [connectionObject, setConnectionObject] = useState(frameworks) const [selectedParent, setSelectedParent] = useState(connectionObject[0].key) // aka nextjs const [selectedChild, setSelectedChild] = useState( connectionObject.find((item) => item.key === selectedParent)?.children[0]?.key ?? '' @@ -54,6 +66,8 @@ export const Connect = () => { ?.children.find((child) => child.key === selectedChild)?.children[0]?.key || '' ) + const isFrameworkSelected = frameworks.some((x) => x.key === selectedParent) + const { data: settings } = useProjectSettingsV2Query({ projectRef }, { enabled: showConnect }) const { can: canReadAPIKeys } = useAsyncCheckProjectPermissions( PermissionAction.READ, @@ -109,8 +123,8 @@ export const Connect = () => { function handleConnectionType(type: string) { if (type === 'frameworks') { - setConnectionObject(FRAMEWORKS) - handleConnectionTypeChange(FRAMEWORKS) + setConnectionObject(frameworks) + handleConnectionTypeChange(frameworks) } if (type === 'mobiles') { @@ -207,14 +221,14 @@ export const Connect = () => { handleConnectionType(value)}> - {CONNECTION_TYPES.map((type) => ( + {connectionTypes.map((type) => ( {type.label} ))} - {CONNECTION_TYPES.map((type) => { + {connectionTypes.map((type) => { const hasChildOptions = (connectionObject.find((parent) => parent.key === selectedParent)?.children.length || 0) > 0 @@ -290,11 +304,18 @@ export const Connect = () => {

Add the following files below to your application

- + {!!connectFrameworks && isFrameworkSelected ? ( + x.key === selectedParent)} + /> + ) : ( + + )} void label: string - items: any[] + items: ConnectionType[] } -const ConnectDropdown = ({ +export const ConnectDropdown = ({ state, updateState, label, @@ -53,11 +54,7 @@ const ConnectDropdown = ({ iconRight={} >
- {selectedItem?.icon ? ( - - ) : ( - - )} + {selectedItem?.icon ? : } {selectedItem?.label}
@@ -79,7 +76,7 @@ const ConnectDropdown = ({ }} className="flex gap-2 items-center" > - {item.icon ? : } + {item.icon ? : } {item.label} ) } - -export default ConnectDropdown diff --git a/apps/studio/components/interfaces/Connect/ConnectTabContent.tsx b/apps/studio/components/interfaces/Connect/ConnectTabContent.tsx index 890ceb58df6e6..3667d93dd4838 100644 --- a/apps/studio/components/interfaces/Connect/ConnectTabContent.tsx +++ b/apps/studio/components/interfaces/Connect/ConnectTabContent.tsx @@ -27,7 +27,7 @@ interface ConnectContentTabProps extends HTMLAttributes { } } -const ConnectTabContent = forwardRef( +export const ConnectTabContent = forwardRef( ({ projectKeys, filePath, ...props }, ref) => { const { ref: projectRef } = useParams() const { data: selectedOrg } = useSelectedOrganizationQuery() @@ -102,5 +102,3 @@ const ConnectTabContent = forwardRef( ) ConnectTabContent.displayName = 'ConnectTabContent' - -export default ConnectTabContent diff --git a/apps/studio/components/interfaces/Connect/ConnectTabContentCustom.tsx b/apps/studio/components/interfaces/Connect/ConnectTabContentCustom.tsx new file mode 100644 index 0000000000000..c56c8e194d010 --- /dev/null +++ b/apps/studio/components/interfaces/Connect/ConnectTabContentCustom.tsx @@ -0,0 +1,56 @@ +import { useEffect, useState } from 'react' + +import { cn, SimpleCodeBlock } from 'ui' +import { ConnectionType } from './Connect.constants' +import { projectKeys } from './Connect.types' +import { + ConnectTabContent, + ConnectTabs, + ConnectTabTrigger, + ConnectTabTriggers, +} from './ConnectTabs' + +interface ConnectTabContentCustomProps { + projectKeys: projectKeys + framework?: ConnectionType +} + +export const ConnectTabContentCustom = ({ + projectKeys, + framework, +}: ConnectTabContentCustomProps) => { + const { files = [] } = framework ?? {} + + const [selectedTab, setSelectedTab] = useState() + + useEffect(() => { + if (framework?.files) setSelectedTab(framework.files[0].name) + }, [framework]) + + return ( +
+ + + {files.map((x) => ( + + ))} + + + {files.map((x) => { + const format = x.name.split('.')[1] ?? 'bash' + const content = x.content + .replaceAll('{{apiUrl}}', projectKeys.apiUrl ?? '') + .replaceAll('{{anonKey}}', projectKeys.anonKey ?? '') + .replaceAll('{{publishableKey}}', projectKeys.publishableKey ?? '') + return ( + + + {content} + + + ) + })} + +
+ ) +} diff --git a/apps/studio/components/interfaces/Connect/ConnectTabs.tsx b/apps/studio/components/interfaces/Connect/ConnectTabs.tsx index ec7b1b5a61fe8..1443c7abfbe7b 100644 --- a/apps/studio/components/interfaces/Connect/ConnectTabs.tsx +++ b/apps/studio/components/interfaces/Connect/ConnectTabs.tsx @@ -12,20 +12,26 @@ interface ConnectTabTriggersProps { interface ConnectFileTabProps { children: ReactNode[] + value?: string + onValueChange?: (value: string) => void } interface ConnectTabContentProps { children: ReactNode value: string } -const ConnectTabs = ({ children }: ConnectFileTabProps) => { +const ConnectTabs = ({ children, value, onValueChange }: ConnectFileTabProps) => { const firstChild = children[0] const defaultValue = isValidElement(firstChild) ? (firstChild.props as any)?.children[0]?.props?.value || '' : null - return {children} + return ( + + {children} + + ) } const ConnectTabTrigger = ({ value }: ConnectTabTriggerProps) => { diff --git a/apps/studio/components/interfaces/Connect/ConnectionIcon.tsx b/apps/studio/components/interfaces/Connect/ConnectionIcon.tsx index fd2452d29619d..27e93521dc831 100644 --- a/apps/studio/components/interfaces/Connect/ConnectionIcon.tsx +++ b/apps/studio/components/interfaces/Connect/ConnectionIcon.tsx @@ -4,26 +4,29 @@ import Image from 'next/image' import { BASE_PATH } from 'lib/constants' interface ConnectionIconProps { - connection: any + icon: string } -export const ConnectionIcon = ({ connection }: ConnectionIconProps) => { +export const ConnectionIcon = ({ icon }: ConnectionIconProps) => { const { resolvedTheme } = useTheme() - const imageFolder = ['ionic-angular'].includes(connection) ? 'icons/frameworks' : 'libraries' + const imageFolder = ['ionic-angular'].includes(icon) ? 'icons/frameworks' : 'libraries' const imageExtension = imageFolder === 'icons/frameworks' ? '' : '-icon' - - return ( - {`${connection} diff --git a/apps/studio/components/interfaces/Connect/content/nextjs/app/supabasejs/content.tsx b/apps/studio/components/interfaces/Connect/content/nextjs/app/supabasejs/content.tsx index 8108b197f0980..8c56900d9e4f4 100644 --- a/apps/studio/components/interfaces/Connect/content/nextjs/app/supabasejs/content.tsx +++ b/apps/studio/components/interfaces/Connect/content/nextjs/app/supabasejs/content.tsx @@ -1,10 +1,10 @@ import type { ContentFileProps } from 'components/interfaces/Connect/Connect.types' import { + ConnectTabContent, ConnectTabs, ConnectTabTrigger, ConnectTabTriggers, - ConnectTabContent, } from 'components/interfaces/Connect/ConnectTabs' import { SimpleCodeBlock } from 'ui' @@ -154,4 +154,6 @@ export const createClient = (request: NextRequest) => { ) } +// [Joshen] Used as a dynamic import +// eslint-disable-next-line no-restricted-exports export default ContentFile diff --git a/apps/studio/components/interfaces/Docs/GeneralContent.tsx b/apps/studio/components/interfaces/Docs/GeneralContent.tsx index da63210858d2f..0550dfc1c42bd 100644 --- a/apps/studio/components/interfaces/Docs/GeneralContent.tsx +++ b/apps/studio/components/interfaces/Docs/GeneralContent.tsx @@ -2,7 +2,7 @@ import Authentication from 'components/interfaces/Docs/Authentication' import Introduction from 'components/interfaces/Docs/Introduction' import RpcIntroduction from 'components/interfaces/Docs/Pages/Rpc/Introduction' import TablesIntroduction from 'components/interfaces/Docs/Pages/Tables/Introduction' -import UserManagement from 'components/interfaces/Docs/Pages/UserManagement' +import { UserManagement } from 'components/interfaces/Docs/Pages/UserManagement' interface GeneralContentProps { page?: string diff --git a/apps/studio/components/interfaces/Docs/Pages/UserManagement.tsx b/apps/studio/components/interfaces/Docs/Pages/UserManagement.tsx index 036acd1719280..ff4ef5661ebe2 100644 --- a/apps/studio/components/interfaces/Docs/Pages/UserManagement.tsx +++ b/apps/studio/components/interfaces/Docs/Pages/UserManagement.tsx @@ -3,6 +3,7 @@ import { useRouter } from 'next/router' import { useParams } from 'common' import { useProjectSettingsV2Query } from 'data/config/project-settings-v2-query' +import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled' import { makeRandomString } from 'lib/helpers' import CodeSnippet from '../CodeSnippet' import Snippets from '../Snippets' @@ -14,11 +15,15 @@ interface UserManagementProps { showApiKey: string } -export default function UserManagement({ selectedLang, showApiKey }: UserManagementProps) { +export const UserManagement = ({ selectedLang, showApiKey }: UserManagementProps) => { const router = useRouter() const { ref: projectRef } = useParams() const keyToShow = showApiKey ? showApiKey : 'SUPABASE_KEY' + const { authenticationSignInProviders } = useIsFeatureEnabled([ + 'authentication:sign_in_providers', + ]) + const { data: settings } = useProjectSettingsV2Query({ projectRef }) const protocol = settings?.app_config?.protocol ?? 'https' const hostEndpoint = settings?.app_config?.endpoint ?? '' @@ -157,72 +162,80 @@ export default function UserManagement({ selectedLang, showApiKey }: UserManagem
-

Log in with Third Party OAuth

-
-
-

- Users can log in with Third Party OAuth like Google, Facebook, GitHub, and more. You - must first enable each of these in the Auth Providers settings{' '} - - - here - - {' '} - . -

-

- View all the available{' '} - - Third Party OAuth providers - -

-

- After they have logged in, all interactions using the Supabase JS client will be - performed as "that user". -

-

- Generate your Client ID and secret from:{` `} - - Google - - ,{` `} - - GitHub - - ,{` `} - - GitLab - - ,{` `} - - Facebook - - ,{` `} - - Bitbucket - - . -

-
-
- -
-
+ {authenticationSignInProviders && ( + <> +

Log in with Third Party OAuth

+
+
+

+ Users can log in with Third Party OAuth like Google, Facebook, GitHub, and more. You + must first enable each of these in the Auth Providers settings{' '} + + + here + + {' '} + . +

+

+ View all the available{' '} + + Third Party OAuth providers + +

+

+ After they have logged in, all interactions using the Supabase JS client will be + performed as "that user". +

+

+ Generate your Client ID and secret from:{` `} + + Google + + ,{` `} + + GitHub + + ,{` `} + + GitLab + + ,{` `} + + Facebook + + ,{` `} + + Bitbucket + + . +

+
+
+ +
+
+ + )}

User

diff --git a/apps/studio/components/interfaces/Home/ExampleProject.tsx b/apps/studio/components/interfaces/Home/ExampleProject.tsx index 13a10c1a00b4c..8f6ba8c573668 100644 --- a/apps/studio/components/interfaces/Home/ExampleProject.tsx +++ b/apps/studio/components/interfaces/Home/ExampleProject.tsx @@ -6,20 +6,39 @@ import { useParams } from 'common' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { BASE_PATH } from 'lib/constants' +import { cn } from 'ui' interface ExampleProjectProps { - framework: string title: string description: string url: string + framework?: string + iconUrl?: string } -const ExampleProject = ({ framework, title, description, url }: ExampleProjectProps) => { +export const ExampleProject = ({ + framework, + title, + description, + url, + iconUrl, +}: ExampleProjectProps) => { const { resolvedTheme } = useTheme() const { ref: projectRef } = useParams() const { data: org } = useSelectedOrganizationQuery() const { mutate: sendEvent } = useSendEventMutation() + const iconImgSrc = iconUrl + ? iconUrl + : !!framework + ? `${BASE_PATH}/img/libraries/${framework.toLowerCase()}${ + ['expo', 'nextjs'].includes(framework.toLowerCase()) + ? resolvedTheme?.includes('dark') + ? '-dark' + : '' + : '' + }-icon.svg` + : '' return (
{`${framework}{description}

@@ -79,5 +87,3 @@ const ExampleProject = ({ framework, title, description, url }: ExampleProjectPr ) } - -export default ExampleProject diff --git a/apps/studio/components/interfaces/Home/NewProjectPanel/APIKeys.tsx b/apps/studio/components/interfaces/Home/NewProjectPanel/APIKeys.tsx index d2779272463df..438cbd5fd70e6 100644 --- a/apps/studio/components/interfaces/Home/NewProjectPanel/APIKeys.tsx +++ b/apps/studio/components/interfaces/Home/NewProjectPanel/APIKeys.tsx @@ -42,7 +42,10 @@ export const APIKeys = () => { ]) const availableLanguages = [ - ...(javascriptExampleEnabled ? [{ name: 'Javascript', key: 'js' }] : []), + { + name: javascriptExampleEnabled ? 'Javascript' : 'Typescript', + key: 'js', + }, ...(dartExampleEnabled ? [{ name: 'Dart', key: 'dart' }] : []), ] const [selectedLanguage, setSelectedLanguage] = useState(availableLanguages[0]) diff --git a/apps/studio/components/interfaces/Home/ProjectList/ProjectCard.tsx b/apps/studio/components/interfaces/Home/ProjectList/ProjectCard.tsx index 0f2283b1b973a..0874e31d8a21f 100644 --- a/apps/studio/components/interfaces/Home/ProjectList/ProjectCard.tsx +++ b/apps/studio/components/interfaces/Home/ProjectList/ProjectCard.tsx @@ -6,6 +6,7 @@ import type { IntegrationProjectConnection } from 'data/integrations/integration import { ProjectIndexPageLink } from 'data/prefetchers/project.$ref' import type { ProjectInfo } from 'data/projects/projects-query' import type { ResourceWarning } from 'data/usage/resource-warnings-query' +import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled' import { BASE_PATH } from 'lib/constants' import InlineSVG from 'react-inlinesvg' import { inferProjectStatus } from './ProjectCard.utils' @@ -29,6 +30,10 @@ const ProjectCard = ({ const { name, ref: projectRef } = project const desc = `${project.cloud_provider} | ${project.region}` + const { projectHomepageShowInstanceSize } = useIsFeatureEnabled([ + 'project_homepage:show_instance_size', + ]) + const isBranchingEnabled = project.preview_branch_refs?.length > 0 const isGithubIntegrated = githubIntegration !== undefined const isVercelIntegrated = vercelIntegration !== undefined @@ -45,7 +50,9 @@ const ProjectCard = ({

{name}

{desc}
- {project.status !== 'INACTIVE' && } + {project.status !== 'INACTIVE' && projectHomepageShowInstanceSize && ( + + )} {isVercelIntegrated && (
{ - const showStripeWrapper = useIsFeatureEnabled('integrations:show_stripe_wrapper') + const { integrationsShowStripeWrapper } = useIsFeatureEnabled([ + 'integrations:show_stripe_wrapper', + ]) const [selectedCategory, setSelectedCategory] = useQueryState( 'category', @@ -41,7 +43,7 @@ export const AvailableIntegrations = () => { const installedIds = installedIntegrations.map((i) => i.id) // available integrations for install - const availableIntegrations = showStripeWrapper + const availableIntegrations = integrationsShowStripeWrapper ? allIntegrations : allIntegrations.filter((x) => x.id !== 'stripe_wrapper') const integrationsByCategory = diff --git a/apps/studio/components/interfaces/Organization/Documents/CustomDocument.tsx b/apps/studio/components/interfaces/Organization/Documents/CustomDocument.tsx new file mode 100644 index 0000000000000..76c9b4ca7de55 --- /dev/null +++ b/apps/studio/components/interfaces/Organization/Documents/CustomDocument.tsx @@ -0,0 +1,33 @@ +import { + ScaffoldContainer, + ScaffoldSection, + ScaffoldSectionContent, + ScaffoldSectionDetail, +} from 'components/layouts/Scaffold' +import { CustomContentTypes } from 'hooks/custom-content/CustomContent.types' +import { ExternalLink } from 'lucide-react' +import { Button } from 'ui' + +interface CustomDocumentProps { + doc: CustomContentTypes['organizationLegalDocuments'][number] +} + +export const CustomDocument = ({ doc }: CustomDocumentProps) => { + return ( + + + +

{doc.name}

+

{doc.description}

+
+ + + +
+
+ ) +} diff --git a/apps/studio/components/interfaces/Organization/Documents/Documents.tsx b/apps/studio/components/interfaces/Organization/Documents/Documents.tsx index 84ecf7b32fe2b..1b35df888dc4b 100644 --- a/apps/studio/components/interfaces/Organization/Documents/Documents.tsx +++ b/apps/studio/components/interfaces/Organization/Documents/Documents.tsx @@ -1,6 +1,9 @@ import Link from 'next/link' import { ScaffoldContainer, ScaffoldDivider, ScaffoldSection } from 'components/layouts/Scaffold' +import { useCustomContent } from 'hooks/custom-content/useCustomContent' +import { Fragment } from 'react' +import { CustomDocument } from './CustomDocument' import { DPA } from './DPA' import { HIPAA } from './HIPAA' import { SecurityQuestionnaire } from './SecurityQuestionnaire' @@ -8,6 +11,19 @@ import { SOC2 } from './SOC2' import { TIA } from './TIA' const Documents = () => { + const { organizationLegalDocuments } = useCustomContent(['organization:legal_documents']) + + if (Array.isArray(organizationLegalDocuments)) { + return organizationLegalDocuments.map((doc, idx) => { + return ( + + + {idx !== organizationLegalDocuments.length - 1 && } + + ) + }) + } + return ( <> diff --git a/apps/studio/components/interfaces/Organization/Usage/Compute.tsx b/apps/studio/components/interfaces/Organization/Usage/Compute.tsx index 4436a14590d47..e32c1458b89c9 100644 --- a/apps/studio/components/interfaces/Organization/Usage/Compute.tsx +++ b/apps/studio/components/interfaces/Organization/Usage/Compute.tsx @@ -8,6 +8,7 @@ import { DataPoint } from 'data/analytics/constants' import { useOrgDailyComputeStatsQuery } from 'data/analytics/org-daily-compute-stats-query' import { ComputeUsageMetric, computeUsageMetricLabel } from 'data/analytics/org-daily-stats-query' import type { OrgSubscription } from 'data/subscriptions/types' +import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled' import SectionContent from './SectionContent' import { Attribute, AttributeColor } from './Usage.constants' import UsageBarChart from './UsageBarChart' @@ -34,6 +35,8 @@ const Compute = ({ orgSlug, projectRef, startDate, endDate }: ComputeProps) => { endDate, }) + const { billingAll } = useIsFeatureEnabled(['billing:all']) + const chartData: DataPoint[] = egressData?.data ?? [] const COMPUTE_TO_COLOR: Record = { @@ -79,16 +82,18 @@ const Compute = ({ orgSlug, projectRef, startDate, endDate }: ComputeProps) => { name: 'Compute Hours', description: 'Amount of hours your projects were active. Each project is a dedicated server and database.\nPaid plans come with $10 in Compute Credits to cover one project running on Micro Compute or parts of any compute add-on.\nBilling is based on the sum of Compute Hours used. Paused projects do not count towards usage.', - links: [ - { - name: 'Compute Add-ons', - url: 'https://supabase.com/docs/guides/platform/compute-add-ons', - }, - { - name: 'Usage-billing for Compute', - url: 'https://supabase.com/docs/guides/platform/manage-your-usage/compute', - }, - ], + links: billingAll + ? [ + { + name: 'Compute Add-ons', + url: 'https://supabase.com/docs/guides/platform/compute-add-ons', + }, + { + name: 'Usage-billing for Compute', + url: 'https://supabase.com/docs/guides/platform/manage-your-usage/compute', + }, + ] + : [], }} > {isLoading && } diff --git a/apps/studio/components/interfaces/Organization/Usage/TotalUsage.tsx b/apps/studio/components/interfaces/Organization/Usage/TotalUsage.tsx index 726ec20f6ff73..c6329db4280a6 100644 --- a/apps/studio/components/interfaces/Organization/Usage/TotalUsage.tsx +++ b/apps/studio/components/interfaces/Organization/Usage/TotalUsage.tsx @@ -9,6 +9,7 @@ import { } from 'data/analytics/org-daily-stats-query' import type { OrgSubscription } from 'data/subscriptions/types' import { useOrgUsageQuery } from 'data/usage/org-usage-query' +import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled' import { cn } from 'ui' import { BILLING_BREAKDOWN_METRICS } from '../BillingSettings/BillingBreakdown/BillingBreakdown.constants' import BillingMetric from '../BillingSettings/BillingBreakdown/BillingMetric' @@ -32,7 +33,7 @@ const METRICS_TO_HIDE_WITH_NO_USAGE: PricingMetric[] = [ PricingMetric.DISK_THROUGHPUT_GP3, ] -const TotalUsage = ({ +export const TotalUsage = ({ orgSlug, projectRef, subscription, @@ -41,6 +42,7 @@ const TotalUsage = ({ currentBillingCycleSelected, }: ComputeProps) => { const isUsageBillingEnabled = subscription?.usage_billing_enabled + const { billingAll } = useIsFeatureEnabled(['billing:all']) const { data: usage, @@ -117,16 +119,18 @@ const TotalUsage = ({ description: isUsageBillingEnabled ? `Your plan includes a limited amount of usage. If exceeded, you will be charged for the overages. It may take up to 1 hour to refresh.` : `Your plan includes a limited amount of usage. If exceeded, you may experience restrictions, as you are currently not billed for overages. It may take up to 1 hour to refresh.`, - links: [ - { - name: 'How billing works', - url: 'https://supabase.com/docs/guides/platform/billing-on-supabase', - }, - { - name: 'Supabase Plans', - url: 'https://supabase.com/pricing', - }, - ], + links: billingAll + ? [ + { + name: 'How billing works', + url: 'https://supabase.com/docs/guides/platform/billing-on-supabase', + }, + { + name: 'Supabase Plans', + url: 'https://supabase.com/pricing', + }, + ] + : [], }} > {isLoadingUsage && ( @@ -234,5 +238,3 @@ const TotalUsage = ({
) } - -export default TotalUsage diff --git a/apps/studio/components/interfaces/Organization/Usage/Usage.tsx b/apps/studio/components/interfaces/Organization/Usage/Usage.tsx index 80a68493edf73..32420143d36bb 100644 --- a/apps/studio/components/interfaces/Organization/Usage/Usage.tsx +++ b/apps/studio/components/interfaces/Organization/Usage/Usage.tsx @@ -22,10 +22,10 @@ import { cn, Listbox } from 'ui' import { Admonition } from 'ui-patterns' import { Restriction } from '../BillingSettings/Restriction' import Activity from './Activity' -import Egress from './Egress' import Compute from './Compute' +import Egress from './Egress' import SizeAndCounts from './SizeAndCounts' -import TotalUsage from './TotalUsage' +import { TotalUsage } from './TotalUsage' const Usage = () => { const { slug, projectRef } = useParams() diff --git a/apps/studio/components/interfaces/ProjectAPIDocs/Content/UserManagement.tsx b/apps/studio/components/interfaces/ProjectAPIDocs/Content/UserManagement.tsx index 22e762d9eb56f..e4bc2e18795c5 100644 --- a/apps/studio/components/interfaces/ProjectAPIDocs/Content/UserManagement.tsx +++ b/apps/studio/components/interfaces/ProjectAPIDocs/Content/UserManagement.tsx @@ -1,8 +1,12 @@ +import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled' import ContentSnippet from '../ContentSnippet' import { DOCS_CONTENT } from '../ProjectAPIDocs.constants' import type { ContentProps } from './Content.types' const UserManagement = ({ language, apikey, endpoint }: ContentProps) => { + const { authenticationSignInProviders } = useIsFeatureEnabled([ + 'authentication:sign_in_providers', + ]) return ( <> @@ -42,12 +46,14 @@ const UserManagement = ({ language, apikey, endpoint }: ContentProps) => { endpoint={endpoint} snippet={DOCS_CONTENT.smsVerify} /> - + {authenticationSignInProviders && ( + + )} ) => { // [Joshen] Just FYI Handles cannot be conditionally rendered const { provider, region, computeSize, numReplicas, numRegions, hasLoadBalancer } = data + const { projectHomepageShowInstanceSize } = useIsFeatureEnabled([ + 'project_homepage:show_instance_size', + ]) + return ( <> ) => {

{provider} - - {computeSize} + {projectHomepageShowInstanceSize && ( + <> + + {computeSize} + + )}

@@ -186,6 +195,10 @@ export const ReplicaNode = ({ data }: NodeProps) => { PermissionAction.CREATE, 'projects' ) + const { projectHomepageShowInstanceSize } = useIsFeatureEnabled([ + 'project_homepage:show_instance_size', + ]) + const [, setShowConnect] = useQueryState('showConnect', parseAsBoolean.withDefault(false)) const { data: databaseStatuses } = useReadReplicasStatusesQuery({ projectRef: ref }) @@ -289,7 +302,7 @@ export const ReplicaNode = ({ data }: NodeProps) => {

{region.name}

{provider} - {!!computeSize && ( + {projectHomepageShowInstanceSize && !!computeSize && ( <> {computeSize} diff --git a/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/MapView.tsx b/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/MapView.tsx index f96afaf94b55e..6140367095b9a 100644 --- a/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/MapView.tsx +++ b/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/MapView.tsx @@ -20,6 +20,7 @@ import { DropdownMenuItemTooltip } from 'components/ui/DropdownMenuItemTooltip' import { Database, useReadReplicasQuery } from 'data/read-replicas/replicas-query' import { formatDatabaseID } from 'data/read-replicas/replicas.utils' import { useAsyncCheckProjectPermissions } from 'hooks/misc/useCheckPermissions' +import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled' import { BASE_PATH } from 'lib/constants' import type { AWS_REGIONS_KEYS } from 'shared-data' import { useDatabaseSelectorStateSnapshot } from 'state/database-selector' @@ -51,6 +52,9 @@ const MapView = ({ }: MapViewProps) => { const { ref } = useParams() const dbSelectorState = useDatabaseSelectorStateSnapshot() + const { projectHomepageShowInstanceSize } = useIsFeatureEnabled([ + 'project_homepage:show_instance_size', + ]) const [mount, setMount] = useState(false) const [zoom, setZoom] = useState(1.5) @@ -286,7 +290,9 @@ const MapView = ({ Unhealthy )}

-

AWS • {database.size}

+

+ AWS{projectHomepageShowInstanceSize ? ` • ${database.size}` : ''} +

{database.identifier !== ref && (

Created on: {created}

)} diff --git a/apps/studio/components/interfaces/Settings/Logs/LogsQueryPanel.tsx b/apps/studio/components/interfaces/Settings/Logs/LogsQueryPanel.tsx index f67aef39e044a..ff2e816a34722 100644 --- a/apps/studio/components/interfaces/Settings/Logs/LogsQueryPanel.tsx +++ b/apps/studio/components/interfaces/Settings/Logs/LogsQueryPanel.tsx @@ -58,6 +58,7 @@ const LogsQueryPanel = ({ onDateChange, }: LogsQueryPanelProps) => { const [showReference, setShowReference] = useState(false) + const { logsTemplates } = useIsFeatureEnabled(['logs:templates']) const { projectAuthAll: authEnabled, @@ -125,7 +126,7 @@ const LogsQueryPanel = ({ - {IS_PLATFORM && ( + {IS_PLATFORM && logsTemplates && (