diff --git a/apps/docs/components/AuthProviders.tsx b/apps/docs/components/AuthProviders.tsx index 3c901f50ac..ec9b59a1e3 100644 --- a/apps/docs/components/AuthProviders.tsx +++ b/apps/docs/components/AuthProviders.tsx @@ -9,10 +9,13 @@ export default function AuthProviders({ type }: { type: string }) { <>
{filterProviders.map((x) => ( - - - - + + ))}
diff --git a/apps/docs/components/ButtonCard.tsx b/apps/docs/components/ButtonCard.tsx index f1aa4caefb..8c5a997071 100644 --- a/apps/docs/components/ButtonCard.tsx +++ b/apps/docs/components/ButtonCard.tsx @@ -1,6 +1,6 @@ -import React, { FC, ReactNode } from 'react' +import Image from 'next/legacy/image' import Link from 'next/link' -import Image from 'next/image' +import { FC } from 'react' interface Props { title: string @@ -20,34 +20,33 @@ const ButtonCard: FC = ({ layout = 'vertical', }) => { return ( - - - {children ? ( - children - ) : ( -
- {icon && typeof icon == 'string' ? ( -
- {title} -
- ) : ( - icon - )} -

{title}

-

{description}

-
- )} -
+ + {children ? ( + children + ) : ( +
+ {icon && typeof icon == 'string' ? ( +
+ {title} +
+ ) : ( + icon + )} +

{title}

+

{description}

+
+ )} ) } diff --git a/apps/docs/components/CustomHTMLElements/Heading.tsx b/apps/docs/components/CustomHTMLElements/Heading.tsx index 336dba4d0f..7ef568146c 100644 --- a/apps/docs/components/CustomHTMLElements/Heading.tsx +++ b/apps/docs/components/CustomHTMLElements/Heading.tsx @@ -28,7 +28,7 @@ interface Props { * need to parse the and generate anchors. Custom anchors are used in tsx files. * (see: /pages/guides/cli/config.tsx) */ -const Heading: React.FC = ({ tag, customAnchor, children }) => { +const Heading: React.FC> = ({ tag, customAnchor, children }) => { const HeadingTag = `${tag}` as any const anchor = customAnchor ? customAnchor : getAnchor(children) const link = `#${anchor}` diff --git a/apps/docs/components/Extensions.tsx b/apps/docs/components/Extensions.tsx index 8740be6787..4c627b6688 100644 --- a/apps/docs/components/Extensions.tsx +++ b/apps/docs/components/Extensions.tsx @@ -105,14 +105,16 @@ export default function Extensions() { filters.length === 0 ? x : x.tags.some((item) => filters.includes(item)) ) .map((extension) => ( - - - -

- {extension.comment.charAt(0).toUpperCase() + extension.comment.slice(1)} -

-
-
+ + +

+ {extension.comment.charAt(0).toUpperCase() + extension.comment.slice(1)} +

+
//
//
diff --git a/apps/docs/components/Flag/FlagProvider.tsx b/apps/docs/components/Flag/FlagProvider.tsx index 4cb3f362fa..9e777ea190 100644 --- a/apps/docs/components/Flag/FlagProvider.tsx +++ b/apps/docs/components/Flag/FlagProvider.tsx @@ -1,8 +1,8 @@ -import { FC, useEffect, useState } from 'react' +import { FC, PropsWithChildren, useEffect, useState } from 'react' // import createConfigCatClient from 'configcat-js' import FlagContext from './FlagContext' -const FlagProvider: FC = ({ children }) => { +const FlagProvider: FC> = ({ children }) => { const [store, setStore] = useState({}) const { Provider } = FlagContext diff --git a/apps/docs/components/HomePageCover.tsx b/apps/docs/components/HomePageCover.tsx index 1d887ae3dc..9487e0fc52 100644 --- a/apps/docs/components/HomePageCover.tsx +++ b/apps/docs/components/HomePageCover.tsx @@ -84,15 +84,13 @@ const HomePageCover = (props) => {
{frameworks.map((framework, i) => ( - - - - + + ))}
diff --git a/apps/docs/components/JwtGenerator.js b/apps/docs/components/JwtGenerator.js index f435a6db78..884f5fd0af 100644 --- a/apps/docs/components/JwtGenerator.js +++ b/apps/docs/components/JwtGenerator.js @@ -1,6 +1,6 @@ -import React, { useState } from 'react' import KJUR from 'jsrsasign' -import { Button, Select, Input, CodeBlock } from 'ui' +import { useState } from 'react' +import { Button, CodeBlock, Input, Select } from 'ui' const JWT_HEADER = { alg: 'HS256', typ: 'JWT' } const now = new Date() @@ -44,7 +44,7 @@ export default function JwtGenerator({}) { return (
- +
- + - - {description ? ( - <> -

{title}

-

{description}

- - ) : ( -
- {icon} -

{title}

-
- )} -
+ + {description ? ( + <> +

{title}

+

{description}

+ + ) : ( +
+ {icon} +

{title}

+
+ )} ) } diff --git a/apps/docs/components/Navigation/Footer.tsx b/apps/docs/components/Navigation/Footer.tsx index b18b0880b7..c5d89404ca 100644 --- a/apps/docs/components/Navigation/Footer.tsx +++ b/apps/docs/components/Navigation/Footer.tsx @@ -28,10 +28,13 @@ const Footer = () => ( )} {Icon && }

{text}

- - - {ctaLabel} - + + {ctaLabel} ))} @@ -40,14 +43,14 @@ const Footer = () => (
- - © Supabase Inc + + © Supabase Inc {secondaryLinks.map(({ component: Component, ...item }) => item.url ? ( - - {item.title} + + {item.title} ) : ( Component && ( diff --git a/apps/docs/components/Navigation/NavigationMenu/HomeMenu.tsx b/apps/docs/components/Navigation/NavigationMenu/HomeMenu.tsx index 9800235c5f..28fa29b18f 100644 --- a/apps/docs/components/Navigation/NavigationMenu/HomeMenu.tsx +++ b/apps/docs/components/Navigation/NavigationMenu/HomeMenu.tsx @@ -35,22 +35,20 @@ const NavigationMenuHome = () => { } else { return ( - -
  • - {link?.icon && } - {link.label} - {link.community && ( - - Community - - )} -
  • -
    +
  • + {link?.icon && } + {link.label} + {link.community && ( + + Community + + )} +
  • ) } diff --git a/apps/docs/components/Navigation/NavigationMenu/HomeMenuIcons.tsx b/apps/docs/components/Navigation/NavigationMenu/HomeMenuIcons.tsx index 09ed2ae29f..d2b0636a8b 100644 --- a/apps/docs/components/Navigation/NavigationMenu/HomeMenuIcons.tsx +++ b/apps/docs/components/Navigation/NavigationMenu/HomeMenuIcons.tsx @@ -313,8 +313,8 @@ export function IconMenuPlatform({ width = 16, height = 16 }: HomeMenuIcon) { xmlns="http://www.w3.org/2000/svg" > diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenuCliList.tsx b/apps/docs/components/Navigation/NavigationMenu/NavigationMenuCliList.tsx index 8c88d73156..7b30483e63 100644 --- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenuCliList.tsx +++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenuCliList.tsx @@ -22,11 +22,12 @@ const NavigationMenuCliList = ({ currentLevel, setLevel, id }) => { }) => { return (
  • - - - {icon && } - {title} - + + {icon && } + {title}
  • ) @@ -96,20 +97,19 @@ const NavigationMenuCliList = ({ currentLevel, setLevel, id }) => { ].join(' ')} >
    - - -
    -
    - -
    + +
    + Back to menu
    { return ( - - {props.children} + + {props.children} ) } @@ -93,17 +93,16 @@ const ContentAccordionLink = React.memo(function ContentAccordionLink(props: any {props.subItem.items.map((subSubItem) => { return (
  • - - - {subSubItem.name} - + + {subSubItem.name}
  • ) @@ -120,25 +119,19 @@ const ContentLink = React.memo(function ContentLink(props: any) { return (
  • - - - {props.icon && ( - {props.icon} - )} - {props.name} - + + {props.icon && ( + {props.icon} + )} + {props.name}
  • ) @@ -149,29 +142,26 @@ const Content = (props) => { return (
      - - -
      -
      - -
      + +
      + Back to Home - - -
      - - -
      -
      + +
      + + +
      {menu.items.map((x) => { diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenuRefListItems.tsx b/apps/docs/components/Navigation/NavigationMenu/NavigationMenuRefListItems.tsx index 8c2007c78b..b325efb3a9 100644 --- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenuRefListItems.tsx +++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenuRefListItems.tsx @@ -4,7 +4,7 @@ import { useRouter } from 'next/router' import { IconChevronLeft, IconChevronUp, cn } from 'ui' import * as NavItems from './NavigationMenu.constants' -import Image from 'next/image' +import Image from 'next/legacy/image' import RevVersionDropdown from '~/components/RefVersionDropdown' import { useMenuActiveRefId } from '~/hooks/useMenuState' @@ -176,20 +176,19 @@ const NavigationMenuRefListItems = ({ return (
      - - -
      -
      - -
      + +
      + Back to Main Menu
      diff --git a/apps/docs/components/Navigation/NavigationMenu/TopNavBar.tsx b/apps/docs/components/Navigation/NavigationMenu/TopNavBar.tsx index 5ba553eaa3..1fd6ddb21c 100644 --- a/apps/docs/components/Navigation/NavigationMenu/TopNavBar.tsx +++ b/apps/docs/components/Navigation/NavigationMenu/TopNavBar.tsx @@ -1,5 +1,5 @@ import { useTheme } from 'next-themes' -import Image from 'next/image' +import Image from 'next/legacy/image' import Link from 'next/link' import { useRouter } from 'next/router' import { FC, useState } from 'react' @@ -55,19 +55,17 @@ const TopNavBar: FC = () => {
      + setShowConfirmEnableModal(false)} /> + setIsDisableModalOpen(false)} + onSelectConfirm={() => { + disableExtension() + }} + > + +

      + Are you sure you want to turn OFF "{extension.name}" extension? +

      +
      +
      ) } diff --git a/studio/components/interfaces/Database/Extensions/Extensions.tsx b/studio/components/interfaces/Database/Extensions/Extensions.tsx index 54fe02020a..de09a3ccbf 100644 --- a/studio/components/interfaces/Database/Extensions/Extensions.tsx +++ b/studio/components/interfaces/Database/Extensions/Extensions.tsx @@ -58,13 +58,15 @@ const Extensions = () => { />
      ) : ( - - - + )}
    diff --git a/studio/components/interfaces/Database/Hooks/EditHookPanel.tsx b/studio/components/interfaces/Database/Hooks/EditHookPanel.tsx index 221f9f011d..661d80f7e4 100644 --- a/studio/components/interfaces/Database/Hooks/EditHookPanel.tsx +++ b/studio/components/interfaces/Database/Hooks/EditHookPanel.tsx @@ -1,5 +1,5 @@ import { PostgresTable, PostgresTrigger } from '@supabase/postgres-meta' -import Image from 'next/image' +import Image from 'next/legacy/image' import { MutableRefObject, useEffect, useMemo, useRef, useState } from 'react' import { useParams } from 'common/hooks' diff --git a/studio/components/interfaces/Database/Hooks/HTTPRequestFields.tsx b/studio/components/interfaces/Database/Hooks/HTTPRequestFields.tsx index 05b2ad90b6..f6cf0b7d54 100644 --- a/studio/components/interfaces/Database/Hooks/HTTPRequestFields.tsx +++ b/studio/components/interfaces/Database/Hooks/HTTPRequestFields.tsx @@ -94,11 +94,9 @@ const HTTPRequestFields = ({

    Select which edge function to trigger

    No edge functions created yet

    - - - - - +
    {errors.http_url &&

    {errors.http_url}

    }
    diff --git a/studio/components/interfaces/Database/Hooks/HooksList/HookList.tsx b/studio/components/interfaces/Database/Hooks/HooksList/HookList.tsx index 2edb983e96..b890a48919 100644 --- a/studio/components/interfaces/Database/Hooks/HooksList/HookList.tsx +++ b/studio/components/interfaces/Database/Hooks/HooksList/HookList.tsx @@ -1,7 +1,7 @@ import * as Tooltip from '@radix-ui/react-tooltip' import { PermissionAction } from '@supabase/shared-types/out/constants' import { includes, noop } from 'lodash' -import Image from 'next/image' +import Image from 'next/legacy/image' import { useParams } from 'common/hooks' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' diff --git a/studio/components/interfaces/Database/Hooks/HooksList/HooksList.tsx b/studio/components/interfaces/Database/Hooks/HooksList/HooksList.tsx index f17a940567..1caa2386ae 100644 --- a/studio/components/interfaces/Database/Hooks/HooksList/HooksList.tsx +++ b/studio/components/interfaces/Database/Hooks/HooksList/HooksList.tsx @@ -87,13 +87,15 @@ const HooksList = ({ onChange={(e) => setFilterString(e.target.value)} />
    - - - - - + - - +
    diff --git a/studio/components/interfaces/Database/Indexes/Indexes.tsx b/studio/components/interfaces/Database/Indexes/Indexes.tsx index fa9a206169..aab135a4bf 100644 --- a/studio/components/interfaces/Database/Indexes/Indexes.tsx +++ b/studio/components/interfaces/Database/Indexes/Indexes.tsx @@ -104,23 +104,24 @@ const Indexes = () => {
    - - - - - - + +
    diff --git a/studio/components/interfaces/Database/Migrations/Migrations.tsx b/studio/components/interfaces/Database/Migrations/Migrations.tsx index 324aad1362..93706d22cb 100644 --- a/studio/components/interfaces/Database/Migrations/Migrations.tsx +++ b/studio/components/interfaces/Database/Migrations/Migrations.tsx @@ -38,13 +38,15 @@ const Migrations = () => {
    - - - - - +
    @@ -63,16 +65,13 @@ const Migrations = () => { variant="warning" title="Failed to retrieve migration history for database" actions={[ - - - - - , + , ]} >

    diff --git a/studio/components/interfaces/Database/Publications/PublicationsList.tsx b/studio/components/interfaces/Database/Publications/PublicationsList.tsx index fa2b16dafc..36c9004a00 100644 --- a/studio/components/interfaces/Database/Publications/PublicationsList.tsx +++ b/studio/components/interfaces/Database/Publications/PublicationsList.tsx @@ -2,13 +2,18 @@ import { PermissionAction } from '@supabase/shared-types/out/constants' import { noop } from 'lodash' import { observer } from 'mobx-react-lite' import { useState } from 'react' -import { Button, IconAlertCircle, IconSearch, Input, Toggle } from 'ui' -import { confirmAlert } from 'components/to-be-cleaned/ModalsDeprecated/ConfirmModal' import Table from 'components/to-be-cleaned/Table' +import ConfirmationModal from 'components/ui/ConfirmationModal' import InformationBox from 'components/ui/InformationBox' import NoSearchResults from 'components/ui/NoSearchResults' import { useCheckPermissions, useStore } from 'hooks' +import { Button, IconAlertCircle, IconSearch, Input, Modal, Toggle } from 'ui' + +interface PublicationEvent { + event: string + key: string +} interface PublicationsListProps { onSelectPublication: (id: number) => void @@ -23,7 +28,7 @@ const PublicationsList = ({ onSelectPublication = noop }: PublicationsListProps) 'publications' ) - const publicationEvents = [ + const publicationEvents: PublicationEvent[] = [ { event: 'Insert', key: 'publish_insert' }, { event: 'Update', key: 'publish_update' }, { event: 'Delete', key: 'publish_delete' }, @@ -34,30 +39,34 @@ const PublicationsList = ({ onSelectPublication = noop }: PublicationsListProps) ? meta.publications.list() : meta.publications.list((publication: any) => publication.name.includes(filterString)) - const toggleListenEvent = async (publication: any, event: any, currentStatus: any) => { - const startStop = currentStatus ? 'stop' : 'start' - confirmAlert({ - title: 'Confirm', - message: `Are you sure you want to ${startStop} sending ${event} events for ${publication.name}?`, - onAsyncConfirm: async () => { - try { - let payload: any = { id: publication.id } - payload[`publish_${event}`] = !currentStatus - const { data, error }: any = await meta.publications.update(publication.id, payload) - if (error) { - throw error - } else { - return data - } - } catch (error: any) { - ui.setNotification({ - category: 'error', - message: `Failed to toggle for ${publication.name}: ${error.message}`, - }) - return false - } - }, - }) + const [toggleListenEventValue, setToggleListenEventValue] = useState<{ + publication: any + event: PublicationEvent + currentStatus: any + } | null>(null) + + const toggleListenEvent = async () => { + if (!toggleListenEventValue) return + + const { publication, event, currentStatus } = toggleListenEventValue + + try { + let payload: any = { id: publication.id } + payload[`publish_${event.event.toLowerCase()}`] = !currentStatus + const { data, error }: any = await meta.publications.update(publication.id, payload) + if (error) { + throw error + } else { + setToggleListenEventValue(null) + return data + } + } catch (error: any) { + ui.setNotification({ + category: 'error', + message: `Failed to toggle for ${publication.name}: ${error.message}`, + }) + return false + } } return ( @@ -101,7 +110,7 @@ const PublicationsList = ({ onSelectPublication = noop }: PublicationsListProps) Source , ]} - body={publications.map((x: any, i: number) => ( + body={publications.map((x, i) => ( {x.name} @@ -115,7 +124,13 @@ const PublicationsList = ({ onSelectPublication = noop }: PublicationsListProps) size="tiny" checked={x[event.key]} disabled={!canUpdatePublications} - onChange={() => toggleListenEvent(x, event.event.toLowerCase(), x[event.key])} + onChange={() => { + setToggleListenEventValue({ + publication: x, + event, + currentStatus: x[event.key], + }) + }} /> ))} @@ -139,6 +154,24 @@ const PublicationsList = ({ onSelectPublication = noop }: PublicationsListProps) />

    )} + + setToggleListenEventValue(null)} + onSelectConfirm={() => { + toggleListenEvent() + }} + > + +

    + Are you sure you want to {toggleListenEventValue?.currentStatus ? 'stop' : 'start'}{' '} + sending {toggleListenEventValue?.event.event.toLowerCase()} events for{' '} + {toggleListenEventValue?.publication.name}? +

    +
    +
    ) } diff --git a/studio/components/interfaces/Database/Publications/PublicationsTables.tsx b/studio/components/interfaces/Database/Publications/PublicationsTables.tsx index 9b881dddd5..80e326943b 100644 --- a/studio/components/interfaces/Database/Publications/PublicationsTables.tsx +++ b/studio/components/interfaces/Database/Publications/PublicationsTables.tsx @@ -55,7 +55,7 @@ const PublicationsTables = ({ selectedPublication, onSelectBack }: PublicationsT // const toggleReplicationForAllTables = async (publication: any, disable: boolean) => { // const toggle = disable ? 'disable' : 'enable' - // confirmAlert({ + // ConfirmAlert({ // title: 'Confirm', // type: 'warn', // message: `Are you sure you want to ${toggle} replication for all tables in ${publication.name}?`, diff --git a/studio/components/interfaces/Database/Wrappers/CreateWrapper.tsx b/studio/components/interfaces/Database/Wrappers/CreateWrapper.tsx index fa28dd5bc2..3f0774206f 100644 --- a/studio/components/interfaces/Database/Wrappers/CreateWrapper.tsx +++ b/studio/components/interfaces/Database/Wrappers/CreateWrapper.tsx @@ -76,11 +76,9 @@ const CreateWrapper = () => { wrapper.

    - - - - - + ) } @@ -130,23 +128,19 @@ const CreateWrapper = () => { ].join(' ')} > - -
    - -

    Back

    -
    -
    +
    + +

    Back

    +

    Create a {wrapperMeta.label} Wrapper

    - - - - - +
    diff --git a/studio/components/interfaces/Database/Wrappers/EditWrapper.tsx b/studio/components/interfaces/Database/Wrappers/EditWrapper.tsx index 0a90ef2115..f34b0e78cf 100644 --- a/studio/components/interfaces/Database/Wrappers/EditWrapper.tsx +++ b/studio/components/interfaces/Database/Wrappers/EditWrapper.tsx @@ -125,11 +125,9 @@ const EditWrapper = () => { wrapper.

    - - - - - + ) } @@ -181,23 +179,23 @@ const EditWrapper = () => { ].join(' ')} > - -
    - -

    Back

    -
    -
    +
    + +

    Back

    +

    Edit wrapper: {wrapper.name}

    - - - - - +
    diff --git a/studio/components/interfaces/Database/Wrappers/InputField.tsx b/studio/components/interfaces/Database/Wrappers/InputField.tsx index ff44468b97..b85d46da7c 100644 --- a/studio/components/interfaces/Database/Wrappers/InputField.tsx +++ b/studio/components/interfaces/Database/Wrappers/InputField.tsx @@ -27,14 +27,12 @@ const InputField = ({ option, loading, error }: InputFieldProps) => {

    {option.label}

    {option.urlHelper !== undefined && ( - - - - + + )}
    @@ -55,14 +53,12 @@ const InputField = ({ option, loading, error }: InputFieldProps) => {

    {option.label}

    {option.urlHelper !== undefined && ( - - - - + + )}
    diff --git a/studio/components/interfaces/Database/Wrappers/WrapperRow.tsx b/studio/components/interfaces/Database/Wrappers/WrapperRow.tsx index 2ff3cf2590..d71714ed1b 100644 --- a/studio/components/interfaces/Database/Wrappers/WrapperRow.tsx +++ b/studio/components/interfaces/Database/Wrappers/WrapperRow.tsx @@ -1,7 +1,7 @@ import * as Tooltip from '@radix-ui/react-tooltip' import { PermissionAction } from '@supabase/shared-types/out/constants' import { partition } from 'lodash' -import Image from 'next/image' +import Image from 'next/legacy/image' import Link from 'next/link' import { Button, Collapsible, IconChevronUp, IconEdit, IconExternalLink, IconTrash } from 'ui' @@ -104,11 +104,10 @@ const WrapperRow = ({

    {metadata.label}:

    - - Encrypted in Vault - - + Encrypted in Vault + ))} @@ -120,14 +119,9 @@ const WrapperRow = ({ {wrapper.tables ? ( wrapper.tables.map((table: any) => ( - -
    - {table.name} -
    -
    +
    + {table.name} +
    )) ) : ( @@ -139,13 +133,11 @@ const WrapperRow = ({
    {canManageWrappers ? ( - -
    - - - - - + {isWrappersEnabled && }
    diff --git a/studio/components/interfaces/Database/Wrappers/WrappersDisabledState.tsx b/studio/components/interfaces/Database/Wrappers/WrappersDisabledState.tsx index 8473cf4b60..78f87d98a2 100644 --- a/studio/components/interfaces/Database/Wrappers/WrappersDisabledState.tsx +++ b/studio/components/interfaces/Database/Wrappers/WrappersDisabledState.tsx @@ -98,34 +98,40 @@ const WrappersDisabledState = () => {

    - - - - - +
    - - - - - +
    ) : (
    - - - - - + - - +
    diff --git a/studio/components/interfaces/Functions/EdgeFunctionDetails/EdgeFunctionDetails.tsx b/studio/components/interfaces/Functions/EdgeFunctionDetails/EdgeFunctionDetails.tsx index 49f7565975..9700f810f4 100644 --- a/studio/components/interfaces/Functions/EdgeFunctionDetails/EdgeFunctionDetails.tsx +++ b/studio/components/interfaces/Functions/EdgeFunctionDetails/EdgeFunctionDetails.tsx @@ -197,13 +197,19 @@ const EdgeFunctionDetails = () => { explicit import URLs

    - - - - - +
    diff --git a/studio/components/interfaces/Functions/EdgeFunctionSecrets/EdgeFunctionSecrets.tsx b/studio/components/interfaces/Functions/EdgeFunctionSecrets/EdgeFunctionSecrets.tsx index 1db79118c1..ad89448ea0 100644 --- a/studio/components/interfaces/Functions/EdgeFunctionSecrets/EdgeFunctionSecrets.tsx +++ b/studio/components/interfaces/Functions/EdgeFunctionSecrets/EdgeFunctionSecrets.tsx @@ -65,13 +65,19 @@ const EdgeFunctionSecrets = () => { icon={} />
    - - - - - +
    diff --git a/studio/components/interfaces/Functions/FunctionsEmptyState.tsx b/studio/components/interfaces/Functions/FunctionsEmptyState.tsx index c28db55ccb..d47dfae624 100644 --- a/studio/components/interfaces/Functions/FunctionsEmptyState.tsx +++ b/studio/components/interfaces/Functions/FunctionsEmptyState.tsx @@ -16,23 +16,24 @@ const FunctionsEmptyState = () => { Supabase project with third-parties.

    - - - - - - - - - - + +
    diff --git a/studio/components/interfaces/Functions/TerminalInstructions.tsx b/studio/components/interfaces/Functions/TerminalInstructions.tsx index 80b77bbc18..f93d8a0f7c 100644 --- a/studio/components/interfaces/Functions/TerminalInstructions.tsx +++ b/studio/components/interfaces/Functions/TerminalInstructions.tsx @@ -136,23 +136,24 @@ const TerminalInstructions = ({

    - - - - - - - - - - + +
    )} diff --git a/studio/components/interfaces/GraphQL/GraphiQL.tsx b/studio/components/interfaces/GraphQL/GraphiQL.tsx index 6baa40ddbc..d6e92f003a 100644 --- a/studio/components/interfaces/GraphQL/GraphiQL.tsx +++ b/studio/components/interfaces/GraphQL/GraphiQL.tsx @@ -19,6 +19,7 @@ import { ToolbarButton, Tooltip, UnStyledButton, + VariableEditor, useCopyQuery, useDragResize, useEditorContext, @@ -28,20 +29,19 @@ import { usePrettifyEditors, useSchemaContext, useTheme, - VariableEditor, } from '@graphiql/react' import { Fetcher } from '@graphiql/toolkit' import clsx from 'clsx' -import { useEffect, useState } from 'react' +import { MouseEventHandler, useCallback, useEffect, useState } from 'react' import styles from './graphiql.module.css' -export type GraphiQLProps = { +export interface GraphiQLProps { fetcher: Fetcher theme?: 'dark' | 'light' accessToken?: string } -const GraphiQL = ({ fetcher, theme = 'dark', accessToken }: GraphiQLProps) => { +export default function GraphiQL({ fetcher, theme = 'dark', accessToken }: GraphiQLProps) { // Ensure props are correct if (typeof fetcher !== 'function') { throw new TypeError( @@ -63,7 +63,7 @@ const GraphiQL = ({ fetcher, theme = 'dark', accessToken }: GraphiQLProps) => { ) } -type GraphiQLInterfaceProps = { +interface GraphiQLInterfaceProps { theme: 'dark' | 'light' } @@ -120,42 +120,104 @@ export const GraphiQLInterface = ({ theme }: GraphiQLInterfaceProps) => { const toolbar = ( <> - prettify()} label="Prettify query (Shift-Ctrl-P)"> + - merge()} label="Merge fragments into query (Shift-Ctrl-M)"> + - copy()} label="Copy query (Shift-Ctrl-C)"> + ) - const onClickReference = () => { + const onClickReference = useCallback(() => { if (pluginResize.hiddenElement === 'second') { pluginResize.setHiddenElement(null) } - } + }, [pluginResize]) + + const handleAddTab = editorContext.addTab + const handleRefetchSchema = schemaContext.introspect + const handleReorder = editorContext.moveTab + + const handlePluginClick: MouseEventHandler = useCallback( + (e) => { + const context = pluginContext! + const pluginIndex = Number(e.currentTarget.dataset.index!) + const plugin = context.plugins.find((_, index) => pluginIndex === index)! + const isVisible = plugin === context.visiblePlugin + if (isVisible) { + context.setVisiblePlugin(null) + pluginResize.setHiddenElement('second') + } else { + context.setVisiblePlugin(plugin) + pluginResize.setHiddenElement(null) + } + }, + [pluginContext, pluginResize] + ) + + const handleToolsTabClick: MouseEventHandler = useCallback( + (event) => { + if (editorToolsResize.hiddenElement === 'second') { + editorToolsResize.setHiddenElement(null) + } + setActiveSecondaryEditor(event.currentTarget.dataset.name as 'variables' | 'headers') + }, + [editorToolsResize] + ) + + const toggleEditorTools: MouseEventHandler = useCallback(() => { + editorToolsResize.setHiddenElement( + editorToolsResize.hiddenElement === 'second' ? null : 'second' + ) + }, [editorToolsResize]) + + const addTab = ( + + + + + ) const hasSingleTab = editorContext.tabs.length === 1 return ( -
    -
    -
    -
    + +
    +
    +
    - - {editorContext.tabs.length > 1 ? ( + + {editorContext.tabs.length > 1 && ( <> {editorContext.tabs.map((tab, index) => ( - + { /> ))} -
    - - editorContext.addTab()} - aria-label="Add tab" - > - - -
    + {addTab} - ) : null} + )}
    - {hasSingleTab ? ( -
    - - editorContext.addTab()} - aria-label="Add tab" - > - - -
    - ) : null} + {hasSingleTab &&
    {addTab}
    }
    { >
    -
    - -
    +
    {toolbar}
    +
    -
    - { - if (editorToolsResize.hiddenElement === 'second') { - editorToolsResize.setHiddenElement(null) - } - setActiveSecondaryEditor('variables') - }} - > - Variables - + + Variables + + + + Headers + - { - if (editorToolsResize.hiddenElement === 'second') { - editorToolsResize.setHiddenElement(null) - } - setActiveSecondaryEditor('headers') - }} - > - Headers - -
    { > { - editorToolsResize.setHiddenElement( - editorToolsResize.hiddenElement === 'second' ? null : 'second' - ) - }} + onClick={toggleEditorTools} aria-label={ editorToolsResize.hiddenElement === 'second' ? 'Show editor tools' : 'Hide editor tools' } + className="graphiql-toggle-editor-tools" > {editorToolsResize.hiddenElement === 'second' ? (
    +
    {
    -
    -
    -
    + +
    +
    {
    + {pluginContext?.visiblePlugin && ( +
    + )} +
    +
    {PluginContent ? : null}
    +
    - -
    - {pluginContext?.visiblePlugin ? ( -
    - ) : null} -
    - -
    -
    {PluginContent ? : null}
    +
    +
    + {pluginContext?.plugins.map((plugin, index) => { + const isVisible = plugin === pluginContext.visiblePlugin + const label = `${isVisible ? 'Hide' : 'Show'} ${plugin.title}` + const Icon = plugin.icon + return ( + + + + + ) + })} +
    +
    + + + + +
    -
    -
    - {pluginContext?.plugins.map((plugin) => { - const isVisible = plugin === pluginContext.visiblePlugin - const label = `${isVisible ? 'Hide' : 'Show'} ${plugin.title}` - const Icon = plugin.icon - return ( - - { - if (isVisible) { - pluginContext.setVisiblePlugin(null) - pluginResize.setHiddenElement('second') - } else { - pluginContext.setVisiblePlugin(plugin) - pluginResize.setHiddenElement(null) - } - }} - aria-label={label} - > - - - ) - })} -
    -
    - - schemaContext.introspect()} - aria-label="Re-fetch GraphQL schema" - > - - -
    -
    -
    + ) } - -export default GraphiQL diff --git a/studio/components/interfaces/Home/ExampleProject.tsx b/studio/components/interfaces/Home/ExampleProject.tsx index b3be54260b..d779faf457 100644 --- a/studio/components/interfaces/Home/ExampleProject.tsx +++ b/studio/components/interfaces/Home/ExampleProject.tsx @@ -14,52 +14,50 @@ const ExampleProject = ({ framework, title, description, url }: ExampleProjectPr const { resolvedTheme } = useTheme() return ( - - -
    - ) } diff --git a/studio/components/interfaces/Home/NewProjectPanel/APIKeys.tsx b/studio/components/interfaces/Home/NewProjectPanel/APIKeys.tsx index f861eeedf4..5d3489efd8 100644 --- a/studio/components/interfaces/Home/NewProjectPanel/APIKeys.tsx +++ b/studio/components/interfaces/Home/NewProjectPanel/APIKeys.tsx @@ -138,8 +138,11 @@ const APIKeys = () => { This key is safe to use in a browser if you have enabled Row Level Security (RLS) for your tables and configured policies. You may also use the service key which can be found{' '} - - here + + here {' '} to bypass RLS.

    diff --git a/studio/components/interfaces/Home/NewProjectPanel/NewProjectPanel.tsx b/studio/components/interfaces/Home/NewProjectPanel/NewProjectPanel.tsx index 457ce145d5..0b7917e425 100644 --- a/studio/components/interfaces/Home/NewProjectPanel/NewProjectPanel.tsx +++ b/studio/components/interfaces/Home/NewProjectPanel/NewProjectPanel.tsx @@ -46,53 +46,53 @@ const NewProjectPanel = () => {

    @@ -124,22 +124,24 @@ const NewProjectPanel = () => {

    - - - - - - - - - - + + +
    @@ -158,22 +160,24 @@ const NewProjectPanel = () => {

    - - - - - - - - - - + + +
    @@ -193,22 +197,23 @@ const NewProjectPanel = () => {

    - - - - - - - - - - + +
    @@ -226,17 +231,20 @@ const NewProjectPanel = () => {

    - - - - - +
    @@ -252,8 +260,8 @@ const NewProjectPanel = () => {

    Connecting to your new project

    Interact with your database through the{' '} - - Supabase client libraries + + Supabase client libraries {' '} with your API keys.

    @@ -263,18 +271,23 @@ const NewProjectPanel = () => {

    - - - - - - - - - - + +
    diff --git a/studio/components/interfaces/Home/ProjectList/ProjectList.tsx b/studio/components/interfaces/Home/ProjectList/ProjectList.tsx index 4ad10333d7..0de9baca7f 100644 --- a/studio/components/interfaces/Home/ProjectList/ProjectList.tsx +++ b/studio/components/interfaces/Home/ProjectList/ProjectList.tsx @@ -120,11 +120,9 @@ const OrganizationProjects = ({ {!!overdueInvoices.length && (
    - - - - - +
    )} @@ -195,10 +193,11 @@ const OrganizationProjects = ({ The organization "{name}" still uses the legacy project-based billing. We've recently made some big improvements to our billing system and require your action. To migrate to the new organization-based billing, head over to your{' '} - - - organization billing settings - + + organization billing settings .

    @@ -209,20 +208,24 @@ const OrganizationProjects = ({

    - - - - - - + +
    @@ -239,11 +242,9 @@ const NoProjectsState = ({ slug }: { slug: string }) => {

    Get started by creating a new project.

    - - - - - +
    ) diff --git a/studio/components/interfaces/Integrations/IntegrationConnection.tsx b/studio/components/interfaces/Integrations/IntegrationConnection.tsx index f0b2098b7e..d3d4e3ff2f 100644 --- a/studio/components/interfaces/Integrations/IntegrationConnection.tsx +++ b/studio/components/interfaces/Integrations/IntegrationConnection.tsx @@ -83,19 +83,16 @@ const IntegrationConnectionItem = forwardRef {router.pathname !== projectIntegrationUrl && ( - - - - View project configuration - - - + + + View project configuration + + )} - - - + ) } diff --git a/studio/components/interfaces/Organization/AuditLogs/AuditLogs.tsx b/studio/components/interfaces/Organization/AuditLogs/AuditLogs.tsx index 85af8b68d0..f0072da457 100644 --- a/studio/components/interfaces/Organization/AuditLogs/AuditLogs.tsx +++ b/studio/components/interfaces/Organization/AuditLogs/AuditLogs.tsx @@ -1,6 +1,6 @@ import * as Tooltip from '@radix-ui/react-tooltip' import dayjs from 'dayjs' -import Image from 'next/image' +import Image from 'next/legacy/image' import { useEffect, useState } from 'react' import { useParams } from 'common' @@ -18,7 +18,6 @@ import { useOrganizationDetailQuery } from 'data/organizations/organization-deta import { useOrganizationRolesQuery } from 'data/organizations/organization-roles-query' import { useOrganizationsQuery } from 'data/organizations/organizations-query' import { useProjectsQuery } from 'data/projects/projects-query' -import { useIsFeatureEnabled } from 'hooks' import Link from 'next/link' import { Alert, @@ -234,9 +233,11 @@ const AuditLogs = () => {
    - - - +
    @@ -274,7 +275,7 @@ const AuditLogs = () => {

    Date

    - + - - + } tooltip={!canUpdateSpendCap ? 'You do not have permission to update spend cap' : undefined} diff --git a/studio/components/interfaces/Organization/BillingSettingsV2/PaymentMethods/PaymentMethods.tsx b/studio/components/interfaces/Organization/BillingSettingsV2/PaymentMethods/PaymentMethods.tsx index 4106917e4b..633a3f5958 100644 --- a/studio/components/interfaces/Organization/BillingSettingsV2/PaymentMethods/PaymentMethods.tsx +++ b/studio/components/interfaces/Organization/BillingSettingsV2/PaymentMethods/PaymentMethods.tsx @@ -99,14 +99,16 @@ const PaymentMethods = () => { variant="info" title="Payment is currently by invoice" actions={[ - - - - - , + , ]} > You get a monthly invoice and payment link via email. To change your payment diff --git a/studio/components/interfaces/Organization/BillingSettingsV2/Subscription/PaymentMethodSelection.tsx b/studio/components/interfaces/Organization/BillingSettingsV2/Subscription/PaymentMethodSelection.tsx index 40cbb27233..42eccd4a3a 100644 --- a/studio/components/interfaces/Organization/BillingSettingsV2/Subscription/PaymentMethodSelection.tsx +++ b/studio/components/interfaces/Organization/BillingSettingsV2/Subscription/PaymentMethodSelection.tsx @@ -86,7 +86,7 @@ const PaymentMethodSelection = ({ - + - - + } > diff --git a/studio/components/interfaces/Organization/BillingSettingsV2/Subscription/Subscription.tsx b/studio/components/interfaces/Organization/BillingSettingsV2/Subscription/Subscription.tsx index 896bfe87f2..c1936f6974 100644 --- a/studio/components/interfaces/Organization/BillingSettingsV2/Subscription/Subscription.tsx +++ b/studio/components/interfaces/Organization/BillingSettingsV2/Subscription/Subscription.tsx @@ -60,13 +60,11 @@ const Subscription = () => {

    More information

    - - -
    -

    Pricing

    - -
    -
    + +
    +

    Pricing

    + +
    @@ -152,13 +150,13 @@ const Subscription = () => { title={`Unable to update plan from ${planName}`} actions={[
    - - - - - +
    , ]} > @@ -186,10 +184,11 @@ const Subscription = () => { >
    When this organization exceeds its{' '} - - - included usage quotas - + + included usage quotas , its projects may become unresponsive.{' '} {currentPlan?.id === 'free' ? ( diff --git a/studio/components/interfaces/Organization/GeneralSettings/GeneralSettings.tsx b/studio/components/interfaces/Organization/GeneralSettings/GeneralSettings.tsx index 3465f104e9..92d15630ab 100644 --- a/studio/components/interfaces/Organization/GeneralSettings/GeneralSettings.tsx +++ b/studio/components/interfaces/Organization/GeneralSettings/GeneralSettings.tsx @@ -169,14 +169,13 @@ const GeneralSettings = () => {

    For more information about how we use personal information, please see our{' '} - - - privacy policy - + + privacy policy .

    diff --git a/studio/components/interfaces/Organization/GeneralSettings/MigrateOrganizationBillingButton.tsx b/studio/components/interfaces/Organization/GeneralSettings/MigrateOrganizationBillingButton.tsx index 9e1589af68..c9a4bddd01 100644 --- a/studio/components/interfaces/Organization/GeneralSettings/MigrateOrganizationBillingButton.tsx +++ b/studio/components/interfaces/Organization/GeneralSettings/MigrateOrganizationBillingButton.tsx @@ -211,16 +211,22 @@ const MigrateOrganizationBillingButton = observer(() => {

    With organization-based billing, you'll have a single subscription for your entire organization. For a detailed breakdown of changes, see{' '} - - - Billing Migration Docs - + + Billing Migration Docs . To transfer projects to a different organization, visit{' '} - - - general project settings - + + general project settings .

    @@ -267,10 +273,13 @@ const MigrateOrganizationBillingButton = observer(() => {

    Paid plans come with one compute instance included. Additional projects will at least cost the compute instance hours used (min $10/month). See{' '} - - - Compute Instance Usage Billing - + + Compute Instance Usage Billing {' '} for more details.

    diff --git a/studio/components/interfaces/Organization/GeneralSettings/OrganizationBillingMigrationPanel.tsx b/studio/components/interfaces/Organization/GeneralSettings/OrganizationBillingMigrationPanel.tsx index d6b4cb33e4..5c6953a564 100644 --- a/studio/components/interfaces/Organization/GeneralSettings/OrganizationBillingMigrationPanel.tsx +++ b/studio/components/interfaces/Organization/GeneralSettings/OrganizationBillingMigrationPanel.tsx @@ -27,13 +27,15 @@ const OrganizationBillingMigrationPanel = observer(() => {

    - - - - - +
    diff --git a/studio/components/interfaces/Organization/IntegrationSettings/IntegrationSettings.tsx b/studio/components/interfaces/Organization/IntegrationSettings/IntegrationSettings.tsx index bfff1701a5..91fe4e7d57 100644 --- a/studio/components/interfaces/Organization/IntegrationSettings/IntegrationSettings.tsx +++ b/studio/components/interfaces/Organization/IntegrationSettings/IntegrationSettings.tsx @@ -226,11 +226,11 @@ You can change the scope of the access for Supabase by configuring }) ) : (
    - - - +
    )} {VercelContentSectionBottom && ( diff --git a/studio/components/interfaces/Organization/IntegrationSettings/SidePanelVercelProjectLinker.tsx b/studio/components/interfaces/Organization/IntegrationSettings/SidePanelVercelProjectLinker.tsx index 97db8ec0ad..67fcc1b78f 100644 --- a/studio/components/interfaces/Organization/IntegrationSettings/SidePanelVercelProjectLinker.tsx +++ b/studio/components/interfaces/Organization/IntegrationSettings/SidePanelVercelProjectLinker.tsx @@ -101,7 +101,7 @@ const SidePanelVercelProjectLinker = () => { }) const onCreateConnections = useCallback( - (vars) => { + (vars: any) => { createConnections({ ...vars, connection: { diff --git a/studio/components/interfaces/Organization/InvoicesSettings/InvoicesSettings.tsx b/studio/components/interfaces/Organization/InvoicesSettings/InvoicesSettings.tsx index ae89f0cc9b..acdb93e261 100644 --- a/studio/components/interfaces/Organization/InvoicesSettings/InvoicesSettings.tsx +++ b/studio/components/interfaces/Organization/InvoicesSettings/InvoicesSettings.tsx @@ -109,11 +109,15 @@ const InvoicesSettings = () => {
    {[InvoiceStatus.UNCOLLECTIBLE, InvoiceStatus.OPEN].includes(x.status) && ( - - - - - + )} - - +
    } diff --git a/studio/components/interfaces/Organization/NewProject/FreeProjectLimitWarning.tsx b/studio/components/interfaces/Organization/NewProject/FreeProjectLimitWarning.tsx index fd9d77af89..7e98d388c7 100644 --- a/studio/components/interfaces/Organization/NewProject/FreeProjectLimitWarning.tsx +++ b/studio/components/interfaces/Organization/NewProject/FreeProjectLimitWarning.tsx @@ -43,11 +43,9 @@ const FreeProjectLimitWarning = ({ {orgLevelBilling && (
    - - - +
    )} diff --git a/studio/components/interfaces/Organization/OAuthApps/OAuthAppRow.tsx b/studio/components/interfaces/Organization/OAuthApps/OAuthAppRow.tsx index 682ccade81..16cf1f0ee1 100644 --- a/studio/components/interfaces/Organization/OAuthApps/OAuthAppRow.tsx +++ b/studio/components/interfaces/Organization/OAuthApps/OAuthAppRow.tsx @@ -70,7 +70,7 @@ const OAuthAppRow = ({ app, onSelectEdit, onSelectDelete }: OAuthAppRowProps) => {dayjs(app.created_at).format('DD/MM/YYYY, HH:mm:ss')} - + diff --git a/studio/components/interfaces/Organization/OAuthApps/PublishAppSidePanel/index.tsx b/studio/components/interfaces/Organization/OAuthApps/PublishAppSidePanel/index.tsx index 1148d48f5f..0febdfe63f 100644 --- a/studio/components/interfaces/Organization/OAuthApps/PublishAppSidePanel/index.tsx +++ b/studio/components/interfaces/Organization/OAuthApps/PublishAppSidePanel/index.tsx @@ -351,16 +351,15 @@ const PublishAppSidePanel = ({ of its projects. - - - + diff --git a/studio/components/interfaces/Organization/TeamSettings/InviteMemberButton.tsx b/studio/components/interfaces/Organization/TeamSettings/InviteMemberButton.tsx index 699bec7fd3..6ebf036a62 100644 --- a/studio/components/interfaces/Organization/TeamSettings/InviteMemberButton.tsx +++ b/studio/components/interfaces/Organization/TeamSettings/InviteMemberButton.tsx @@ -93,7 +93,7 @@ const InviteMemberButton = ({ return ( <> - + diff --git a/studio/components/interfaces/Organization/TeamSettings/MemberActions.tsx b/studio/components/interfaces/Organization/TeamSettings/MemberActions.tsx index cd4a5f0192..d6a9bc5079 100644 --- a/studio/components/interfaces/Organization/TeamSettings/MemberActions.tsx +++ b/studio/components/interfaces/Organization/TeamSettings/MemberActions.tsx @@ -2,13 +2,14 @@ import * as Tooltip from '@radix-ui/react-tooltip' import { PermissionAction } from '@supabase/shared-types/out/constants' import { useParams } from 'common/hooks' -import { confirmAlert } from 'components/to-be-cleaned/ModalsDeprecated/ConfirmModal' +import ConfirmationModal from 'components/ui/ConfirmationModal' import { useOrganizationMemberDeleteMutation } from 'data/organizations/organization-member-delete-mutation' import { useOrganizationMemberInviteCreateMutation } from 'data/organizations/organization-member-invite-create-mutation' import { useOrganizationMemberInviteDeleteMutation } from 'data/organizations/organization-member-invite-delete-mutation' import { usePermissionsQuery } from 'data/permissions/permissions-query' import { useCheckPermissions, useIsFeatureEnabled, useSelectedOrganization, useStore } from 'hooks' import { observer } from 'mobx-react-lite' +import { useState } from 'react' import { Member, Role } from 'types' import { Button, @@ -19,6 +20,7 @@ import { DropdownMenuTrigger, IconMoreHorizontal, IconTrash, + Modal, } from 'ui' import { isInviteExpired } from '../Organization.utils' import { useGetRolesManagementPermissions } from './TeamSettings.utils' @@ -54,6 +56,8 @@ const MemberActions = ({ member, roles }: MemberActionsProps) => { resource: { role_id: roleId }, }) + const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false) + const { mutate: deleteOrganizationMember, isLoading: isDeletingMember } = useOrganizationMemberDeleteMutation({ onSuccess: () => { @@ -61,6 +65,7 @@ const MemberActions = ({ member, roles }: MemberActionsProps) => { category: 'success', message: `Successfully removed ${member.primary_email}`, }) + setIsDeleteModalOpen(false) }, }) @@ -81,15 +86,9 @@ const MemberActions = ({ member, roles }: MemberActionsProps) => { useOrganizationMemberInviteDeleteMutation() const handleMemberDelete = async () => { - confirmAlert({ - title: 'Confirm to remove', - message: `This is permanent! Are you sure you want to remove ${member.primary_email}`, - onAsyncConfirm: async () => { - if (!slug) return console.error('slug is required') - if (!member.gotrue_id) return console.error('gotrue_id is required') - deleteOrganizationMember({ slug, gotrueId: member.gotrue_id }) - }, - }) + if (!slug) return console.error('slug is required') + if (!member.gotrue_id) return console.error('gotrue_id is required') + deleteOrganizationMember({ slug, gotrueId: member.gotrue_id }) } const handleResendInvite = async (member: Member) => { @@ -150,56 +149,79 @@ const MemberActions = ({ member, roles }: MemberActionsProps) => { const isLoading = isDeletingMember || isDeletingInvite || isCreatingInvite return ( -
    - - - - - - <> - {isPendingInviteAcceptance ? ( - <> - {canRevokeInvite && ( - handleRevokeInvitation(member)}> -
    -

    Cancel invitation

    -

    Revoke this invitation.

    -
    -
    - )} - {/* canResendInvite && isExpired */} - {true && ( - <> - - handleResendInvite(member)}> + <> +
    + + + + + + <> + {isPendingInviteAcceptance ? ( + <> + {canRevokeInvite && ( + handleRevokeInvitation(member)}>
    -

    Resend invitation

    -

    Invites expire after 24hrs.

    +

    Cancel invitation

    +

    Revoke this invitation.

    - - )} - - ) : ( - organizationMembersDeletionEnabled && ( - - -

    Remove member

    -
    - ) - )} - -
    -
    -
    + )} + {/* canResendInvite && isExpired */} + {true && ( + <> + + handleResendInvite(member)}> +
    +

    Resend invitation

    +

    Invites expire after 24hrs.

    +
    +
    + + )} + + ) : ( + organizationMembersDeletionEnabled && ( + { + setIsDeleteModalOpen(true) + }} + > + +

    Remove member

    +
    + ) + )} + +
    +
    +
    + + setIsDeleteModalOpen(false)} + onSelectConfirm={() => { + handleMemberDelete() + }} + > + +

    + This is permanent! Are you sure you want to remove {member.primary_email} +

    +
    +
    + ) } diff --git a/studio/components/interfaces/Organization/TeamSettings/MembersView.tsx b/studio/components/interfaces/Organization/TeamSettings/MembersView.tsx index c41b258a3b..303b85f4ce 100644 --- a/studio/components/interfaces/Organization/TeamSettings/MembersView.tsx +++ b/studio/components/interfaces/Organization/TeamSettings/MembersView.tsx @@ -1,6 +1,6 @@ import * as Tooltip from '@radix-ui/react-tooltip' import { observer } from 'mobx-react-lite' -import Image from 'next/image' +import Image from 'next/legacy/image' import { Fragment, useState } from 'react' import { useParams } from 'common/hooks' @@ -210,25 +210,27 @@ const MembersView = ({ searchString }: MembersViewProps) => { ) : role !== undefined ? ( - - - {roles.map((r: any) => ( - - {r.name} - - ))} - + +
    + + {roles.map((r: any) => ( + + {r.name} + + ))} + +
    {memberIsPendingInvite ? ( diff --git a/studio/components/interfaces/Organization/TeamSettings/TeamSettings.tsx b/studio/components/interfaces/Organization/TeamSettings/TeamSettings.tsx index 22845c6213..983933745f 100644 --- a/studio/components/interfaces/Organization/TeamSettings/TeamSettings.tsx +++ b/studio/components/interfaces/Organization/TeamSettings/TeamSettings.tsx @@ -9,14 +9,14 @@ import { ScaffoldFilterAndContent, ScaffoldSectionContent, } from 'components/layouts/Scaffold' -import { confirmAlert } from 'components/to-be-cleaned/ModalsDeprecated/ConfirmModal' +import ConfirmationModal from 'components/ui/ConfirmationModal' import { useOrganizationDetailQuery } from 'data/organizations/organization-detail-query' import { useOrganizationMemberDeleteMutation } from 'data/organizations/organization-member-delete-mutation' import { useOrganizationRolesQuery } from 'data/organizations/organization-roles-query' import { usePermissionsQuery } from 'data/permissions/permissions-query' import { useIsFeatureEnabled, useSelectedOrganization, useStore } from 'hooks' import { useProfile } from 'lib/profile' -import { Button, IconSearch, Input } from 'ui' +import { Button, IconSearch, Input, Modal } from 'ui' import InviteMemberButton from './InviteMemberButton' import MembersView from './MembersView' import { hasMultipleOwners, useGetRolesManagementPermissions } from './TeamSettings.utils' @@ -55,21 +55,15 @@ const TeamSettings = () => { const { mutateAsync: deleteMember } = useOrganizationMemberDeleteMutation() + const [isLeaveTeamModalOpen, setIsLeaveTeamModalOpen] = useState(false) + const leaveTeam = async () => { setIsLeaving(true) try { - confirmAlert({ - title: 'Are you sure?', - message: 'Are you sure you want to leave this organization? This is permanent.', - onAsyncConfirm: async () => { - try { - if (!slug) return console.error('Org slug is required') - await deleteMember({ slug, gotrueId: profile!.gotrue_id }) - window?.location.replace('/') // Force reload to clear Store - } finally { - } - }, - }) + if (!slug) return console.error('Org slug is required') + await deleteMember({ slug, gotrueId: profile!.gotrue_id }) + setIsLeaveTeamModalOpen(false) + window?.location.replace('/') // Force reload to clear Store } catch (error: any) { ui.setNotification({ category: 'error', @@ -81,74 +75,92 @@ const TeamSettings = () => { } return ( - - - - } - size="small" - value={searchString} - onChange={(e: any) => setSearchString(e.target.value)} - name="email" - id="email" - placeholder="Filter members" - /> - - {organizationMembersCreationEnabled && - canAddMembers && - profile !== undefined && - selectedOrganization !== undefined && ( + <> + + + + } + size="small" + value={searchString} + onChange={(e: any) => setSearchString(e.target.value)} + name="email" + id="email" + placeholder="Filter members" + /> + + {organizationMembersCreationEnabled && + canAddMembers && + profile !== undefined && + selectedOrganization !== undefined && ( +
    + +
    + )} + {/* if organizationMembersDeletionEnabled is false, you also can't delete yourself */} + {organizationMembersDeletionEnabled && (
    - + + + + + {!canLeave && ( + + + +
    + + An organization requires at least 1 owner + +
    +
    +
    + )} +
    )} - {/* if organizationMembersDeletionEnabled is false, you also can't delete yourself */} - {organizationMembersDeletionEnabled && ( -
    - - - - - {!canLeave && ( - - - -
    - - An organization requires at least 1 owner - -
    -
    -
    - )} -
    -
    - )} -
    -
    - - - -
    -
    +
    +
    + + + +
    +
    + + setIsLeaveTeamModalOpen(false)} + onSelectConfirm={() => { + leaveTeam() + }} + > + +

    + Are you sure you want to leave this organization? This is permanent. +

    +
    +
    + ) } diff --git a/studio/components/interfaces/Organization/Usage/SectionContent.tsx b/studio/components/interfaces/Organization/Usage/SectionContent.tsx index 05e76ef2d1..553997055f 100644 --- a/studio/components/interfaces/Organization/Usage/SectionContent.tsx +++ b/studio/components/interfaces/Organization/Usage/SectionContent.tsx @@ -43,13 +43,11 @@ const SectionContent = ({

    {links.map((link) => (
    - - -
    -

    {link.name}

    - -
    -
    + +
    +

    {link.name}

    + +
    ))} diff --git a/studio/components/interfaces/Organization/Usage/Usage.tsx b/studio/components/interfaces/Organization/Usage/Usage.tsx index a57f4084f7..3b18334018 100644 --- a/studio/components/interfaces/Organization/Usage/Usage.tsx +++ b/studio/components/interfaces/Organization/Usage/Usage.tsx @@ -175,16 +175,15 @@ const Usage = () => { variant="danger" title="Your organization's usage has exceeded its included quota" actions={[ - - - , + , ]} > Your projects can become unresponsive or enter read only mode.{' '} @@ -210,13 +209,15 @@ const Usage = () => { "All Projects".

    - - - - - +
    } diff --git a/studio/components/interfaces/Organization/Usage/UsageSection/AttributeUsage.tsx b/studio/components/interfaces/Organization/Usage/UsageSection/AttributeUsage.tsx index 0eaf9d2267..394c9ab25d 100644 --- a/studio/components/interfaces/Organization/Usage/UsageSection/AttributeUsage.tsx +++ b/studio/components/interfaces/Organization/Usage/UsageSection/AttributeUsage.tsx @@ -151,15 +151,13 @@ const AttributeUsage = ({ {showUsageWarning && ( - - - + )} @@ -284,11 +282,9 @@ const AttributeUsage = ({ - - - + diff --git a/studio/components/interfaces/ProjectAPIDocs/Content/Content.utils.ts b/studio/components/interfaces/ProjectAPIDocs/Content/Content.utils.ts index 7a3f2dfb69..da308eb606 100644 --- a/studio/components/interfaces/ProjectAPIDocs/Content/Content.utils.ts +++ b/studio/components/interfaces/ProjectAPIDocs/Content/Content.utils.ts @@ -4,3 +4,17 @@ export const navigateToSection = (key: string) => { if (el) el.scrollIntoView({ behavior: 'smooth' }) } } + +// Removes some auto-generated Postgrest text +// Ideally PostgREST wouldn't add this if there is already a comment +export const tempRemovePostgrestText = (content: string) => { + const postgrestTextPk = `Note:\nThis is a Primary Key.` + const postgrestTextFk = `Note:\nThis is a Foreign Key to` + const pkTextPos = content.lastIndexOf(postgrestTextPk) + const fkTextPos = content.lastIndexOf(postgrestTextFk) + + let cleansed = content + if (pkTextPos >= 0) cleansed = cleansed.substring(0, pkTextPos) + if (fkTextPos >= 0) cleansed = cleansed.substring(0, fkTextPos) + return cleansed +} diff --git a/studio/components/interfaces/ProjectAPIDocs/Content/Entities.tsx b/studio/components/interfaces/ProjectAPIDocs/Content/Entities.tsx index c4f8c7888d..9a669a98b8 100644 --- a/studio/components/interfaces/ProjectAPIDocs/Content/Entities.tsx +++ b/studio/components/interfaces/ProjectAPIDocs/Content/Entities.tsx @@ -47,13 +47,15 @@ const Entities = ({ language }: ContentProps) => {
    - - - +
    - - - - - - - - - + Documentation + + + +
    ) diff --git a/studio/components/interfaces/ProjectAPIDocs/ResourceContent.tsx b/studio/components/interfaces/ProjectAPIDocs/ResourceContent.tsx index c78fd29ebc..7a71cb23b6 100644 --- a/studio/components/interfaces/ProjectAPIDocs/ResourceContent.tsx +++ b/studio/components/interfaces/ProjectAPIDocs/ResourceContent.tsx @@ -25,13 +25,11 @@ const ResourceContent = ({ selectedLanguage, snippet, codeSnippets }: ResourceCo

    {snippet.title}

    {snippet.docsUrl !== undefined && ( - - - + )}
    {snippet.description !== undefined && ( diff --git a/studio/components/interfaces/ProjectAPIDocs/SecondLevelNav.tsx b/studio/components/interfaces/ProjectAPIDocs/SecondLevelNav.tsx index 88579e949a..05418acee2 100644 --- a/studio/components/interfaces/ProjectAPIDocs/SecondLevelNav.tsx +++ b/studio/components/interfaces/ProjectAPIDocs/SecondLevelNav.tsx @@ -153,19 +153,17 @@ const SecondLevelNav = () => {

    Head over to our docs site for the full API documentation.

    - - - +
    diff --git a/studio/components/interfaces/Reports/ReportPadding.tsx b/studio/components/interfaces/Reports/ReportPadding.tsx index 29eaf8c0df..5adf34a94a 100644 --- a/studio/components/interfaces/Reports/ReportPadding.tsx +++ b/studio/components/interfaces/Reports/ReportPadding.tsx @@ -1,7 +1,7 @@ /** * Standardized padding and width layout for non-custom reports */ -const ReportPadding: React.FC = ({ children }) => ( +const ReportPadding: React.FC = ({ children }) => (
    {children}
    diff --git a/studio/components/interfaces/SQLEditor/AISettingsModal.tsx b/studio/components/interfaces/SQLEditor/AISettingsModal.tsx index 3ef85daf75..8ab1da2e8b 100644 --- a/studio/components/interfaces/SQLEditor/AISettingsModal.tsx +++ b/studio/components/interfaces/SQLEditor/AISettingsModal.tsx @@ -31,11 +31,14 @@ const AISettingsModal = (props: ModalProps) => { variant="warning" title="This option is only available if your organization has opted-in to sending anonymous data to OpenAI." > - - - Go to your organization's settings to opt-in. - - + + Go to your organization's settings to opt-in. + )} diff --git a/studio/components/interfaces/SQLEditor/ResultsPane.tsx b/studio/components/interfaces/SQLEditor/ResultsPane.tsx index 95cc44270f..bea8ac2328 100644 --- a/studio/components/interfaces/SQLEditor/ResultsPane.tsx +++ b/studio/components/interfaces/SQLEditor/ResultsPane.tsx @@ -1,4 +1,4 @@ -import DataGrid, { Row } from '@supabase/react-data-grid' +import DataGrid, { Row } from 'react-data-grid' interface ResultsPaneProps { results: any @@ -48,7 +48,7 @@ const ResultsPane = ({ results }: ResultsPaneProps) => { diff --git a/studio/components/interfaces/SQLEditor/UtilityPanel/Results.tsx b/studio/components/interfaces/SQLEditor/UtilityPanel/Results.tsx index 892aa1d149..2d9ebb396a 100644 --- a/studio/components/interfaces/SQLEditor/UtilityPanel/Results.tsx +++ b/studio/components/interfaces/SQLEditor/UtilityPanel/Results.tsx @@ -1,8 +1,8 @@ -import DataGrid, { Column } from '@supabase/react-data-grid' import { useKeyboardShortcuts } from 'hooks' import { copyToClipboard } from 'lib/helpers' import { useState } from 'react' import { Item, Menu, useContextMenu } from 'react-contexify' +import DataGrid, { CalculatedColumn } from 'react-data-grid' import { createPortal } from 'react-dom' import { IconClipboard } from 'ui' @@ -54,13 +54,22 @@ const Results = ({ id, rows }: { id: string; rows: readonly any[] }) => { const columnRender = (name: string) => { return
    {name}
    } - const columns: Column[] = Object.keys(rows?.[0] ?? []).map((key) => ({ + const columns: CalculatedColumn[] = Object.keys(rows?.[0] ?? []).map((key, idx) => ({ + idx, key, name: key, - formatter: ({ row }: any) => formatter(key, row), - headerRenderer: () => columnRender(key), resizable: true, + parent: undefined, + level: 0, width: 120, + minWidth: 120, + maxWidth: undefined, + draggable: false, + frozen: false, + sortable: false, + isLastFrozenColumn: false, + renderCell: ({ row }: any) => formatter(key, row), + renderHeaderCell: () => columnRender(key), })) function onSelectedCellChange(position: any) { @@ -80,7 +89,9 @@ const Results = ({ id, rows }: { id: string; rows: readonly any[] }) => { '[&>.rdg-cell]:items-center'} onSelectedCellChange={onSelectedCellChange} /> {typeof window !== 'undefined' && diff --git a/studio/components/interfaces/SQLEditor/UtilityPanel/UtilityTabResults.tsx b/studio/components/interfaces/SQLEditor/UtilityPanel/UtilityTabResults.tsx index 6d98ad50a2..a3dc1c60bd 100644 --- a/studio/components/interfaces/SQLEditor/UtilityPanel/UtilityTabResults.tsx +++ b/studio/components/interfaces/SQLEditor/UtilityPanel/UtilityTabResults.tsx @@ -55,6 +55,10 @@ const UtilityTabResults = ({ id, isExecuting }: UtilityTabResultsProps) => { // Customers on HIPAA plans should not have access to Supabase AI const hasHipaaAddon = subscriptionHasHipaaAddon(subscription) + const isTimeout = + result?.error.message?.includes('canceling statement due to statement timeout') || + result?.error.message?.includes('upstream request timeout') + if (isUtilityPanelCollapsed) return null if (isExecuting) { @@ -64,24 +68,51 @@ const UtilityTabResults = ({ id, isExecuting }: UtilityTabResultsProps) => { ) } else if (result?.error) { - const formattedError = (result.error?.formattedError.split('\n') ?? []).filter( + const formattedError = (result.error?.formattedError?.split('\n') ?? []).filter( (x: string) => x.length > 0 ) return (
    -
    - {formattedError.length > 0 ? ( - formattedError.map((x: string, i: number) => ( -
    -                  {x}
    -                
    - )) - ) : ( -

    {result.error.error}

    - )} -
    + {isTimeout ? ( +
    +

    SQL query ran into an upstream timeout

    +

    + You can either{' '} + + optimize your query + + , or{' '} + + increase the statement timeout + + . +

    +
    + ) : ( +
    + {formattedError.length > 0 ? ( + formattedError.map((x: string, i: number) => ( +
    +                    {x}
    +                  
    + )) + ) : ( +

    {result.error.error}

    + )} +
    + )} {supabaseAIEnabled && !hasHipaaAddon && ( )}
    - {(result.error.message ?? result.error)?.includes( - 'canceling statement due to statement timeout' - ) && ( -

    - You can either{' '} - - optimize your query - - , or{' '} - - increase the statement timeout - - . -

    - )}
    ) } else if (!result) { @@ -156,7 +169,7 @@ const UtilityTabResults = ({ id, isExecuting }: UtilityTabResultsProps) => { } return ( -
    +
    ) diff --git a/studio/components/interfaces/Settings/Addons/Addons.tsx b/studio/components/interfaces/Settings/Addons/Addons.tsx index 56f6173d75..9932c1cf33 100644 --- a/studio/components/interfaces/Settings/Addons/Addons.tsx +++ b/studio/components/interfaces/Settings/Addons/Addons.tsx @@ -104,8 +104,11 @@ const Addons = () => { Updating addons are not available while you're on a preview branch. To manage your addons, you may return to your{' '} - - main branch + + main branch . @@ -143,23 +146,27 @@ const Addons = () => {

    More information

    - - -
    -

    About compute add-ons

    - -
    -
    + +
    +

    About compute add-ons

    + +
    - - -
    -

    Connection Pooler

    - -
    -
    + +
    +

    Connection Pooler

    + +
    @@ -243,35 +250,31 @@ const Addons = () => {
    - -
    -

    - Memory -

    - -
    -
    +
    +

    + Memory +

    + +

    {computeInstance?.variant?.meta?.memory_gb ?? 1} GB

    - -
    -

    - CPU -

    - -
    -
    +
    +

    + CPU +

    + +

    {computeInstance?.variant?.meta?.cpu_cores ?? 2}-core {cpuArchitecture}{' '} @@ -292,18 +295,16 @@ const Addons = () => {

    - -
    -

    - Max Disk Throughput -

    - -
    -
    +
    +

    + Max Disk Throughput +

    + +

    {computeInstance?.variant?.meta?.max_disk_io_mbs?.toLocaleString() ?? @@ -313,18 +314,16 @@ const Addons = () => {

    - -
    -

    - Baseline Disk Throughput -

    - -
    -
    +
    +

    + Baseline Disk Throughput +

    + +

    {computeInstance?.variant?.meta?.baseline_disk_io_mbs?.toLocaleString() ?? @@ -348,13 +347,15 @@ const Addons = () => {

    More information

    - - -
    -

    About PITR backups

    - -
    -
    + +
    +

    About PITR backups

    + +
    @@ -396,14 +397,13 @@ const Addons = () => {

    Reach out to us via support if you're interested

    - - - + + ) : ( @@ -442,13 +442,15 @@ const Addons = () => {

    More information

    - - -
    -

    About custom domains

    - -
    -
    + +
    +

    About custom domains

    + +
    diff --git a/studio/components/interfaces/Settings/Addons/ComputeInstanceSidePanel.tsx b/studio/components/interfaces/Settings/Addons/ComputeInstanceSidePanel.tsx index 6cfb75416d..c0fdcd033f 100644 --- a/studio/components/interfaces/Settings/Addons/ComputeInstanceSidePanel.tsx +++ b/studio/components/interfaces/Settings/Addons/ComputeInstanceSidePanel.tsx @@ -195,13 +195,15 @@ const ComputeInstanceSidePanel = () => { header={

    Change project compute size

    - - - - - +
    } > @@ -275,11 +277,11 @@ const ComputeInstanceSidePanel = () => { title="Changing your compute size is only available on the Pro plan" actions={ isOrgBilling ? ( - - - - - + ) : ( - - +
    } > @@ -153,8 +155,8 @@ const CustomDomainSidePanel = () => {

    Custom domains allow you to present a branded experience to your users. You may set up your custom domain in the{' '} - - General Settings + + General Settings {' '} page after enabling the add-on.

    @@ -272,11 +274,11 @@ const CustomDomainSidePanel = () => { title="Custom domains are unavailable on the free plan" actions={ isOrgBilling ? ( - - - - - + ) : ( - - +
    } > @@ -234,11 +236,11 @@ const PITRSidePanel = () => { title="Changing your Point-In-Time-Recovery is only available on the Pro plan" actions={ isOrgBilling ? ( - - - - - + ) : ( - - + diff --git a/studio/components/interfaces/Settings/Database/DatabaseSettings/DatabaseSettings.tsx b/studio/components/interfaces/Settings/Database/DatabaseSettings/DatabaseSettings.tsx index 8497b40720..e7ff73d886 100644 --- a/studio/components/interfaces/Settings/Database/DatabaseSettings/DatabaseSettings.tsx +++ b/studio/components/interfaces/Settings/Database/DatabaseSettings/DatabaseSettings.tsx @@ -210,16 +210,15 @@ const DatabaseSettings = () => { - - - - - + )} diff --git a/studio/components/interfaces/Settings/Database/DiskSizeConfiguration.tsx b/studio/components/interfaces/Settings/Database/DiskSizeConfiguration.tsx index 685fd82ae5..55dafef487 100644 --- a/studio/components/interfaces/Settings/Database/DiskSizeConfiguration.tsx +++ b/studio/components/interfaces/Settings/Database/DiskSizeConfiguration.tsx @@ -159,9 +159,11 @@ const DiskSizeConfiguration = ({ disabled = false }: DiskSizeConfigurationProps) variant="info" title={'Disk size configuration is not available for projects on the Free plan'} actions={ - - - + } >
    diff --git a/studio/components/interfaces/Settings/Database/NetworkRestrictions/NetworkRestrictions.tsx b/studio/components/interfaces/Settings/Database/NetworkRestrictions/NetworkRestrictions.tsx index 0814036169..2e1b95a7f0 100644 --- a/studio/components/interfaces/Settings/Database/NetworkRestrictions/NetworkRestrictions.tsx +++ b/studio/components/interfaces/Settings/Database/NetworkRestrictions/NetworkRestrictions.tsx @@ -110,13 +110,15 @@ const NetworkRestrictions = ({}) => { description="Allow specific IP ranges to have access to your database." />
    - - - - - + - - +
    @@ -110,10 +108,13 @@ const SSLConfiguration = () => { title="SSL enforcement was not updated successfully" > Please try updating again, or contact{' '} - - - support - + + support {' '} if this error persists diff --git a/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainActivate.tsx b/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainActivate.tsx index 85f926d6c9..557633ceb3 100644 --- a/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainActivate.tsx +++ b/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainActivate.tsx @@ -99,13 +99,15 @@ const CustomDomainActivate = ({ projectRef, customDomain }: CustomDomainActivate
    - - - - - +
    - - + - - +
    - - + ) } /> diff --git a/studio/components/interfaces/Settings/General/General.tsx b/studio/components/interfaces/Settings/General/General.tsx index c922bf2dad..dbd1670760 100644 --- a/studio/components/interfaces/Settings/General/General.tsx +++ b/studio/components/interfaces/Settings/General/General.tsx @@ -67,8 +67,11 @@ const General = () => { Certain settings are not available while you're on a preview branch. To adjust your project settings, you may return to your{' '} - - main branch + + main branch . @@ -160,11 +163,13 @@ const General = () => {

    - - - - - +
    + +
    diff --git a/studio/components/interfaces/Settings/General/Infrastructure/Infrastructure.tsx b/studio/components/interfaces/Settings/General/Infrastructure/Infrastructure.tsx index 99af70d986..8732ba8eef 100644 --- a/studio/components/interfaces/Settings/General/Infrastructure/Infrastructure.tsx +++ b/studio/components/interfaces/Settings/General/Infrastructure/Infrastructure.tsx @@ -134,15 +134,15 @@ const Infrastructure = ({}: InfrastructureProps) => { Please reach out to us via our support form if you are keen to upgrade your Postgres version to the latest available ({latestPgVersion}).

    - - - - - + )} diff --git a/studio/components/interfaces/Settings/General/Infrastructure/ProjectUpgradeAlert/ProjectUpgradeAlert.tsx b/studio/components/interfaces/Settings/General/Infrastructure/ProjectUpgradeAlert/ProjectUpgradeAlert.tsx index 3a2fc1bb38..73a3ae05b8 100644 --- a/studio/components/interfaces/Settings/General/Infrastructure/ProjectUpgradeAlert/ProjectUpgradeAlert.tsx +++ b/studio/components/interfaces/Settings/General/Infrastructure/ProjectUpgradeAlert/ProjectUpgradeAlert.tsx @@ -110,16 +110,15 @@ const ProjectUpgradeAlert = () => {

    - - - +
    @@ -153,16 +152,15 @@ const ProjectUpgradeAlert = () => {
    - - - +
    diff --git a/studio/components/interfaces/Settings/General/TransferProjectPanel/TransferProjectButton.tsx b/studio/components/interfaces/Settings/General/TransferProjectPanel/TransferProjectButton.tsx index 1eecf14c5c..003e5c265d 100644 --- a/studio/components/interfaces/Settings/General/TransferProjectPanel/TransferProjectButton.tsx +++ b/studio/components/interfaces/Settings/General/TransferProjectPanel/TransferProjectButton.tsx @@ -145,10 +145,13 @@ const TransferProjectButton = () => {

    To transfer projects, the owner must be a member of both the source and target organizations. For further information see our{' '} - - - Documentation - + + Documentation .

    @@ -227,16 +230,22 @@ const TransferProjectButton = () => {

    The target organization needs to use{' '} - - - organization-based billing - + + organization-based billing . To migrate an organization to the new billing, head to your{' '} - - - organizations billing settings - + + organizations billing settings .

    diff --git a/studio/components/interfaces/Settings/Infrastructure/InfrastructureActivity.tsx b/studio/components/interfaces/Settings/Infrastructure/InfrastructureActivity.tsx index a1029d516a..d8c4fa01f6 100644 --- a/studio/components/interfaces/Settings/Infrastructure/InfrastructureActivity.tsx +++ b/studio/components/interfaces/Settings/Infrastructure/InfrastructureActivity.tsx @@ -231,13 +231,11 @@ const InfrastructureActivity = () => {

    {attribute.links.map((link) => (
    - - -
    -

    {link.name}

    - -
    -
    + +
    +

    {link.name}

    + +
    ))} diff --git a/studio/components/interfaces/Settings/Infrastructure/InfrastructureInfo.tsx b/studio/components/interfaces/Settings/Infrastructure/InfrastructureInfo.tsx index dc10659ab6..82a361ff92 100644 --- a/studio/components/interfaces/Settings/Infrastructure/InfrastructureInfo.tsx +++ b/studio/components/interfaces/Settings/Infrastructure/InfrastructureInfo.tsx @@ -143,16 +143,15 @@ const InfrastructureInfo = () => { Please reach out to us via our support form if you are keen to upgrade your Postgres version to the latest available ({latestPgVersion}).

    - - - + )} @@ -185,16 +184,15 @@ const InfrastructureInfo = () => { operation is complete.

    - - - +
    diff --git a/studio/components/interfaces/Settings/Integrations/VercelIntegration/VercelSection.tsx b/studio/components/interfaces/Settings/Integrations/VercelIntegration/VercelSection.tsx index e34ea6c543..f4eed0be0e 100644 --- a/studio/components/interfaces/Settings/Integrations/VercelIntegration/VercelSection.tsx +++ b/studio/components/interfaces/Settings/Integrations/VercelIntegration/VercelSection.tsx @@ -180,11 +180,11 @@ You can change the scope of the access for Supabase by configuring }) ) : (
    - - - +
    )} {VercelContentSectionBottom && ( diff --git a/studio/components/interfaces/Settings/Logs/LogColumnRenderers/AuthColumnRenderer.tsx b/studio/components/interfaces/Settings/Logs/LogColumnRenderers/AuthColumnRenderer.tsx index 126303726d..ebfa56ed5d 100644 --- a/studio/components/interfaces/Settings/Logs/LogColumnRenderers/AuthColumnRenderer.tsx +++ b/studio/components/interfaces/Settings/Logs/LogColumnRenderers/AuthColumnRenderer.tsx @@ -1,30 +1,31 @@ -import { PreviewLogData } from '..' +import { Column } from 'react-data-grid' +import { LogData } from '..' import { RowLayout, SeverityFormatter, TextFormatter, TimestampLocalFormatter, } from '../LogsFormatters' -import DefaultPreviewColumnRenderer from './DefaultPreviewColumnRenderer' +import { defaultRenderCell } from './DefaultPreviewColumnRenderer' -export default [ +const columns: Column[] = [ { - formatter: (data: { - row: PreviewLogData & { level: string; msg: string | null; status: number; path: string } - }) => { - if (!data.row.level) { - return DefaultPreviewColumnRenderer[0].formatter(data) + name: 'auth-first-column', + key: 'auth-first-column', + renderCell: (props) => { + if (!props.row.level) { + return defaultRenderCell(props) } return ( - - {data.row.level && } + + {props.row.level && } @@ -32,3 +33,5 @@ export default [ }, }, ] + +export default columns diff --git a/studio/components/interfaces/Settings/Logs/LogColumnRenderers/DatabaseApiColumnRender.tsx b/studio/components/interfaces/Settings/Logs/LogColumnRenderers/DatabaseApiColumnRender.tsx index 8c2375150b..17ef7e738e 100644 --- a/studio/components/interfaces/Settings/Logs/LogColumnRenderers/DatabaseApiColumnRender.tsx +++ b/studio/components/interfaces/Settings/Logs/LogColumnRenderers/DatabaseApiColumnRender.tsx @@ -1,25 +1,31 @@ +import { Column } from 'react-data-grid' +import { LogData } from '../Logs.types' import { ResponseCodeFormatter, RowLayout, TextFormatter, TimestampLocalFormatter, } from '../LogsFormatters' -import DefaultPreviewColumnRenderer from './DefaultPreviewColumnRenderer' +import { defaultRenderCell } from './DefaultPreviewColumnRenderer' -export default [ +const columns: Column[] = [ { - formatter: (data: any) => { - if (!data.row.status_code && !data.row.method && !data.row.path) { - return DefaultPreviewColumnRenderer[0].formatter(data) + name: 'database-api-first-column', + key: 'database-api-first-column', + renderCell: (props) => { + if (!props.row.status_code && !props.row.method && !props.row.path) { + return defaultRenderCell(props) } return ( - - - - + + + + ) }, }, ] + +export default columns diff --git a/studio/components/interfaces/Settings/Logs/LogColumnRenderers/DatabasePostgresColumnRender.tsx b/studio/components/interfaces/Settings/Logs/LogColumnRenderers/DatabasePostgresColumnRender.tsx index eff172a663..9704667ae6 100644 --- a/studio/components/interfaces/Settings/Logs/LogColumnRenderers/DatabasePostgresColumnRender.tsx +++ b/studio/components/interfaces/Settings/Logs/LogColumnRenderers/DatabasePostgresColumnRender.tsx @@ -1,24 +1,30 @@ +import { Column } from 'react-data-grid' +import { LogData } from '../Logs.types' import { RowLayout, SeverityFormatter, TextFormatter, TimestampLocalFormatter, } from '../LogsFormatters' -import DefaultPreviewColumnRenderer from './DefaultPreviewColumnRenderer' +import { defaultRenderCell } from './DefaultPreviewColumnRenderer' -export default [ +const columns: Column[] = [ { - formatter: (data: any) => { - if (!data.row.error_severity) { - return DefaultPreviewColumnRenderer[0].formatter(data) + name: 'database-postgres-first-column', + key: 'database-postgres-first-column', + renderCell: (props) => { + if (!props.row.error_severity) { + return defaultRenderCell(props) } return ( - - - + + + ) }, }, ] + +export default columns diff --git a/studio/components/interfaces/Settings/Logs/LogColumnRenderers/DefaultPreviewColumnRenderer.tsx b/studio/components/interfaces/Settings/Logs/LogColumnRenderers/DefaultPreviewColumnRenderer.tsx index 4f84b89bba..e945e75493 100644 --- a/studio/components/interfaces/Settings/Logs/LogColumnRenderers/DefaultPreviewColumnRenderer.tsx +++ b/studio/components/interfaces/Settings/Logs/LogColumnRenderers/DefaultPreviewColumnRenderer.tsx @@ -1,13 +1,20 @@ -import { PreviewLogData } from '..' +import { Column, RenderCellProps } from 'react-data-grid' +import { LogData } from '..' import { RowLayout, TextFormatter, TimestampLocalFormatter } from '../LogsFormatters' -export default [ +export const defaultRenderCell = (props: RenderCellProps) => ( + + + + +) + +const columns: Column[] = [ { - formatter: (data: { row: PreviewLogData }) => ( - - - - - ), + name: 'default-preview-first-column', + key: 'default-preview-first-column', + renderCell: defaultRenderCell, }, ] + +export default columns diff --git a/studio/components/interfaces/Settings/Logs/LogColumnRenderers/FunctionsEdgeColumnRender.tsx b/studio/components/interfaces/Settings/Logs/LogColumnRenderers/FunctionsEdgeColumnRender.tsx index c1c33dd4fb..ed4e9c10a4 100644 --- a/studio/components/interfaces/Settings/Logs/LogColumnRenderers/FunctionsEdgeColumnRender.tsx +++ b/studio/components/interfaces/Settings/Logs/LogColumnRenderers/FunctionsEdgeColumnRender.tsx @@ -1,25 +1,31 @@ +import { Column } from 'react-data-grid' +import { LogData } from '../Logs.types' import { ResponseCodeFormatter, RowLayout, TextFormatter, TimestampLocalFormatter, } from '../LogsFormatters' -import DefaultPreviewColumnRenderer from './DefaultPreviewColumnRenderer' +import { defaultRenderCell } from './DefaultPreviewColumnRenderer' -export default [ +const columns: Column[] = [ { - formatter: (data: any) => { - if (!data.row.status_code && !data.row.method) { - return DefaultPreviewColumnRenderer[0].formatter(data) + name: 'functions-edge-first-column', + key: 'functions-edge-first-column', + renderCell: (props) => { + if (!props.row.status_code && !props.row.method) { + return defaultRenderCell(props) } return ( - - - - + + + + ) }, }, ] + +export default columns diff --git a/studio/components/interfaces/Settings/Logs/LogColumnRenderers/FunctionsLogsColumnRender.tsx b/studio/components/interfaces/Settings/Logs/LogColumnRenderers/FunctionsLogsColumnRender.tsx index 15b2c3db7b..33ce303e04 100644 --- a/studio/components/interfaces/Settings/Logs/LogColumnRenderers/FunctionsLogsColumnRender.tsx +++ b/studio/components/interfaces/Settings/Logs/LogColumnRenderers/FunctionsLogsColumnRender.tsx @@ -1,28 +1,34 @@ +import { Column } from 'react-data-grid' +import { LogData } from '../Logs.types' import { RowLayout, SeverityFormatter, TextFormatter, TimestampLocalFormatter, } from '../LogsFormatters' -import DefaultPreviewColumnRenderer from './DefaultPreviewColumnRenderer' +import { defaultRenderCell } from './DefaultPreviewColumnRenderer' -export default [ +const columns: Column[] = [ { - formatter: (data: any) => { - if (!data.row.event_type && !data.row.level) { - return DefaultPreviewColumnRenderer[0].formatter(data) + name: 'functions-logs-first-column', + key: 'functions-logs-first-column', + renderCell: (props) => { + if (!props.row.event_type && !props.row.level) { + return defaultRenderCell(props) } return ( - - {data.row.event_type === 'uncaughtException' ? ( - + + {props.row.event_type === 'uncaughtException' ? ( + ) : ( - + )} - + ) }, }, ] + +export default columns diff --git a/studio/components/interfaces/Settings/Logs/LogTable.tsx b/studio/components/interfaces/Settings/Logs/LogTable.tsx index dd7da8b40f..79e7629183 100644 --- a/studio/components/interfaces/Settings/Logs/LogTable.tsx +++ b/studio/components/interfaces/Settings/Logs/LogTable.tsx @@ -1,21 +1,20 @@ -import DataGrid, { Row, RowRendererProps } from '@supabase/react-data-grid' -import { useCallback, useEffect, useMemo, useState } from 'react' +import { isEqual } from 'lodash' +import { Key, ReactNode, useCallback, useEffect, useMemo, useState } from 'react' +import DataGrid, { Column, RenderRowProps, Row } from 'react-data-grid' import { Alert, Button, IconClipboard, IconEye, IconEyeOff } from 'ui' import CSVButton from 'components/ui/CSVButton' import { useStore } from 'hooks' import { copyToClipboard } from 'lib/helpers' -import { isEqual } from 'lodash' -import { LogQueryError } from '.' +import { LogQueryError, isDefaultLogPreviewFormat } from '.' import AuthColumnRenderer from './LogColumnRenderers/AuthColumnRenderer' import DatabaseApiColumnRender from './LogColumnRenderers/DatabaseApiColumnRender' import DatabasePostgresColumnRender from './LogColumnRenderers/DatabasePostgresColumnRender' import DefaultPreviewColumnRenderer from './LogColumnRenderers/DefaultPreviewColumnRenderer' import FunctionsEdgeColumnRender from './LogColumnRenderers/FunctionsEdgeColumnRender' import FunctionsLogsColumnRender from './LogColumnRenderers/FunctionsLogsColumnRender' -import { LogData, QueryType } from './Logs.types' -import { isDefaultLogPreviewFormat } from './Logs.utils' import LogSelection, { LogSelectionProps } from './LogSelection' +import { LogData, QueryType } from './Logs.types' import DefaultErrorRenderer from './LogsErrorRenderers/DefaultErrorRenderer' import ResourcesExceededErrorRenderer from './LogsErrorRenderers/ResourcesExceededErrorRenderer' @@ -33,24 +32,6 @@ interface Props { } type LogMap = { [id: string]: LogData } -interface FormatterArg { - column: { - key: string - name: string - resizable: boolean - header: string - minWidth: number - idx: number - frozen: boolean - isLastFrozenColumn: boolean - rowGroup: boolean - sortable: boolean - } - isCellSelected: boolean - onRowChange: Function - row: any -} - /** * Logs table view with focus side panel * @@ -73,32 +54,32 @@ const LogTable = ({ const hasId = columnNames.includes('id') const hasTimestamp = columnNames.includes('timestamp') - const DEFAULT_COLUMNS = columnNames.map((v, idx: number) => { - let formatter = undefined - - formatter = (received: FormatterArg) => { - const value = received.row?.[v] - if (value && typeof value === 'object') { - return JSON.stringify(value) - } else if (value === null) { - return 'NULL' - } else { - return String(value) - } - } - return { + const DEFAULT_COLUMNS = columnNames.map((v: keyof LogData, idx) => { + const result: Column = { key: `logs-column-${idx}`, - name: v, + name: v as string, resizable: true, - formatter, - header: v, + renderCell: (props) => { + const value = props.row?.[v] + if (value && typeof value === 'object') { + return JSON.stringify(value) + } else if (value === null) { + return 'NULL' + } else { + return String(value) + } + }, + renderHeaderCell: (props) => { + return v + }, minWidth: 128, } + return result }) - let columns + let columns = DEFAULT_COLUMNS if (!queryType) { - columns = DEFAULT_COLUMNS + columns } else { switch (queryType) { case 'api': @@ -166,10 +147,10 @@ const LogTable = ({ } }, [stringData]) - const RowRenderer = useCallback( - (props: RowRendererProps) => ( - - ), + const RowRenderer = useCallback<(key: Key, props: RenderRowProps) => ReactNode>( + (key, props) => { + return + }, [] ) @@ -287,15 +268,7 @@ const LogTable = ({ setFocusedLog(data[rowIdx] as LogData) }} selectedRows={new Set([])} - noRowsFallback={ - !isLoading ? ( -
    - {!error && renderNoResultAlert()} - {error && renderErrorAlert()} -
    - ) : null - } - columns={columns as any} + columns={columns} rowClass={(row: LogData) => [ 'font-mono tracking-tight', @@ -310,8 +283,17 @@ const LogTable = ({ const row = r as LogData return row.id }} - onRowClick={setFocusedLog} - rowRenderer={RowRenderer} + // [Next 18 refactor] need to fix + // onRowClick={setFocusedLog} + renderers={{ + renderRow: RowRenderer, + noRowsFallback: !isLoading ? ( +
    + {!error && renderNoResultAlert()} + {error && renderErrorAlert()} +
    + ) : null, + }} /> {logDataRows.length > 0 ? (
    ( +const SqlSnippetCode: React.FC = ({ children }) => (
    {children}
    ) diff --git a/studio/components/interfaces/Settings/Logs/LogsFormatters.tsx b/studio/components/interfaces/Settings/Logs/LogsFormatters.tsx index b26a2cfd3a..28a737de33 100644 --- a/studio/components/interfaces/Settings/Logs/LogsFormatters.tsx +++ b/studio/components/interfaces/Settings/Logs/LogsFormatters.tsx @@ -10,7 +10,7 @@ import React from 'react' import { IconAlertCircle, IconInfo } from 'ui' import { isUnixMicro, unixMicroToIsoTimestamp } from '.' -export const RowLayout: React.FC = ({ children }) => ( +export const RowLayout: React.FC = ({ children }) => (
    {children}
    ) // renders a timestamp (either unix microsecond or iso timestamp) @@ -157,9 +157,10 @@ export const SeverityFormatter = ({ const uppercasedValue = value.toUpperCase() const text = uppercase ? uppercasedValue : value - const Layout: React.FC<{ className?: string }> = ({ className, children }) => ( -
    {children}
    - ) + const Layout: React.FC> = ({ + className, + children, + }) =>
    {children}
    switch (uppercasedValue) { case 'UNCAUGHTEXCEPTION': diff --git a/studio/components/interfaces/Settings/Logs/UpgradePrompt.tsx b/studio/components/interfaces/Settings/Logs/UpgradePrompt.tsx index f1a5654910..b06be1ba65 100644 --- a/studio/components/interfaces/Settings/Logs/UpgradePrompt.tsx +++ b/studio/components/interfaces/Settings/Logs/UpgradePrompt.tsx @@ -61,11 +61,9 @@ const UpgradePrompt: React.FC = ({ show, setShowUpgradePrompt }) => { - - - - - +
    diff --git a/studio/components/interfaces/Settings/Vault/Keys/EncryptionKeysManagement.tsx b/studio/components/interfaces/Settings/Vault/Keys/EncryptionKeysManagement.tsx index 57ac6f3088..3968441d78 100644 --- a/studio/components/interfaces/Settings/Vault/Keys/EncryptionKeysManagement.tsx +++ b/studio/components/interfaces/Settings/Vault/Keys/EncryptionKeysManagement.tsx @@ -140,13 +140,15 @@ const EncryptionKeysManagement = () => {
    - - - - - +
    diff --git a/studio/components/interfaces/Settings/Vault/Secrets/SecretsManagement.tsx b/studio/components/interfaces/Settings/Vault/Secrets/SecretsManagement.tsx index 9a4f1b6c54..22ca0db785 100644 --- a/studio/components/interfaces/Settings/Vault/Secrets/SecretsManagement.tsx +++ b/studio/components/interfaces/Settings/Vault/Secrets/SecretsManagement.tsx @@ -102,13 +102,15 @@ const SecretsManagement = () => {
    - - - - - +
    - - - - - +
    - - - - - +
    ) : (
    - - - - - +
    diff --git a/studio/components/interfaces/SignIn/SignInMfaForm.tsx b/studio/components/interfaces/SignIn/SignInMfaForm.tsx index d18ac5a304..3c4cf01d63 100644 --- a/studio/components/interfaces/SignIn/SignInMfaForm.tsx +++ b/studio/components/interfaces/SignIn/SignInMfaForm.tsx @@ -171,16 +171,12 @@ const SignInMfaForm = () => { )}
  • - - Reach out to us via support - + Reach out to us via support
  • diff --git a/studio/components/interfaces/SignIn/SignInWithSSO.tsx b/studio/components/interfaces/SignIn/SignInWithSSO.tsx index 6bfc853516..6558395444 100644 --- a/studio/components/interfaces/SignIn/SignInWithSSO.tsx +++ b/studio/components/interfaces/SignIn/SignInWithSSO.tsx @@ -3,11 +3,9 @@ import { Button, IconLock } from 'ui' const SignInWithSSO = () => { return ( - - - + ) } diff --git a/studio/components/interfaces/Storage/CreateBucketModal.tsx b/studio/components/interfaces/Storage/CreateBucketModal.tsx index 9768b69c86..a9ad0db92f 100644 --- a/studio/components/interfaces/Storage/CreateBucketModal.tsx +++ b/studio/components/interfaces/Storage/CreateBucketModal.tsx @@ -215,10 +215,11 @@ const CreateBucketModal = ({ visible, onClose }: CreateBucketModalProps) => {

    Note: The{' '} - - - global upload limit - + + global upload limit {' '} takes precedence over this value ({formattedGlobalUploadLimit})

    diff --git a/studio/components/interfaces/Storage/EditBucketModal.tsx b/studio/components/interfaces/Storage/EditBucketModal.tsx index 7316f8a74a..6e3bfc72e5 100644 --- a/studio/components/interfaces/Storage/EditBucketModal.tsx +++ b/studio/components/interfaces/Storage/EditBucketModal.tsx @@ -220,10 +220,11 @@ const EditBucketModal = ({ visible, bucket, onClose }: EditBucketModalProps) =>

    Note: The{' '} - - - global upload limit - + + global upload limit {' '} takes precedence over this value ({formattedGlobalUploadLimit})

    diff --git a/studio/components/interfaces/Support/DisabledStateForFreeTier.tsx b/studio/components/interfaces/Support/DisabledStateForFreeTier.tsx index d2be8f09d0..c4a22e72d4 100644 --- a/studio/components/interfaces/Support/DisabledStateForFreeTier.tsx +++ b/studio/components/interfaces/Support/DisabledStateForFreeTier.tsx @@ -20,20 +20,18 @@ const DisabledStateForFreeTier = ({ projectRef, category }: DisabledStateForFree

    Upgrade your project to the Pro plan for support in this area

    - - - - - - - - - - + +
    } diff --git a/studio/components/interfaces/Support/Success.tsx b/studio/components/interfaces/Support/Success.tsx index fa045d86c6..ec23215ffd 100644 --- a/studio/components/interfaces/Support/Success.tsx +++ b/studio/components/interfaces/Support/Success.tsx @@ -47,20 +47,21 @@ const Success = ({ sentCategory = '' }: SuccessProps) => { onChange={(e) => setSearchValue(e.target.value)} icon={} actions={[ - } > - - - - , + + Search on Github discussions + + , ]} />
    @@ -71,9 +72,7 @@ const Success = ({ sentCategory = '' }: SuccessProps) => {
    - - - +
    diff --git a/studio/components/interfaces/Support/SupportForm.tsx b/studio/components/interfaces/Support/SupportForm.tsx index bb8f76cf2c..3199917838 100644 --- a/studio/components/interfaces/Support/SupportForm.tsx +++ b/studio/components/interfaces/Support/SupportForm.tsx @@ -444,20 +444,22 @@ const SupportForm = ({ setSentCategory }: SupportFormProps) => { Enhanced SLAs for support are available on our Enterprise Plan.

    - - - - - - - - - - + +
    } @@ -489,15 +491,12 @@ const SupportForm = ({ setSentCategory }: SupportFormProps) => { - - Github discussions - - + Github discussions + for a quick answer

    @@ -562,16 +561,15 @@ const SupportForm = ({ setSentCategory }: SupportFormProps) => {

    - - - - - +
    ) @@ -589,16 +587,19 @@ const SupportForm = ({ setSentCategory }: SupportFormProps) => {

    - - - - - +
    diff --git a/studio/components/interfaces/TableGridEditor/DeleteConfirmationDialogs.tsx b/studio/components/interfaces/TableGridEditor/DeleteConfirmationDialogs.tsx index c599eca798..cdad1c6d2e 100644 --- a/studio/components/interfaces/TableGridEditor/DeleteConfirmationDialogs.tsx +++ b/studio/components/interfaces/TableGridEditor/DeleteConfirmationDialogs.tsx @@ -1,17 +1,23 @@ import { useQueryClient } from '@tanstack/react-query' import Link from 'next/link' +import toast from 'react-hot-toast' +import { Alert, Button, Checkbox, IconExternalLink, Modal } from 'ui' +import { SupaRow } from 'components/grid' +import { formatFilterURLParams } from 'components/grid/SupabaseGrid.utils' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import ConfirmationModal from 'components/ui/ConfirmationModal' import { entityTypeKeys } from 'data/entity-types/keys' import { sqlKeys } from 'data/sql/keys' +import { useTableRowDeleteAllMutation } from 'data/table-rows/table-row-delete-all-mutation' +import { useTableRowDeleteMutation } from 'data/table-rows/table-row-delete-mutation' +import { useTableRowTruncateMutation } from 'data/table-rows/table-row-truncate-mutation' import { tableKeys } from 'data/tables/keys' import { useGetTables } from 'data/tables/tables-query' import { useStore, useUrlState } from 'hooks' import { TableLike } from 'hooks/misc/useTable' import { noop } from 'lib/void' import { useTableEditorStateSnapshot } from 'state/table-editor' -import { Alert, Button, Checkbox, IconExternalLink, Modal } from 'ui' export type DeleteConfirmationDialogsProps = { projectRef?: string @@ -24,20 +30,70 @@ const DeleteConfirmationDialogs = ({ selectedTable, onAfterDeleteTable = noop, }: DeleteConfirmationDialogsProps) => { + const { meta, ui } = useStore() + const queryClient = useQueryClient() const { project } = useProjectContext() const snap = useTableEditorStateSnapshot() - const [, setParams] = useUrlState({ arrayKeys: ['filter', 'sort'] }) - - const queryClient = useQueryClient() - - const { meta, ui } = useStore() + const [{ filter }, setParams] = useUrlState({ arrayKeys: ['filter', 'sort'] }) + const filters = formatFilterURLParams(filter as string[]) const getTables = useGetTables({ projectRef: project?.ref, connectionString: project?.connectionString, }) + const { mutate: deleteRows } = useTableRowDeleteMutation({ + onSuccess: () => { + if (snap.confirmationDialog?.type === 'row') { + snap.confirmationDialog.callback?.() + } + toast.success(`Successfully deleted selected row(s)`) + snap.closeConfirmationDialog() + }, + onError: (error) => { + toast.error(`Failed to delete row: ${error.message}`) + snap.closeConfirmationDialog() + }, + }) + + const { mutateAsync: deleteAllRows } = useTableRowDeleteAllMutation({ + onSuccess: () => { + if (snap.confirmationDialog?.type === 'row') { + snap.confirmationDialog.callback?.() + } + toast.success(`Successfully deleted selected rows`) + snap.closeConfirmationDialog() + }, + onError: (error) => { + toast.error(`Failed to delete rows: ${error.message}`) + snap.closeConfirmationDialog() + }, + }) + + const { mutateAsync: truncateRows } = useTableRowTruncateMutation({ + onSuccess: () => { + if (snap.confirmationDialog?.type === 'row') { + snap.confirmationDialog.callback?.() + } + toast.success(`Successfully deleted all rows from table`) + snap.closeConfirmationDialog() + }, + onError: (error) => { + toast.error(`Failed to delete rows: ${error.message}`) + snap.closeConfirmationDialog() + }, + }) + + const isAllRowsSelected = + snap.confirmationDialog?.type === 'row' ? snap.confirmationDialog.allRowsSelected : false + const numRows = + snap.confirmationDialog?.type === 'row' + ? snap.confirmationDialog.allRowsSelected + ? snap.confirmationDialog.numRows ?? 0 + : snap.confirmationDialog.rows.length + : 0 + const removeDeletedColumnFromFiltersAndSorts = (columnName: string) => { setParams((prevParams) => { const existingFilters = (prevParams?.filter ?? []) as string[] @@ -57,7 +113,8 @@ const DeleteConfirmationDialogs = ({ }) } - const isDeleteWithCascade = snap.confirmationDialog?.isDeleteWithCascade ?? false + const isDeleteWithCascade = + snap.confirmationDialog?.type === 'column' ? snap.confirmationDialog.isDeleteWithCascade : false const onConfirmDeleteColumn = async () => { if (!(snap.confirmationDialog?.type === 'column')) return @@ -136,6 +193,37 @@ const DeleteConfirmationDialogs = ({ } } + const onConfirmDeleteRow = async () => { + if (!project) return console.error('Project ref is required') + if (!selectedTable) return console.error('Selected table required') + if (snap.confirmationDialog?.type !== 'row') return + const selectedRowsToDelete = snap.confirmationDialog.rows + + if (snap.confirmationDialog.allRowsSelected) { + if (filters.length === 0) { + truncateRows({ + projectRef: project.ref, + connectionString: project.connectionString, + table: selectedTable as any, + }) + } else { + deleteAllRows({ + projectRef: project.ref, + connectionString: project.connectionString, + table: selectedTable as any, + filters, + }) + } + } else { + deleteRows({ + projectRef: project.ref, + connectionString: project.connectionString, + table: selectedTable as any, + rows: selectedRowsToDelete as SupaRow[], + }) + } + } + return ( <> - - - - - + )} + - - - - - + )} + + + Confirm to delete the selected row{numRows > 1 && 's'} + + } + buttonLabel="Delete" + buttonLoadingLabel="Deleting" + onSelectCancel={() => snap.closeConfirmationDialog()} + onSelectConfirm={() => onConfirmDeleteRow()} + > + +
    +

    + Are you sure you want to delete {isAllRowsSelected ? 'all' : 'the selected'}{' '} + {numRows > 1 && `${numRows} `}row + {numRows > 1 && 's'}? This action cannot be undone. +

    +
    +
    +
    ) } diff --git a/studio/components/interfaces/TableGridEditor/GridHeaderActions.tsx b/studio/components/interfaces/TableGridEditor/GridHeaderActions.tsx index 64632c88c5..38397dcf28 100644 --- a/studio/components/interfaces/TableGridEditor/GridHeaderActions.tsx +++ b/studio/components/interfaces/TableGridEditor/GridHeaderActions.tsx @@ -139,26 +139,25 @@ const GridHeaderActions = ({ table, openAPIDocsPanel, refreshDocs }: GridHeaderA )} {(table.rls_enabled || showRLSWarning) && ( - - - - - + )} + - - - - + About data types + + } > @@ -379,8 +379,11 @@ const ColumnEditor = ({ {!isPgSodiumInstalled ? (

    You will need to{' '} - - install + + install {' '} the extension pgsodium first before being able to encrypt your column. diff --git a/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnType.tsx b/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnType.tsx index 3081435412..38e3bcd073 100644 --- a/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnType.tsx +++ b/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnType.tsx @@ -184,13 +184,11 @@ const ColumnType = ({ unless you have a very specific use case.

    - - - - - + diff --git a/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/ForeignRowSelector/ForeignRowSelector.tsx b/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/ForeignRowSelector/ForeignRowSelector.tsx index 7fb588b451..3425573402 100644 --- a/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/ForeignRowSelector/ForeignRowSelector.tsx +++ b/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/ForeignRowSelector/ForeignRowSelector.tsx @@ -2,17 +2,17 @@ import { PostgresTable } from '@supabase/postgres-meta' import { useState } from 'react' import { DndProvider } from 'react-dnd' import { HTML5Backend } from 'react-dnd-html5-backend' +import { IconLoader, SidePanel } from 'ui' import { parseSupaTable } from 'components/grid' -import FilterPopover from 'components/grid/components/header/filter' -import RefreshButton from 'components/grid/components/header/RefreshButton' -import SortPopover from 'components/grid/components/header/sort' import { formatFilterURLParams, formatSortURLParams } from 'components/grid/SupabaseGrid.utils' +import RefreshButton from 'components/grid/components/header/RefreshButton' +import FilterPopover from 'components/grid/components/header/filter' +import SortPopover from 'components/grid/components/header/sort' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { ForeignKeyConstraint } from 'data/database/foreign-key-constraints-query' import { useTableRowsQuery } from 'data/table-rows/table-rows-query' import { useTableQuery } from 'data/tables/table-query' -import { IconLoader, SidePanel } from 'ui' import ActionBar from '../../ActionBar' import { useEncryptedColumns } from './ForeignRowSelector.utils' import Pagination from './Pagination' diff --git a/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/ForeignRowSelector/SelectorGrid.tsx b/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/ForeignRowSelector/SelectorGrid.tsx index 3aa6d6cee2..d760250cf9 100644 --- a/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/ForeignRowSelector/SelectorGrid.tsx +++ b/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/ForeignRowSelector/SelectorGrid.tsx @@ -1,4 +1,4 @@ -import DataGrid, { Column } from '@supabase/react-data-grid' +import DataGrid, { Column } from 'react-data-grid' import * as Tooltip from '@radix-ui/react-tooltip' import { SupaRow, SupaTable } from 'components/grid' import { IconKey } from 'ui' @@ -73,7 +73,7 @@ const SelectorGrid = ({ table, rows, onRowSelect }: SelectorGridProps) => { columns={columns} rows={rows} style={{ height: '100%' }} - onRowClick={onRowSelect} + onCellClick={(props) => onRowSelect(props.row)} rowClass={() => 'cursor-pointer'} /> ) diff --git a/studio/components/interfaces/TableGridEditor/SidePanelEditor/SpreadsheetImport/SpreadsheetImport.tsx b/studio/components/interfaces/TableGridEditor/SidePanelEditor/SpreadsheetImport/SpreadsheetImport.tsx index ea654cb650..b7735a8298 100644 --- a/studio/components/interfaces/TableGridEditor/SidePanelEditor/SpreadsheetImport/SpreadsheetImport.tsx +++ b/studio/components/interfaces/TableGridEditor/SidePanelEditor/SpreadsheetImport/SpreadsheetImport.tsx @@ -85,13 +85,15 @@ const SpreadsheetImport = ({

    The dashboard currently only supports importing of CSVs below 100MB.

    For bulk data loading, we recommend doing so directly through the database.

    - - - +
    , { duration: Infinity } ) diff --git a/studio/components/interfaces/TableGridEditor/SidePanelEditor/SpreadsheetImport/SpreadsheetPreviewGrid.tsx b/studio/components/interfaces/TableGridEditor/SidePanelEditor/SpreadsheetImport/SpreadsheetPreviewGrid.tsx index 7539927999..4824459743 100644 --- a/studio/components/interfaces/TableGridEditor/SidePanelEditor/SpreadsheetImport/SpreadsheetPreviewGrid.tsx +++ b/studio/components/interfaces/TableGridEditor/SidePanelEditor/SpreadsheetImport/SpreadsheetPreviewGrid.tsx @@ -1,4 +1,4 @@ -import DataGrid from '@supabase/react-data-grid' +import DataGrid from 'react-data-grid' import clsx from 'clsx' const MAX_ROWS = 20 diff --git a/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/ColumnManagement.tsx b/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/ColumnManagement.tsx index be2b15c43b..e532382221 100644 --- a/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/ColumnManagement.tsx +++ b/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/ColumnManagement.tsx @@ -184,7 +184,7 @@ const ColumnManagement = ({ icon={} title="Composite primary key selected" description="The columns that you've selected will be grouped as a primary key, and will serve - as the unique identifier for the rows in your table" + as the unique identifier for the rows in your table" /> )} @@ -340,17 +340,20 @@ const ColumnManagement = ({ Add column )} - - - - - +

    - - - - - +

    diff --git a/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/TableEditor.tsx b/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/TableEditor.tsx index dd97c46743..e6d5e4d864 100644 --- a/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/TableEditor.tsx +++ b/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/TableEditor.tsx @@ -251,13 +251,15 @@ const TableEditor = ({

    You can create policies after you create this table.

    )}

    - - - - - +

    ) : ( @@ -272,13 +274,15 @@ const TableEditor = ({ publicly writable and readable

    - - - - - +

    )} diff --git a/studio/components/interfaces/TableGridEditor/TableDefinition.tsx b/studio/components/interfaces/TableGridEditor/TableDefinition.tsx index 83e00cc868..7e2747b48b 100644 --- a/studio/components/interfaces/TableGridEditor/TableDefinition.tsx +++ b/studio/components/interfaces/TableGridEditor/TableDefinition.tsx @@ -103,14 +103,13 @@ const TableDefinition = ({ id }: TableDefinitionProps) => { return (
    - - - + - - - + )} + + {isSubitem ?

    {label}

    : label} +
    + ) } diff --git a/studio/components/layouts/AccountLayout/WithSidebar.tsx b/studio/components/layouts/AccountLayout/WithSidebar.tsx index 385e15b473..2698722a9f 100644 --- a/studio/components/layouts/AccountLayout/WithSidebar.tsx +++ b/studio/components/layouts/AccountLayout/WithSidebar.tsx @@ -206,22 +206,20 @@ const SidebarLinkItem = ({ } return ( - - - - {isExternal && ( - - - - )} - - {isSubitem ?

    {label}

    : label} + + + {isExternal && ( + + + )} + + {isSubitem ?

    {label}

    : label}
    -
    + ) } diff --git a/studio/components/layouts/AppLayout/AppHeader.tsx b/studio/components/layouts/AppLayout/AppHeader.tsx index e5cffc75cb..0ffea0c237 100644 --- a/studio/components/layouts/AppLayout/AppHeader.tsx +++ b/studio/components/layouts/AppLayout/AppHeader.tsx @@ -26,14 +26,15 @@ const AppHeader = () => { return (
    - - - Supabase - + + Supabase {ref !== undefined && } diff --git a/studio/components/layouts/AppLayout/BranchDropdown.tsx b/studio/components/layouts/AppLayout/BranchDropdown.tsx index d144dc484e..b58ac18b4e 100644 --- a/studio/components/layouts/AppLayout/BranchDropdown.tsx +++ b/studio/components/layouts/AppLayout/BranchDropdown.tsx @@ -1,7 +1,7 @@ import { ListTree } from 'lucide-react' import Link from 'next/link' import { useRouter } from 'next/router' -import { useRef, useState } from 'react' +import { useState } from 'react' import { useParams } from 'common' import ShimmeringLoader from 'components/ui/ShimmeringLoader' @@ -43,7 +43,6 @@ const BranchLink = ({ return ( { @@ -54,12 +53,10 @@ const BranchLink = ({ setOpen(false) }} > - -

    - {branch.name} -

    - {isSelected && } -
    +

    + {branch.name} +

    + {isSelected && }
    ) @@ -132,22 +129,22 @@ const BranchDropdown = ({ isNewNav = false }: BranchDropdownProps) => { - - { - setOpen(false) - router.push(`/project/${ref}/branches`) - }} - onClick={() => setOpen(false)} + { + setOpen(false) + router.push(`/project/${ref}/branches`) + }} + onClick={() => setOpen(false)} + > + - - -

    Manage branches

    -
    -
    - + +

    Manage branches

    + +
    diff --git a/studio/components/layouts/AppLayout/EnableBranchingButton/BranchingWaitlistPopover.tsx b/studio/components/layouts/AppLayout/EnableBranchingButton/BranchingWaitlistPopover.tsx index 79af22b360..ee1139cc01 100644 --- a/studio/components/layouts/AppLayout/EnableBranchingButton/BranchingWaitlistPopover.tsx +++ b/studio/components/layouts/AppLayout/EnableBranchingButton/BranchingWaitlistPopover.tsx @@ -39,11 +39,15 @@ const BranchingWaitlistPopover = ({ isNewNav = false }: BranchingWaitlistPopover enrolled in database branching.

    diff --git a/studio/components/layouts/AppLayout/EnableBranchingButton/GithubRepositorySelection.tsx b/studio/components/layouts/AppLayout/EnableBranchingButton/GithubRepositorySelection.tsx index 00294773c8..62f6e1d839 100644 --- a/studio/components/layouts/AppLayout/EnableBranchingButton/GithubRepositorySelection.tsx +++ b/studio/components/layouts/AppLayout/EnableBranchingButton/GithubRepositorySelection.tsx @@ -78,13 +78,9 @@ const GithubRepositorySelection = ({ : 'Your database preview branches will be based on the branches in the Git repository that your project is connected with.'}

    {!hasGithubIntegrationInstalled && ( - - - - - + )} {hasGithubIntegrationInstalled && !githubConnection && ( Previews can be available by connecting your Supabase project to a Vercel project.

    {!integration && ( - - - - - + )} {integration && !vercelProjectIntegration &&
    Connect project
    } {integration && vercelProjectIntegration &&
    Select project
    } diff --git a/studio/components/layouts/AppLayout/IncidentBanner.tsx b/studio/components/layouts/AppLayout/IncidentBanner.tsx index e2c4f5b16d..49aedbd572 100644 --- a/studio/components/layouts/AppLayout/IncidentBanner.tsx +++ b/studio/components/layouts/AppLayout/IncidentBanner.tsx @@ -3,15 +3,13 @@ import { IconExternalLink } from 'ui' const IncidentBanner = () => { return ( - - -
    -

    - We are currently investigating a technical issue, follow status.supabase.com for updates -

    - -
    -
    + +
    +

    + We are currently investigating a technical issue, follow status.supabase.com for updates +

    + +
    ) } diff --git a/studio/components/layouts/AppLayout/OrganizationDropdown.tsx b/studio/components/layouts/AppLayout/OrganizationDropdown.tsx index c008b6c7c7..cfb146006d 100644 --- a/studio/components/layouts/AppLayout/OrganizationDropdown.tsx +++ b/studio/components/layouts/AppLayout/OrganizationDropdown.tsx @@ -82,45 +82,40 @@ const OrganizationDropdown = ({ isNewNav = false }: OrganizationDropdownProps) = ? `/org/${org.slug}` : `/org/${org.slug}/general` return ( - - { - setOpen(false) - router.push(href) - }} - onClick={() => setOpen(false)} - > - - {org.name} - {org.slug === slug && } - - - + { + setOpen(false) + router.push(href) + }} + onClick={() => setOpen(false)} + > + + {org.name} + {org.slug === slug && } + + ) })} {organizationCreationEnabled && ( - - { - setOpen(false) - router.push(`/new`) - }} - onClick={() => setOpen(false)} - > - - -

    New organization

    -
    -
    - + { + setOpen(false) + router.push(`/new`) + }} + onClick={() => setOpen(false)} + > + + +

    New organization

    + +
    )} diff --git a/studio/components/layouts/AppLayout/ProjectDropdown.tsx b/studio/components/layouts/AppLayout/ProjectDropdown.tsx index b0a787a0c0..c72011468c 100644 --- a/studio/components/layouts/AppLayout/ProjectDropdown.tsx +++ b/studio/components/layouts/AppLayout/ProjectDropdown.tsx @@ -78,24 +78,21 @@ const ProjectLink = ({ } return ( - - { - router.push(href) - setOpen(false) - }} - onClick={() => setOpen(false)} - > - - {project.name} - {project.ref === ref && } - - - + { + router.push(href) + setOpen(false) + }} + onClick={() => setOpen(false)} + > + + {project.name} + {project.ref === ref && } + + ) } @@ -169,28 +166,25 @@ const ProjectDropdown = ({ isNewNav = false }: ProjectDropdownProps) => { {projectCreationEnabled && ( - { + { setOpen(false) + router.push(`/new/${selectedOrganization?.slug}`) }} + onClick={() => setOpen(false)} > - { + { setOpen(false) - router.push(`/new/${selectedOrganization?.slug}`) }} - onClick={() => setOpen(false)} + className="w-full flex items-center gap-2" > - - -

    New project

    -
    -
    - + +

    New project

    + +
    )} diff --git a/studio/components/layouts/AppLayout/SettingsButton.tsx b/studio/components/layouts/AppLayout/SettingsButton.tsx index 035c564093..36a909d44a 100644 --- a/studio/components/layouts/AppLayout/SettingsButton.tsx +++ b/studio/components/layouts/AppLayout/SettingsButton.tsx @@ -9,13 +9,11 @@ const SettingsButton = () => { return ( - - - - - - - + + + + + diff --git a/studio/components/layouts/AppLayout/UserSettingsDropdown.tsx b/studio/components/layouts/AppLayout/UserSettingsDropdown.tsx index 93cea0f592..6e24085177 100644 --- a/studio/components/layouts/AppLayout/UserSettingsDropdown.tsx +++ b/studio/components/layouts/AppLayout/UserSettingsDropdown.tsx @@ -55,22 +55,16 @@ const UserSettingsDropdown = () => {
    - - setOpen(false)} asChild> - Preferences - - - - setOpen(false)} asChild> - Access tokens - - + setOpen(false)} asChild> + Preferences + + setOpen(false)} asChild> + Access tokens + {showAuditLogs ? ( - - setOpen(false)} asChild> - Audit logs - - + setOpen(false)} asChild> + Audit logs + ) : null} ) => {
    {/* Header */}
    - - - - + +

    Customize your plan

    diff --git a/studio/components/layouts/DocsLayout/DocsLayout.tsx b/studio/components/layouts/DocsLayout/DocsLayout.tsx index 10ddcd7c04..7882550e18 100644 --- a/studio/components/layouts/DocsLayout/DocsLayout.tsx +++ b/studio/components/layouts/DocsLayout/DocsLayout.tsx @@ -14,7 +14,6 @@ function DocsLayout({ title, children }: { title: string; children: ReactElement const { ui, meta } = useStore() const { data, isLoading, error } = meta.openApi const selectedProject = useSelectedProject() - const isPaused = selectedProject?.status === PROJECT_STATUS.INACTIVE const getPage = () => { @@ -29,7 +28,7 @@ function DocsLayout({ title, children }: { title: string; children: ReactElement if (ui.selectedProjectRef && !isPaused) { meta.openApi.load() } - }, [ui.selectedProjectRef]) + }, [ui.selectedProjectRef, isPaused]) if (error) { return ( diff --git a/studio/components/layouts/FunctionsLayout.tsx b/studio/components/layouts/FunctionsLayout.tsx index 3cbe746ef0..605b6f2ecd 100644 --- a/studio/components/layouts/FunctionsLayout.tsx +++ b/studio/components/layouts/FunctionsLayout.tsx @@ -111,11 +111,9 @@ const FunctionsLayout = ({ title, children }: PropsWithChildren
    - - - - - + {isNewAPIDocsEnabled && ( - - +
    diff --git a/studio/components/layouts/IntegrationsLayout/IntegrationWindowLayout.tsx b/studio/components/layouts/IntegrationsLayout/IntegrationWindowLayout.tsx index 7db53f8073..bffc38dd6b 100644 --- a/studio/components/layouts/IntegrationsLayout/IntegrationWindowLayout.tsx +++ b/studio/components/layouts/IntegrationsLayout/IntegrationWindowLayout.tsx @@ -30,24 +30,24 @@ const IntegrationWindowLayout = ({
    {children}
    {docsHref && ( - - - Docs - - - )} - - - Support - + + Docs + + )} + + + Support
    diff --git a/studio/components/layouts/ProjectLayout/BuildingState.tsx b/studio/components/layouts/ProjectLayout/BuildingState.tsx index 2000ecb22e..22f7d1d3a7 100644 --- a/studio/components/layouts/ProjectLayout/BuildingState.tsx +++ b/studio/components/layouts/ProjectLayout/BuildingState.tsx @@ -82,14 +82,13 @@ const BuildingState = () => { description={

    Browse the Supabase{' '} - - - documentation - + + documentation .

    @@ -113,11 +112,9 @@ const BuildingState = () => { If your dashboard hasn't connected within 2 minutes, you can open a support ticket.

    - - - - - + } /> diff --git a/studio/components/layouts/ProjectLayout/ConnectingState.tsx b/studio/components/layouts/ProjectLayout/ConnectingState.tsx index 36708f85ff..9743731dd0 100644 --- a/studio/components/layouts/ProjectLayout/ConnectingState.tsx +++ b/studio/components/layouts/ProjectLayout/ConnectingState.tsx @@ -77,22 +77,21 @@ const ConnectingState = ({ project }: ConnectingStateProps) => {
    - - - - - - - - - - + +
    diff --git a/studio/components/layouts/ProjectLayout/LayoutHeader/FeedbackDropdown/FeedbackWidget.tsx b/studio/components/layouts/ProjectLayout/LayoutHeader/FeedbackDropdown/FeedbackWidget.tsx index 62f27f08d3..bc48ae8fe9 100644 --- a/studio/components/layouts/ProjectLayout/LayoutHeader/FeedbackDropdown/FeedbackWidget.tsx +++ b/studio/components/layouts/ProjectLayout/LayoutHeader/FeedbackDropdown/FeedbackWidget.tsx @@ -223,11 +223,9 @@ const FeedbackWidget = ({

    Have a technical issue? Contact{' '} - - - Supabase support - - + + Supabase support + {' '} or{' '} diff --git a/studio/components/layouts/ProjectLayout/LayoutHeader/HelpPopover.tsx b/studio/components/layouts/ProjectLayout/LayoutHeader/HelpPopover.tsx index 557f9d00f8..dbc51fba5d 100644 --- a/studio/components/layouts/ProjectLayout/LayoutHeader/HelpPopover.tsx +++ b/studio/components/layouts/ProjectLayout/LayoutHeader/HelpPopover.tsx @@ -1,5 +1,5 @@ import * as Tooltip from '@radix-ui/react-tooltip' -import Image from 'next/image' +import Image from 'next/legacy/image' import Link from 'next/link' import { useRouter } from 'next/router' import SVG from 'react-inlinesvg' @@ -73,38 +73,34 @@ const HelpPopover = ({ alt = false }: HelpPopoverProps) => { services.

    - - - - - - - - - + + +

    Expected response time is based on your billing plan. Pro and Pay as You Go plans are prioritized.

    - - - +
    diff --git a/studio/components/layouts/ProjectLayout/LayoutHeader/LayoutHeader.tsx b/studio/components/layouts/ProjectLayout/LayoutHeader/LayoutHeader.tsx index 3ce97f1abb..ee4c4a3022 100644 --- a/studio/components/layouts/ProjectLayout/LayoutHeader/LayoutHeader.tsx +++ b/studio/components/layouts/ProjectLayout/LayoutHeader/LayoutHeader.tsx @@ -116,9 +116,7 @@ const LayoutHeader = ({ customHeaderComponents, breadcrumbs = [], headerBorder = : `/project/${projectRef}/settings/billing/usage` } > - - Exceeding usage limits - + Exceeding usage limits )} diff --git a/studio/components/layouts/ProjectLayout/LayoutHeader/NotificationsPopover/NotificationActions.tsx b/studio/components/layouts/ProjectLayout/LayoutHeader/NotificationsPopover/NotificationActions.tsx index 581129e15d..5a83ecc303 100644 --- a/studio/components/layouts/ProjectLayout/LayoutHeader/NotificationsPopover/NotificationActions.tsx +++ b/studio/components/layouts/ProjectLayout/LayoutHeader/NotificationsPopover/NotificationActions.tsx @@ -72,13 +72,11 @@ const NotificationActions = ({ ) })} {changelogLink && ( - - - + )} ) diff --git a/studio/components/layouts/ProjectLayout/LayoutHeader/NotificationsPopover/NotificationRows.utils.tsx b/studio/components/layouts/ProjectLayout/LayoutHeader/NotificationsPopover/NotificationRows.utils.tsx index 5b60819767..b4ecebc46f 100644 --- a/studio/components/layouts/ProjectLayout/LayoutHeader/NotificationsPopover/NotificationRows.utils.tsx +++ b/studio/components/layouts/ProjectLayout/LayoutHeader/NotificationsPopover/NotificationRows.utils.tsx @@ -108,14 +108,12 @@ export const formatNotificationText = (project: Project, notification: Notificat

    {upgrade.version_to}

    {upgrade.changelog_link && (
    - - - - + +
    )} diff --git a/studio/components/layouts/ProjectLayout/NavigationBar/NavigationBar.tsx b/studio/components/layouts/ProjectLayout/NavigationBar/NavigationBar.tsx index b341b17f98..cbf55dc059 100644 --- a/studio/components/layouts/ProjectLayout/NavigationBar/NavigationBar.tsx +++ b/studio/components/layouts/ProjectLayout/NavigationBar/NavigationBar.tsx @@ -77,14 +77,12 @@ const NavigationBar = () => { >
      {(!navLayoutV2 || !IS_PLATFORM) && ( - - - Supabase - + + Supabase )} { {IS_PLATFORM && ( <> - - + +

      Account preferences

      -
      - + +
      {showFeaturePreviews && ( ( - - {children} - - )} + wrap={(children) => {children}} > {

      Unpaused projects count towards compute usage. For every hour your instance is active, we'll bill you based on the instance size of your project. See{' '} - - - Compute Instance Usage Billing - + + Compute Instance Usage Billing {' '} for more details.

      @@ -145,23 +148,21 @@ const ProjectPausedState = ({ product }: ProjectPausedStateProps) => { )} {isFreePlan ? ( - - - - - + ) : ( - - - - - + )} diff --git a/studio/components/layouts/ProjectLayout/RestoringState.tsx b/studio/components/layouts/ProjectLayout/RestoringState.tsx index 3eb4e3c71d..982a871723 100644 --- a/studio/components/layouts/ProjectLayout/RestoringState.tsx +++ b/studio/components/layouts/ProjectLayout/RestoringState.tsx @@ -91,13 +91,13 @@ const RestoringState = () => { {isFailed && (
      - - - - - +
      )} diff --git a/studio/components/layouts/ProjectLayout/UpgradingState/UpgradingState.tsx b/studio/components/layouts/ProjectLayout/UpgradingState/UpgradingState.tsx index 86ec8d78e2..3c96da075a 100644 --- a/studio/components/layouts/ProjectLayout/UpgradingState/UpgradingState.tsx +++ b/studio/components/layouts/ProjectLayout/UpgradingState/UpgradingState.tsx @@ -104,13 +104,15 @@ const UpgradingState = () => {

      - - - - - + diff --git a/studio/components/layouts/SQLEditorLayout/QueryItem.tsx b/studio/components/layouts/SQLEditorLayout/QueryItem.tsx index a78e83eb21..abdaf612dc 100644 --- a/studio/components/layouts/SQLEditorLayout/QueryItem.tsx +++ b/studio/components/layouts/SQLEditorLayout/QueryItem.tsx @@ -67,15 +67,13 @@ const QueryItem = ({ tabInfo }: QueryItemProps) => { )} ref={isActive ? (activeItemRef as React.RefObject) : null} > - - -

      - {name} -

      -
      + +

      + {name} +

      {}
      diff --git a/studio/components/layouts/SettingsLayout/SettingsMenuItem.tsx b/studio/components/layouts/SettingsLayout/SettingsMenuItem.tsx index 819b7e28e3..c79f5b56f4 100644 --- a/studio/components/layouts/SettingsLayout/SettingsMenuItem.tsx +++ b/studio/components/layouts/SettingsLayout/SettingsMenuItem.tsx @@ -10,15 +10,14 @@ interface SettingsMenuItemProps { const SettingsMenuItem = ({ href, label, isActive }: SettingsMenuItemProps) => { return (
      - - - {label} - + + {label}
      ) diff --git a/studio/components/layouts/SignInLayout/ForgotPasswordLayout.tsx b/studio/components/layouts/SignInLayout/ForgotPasswordLayout.tsx index 07b13f67f2..e943936d20 100644 --- a/studio/components/layouts/SignInLayout/ForgotPasswordLayout.tsx +++ b/studio/components/layouts/SignInLayout/ForgotPasswordLayout.tsx @@ -1,7 +1,7 @@ import { useTheme } from 'next-themes' import { BASE_PATH } from 'lib/constants' import { observer } from 'mobx-react-lite' -import Image from 'next/image' +import Image from 'next/legacy/image' import Link from 'next/link' import { PropsWithChildren } from 'react' @@ -28,18 +28,16 @@ const ForgotPasswordLayout = ({
      - - - +
      diff --git a/studio/components/layouts/SignInLayout/SignInLayout.tsx b/studio/components/layouts/SignInLayout/SignInLayout.tsx index 667de365b2..330f2f42dc 100644 --- a/studio/components/layouts/SignInLayout/SignInLayout.tsx +++ b/studio/components/layouts/SignInLayout/SignInLayout.tsx @@ -5,7 +5,7 @@ import { usePushNext } from 'hooks/misc/useAutoAuthRedirect' import { BASE_PATH } from 'lib/constants' import { auth, buildPathWithParams, getAccessToken } from 'lib/gotrue' import { observer } from 'mobx-react-lite' -import Image from 'next/image' +import Image from 'next/legacy/image' import Link from 'next/link' import { useRouter } from 'next/router' import { PropsWithChildren, useEffect, useState } from 'react' @@ -100,30 +100,26 @@ const SignInLayout = ({
      - - Supabase Logo - + Supabase Logo
      - - - - - +
      @@ -143,12 +139,18 @@ const SignInLayout = ({

      By continuing, you agree to Supabase's{' '} - - Terms of Service + + Terms of Service {' '} and{' '} - - Privacy Policy + + Privacy Policy , and to receive periodic emails with updates.

      diff --git a/studio/components/layouts/StorageLayout/BucketRow.tsx b/studio/components/layouts/StorageLayout/BucketRow.tsx index 2fc2f3c8df..9973f728da 100644 --- a/studio/components/layouts/StorageLayout/BucketRow.tsx +++ b/studio/components/layouts/StorageLayout/BucketRow.tsx @@ -45,18 +45,19 @@ const BucketRow = ({ )} > {/* Even though we trim whitespaces from bucket names, there may be some existing buckets with trailing whitespaces. */} - - -
      -

      - {bucket.name} -

      - {bucket.public && Public} -
      -
      + +
      +

      + {bucket.name} +

      + {bucket.public && Public} +
      {/* [JOSHEN TODO] need to change this */} {false ? ( diff --git a/studio/components/layouts/StorageLayout/StorageBucketsError.tsx b/studio/components/layouts/StorageLayout/StorageBucketsError.tsx index 973abb0727..c5bddff3a9 100644 --- a/studio/components/layouts/StorageLayout/StorageBucketsError.tsx +++ b/studio/components/layouts/StorageLayout/StorageBucketsError.tsx @@ -11,23 +11,20 @@ const StorageBucketsError = ({ error }: StorageBucketsErrorProps) => { const { ref } = useParams() return ( -
      +
      - - - - , + , ]} >

      diff --git a/studio/components/layouts/StorageLayout/StorageMenu.tsx b/studio/components/layouts/StorageLayout/StorageMenu.tsx index b49ea1311c..b5c9b7d1aa 100644 --- a/studio/components/layouts/StorageLayout/StorageMenu.tsx +++ b/studio/components/layouts/StorageLayout/StorageMenu.tsx @@ -124,7 +124,7 @@ const StorageMenu = () => {

      - +

      Policies

      diff --git a/studio/components/layouts/TableEditorLayout/EntityListItem.tsx b/studio/components/layouts/TableEditorLayout/EntityListItem.tsx index 76f36ce19f..0f0a71ad21 100644 --- a/studio/components/layouts/TableEditorLayout/EntityListItem.tsx +++ b/studio/components/layouts/TableEditorLayout/EntityListItem.tsx @@ -117,87 +117,87 @@ const EntityListItem = ({ id, projectRef, item: entity, isLocked }: EntityListIt isActive && 'text-foreground bg-scale-300' )} > - - - - - {entity.type === ENTITY_TYPE.TABLE ? ( - - code.replace(/svg/, 'svg class="m-auto text-color-inherit"') - } - /> - ) : entity.type === ENTITY_TYPE.VIEW ? ( - - code.replace(/svg/, 'svg class="m-auto text-color-inherit"') - } - /> - ) : ( -
      - {Object.entries(ENTITY_TYPE) - .find(([, value]) => value === entity.type)?.[0]?.[0] - ?.toUpperCase()} -
      - )} -
      - - - -
      - - {formatTooltipText(entity.type)} - -
      -
      -
      -
      -

      - {/* only show tooltips if required, to reduce noise */} - {entity.name.length > 20 ? ( - - - {entity.name} - - - - -

      - {entity.name} -
      - - - + + + + {entity.type === ENTITY_TYPE.TABLE ? ( + + code.replace(/svg/, 'svg class="m-auto text-color-inherit"') + } + /> + ) : entity.type === ENTITY_TYPE.VIEW ? ( + + code.replace(/svg/, 'svg class="m-auto text-color-inherit"') + } + /> ) : ( - entity.name +
      + {Object.entries(ENTITY_TYPE) + .find(([, value]) => value === entity.type)?.[0]?.[0] + ?.toUpperCase()} +
      )} -

      -
      + + + + +
      + + {formatTooltipText(entity.type)} + +
      +
      +
      + +

      + {/* only show tooltips if required, to reduce noise */} + {entity.name.length > 20 ? ( + + + {entity.name} + + + + +

      + {entity.name} +
      + + + + ) : ( + entity.name + )} +

      {entity.type === ENTITY_TYPE.TABLE && isActive && !isLocked && ( @@ -230,17 +230,15 @@ const EntityListItem = ({ id, projectRef, item: entity, isLocked }: EntityListIt

      Duplicate Table

      - - - - -

      View Policies

      -
      -
      - + + + +

      View Policies

      + +
      {
      - - Supabase - + Supabase

      diff --git a/studio/components/to-be-cleaned/ModalsDeprecated/ConfirmModal.js b/studio/components/to-be-cleaned/ModalsDeprecated/ConfirmModal.js deleted file mode 100644 index 20fffb585e..0000000000 --- a/studio/components/to-be-cleaned/ModalsDeprecated/ConfirmModal.js +++ /dev/null @@ -1,91 +0,0 @@ -import { useState } from 'react' -import { render, unmountComponentAtNode } from 'react-dom' -import { Button, Modal } from 'ui' - -function ConfirmModal({ - title, - message: description, - onConfirm, - onAsyncConfirm, - variant = 'danger', - confirmText = 'Confirm', -}) { - const [loading, setLoading] = useState(false) - - function onCancelClick() { - if (!loading) onClose() - } - - async function onConfirmClick() { - if (onAsyncConfirm) { - setLoading(true) - await onAsyncConfirm() - - onClose() - } else if (onConfirm) { - onConfirm() - onClose() - } - } - - function onClose() { - removeElement() - } - - return ( - - - -

      - } - > - {description && ( - -

      {description}

      -
      - )} - - ) -} - -function removeElement() { - const target = document.getElementById('supabase-ui-confirm-alert') - if (target) { - unmountComponentAtNode(target) - target.parentNode.removeChild(target) - } -} - -function createElement(properties) { - let divTarget = document.getElementById('supabase-ui-confirm-alert') - if (divTarget) { - render(, divTarget) - } else { - divTarget = document.createElement('div') - divTarget.id = 'supabase-ui-confirm-alert' - document.body.appendChild(divTarget) - render(, divTarget) - } -} - -export function confirmAlert(properties) { - createElement(properties) -} diff --git a/studio/components/ui/AlertError.tsx b/studio/components/ui/AlertError.tsx index aed01b2fc5..5cd6690316 100644 --- a/studio/components/ui/AlertError.tsx +++ b/studio/components/ui/AlertError.tsx @@ -39,11 +39,9 @@ const AlertError = ({ ref, subject, error, className }: AlertErrorProps) => {

      - - - +
      diff --git a/studio/components/ui/CSVButton.tsx b/studio/components/ui/CSVButton.tsx index 9ddcbf49ae..3289641afe 100644 --- a/studio/components/ui/CSVButton.tsx +++ b/studio/components/ui/CSVButton.tsx @@ -1,10 +1,10 @@ import { Button, IconDownloadCloud } from 'ui' import { ButtonProps } from 'ui/src/components/Button/Button' import { flattenDeep } from 'lodash' -import React, { useMemo, useRef } from 'react' +import React, { PropsWithChildren, useMemo, useRef } from 'react' import { CSVLink } from 'react-csv' -interface Props { +interface CSVButtonProps { buttonType?: ButtonProps['type'] onClick?: ButtonProps['onClick'] disabled?: ButtonProps['disabled'] @@ -13,7 +13,7 @@ interface Props { title?: string } -const CSVButton: React.FC = ({ +const CSVButton = ({ onClick, buttonType = 'default', icon, @@ -21,7 +21,7 @@ const CSVButton: React.FC = ({ disabled, data, title, -}) => { +}: PropsWithChildren) => { const csvRef = useRef(null) const handleDownload = () => { ;(csvRef.current as any)?.link.click() diff --git a/studio/components/ui/CardButton.tsx b/studio/components/ui/CardButton.tsx index 2fc3a80912..e3c5abc14c 100644 --- a/studio/components/ui/CardButton.tsx +++ b/studio/components/ui/CardButton.tsx @@ -31,9 +31,7 @@ const CardButton = ({ loading = false, }: PropsWithChildren) => { const LinkContainer = ({ children }: { children: React.ReactNode }) => ( - - {children} - + {children} ) const UrlContainer = ({ children }: { children: React.ReactNode }) => {children} const NonLinkContainer = ({ children }: { children: React.ReactNode }) =>
      {children}
      diff --git a/studio/components/ui/Charts/AreaChart.stories.tsx b/studio/components/ui/Charts/AreaChart.stories.tsx index 77a3b92db6..ebcad3f384 100644 --- a/studio/components/ui/Charts/AreaChart.stories.tsx +++ b/studio/components/ui/Charts/AreaChart.stories.tsx @@ -50,6 +50,6 @@ export const AreaChart = () => (
      ) -const ExampleName: React.FC = ({ children }) => ( +const ExampleName: React.FC = ({ children }) => (

      {children}

      ) diff --git a/studio/components/ui/Charts/BarChart.stories.tsx b/studio/components/ui/Charts/BarChart.stories.tsx index 72894c415c..cb8489dafc 100644 --- a/studio/components/ui/Charts/BarChart.stories.tsx +++ b/studio/components/ui/Charts/BarChart.stories.tsx @@ -51,6 +51,6 @@ export const BarChart = () => (
      ) -const ExampleName: React.FC = ({ children }) => ( +const ExampleName: React.FC = ({ children }) => (

      {children}

      ) diff --git a/studio/components/ui/Charts/Charts.utils.tsx b/studio/components/ui/Charts/Charts.utils.tsx index 913f9965b8..a824e1a881 100644 --- a/studio/components/ui/Charts/Charts.utils.tsx +++ b/studio/components/ui/Charts/Charts.utils.tsx @@ -82,7 +82,7 @@ export const useChartSize = ( } ) => { const minHeight = sizeMap[size] - const Container: React.FC = useMemo( + const Container: React.FC = useMemo( () => ({ children }) => ( diff --git a/studio/components/ui/Charts/Sparkline.stories.tsx b/studio/components/ui/Charts/Sparkline.stories.tsx index 1808d40a2d..a305d48416 100644 --- a/studio/components/ui/Charts/Sparkline.stories.tsx +++ b/studio/components/ui/Charts/Sparkline.stories.tsx @@ -42,7 +42,7 @@ export const Sparkline = () => (
      ) -const ExampleName: React.FC = ({ children }) => ( +const ExampleName: React.FC = ({ children }) => (

      (

      ) -const ExampleName: React.FC = ({ children }) => ( +const ExampleName: React.FC = ({ children }) => (

      - - - - - + ) } diff --git a/studio/components/ui/Error.tsx b/studio/components/ui/Error.tsx index 3e0acad818..52045c1595 100644 --- a/studio/components/ui/Error.tsx +++ b/studio/components/ui/Error.tsx @@ -17,16 +17,12 @@ export default function EmptyPageState({ error }: any) {

      - - - - - - - - - - + +

      Error: [{error?.code}] {error?.message} diff --git a/studio/components/ui/Forms/FormHeader.tsx b/studio/components/ui/Forms/FormHeader.tsx index 88261b2619..1e85d6b386 100644 --- a/studio/components/ui/Forms/FormHeader.tsx +++ b/studio/components/ui/Forms/FormHeader.tsx @@ -26,13 +26,11 @@ const FormHeader = ({ )} {docsUrl !== undefined && ( - - - + )} ) diff --git a/studio/components/ui/InformationBox.tsx b/studio/components/ui/InformationBox.tsx index 7422ca0383..abcaf4ff5d 100644 --- a/studio/components/ui/InformationBox.tsx +++ b/studio/components/ui/InformationBox.tsx @@ -65,13 +65,11 @@ const InformationBox = ({

      {description}
      {url && ( - - - - - + )} {button &&
      {button}
      } diff --git a/studio/components/ui/Logs/LogsExplorerHeader.tsx b/studio/components/ui/Logs/LogsExplorerHeader.tsx index d3eac01b17..59697b68dc 100644 --- a/studio/components/ui/Logs/LogsExplorerHeader.tsx +++ b/studio/components/ui/Logs/LogsExplorerHeader.tsx @@ -39,13 +39,9 @@ const LogsExplorerHeader = ({ subtitle }: LogsExplorerHeaderProps) => { {subtitle && {subtitle}}
      - - - - - + { The following table shows all the available paths that can be queried from each respective source. Do note that to access nested keys, you would need to perform the necessary{' '} - - - unnesting joins - - + + unnesting joins +

      diff --git a/studio/components/ui/OveragesBanner/OveragesBanner.tsx b/studio/components/ui/OveragesBanner/OveragesBanner.tsx index d99fba0736..4e8ddd990d 100644 --- a/studio/components/ui/OveragesBanner/OveragesBanner.tsx +++ b/studio/components/ui/OveragesBanner/OveragesBanner.tsx @@ -84,11 +84,11 @@ const OveragesBanner = ({ tier, minimal }: OveragesBannerProps) => { actions={ minimal ? (
      - - - - - +
      ) : ( <> diff --git a/studio/components/ui/ProductMenu/ProductMenu.tsx b/studio/components/ui/ProductMenu/ProductMenu.tsx index 3d12c17ac0..ded04b416f 100644 --- a/studio/components/ui/ProductMenu/ProductMenu.tsx +++ b/studio/components/ui/ProductMenu/ProductMenu.tsx @@ -1,6 +1,6 @@ import { Badge, Menu } from 'ui' -import { ProductMenuGroup, ProductMenuGroupItem } from './ProductMenu.types' +import { ProductMenuGroup } from './ProductMenu.types' import ProductMenuItem from './ProductMenuItem' interface ProductMenuProps { @@ -12,7 +12,7 @@ const ProductMenu = ({ page, menu }: ProductMenuProps) => { return (
      - {menu.map((group: ProductMenuGroup, idx: number) => ( + {menu.map((group, idx) => (
      @@ -28,7 +28,7 @@ const ProductMenu = ({ page, menu }: ProductMenuProps) => { } />
      - {group.items.map((item: ProductMenuGroupItem) => ( + {group.items.map((item) => ( - - - - + ) } return ( - - - {menuItem} - + + {menuItem} ) } diff --git a/studio/components/ui/ProjectUpgradeFailedBanner.tsx b/studio/components/ui/ProjectUpgradeFailedBanner.tsx index b528e3698d..9f4810006b 100644 --- a/studio/components/ui/ProjectUpgradeFailedBanner.tsx +++ b/studio/components/ui/ProjectUpgradeFailedBanner.tsx @@ -45,13 +45,15 @@ const ProjectUpgradeFailedBanner = () => { title={`Postgres version upgrade to ${target_version} was not successful (Initiated at ${initiatedAtUTC} UTC)`} actions={
      - - - - - + - - + )} {correctionUrl !== undefined && ( - - - - - + )}
      diff --git a/studio/components/ui/UpgradeToPro.tsx b/studio/components/ui/UpgradeToPro.tsx index ccb8225ed5..fad765cbfb 100644 --- a/studio/components/ui/UpgradeToPro.tsx +++ b/studio/components/ui/UpgradeToPro.tsx @@ -56,7 +56,7 @@ const UpgradeToPro = ({ plan === 'free' ? 'subscriptionPlan' : addon || 'subscriptionPlan' }`} > - {plan === 'free' ? 'Upgrade to Pro' : 'Enable Addon'} + {plan === 'free' ? 'Upgrade to Pro' : 'Enable Addon'} diff --git a/studio/data/database/migrations-query.ts b/studio/data/database/migrations-query.ts index 6c9107372a..89f089c751 100644 --- a/studio/data/database/migrations-query.ts +++ b/studio/data/database/migrations-query.ts @@ -39,7 +39,6 @@ export const useMigrationsQuery = { if ( - error.code === 400 && error.message.includes('relation "supabase_migrations.schema_migrations" does not exist') ) { return { result: [] } diff --git a/studio/data/sql/execute-sql-query.ts b/studio/data/sql/execute-sql-query.ts index 9736d249c5..5ca2593073 100644 --- a/studio/data/sql/execute-sql-query.ts +++ b/studio/data/sql/execute-sql-query.ts @@ -6,7 +6,7 @@ import { UseQueryOptions, } from '@tanstack/react-query' import md5 from 'blueimp-md5' -import { post as newPost } from 'data/fetchers' +import { post } from 'data/fetchers' import { useCallback } from 'react' import { sqlKeys } from './keys' @@ -38,7 +38,7 @@ export async function executeSql( let headers = new Headers() if (connectionString) headers.set('x-connection-encrypted', connectionString) - const { data, error } = await newPost('/platform/pg-meta/{ref}/query', { + const { data, error } = await post('/platform/pg-meta/{ref}/query', { signal, params: { header: { 'x-connection-encrypted': connectionString ?? '' }, diff --git a/studio/data/table-rows/table-row-delete-mutation.ts b/studio/data/table-rows/table-row-delete-mutation.ts index eaa22e041d..1e6498f359 100644 --- a/studio/data/table-rows/table-row-delete-mutation.ts +++ b/studio/data/table-rows/table-row-delete-mutation.ts @@ -6,11 +6,12 @@ import { executeSql } from 'data/sql/execute-sql-query' import { sqlKeys } from 'data/sql/keys' import { ResponseError } from 'types' import { getPrimaryKeys } from './utils' +import { Table } from 'data/tables/table-query' export type TableRowDeleteVariables = { projectRef: string connectionString?: string - table: SupaTable + table: Table rows: SupaRow[] } diff --git a/studio/data/table-rows/utils.ts b/studio/data/table-rows/utils.ts index 6ae498e340..48aa9f38f1 100644 --- a/studio/data/table-rows/utils.ts +++ b/studio/data/table-rows/utils.ts @@ -1,6 +1,8 @@ import { Filter, ServiceError, SupaTable } from 'components/grid' import { ERROR_PRIMARY_KEY_NOTFOUND } from 'components/grid/constants' import { isNumericalColumn } from 'components/grid/utils' +import { Table } from 'data/tables/table-query' +import { TableLike } from 'hooks/misc/useTable' /** * temporary fix until we implement a better filter UI @@ -17,11 +19,11 @@ export function formatFilterValue(table: SupaTable, filter: Filter) { return filter.value } -export function getPrimaryKeys({ table }: { table: SupaTable }): { +export function getPrimaryKeys({ table }: { table: Table }): { primaryKeys?: string[] error?: ServiceError } { - const pkColumns = table.columns.filter((x) => x.isPrimaryKey) + const pkColumns = table.primary_keys if (!pkColumns || pkColumns.length == 0) { return { error: { message: ERROR_PRIMARY_KEY_NOTFOUND } } } diff --git a/studio/hooks/misc/withAuth.tsx b/studio/hooks/misc/withAuth.tsx index 8fafe0a13a..baffaec303 100644 --- a/studio/hooks/misc/withAuth.tsx +++ b/studio/hooks/misc/withAuth.tsx @@ -1,5 +1,5 @@ -import Head from 'next/head' import { useRouter } from 'next/router' +import Script from 'next/script' import { ComponentType, useEffect } from 'react' import { useParams } from 'common/hooks' @@ -8,8 +8,8 @@ import { useAuthenticatorAssuranceLevelQuery } from 'data/profile/mfa-authentica import { useSelectedProject, useStore } from 'hooks' import { useAuth } from 'lib/auth' import { IS_PLATFORM } from 'lib/constants' -import { getReturnToPath, STORAGE_KEY } from 'lib/gotrue' -import { isNextPageWithLayout, NextPageWithLayout } from 'types' +import { STORAGE_KEY, getReturnToPath } from 'lib/gotrue' +import { NextPageWithLayout, isNextPageWithLayout } from 'types' import Error500 from '../../pages/500' const PLATFORM_ONLY_PAGES = [ @@ -96,22 +96,27 @@ export function withAuth( return } + const InnerComponent = WrappedComponent as any + return ( <> - - {/* This script will quickly (before the main JS loads) redirect the user + {/* This script will quickly (before the main JS loads) redirect the user to the login page if they are guaranteed (no token at all) to not be logged in. */} - {IS_PLATFORM && ( -