mirror of
https://github.com/supabase/supabase.git
synced 2026-10-18 23:59:08 +03:00
Merge branch 'master' into fix/schema-enums
This commit is contained in:
commit
1dc020dd2d
13 files changed
+131
-98
No files matched your search
+8
-8
@@ -3,11 +3,11 @@ import { Lock } from 'lucide-react'
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
import { useParams } from 'common'
|
||||
import { useTableEditorStateSnapshot } from 'state/table-editor'
|
||||
import { Button } from 'ui'
|
||||
import { generateAlterPolicyQuery, generateCreatePolicyQuery } from './AIPolicyEditorPanel.utils'
|
||||
|
||||
interface LockedCreateQuerySection {
|
||||
schema: string
|
||||
selectedPolicy?: PostgresPolicy
|
||||
formFields: { name: string; table: string; behavior: string; command: string; roles: string }
|
||||
editorOneRef: any
|
||||
@@ -15,6 +15,7 @@ interface LockedCreateQuerySection {
|
||||
}
|
||||
|
||||
export const LockedCreateQuerySection = ({
|
||||
schema,
|
||||
selectedPolicy,
|
||||
formFields,
|
||||
editorOneRef,
|
||||
@@ -22,7 +23,6 @@ export const LockedCreateQuerySection = ({
|
||||
}: LockedCreateQuerySection) => {
|
||||
const router = useRouter()
|
||||
const { ref } = useParams()
|
||||
const state = useTableEditorStateSnapshot()
|
||||
|
||||
const isEditing = selectedPolicy !== undefined
|
||||
const { name, table, behavior, command, roles } = formFields
|
||||
@@ -44,7 +44,7 @@ export const LockedCreateQuerySection = ({
|
||||
const query = isEditing
|
||||
? generateCreatePolicyQuery({
|
||||
name,
|
||||
schema: state.selectedSchemaName,
|
||||
schema,
|
||||
table,
|
||||
behavior,
|
||||
command,
|
||||
@@ -58,7 +58,7 @@ export const LockedCreateQuerySection = ({
|
||||
: generateAlterPolicyQuery({
|
||||
name: '',
|
||||
newName: name,
|
||||
schema: state.selectedSchemaName,
|
||||
schema,
|
||||
table,
|
||||
command,
|
||||
roles: roles.length === 0 ? 'public' : roles,
|
||||
@@ -84,7 +84,7 @@ export const LockedCreateQuerySection = ({
|
||||
<div className="flex items-start" style={{ fontSize: '14px' }}>
|
||||
<p className="px-6 font-mono text-sm text-foreground-light select-none">2</p>
|
||||
<p className="font-mono tracking-tighter">
|
||||
<span className="text-[#569cd6]">on</span> "{state.selectedSchemaName}"."
|
||||
<span className="text-[#569cd6]">on</span> "{schema}"."
|
||||
{table}"
|
||||
</p>
|
||||
</div>
|
||||
@@ -124,16 +124,16 @@ export const LockedCreateQuerySection = ({
|
||||
export const LockedRenameQuerySection = ({
|
||||
oldName,
|
||||
newName,
|
||||
schema,
|
||||
table,
|
||||
lineNumber,
|
||||
}: {
|
||||
oldName: string
|
||||
newName: string
|
||||
schema: string
|
||||
table: string
|
||||
lineNumber: number
|
||||
}) => {
|
||||
const state = useTableEditorStateSnapshot()
|
||||
|
||||
return (
|
||||
<div className="bg-surface-300 py-1">
|
||||
<div className="flex items-center" style={{ fontSize: '14px' }}>
|
||||
@@ -153,7 +153,7 @@ export const LockedRenameQuerySection = ({
|
||||
</p>
|
||||
</div>
|
||||
<p className="font-mono tracking-tighter">
|
||||
<span className="text-[#569cd6]">on</span> "{state.selectedSchemaName}"."{table}"
|
||||
<span className="text-[#569cd6]">on</span> "{schema}"."{table}"
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex items-center" style={{ fontSize: '14px' }}>
|
||||
|
||||
+5
-6
@@ -1,10 +1,8 @@
|
||||
import { useEffect } from 'react'
|
||||
|
||||
import { useParams } from 'common'
|
||||
import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext'
|
||||
import { useDatabaseRolesQuery } from 'data/database-roles/database-roles-query'
|
||||
import { useTablesQuery } from 'data/tables/tables-query'
|
||||
import { useTableEditorStateSnapshot } from 'state/table-editor'
|
||||
import {
|
||||
FormControl_Shadcn_,
|
||||
FormField_Shadcn_,
|
||||
@@ -24,6 +22,7 @@ import {
|
||||
import { MultiSelectV2 } from 'ui-patterns/MultiSelect/MultiSelectV2'
|
||||
|
||||
interface PolicyDetailsV2Props {
|
||||
schema: string
|
||||
searchString?: string
|
||||
isEditing: boolean
|
||||
form: any
|
||||
@@ -31,18 +30,18 @@ interface PolicyDetailsV2Props {
|
||||
}
|
||||
|
||||
export const PolicyDetailsV2 = ({
|
||||
schema,
|
||||
searchString,
|
||||
isEditing,
|
||||
form,
|
||||
onUpdateCommand,
|
||||
}: PolicyDetailsV2Props) => {
|
||||
const { project } = useProjectContext()
|
||||
const snap = useTableEditorStateSnapshot()
|
||||
|
||||
const { data: tables, isSuccess: isSuccessTables } = useTablesQuery({
|
||||
projectRef: project?.ref,
|
||||
connectionString: project?.connectionString,
|
||||
schema: snap.selectedSchemaName,
|
||||
schema: schema,
|
||||
sortByProperty: 'name',
|
||||
includeColumns: true,
|
||||
})
|
||||
@@ -66,7 +65,7 @@ export const PolicyDetailsV2 = ({
|
||||
if (!isEditing) {
|
||||
const table = tables?.find(
|
||||
(table) =>
|
||||
table.schema === snap.selectedSchemaName &&
|
||||
table.schema === schema &&
|
||||
(table.id.toString() === searchString || table.name === searchString)
|
||||
)
|
||||
if (table) {
|
||||
@@ -117,7 +116,7 @@ export const PolicyDetailsV2 = ({
|
||||
onValueChange={(value) => form.setValue('table', value)}
|
||||
>
|
||||
<SelectTrigger_Shadcn_ className="text-sm h-10">
|
||||
{snap.selectedSchemaName}.{field.value}
|
||||
{schema}.{field.value}
|
||||
</SelectTrigger_Shadcn_>
|
||||
<SelectContent_Shadcn_>
|
||||
<SelectGroup_Shadcn_>
|
||||
|
||||
+3
-6
@@ -9,9 +9,9 @@ import CardButton from 'components/ui/CardButton'
|
||||
import CopyButton from 'components/ui/CopyButton'
|
||||
import NoSearchResults from 'components/ui/NoSearchResults'
|
||||
import { getGeneralPolicyTemplates } from '../PolicyEditorModal/PolicyEditorModal.constants'
|
||||
import { useTableEditorStateSnapshot } from 'state/table-editor'
|
||||
|
||||
interface PolicyTemplatesProps {
|
||||
schema: string
|
||||
table: string
|
||||
selectedPolicy?: PostgresPolicy
|
||||
selectedTemplate?: string
|
||||
@@ -19,17 +19,14 @@ interface PolicyTemplatesProps {
|
||||
}
|
||||
|
||||
export const PolicyTemplates = ({
|
||||
schema,
|
||||
table,
|
||||
selectedPolicy,
|
||||
selectedTemplate,
|
||||
onSelectTemplate,
|
||||
}: PolicyTemplatesProps) => {
|
||||
const [search, setSearch] = useState('')
|
||||
const state = useTableEditorStateSnapshot()
|
||||
const templates = getGeneralPolicyTemplates(
|
||||
state.selectedSchemaName,
|
||||
table.length > 0 ? table : 'table_name'
|
||||
)
|
||||
const templates = getGeneralPolicyTemplates(schema, table.length > 0 ? table : 'table_name')
|
||||
|
||||
const baseTemplates =
|
||||
selectedPolicy !== undefined
|
||||
|
||||
@@ -15,7 +15,6 @@ import {
|
||||
Checkbox_Shadcn_,
|
||||
Form_Shadcn_,
|
||||
Label_Shadcn_,
|
||||
Modal,
|
||||
ScrollArea,
|
||||
Sheet,
|
||||
SheetContent,
|
||||
@@ -45,7 +44,6 @@ import { useSelectedOrganization, useSelectedProject } from 'hooks'
|
||||
import { BASE_PATH, OPT_IN_TAGS } from 'lib/constants'
|
||||
import { uuidv4 } from 'lib/helpers'
|
||||
import Telemetry from 'lib/telemetry'
|
||||
import { useTableEditorStateSnapshot } from 'state/table-editor'
|
||||
import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal'
|
||||
import { AIPolicyChat } from './AIPolicyChat'
|
||||
import {
|
||||
@@ -70,6 +68,7 @@ const DiffEditor = dynamic(
|
||||
|
||||
interface AIPolicyEditorPanelProps {
|
||||
visible: boolean
|
||||
schema: string
|
||||
searchString?: string
|
||||
selectedPolicy?: PostgresPolicy
|
||||
onSelectCancel: () => void
|
||||
@@ -80,6 +79,7 @@ interface AIPolicyEditorPanelProps {
|
||||
*/
|
||||
export const AIPolicyEditorPanel = memo(function ({
|
||||
visible,
|
||||
schema,
|
||||
searchString,
|
||||
selectedPolicy,
|
||||
onSelectCancel,
|
||||
@@ -91,7 +91,6 @@ export const AIPolicyEditorPanel = memo(function ({
|
||||
const selectedOrganization = useSelectedOrganization()
|
||||
|
||||
const telemetryProps = useTelemetryProps()
|
||||
const state = useTableEditorStateSnapshot()
|
||||
const isAiAssistantEnabled = useIsRLSAIAssistantEnabled()
|
||||
|
||||
// [Joshen] Hyrid form fields, just spit balling to get a decent POC out
|
||||
@@ -330,7 +329,7 @@ export const AIPolicyEditorPanel = memo(function ({
|
||||
if (selectedPolicy === undefined) {
|
||||
const sql = generateCreatePolicyQuery({
|
||||
name: name,
|
||||
schema: state.selectedSchemaName,
|
||||
schema,
|
||||
table,
|
||||
behavior,
|
||||
command,
|
||||
@@ -534,6 +533,7 @@ export const AIPolicyEditorPanel = memo(function ({
|
||||
) : (
|
||||
<>
|
||||
<PolicyDetailsV2
|
||||
schema={schema}
|
||||
searchString={searchString}
|
||||
isEditing={selectedPolicy !== undefined}
|
||||
form={form}
|
||||
@@ -544,6 +544,7 @@ export const AIPolicyEditorPanel = memo(function ({
|
||||
/>
|
||||
<div className="h-full">
|
||||
<LockedCreateQuerySection
|
||||
schema={schema}
|
||||
selectedPolicy={selectedPolicy}
|
||||
editorOneRef={editorOneRef}
|
||||
editorTwoRef={editorTwoRef}
|
||||
@@ -670,6 +671,7 @@ export const AIPolicyEditorPanel = memo(function ({
|
||||
<LockedRenameQuerySection
|
||||
oldName={selectedPolicy.name}
|
||||
newName={name}
|
||||
schema={schema}
|
||||
table={table}
|
||||
lineNumber={
|
||||
8 + expOneLineCount + (showCheckBlock ? expTwoLineCount : 0)
|
||||
@@ -789,6 +791,7 @@ export const AIPolicyEditorPanel = memo(function ({
|
||||
>
|
||||
<ScrollArea className="h-full w-full">
|
||||
<PolicyTemplates
|
||||
schema={schema}
|
||||
table={table}
|
||||
selectedPolicy={selectedPolicy}
|
||||
selectedTemplate={selectedDiff}
|
||||
|
||||
@@ -14,10 +14,10 @@ import ProductEmptyState from 'components/to-be-cleaned/ProductEmptyState'
|
||||
import InformationBox from 'components/ui/InformationBox'
|
||||
import { useDatabasePolicyDeleteMutation } from 'data/database-policies/database-policy-delete-mutation'
|
||||
import { useTableUpdateMutation } from 'data/tables/table-update-mutation'
|
||||
import { useTableEditorStateSnapshot } from 'state/table-editor'
|
||||
import ConfirmModal from 'ui-patterns/Dialogs/ConfirmDialog'
|
||||
|
||||
interface PoliciesProps {
|
||||
schema: string
|
||||
tables: PostgresTable[]
|
||||
hasTables: boolean
|
||||
isLocked: boolean
|
||||
@@ -25,6 +25,7 @@ interface PoliciesProps {
|
||||
}
|
||||
|
||||
const Policies = ({
|
||||
schema,
|
||||
tables,
|
||||
hasTables,
|
||||
isLocked,
|
||||
@@ -33,7 +34,6 @@ const Policies = ({
|
||||
const router = useRouter()
|
||||
const { ref } = useParams()
|
||||
const { project } = useProjectContext()
|
||||
const snap = useTableEditorStateSnapshot()
|
||||
|
||||
const [selectedTableToToggleRLS, setSelectedTableToToggleRLS] = useState<any>({})
|
||||
const [selectedPolicyToDelete, setSelectedPolicyToDelete] = useState<any>({})
|
||||
@@ -137,7 +137,7 @@ const Policies = ({
|
||||
return (
|
||||
<>
|
||||
<div className="flex flex-col gap-y-4 pb-4">
|
||||
{isLocked && <ProtectedSchemaWarning schema={snap.selectedSchemaName} entity="policies" />}
|
||||
{isLocked && <ProtectedSchemaWarning schema={schema} entity="policies" />}
|
||||
{tables.length > 0 ? (
|
||||
tables.map((table: any) => (
|
||||
<section key={table.id}>
|
||||
|
||||
@@ -162,7 +162,7 @@ const GridHeaderActions = ({ table, isViewSelected, isTableSelected }: GridHeade
|
||||
>
|
||||
<Link
|
||||
passHref
|
||||
href={`/project/${projectRef}/auth/policies?search=${table.id}`}
|
||||
href={`/project/${projectRef}/auth/policies?search=${table.id}&schema=${table.schema}`}
|
||||
>
|
||||
Add RLS policy
|
||||
</Link>
|
||||
@@ -202,7 +202,10 @@ const GridHeaderActions = ({ table, isViewSelected, isTableSelected }: GridHeade
|
||||
)
|
||||
}
|
||||
>
|
||||
<Link passHref href={`/project/${projectRef}/auth/policies?search=${table.id}`}>
|
||||
<Link
|
||||
passHref
|
||||
href={`/project/${projectRef}/auth/policies?search=${table.id}&schema=${table.schema}`}
|
||||
>
|
||||
Auth {policies.length > 1 ? 'policies' : 'policy'}
|
||||
</Link>
|
||||
</Button>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { useCallback } from 'react'
|
||||
import { useRouter } from 'next/router'
|
||||
import { Dispatch, SetStateAction, useCallback, useMemo } from 'react'
|
||||
|
||||
export type UrlStateParams = {
|
||||
[k: string]: string | string[] | undefined
|
||||
}
|
||||
|
||||
export function useUrlState({
|
||||
export function useUrlState<ValueParams extends UrlStateParams>({
|
||||
replace = true,
|
||||
arrayKeys = [],
|
||||
}: {
|
||||
@@ -14,22 +14,26 @@ export function useUrlState({
|
||||
*/
|
||||
replace?: boolean
|
||||
arrayKeys?: string[]
|
||||
} = {}) {
|
||||
const arrayKeysSet = new Set(arrayKeys)
|
||||
} = {}): [ValueParams, Dispatch<SetStateAction<ValueParams>>] {
|
||||
const stringifiedArrayKeys = JSON.stringify(arrayKeys)
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
const arrayKeysSet = useMemo(() => new Set(arrayKeys), [stringifiedArrayKeys])
|
||||
const router = useRouter()
|
||||
|
||||
const params: UrlStateParams = Object.fromEntries(
|
||||
Object.entries(router.query).map(([key, value]) => {
|
||||
if (arrayKeysSet.has(key)) {
|
||||
return Array.isArray(value) ? [key, value] : [key, [value]]
|
||||
}
|
||||
const params: ValueParams = useMemo(() => {
|
||||
return Object.fromEntries(
|
||||
Object.entries(router.query).map(([key, value]) => {
|
||||
if (arrayKeysSet.has(key)) {
|
||||
return Array.isArray(value) ? [key, value] : [key, [value]]
|
||||
}
|
||||
|
||||
return [key, value]
|
||||
})
|
||||
)
|
||||
return [key, value]
|
||||
})
|
||||
)
|
||||
}, [arrayKeysSet, router.query])
|
||||
|
||||
const setParams = useCallback(
|
||||
(newParams: UrlStateParams | ((previousParams: UrlStateParams) => UrlStateParams)) => {
|
||||
const setParams: Dispatch<SetStateAction<ValueParams>> = useCallback(
|
||||
(newParams) => {
|
||||
const nextParams = typeof newParams === 'function' ? newParams(params) : newParams
|
||||
let newQuery = Object.fromEntries(
|
||||
Object.entries({ ...params, ...nextParams }).filter(([, value]) => Boolean(value))
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
import type { PostgresPolicy, PostgresTable } from '@supabase/postgres-meta'
|
||||
import { PermissionAction } from '@supabase/shared-types/out/constants'
|
||||
import { partition } from 'lodash'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useState } from 'react'
|
||||
|
||||
import { useParams } from 'common'
|
||||
import { useIsRLSAIAssistantEnabled } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext'
|
||||
import { Policies } from 'components/interfaces/Auth/Policies'
|
||||
import { AIPolicyEditorPanel } from 'components/interfaces/Auth/Policies/AIPolicyEditorPanel'
|
||||
import { AuthLayout } from 'components/layouts'
|
||||
@@ -16,9 +13,9 @@ import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader'
|
||||
import { useDatabasePoliciesQuery } from 'data/database-policies/database-policies-query'
|
||||
import { useSchemasQuery } from 'data/database/schemas-query'
|
||||
import { useTablesQuery } from 'data/tables/tables-query'
|
||||
import { useCheckPermissions, usePermissionsLoaded } from 'hooks'
|
||||
import { useCheckPermissions, usePermissionsLoaded, useUrlState } from 'hooks'
|
||||
import { EXCLUDED_SCHEMAS } from 'lib/constants/schemas'
|
||||
import { useTableEditorStateSnapshot } from 'state/table-editor'
|
||||
import { partition } from 'lodash'
|
||||
import type { NextPageWithLayout } from 'types'
|
||||
import {
|
||||
Button,
|
||||
@@ -66,22 +63,16 @@ const onFilterTables = (
|
||||
}
|
||||
|
||||
const AuthPoliciesPage: NextPageWithLayout = () => {
|
||||
const { search, schema } = useParams()
|
||||
const [params, setParams] = useUrlState<{
|
||||
schema?: string
|
||||
search?: string
|
||||
}>()
|
||||
const { schema = 'public', search: searchString = '' } = params
|
||||
const { project } = useProjectContext()
|
||||
const snap = useTableEditorStateSnapshot()
|
||||
const [searchString, setSearchString] = useState<string>('')
|
||||
|
||||
const [showPolicyAiEditor, setShowPolicyAiEditor] = useState(false)
|
||||
const [selectedPolicyToEdit, setSelectedPolicyToEdit] = useState<PostgresPolicy>()
|
||||
|
||||
useEffect(() => {
|
||||
if (search) setSearchString(search)
|
||||
}, [search])
|
||||
|
||||
useEffect(() => {
|
||||
if (schema) snap.setSelectedSchemaName(schema)
|
||||
}, [schema])
|
||||
|
||||
const { data: schemas } = useSchemasQuery({
|
||||
projectRef: project?.ref,
|
||||
connectionString: project?.connectionString,
|
||||
@@ -89,7 +80,7 @@ const AuthPoliciesPage: NextPageWithLayout = () => {
|
||||
const [protectedSchemas] = partition(schemas, (schema) =>
|
||||
EXCLUDED_SCHEMAS.includes(schema?.name ?? '')
|
||||
)
|
||||
const selectedSchema = schemas?.find((schema) => schema.name === snap.selectedSchemaName)
|
||||
const selectedSchema = schemas?.find((s) => s.name === schema)
|
||||
const isLocked = protectedSchemas.some((s) => s.id === selectedSchema?.id)
|
||||
|
||||
const { data: policies } = useDatabasePoliciesQuery({
|
||||
@@ -106,7 +97,7 @@ const AuthPoliciesPage: NextPageWithLayout = () => {
|
||||
} = useTablesQuery({
|
||||
projectRef: project?.ref,
|
||||
connectionString: project?.connectionString,
|
||||
schema: snap.selectedSchemaName,
|
||||
schema: schema,
|
||||
})
|
||||
|
||||
const filteredTables = onFilterTables(tables ?? [], policies ?? [], searchString)
|
||||
@@ -128,18 +119,20 @@ const AuthPoliciesPage: NextPageWithLayout = () => {
|
||||
className="w-[260px]"
|
||||
size="small"
|
||||
showError={false}
|
||||
selectedSchemaName={snap.selectedSchemaName}
|
||||
onSelectSchema={(schema: string) => {
|
||||
snap.setSelectedSchemaName(schema)
|
||||
setSearchString('')
|
||||
selectedSchemaName={schema}
|
||||
onSelectSchema={(schema) => {
|
||||
setParams({ ...params, search: undefined, schema })
|
||||
}}
|
||||
/>
|
||||
<Input
|
||||
size="small"
|
||||
placeholder="Filter tables and policies"
|
||||
className="block w-64 text-sm placeholder-border-muted"
|
||||
value={searchString}
|
||||
onChange={(e) => setSearchString(e.target.value)}
|
||||
value={searchString || ''}
|
||||
onChange={(e) => {
|
||||
const str = e.target.value
|
||||
setParams({ ...params, search: str === '' ? undefined : str })
|
||||
}}
|
||||
icon={<IconSearch size="tiny" />}
|
||||
/>
|
||||
</div>
|
||||
@@ -169,7 +162,7 @@ const AuthPoliciesPage: NextPageWithLayout = () => {
|
||||
{!canCreatePolicies
|
||||
? 'You need additional permissions to create RLS policies'
|
||||
: schemaHasNoTables
|
||||
? `No table in schema ${snap.selectedSchemaName} to create policies on`
|
||||
? `No table in schema ${schema} to create policies on`
|
||||
: null}
|
||||
</TooltipContent_Shadcn_>
|
||||
)}
|
||||
@@ -184,6 +177,7 @@ const AuthPoliciesPage: NextPageWithLayout = () => {
|
||||
|
||||
{isSuccess && (
|
||||
<Policies
|
||||
schema={schema}
|
||||
tables={filteredTables}
|
||||
hasTables={tables.length > 0}
|
||||
isLocked={isLocked}
|
||||
@@ -196,6 +190,7 @@ const AuthPoliciesPage: NextPageWithLayout = () => {
|
||||
|
||||
<AIPolicyEditorPanel
|
||||
visible={showPolicyAiEditor}
|
||||
schema={schema}
|
||||
searchString={searchString}
|
||||
selectedPolicy={selectedPolicyToEdit}
|
||||
onSelectCancel={() => {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import Nav from 'components/Nav/index'
|
||||
import Footer from 'components/Footer/index'
|
||||
import { cn } from 'ui'
|
||||
import { useForceDeepDark } from '~/lib/theme.utils'
|
||||
|
||||
type Props = {
|
||||
hideHeader?: boolean
|
||||
@@ -19,6 +20,8 @@ const DefaultLayout = (props: Props) => {
|
||||
children,
|
||||
} = props
|
||||
|
||||
useForceDeepDark()
|
||||
|
||||
return (
|
||||
<>
|
||||
<Nav hideNavbar={hideHeader} />
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
import { useEffect } from 'react'
|
||||
import { useTheme } from 'next-themes'
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
export function useForceDeepDark() {
|
||||
const router = useRouter()
|
||||
const { resolvedTheme, theme } = useTheme()
|
||||
|
||||
const isDarkTheme = resolvedTheme?.includes('dark')
|
||||
const isGaSection = router.pathname.includes('/ga-week') || router.pathname === '/ga'
|
||||
|
||||
useEffect(() => {
|
||||
const handleDocumentLoad = () => {
|
||||
// Update the HTML element attributes
|
||||
const theme = isDarkTheme ? (isGaSection ? 'deep-dark' : 'dark') : 'light'
|
||||
|
||||
document.documentElement.setAttribute('data-theme', theme)
|
||||
document.documentElement.style.colorScheme = theme
|
||||
|
||||
// wait before setting the theme
|
||||
setTimeout(() => {
|
||||
document.documentElement.setAttribute('data-theme', theme)
|
||||
document.documentElement.style.colorScheme = theme
|
||||
}, 200)
|
||||
|
||||
// Clean up the event listener
|
||||
window.removeEventListener('load', handleDocumentLoad)
|
||||
}
|
||||
|
||||
// Check if document is already loaded
|
||||
if (document.readyState === 'complete') {
|
||||
handleDocumentLoad()
|
||||
} else {
|
||||
// Add a global load event listener
|
||||
window.addEventListener('load', handleDocumentLoad)
|
||||
}
|
||||
|
||||
// Clean up the event listener on component unmount
|
||||
return () => {
|
||||
window.removeEventListener('load', handleDocumentLoad)
|
||||
}
|
||||
}, [resolvedTheme, theme, isDarkTheme, router])
|
||||
}
|
||||
@@ -14,7 +14,6 @@ import { Meetup } from '~/components/LaunchWeek/11/LW11Meetups'
|
||||
import LW11StickyNav from '~/components/LaunchWeek/11/Releases/LW11StickyNav'
|
||||
import LW11Header from '~/components/LaunchWeek/11/Releases/LW11Header'
|
||||
import MainStage from '~/components/LaunchWeek/11/Releases/MainStage'
|
||||
import { useTheme } from 'next-themes'
|
||||
|
||||
const BuildStage = dynamic(() => import('~/components/LaunchWeek/11/Releases/BuildStage'))
|
||||
const LW11Meetups = dynamic(() => import('~/components/LaunchWeek/11/LW11Meetups'))
|
||||
@@ -29,7 +28,6 @@ interface Props {
|
||||
|
||||
export default function GAWeekIndex({ meetups }: Props) {
|
||||
const { query } = useRouter()
|
||||
const { resolvedTheme, setTheme } = useTheme()
|
||||
|
||||
const TITLE = 'Supabase GA Week | 15-19 April 2024'
|
||||
const DESCRIPTION = 'Join us for a week of announcing new features, every day at 7 AM PT.'
|
||||
@@ -65,19 +63,6 @@ export default function GAWeekIndex({ meetups }: Props) {
|
||||
}
|
||||
}, [supabase])
|
||||
|
||||
const isDark = resolvedTheme?.includes('dark')
|
||||
const isDarkTheme = resolvedTheme === 'dark'
|
||||
|
||||
useEffect(() => {
|
||||
isDarkTheme && setTheme('deep-dark')
|
||||
}, [isDarkTheme])
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
isDark && setTheme('dark')
|
||||
}
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
if (session?.user) {
|
||||
if (userData?.id) {
|
||||
|
||||
+2
-14
@@ -1,4 +1,4 @@
|
||||
import React, { useEffect } from 'react'
|
||||
import React from 'react'
|
||||
import dynamic from 'next/dynamic'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
@@ -19,7 +19,7 @@ const CTABanner = dynamic(() => import('~/components/CTABanner'))
|
||||
|
||||
export default function IndexPage() {
|
||||
const router = useRouter()
|
||||
const { resolvedTheme, setTheme } = useTheme()
|
||||
const { resolvedTheme } = useTheme()
|
||||
const isDark = resolvedTheme?.includes('dark')
|
||||
const data = pageData(isDark!)
|
||||
|
||||
@@ -27,18 +27,6 @@ export default function IndexPage() {
|
||||
const meta_description = 'Supabase is officially launching into General Availability.'
|
||||
const meta_image = '/images/ga/ga-og-alt.png'
|
||||
|
||||
const isDarkTheme = resolvedTheme === 'dark'
|
||||
|
||||
useEffect(() => {
|
||||
isDarkTheme && setTheme('deep-dark')
|
||||
}, [isDarkTheme])
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
isDark && setTheme('dark')
|
||||
}
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<DefaultLayout>
|
||||
<NextSeo
|
||||
|
||||
@@ -152,6 +152,19 @@ export const pricing: Pricing = {
|
||||
},
|
||||
usage_based: true,
|
||||
},
|
||||
{
|
||||
title: 'Anonymous Sign-ins',
|
||||
tooltips: {
|
||||
main: 'Anonymous user requests count towards MAU, just like a permanent user.',
|
||||
},
|
||||
plans: {
|
||||
free: true,
|
||||
pro: true,
|
||||
team: true,
|
||||
enterprise: true,
|
||||
},
|
||||
usage_based: false,
|
||||
},
|
||||
{
|
||||
title: 'Social OAuth providers',
|
||||
plans: {
|
||||
|
||||
Reference in new issue
Block a user