diff --git a/studio/components/interfaces/TableGridEditor/GridHeaderActions.tsx b/studio/components/interfaces/TableGridEditor/GridHeaderActions.tsx index 7490534beda..e8cc20c8e7f 100644 --- a/studio/components/interfaces/TableGridEditor/GridHeaderActions.tsx +++ b/studio/components/interfaces/TableGridEditor/GridHeaderActions.tsx @@ -1,13 +1,15 @@ import * as Tooltip from '@radix-ui/react-tooltip' import type { PostgresPolicy, PostgresTable } from '@supabase/postgres-meta' import { PermissionAction } from '@supabase/shared-types/out/constants' +import { useParams } from 'common' import Link from 'next/link' - -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' -import { useCheckPermissions, useStore } from 'hooks' -import { Button, IconAlertCircle, IconCode, IconLock } from 'ui' import { useEffect, useRef, useState } from 'react' -import { RLS_ACKNOWLEDGED_KEY, rlsAcknowledgedKey } from 'components/grid/constants' +import { Button, IconAlertCircle, IconCode, IconLock, IconZap, IconZapOff, Modal } from 'ui' + +import { rlsAcknowledgedKey } from 'components/grid/constants' +import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' +import ConfirmationModal from 'components/ui/ConfirmationModal' +import { useCheckPermissions, useStore } from 'hooks' export interface GridHeaderActionsProps { table: PostgresTable @@ -22,11 +24,23 @@ const GridHeaderActions = ({ setApiPreviewPanelOpen, refreshDocs, }: GridHeaderActionsProps) => { - const { meta } = useStore() + const { ref } = useParams() + const { meta, ui } = useStore() const { project } = useProjectContext() + + const [isTogglingRealtime, setIsTogglingRealtime] = useState(false) + const [showEnableRealtime, setShowEnableRealtime] = useState(false) + const projectRef = project?.ref + const publications = meta.publications.list() const policies = meta.policies.list((policy: PostgresPolicy) => policy.table_id === table.id) + const realtimePublication = publications.find( + (publication) => publication.name === 'supabase_realtime' + ) + const realtimeEnabledTables = realtimePublication?.tables ?? [] + const isRealtimeEnabled = realtimeEnabledTables.some((t: any) => t.id === table?.id) + const canSqlWriteTables = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'tables') const canSqlWriteColumns = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'columns') const isReadOnly = !canSqlWriteTables && !canSqlWriteColumns @@ -34,14 +48,11 @@ const GridHeaderActions = ({ const doesHaveAutoGeneratedAPIdocs = table.schema === 'public' const rlsKey = rlsAcknowledgedKey(table.id.toString()) - const rlsAcknowledgedChannel = useRef(new BroadcastChannel(rlsKey)) const [showRLSWarning, setShowRLSWarning] = useState( !table.rls_enabled && localStorage.getItem(rlsKey) === 'true' ) - const rlsDisabledMessage = 'RLS is not enabled' - useEffect(() => { if (rlsAcknowledgedChannel.current) { rlsAcknowledgedChannel.current.close() @@ -75,62 +86,134 @@ const GridHeaderActions = ({ ) } + const toggleRealtime = async () => { + if (!realtimePublication) return console.error('Unable to find realtime publication') + + setIsTogglingRealtime(true) + const exists = realtimeEnabledTables.some((x: any) => x.id == table.id) + const tables = !exists + ? [`${table.schema}.${table.name}`].concat( + realtimeEnabledTables.map((t: any) => `${t.schema}.${t.name}`) + ) + : realtimeEnabledTables + .filter((x: any) => x.id != table.id) + .map((x: any) => `${x.schema}.${x.name}`) + + try { + const id = realtimePublication.id + const payload = { tables, id } + const { error } = await meta.publications.update(id, payload) + if (error) throw error + setShowEnableRealtime(false) + } catch (error: any) { + ui.setNotification({ + category: 'error', + message: `Failed to toggle realtime for ${table.name}: ${error.message}`, + }) + } finally { + setIsTogglingRealtime(false) + } + } + return ( -
- {isReadOnly && ( - - -
- Viewing as read-only -
-
- - - -
- - You need additional permissions to manage your project's data - + <> +
+ {isReadOnly && ( + + +
+ Viewing as read-only
- - -
- )} + + + + +
+ + You need additional permissions to manage your project's data + +
+
+
+ + )} - {(table.rls_enabled || showRLSWarning) && ( - - - - - - )} + {(table.rls_enabled || showRLSWarning) && ( + + + + + + )} - {doesHaveAutoGeneratedAPIdocs && ( -
- -
- )} -
+ + + {doesHaveAutoGeneratedAPIdocs && ( +
+ +
+ )} +
+ + setShowEnableRealtime(false)} + onSelectConfirm={() => toggleRealtime()} + > + +

+ Any changes on this table will {isRealtimeEnabled && 'no longer '}be broadcasted to + authorized subscribers once realtime has been{' '} + {isRealtimeEnabled ? 'disabled' : 'enabled'}. +

+ {!isRealtimeEnabled && ( +

+ You may also select which events to broadcast to subscribers on the{' '} + + database replication + {' '} + settings. +

+ )} +
+
+ ) }