From 972773ca877a924c147f077502e7a5aa04b3b292 Mon Sep 17 00:00:00 2001 From: Jonathan Summers-Muir Date: Wed, 5 Jun 2024 18:06:55 +0800 Subject: [PATCH] [Dashboard] Chore: update `Modal` component to use new components (#26844) * init * add more examples * update modal * update modals * more modals updated * update modal * Update NewAccessTokenButton.tsx * Update NewAccessTokenButton.tsx * fix: issue with scale on dialog opening. chore: added bg-dialog color * fix modals * add deprecation notices * revert bg * revert * Update Modal.tsx * Update PITRSelection.tsx * update dialog docs * fix: issue with payment method modal * update terminal instructions * update padding defaults --- apps/design-system/__registry__/index.tsx | 44 ++ apps/design-system/config/docs.ts | 5 + .../content/docs/fragments/modal.mdx | 24 + .../default/example/dialog-close-button.tsx | 45 +- .../registry/default/example/dialog-demo.tsx | 17 +- .../default/example/modal-aligned-footer.tsx | 43 ++ .../default/example/modal-custom-footer.tsx | 53 +++ .../registry/default/example/modal-demo.tsx | 42 ++ .../default/example/modal-hide-footer.tsx | 43 ++ .../default/example/modal-vertical-layout.tsx | 43 ++ apps/design-system/registry/examples.ts | 20 + .../Account/NewAccessTokenButton.tsx | 12 +- .../FeaturePreview/FeaturePreviewModal.tsx | 2 +- .../Auth/Policies/PolicyEditor/index.tsx | 76 ++-- .../Auth/RedirectUrls/RedirectUrls.tsx | 87 ++-- .../interfaces/Auth/Users/CreateUserModal.tsx | 92 ++-- .../interfaces/Auth/Users/InviteUserModal.tsx | 4 +- .../Payment/AddNewPaymentMethodModal.tsx | 16 +- .../Billing/Payment/AddPaymentMethodForm.tsx | 40 +- .../interfaces/Billing/SpendCapModal.tsx | 310 +++++++------ .../BranchManagement/CreateBranchModal.tsx | 32 +- .../Database/Backups/PITR/PITRSelection.tsx | 68 ++- .../Extensions/EnableExtensionModal.tsx | 21 +- .../Database/ProtectedSchemaWarning.tsx | 2 +- .../Database/Roles/DeleteRoleModal.tsx | 14 +- .../Database/Wrappers/DeleteWrapperModal.tsx | 14 +- .../interfaces/Functions/CommandRender.tsx | 25 +- .../EdgeFunctionDetails.tsx | 12 +- .../EdgeFunctionSecrets/AddNewSecretModal.tsx | 2 +- .../Functions/FunctionsEmptyState.tsx | 8 +- .../Functions/TerminalInstructions.tsx | 147 +++--- .../interfaces/Home/Connect/Connect.tsx | 4 +- .../ChangePaymentMethodModal.tsx | 14 +- .../DeletePaymentMethodModal.tsx | 12 +- .../Subscription/DowngradeModal.tsx | 144 +++--- .../Subscription/ExitSurveyModal.tsx | 2 +- .../Subscription/MembersExceedLimitModal.tsx | 56 ++- .../Subscription/PlanUpdateSidePanel.tsx | 2 +- .../Subscription/UpgradeModal.tsx | 70 ++- .../DeleteOrganizationButton.tsx | 6 +- .../Organization/OAuthApps/DeleteAppModal.tsx | 40 +- .../OAuthApps/PublishAppSidePanel/index.tsx | 28 +- .../Organization/OAuthApps/RevokeAppModal.tsx | 40 +- .../TeamSettings/InviteMemberButton.tsx | 79 ++-- .../Organization/TeamSettings/MembersView.tsx | 69 ++- .../RolesHelperModal/RolesHelperModal.tsx | 104 ++--- .../Realtime/Inspector/SendMessageModal.tsx | 40 +- .../Reports/Reports.CreateReportModal.tsx | 24 +- .../Reports/Reports.UpdateModal.tsx | 20 +- .../SQLEditor/DownloadSnippetModal.tsx | 62 +-- .../interfaces/SQLEditor/RenameQueryModal.tsx | 24 +- .../interfaces/Settings/API/JWTSettings.tsx | 68 ++- .../Addons/ComputeInstanceSidePanel.tsx | 16 +- .../ConfirmDisableReadOnlyModal.tsx | 2 +- .../DatabaseSettings/ResetDbPassword.tsx | 70 ++- .../Database/DiskSizeConfiguration.tsx | 76 ++-- .../AddRestrictionModal.tsx | 175 ++++--- .../NetworkRestrictions/AllowAllModal.tsx | 15 +- .../NetworkRestrictions/DisallowAllModal.tsx | 29 +- .../RemoveRestrictionModal.tsx | 34 +- .../ProjectUpgradeAlert.tsx | 213 +++++---- .../TransferProjectButton.tsx | 426 +++++++++--------- .../Logs/Logs.UpdateSavedQueryModal.tsx | 20 +- .../Settings/Logs/UpgradePrompt.tsx | 80 ++-- .../Vault/Keys/EncryptionKeysManagement.tsx | 86 ++-- .../Vault/Secrets/AddNewSecretModal.tsx | 114 +++-- .../Vault/Secrets/DeleteSecretModal.tsx | 29 +- .../Vault/Secrets/EditSecretModal.tsx | 80 ++-- .../interfaces/Storage/CreateBucketModal.tsx | 41 +- .../interfaces/Storage/EditBucketModal.tsx | 27 +- .../BranchingPlanNotice.tsx | 2 +- .../EnableBranchingModal.tsx | 59 ++- .../ProjectLayout/ProjectPausedState.tsx | 64 ++- .../StorageExplorer/ConfirmDeleteModal.tsx | 8 +- .../StorageExplorer/CustomExpiryModal.tsx | 82 ++-- .../StorageExplorer/MoveItemsModal.tsx | 2 +- .../StoragePolicies/StoragePoliciesEditor.tsx | 6 +- .../StoragePolicies/StoragePoliciesReview.tsx | 51 +-- .../StorageSettings/CreateCredentialModal.tsx | 3 +- .../StorageSettings/StorageSettings.tsx | 2 +- apps/studio/components/ui/AISettingsModal.tsx | 6 +- .../pages/project/[ref]/functions/index.tsx | 44 +- .../project/[ref]/logs/explorer/index.tsx | 63 ++- apps/studio/styles/stripe.scss | 1 - packages/config/ui.config.js | 4 +- .../ui-patterns/Dialogs/ConfirmDialog.tsx | 8 +- packages/ui-patterns/Icons/StatusIcons.tsx | 2 +- packages/ui/build/css/themes/dark.css | 1 + packages/ui/build/css/themes/deep-dark.css | 1 + packages/ui/build/css/themes/light.css | 1 + packages/ui/build/css/tw-extend/color.js | 4 + packages/ui/src/components/Modal/Modal.tsx | 295 ++++++------ .../ui/src/components/shadcn/ui/dialog.tsx | 24 +- packages/ui/src/lib/tailwind-demo-classes.ts | 3 +- supabase/functions/hello-world/index.ts | 29 ++ 95 files changed, 2375 insertions(+), 2194 deletions(-) create mode 100644 apps/design-system/content/docs/fragments/modal.mdx create mode 100644 apps/design-system/registry/default/example/modal-aligned-footer.tsx create mode 100644 apps/design-system/registry/default/example/modal-custom-footer.tsx create mode 100644 apps/design-system/registry/default/example/modal-demo.tsx create mode 100644 apps/design-system/registry/default/example/modal-hide-footer.tsx create mode 100644 apps/design-system/registry/default/example/modal-vertical-layout.tsx create mode 100644 supabase/functions/hello-world/index.ts diff --git a/apps/design-system/__registry__/index.tsx b/apps/design-system/__registry__/index.tsx index d1fa65d3377..86da880f0d8 100644 --- a/apps/design-system/__registry__/index.tsx +++ b/apps/design-system/__registry__/index.tsx @@ -1754,6 +1754,50 @@ export const Index: Record = { subcategory: "undefined", chunks: [] }, + "modal-demo": { + name: "modal-demo", + type: "components:example", + registryDependencies: undefined, + component: React.lazy(() => import("@/registry/default/example/modal-demo")), + source: "", + files: ["registry/default/example/modal-demo.tsx"], + category: "undefined", + subcategory: "undefined", + chunks: [] + }, + "modal-aligned-footer": { + name: "modal-aligned-footer", + type: "components:example", + registryDependencies: undefined, + component: React.lazy(() => import("@/registry/default/example/modal-aligned-footer")), + source: "", + files: ["registry/default/example/modal-aligned-footer.tsx"], + category: "undefined", + subcategory: "undefined", + chunks: [] + }, + "modal-custom-footer": { + name: "modal-custom-footer", + type: "components:example", + registryDependencies: undefined, + component: React.lazy(() => import("@/registry/default/example/modal-custom-footer")), + source: "", + files: ["registry/default/example/modal-custom-footer.tsx"], + category: "undefined", + subcategory: "undefined", + chunks: [] + }, + "modal-hide-footer": { + name: "modal-hide-footer", + type: "components:example", + registryDependencies: undefined, + component: React.lazy(() => import("@/registry/default/example/modal-hide-footer")), + source: "", + files: ["registry/default/example/modal-hide-footer.tsx"], + category: "undefined", + subcategory: "undefined", + chunks: [] + }, "color-usage-surface-www-and-docs": { name: "color-usage-surface-www-and-docs", type: "docs:example", diff --git a/apps/design-system/config/docs.ts b/apps/design-system/config/docs.ts index 36ce6c7f38b..4e1a7be559d 100644 --- a/apps/design-system/config/docs.ts +++ b/apps/design-system/config/docs.ts @@ -82,6 +82,11 @@ export const docsConfig: DocsConfig = { href: '/docs/fragments/admonition', items: [], }, + { + title: 'Modal', + href: '/docs/fragments/modal', + items: [], + }, { title: 'Text Confirm Dialog', href: '/docs/fragments/text-confirm-dialog', diff --git a/apps/design-system/content/docs/fragments/modal.mdx b/apps/design-system/content/docs/fragments/modal.mdx new file mode 100644 index 00000000000..2bbd59837cf --- /dev/null +++ b/apps/design-system/content/docs/fragments/modal.mdx @@ -0,0 +1,24 @@ +--- +title: Modal +description: A window overlaid on either the primary window or another dialog window, rendering the content underneath inert. +fragment: true +links: + doc: https://www.radix-ui.com/docs/primitives/components/dialog + api: https://www.radix-ui.com/docs/primitives/components/dialog#api-reference +--- + + + +## Examples + +### Aligned footer + + + +### Hide footer + + + +### Custom footer + + diff --git a/apps/design-system/registry/default/example/dialog-close-button.tsx b/apps/design-system/registry/default/example/dialog-close-button.tsx index 89614491661..4c45847ef7b 100644 --- a/apps/design-system/registry/default/example/dialog-close-button.tsx +++ b/apps/design-system/registry/default/example/dialog-close-button.tsx @@ -1,6 +1,6 @@ import { Copy } from 'lucide-react' -import { Button } from 'ui' +import { Button, DialogSection, DialogSectionSeparator } from 'ui' import { Dialog, DialogClose, @@ -18,33 +18,36 @@ export default function DialogCloseButton() { return ( - + - + Share link Anyone who has this link will be able to view this. -
-
- - Link - - + + +
+
+ + Link + + +
+
- -
- + + - diff --git a/apps/design-system/registry/default/example/dialog-demo.tsx b/apps/design-system/registry/default/example/dialog-demo.tsx index d1c14753a76..68e81be28d5 100644 --- a/apps/design-system/registry/default/example/dialog-demo.tsx +++ b/apps/design-system/registry/default/example/dialog-demo.tsx @@ -1,4 +1,4 @@ -import { Button } from 'ui' +import { Button, DialogSection, DialogSectionSeparator } from 'ui' import { Dialog, DialogContent, @@ -15,30 +15,31 @@ export default function DialogDemo() { return ( - + - + Edit profile Make changes to your profile here. Click save when you're done. -
-
+ + +
Name
-
+
Username
-
- +
+ diff --git a/apps/design-system/registry/default/example/modal-aligned-footer.tsx b/apps/design-system/registry/default/example/modal-aligned-footer.tsx new file mode 100644 index 00000000000..cd8c6b239ca --- /dev/null +++ b/apps/design-system/registry/default/example/modal-aligned-footer.tsx @@ -0,0 +1,43 @@ +import { Link2 } from 'lucide-react' +import { useState } from 'react' +import { Button, Modal } from 'ui' + +export default function ModalVerticalAlignedFooter() { + const [visible, setVisible] = useState(false) + + return ( + <> + + setVisible(!visible)} + onConfirm={() => setVisible(!visible)} + title="This is the title of the modal" + description="And i am the description" + alignFooter="right" + size="medium" + hideClose={false} + header={ +
+
+ +
+
+

This is the title

+ This is the title +
+
+ } + > + +

+ Modal content is inserted here, if you need to insert anything into the Modal you can do + so via `children`. +

+
+
+ + ) +} diff --git a/apps/design-system/registry/default/example/modal-custom-footer.tsx b/apps/design-system/registry/default/example/modal-custom-footer.tsx new file mode 100644 index 00000000000..206fb72e092 --- /dev/null +++ b/apps/design-system/registry/default/example/modal-custom-footer.tsx @@ -0,0 +1,53 @@ +import { Link2 } from 'lucide-react' +import { useState } from 'react' +import { Badge, Button, Modal } from 'ui' + +export default function ModalVerticalCustomFooter() { + const [visible, setVisible] = useState(false) + + return ( + <> + + setVisible(!visible)} + onConfirm={() => setVisible(!visible)} + title="This is the title of the modal" + description="And i am the description" + size="medium" + hideClose={false} + header={ +
+
+ +
+
+

This is the title

+ This is the title +
+
+ } + customFooter={ +
+
+ + Proceed with caution + +
+ + +
+ } + > + +

+ Modal content is inserted here, if you need to insert anything into the Modal you can do + so via `children`. +

+
+
+ + ) +} diff --git a/apps/design-system/registry/default/example/modal-demo.tsx b/apps/design-system/registry/default/example/modal-demo.tsx new file mode 100644 index 00000000000..f11c441568b --- /dev/null +++ b/apps/design-system/registry/default/example/modal-demo.tsx @@ -0,0 +1,42 @@ +import { Link2 } from 'lucide-react' +import { useState } from 'react' +import { Button, Modal } from 'ui' + +export default function ModalDemo() { + const [visible, setVisible] = useState(false) + + return ( + <> + + setVisible(!visible)} + onConfirm={() => setVisible(!visible)} + title="This is the title of the modal" + description="And i am the description" + size="medium" + hideClose={false} + header={ +
+
+ +
+
+

This is the title

+ This is the title +
+
+ } + > + +

+ Modal content is inserted here, if you need to insert anything into the Modal you can do + so via `children`. +

+
+
+ + ) +} diff --git a/apps/design-system/registry/default/example/modal-hide-footer.tsx b/apps/design-system/registry/default/example/modal-hide-footer.tsx new file mode 100644 index 00000000000..ff14e8bf566 --- /dev/null +++ b/apps/design-system/registry/default/example/modal-hide-footer.tsx @@ -0,0 +1,43 @@ +import { Link2 } from 'lucide-react' +import { useState } from 'react' +import { Button, Modal } from 'ui' + +export default function ModalVerticalHideFooter() { + const [visible, setVisible] = useState(false) + + return ( + <> + + setVisible(!visible)} + onConfirm={() => setVisible(!visible)} + title="This is the title of the modal" + description="And i am the description" + hideFooter={true} + size="medium" + hideClose={false} + header={ +
+
+ +
+
+

This is the title

+ This is the title +
+
+ } + > + +

+ Modal content is inserted here, if you need to insert anything into the Modal you can do + so via `children`. +

+
+
+ + ) +} diff --git a/apps/design-system/registry/default/example/modal-vertical-layout.tsx b/apps/design-system/registry/default/example/modal-vertical-layout.tsx new file mode 100644 index 00000000000..e1578fb2660 --- /dev/null +++ b/apps/design-system/registry/default/example/modal-vertical-layout.tsx @@ -0,0 +1,43 @@ +import { Link2 } from 'lucide-react' +import { useState } from 'react' +import { Button, Modal } from 'ui' + +export default function ModalVerticalLayout() { + const [visible, setVisible] = useState(false) + + return ( + <> + + setVisible(!visible)} + onConfirm={() => setVisible(!visible)} + title="This is the title of the modal" + description="And i am the description" + layout="vertical" + size="medium" + hideClose={false} + header={ +
+
+ +
+
+

This is the title

+ This is the title +
+
+ } + > + +

+ Modal content is inserted here, if you need to insert anything into the Modal you can do + so via `children`. +

+
+
+ + ) +} diff --git a/apps/design-system/registry/examples.ts b/apps/design-system/registry/examples.ts index 8676892a518..f8943b0c6c0 100644 --- a/apps/design-system/registry/examples.ts +++ b/apps/design-system/registry/examples.ts @@ -1012,6 +1012,26 @@ export const examples: Registry = [ type: 'components:example', files: ['example/tree-view-multi-select.tsx'], }, + { + name: 'modal-demo', + type: 'components:example', + files: ['example/modal-demo.tsx'], + }, + { + name: 'modal-aligned-footer', + type: 'components:example', + files: ['example/modal-aligned-footer.tsx'], + }, + { + name: 'modal-custom-footer', + type: 'components:example', + files: ['example/modal-custom-footer.tsx'], + }, + { + name: 'modal-hide-footer', + type: 'components:example', + files: ['example/modal-hide-footer.tsx'], + }, { name: 'color-usage-surface-www-and-docs', type: 'docs:example', diff --git a/apps/studio/components/interfaces/Account/NewAccessTokenButton.tsx b/apps/studio/components/interfaces/Account/NewAccessTokenButton.tsx index 84f6f4014ee..415d08c64cd 100644 --- a/apps/studio/components/interfaces/Account/NewAccessTokenButton.tsx +++ b/apps/studio/components/interfaces/Account/NewAccessTokenButton.tsx @@ -3,6 +3,7 @@ import { useState } from 'react' import { Alert, Button, + DialogFooter, DropdownMenu, DropdownMenuContent, DropdownMenuItem, @@ -87,7 +88,7 @@ const NewAccessTokenButton = ({ onCreateToken }: NewAccessTokenButtonProps) => { setIsOpen(!isOpen)} header={ @@ -105,7 +106,7 @@ const NewAccessTokenButton = ({ onCreateToken }: NewAccessTokenButtonProps) => { validate={validate} > {() => ( -
+ <> {tokenScope === 'V0' && ( { className="w-full" /> - - +
-
-
+ + )}
diff --git a/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreviewModal.tsx b/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreviewModal.tsx index 7ec434e29f0..583d1e1f052 100644 --- a/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreviewModal.tsx +++ b/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreviewModal.tsx @@ -87,7 +87,7 @@ const FeaturePreviewModal = () => { onCancel={handleCloseFeaturePreviewModal} > {FEATURE_PREVIEWS.length > 0 ? ( -
+
{FEATURE_PREVIEWS.map((feature) => { diff --git a/apps/studio/components/interfaces/Auth/Policies/PolicyEditor/index.tsx b/apps/studio/components/interfaces/Auth/Policies/PolicyEditor/index.tsx index 77d19c4339d..bb26536bd24 100644 --- a/apps/studio/components/interfaces/Auth/Policies/PolicyEditor/index.tsx +++ b/apps/studio/components/interfaces/Auth/Policies/PolicyEditor/index.tsx @@ -33,45 +33,43 @@ const PolicyEditor = ({ return (
-
- - onUpdatePolicyFormFields({ name })} - /> - - - {isNewPolicy && ( - <> - - onUpdatePolicyFormFields({ command })} - /> - - - - )} - - onUpdatePolicyFormFields({ roles })} - /> - - - - - onUpdatePolicyFormFields({ definition }) - } - onUpdatePolicyCheck={(check: string | undefined) => onUpdatePolicyFormFields({ check })} - /> - -
+ + onUpdatePolicyFormFields({ name })} + /> + + + {isNewPolicy && ( + <> + + onUpdatePolicyFormFields({ command })} + /> + + + + )} + + onUpdatePolicyFormFields({ roles })} + /> + + + + + onUpdatePolicyFormFields({ definition }) + } + onUpdatePolicyCheck={(check: string | undefined) => onUpdatePolicyFormFields({ check })} + /> + { size="small" visible={open} onCancel={() => setOpen(!open)} - header={

Add a new URL

} + header="Add a new URL" + description="This will add a URL to a list of allowed URLs that can interact with your Authentication services for this project." >
{ > {() => { return ( -
-
-

- This will add a URL to a list of allowed URLs that can interact with your - Authentication services for this project. -

-
-
-
+ <> + -
-
-
+ + + -
-
+ + ) }} @@ -220,37 +215,35 @@ const RedirectUrls = () => { header={

Remove URL

} onCancel={() => setSelectedUrlToDelete(undefined)} > -
-
-

- Are you sure you want to remove{' '} - {selectedUrlToDelete}? -

-

- This URL will no longer work with your authentication configuration. -

-
-
-
- - -
-
+ +

+ Are you sure you want to remove{' '} + {selectedUrlToDelete}? +

+

+ This URL will no longer work with your authentication configuration. +

+
+ + + + +
) diff --git a/apps/studio/components/interfaces/Auth/Users/CreateUserModal.tsx b/apps/studio/components/interfaces/Auth/Users/CreateUserModal.tsx index c0d7616693d..a8d773c7ac5 100644 --- a/apps/studio/components/interfaces/Auth/Users/CreateUserModal.tsx +++ b/apps/studio/components/interfaces/Auth/Users/CreateUserModal.tsx @@ -72,56 +72,52 @@ const CreateUserModal = ({ visible, setVisible }: CreateUserModalProps) => { > {() => ( -
- -
- } - type="email" - name="email" - placeholder="user@example.com" - disabled={isCreatingUser || isLoading} - /> + + } + type="email" + name="email" + placeholder="user@example.com" + disabled={isCreatingUser || isLoading} + /> - } - disabled={isCreatingUser || isLoading} - autoComplete="new-password" - /> + } + disabled={isCreatingUser || isLoading} + autoComplete="new-password" + /> - -
-
- - - - -
+ + + + + +
)} diff --git a/apps/studio/components/interfaces/Auth/Users/InviteUserModal.tsx b/apps/studio/components/interfaces/Auth/Users/InviteUserModal.tsx index d5da5f29418..4584d7c9343 100644 --- a/apps/studio/components/interfaces/Auth/Users/InviteUserModal.tsx +++ b/apps/studio/components/interfaces/Auth/Users/InviteUserModal.tsx @@ -61,7 +61,7 @@ const InviteUserModal = ({ visible, setVisible }: InviteUserModalProps) => { onSubmit={onInviteUser} > {() => ( -
+ <> { Invite user -
+ )} diff --git a/apps/studio/components/interfaces/Billing/Payment/AddNewPaymentMethodModal.tsx b/apps/studio/components/interfaces/Billing/Payment/AddNewPaymentMethodModal.tsx index 2fd7bf429a5..00cfa7fdb68 100644 --- a/apps/studio/components/interfaces/Billing/Payment/AddNewPaymentMethodModal.tsx +++ b/apps/studio/components/interfaces/Billing/Payment/AddNewPaymentMethodModal.tsx @@ -132,15 +132,13 @@ const AddNewPaymentMethodModal = ({ onCancel={onLocalCancel} className="PAYMENT" > -
- - - -
+ + + ) diff --git a/apps/studio/components/interfaces/Billing/Payment/AddPaymentMethodForm.tsx b/apps/studio/components/interfaces/Billing/Payment/AddPaymentMethodForm.tsx index 581fe0a2da0..3d1fa69eca8 100644 --- a/apps/studio/components/interfaces/Billing/Payment/AddPaymentMethodForm.tsx +++ b/apps/studio/components/interfaces/Billing/Payment/AddPaymentMethodForm.tsx @@ -55,23 +55,33 @@ const AddPaymentMethodForm = ({ returnUrl, onCancel, onConfirm }: AddPaymentMeth return (
- -
- -
+ + - -
- - -
+ + + ) diff --git a/apps/studio/components/interfaces/Billing/SpendCapModal.tsx b/apps/studio/components/interfaces/Billing/SpendCapModal.tsx index d5a33f30f45..87e9d4a895f 100644 --- a/apps/studio/components/interfaces/Billing/SpendCapModal.tsx +++ b/apps/studio/components/interfaces/Billing/SpendCapModal.tsx @@ -10,174 +10,172 @@ interface SpendCapModalProps { const SpendCapModal = ({ visible, onHide }: SpendCapModalProps) => { return ( onHide()}> -
- -
-

- Enabling the spend cap sets a limit on your usage to stay within your plan's quota, - which controls costs but can limit service. Disabling the spend cap removes these - limits, but any extra usage beyond the plan's limit will be charged per usage. -

-

- Take a look at the following table to see which resources are chargeable and how they - are charged: -

- {/* Maybe instead of a table, show something more interactive like a spend cap playground */} - {/* Maybe ideate this in Figma first but this is good enough for now */} -
-
-

Item

-

Limit

-

Rate

+ +
+

+ Enabling the spend cap sets a limit on your usage to stay within your plan's quota, + which controls costs but can limit service. Disabling the spend cap removes these + limits, but any extra usage beyond the plan's limit will be charged per usage. +

+

+ Take a look at the following table to see which resources are chargeable and how they + are charged: +

+ {/* Maybe instead of a table, show something more interactive like a spend cap playground */} + {/* Maybe ideate this in Figma first but this is good enough for now */} +
+
+

Item

+

Limit

+

Rate

+
+
+
+

Database size

+

8GB

+

$0.125 per GB

-
-
-

Database size

-

8GB

-

$0.125 per GB

-
-
-

Egress

-

250GB

-

$0.09 per GB

-
+
+

Egress

+

250GB

+

$0.09 per GB

-
-
-
-

Auth MAUs

- - - - +
+
+
+
+

Auth MAUs

+ + + + + - - - -
- - Monthly Active Users: A user that has made an API request in the - last month - -
-
-
+ + +
+ + Monthly Active Users: A user that has made an API request in the last + month + +
+
-
-
-

100,000

-

$0.00325 per user

+ +
-
-
-

Single Sign-On (SAML 2.0) MAUs

- - - - +

100,000

+

$0.00325 per user

+
+
+
+

Single Sign-On (SAML 2.0) MAUs

+ + + + + - - - -
- - Single Sign-On Monthly Active Users: A user that has made an API - request in the last month - -
-
-
+ + +
+ + Single Sign-On Monthly Active Users: A user that has made an API + request in the last month + +
+
-
-
-

50

-

$0.015 per user

-
-
- -
-
-

Storage size

-

100GB

-

$0.021 per GB

-
-
-

Storage Image Transformations

-

100 origin images

-

$5 per 1000 origin images

-
-
- -
-
-

Realtime concurrent peak connections

-

500

-

$10 per 1000

-
- -
-

Realtime messages

-

5 Million

-

$2.50 per Million

-
-
- -
-
-

Function invocations

-

2 Million

-

$2 per Million

-
- -
-

Function count

-

100 functions

-

$10 per 100 functions

+ +
+

50

+

$0.015 per user

-

- See{' '} - - pricing page - {' '} - for a full overview. -

+
+
+

Storage size

+

100GB

+

$0.021 per GB

+
+
+

Storage Image Transformations

+

100 origin images

+

$5 per 1000 origin images

+
+
+ +
+
+

Realtime concurrent peak connections

+

500

+

$10 per 1000

+
+ +
+

Realtime messages

+

5 Million

+

$2.50 per Million

+
+
+ +
+
+

Function invocations

+

2 Million

+

$2 per Million

+
+ +
+

Function count

+

100 functions

+

$10 per 100 functions

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

+ See{' '} + + pricing page + {' '} + for a full overview. +

+
+ + + +
+ +
+
) } diff --git a/apps/studio/components/interfaces/BranchManagement/CreateBranchModal.tsx b/apps/studio/components/interfaces/BranchManagement/CreateBranchModal.tsx index 6a28ef30bad..29c303e5dac 100644 --- a/apps/studio/components/interfaces/BranchManagement/CreateBranchModal.tsx +++ b/apps/studio/components/interfaces/BranchManagement/CreateBranchModal.tsx @@ -146,7 +146,7 @@ const CreateBranchModal = ({ visible, onClose }: CreateBranchModalProps) => { header="Create a new preview branch" confirmText="Create Preview Branch" > - + {isLoadingConnections && } {isErrorConnections && ( { - +

Choose a Git Branch to base your Preview Branch on. Any migration changes added to this Git Branch will be run on this new Preview Branch. @@ -220,21 +220,19 @@ const CreateBranchModal = ({ visible, onClose }: CreateBranchModalProps) => { - -

- - -
+ + + diff --git a/apps/studio/components/interfaces/Database/Backups/PITR/PITRSelection.tsx b/apps/studio/components/interfaces/Database/Backups/PITR/PITRSelection.tsx index a396ea0786d..9ae3cb055db 100644 --- a/apps/studio/components/interfaces/Database/Backups/PITR/PITRSelection.tsx +++ b/apps/studio/components/interfaces/Database/Backups/PITR/PITRSelection.tsx @@ -380,44 +380,40 @@ const PITRSelection = () => {
} > -
- -
-

Your database will be restored to:

+ +
+

Your database will be restored to:

+
+
+
+

{selectedTimezone?.text}

+

{recoveryTimeString}

-
-
-

- {selectedTimezone?.text} -

-

{recoveryTimeString}

-
-
-

(UTC+00:00)

-

{recoveryTimeStringUtc}

-
+
+

(UTC+00:00)

+

{recoveryTimeStringUtc}

- - - - - Any changes made to your database after this point in time will be lost. This includes - any changes to your project's storage and authentication. - - - - -

- Restores may take from a few minutes up to several hours depending on the size of your - database. During this period, your project will not be available, until the - restoration is completed. -

-
-
+
+
+ + + + Any changes made to your database after this point in time will be lost. This includes + any changes to your project's storage and authentication. + + + + +

+ Restores may take from a few minutes up to several hours depending on the size of your + database. During this period, your project will not be available, until the restoration + is completed. +

+
) diff --git a/apps/studio/components/interfaces/Database/Extensions/EnableExtensionModal.tsx b/apps/studio/components/interfaces/Database/Extensions/EnableExtensionModal.tsx index a657a4469b6..42fba377d29 100644 --- a/apps/studio/components/interfaces/Database/Extensions/EnableExtensionModal.tsx +++ b/apps/studio/components/interfaces/Database/Extensions/EnableExtensionModal.tsx @@ -130,7 +130,7 @@ const EnableExtensionModal = ({ visible, extension, onCancel }: EnableExtensionM > {({ values }: any) => { return ( -
+ <> {fetchingSchemaInfo || isSchemasLoading ? (
@@ -218,19 +218,16 @@ const EnableExtensionModal = ({ visible, extension, onCancel }: EnableExtensionM )} - - -
- - -
+ + + -
+ ) }} diff --git a/apps/studio/components/interfaces/Database/ProtectedSchemaWarning.tsx b/apps/studio/components/interfaces/Database/ProtectedSchemaWarning.tsx index 32ba97de4bc..895f283ff8c 100644 --- a/apps/studio/components/interfaces/Database/ProtectedSchemaWarning.tsx +++ b/apps/studio/components/interfaces/Database/ProtectedSchemaWarning.tsx @@ -31,7 +31,7 @@ export const ProtectedSchemaModal = ({ } onCancel={() => onClose()} > - +

The following schemas are managed by Supabase and are currently protected from write access through the dashboard. diff --git a/apps/studio/components/interfaces/Database/Roles/DeleteRoleModal.tsx b/apps/studio/components/interfaces/Database/Roles/DeleteRoleModal.tsx index 4422024b5c2..9707ab9353b 100644 --- a/apps/studio/components/interfaces/Database/Roles/DeleteRoleModal.tsx +++ b/apps/studio/components/interfaces/Database/Roles/DeleteRoleModal.tsx @@ -41,14 +41,12 @@ const DeleteRoleModal = ({ role, visible, onClose }: DeleteRoleModalProps) => { header={

Confirm to delete role "{role?.name}"

} loading={isDeleting} > -
- -

- This will automatically revoke any membership of this role in other roles, and this - action cannot be undone. -

-
-
+ +

+ This will automatically revoke any membership of this role in other roles, and this action + cannot be undone. +

+
) } diff --git a/apps/studio/components/interfaces/Database/Wrappers/DeleteWrapperModal.tsx b/apps/studio/components/interfaces/Database/Wrappers/DeleteWrapperModal.tsx index f7033ee3b52..428d0a183d3 100644 --- a/apps/studio/components/interfaces/Database/Wrappers/DeleteWrapperModal.tsx +++ b/apps/studio/components/interfaces/Database/Wrappers/DeleteWrapperModal.tsx @@ -44,14 +44,12 @@ const DeleteWrapperModal = ({ selectedWrapper, onClose }: DeleteWrapperModalProp onConfirm={() => onConfirmDelete()} header={`Confirm to disable ${selectedWrapper?.name}`} > -
- -

- Are you sure you want to disable {selectedWrapper?.name}? This will also remove all - tables created with this wrapper. -

-
-
+ +

+ Are you sure you want to disable {selectedWrapper?.name}? This will also remove all tables + created with this wrapper. +

+
) } diff --git a/apps/studio/components/interfaces/Functions/CommandRender.tsx b/apps/studio/components/interfaces/Functions/CommandRender.tsx index 010ff1f3474..6b3a1afa803 100644 --- a/apps/studio/components/interfaces/Functions/CommandRender.tsx +++ b/apps/studio/components/interfaces/Functions/CommandRender.tsx @@ -1,15 +1,20 @@ import { Check, Clipboard } from 'lucide-react' -import { useState } from 'react' +import { forwardRef, useState } from 'react' +import { cn } from 'ui' -const CommandRender = ({ commands }: any) => { - return ( -
- {commands.map((item: any, idx: number) => { - return - })} -
- ) -} +const CommandRender = forwardRef( + ({ commands, className }, ref) => { + return ( +
+ {commands.map((item: any, idx: number) => ( + + ))} +
+ ) + } +) + +CommandRender.displayName = 'CommandRender' export default CommandRender diff --git a/apps/studio/components/interfaces/Functions/EdgeFunctionDetails/EdgeFunctionDetails.tsx b/apps/studio/components/interfaces/Functions/EdgeFunctionDetails/EdgeFunctionDetails.tsx index 0fd475adaef..948219253b8 100644 --- a/apps/studio/components/interfaces/Functions/EdgeFunctionDetails/EdgeFunctionDetails.tsx +++ b/apps/studio/components/interfaces/Functions/EdgeFunctionDetails/EdgeFunctionDetails.tsx @@ -289,13 +289,11 @@ const EdgeFunctionDetails = () => { onCancel={() => setShowDeleteModal(false)} onConfirm={onConfirmDelete} > -
- - - Ensure that you have made a backup if you want to restore your edge function - - -
+ + + Ensure that you have made a backup if you want to restore your edge function + + ) diff --git a/apps/studio/components/interfaces/Functions/EdgeFunctionSecrets/AddNewSecretModal.tsx b/apps/studio/components/interfaces/Functions/EdgeFunctionSecrets/AddNewSecretModal.tsx index 76b99e50bd8..ddedf66ba46 100644 --- a/apps/studio/components/interfaces/Functions/EdgeFunctionSecrets/AddNewSecretModal.tsx +++ b/apps/studio/components/interfaces/Functions/EdgeFunctionSecrets/AddNewSecretModal.tsx @@ -64,7 +64,7 @@ const AddNewSecretModal = ({ visible, onClose }: AddNewSecretModalProps) => { > {() => ( <> - + { return ( <> -
-
+
+

Scalable functions to run your code with no server management.

@@ -38,7 +38,9 @@ const FunctionsEmptyState = () => {
- +
+ +
) diff --git a/apps/studio/components/interfaces/Functions/TerminalInstructions.tsx b/apps/studio/components/interfaces/Functions/TerminalInstructions.tsx index 53e27edf308..508119e9fbb 100644 --- a/apps/studio/components/interfaces/Functions/TerminalInstructions.tsx +++ b/apps/studio/components/interfaces/Functions/TerminalInstructions.tsx @@ -1,7 +1,12 @@ import { useParams } from 'common/hooks' import { useRouter } from 'next/router' -import { useState } from 'react' -import { Button } from 'ui' +import { ElementRef, forwardRef, useState } from 'react' +import { + Button, + CollapsibleContent_Shadcn_, + CollapsibleTrigger_Shadcn_, + Collapsible_Shadcn_, +} from 'ui' import CommandRender from 'components/interfaces/Functions/CommandRender' import { useAccessTokensQuery } from 'data/access-tokens/access-tokens-query' @@ -10,15 +15,16 @@ import { useCustomDomainsQuery } from 'data/custom-domains/custom-domains-query' import { Code, ExternalLink, Maximize2, Minimize2, Terminal } from 'lucide-react' import type { Commands } from './Functions.types' -interface TerminalInstructionsProps { +interface TerminalInstructionsProps + extends React.ComponentPropsWithoutRef { closable?: boolean removeBorder?: boolean } -const TerminalInstructions = ({ - closable = false, - removeBorder = false, -}: TerminalInstructionsProps) => { +const TerminalInstructions = forwardRef< + React.ElementRef, + TerminalInstructionsProps +>(({ closable = false, removeBorder = false, ...props }, ref) => { const router = useRouter() const { ref: projectRef } = useParams() const [showInstructions, setShowInstructions] = useState(!closable) @@ -84,72 +90,79 @@ const TerminalInstructions = ({ ] return ( -
setShowInstructions(!showInstructions)} + {...props} > -
-
-
-
- -
-

Create your first Edge Function via the CLI

+ +
+
+
- {closable && ( -
setShowInstructions(!showInstructions)}> - {showInstructions ? ( - - ) : ( - - )} -
- )} +

Create your first Edge Function via the CLI

- -
- {tokens && tokens.length === 0 ? ( -
-
-

You may need to create an access token

-

- You can create a secure access token in your account section -

+ {closable && ( +
setShowInstructions(!showInstructions)}> + {showInstructions ? ( + + ) : ( + + )}
- -
- ) : ( -
-
-

Need help?

-

- Read the documentation, or browse some sample code. -

-
-
- -
-
- )} -
+ ) : ( +
+
+

Need help?

+

+ Read the documentation, or browse some sample code. +

+
+ +
+ )} + + ) -} +}) + +TerminalInstructions.displayName = 'TerminalInstructions' export default TerminalInstructions diff --git a/apps/studio/components/interfaces/Home/Connect/Connect.tsx b/apps/studio/components/interfaces/Home/Connect/Connect.tsx index 3261ea2c0a8..9e15dff8016 100644 --- a/apps/studio/components/interfaces/Home/Connect/Connect.tsx +++ b/apps/studio/components/interfaces/Home/Connect/Connect.tsx @@ -170,8 +170,8 @@ const Connect = () => { - - + + Connect to your project Get the connection strings and environment variables for your app diff --git a/apps/studio/components/interfaces/Organization/BillingSettings/PaymentMethods/ChangePaymentMethodModal.tsx b/apps/studio/components/interfaces/Organization/BillingSettings/PaymentMethods/ChangePaymentMethodModal.tsx index c748e564b7b..e30d69ef331 100644 --- a/apps/studio/components/interfaces/Organization/BillingSettings/PaymentMethods/ChangePaymentMethodModal.tsx +++ b/apps/studio/components/interfaces/Organization/BillingSettings/PaymentMethods/ChangePaymentMethodModal.tsx @@ -62,14 +62,12 @@ const ChangePaymentMethodModal = ({
} > -
- -

- Upon clicking confirm, all future charges will be deducted from the card ending with{' '} - {selectedPaymentMethod?.card?.last4}. There are no immediate charges. -

-
-
+ +

+ Upon clicking confirm, all future charges will be deducted from the card ending with{' '} + {selectedPaymentMethod?.card?.last4}. There are no immediate charges. +

+
) } diff --git a/apps/studio/components/interfaces/Organization/BillingSettings/PaymentMethods/DeletePaymentMethodModal.tsx b/apps/studio/components/interfaces/Organization/BillingSettings/PaymentMethods/DeletePaymentMethodModal.tsx index 7beb2a53f38..fc58ab39861 100644 --- a/apps/studio/components/interfaces/Organization/BillingSettings/PaymentMethods/DeletePaymentMethodModal.tsx +++ b/apps/studio/components/interfaces/Organization/BillingSettings/PaymentMethods/DeletePaymentMethodModal.tsx @@ -54,13 +54,11 @@ const DeletePaymentMethodModal = ({
} > -
- - -

You can re-add the payment method any time.

-
-
-
+ + +

You can re-add the payment method any time.

+
+
) } diff --git a/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/DowngradeModal.tsx b/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/DowngradeModal.tsx index f0330e8471d..3a6514e1c56 100644 --- a/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/DowngradeModal.tsx +++ b/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/DowngradeModal.tsx @@ -71,82 +71,80 @@ const DowngradeModal = ({ header={`Confirm to downgrade to ${selectedPlan?.name} plan`} > -
-
- -

- If you're already past the limits of the Free plan, your projects could become - unresponsive or enter read only mode. -

-
- - {((previousProjectAddons.length ?? 0) > 0 || - (hasInstancesOnMicro && downgradingToNano)) && ( - -
    - {previousProjectAddons.map((project) => ( - - ))} - - {projects - .filter((it) => it.infra_compute_size === 'micro') - .map((project) => ( -
  • - {project.name}: Compute will be downgraded. Project will also{' '} - need to be restarted. -
  • - ))} -
-
- )} -
- -
    -
  • -
    - -
    - Projects will be paused after a week of inactivity -
  • - -
  • -
    -
    - -
    - Add ons from all projects under this organization will be removed. -
    -
  • - -
  • - -
    - Before you downgrade to the {selectedPlan?.name} plan, consider: -
      -
    • - Your projects no longer require their respective add ons. -
    • -
    • - Your resource consumption are well within the {selectedPlan?.name} plan's quota. -
    • -
    • - Alternatively, you may also transfer projects across organizations. -
    • -
    -
    -
  • -
- - {subscription?.billing_via_partner === true && subscription.billing_partner === 'fly' && ( -

- Your organization will be downgraded at the end of your current billing cycle. +

+ +

+ If you're already past the limits of the Free plan, your projects could become + unresponsive or enter read only mode.

+
+ + {((previousProjectAddons.length ?? 0) > 0 || + (hasInstancesOnMicro && downgradingToNano)) && ( + +
    + {previousProjectAddons.map((project) => ( + + ))} + + {projects + .filter((it) => it.infra_compute_size === 'micro') + .map((project) => ( +
  • + {project.name}: Compute will be downgraded. Project will also{' '} + need to be restarted. +
  • + ))} +
+
)}
+ +
    +
  • +
    + +
    + Projects will be paused after a week of inactivity +
  • + +
  • +
    +
    + +
    + Add ons from all projects under this organization will be removed. +
    +
  • + +
  • + +
    + Before you downgrade to the {selectedPlan?.name} plan, consider: +
      +
    • + Your projects no longer require their respective add ons. +
    • +
    • + Your resource consumption are well within the {selectedPlan?.name} plan's quota. +
    • +
    • + Alternatively, you may also transfer projects across organizations. +
    • +
    +
    +
  • +
+ + {subscription?.billing_via_partner === true && subscription.billing_partner === 'fly' && ( +

+ Your organization will be downgraded at the end of your current billing cycle. +

+ )} ) diff --git a/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/ExitSurveyModal.tsx b/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/ExitSurveyModal.tsx index 0edb1323cfd..447e929fe18 100644 --- a/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/ExitSurveyModal.tsx +++ b/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/ExitSurveyModal.tsx @@ -150,7 +150,7 @@ const ExitSurveyModal = ({ visible, subscription, projects, onClose }: ExitSurve header="We're sad that you're leaving" > -
+

We always strive to improve Supabase as much as we can. Please let us know the reasons you are canceling your subscription so that we can improve in the future. diff --git a/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/MembersExceedLimitModal.tsx b/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/MembersExceedLimitModal.tsx index ebfb6403d87..ca756e99cfd 100644 --- a/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/MembersExceedLimitModal.tsx +++ b/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/MembersExceedLimitModal.tsx @@ -22,36 +22,32 @@ const MembersExceedLimitModal = ({ visible, onClose }: MembersExceedLimitModalPr header="Your organization has members who have exceeded their free project limits" onCancel={onClose} > -

- -
-

- The following members have reached their maximum limits for the number of active free - plan projects within organizations where they are an administrator or owner: -

-
    - {(membersExceededLimit || []).map((member, idx: number) => ( -
  • - {member.username || member.primary_email} (Limit: {member.free_project_limit} free - projects) -
  • - ))} -
-

- These members will need to either delete, pause, or upgrade one or more of these - projects before you're able to downgrade this project. -

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

+ The following members have reached their maximum limits for the number of active free + plan projects within organizations where they are an administrator or owner: +

+
    + {(membersExceededLimit || []).map((member, idx: number) => ( +
  • + {member.username || member.primary_email} (Limit: {member.free_project_limit} free + projects) +
  • + ))} +
+

+ These members will need to either delete, pause, or upgrade one or more of these + projects before you're able to downgrade this project. +

+
+
+ + + + ) } diff --git a/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/PlanUpdateSidePanel.tsx b/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/PlanUpdateSidePanel.tsx index c2a843aafe6..d3923a8b0f5 100644 --- a/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/PlanUpdateSidePanel.tsx +++ b/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/PlanUpdateSidePanel.tsx @@ -359,7 +359,7 @@ const PlanUpdateSidePanel = () => { overlayClassName="pointer-events-none" header={`Confirm ${planMeta?.change_type === 'downgrade' ? 'downgrade' : 'upgrade'} to ${subscriptionPlanMeta?.name}`} > - + {subscriptionPreviewError && ( - -
-

- What reasons motivated your decision to upgrade? Your feedback helps us improve - Supabase as much as we can. -

-
-
- {upgradeReasons.map((option) => { - const active = selectedReasons.find((x) => x === option) - return ( -
diff --git a/apps/studio/components/interfaces/Organization/GeneralSettings/DeleteOrganizationButton.tsx b/apps/studio/components/interfaces/Organization/GeneralSettings/DeleteOrganizationButton.tsx index aaad24ff686..335ccad8e09 100644 --- a/apps/studio/components/interfaces/Organization/GeneralSettings/DeleteOrganizationButton.tsx +++ b/apps/studio/components/interfaces/Organization/GeneralSettings/DeleteOrganizationButton.tsx @@ -58,7 +58,7 @@ const DeleteOrganizationButton = () => { onCancel={() => setIsOpen(false)} header={
-
Delete organization
+ Delete organization Are you sure?
} @@ -70,7 +70,7 @@ const DeleteOrganizationButton = () => { validate={onValidate} > {() => ( -
+ <>

This action cannot be undone. This will @@ -106,7 +106,7 @@ const DeleteOrganizationButton = () => { I understand, delete this organization -

+ )} diff --git a/apps/studio/components/interfaces/Organization/OAuthApps/DeleteAppModal.tsx b/apps/studio/components/interfaces/Organization/OAuthApps/DeleteAppModal.tsx index ee92712e936..59d65bea7d8 100644 --- a/apps/studio/components/interfaces/Organization/OAuthApps/DeleteAppModal.tsx +++ b/apps/studio/components/interfaces/Organization/OAuthApps/DeleteAppModal.tsx @@ -36,26 +36,26 @@ const DeleteAppModal = ({ selectedApp, onClose }: DeleteAppModalProps) => { onConfirm={onConfirmDelete} > -
- - Deleting {selectedApp?.name} will invalidate any access tokens from this application - that were authorized by users. - -
    -
  • - -
    - Before you remove this application, consider: -
      -
    • - No users are currently using this application. It will no longer be available - for use after deletion. -
    • -
    -
    -
  • -
-
+ + Deleting {selectedApp?.name} will invalidate any access tokens from this application that + were authorized by users. + +
+ +
    +
  • + +
    + Before you remove this application, consider: +
      +
    • + No users are currently using this application. It will no longer be available for + use after deletion. +
    • +
    +
    +
  • +
) diff --git a/apps/studio/components/interfaces/Organization/OAuthApps/PublishAppSidePanel/index.tsx b/apps/studio/components/interfaces/Organization/OAuthApps/PublishAppSidePanel/index.tsx index 6b2d2adac67..ce2eabf2213 100644 --- a/apps/studio/components/interfaces/Organization/OAuthApps/PublishAppSidePanel/index.tsx +++ b/apps/studio/components/interfaces/Organization/OAuthApps/PublishAppSidePanel/index.tsx @@ -383,33 +383,29 @@ const PublishAppSidePanel = ({ onCancel={() => setShowPreview(false)} > -
+

Authorize API access for {values.name}

Preview
-
- -
-

- Select an organization to grant API access to -

-
- Organizations that you have access to will be listed here -
+ +
+

Select an organization to grant API access to

+
+ Organizations that you have access to will be listed here
-
+

This is what your users will see when authorizing with your app

diff --git a/apps/studio/components/interfaces/Organization/OAuthApps/RevokeAppModal.tsx b/apps/studio/components/interfaces/Organization/OAuthApps/RevokeAppModal.tsx index 5583bef9226..b63fc5f6143 100644 --- a/apps/studio/components/interfaces/Organization/OAuthApps/RevokeAppModal.tsx +++ b/apps/studio/components/interfaces/Organization/OAuthApps/RevokeAppModal.tsx @@ -36,26 +36,26 @@ const RevokeAppModal = ({ selectedApp, onClose }: RevokeAppModalProps) => { onConfirm={onConfirmDelete} > -
- - {selectedApp?.name} application will no longer have access to your organization's - settings and projects. - -
    -
  • - -
    - Before you remove this app, consider: -
      -
    • - No users are currently using this application. The application will no longer - have access to your organization after being revoked. -
    • -
    -
    -
  • -
-
+ + {selectedApp?.name} application will no longer have access to your organization's settings + and projects. + +
+ +
    +
  • + +
    + Before you remove this app, consider: +
      +
    • + No users are currently using this application. The application will no longer have + access to your organization after being revoked. +
    • +
    +
    +
  • +
) diff --git a/apps/studio/components/interfaces/Organization/TeamSettings/InviteMemberButton.tsx b/apps/studio/components/interfaces/Organization/TeamSettings/InviteMemberButton.tsx index 70326da0578..813f7f8a466 100644 --- a/apps/studio/components/interfaces/Organization/TeamSettings/InviteMemberButton.tsx +++ b/apps/studio/components/interfaces/Organization/TeamSettings/InviteMemberButton.tsx @@ -150,53 +150,44 @@ const InviteMemberButton = ({ return ( <> - -
-
-
- {roles && ( - - {roles.map((role: any) => ( - - {role.name} - - ))} - - )} -
- - } - placeholder="Enter email address" - label="Email address" - /> -
-
+ + {roles && ( + + {roles.map((role: any) => ( + + {role.name} + + ))} + + )} + } + placeholder="Enter email address" + label="Email address" + /> -
- -
+
) diff --git a/apps/studio/components/interfaces/Organization/TeamSettings/MembersView.tsx b/apps/studio/components/interfaces/Organization/TeamSettings/MembersView.tsx index 6fa2df79664..cdd992ecab9 100644 --- a/apps/studio/components/interfaces/Organization/TeamSettings/MembersView.tsx +++ b/apps/studio/components/interfaces/Organization/TeamSettings/MembersView.tsx @@ -165,43 +165,38 @@ const MembersView = ({ searchString }: MembersViewProps) => { onCancel={() => setUserRoleChangeModalVisible(false)} header="Change role of member" > -
- -

- You are changing the role of{' '} - {getUserDisplayName(selectedMember)} from{' '} - {getRoleNameById(selectedMember?.oldRoleId)}{' '} - to{' '} - {getRoleNameById(selectedMember?.newRoleId)} -

-

- By changing the role of this member their permissions will change. -

-
- - -
- - -
-
-
+ +

+ You are changing the role of{' '} + {getUserDisplayName(selectedMember)} from{' '} + {getRoleNameById(selectedMember?.oldRoleId)} to{' '} + {getRoleNameById(selectedMember?.newRoleId)} +

+

+ By changing the role of this member their permissions will change. +

+
+ + + + + ) diff --git a/apps/studio/components/interfaces/Organization/TeamSettings/RolesHelperModal/RolesHelperModal.tsx b/apps/studio/components/interfaces/Organization/TeamSettings/RolesHelperModal/RolesHelperModal.tsx index d8a5d96e0c5..dcc77f1e4a1 100644 --- a/apps/studio/components/interfaces/Organization/TeamSettings/RolesHelperModal/RolesHelperModal.tsx +++ b/apps/studio/components/interfaces/Organization/TeamSettings/RolesHelperModal/RolesHelperModal.tsx @@ -48,61 +48,57 @@ const RolesHelperModal = () => { header="Permissions for each role" onCancel={() => setShowModal(!showModal)} > -
- -

- The following table shows the corresponding permissions for each available role in the - dashboard. -

-
- -
-
-
Permissions
-
Owner
-
Administrator
-
Developer
-
Read-only {accessTooltip}
-
Billing-only {accessTooltip}
-
- -
- {PERMISSIONS_MAPPING.map((group) => ( - -
-
{group.title}
-
- {group.actions.map((action, idx) => ( -
-
{action.description}
-
- {action.permissions.owner && } -
-
- {action.permissions.admin && } -
-
- {action.permissions.developer && } -
-
- {action.permissions.read_only && } -
-
- {action.permissions.billing_only && ( - - )} -
-
- ))} -
- ))} -
+ +

+ The following table shows the corresponding permissions for each available role in the + dashboard. +

+
+ +
+
+
Permissions
+
Owner
+
Administrator
+
Developer
+
Read-only {accessTooltip}
+
Billing-only {accessTooltip}
- -
+ +
+ {PERMISSIONS_MAPPING.map((group) => ( + +
+
{group.title}
+
+ {group.actions.map((action, idx) => ( +
+
{action.description}
+
+ {action.permissions.owner && } +
+
+ {action.permissions.admin && } +
+
+ {action.permissions.developer && } +
+
+ {action.permissions.read_only && } +
+
+ {action.permissions.billing_only && } +
+
+ ))} +
+ ))} +
+
+
) diff --git a/apps/studio/components/interfaces/Realtime/Inspector/SendMessageModal.tsx b/apps/studio/components/interfaces/Realtime/Inspector/SendMessageModal.tsx index 00dfb8a95e2..5a6b869d78e 100644 --- a/apps/studio/components/interfaces/Realtime/Inspector/SendMessageModal.tsx +++ b/apps/studio/components/interfaces/Realtime/Inspector/SendMessageModal.tsx @@ -47,29 +47,25 @@ export const SendMessageModal = ({ } }} > - -
- setValues({ ...values, message: v.target.value })} + + setValues({ ...values, message: v.target.value })} + /> +
+

Message payload

+ setValues({ ...values, payload: e ?? '{}' })} + options={{ wordWrap: 'off', contextmenu: false }} + value={values.payload} /> -
-

Message payload

- - setValues({ ...values, payload: e ?? '{}' }) - } - options={{ wordWrap: 'off', contextmenu: false }} - value={values.payload} - /> - {error !== undefined &&

{error}

} -
+ {error !== undefined &&

{error}

}
diff --git a/apps/studio/components/interfaces/Reports/Reports.CreateReportModal.tsx b/apps/studio/components/interfaces/Reports/Reports.CreateReportModal.tsx index d50b77781e3..5154157a82c 100644 --- a/apps/studio/components/interfaces/Reports/Reports.CreateReportModal.tsx +++ b/apps/studio/components/interfaces/Reports/Reports.CreateReportModal.tsx @@ -82,11 +82,9 @@ export const CreateReportModal = ({ visible, onCancel, afterSubmit }: CreateRepo onSubmit={(newVals) => createCustomReport(newVals)} > {() => ( -
- + <> + - - - -
- - -
+ + + -
+ )} diff --git a/apps/studio/components/interfaces/Reports/Reports.UpdateModal.tsx b/apps/studio/components/interfaces/Reports/Reports.UpdateModal.tsx index 9a903322da2..ccb2193ee67 100644 --- a/apps/studio/components/interfaces/Reports/Reports.UpdateModal.tsx +++ b/apps/studio/components/interfaces/Reports/Reports.UpdateModal.tsx @@ -68,7 +68,7 @@ export const UpdateCustomReportModal = ({ onSubmit={onConfirmUpdateReport} > {({ isSubmitting }: { isSubmitting: boolean }) => ( -
+ <> @@ -82,17 +82,15 @@ export const UpdateCustomReportModal = ({ /> - -
- - -
+ + + -
+ )} diff --git a/apps/studio/components/interfaces/SQLEditor/DownloadSnippetModal.tsx b/apps/studio/components/interfaces/SQLEditor/DownloadSnippetModal.tsx index 4c987537d10..340279bd08e 100644 --- a/apps/studio/components/interfaces/SQLEditor/DownloadSnippetModal.tsx +++ b/apps/studio/components/interfaces/SQLEditor/DownloadSnippetModal.tsx @@ -60,44 +60,46 @@ const DownloadSnippetModal = ({ id, ...props }: DownloadSnippetModalProps) => { header={

Download snippet as local migration file via the Supabase CLI.

} {...props} > -
+
{SNIPPETS.map((snippet) => { return ( - -
-
-

{snippet.title}

- + +
+
+

{snippet.title}

+ +
+ + selectedView === 'CLI' ? setSelectedView('NPM') : setSelectedView('CLI') + } />
- - selectedView === 'CLI' ? setSelectedView('NPM') : setSelectedView('CLI') - } - /> -
-
-                  
-                    {selectedView === 'CLI' ? snippet.cli : snippet.npm}
-                  
-                
+
+                    
+                      {selectedView === 'CLI' ? snippet.cli : snippet.npm}
+                    
+                  
+ ) })} -
-

Run this command from your project directory

-
+ +

Run this command from your project directory

+
-
+
) diff --git a/apps/studio/components/interfaces/SQLEditor/RenameQueryModal.tsx b/apps/studio/components/interfaces/SQLEditor/RenameQueryModal.tsx index 76aec556466..2ce6b2783a3 100644 --- a/apps/studio/components/interfaces/SQLEditor/RenameQueryModal.tsx +++ b/apps/studio/components/interfaces/SQLEditor/RenameQueryModal.tsx @@ -82,8 +82,8 @@ const RenameQueryModal = ({ snippet, visible, onCancel, onComplete }: RenameQuer onSubmit={onSubmit} > {({ isSubmitting }: { isSubmitting: boolean }) => ( -
- + <> + )}
- - - -
- - -
+ + + -
+ )} diff --git a/apps/studio/components/interfaces/Settings/API/JWTSettings.tsx b/apps/studio/components/interfaces/Settings/API/JWTSettings.tsx index e967351ba96..8dd279f79ce 100644 --- a/apps/studio/components/interfaces/Settings/API/JWTSettings.tsx +++ b/apps/studio/components/interfaces/Settings/API/JWTSettings.tsx @@ -265,41 +265,39 @@ const JWTSettings = () => {
} > - -
-

- Create a custom JWT secret. Make sure it is a strong combination of characters that - cannot be guessed easily. -

- - - This will invalidate all existing API keys - - Generating a new JWT secret will invalidate all{' '} - of your API keys, including your service_role and{' '} - anon keys. Your project will also be restarted - during this process, which will terminate any existing connections. - - - setCustomToken(e.target.value)} - value={customToken} - icon={} - type={showCustomTokenInput ? 'text' : 'password'} - className="w-full text-left" - label="Custom JWT secret" - descriptionText="Minimally 32 characters long, '@' and '$' are not allowed." - actions={ -
-
- } - /> -
+ +

+ Create a custom JWT secret. Make sure it is a strong combination of characters that + cannot be guessed easily. +

+ + + This will invalidate all existing API keys + + Generating a new JWT secret will invalidate all of + your API keys, including your service_role and{' '} + anon keys. Your project will also be restarted during + this process, which will terminate any existing connections. + + + setCustomToken(e.target.value)} + value={customToken} + icon={} + type={showCustomTokenInput ? 'text' : 'password'} + className="w-full text-left" + label="Custom JWT secret" + descriptionText="Minimally 32 characters long, '@' and '$' are not allowed." + actions={ +
+
+ } + />
diff --git a/apps/studio/components/interfaces/Settings/Addons/ComputeInstanceSidePanel.tsx b/apps/studio/components/interfaces/Settings/Addons/ComputeInstanceSidePanel.tsx index abadf017f52..b6619f8804d 100644 --- a/apps/studio/components/interfaces/Settings/Addons/ComputeInstanceSidePanel.tsx +++ b/apps/studio/components/interfaces/Settings/Addons/ComputeInstanceSidePanel.tsx @@ -470,15 +470,13 @@ const ComputeInstanceSidePanel = () => { header="Confirm to upgrade compute instance now" > -
- - Your project will be unavailable for up to 2 minutes while the changes take place. - -
+ + Your project will be unavailable for up to 2 minutes while the changes take place. +
diff --git a/apps/studio/components/interfaces/Settings/Database/DatabaseSettings/ConfirmDisableReadOnlyModal.tsx b/apps/studio/components/interfaces/Settings/Database/DatabaseSettings/ConfirmDisableReadOnlyModal.tsx index 1ed5977e7d0..70ba0437937 100644 --- a/apps/studio/components/interfaces/Settings/Database/DatabaseSettings/ConfirmDisableReadOnlyModal.tsx +++ b/apps/studio/components/interfaces/Settings/Database/DatabaseSettings/ConfirmDisableReadOnlyModal.tsx @@ -34,7 +34,7 @@ const ConfirmDisableReadOnlyModeModal = ({ disableReadOnlyMode({ projectRef: ref }) }} > - +

This will temporarily allow writes to your database for the{' '} next 15 minutes, during which you can reduce your diff --git a/apps/studio/components/interfaces/Settings/Database/DatabaseSettings/ResetDbPassword.tsx b/apps/studio/components/interfaces/Settings/Database/DatabaseSettings/ResetDbPassword.tsx index dcaba5cd42e..0407bb9eefe 100644 --- a/apps/studio/components/interfaces/Settings/Database/DatabaseSettings/ResetDbPassword.tsx +++ b/apps/studio/components/interfaces/Settings/Database/DatabaseSettings/ResetDbPassword.tsx @@ -150,45 +150,41 @@ const ResetDbPassword = ({ disabled = false }) => { loading={isUpdatingPassword} onCancel={() => setShowResetDbPass(false)} > - -

- 0} - onChange={onDbPassChange} - error={passwordStrengthWarning} - // @ts-ignore - descriptionText={ - - } - /> -
+ + 0} + onChange={onDbPassChange} + error={passwordStrengthWarning} + // @ts-ignore + descriptionText={ + + } + /> - -
- - -
+ + + diff --git a/apps/studio/components/interfaces/Settings/Database/DiskSizeConfiguration.tsx b/apps/studio/components/interfaces/Settings/Database/DiskSizeConfiguration.tsx index 8ed19d53aa5..16b3c82de11 100644 --- a/apps/studio/components/interfaces/Settings/Database/DiskSizeConfiguration.tsx +++ b/apps/studio/components/interfaces/Settings/Database/DiskSizeConfiguration.tsx @@ -196,7 +196,7 @@ Read more about [disk management](https://supabase.com/docs/guides/platform/data )} Increase Disk Storage Size} + header="Increase Disk Storage Size" size="medium" visible={showResetDbPass} loading={isUpdatingDiskSize} @@ -230,47 +230,43 @@ Read more about [disk management](https://supabase.com/docs/guides/platform/data ) : ( <> - -
- - - - This operation is only possible every 6 hours - - - {isAbleToResizeDatabase - ? `Upon updating your disk size, the next disk size update will only be available from ${dayjs().format( - 'DD MMM YYYY, HH:mm (ZZ)' - )}` - : `Your database was last resized at ${dayjs(lastDatabaseResizeAt).format( - 'DD MMM YYYY, HH:mm (ZZ)' - )}. You can resize your database again in approximately ${formattedTimeTillNextAvailableResize}`} - - - -
+ + + + + This operation is only possible every 6 hours + + + {isAbleToResizeDatabase + ? `Upon updating your disk size, the next disk size update will only be available from ${dayjs().format( + 'DD MMM YYYY, HH:mm (ZZ)' + )}` + : `Your database was last resized at ${dayjs(lastDatabaseResizeAt).format( + 'DD MMM YYYY, HH:mm (ZZ)' + )}. You can resize your database again in approximately ${formattedTimeTillNextAvailableResize}`} + + + - -
- - -
+ + + ) diff --git a/apps/studio/components/interfaces/Settings/Database/NetworkRestrictions/AddRestrictionModal.tsx b/apps/studio/components/interfaces/Settings/Database/NetworkRestrictions/AddRestrictionModal.tsx index c12b49908db..b0bfcabe7a4 100644 --- a/apps/studio/components/interfaces/Settings/Database/NetworkRestrictions/AddRestrictionModal.tsx +++ b/apps/studio/components/interfaces/Settings/Database/NetworkRestrictions/AddRestrictionModal.tsx @@ -156,113 +156,108 @@ const AddRestrictionModal = ({ return ( <> - -
-

- This will add an IP address range to a list of allowed ranges that can access - your database. -

- -
-
- -
-
- -

CIDR Block Size

- - - - - - - -
- - Classless inter-domain routing (CIDR) notation is the notation - used to identify networks and hosts in the networks. The block - size tells us how many bits we need to take for the network - prefix, and is a value between 0 to{' '} - {type === 'IPv4' - ? IPV4_MAX_CIDR_BLOCK_SIZE - : IPV6_MAX_CIDR_BLOCK_SIZE} - . - -
-
-
-
-
- } - id="cidrBlockSize" - name="cidrBlockSize" - type="number" - placeholder={ - type === 'IPv4' - ? IPV4_MAX_CIDR_BLOCK_SIZE.toString() - : IPV6_MAX_CIDR_BLOCK_SIZE.toString() - } - min={0} - max={type === 'IPv4' ? IPV4_MAX_CIDR_BLOCK_SIZE : IPV6_MAX_CIDR_BLOCK_SIZE} - /> -
+ +

+ This will add an IP address range to a list of allowed ranges that can access your + database. +

+ +
+
+ +
+
+ +

CIDR Block Size

+ + + + + + + +
+ + Classless inter-domain routing (CIDR) notation is the notation + used to identify networks and hosts in the networks. The block + size tells us how many bits we need to take for the network + prefix, and is a value between 0 to{' '} + {type === 'IPv4' + ? IPV4_MAX_CIDR_BLOCK_SIZE + : IPV6_MAX_CIDR_BLOCK_SIZE} + . + +
+
+
+
+
+ } + id="cidrBlockSize" + name="cidrBlockSize" + type="number" + placeholder={ + type === 'IPv4' + ? IPV4_MAX_CIDR_BLOCK_SIZE.toString() + : IPV6_MAX_CIDR_BLOCK_SIZE.toString() + } + min={0} + max={type === 'IPv4' ? IPV4_MAX_CIDR_BLOCK_SIZE : IPV6_MAX_CIDR_BLOCK_SIZE} + />
{isValidCIDR ? ( - -
-

- The address range {normalizedAddress} will be - restricted -

-

- Selected address space: {addressRange.start}{' '} - to {addressRange.end}{' '} -

-

- Number of addresses: {availableAddresses} -

-
+ +

+ The address range {normalizedAddress} will be + restricted +

+

+ Selected address space: {addressRange.start} to{' '} + {addressRange.end}{' '} +

+

+ Number of addresses: {availableAddresses} +

) : ( -
-
-

- A summary of your restriction will be shown here after entering a valid IP - address and CIDR block size. IP addresses will also be normalized. -

-
+
+

+ A summary of your restriction will be shown here after entering a valid IP + address and CIDR block size. IP addresses will also be normalized. +

)} -
+ + -
+ ) }} diff --git a/apps/studio/components/interfaces/Settings/Database/NetworkRestrictions/AllowAllModal.tsx b/apps/studio/components/interfaces/Settings/Database/NetworkRestrictions/AllowAllModal.tsx index bbd0cd23c60..6ab6806e6e6 100644 --- a/apps/studio/components/interfaces/Settings/Database/NetworkRestrictions/AllowAllModal.tsx +++ b/apps/studio/components/interfaces/Settings/Database/NetworkRestrictions/AllowAllModal.tsx @@ -33,21 +33,20 @@ const AllowAllModal = ({ visible, onClose }: AllowAllModalProps) => { onCancel={onClose} header="Allow access from all IP addresses" > - -
-

- This will allow any IP address to access your project's database. Are you sure? -

-
+ +

+ This will allow any IP address to access your project's database. Are you sure? +

-
+ + -
+
) } diff --git a/apps/studio/components/interfaces/Settings/Database/NetworkRestrictions/DisallowAllModal.tsx b/apps/studio/components/interfaces/Settings/Database/NetworkRestrictions/DisallowAllModal.tsx index a8cab34a910..ef6c5bf31be 100644 --- a/apps/studio/components/interfaces/Settings/Database/NetworkRestrictions/DisallowAllModal.tsx +++ b/apps/studio/components/interfaces/Settings/Database/NetworkRestrictions/DisallowAllModal.tsx @@ -31,28 +31,27 @@ const DisallowAllModal = ({ visible, onClose }: DisallowAllModalProps) => { onCancel={onClose} header="Restrict access from all IP addresses" > - -
-

- This will prevent any external IP addresses from accessing your project's database. Are - you sure? -

- -
+ +

+ This will prevent any external IP addresses from accessing your project's database. Are + you sure? +

+
-
+ + -
+
) } diff --git a/apps/studio/components/interfaces/Settings/Database/NetworkRestrictions/RemoveRestrictionModal.tsx b/apps/studio/components/interfaces/Settings/Database/NetworkRestrictions/RemoveRestrictionModal.tsx index 77f09cad631..1c9fbd135a7 100644 --- a/apps/studio/components/interfaces/Settings/Database/NetworkRestrictions/RemoveRestrictionModal.tsx +++ b/apps/studio/components/interfaces/Settings/Database/NetworkRestrictions/RemoveRestrictionModal.tsx @@ -66,31 +66,29 @@ const RemoveRestrictionModal = ({ onCancel={onClose} header="Confirm to remove restriction" > - -
-

- The IPv4 address {selectedRestriction} will be removed - from your list of network restrictions - {isRemovingOnlyRestriction - ? '.' - : ", and no longer have access to your project's database."} -

- {isRemovingOnlyRestriction && ( - - Removing all network restrictions will default to your database being accessible from - all IP addresses. - - )} -
+ +

+ The IPv4 address {selectedRestriction} will be removed + from your list of network restrictions + {isRemovingOnlyRestriction + ? '.' + : ", and no longer have access to your project's database."} +

+ {isRemovingOnlyRestriction && ( + + Removing all network restrictions will default to your database being accessible from + all IP addresses. + + )}
-
+ -
+
) } diff --git a/apps/studio/components/interfaces/Settings/General/Infrastructure/ProjectUpgradeAlert/ProjectUpgradeAlert.tsx b/apps/studio/components/interfaces/Settings/General/Infrastructure/ProjectUpgradeAlert/ProjectUpgradeAlert.tsx index 970a4188a30..5cb8ad5ea72 100644 --- a/apps/studio/components/interfaces/Settings/General/Infrastructure/ProjectUpgradeAlert/ProjectUpgradeAlert.tsx +++ b/apps/studio/components/interfaces/Settings/General/Infrastructure/ProjectUpgradeAlert/ProjectUpgradeAlert.tsx @@ -99,118 +99,117 @@ const ProjectUpgradeAlert = () => { return ( <> -
- -
-

All services are going offline.

-

- You will not be able to downgrade back to Postgres {currentPgVersion}. -

- + +
+

All services are going offline.

+

+ You will not be able to downgrade back to Postgres {currentPgVersion}. +

+ + + + Your project will be offline for up to {durationEstimateHours} hour + {durationEstimateHours === 1 ? '' : 's'} + + +

+ It is advised to upgrade at a time when there will be minimal impact for + your application. +

+
+
+ {(data?.potential_breaking_changes ?? []).length > 0 && ( + - - Your project will be offline for up to {durationEstimateHours} hour - {durationEstimateHours === 1 ? '' : 's'} - - + Breaking changes +

- It is advised to upgrade at a time when there will be minimal impact for - your application. + Your project will be upgraded across major versions of Postgres. This + may involve breaking changes.

+ +
+ +
- {(data?.potential_breaking_changes ?? []).length > 0 && ( - - - Breaking changes - -

- Your project will be upgraded across major versions of Postgres. This - may involve breaking changes. -

- -
- -
-
-
- )} - {legacyAuthCustomRoles.length > 0 && ( - - - - Custom Postgres roles will not work automatically after upgrade - - -

You must run a series of commands after upgrading.

-

- This is because new Postgres versions use scram-sha-256 authentication - by default and do not support md5, as it has been deprecated. -

-
-

Run the following commands after the upgrade:

-
- - {legacyAuthCustomRoles.map((role) => ( -
- ALTER ROLE {role} WITH - PASSWORD 'newpassword'; -
- ))} -
-
-
-
- -
-
-
- )} - 0 && ( + - {data?.target_upgrade_versions.map((version) => ( - - {version.postgres_version} ( - {version.app_version.split('supabase-postgres-')[1]}) - - ))} - -
-
-
-
+ + + Custom Postgres roles will not work automatically after upgrade + + +

You must run a series of commands after upgrading.

+

+ This is because new Postgres versions use scram-sha-256 authentication + by default and do not support md5, as it has been deprecated. +

+
+

Run the following commands after the upgrade:

+
+ + {legacyAuthCustomRoles.map((role) => ( +
+ ALTER ROLE {role} WITH + PASSWORD 'newpassword'; +
+ ))} +
+
+
+
+ +
+
+ + )} + + {data?.target_upgrade_versions.map((version) => ( + + {version.postgres_version} ( + {version.app_version.split('supabase-postgres-')[1]}) + + ))} + +
+
+ + -
+ ) }} diff --git a/apps/studio/components/interfaces/Settings/General/TransferProjectPanel/TransferProjectButton.tsx b/apps/studio/components/interfaces/Settings/General/TransferProjectPanel/TransferProjectButton.tsx index 1e9c0a7f746..4c00387634c 100644 --- a/apps/studio/components/interfaces/Settings/General/TransferProjectPanel/TransferProjectButton.tsx +++ b/apps/studio/components/interfaces/Settings/General/TransferProjectPanel/TransferProjectButton.tsx @@ -7,6 +7,7 @@ import { Alert, Button, IconAlertCircle, + IconInfo, IconLoader, IconShield, IconTool, @@ -21,6 +22,7 @@ import { useProjectTransferMutation } from 'data/projects/project-transfer-mutat import { useProjectTransferPreviewQuery } from 'data/projects/project-transfer-preview-query' import { useCheckPermissions, useFlag, useSelectedProject } from 'hooks' import { formatCurrency } from 'lib/helpers' +import { InfoIcon } from 'ui-patterns/Icons/StatusIcons' const TransferProjectButton = () => { const project = useSelectedProject() @@ -115,7 +117,7 @@ const TransferProjectButton = () => { onCancel={() => toggle()} visible={isOpen} loading={isTransferring} - size={'xlarge'} + size={'large'} header={`Transfer project ${project?.name}`} customFooter={
@@ -133,233 +135,221 @@ const TransferProjectButton = () => {
} > -
- -

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

+ +

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

-

Transferring considerations:

+

Transferring considerations:

-
    -
  • - - - -
    -

    No downtime

    -

    There is no downtime or restrictions involved when transferring a project.

    -
    -
  • +
      +
    • + + + +
      +

      No downtime

      +

      There is no downtime or restrictions involved when transferring a project.

      +
      +
    • -
    • - - - -
      -

      Permissions

      -

      - Depending on your role in the target organization, your level of permissions may - change after transfer. -

      -
      -
    • - -
    • - - - -
      -

      Features

      -

      - Moving your project to an organization with a smaller subscription plan may - result in the loss of certain features (i.e. image transformations). -

      -
      -
    • -
    - - - {organizations && ( -
    - {organizations.length === 0 ? ( -
    - You do not have any organizations with an organization-based - subscription. -
    - ) : ( - setSelectedOrg(slug)} - placeholder="Select Organization" - > - - Select Organization - - {organizations.map((x: any) => ( - } - > - {x.name} - - ))} - - )} - -

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

  • + + + +
    +

    Permissions

    +

    + Depending on your role in the target organization, your level of permissions may + change after transfer.

    - )} - +
  • - - -
    - {transferPreviewData && transferPreviewData.valid && ( -
    - {transferPreviewData.source_subscription_plan !== - transferPreviewData.target_subscription_plan ? ( -
    -

    - Your project is currently on the{' '} - {transferPreviewData.source_subscription_plan} plan, whereas the target - organization uses the {transferPreviewData.target_subscription_plan} plan. -

    -
    - ) : ( -
    - Your project and the target organization are both on the{' '} - {transferPreviewData.source_subscription_plan} subscription plan. -
    - )} +
  • + + + +
    +

    Features

    +

    + Moving your project to an organization with a smaller subscription plan may result + in the loss of certain features (i.e. image transformations). +

    +
    +
  • +
+
+ + + {organizations && ( +
+ {organizations.length === 0 ? ( +
+ You do not have any organizations with an organization-based + subscription. +
+ ) : ( + setSelectedOrg(slug)} + placeholder="Select Organization" + > + + Select Organization + + {organizations.map((x: any) => ( + } + > + {x.name} + + ))} + + )} -
- {transferPreviewData.credits_on_source_organization === 0 ? ( - - {' '} - Your current organization won't be granted any prorated credits. - - ) : ( - - {' '} - Your current organization will be granted{' '} - - ${transferPreviewData.credits_on_source_organization} - {' '} - in credits as proration. - - )} - {transferPreviewData.costs_on_target_organization === 0 ? ( - - {' '} - The target organization won't be charged any immediate upfront payment. - - ) : ( - - {' '} - The target organization will be billed{' '} - - {formatCurrency(transferPreviewData.costs_on_target_organization)} - {' '} - immediately to prorate for the remainder of the billing period. - - )} -
+

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

+
+ )} +
+ + + + {transferPreviewData && transferPreviewData.valid && ( +
+ {transferPreviewData.source_subscription_plan !== + transferPreviewData.target_subscription_plan ? ( +
+

+ Your project is currently on the{' '} + {transferPreviewData.source_subscription_plan} plan, whereas the target + organization uses the {transferPreviewData.target_subscription_plan} plan. +

+
+ ) : ( +
+ Your project and the target organization are both on the{' '} + {transferPreviewData.source_subscription_plan} subscription plan.
)} - {transferPreviewData && transferPreviewData.warnings.length > 0 && ( - -
- {transferPreviewData.warnings.map((warning) => ( -

{warning.message}

- ))} -
-
- )} - {transferPreviewData && transferPreviewData.errors.length > 0 && ( - -
- {transferPreviewData.errors.map((error) => ( -

{error.message}

- ))} -
- {transferPreviewData.members_exceeding_free_project_limit.length > 0 && ( -
-

- These members have reached their maximum limits for the number of active - Free plan projects within organizations where they are an administrator or - owner: -

-
    - {(transferPreviewData.members_exceeding_free_project_limit || []).map( - (member, idx: number) => ( -
  • - {member.name} (Limit: {member.limit} free projects) -
  • - ) - )} -
-

- These members will need to either delete, pause, or upgrade one or more of - their projects before you can downgrade this project. -

-
- )} -
- )} - {transferPreviewError && !transferError && ( - -

{transferPreviewError.message}

-
- )} - {transferError && ( - -

{transferError.message}

-
- )} + +
+ {transferPreviewData.credits_on_source_organization === 0 ? ( + Your current organization won't be granted any prorated credits. + ) : ( + + {' '} + Your current organization will be granted{' '} + + ${transferPreviewData.credits_on_source_organization} + {' '} + in credits as proration. + + )} + {transferPreviewData.costs_on_target_organization === 0 ? ( + + {' '} + The target organization won't be charged any immediate upfront payment. + + ) : ( + + {' '} + The target organization will be billed{' '} + + {formatCurrency(transferPreviewData.costs_on_target_organization)} + {' '} + immediately to prorate for the remainder of the billing period. + + )} +
-
-
-
+ )} + {transferPreviewData && transferPreviewData.warnings.length > 0 && ( + +
+ {transferPreviewData.warnings.map((warning) => ( +

{warning.message}

+ ))} +
+
+ )} + {transferPreviewData && transferPreviewData.errors.length > 0 && ( + +
+ {transferPreviewData.errors.map((error) => ( +

{error.message}

+ ))} +
+ {transferPreviewData.members_exceeding_free_project_limit.length > 0 && ( +
+

+ These members have reached their maximum limits for the number of active Free + plan projects within organizations where they are an administrator or owner: +

+
    + {(transferPreviewData.members_exceeding_free_project_limit || []).map( + (member, idx: number) => ( +
  • + {member.name} (Limit: {member.limit} free projects) +
  • + ) + )} +
+

+ These members will need to either delete, pause, or upgrade one or more of + their projects before you can downgrade this project. +

+
+ )} +
+ )} + {transferPreviewError && !transferError && ( + +

{transferPreviewError.message}

+
+ )} + {transferError && ( + +

{transferError.message}

+
+ )} + + ) diff --git a/apps/studio/components/interfaces/Settings/Logs/Logs.UpdateSavedQueryModal.tsx b/apps/studio/components/interfaces/Settings/Logs/Logs.UpdateSavedQueryModal.tsx index 11f84cf24df..e7efb94920e 100644 --- a/apps/studio/components/interfaces/Settings/Logs/Logs.UpdateSavedQueryModal.tsx +++ b/apps/studio/components/interfaces/Settings/Logs/Logs.UpdateSavedQueryModal.tsx @@ -41,7 +41,7 @@ export const UpdateSavedQueryModal = ({ onSubmit={onSubmit} > {({ isSubmitting }: { isSubmitting: boolean }) => ( -
+ <> @@ -55,17 +55,15 @@ export const UpdateSavedQueryModal = ({ /> - -
- - -
+ + + -
+ )} diff --git a/apps/studio/components/interfaces/Settings/Logs/UpgradePrompt.tsx b/apps/studio/components/interfaces/Settings/Logs/UpgradePrompt.tsx index bddf214365d..813a351325a 100644 --- a/apps/studio/components/interfaces/Settings/Logs/UpgradePrompt.tsx +++ b/apps/studio/components/interfaces/Settings/Logs/UpgradePrompt.tsx @@ -22,53 +22,47 @@ const UpgradePrompt: React.FC = ({ show, setShowUpgradePrompt }) => { header="Log retention" onCancel={() => setShowUpgradePrompt(false)} > -
- -
-

- Logs can be retained up to a duration of 3 months depending on the plan that your - project is on. -

-
-
-

Plan

-

Retention duration

+ +
+

+ Logs can be retained up to a duration of 3 months depending on the plan that your + project is on. +

+
+
+

Plan

+

Retention duration

+
+
+
+

Free

+

{TIER_QUERY_LIMITS.FREE.text}

-
-
-

Free

-

{TIER_QUERY_LIMITS.FREE.text}

-
-
-

Pro

-

{TIER_QUERY_LIMITS.PRO.text}

-
-
-

Team

-

{TIER_QUERY_LIMITS.TEAM.text}

-
-
-

Enterprise

-

{TIER_QUERY_LIMITS.ENTERPRISE.text}

-
+
+

Pro

+

{TIER_QUERY_LIMITS.PRO.text}

+
+
+

Team

+

{TIER_QUERY_LIMITS.TEAM.text}

+
+
+

Enterprise

+

{TIER_QUERY_LIMITS.ENTERPRISE.text}

- - - -
- - -
-
-
+
+
+ + + + + ) } diff --git a/apps/studio/components/interfaces/Settings/Vault/Keys/EncryptionKeysManagement.tsx b/apps/studio/components/interfaces/Settings/Vault/Keys/EncryptionKeysManagement.tsx index 8e5f4c4790d..6fa6a7996b4 100644 --- a/apps/studio/components/interfaces/Settings/Vault/Keys/EncryptionKeysManagement.tsx +++ b/apps/studio/components/interfaces/Settings/Vault/Keys/EncryptionKeysManagement.tsx @@ -292,32 +292,28 @@ const EncryptionKeysManagement = () => { onCancel={() => setSelectedKeyToRemove(undefined)} onConfirm={confirmDeleteKey} loading={isDeleting} - header={
Confirm to delete key
} + header="Confirm to delete key" > -
- -
- - Do ensure that the key is not currently in use to prevent any issues. - -

- The following key will be permanently removed and cannot be recovered. -

-
-

- {selectedKeyToRemove?.name ?? DEFAULT_KEY_NAME} -

-

- ID: {selectedKeyToRemove?.id} -

-
-
-
-
+ + + Do ensure that the key is not currently in use to prevent any issues. + +

+ The following key will be permanently removed and cannot be recovered. +

+
+

+ {selectedKeyToRemove?.name ?? DEFAULT_KEY_NAME} +

+

+ ID: {selectedKeyToRemove?.id} +

+
+
{ size="medium" visible={showAddKeyModal} onCancel={() => setShowAddKeyModal(false)} - header={
Add a new key
} + header="Add a new key" >
{ > {() => { return ( -
- -

- Provide a name for your key for easier identification. -

-
- -
+ <> + +

Provide a name for your key for easier identification.

+
- -
- - -
+ + + -
+ ) }}
diff --git a/apps/studio/components/interfaces/Settings/Vault/Secrets/AddNewSecretModal.tsx b/apps/studio/components/interfaces/Settings/Vault/Secrets/AddNewSecretModal.tsx index 4ac0451435d..1aaf7967d53 100644 --- a/apps/studio/components/interfaces/Settings/Vault/Secrets/AddNewSecretModal.tsx +++ b/apps/studio/components/interfaces/Settings/Vault/Secrets/AddNewSecretModal.tsx @@ -84,7 +84,7 @@ const AddNewSecretModal = ({ visible, onClose }: AddNewSecretModalProps) => { size="medium" visible={visible} onCancel={onClose} - header={
Add new secret
} + header="Add new secret" >
{ > {({ isSubmitting }: any) => { return ( -
- -
- - - -
- } - /> -
+ <> + + + + +
+ } + /> - -
- - } - url="https://github.com/supabase/vault" - urlLabel="Vault documentation" - title="What is a key?" - description={ -
-

- Keys are used to encrypt data inside your database, and every secret in - the Vault is encrypted with a key. -

-

- You may create different keys for different purposes, such as one for - encrypting user data, and another for application data. -

-
- } - /> -
+ + + } + url="https://github.com/supabase/vault" + urlLabel="Vault documentation" + title="What is a key?" + description={ +
+

+ Keys are used to encrypt data inside your database, and every secret in the + Vault is encrypted with a key. +

+

+ You may create different keys for different purposes, such as one for + encrypting user data, and another for application data. +

+
+ } + />
- -
- - -
+ + + -
+ ) }} diff --git a/apps/studio/components/interfaces/Settings/Vault/Secrets/DeleteSecretModal.tsx b/apps/studio/components/interfaces/Settings/Vault/Secrets/DeleteSecretModal.tsx index 1ee4dc068d4..d9e843c31f7 100644 --- a/apps/studio/components/interfaces/Settings/Vault/Secrets/DeleteSecretModal.tsx +++ b/apps/studio/components/interfaces/Settings/Vault/Secrets/DeleteSecretModal.tsx @@ -42,24 +42,19 @@ const DeleteSecretModal = ({ selectedSecret, onClose }: DeleteSecretModalProps) onCancel={onClose} onConfirm={onConfirmDeleteSecret} loading={isDeleting} - header={
Confirm to delete secret
} + header="Confirm to delete secret" > -
- -
-

- The following secret will be permanently removed and cannot be recovered. Are you - sure? -

-
-

{selectedSecret?.description}

-

- ID: {selectedSecret?.key_id} -

-
-
-
-
+ +

+ The following secret will be permanently removed and cannot be recovered. Are you sure? +

+
+

{selectedSecret?.description}

+

+ ID: {selectedSecret?.key_id} +

+
+
) } diff --git a/apps/studio/components/interfaces/Settings/Vault/Secrets/EditSecretModal.tsx b/apps/studio/components/interfaces/Settings/Vault/Secrets/EditSecretModal.tsx index 412714ee879..cfd5355d51d 100644 --- a/apps/studio/components/interfaces/Settings/Vault/Secrets/EditSecretModal.tsx +++ b/apps/studio/components/interfaces/Settings/Vault/Secrets/EditSecretModal.tsx @@ -129,56 +129,50 @@ const EditSecretModal = ({ selectedSecret, onClose }: EditSecretModalProps) => { ) return isLoadingSecretValue ? ( -
+ -
+ ) : ( -
- -
- - - -
- } - /> -
+ <> + + + + +
+ } + />
- -
- -
+ + - -
- - -
+ + + -
+ ) }} diff --git a/apps/studio/components/interfaces/Storage/CreateBucketModal.tsx b/apps/studio/components/interfaces/Storage/CreateBucketModal.tsx index e108f6e4c47..de28da34603 100644 --- a/apps/studio/components/interfaces/Storage/CreateBucketModal.tsx +++ b/apps/studio/components/interfaces/Storage/CreateBucketModal.tsx @@ -116,7 +116,7 @@ const CreateBucketModal = ({ visible, onClose }: CreateBucketModalProps) => { > {({ values }: { values: any }) => { return ( -
+ <> {
-
-
+
+
{
-
- -
- - -
+ + + + -
+ ) }} diff --git a/apps/studio/components/interfaces/Storage/EditBucketModal.tsx b/apps/studio/components/interfaces/Storage/EditBucketModal.tsx index 1a41f7aee1a..a49687c10c7 100644 --- a/apps/studio/components/interfaces/Storage/EditBucketModal.tsx +++ b/apps/studio/components/interfaces/Storage/EditBucketModal.tsx @@ -112,7 +112,7 @@ const EditBucketModal = ({ visible, bucket, onClose }: EditBucketModalProps) => }, [visible]) return ( -
+ <>
-
- -
- - -
+ + + + -
+ ) }} diff --git a/apps/studio/components/layouts/AppLayout/EnableBranchingButton/BranchingPlanNotice.tsx b/apps/studio/components/layouts/AppLayout/EnableBranchingButton/BranchingPlanNotice.tsx index b818fecf66f..e548262fede 100644 --- a/apps/studio/components/layouts/AppLayout/EnableBranchingButton/BranchingPlanNotice.tsx +++ b/apps/studio/components/layouts/AppLayout/EnableBranchingButton/BranchingPlanNotice.tsx @@ -12,7 +12,7 @@ const BranchingPlanNotice = () => { return ( - + Database branching is only available on the Pro plan and above diff --git a/apps/studio/components/layouts/AppLayout/EnableBranchingButton/EnableBranchingModal.tsx b/apps/studio/components/layouts/AppLayout/EnableBranchingButton/EnableBranchingModal.tsx index a1920b1de5f..ca8f0b05f55 100644 --- a/apps/studio/components/layouts/AppLayout/EnableBranchingButton/EnableBranchingModal.tsx +++ b/apps/studio/components/layouts/AppLayout/EnableBranchingButton/EnableBranchingModal.tsx @@ -138,7 +138,8 @@ const EnableBranchingModal = () => { visible={snap.showEnableBranchingModal} onCancel={() => snap.setShowEnableBranchingModal(false)} className="!bg !max-w-[40rem]" - size="xlarge" + size="medium" + hideClose >
{ onSubmit={form.handleSubmit(onSubmit)} onChange={() => setIsValid(false)} > - +
@@ -207,14 +208,14 @@ const EnableBranchingModal = () => { {!hasPitrEnabled && } )} - +

Please keep in mind the following:

-
- +
+
@@ -230,8 +231,8 @@ const EnableBranchingModal = () => {
-
- +
+
@@ -251,29 +252,27 @@ const EnableBranchingModal = () => { )} - -
- - -
+ + + diff --git a/apps/studio/components/layouts/ProjectLayout/ProjectPausedState.tsx b/apps/studio/components/layouts/ProjectLayout/ProjectPausedState.tsx index 81aed121ef9..17b09b04543 100644 --- a/apps/studio/components/layouts/ProjectLayout/ProjectPausedState.tsx +++ b/apps/studio/components/layouts/ProjectLayout/ProjectPausedState.tsx @@ -175,41 +175,35 @@ const ProjectPausedState = ({ product }: ProjectPausedStateProps) => { header="Your organization has members who have exceeded their free project limits" onCancel={() => setShowFreeProjectLimitWarning(false)} > -
- -
-

- The following members have reached their maximum limits for the number of active - free plan projects within organizations where they are an administrator or owner: -

-
    - {(membersExceededLimit || []).map((member, idx: number) => ( -
  • - {member.username || member.primary_email} (Limit: {member.free_project_limit}{' '} - free projects) -
  • - ))} -
-

- These members will need to either delete, pause, or upgrade one or more of these - projects before you're able to unpause this project. -

-
-
- - -
- -
-
-
+ +

+ The following members have reached their maximum limits for the number of active free + plan projects within organizations where they are an administrator or owner: +

+
    + {(membersExceededLimit || []).map((member, idx: number) => ( +
  • + {member.username || member.primary_email} (Limit: {member.free_project_limit} free + projects) +
  • + ))} +
+

+ These members will need to either delete, pause, or upgrade one or more of these + projects before you're able to unpause this project. +

+
+ + + + ) diff --git a/apps/studio/components/to-be-cleaned/Storage/StorageExplorer/ConfirmDeleteModal.tsx b/apps/studio/components/to-be-cleaned/Storage/StorageExplorer/ConfirmDeleteModal.tsx index c782c431f27..ee529dcc9ac 100644 --- a/apps/studio/components/to-be-cleaned/Storage/StorageExplorer/ConfirmDeleteModal.tsx +++ b/apps/studio/components/to-be-cleaned/Storage/StorageExplorer/ConfirmDeleteModal.tsx @@ -58,11 +58,9 @@ const ConfirmDeleteModal = ({ } > -
- - {description} - -
+ + {description} +
) diff --git a/apps/studio/components/to-be-cleaned/Storage/StorageExplorer/CustomExpiryModal.tsx b/apps/studio/components/to-be-cleaned/Storage/StorageExplorer/CustomExpiryModal.tsx index 323f90fef72..dbb6c6fff08 100644 --- a/apps/studio/components/to-be-cleaned/Storage/StorageExplorer/CustomExpiryModal.tsx +++ b/apps/studio/components/to-be-cleaned/Storage/StorageExplorer/CustomExpiryModal.tsx @@ -58,51 +58,47 @@ const CustomExpiryModal = ({ onCopyUrl }: CustomExpiryModalProps) => { > {({ values, isSubmitting }: { values: any; isSubmitting: boolean }) => ( <> -
- -

- Enter the duration for which the URL will be valid for: -

-
- - - - days - - - weeks - - - months - - - years - - -
- {values.expiresIn !== '' && ( -

- URL will expire on{' '} - {dayjs().add(values.expiresIn, values.units).format(DATETIME_FORMAT)} -

- )} -
-
- -
- - +

+ Enter the duration for which the URL will be valid for: +

+
+ + + + days + + + weeks + + + months + + + years + +
+ {values.expiresIn !== '' && ( +

+ URL will expire on{' '} + {dayjs().add(values.expiresIn, values.units).format(DATETIME_FORMAT)} +

+ )} + + + + + )} diff --git a/apps/studio/components/to-be-cleaned/Storage/StorageExplorer/MoveItemsModal.tsx b/apps/studio/components/to-be-cleaned/Storage/StorageExplorer/MoveItemsModal.tsx index ac3d2c8edf2..6bbef352986 100644 --- a/apps/studio/components/to-be-cleaned/Storage/StorageExplorer/MoveItemsModal.tsx +++ b/apps/studio/components/to-be-cleaned/Storage/StorageExplorer/MoveItemsModal.tsx @@ -65,7 +65,7 @@ const MoveItemsModal = ({ } > -
+
-
+ <> +
-
+ ) } diff --git a/apps/studio/components/to-be-cleaned/Storage/StoragePolicies/StoragePoliciesReview.tsx b/apps/studio/components/to-be-cleaned/Storage/StoragePolicies/StoragePoliciesReview.tsx index 7a71e07a437..fde162aa5b5 100644 --- a/apps/studio/components/to-be-cleaned/Storage/StoragePolicies/StoragePoliciesReview.tsx +++ b/apps/studio/components/to-be-cleaned/Storage/StoragePolicies/StoragePoliciesReview.tsx @@ -29,34 +29,33 @@ const StoragePoliciesReview = ({ return ( <> - -
-
-
-

- These are the SQL statements that will be used to create your policies. The suffix - appended to the end of your policy name ([hashString]_[number]) just - functions as a unique identifier for each of your policies. -

-
-
-
- {policyStatements.length === 0 && } - {policyStatements.map((policy, idx) => { - let formattedSQLStatement = policy.statement || '' - return ( -
- {policy.description} -
- -
-
- ) - })} + +
+
+

+ These are the SQL statements that will be used to create your policies. The suffix + appended to the end of your policy name ([hashString]_[number]) just + functions as a unique identifier for each of your policies. +

+
+ {policyStatements.length === 0 && } + {policyStatements.map((policy, idx) => { + let formattedSQLStatement = policy.statement || '' + return ( +
+ {policy.description} +
+ +
+
+ ) + })} +
-
+ + @@ -65,7 +64,7 @@ const StoragePoliciesReview = ({ Save policy )} -
+ ) } diff --git a/apps/studio/components/to-be-cleaned/Storage/StorageSettings/CreateCredentialModal.tsx b/apps/studio/components/to-be-cleaned/Storage/StorageSettings/CreateCredentialModal.tsx index 2a3da7be680..7d2f1af98ef 100644 --- a/apps/studio/components/to-be-cleaned/Storage/StorageSettings/CreateCredentialModal.tsx +++ b/apps/studio/components/to-be-cleaned/Storage/StorageSettings/CreateCredentialModal.tsx @@ -159,9 +159,8 @@ export const CreateCredentialModal = ({ visible, onOpenChange }: CreateCredentia )} /> - - diff --git a/apps/studio/components/to-be-cleaned/Storage/StorageSettings/StorageSettings.tsx b/apps/studio/components/to-be-cleaned/Storage/StorageSettings/StorageSettings.tsx index 88bcee856e0..df2960c61a9 100644 --- a/apps/studio/components/to-be-cleaned/Storage/StorageSettings/StorageSettings.tsx +++ b/apps/studio/components/to-be-cleaned/Storage/StorageSettings/StorageSettings.tsx @@ -192,7 +192,7 @@ const StorageSettings = () => { {isFreeTier && (
} + icon={} primaryText="Free Plan has a fixed upload file size limit of 50 MB." secondaryText="Upgrade to the Pro plan for a configurable upload file size limit of up to 50 GB." /> diff --git a/apps/studio/components/ui/AISettingsModal.tsx b/apps/studio/components/ui/AISettingsModal.tsx index 8daf70a72e9..1de599311c3 100644 --- a/apps/studio/components/ui/AISettingsModal.tsx +++ b/apps/studio/components/ui/AISettingsModal.tsx @@ -38,8 +38,8 @@ const AISettingsModal = () => { visible={snap.showAiSettingsModal} onCancel={() => snap.setShowAiSettingsModal(false)} > -
-
+ +
{ )} -
+
) } diff --git a/apps/studio/pages/project/[ref]/functions/index.tsx b/apps/studio/pages/project/[ref]/functions/index.tsx index bfd9e6b3260..740ac23c1fa 100644 --- a/apps/studio/pages/project/[ref]/functions/index.tsx +++ b/apps/studio/pages/project/[ref]/functions/index.tsx @@ -1,6 +1,16 @@ import { useParams } from 'common' import { useState } from 'react' -import { Button, Modal } from 'ui' +import { + Button, + Dialog, + DialogContent, + DialogFooter, + DialogHeader, + DialogSection, + DialogSectionSeparator, + DialogTrigger, + Modal, +} from 'ui' import { EdgeFunctionsListItem, @@ -43,9 +53,18 @@ const PageLayout: NextPageWithLayout = () => { {`${functions.length} function${ functions.length > 1 ? 's' : '' } deployed`} - + + + + + + + + + +
{ )} - setShowTerminalInstructions(false)} - header={

Deploying an edge function to your project

} - customFooter={ -
- -
- } - > -
- -
-
) } diff --git a/apps/studio/pages/project/[ref]/logs/explorer/index.tsx b/apps/studio/pages/project/[ref]/logs/explorer/index.tsx index 359cfd00d51..f45342c61e3 100644 --- a/apps/studio/pages/project/[ref]/logs/explorer/index.tsx +++ b/apps/studio/pages/project/[ref]/logs/explorer/index.tsx @@ -272,43 +272,32 @@ export const LogsExplorerPage: NextPageWithLayout = () => { > {() => ( <> -
- -
- -
- -
-
-
-
-
- -
- - -
-
-
+ + +
+ +
+
+ + + + + )} diff --git a/apps/studio/styles/stripe.scss b/apps/studio/styles/stripe.scss index a3d77453c86..13ed536ab87 100644 --- a/apps/studio/styles/stripe.scss +++ b/apps/studio/styles/stripe.scss @@ -24,7 +24,6 @@ .StripeElement { width: 100%; - padding: 11px 15px 11px 0; } .ErrorMessage { diff --git a/packages/config/ui.config.js b/packages/config/ui.config.js index 74231fea59d..6005aef8551 100644 --- a/packages/config/ui.config.js +++ b/packages/config/ui.config.js @@ -166,12 +166,12 @@ const uiConfig = { '100%': { transform: 'scale(0.95)', opacity: 0 }, }, overlayContentShow: { - '0%': { opacity: 0, transform: 'translate(0%, -2%) scale(.96)' }, + '0%': { opacity: 0, transform: 'translate(0%, -2%) scale(1)' }, '100%': { opacity: 1, transform: 'translate(0%, 0%) scale(1)' }, }, overlayContentHide: { '0%': { opacity: 1, transform: 'translate(0%, 0%) scale(1)' }, - '100%': { opacity: 0, transform: 'translate(0%, -2%) scale(.96)' }, + '100%': { opacity: 0, transform: 'translate(0%, -2%) scale(1)' }, }, dropdownFadeIn: { '0%': { transform: 'scale(0.95)', opacity: 0 }, diff --git a/packages/ui-patterns/Dialogs/ConfirmDialog.tsx b/packages/ui-patterns/Dialogs/ConfirmDialog.tsx index 4039b157739..11ff5a24457 100644 --- a/packages/ui-patterns/Dialogs/ConfirmDialog.tsx +++ b/packages/ui-patterns/Dialogs/ConfirmDialog.tsx @@ -59,11 +59,7 @@ const ConfirmModal = ({ > {() => { return ( -
- -

{description}

-
- + <>
-
+ ) }} diff --git a/packages/ui-patterns/Icons/StatusIcons.tsx b/packages/ui-patterns/Icons/StatusIcons.tsx index 075fd1179a4..68f307c5dd3 100644 --- a/packages/ui-patterns/Icons/StatusIcons.tsx +++ b/packages/ui-patterns/Icons/StatusIcons.tsx @@ -101,4 +101,4 @@ const WarningIcon: React.FC & StatusIconProps> = ({ ) } -export { WarningIcon, CriticalIcon } +export { WarningIcon, CriticalIcon, InfoIcon } diff --git a/packages/ui/build/css/themes/dark.css b/packages/ui/build/css/themes/dark.css index c7c9c9ab248..27367de1ed6 100644 --- a/packages/ui/build/css/themes/dark.css +++ b/packages/ui/build/css/themes/dark.css @@ -29,6 +29,7 @@ --destructive-400: 6.7deg 60% 20.6%; --destructive-300: 7.5deg 51.3% 15.3%; --destructive-200: 10.9deg 23.4% 9.2%; + --background-dialog-default: 0deg 0% 11%; --background-surface-75: 0deg 0% 12.5%; --background-200: 0deg 0% 11%; --foreground-contrast: 0deg 0% 11%; diff --git a/packages/ui/build/css/themes/deep-dark.css b/packages/ui/build/css/themes/deep-dark.css index 641dd925ab1..ce1fff2bf3b 100644 --- a/packages/ui/build/css/themes/deep-dark.css +++ b/packages/ui/build/css/themes/deep-dark.css @@ -37,6 +37,7 @@ --border-secondary: 0deg 0% 14.1%; --border-muted: 0deg 0% 14.1%; --border-default: 0deg 0% 16.1%; + --background-dialog-default: 0deg 0% 7.1%; --background-muted: 0deg 0% 14.1%; --background-overlay-hover: 0deg 0% 18%; --background-overlay-default: 0deg 0% 14.1%; diff --git a/packages/ui/build/css/themes/light.css b/packages/ui/build/css/themes/light.css index 98dd1b02050..1450f69c67c 100644 --- a/packages/ui/build/css/themes/light.css +++ b/packages/ui/build/css/themes/light.css @@ -32,6 +32,7 @@ --border-stronger: 0deg 0% 56.1%; --border-strong: 0deg 0% 83.1%; --border-default: 0deg 0% 87.5%; + --background-dialog-default: 0deg 0% 100%; --background-muted: 0deg 0% 96.9%; --background-surface-400: 0deg 0% 89.8%; --background-surface-300: 0deg 0% 92.9%; diff --git a/packages/ui/build/css/tw-extend/color.js b/packages/ui/build/css/tw-extend/color.js index 5e7282ce1ec..0cd2028ea30 100644 --- a/packages/ui/build/css/tw-extend/color.js +++ b/packages/ui/build/css/tw-extend/color.js @@ -479,6 +479,10 @@ module.exports = { cssVariable: "var(--background-button-default)", value: "hsl(0, 0%, 18%)" }, +"background-dialog-DEFAULT": { + cssVariable: "var(--background-dialog-default)", + value: "hsl(0, 0%, 7.1%)" +}, "border-DEFAULT": { cssVariable: "var(--border-default)", value: "hsl(0, 0%, 16.1%)" diff --git a/packages/ui/src/components/Modal/Modal.tsx b/packages/ui/src/components/Modal/Modal.tsx index d62d1fb32ef..218050bc488 100644 --- a/packages/ui/src/components/Modal/Modal.tsx +++ b/packages/ui/src/components/Modal/Modal.tsx @@ -1,189 +1,176 @@ 'use client' -import * as Dialog from '@radix-ui/react-dialog' -import React, { useEffect } from 'react' - +import React, { forwardRef, useEffect } from 'react' import styleHandler from '../../lib/theme/styleHandler' import { cn } from '../../lib/utils/cn' -import { AnimationTailwindClasses } from '../../types' -import { Button } from '../Button/Button' -import IconX from '../Icon/icons/IconX/IconX' -import Space from '../Space/Space' +import { Button, ButtonVariantProps } from '../Button/Button' +import { + Dialog, + DialogContent, + DialogFooter, + DialogHeader, + DialogSection, + DialogSectionSeparator, + DialogTitle, + DialogTrigger, + DialogDescription, + DialogClose, +} from '../shadcn/ui/dialog' -// import { Transition } from '@tailwindui/react' -// Merge Radix Props to surface in the modal component -export type ModalProps = RadixProps & Props - -interface RadixProps - extends Dialog.DialogProps, - Pick< - Dialog.DialogContentProps, - | 'onOpenAutoFocus' - | 'onCloseAutoFocus' - | 'onEscapeKeyDown' - | 'onPointerDownOutside' - | 'onInteractOutside' - > {} - -interface Props { - children?: React.ReactNode +export interface ModalProps extends React.ComponentProps { + Separator?: React.ComponentType + Content?: React.ComponentType + visible?: boolean + // @deprecated please add the footer directly in component children. This is to prepare for using component customFooter?: React.ReactNode description?: string + // @deprecated please add the footer directly in component children. This is to prepare for using component hideFooter?: boolean + // @deprecated please add the footer directly in component children. This is to prepare for using component alignFooter?: 'right' | 'left' + // @deprecated please add the footer directly in component children. This is to prepare for using component layout?: 'horizontal' | 'vertical' - icon?: React.ReactNode loading?: boolean onCancel?: any cancelText?: string onConfirm?: any confirmText?: string - /** - * @deprecated This prop is no longer being used in the Modal component - */ - closable?: boolean - showIcon?: boolean showCloseButton?: boolean footerBackground?: boolean - title?: string | React.ReactNode - variant?: 'danger' | 'warning' | 'success' - visible: boolean - size?: 'tiny' | 'small' | 'medium' | 'large' | 'xlarge' | 'xxlarge' - style?: React.CSSProperties + // @deprecated please add the footer directly in component children. This is to prepare for using component + variant?: ButtonVariantProps['type'] overlayStyle?: React.CSSProperties contentStyle?: React.CSSProperties - className?: string overlayClassName?: string - transition?: AnimationTailwindClasses - transitionOverlay?: AnimationTailwindClasses + // @deprecated please consider using and components triggerElement?: React.ReactNode + // @deprecated please consider using and components header?: React.ReactNode + modal?: React.ComponentProps['modal'] + defaultOpen?: React.ComponentProps['defaultOpen'] + /** + * @deprecated No longer in use + */ + closable?: boolean } -/** - * @deprecated Use ./Dialog instead - */ -const Modal = ({ - children, - customFooter = undefined, - description, - hideFooter = false, - alignFooter = 'left', - layout = 'horizontal', - loading = false, - cancelText = 'Cancel', - onConfirm = () => {}, - onCancel = () => {}, - confirmText = 'Confirm', - closable = false, - showIcon = false, - showCloseButton = false, - title, - footerBackground, - icon, - variant = 'success', - visible = false, - size = 'large', - style, - overlayStyle, - contentStyle, - className = '', - overlayClassName, - triggerElement, - header, - ...props -}: ModalProps) => { - const [open, setOpen] = React.useState(visible ? visible : false) - const __styles = styleHandler('modal') +interface ModalType + extends React.ForwardRefExoticComponent< + React.ComponentPropsWithoutRef & ModalProps + > { + Content: React.ComponentType<{ children: React.ReactNode; className?: string }> + Separator: React.ComponentType +} - useEffect(() => { - setOpen(visible) - }, [visible]) +// @deprecated use instead +const Modal = forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & ModalProps +>( + ( + { + children, + customFooter = undefined, + description, + hideFooter = false, + alignFooter = 'left', + layout = 'horizontal', + loading = false, + cancelText = 'Cancel', + onConfirm = () => {}, + onCancel = () => {}, + confirmText = 'Confirm', + showCloseButton = true, + footerBackground, + variant = 'success', + visible = false, + size = 'large', + style, + overlayStyle, + contentStyle, + className = '', + overlayClassName, + triggerElement, + header, + modal, + defaultOpen, + ...props + }, + ref + ) => { + const [open, setOpen] = React.useState(visible ? visible : false) + const __styles = styleHandler('modal') - const footerContent = customFooter ? ( - customFooter - ) : ( - - - - - ) + + + + ) - function handleOpenChange(open: boolean) { - if (visible !== undefined && !open) { - // controlled component behaviour - onCancel() - } else { - // un-controlled component behaviour - setOpen(open) + function handleOpenChange(open: boolean) { + if (visible !== undefined && !open) { + // controlled component behavior + onCancel() + } else { + // un-controlled component behavior + setOpen(open) + } } + + return ( + + {triggerElement && {triggerElement}} + + {header || description ? ( + + {header && {header}} + {description && {description}} + + ) : null} + {children} + {!hideFooter && {footerContent}} + + + ) } +) as ModalType - return ( - - {triggerElement && {triggerElement}} - - - - - {header && ( -
- {header} - {showCloseButton && ( -
- )} - {children} - {!hideFooter &&
{footerContent}
} -
-
-
-
- ) -} +const Content = forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ ...props }, ref) => { + return +}) -/** - * @deprecated Use ./Dialog instead - */ -function Content({ children, className }: { children: React.ReactNode; className?: string }) { - const __styles = styleHandler('modal') - return
{children}
-} - -/** - * @deprecated Use ./Dialog instead - */ -export function Separator() { - const __styles = styleHandler('modal') - - return
-} +const Separator = forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ ...props }, ref) => { + return +}) Modal.Content = Content Modal.Separator = Separator diff --git a/packages/ui/src/components/shadcn/ui/dialog.tsx b/packages/ui/src/components/shadcn/ui/dialog.tsx index 57bee4b5df5..7905acdf8a5 100644 --- a/packages/ui/src/components/shadcn/ui/dialog.tsx +++ b/packages/ui/src/components/shadcn/ui/dialog.tsx @@ -16,12 +16,12 @@ export const DIALOG_PADDING_X = 'px-7' const DialogPaddingVariants = cva('', { variants: { padding: { - default: `${DIALOG_PADDING_Y} ${DIALOG_PADDING_X}`, + medium: `${DIALOG_PADDING_Y} ${DIALOG_PADDING_X}`, small: `${DIALOG_PADDING_Y_SMALL} ${DIALOG_PADDING_X_SMALL}`, }, }, defaultVariants: { - padding: 'default', + padding: 'small', }, }) @@ -41,9 +41,7 @@ const DialogOverlay = React.forwardRef< {children} {!hideClose && ( - + Close @@ -109,7 +107,7 @@ DialogContent.displayName = DialogPrimitive.Content.displayName const DialogHeader = React.forwardRef< HTMLDivElement, React.HTMLAttributes & VariantProps ->(({ className, padding = 'default', ...props }, ref) => ( +>(({ className, padding, ...props }, ref) => (
& VariantProps >(({ className, children, padding, ...props }, ref) => ( -
+
{children}
)) @@ -201,7 +195,7 @@ const DialogSectionSeparator = React.forwardRef< HTMLDivElement, React.HTMLAttributes >(({ className, children, ...props }, ref) => ( -
+
)) DialogSectionSeparator.displayName = 'DialogSectionSeparator' diff --git a/packages/ui/src/lib/tailwind-demo-classes.ts b/packages/ui/src/lib/tailwind-demo-classes.ts index 46845c97460..d8673159670 100644 --- a/packages/ui/src/lib/tailwind-demo-classes.ts +++ b/packages/ui/src/lib/tailwind-demo-classes.ts @@ -14,7 +14,8 @@ export default { "bg-overlay", "bg-overlay-hover", "bg-muted", - "bg-button" + "bg-button", + "bg-dialog" ], "border": [ "border", diff --git a/supabase/functions/hello-world/index.ts b/supabase/functions/hello-world/index.ts new file mode 100644 index 00000000000..3edda14900d --- /dev/null +++ b/supabase/functions/hello-world/index.ts @@ -0,0 +1,29 @@ +// Follow this setup guide to integrate the Deno language server with your editor: +// https://deno.land/manual/getting_started/setup_your_environment +// This enables autocomplete, go to definition, etc. + +console.log("Hello from Functions!") + +Deno.serve(async (req) => { + const { name } = await req.json() + const data = { + message: `Hello ${name}!`, + } + + return new Response( + JSON.stringify(data), + { headers: { "Content-Type": "application/json" } }, + ) +}) + +/* To invoke locally: + + 1. Run `supabase start` (see: https://supabase.com/docs/reference/cli/supabase-start) + 2. Make an HTTP request: + + curl -i --location --request POST 'http://127.0.0.1:54321/functions/v1/hello-world' \ + --header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0' \ + --header 'Content-Type: application/json' \ + --data '{"name":"Functions"}' + +*/