diff --git a/apps/docs/components/CustomHTMLElements/CustomHTMLElements.utils.ts b/apps/docs/components/CustomHTMLElements/CustomHTMLElements.utils.ts index 844724a546682..337f48b2bbfd3 100644 --- a/apps/docs/components/CustomHTMLElements/CustomHTMLElements.utils.ts +++ b/apps/docs/components/CustomHTMLElements/CustomHTMLElements.utils.ts @@ -89,13 +89,13 @@ export const highlightSelectedNavItem = (id: string) => { const navMenuItems = document.querySelectorAll('.function-link-item a') // find any currently active items and remove them - const currentActiveItems = document.querySelectorAll('.function-link-list .text-brand-900') - currentActiveItems.forEach((item) => item.classList.remove('text-brand-900')) + const currentActiveItems = document.querySelectorAll('.function-link-list .text-brand') + currentActiveItems.forEach((item) => item.classList.remove('text-brand')) // Add active class to the current item navMenuItems.forEach((item) => { if (item.href.split('/').at(-1) === id) { - item.classList.add('text-brand-900') + item.classList.add('text-brand') } }) } diff --git a/apps/docs/components/GuidesTableOfContents.tsx b/apps/docs/components/GuidesTableOfContents.tsx index 9d25121f661a6..553f3165452cb 100644 --- a/apps/docs/components/GuidesTableOfContents.tsx +++ b/apps/docs/components/GuidesTableOfContents.tsx @@ -46,7 +46,7 @@ const GuidesTableOfContents: FC = ({ list }) => {
  • diff --git a/apps/docs/components/HomePageCover.tsx b/apps/docs/components/HomePageCover.tsx index e760c411dc38a..657083befd21c 100644 --- a/apps/docs/components/HomePageCover.tsx +++ b/apps/docs/components/HomePageCover.tsx @@ -28,6 +28,11 @@ const HomePageCover = (props) => { icon: '/docs/img/icons/flutter-icon', href: '/guides/getting-started/quickstarts/flutter', }, + { + tooltip: 'Android Kotlin', + icon: '/docs/img/icons/kotlin-icon', + href: '/guides/getting-started/quickstarts/kotlin', + }, { tooltip: 'SvelteKit', icon: '/docs/img/icons/svelte-icon', @@ -69,7 +74,7 @@ const HomePageCover = (props) => {
    - +

    Getting Started

    diff --git a/apps/docs/components/LinkCard.tsx b/apps/docs/components/LinkCard.tsx index e74ac68384a82..6e22200bbda34 100644 --- a/apps/docs/components/LinkCard.tsx +++ b/apps/docs/components/LinkCard.tsx @@ -14,7 +14,7 @@ export default function LinkCard({ }) { return ( -
    + {description ? ( <>

    {title}

    diff --git a/apps/docs/components/Navigation/Footer.tsx b/apps/docs/components/Navigation/Footer.tsx index 32f1b4f73db83..6550b0f24cedb 100644 --- a/apps/docs/components/Navigation/Footer.tsx +++ b/apps/docs/components/Navigation/Footer.tsx @@ -29,11 +29,7 @@ const Footer = () => ( {Icon && }

    {text}

    -
    + {ctaLabel} diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts index 71029382f99c7..f9b04a969ba6c 100644 --- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts +++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts @@ -72,12 +72,6 @@ export const HOMEPAGE_MENU_ITEMS: HomepageMenuItems = [ href: '/guides/platform', level: 'platform', }, - { - label: 'Resources', - icon: 'resources', - href: '/guides/resources', - level: 'resources', - }, { label: 'Self-Hosting', icon: 'self-hosting', @@ -130,14 +124,13 @@ export const HOMEPAGE_MENU_ITEMS: HomepageMenuItems = [ community: true, }, { - label: 'Tools', + label: 'Resources', }, { - label: 'Integrations', - icon: 'integrations', - hasLightIcon: true, - href: 'https://supabase.com/partners/integrations', - level: 'integrations', + label: 'CLI Commands', + icon: 'reference-cli', + href: '/reference/cli/introduction', + level: 'reference_javascript', }, { label: 'Management API', @@ -145,6 +138,19 @@ export const HOMEPAGE_MENU_ITEMS: HomepageMenuItems = [ href: '/reference/api/introduction', level: 'reference_javascript', }, + { + label: 'Guides and Examples', + icon: 'resources', + href: '/guides/resources', + level: 'resources', + }, + { + label: 'Integrations', + icon: 'integrations', + hasLightIcon: true, + href: 'https://supabase.com/partners/integrations', + level: 'integrations', + }, ], [ { @@ -550,6 +556,10 @@ export const database: NavMenuConstant = { name: 'Postgres Guides', url: undefined, items: [ + { + name: 'Analyzing efficiency and performance', + url: '/guides/database/inspect', + }, { name: 'JSON and unstructured data', url: '/guides/database/json', @@ -663,10 +673,23 @@ export const database: NavMenuConstant = { name: 'RUM: inverted index for full-text search', url: '/guides/database/extensions/rum', }, + ], + }, + { + name: 'Foreign Data Wrappers', + url: undefined, + items: [ + { name: 'Overview', url: '/guides/database/extensions/wrappers/overview' }, + { name: 'Connecting to Airtable', url: '/guides/database/extensions/wrappers/airtable' }, + { name: 'Connecting to AWS S3', url: '/guides/database/extensions/wrappers/s3' }, + { name: 'Connecting to BigQuery', url: '/guides/database/extensions/wrappers/bigquery' }, { - name: 'wrappers: 3rd Party Integrations', - url: '/guides/database/extensions/wrappers', + name: 'Connecting to ClickHouse', + url: '/guides/database/extensions/wrappers/clickhouse', }, + { name: 'Connecting to Firebase', url: '/guides/database/extensions/wrappers/firebase' }, + { name: 'Connecting to Logflare', url: '/guides/database/extensions/wrappers/logflare' }, + { name: 'Connecting to Stripe', url: '/guides/database/extensions/wrappers/stripe' }, ], }, { @@ -983,33 +1006,51 @@ export const supabase_cli: NavMenuConstant = { title: 'Local Dev / CLI', url: '/guides/cli', items: [ - { name: 'Getting started', url: '/guides/cli' }, - { name: 'Local Development', url: '/guides/cli/local-development' }, - { name: 'Managing environments', url: '/guides/cli/managing-environments' }, - { - name: 'Managing config and secrets', - url: '/guides/cli/managing-config', - }, + { name: 'Overview', url: '/guides/cli' }, { - name: 'Testing emails locally', - url: '/guides/cli/testing-emails', + name: 'Using the CLI', + url: undefined, + items: [ + { name: 'Getting started', url: '/guides/cli/getting-started' }, + { name: 'CLI Configuration', url: '/guides/cli/config' }, + ], }, { - name: 'GitHub Action', + name: 'Developing with Supabase', url: undefined, items: [ + { name: 'Local Development', url: '/guides/cli/local-development' }, + { name: 'Managing environments', url: '/guides/cli/managing-environments' }, { - name: 'Generate types from your database', - url: '/guides/cli/github-action/generating-types', + name: 'Managing config and secrets', + url: '/guides/cli/managing-config', + }, + { + name: 'Seeding your database', + url: '/guides/cli/seeding-your-database', + }, + { + name: 'Testing and linting', + url: '/guides/cli/testing-and-linting', }, ], }, { - name: 'Reference', + name: 'GitHub Action', url: undefined, items: [ - { name: 'Commands', url: '/reference/cli/introduction' }, - { name: 'Configuration', url: '/reference/cli/config' }, + { + name: 'Generate types from your database', + url: '/guides/cli/github-action/generating-types', + }, + { + name: 'Automated testing', + url: '/guides/cli/github-action/testing', + }, + { + name: 'Backup your database', + url: '/guides/cli/github-action/backups', + }, ], }, ], diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenuCliList.tsx b/apps/docs/components/Navigation/NavigationMenu/NavigationMenuCliList.tsx index deb8caf1f178e..8c88d73156072 100644 --- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenuCliList.tsx +++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenuCliList.tsx @@ -23,7 +23,7 @@ const NavigationMenuCliList = ({ currentLevel, setLevel, id }) => { return (
  • - + {icon && } {title} @@ -100,7 +100,7 @@ const NavigationMenuCliList = ({ currentLevel, setLevel, id }) => {
    diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenuGuideListItems.tsx b/apps/docs/components/Navigation/NavigationMenu/NavigationMenuGuideListItems.tsx index f264a4112b77d..0d390a0e6af29 100644 --- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenuGuideListItems.tsx +++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenuGuideListItems.tsx @@ -19,7 +19,7 @@ const HeaderLink = React.memo(function HeaderLink(props: { className={[ ' ', !props.title && 'capitalize', - props.url === router.pathname ? 'text-brand-900' : 'hover:text-brand-900 text-scale-1200', + props.url === router.pathname ? 'text-brand' : 'hover:text-brand text-scale-1200', ].join(' ')} > {props.title ?? props.id} @@ -68,7 +68,7 @@ const ContentAccordionLink = React.memo(function ContentAccordionLink(props: any 'flex items-center gap-2', 'cursor-pointer transition text-sm', activeItem - ? 'text-brand-900 font-medium' + ? 'text-brand font-medium' : 'hover:text-scale-1200 dark:hover:text-scale-1100 text-scale-1000', ].join(' ')} parent={props.subItem.parent} @@ -97,8 +97,8 @@ const ContentAccordionLink = React.memo(function ContentAccordionLink(props: any className={[ 'cursor-pointer transition text-sm', subSubItem.url === router.pathname - ? 'text-brand-900' - : 'hover:text-brand-900 text-scale-1000', + ? 'text-brand' + : 'hover:text-brand text-scale-1000', ].join(' ')} > {subSubItem.name} @@ -124,7 +124,7 @@ const ContentLink = React.memo(function ContentLink(props: any) { className={[ 'cursor-pointer transition text-sm', props.url === router.pathname - ? 'text-brand-900' + ? 'text-brand' : 'hover:text-scale-1200 dark:hover:text-scale-1100 text-scale-1000', ].join(' ')} > @@ -152,7 +152,7 @@ const Content = (props) => {
    @@ -166,7 +166,7 @@ const Content = (props) => { -
    +
    diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenuRefListItems.tsx b/apps/docs/components/Navigation/NavigationMenu/NavigationMenuRefListItems.tsx index a280bf07da685..8c2007c78b322 100644 --- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenuRefListItems.tsx +++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenuRefListItems.tsx @@ -16,7 +16,7 @@ import { deepFilterSections } from './NavigationMenu.utils' const HeaderLink = React.memo(function HeaderLink(props: any) { return ( - + {props.title ?? props.id} ) @@ -64,7 +64,7 @@ const FunctionLink = React.memo(function FunctionLink({ className={cn( 'cursor-pointer transition text-sm hover:text-scale-1200 gap-3 relative', isParent ? 'flex justify-between' : 'leading-3', - active ? 'text-brand-900' : 'text-scale-1000' + active ? 'text-brand' : 'text-scale-1000' )} > {icon && {icon}} @@ -72,7 +72,7 @@ const FunctionLink = React.memo(function FunctionLink({ {active && !isSubItem && ( )} {isParent && ( @@ -180,7 +180,7 @@ const NavigationMenuRefListItems = ({
    diff --git a/apps/docs/components/Navigation/NavigationMenu/TopNavBarRef.tsx b/apps/docs/components/Navigation/NavigationMenu/TopNavBarRef.tsx index bd080d8e7c9fb..bba1342132191 100644 --- a/apps/docs/components/Navigation/NavigationMenu/TopNavBarRef.tsx +++ b/apps/docs/components/Navigation/NavigationMenu/TopNavBarRef.tsx @@ -56,7 +56,7 @@ const TopNavBarRef: FC = () => { } return ( -
  • Adopted the{' '} - + Snyk {' '} dependency monitor as part of our SSDLC on several key component of our system, to @@ -467,7 +462,7 @@ const Security = () => { now uses {' '} @@ -513,7 +508,7 @@ const Reliability = () => { https://status.supabase.com {' '} @@ -557,7 +552,7 @@ const NewFeaturesAndIntegrations = () => { JavaScript {' '} @@ -565,7 +560,7 @@ const NewFeaturesAndIntegrations = () => { HTTP @@ -587,7 +582,7 @@ const NewFeaturesAndIntegrations = () => { subscribe to changes in your database {' '} @@ -606,7 +601,7 @@ const NewFeaturesAndIntegrations = () => { querying from multiple tables {' '} @@ -614,7 +609,7 @@ const NewFeaturesAndIntegrations = () => { invoke complex functions @@ -703,7 +698,7 @@ const BetaPricing = () => ( rory@supabase.io @@ -716,7 +711,7 @@ const BetaPricing = () => (

    The Supabase Base plan is now called the Supabase Pro plan as per the{' '} - + pricing page . @@ -747,7 +742,7 @@ const OpenSource = () => ( sponsorship {' '} @@ -759,7 +754,7 @@ const OpenSource = () => ( partnering with Strive School {' '} @@ -772,7 +767,7 @@ const OpenSource = () => ( rory@supabase.io {' '} @@ -783,7 +778,7 @@ const OpenSource = () => ( our GitHub. {' '} @@ -819,7 +814,7 @@ const FundingPartners = () => ( Twitter {' '} @@ -856,7 +851,7 @@ const ScalingOurTeam = () => ( work@supabase.io @@ -917,7 +912,7 @@ const WhatsNext = () => ( support@supabase.io {' '} @@ -925,7 +920,7 @@ const WhatsNext = () => ( discussion {' '} diff --git a/apps/www/pages/blog/[slug].tsx b/apps/www/pages/blog/[slug].tsx index 1b1fcbd5b8b48..356c3d5c107c8 100644 --- a/apps/www/pages/blog/[slug].tsx +++ b/apps/www/pages/blog/[slug].tsx @@ -202,7 +202,7 @@ function BlogPostPage(props: any) { {/* Title and description */}

    -

    Blog post

    +

    Blog post

    {props.blog.title}

    {props.blog.date}

    diff --git a/apps/www/pages/careers/index.tsx b/apps/www/pages/careers/index.tsx index a303e9f2e9a35..f03c234b0a1f9 100644 --- a/apps/www/pages/careers/index.tsx +++ b/apps/www/pages/careers/index.tsx @@ -101,7 +101,7 @@ const CareerPage: NextPage = ({ jobs, contributors }: any) => {
    -

    +

    Supabase Careers

    @@ -121,9 +121,9 @@ const CareerPage: NextPage = ({ jobs, contributors }: any) => { return (
    -
    +

    {company.number}

    @@ -153,7 +153,7 @@ const CareerPage: NextPage = ({ jobs, contributors }: any) => { Discord to stay connected to our team, and our community.

    -
    +

    We deeply believe in the efficacy of collaborative open source

    @@ -445,10 +445,10 @@ const CareerPage: NextPage = ({ jobs, contributors }: any) => { className="flex lg:block items-start space-x-6 lg:space-x-0 lg:w-full" >
    -

    +

    {i + 1}

    -
    +

    @@ -461,7 +461,7 @@ const CareerPage: NextPage = ({ jobs, contributors }: any) => {

    ) })} -

    +

    diff --git a/apps/www/pages/customers/[slug].tsx b/apps/www/pages/customers/[slug].tsx index 7be097ca5b98d..19880b2ca34c8 100644 --- a/apps/www/pages/customers/[slug].tsx +++ b/apps/www/pages/customers/[slug].tsx @@ -122,9 +122,7 @@ function CaseStudyPage(props: any) {
    - - Customer Stories - + Customer Stories

    {props.blog.title} diff --git a/apps/www/pages/edge-functions/edge-functions.tsx b/apps/www/pages/edge-functions/edge-functions.tsx index 20900033d315c..981685a02683f 100644 --- a/apps/www/pages/edge-functions/edge-functions.tsx +++ b/apps/www/pages/edge-functions/edge-functions.tsx @@ -145,7 +145,7 @@ function Database() { className="bg-scale-100 dark:bg-scale-300 group flex flex-col gap-4 rounded border px-8 py-6" key={i} > -
    +
    {item.icon ? item.icon : }
    diff --git a/apps/www/pages/launch-week/6/index.tsx b/apps/www/pages/launch-week/6/index.tsx index 7f8f8426cc143..4912c976a6b08 100644 --- a/apps/www/pages/launch-week/6/index.tsx +++ b/apps/www/pages/launch-week/6/index.tsx @@ -1018,7 +1018,7 @@ export default function launchweek() { href="https://supabase.com/blog/launch-week-6-hackathon" target="_blank" rel="nooper noreferrer" - className="text-brand-900" + className="text-brand" > blog post @@ -1052,7 +1052,7 @@ export default function launchweek() { Join our Discord @@ -1064,7 +1064,7 @@ export default function launchweek() {

    Submit your project through{' '} @@ -1091,7 +1091,7 @@ export default function launchweek() {

    Supabase Cache Helpers

    Previous Best Overall Project Winner

    @@ -1105,7 +1105,7 @@ export default function launchweek() {

    Super UI

    Previous Best Overall Project Runner Up

    @@ -1120,7 +1120,7 @@ export default function launchweek() {

    Quid Faciam Hodie?

    Winner Best Flutter Project

    @@ -1130,7 +1130,7 @@ export default function launchweek() {

    That Hot Dog Game

    Previous Winner: Most Fun/Interesting

    @@ -1145,7 +1145,7 @@ export default function launchweek() {

    RepoWatch

    Previous Winner Best Realtime Project

    @@ -1177,10 +1177,10 @@ export default function launchweek() { }} >
    -
    +
    @@ -1204,7 +1204,7 @@ export default function launchweek() { We worked with more than 30 content creators from around the world to drop a mountain of content simultaneously! -
    +
    See all the content
    @@ -1220,7 +1220,7 @@ export default function launchweek() { {activeCreator !== null && (

    {creators[activeCreator].description}

    )} -

    +

    {creators[activeCreator].link_title} diff --git a/apps/www/pages/launch-week/7/index.tsx b/apps/www/pages/launch-week/7/index.tsx index 55c3b4348aafd..5043d62d84dc4 100644 --- a/apps/www/pages/launch-week/7/index.tsx +++ b/apps/www/pages/launch-week/7/index.tsx @@ -28,11 +28,11 @@ interface Props { const supabaseAdmin = createClient( process.env.NEXT_PUBLIC_SUPABASE_URL ?? 'http://localhost:54321', + // ANON KEY process.env.SUPABASE_SERVICE_ROLE_SECRET ?? process.env.NEXT_PUBLIC_SUPABASE_SERVICE_ROLE_SECRET ?? - '' + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Im9idWxkYW5ycHRsb2t0eGNmZnZuIiwicm9sZSI6ImFub24iLCJpYXQiOjE2Njk3MjcwMTIsImV4cCI6MTk4NTMwMzAxMn0.SZLqryz_-stF8dgzeVXmzZWPOqdOrBwqJROlFES8v3I' ) - export default function TicketHome({ users }: Props) { const { isDarkMode, toggleTheme } = useTheme() diff --git a/apps/www/pages/launch-week/7/tickets/index.tsx b/apps/www/pages/launch-week/7/tickets/index.tsx index 61b1b0cd3a6c3..0027a45b7c68b 100644 --- a/apps/www/pages/launch-week/7/tickets/index.tsx +++ b/apps/www/pages/launch-week/7/tickets/index.tsx @@ -131,11 +131,7 @@ export default function TicketsPage({ users }: Props) {

    Check out all the tickets

    -

    - Join us on April 16th for Launch Week 7's final day{' '} -
    and find out if you are one of the lucky - winners. Get sharing! -

    +

    Submissions are closed.

    diff --git a/apps/www/pages/launch-week/index.tsx b/apps/www/pages/launch-week/index.tsx index a44ac87bf85e2..d7405a095ad24 100644 --- a/apps/www/pages/launch-week/index.tsx +++ b/apps/www/pages/launch-week/index.tsx @@ -1,25 +1,29 @@ -import { GetServerSideProps } from 'next' -import { NextSeo } from 'next-seo' import { useState, useEffect } from 'react' -import Image from 'next/image' +import { GetServerSideProps } from 'next' import dynamic from 'next/dynamic' +import Head from 'next/head' +import Image from 'next/image' import { useRouter } from 'next/router' +import { NextSeo } from 'next-seo' import { createClient, Session, SupabaseClient } from '@supabase/supabase-js' import { SITE_ORIGIN, SITE_URL } from '~/lib/constants' -import { PageState, ConfDataContext, UserData } from '~/components/LaunchWeek/hooks/use-conf-data' import DefaultLayout from '~/components/Layouts/Default' +import { PageState, ConfDataContext, UserData } from '~/components/LaunchWeek/hooks/use-conf-data' import SectionContainer from '~/components/Layouts/SectionContainer' import { LaunchWeekLogoHeader } from '~/components/LaunchWeek/8/LaunchWeekLogoHeader' +import { Meetup } from '~/components/LaunchWeek/8/LW8Meetups' +import LW8CalloutsSection from '~/components/LaunchWeek/8/LW8CalloutsSection' import { useTheme } from 'common/Providers' import 'swiper/swiper.min.css' -import Head from 'next/head' const AnimatedParticles = dynamic( () => import('~/components/LaunchWeek/8/AnimatedParticles/ParticlesCanvas') ) +const LW8Releases = dynamic(() => import('~/components/LaunchWeek/8/Releases')) +const LW8Meetups = dynamic(() => import('~/components/LaunchWeek/8/LW8Meetups')) const TicketContainer = dynamic(() => import('~/components/LaunchWeek/8/Ticket/TicketContainer')) const LaunchWeekPrizeSection = dynamic( () => import('~/components/LaunchWeek/8/LaunchWeekPrizeSection') @@ -29,6 +33,7 @@ const CTABanner = dynamic(() => import('~/components/CTABanner')) interface Props { users?: UserData[] + meetups?: Meetup[] } const supabaseAdmin = createClient( @@ -39,7 +44,7 @@ const supabaseAdmin = createClient( 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Im9idWxkYW5ycHRsb2t0eGNmZnZuIiwicm9sZSI6ImFub24iLCJpYXQiOjE2Njk3MjcwMTIsImV4cCI6MTk4NTMwMzAxMn0.SZLqryz_-stF8dgzeVXmzZWPOqdOrBwqJROlFES8v3I' ) -export default function TicketHome({ users }: Props) { +export default function TicketHome({ users, meetups }: Props) { const { query } = useRouter() const TITLE = 'Supabase LaunchWeek 8' @@ -63,7 +68,7 @@ export default function TicketHome({ users }: Props) { } const [userData, setUserData] = useState(defaultUserData) - const [pageState, setPageState] = useState('ticket') + const [_, setPageState] = useState('ticket') useEffect(() => { if (!supabase) { @@ -138,31 +143,48 @@ export default function TicketHome({ users }: Props) {
    - {supabase && } + starts background
    -
    - -
    +
    + +
    +
    + +
    + + +
    -
    + + + + + + + + +
    {supabase && (
    )}
    - - + + {users && }
    @@ -185,15 +207,19 @@ export default function TicketHome({ users }: Props) { ) } -export const getServerSideProps: GetServerSideProps = async ({ req, res }) => { +export const getServerSideProps: GetServerSideProps = async () => { // fetch users for the TicketBrickWall const { data: users } = await supabaseAdmin! .from('lw8_tickets_golden') - .select('username, golden', { count: 'exact' }) + .select('username, golden') + .limit(17) + + const { data: meetups } = await supabaseAdmin!.from('lw8_meetups').select('*') return { props: { users, + meetups, }, } } diff --git a/apps/www/pages/launch-week/tickets/[username].tsx b/apps/www/pages/launch-week/tickets/[username].tsx index 37808e679e4ab..0aa62979f24f7 100644 --- a/apps/www/pages/launch-week/tickets/[username].tsx +++ b/apps/www/pages/launch-week/tickets/[username].tsx @@ -114,7 +114,7 @@ export default function UsernamePage({ user, users, ogImageUrl }: Props) { )}
    -
    +
    -
    +
    {

    You can download our latest DPA document by submitting your email here.

    {formSubmitted ? ( -

    +

    Thank you for your submission! A new tab should have opened with the DPA document

    diff --git a/apps/www/pages/open-source/index.tsx b/apps/www/pages/open-source/index.tsx index 1aac63bdcbe8a..49d24b5515185 100644 --- a/apps/www/pages/open-source/index.tsx +++ b/apps/www/pages/open-source/index.tsx @@ -82,8 +82,8 @@ const OpenSource = () => { {maintainerPills.map((x) => (
  • setActivePill(x)} > diff --git a/apps/www/pages/partners/experts/[slug].tsx b/apps/www/pages/partners/experts/[slug].tsx index ffb5f8fe409bc..af94fef4e3c9f 100644 --- a/apps/www/pages/partners/experts/[slug].tsx +++ b/apps/www/pages/partners/experts/[slug].tsx @@ -160,7 +160,7 @@ function Partner({
    Category - + {partner.category} @@ -172,7 +172,7 @@ function Partner({ href={partner.website} target="_blank" rel="noreferrer" - className="text-brand-900 hover:text-brand-800 transition-colors" + className="text-brand hover:text-brand-300 transition-colors" > {new URL(partner.website).host} @@ -185,7 +185,7 @@ function Partner({ href={partner.docs} target="_blank" rel="noreferrer" - className="text-brand-900 hover:text-brand-800 transition-colors" + className="text-brand hover:text-brand-300 transition-colors" > Learn diff --git a/apps/www/pages/partners/experts/index.tsx b/apps/www/pages/partners/experts/index.tsx index d1f152a074b0d..eef756d787e62 100644 --- a/apps/www/pages/partners/experts/index.tsx +++ b/apps/www/pages/partners/experts/index.tsx @@ -78,11 +78,11 @@ function ExpertPartnersPage(props: Props) { fill="none" viewBox="0 0 24 24" stroke="currentColor" - stroke-width="1" + strokeWidth="1" > @@ -100,11 +100,11 @@ function ExpertPartnersPage(props: Props) { fill="none" viewBox="0 0 24 24" stroke="currentColor" - stroke-width="1" + strokeWidth="1" > diff --git a/apps/www/pages/partners/integrations/[slug].tsx b/apps/www/pages/partners/integrations/[slug].tsx index 95a87f58eba4f..76772b6646984 100644 --- a/apps/www/pages/partners/integrations/[slug].tsx +++ b/apps/www/pages/partners/integrations/[slug].tsx @@ -201,7 +201,7 @@ function Partner({
    Category - + {partner.category} @@ -213,7 +213,7 @@ function Partner({ href={partner.website} target="_blank" rel="noreferrer" - className="text-brand-900 hover:text-brand-800 transition-colors" + className="text-brand hover:text-brand-300 transition-colors" > {new URL(partner.website).host} @@ -226,7 +226,7 @@ function Partner({ href={partner.docs} target="_blank" rel="noreferrer" - className="text-brand-900 hover:text-brand-800 transition-colors" + className="text-brand hover:text-brand-300 transition-colors" > Learn diff --git a/apps/www/pages/partners/integrations/index.tsx b/apps/www/pages/partners/integrations/index.tsx index 8eba3c43e9bbe..eccd6d0ba2c6c 100644 --- a/apps/www/pages/partners/integrations/index.tsx +++ b/apps/www/pages/partners/integrations/index.tsx @@ -202,10 +202,10 @@ function IntegrationPartnersPage(props: Props) { INTEGRATIONS - EXPERTS + EXPERTS - + BECOME A PARTNER diff --git a/apps/www/pages/pricing/index.tsx b/apps/www/pages/pricing/index.tsx index 3940e1b06e60f..1cc52e0a39762 100644 --- a/apps/www/pages/pricing/index.tsx +++ b/apps/www/pages/pricing/index.tsx @@ -104,7 +104,7 @@ export default function IndexPage() { }) => { return (
    -

    +

    {plan}

    @@ -150,7 +150,7 @@ export default function IndexPage() {
    -

    Pricing

    +

    Pricing

    Predictable pricing, no surprises

    Start building for free, collaborate with a team, then scale to millions of users @@ -174,7 +174,7 @@ export default function IndexPage() { key={`row-${plan.name}`} className={[ plan.name === 'Pro' - ? 'bg-brand-1100 dark:bg-brand-900 border px-0.5 -mt-8 rounded-[6px]' + ? 'bg-brand-600 dark:bg-brand border px-0.5 -mt-8 rounded-[6px]' : '', ].join(' ')} > @@ -198,13 +198,13 @@ export default function IndexPage() {

    {plan.name}

    {plan.nameBadge && ( - + {plan.nameBadge} )} @@ -249,7 +249,7 @@ export default function IndexPage() { {plan.warning && (

    - + {plan.warning}

    @@ -273,7 +273,7 @@ export default function IndexPage() { {plan.features.map((feature) => (
  • ) } @@ -130,10 +134,15 @@ export interface IntegrationConnectionProps extends React.HTMLAttributes( - ({ className, connection, type, actions, ...props }, ref) => { + ( + { className, connection, type, actions, showNode = true, orientation = 'horizontal', ...props }, + ref + ) => { const { data: projects } = useProjectsQuery() const project = projects?.find((project) => project.ref === connection.supabase_project_ref) @@ -142,18 +151,31 @@ const IntegrationConnection = React.forwardRef -
    -
    -
    + {showNode && ( +
    + )} +
    +
    - {project?.name} + {project?.name} {!connection?.metadata?.framework ? (
    - +
    ) : ( {`icon`} )} - {connection.metadata?.name} + {connection.metadata?.name}
    - + Connected {dayjs(connection?.inserted_at).fromNow()} - + Added by {connection?.added_by?.primary_email}
    @@ -206,7 +228,7 @@ const IntegrationConnectionOption = React.forwardRef{connection.metadata.name}
    - + Connected {dayjs(connection.inserted_at).fromNow()}
    @@ -219,15 +241,23 @@ const IntegrationConnectionOption = React.forwardRef ->(({ className, ...props }, ref) => { + React.HTMLAttributes & { showNode?: boolean } +>(({ className, showNode = true, ...props }, ref) => { return (
    -
    + {showNode && ( +
    + )}
    void +} + +const OrganizationPicker = ({ + integrationName, + configurationId, + selectedOrg, + onSelectedOrgChange, +}: OrganizationPickerProps) => { + const [open, setOpen] = useState(false) + const ref = useRef(null) + + const { data: integrationData } = useIntegrationsQuery() + const { data: organizationsData, isLoading: isLoadingOrganization } = useOrganizationsQuery() + + const installed = useMemo( + () => + integrationData && organizationsData + ? getHasInstalledObject({ + integrationName, + integrationData, + organizationsData, + installationId: configurationId, + }) + : {}, + [configurationId, integrationData, integrationName, organizationsData] + ) + + return ( + <> + + + + + + + + + No results found. + + {organizationsData?.map((org) => { + return ( + { + const org = organizationsData?.find( + (org) => org.slug.toLowerCase() === slug.toLowerCase() + ) + if (org) { + onSelectedOrgChange(org) + } + + setOpen(false) + }} + > + + {org.name}{' '} + {configurationId && installed[org.slug] && ( + + Integration Installed + + )} + + ) + })} + + + + + + + ) +} + +export default OrganizationPicker diff --git a/studio/components/interfaces/Integrations/ProjectLinker.tsx b/studio/components/interfaces/Integrations/ProjectLinker.tsx index e220c54f1d291..2bebe5af4b789 100644 --- a/studio/components/interfaces/Integrations/ProjectLinker.tsx +++ b/studio/components/interfaces/Integrations/ProjectLinker.tsx @@ -1,13 +1,9 @@ -import { ENV_VAR_RAW_KEYS } from 'components/interfaces/Integrations/Integrations-Vercel.constants' -import { Markdown } from 'components/interfaces/Markdown' -import { vercelIcon } from 'components/to-be-cleaned/ListIcons' -import { useIntegrationConnectionsCreateMutation } from 'data/integrations/integration-connections-create-mutation' -import { useIntegrationsVercelConnectionSyncEnvsMutation } from 'data/integrations/integrations-vercel-connection-sync-envs-mutation' -import { VercelProjectsResponse } from 'data/integrations/integrations-vercel-projects-query' +import { ReactNode, useRef, useState } from 'react' + import { IntegrationProjectConnection } from 'data/integrations/integrations.types' +import { IntegrationConnectionsCreateVariables } from 'data/integrations/types' import { useSelectedOrganization } from 'hooks' import { BASE_PATH } from 'lib/constants' -import { useRef, useState } from 'react' import { toast } from 'react-hot-toast' import { Button, @@ -24,22 +20,33 @@ import { cn, } from 'ui' -interface Project { +export interface Project { id: string name: string ref: string } +export interface ForeignProject { + id: string + name: string +} + export interface ProjectLinkerProps { organizationIntegrationId: string | undefined - foreignProjects: VercelProjectsResponse[] + foreignProjects: ForeignProject[] supabaseProjects: Project[] - onCreateConnections?: () => void + onCreateConnections: (variables: IntegrationConnectionsCreateVariables) => void installedConnections: IntegrationProjectConnection[] | undefined - setLoading?: (x: boolean) => void - showSkip?: boolean + isLoading?: boolean + integrationIcon: ReactNode + getForeignProjectIcon?: (project: ForeignProject) => ReactNode + choosePrompt?: string + onSkip?: () => void loadingForeignProjects?: boolean loadingSupabaseProjects?: boolean + + defaultSupabaseProjectRef?: string + defaultForeignProjectId?: string } const ProjectLinker = ({ @@ -48,77 +55,63 @@ const ProjectLinker = ({ supabaseProjects, onCreateConnections: _onCreateConnections, installedConnections = [], - setLoading, - showSkip = false, + isLoading, + integrationIcon, + getForeignProjectIcon, + choosePrompt = 'Choose a project', + onSkip, loadingForeignProjects, loadingSupabaseProjects, + + defaultSupabaseProjectRef, + defaultForeignProjectId, }: ProjectLinkerProps) => { const [supabaseProjectsComboBoxOpen, setSupabaseProjectsComboboxOpen] = useState(false) - const [vercelProjectsComboBoxOpen, setVercelProjectsComboboxOpen] = useState(false) + const [foreignProjectsComboBoxOpen, setForeignProjectsComboboxOpen] = useState(false) const supabaseProjectsComboBoxRef = useRef(null) - const vercelProjectsComboBoxRef = useRef(null) + const foreignProjectsComboBoxRef = useRef(null) const selectedOrganization = useSelectedOrganization() - const [supabaseProjectRef, setSupabaseProjectRef] = useState(undefined) - const [vercelProjectId, setVercelProjectId] = useState(undefined) - - const { mutateAsync: syncEnvs } = useIntegrationsVercelConnectionSyncEnvsMutation() - const { mutate: createConnections, isLoading } = useIntegrationConnectionsCreateMutation({ - async onSuccess({ id }) { - try { - await syncEnvs({ connectionId: id }) - } catch (error: any) { - toast.error('Failed to sync environment variables: ', error.message) - } - - if (setLoading) setLoading(false) - _onCreateConnections?.() - }, - onError() { - if (setLoading) setLoading(false) - }, - }) + const [supabaseProjectRef, setSupabaseProjectRef] = useState( + defaultSupabaseProjectRef + ) + const [foreignProjectId, setForeignProjectId] = useState( + defaultForeignProjectId + ) // create a flat array of foreign project ids. ie, ["prj_MlkO6AiLG5ofS9ojKrkS3PhhlY3f", ..] const flatInstalledConnectionsIds = new Set(installedConnections.map((x) => x.foreign_project_id)) - // check that vercel project is not already installed - const filteredForeignProjects: VercelProjectsResponse[] = foreignProjects.filter( - (foreignProject) => { - return !flatInstalledConnectionsIds.has(foreignProject.id) - } - ) - const selectedSupabaseProject = supabaseProjectRef ? supabaseProjects.find((x) => x.ref?.toLowerCase() === supabaseProjectRef?.toLowerCase()) : undefined - const selectedVercelProject = vercelProjectId - ? filteredForeignProjects.find((x) => x.id?.toLowerCase() === vercelProjectId?.toLowerCase()) + const selectedForeignProject = foreignProjectId + ? foreignProjects.find((x) => x.id?.toLowerCase() === foreignProjectId?.toLowerCase()) : undefined function onCreateConnections() { - const projectDetails = selectedVercelProject + const projectDetails = selectedForeignProject if (!organizationIntegrationId) return console.error('No integration ID set') - if (!selectedVercelProject?.id) return console.error('No Vercel project ID set') + if (!selectedForeignProject?.id) return console.error('No Foreign project ID set') if (!selectedSupabaseProject?.ref) return console.error('No Supabase project ref set') - if (setLoading) setLoading(true) + const alreadyInstalled = flatInstalledConnectionsIds.has(foreignProjectId ?? '') + if (alreadyInstalled) { + return toast.error( + `Unable to connect to ${selectedForeignProject.name}: Selected repository already has an installed connection to a project` + ) + } - createConnections({ + _onCreateConnections({ organizationIntegrationId, connection: { - foreign_project_id: selectedVercelProject?.id, + foreign_project_id: selectedForeignProject?.id, supabase_project_ref: selectedSupabaseProject?.ref, metadata: { ...projectDetails, - supabaseConfig: { - projectEnvVars: { - write: true, - }, - }, }, }, orgSlug: selectedOrganization?.slug, @@ -162,7 +155,7 @@ const ProjectLinker = ({ type="default" size="medium" block - disabled={loadingSupabaseProjects} + disabled={defaultSupabaseProjectRef !== undefined || loadingSupabaseProjects} loading={loadingSupabaseProjects} className="justify-start" icon={ @@ -175,9 +168,11 @@ const ProjectLinker = ({
    } iconRight={ - - - + defaultSupabaseProjectRef === undefined ? ( + + + + ) : null } > {selectedSupabaseProject ? selectedSupabaseProject.name : 'Choose Project'} @@ -194,14 +189,14 @@ const ProjectLinker = ({ No results found. - {supabaseProjects.map((project) => { + {supabaseProjects.map((project, i) => { return ( { - if (ref) setSupabaseProjectRef(ref) + onSelect={() => { + if (project.ref) setSupabaseProjectRef(project.ref) setSupabaseProjectsComboboxOpen(false) }} > @@ -225,23 +220,16 @@ const ProjectLinker = ({
    - - - + {integrationIcon}
    No results found. - {filteredForeignProjects.map((project) => { + {foreignProjects.map((project, i) => { return ( { - if (id) setVercelProjectId(id) - setVercelProjectsComboboxOpen(false) + onSelect={() => { + if (project.id) setForeignProjectId(project.id) + setForeignProjectsComboboxOpen(false) }} > - {!project?.framework ? ( - vercelIcon - ) : ( - {`icon`} - )} + {getForeignProjectIcon?.(project) ?? integrationIcon} {project.name} ) @@ -319,12 +286,12 @@ const ProjectLinker = ({
    - {showSkip && ( + {onSkip !== undefined && (
    - { - return ` - \n - - \`${x}\` -` -})} -`} - />
    ) } diff --git a/studio/components/interfaces/Organization/AuditLogs/AuditLogs.tsx b/studio/components/interfaces/Organization/AuditLogs/AuditLogs.tsx index c463ce98397f5..7a864aef62627 100644 --- a/studio/components/interfaces/Organization/AuditLogs/AuditLogs.tsx +++ b/studio/components/interfaces/Organization/AuditLogs/AuditLogs.tsx @@ -132,7 +132,7 @@ const AuditLogs = () => { return ( Your organization has a log retention period of{' '} - + {retentionPeriod} day {retentionPeriod > 1 ? 's' : ''} diff --git a/studio/components/interfaces/Organization/BillingSettingsV2/Subscription/EnterpriseCard.tsx b/studio/components/interfaces/Organization/BillingSettingsV2/Subscription/EnterpriseCard.tsx index af9608f0dd0b0..cbf139f924ba6 100644 --- a/studio/components/interfaces/Organization/BillingSettingsV2/Subscription/EnterpriseCard.tsx +++ b/studio/components/interfaces/Organization/BillingSettingsV2/Subscription/EnterpriseCard.tsx @@ -18,13 +18,13 @@ const EnterpriseCard = ({ plan, isCurrentPlan }: EnterpriseCardProps) => { >
    -

    {plan.name}

    +

    {plan.name}

    {isCurrentPlan ? (
    Current plan
    ) : plan.nameBadge ? ( -
    +
    {plan.nameBadge}
    ) : null} @@ -43,7 +43,7 @@ const EnterpriseCard = ({ plan, isCurrentPlan }: EnterpriseCardProps) => {
      {plan.features.map((feature) => (
    • -
    • ))} diff --git a/studio/components/interfaces/Organization/BillingSettingsV2/Subscription/PlanUpdateSidePanel.tsx b/studio/components/interfaces/Organization/BillingSettingsV2/Subscription/PlanUpdateSidePanel.tsx index fd50323a60eb7..9ec255913b81a 100644 --- a/studio/components/interfaces/Organization/BillingSettingsV2/Subscription/PlanUpdateSidePanel.tsx +++ b/studio/components/interfaces/Organization/BillingSettingsV2/Subscription/PlanUpdateSidePanel.tsx @@ -7,7 +7,7 @@ import { useEffect, useState } from 'react' import ShimmeringLoader from 'components/ui/ShimmeringLoader' import { useOrgPlansQuery } from 'data/subscriptions/org-plans-query' import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query' -import { useOrgSubscriptionUpdateMutation } from 'data/subscriptions/org-subscription-update-mutation' +import { SubscriptionTier, useOrgSubscriptionUpdateMutation } from 'data/subscriptions/org-subscription-update-mutation' import { useCheckPermissions, useSelectedOrganization, useStore } from 'hooks' import { PRICING_TIER_PRODUCT_IDS } from 'lib/constants' import Telemetry from 'lib/telemetry' @@ -110,9 +110,14 @@ const PlanUpdateSidePanel = () => { return ui.setNotification({ category: 'error', message: 'Please select a payment method' }) } - updateOrgSubscription({ slug, tier: selectedTier, paymentMethod: selectedPaymentMethod }) + // If the user is downgrading from team, should have spend cap disabled by default + const tier = subscription?.plan?.id === 'team' && selectedTier === PRICING_TIER_PRODUCT_IDS.PRO ? PRICING_TIER_PRODUCT_IDS.PAYG as SubscriptionTier : selectedTier + + updateOrgSubscription({ slug, tier, paymentMethod: selectedPaymentMethod }) } + const planMeta = selectedTier ? availablePlans.find((p) => p.id === selectedTier.split('tier_')[1]) : null + return ( <> { >
      -

      {plan.name}

      +

      {plan.name}

      {isCurrentPlan ? (
      Current plan
      ) : plan.nameBadge ? ( -
      +
      {plan.nameBadge}
      ) : ( @@ -182,7 +187,7 @@ const PlanUpdateSidePanel = () => {

      {tierMeta?.costUnitOrg}

      -
      +
      {tierMeta?.warning}
      @@ -250,7 +255,7 @@ const PlanUpdateSidePanel = () => {