chore(studio): delete Confirm Modal component (#41295)

* docs

* naming

* docs

* mini fix

* update policies component

* use destructured prop

* rls policies dialogs

* custom domain dialogs

* restart server dialog

* remove ConfirmDialog (aka ConfirmModal)

* remove unrelated changes

* delete unrelated file

* language

* Update apps/studio/components/interfaces/Storage/StoragePolicies/StoragePolicies.tsx

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* fixed broken test

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Ali Waseem <waseema393@gmail.com>
This commit is contained in:
authored and GitHub committed 2025-12-12 17:23:24 +08:00
1 parent a90890ad52
commit 3fdacb2cca
14 files changed
+161 -315

No files matched your search

-11
View File
@@ -38,17 +38,6 @@ export const Index: Record<string, any> = {
subcategory: "undefined",
chunks: []
},
"ConfirmDialog": {
name: "ConfirmDialog",
type: "components:fragment",
registryDependencies: undefined,
component: React.lazy(() => import("@/../../packages/ui-patterns/src/Dialogs/ConfirmDialog")),
source: "",
files: ["registry/default//Dialogs/ConfirmDialog.tsx"],
category: "undefined",
subcategory: "undefined",
chunks: []
},
"PageContainer": {
name: "PageContainer",
type: "components:fragment",
-6
View File
@@ -19,12 +19,6 @@ export const fragments: Registry = [
files: ['/Dialogs/TextConfirmModal.tsx'],
optionalPath: '/Dialogs',
},
{
name: 'ConfirmDialog',
type: 'components:fragment',
files: ['/Dialogs/ConfirmDialog.tsx'],
optionalPath: '/Dialogs',
},
{
name: 'PageContainer',
type: 'components:fragment',
@@ -15,7 +15,7 @@ import { useDatabasePolicyDeleteMutation } from 'data/database-policies/database
import { useTableUpdateMutation } from 'data/tables/table-update-mutation'
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
import { Button, Card, CardContent } from 'ui'
import ConfirmModal from 'ui-patterns/Dialogs/ConfirmDialog'
import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal'
interface PoliciesProps {
search?: string
@@ -51,7 +51,7 @@ export const Policies = ({
}>()
const [selectedPolicyToDelete, setSelectedPolicyToDelete] = useState<any>({})
const { mutate: updateTable } = useTableUpdateMutation({
const { mutate: updateTable, isPending: isUpdatingTable } = useTableUpdateMutation({
onError: (error) => {
toast.error(`Failed to toggle RLS: ${error.message}`)
},
@@ -60,14 +60,15 @@ export const Policies = ({
},
})
const { mutate: deleteDatabasePolicy } = useDatabasePolicyDeleteMutation({
onSuccess: () => {
toast.success('Successfully deleted policy!')
},
onSettled: () => {
closeConfirmModal()
},
})
const { mutate: deleteDatabasePolicy, isPending: isDeletingPolicy } =
useDatabasePolicyDeleteMutation({
onSuccess: () => {
toast.success('Successfully deleted policy!')
},
onSettled: () => {
closeConfirmModal()
},
})
const closeConfirmModal = useCallback(() => {
setSelectedPolicyToDelete({})
@@ -180,30 +181,30 @@ export const Policies = ({
) : null}
</div>
<ConfirmModal
danger
<ConfirmationModal
visible={!isEmpty(selectedPolicyToDelete)}
title="Confirm to delete policy"
description={`This is permanent! Are you sure you want to delete the policy "${selectedPolicyToDelete.name}"`}
buttonLabel="Delete"
buttonLoadingLabel="Deleting"
onSelectCancel={closeConfirmModal}
onSelectConfirm={onDeletePolicy}
variant="destructive"
title="Delete policy"
description={`Are you sure you want to delete the policy “${selectedPolicyToDelete.name}”? This action cannot be undone.`}
confirmLabel="Delete"
confirmLabelLoading="Deleting"
loading={isDeletingPolicy}
onCancel={closeConfirmModal}
onConfirm={onDeletePolicy}
/>
<ConfirmModal
danger={selectedTableToToggleRLS?.rls_enabled}
<ConfirmationModal
visible={selectedTableToToggleRLS !== undefined}
title={`Confirm to ${
selectedTableToToggleRLS?.rls_enabled ? 'disable' : 'enable'
} Row Level Security`}
variant={selectedTableToToggleRLS?.rls_enabled ? 'destructive' : 'default'}
title={`${selectedTableToToggleRLS?.rls_enabled ? 'Disable' : 'Enable'} Row Level Security`}
description={`Are you sure you want to ${
selectedTableToToggleRLS?.rls_enabled ? 'disable' : 'enable'
} Row Level Security for the table "${selectedTableToToggleRLS?.name}"?`}
buttonLabel="Confirm"
buttonLoadingLabel="Saving"
onSelectCancel={closeConfirmModal}
onSelectConfirm={onToggleRLS}
} Row Level Security (RLS) for the table “${selectedTableToToggleRLS?.name}”?`}
confirmLabel={`${selectedTableToToggleRLS?.rls_enabled ? 'Disable' : 'Enable'} RLS`}
confirmLabelLoading={`${selectedTableToToggleRLS?.rls_enabled ? 'Disabling' : 'Enabling'} RLS`}
loading={isUpdatingTable}
onCancel={closeConfirmModal}
onConfirm={onToggleRLS}
/>
</>
)
@@ -1,4 +1,3 @@
import { AlertCircle } from 'lucide-react'
import { useState } from 'react'
import { toast } from 'sonner'
@@ -10,8 +9,9 @@ import { useCustomDomainActivateMutation } from 'data/custom-domains/custom-doma
import { useCustomDomainDeleteMutation } from 'data/custom-domains/custom-domains-delete-mutation'
import type { CustomDomainResponse } from 'data/custom-domains/custom-domains-query'
import { DOCS_URL } from 'lib/constants'
import { AlertDescription_Shadcn_, AlertTitle_Shadcn_, Alert_Shadcn_, Button } from 'ui'
import { Button } from 'ui'
import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal'
import { Admonition } from 'ui-patterns/admonition'
export type CustomDomainActivateProps = {
projectRef?: string
@@ -59,36 +59,33 @@ const CustomDomainActivate = ({ projectRef, customDomain }: CustomDomainActivate
<div className="flex flex-col items-start">
<Panel.Content>
<div className="flex flex-col gap-2">
<h4 className="text-foreground">
Setup complete! Press activate to enable the custom domain{' '}
<code className="text-sm">{customDomain.hostname}</code> for this project.
</h4>
<span className="text-sm text-foreground-light">
<h4 className="text-foreground">Enable your custom domain</h4>
<p className="text-sm text-foreground-light">
Set up is almost complete. Press “Activate” below to enable{' '}
<code className="text-code-inline">{customDomain.hostname}</code> for this project.
</p>
<p className="text-sm text-foreground-light">
We recommend that you schedule a downtime window of 20 - 30 minutes for your
application, as you will need to update any services that need to know about your
custom domain (e.g client side code or OAuth providers)
</span>
custom domain (e.g client side code or OAuth providers).
</p>
</div>
<div className="mt-4">
<Alert_Shadcn_>
<AlertCircle className="text-foreground-light" strokeWidth={1.5} />
<AlertTitle_Shadcn_>
Remember to retain your CNAME record for service continuity after activation
</AlertTitle_Shadcn_>
<AlertDescription_Shadcn_>
<p className="col-span-12 text-sm lg:col-span-7 leading-6">
Your custom domain CNAME record for{' '}
<code className="text-code-inline">{customDomain.hostname}</code> should resolve
to{' '}
{endpoint ? (
<code className="text-xs">{endpoint}</code>
) : (
"your project's API URL"
)}
. If you're using Cloudflare as your DNS provider, disable the proxy option.
</p>
</AlertDescription_Shadcn_>
</Alert_Shadcn_>
<Admonition
type="note"
title="Retain your CNAME record for service continuity after activation"
>
<p>
Your custom domain CNAME record for{' '}
<code className="text-code-inline">{customDomain.hostname}</code> should resolve to{' '}
{endpoint ? (
<code className="text-code-inline">{endpoint}</code>
) : (
"your project's API URL"
)}
. If you're using Cloudflare as your DNS provider, disable the proxy option.
</p>
</Admonition>
</div>
</Panel.Content>
@@ -107,22 +104,6 @@ const CustomDomainActivate = ({ projectRef, customDomain }: CustomDomainActivate
Cancel
</Button>
<Button
icon={
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth={1}
stroke="currentColor"
className="w-4 h-4"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M3.75 13.5l10.5-11.25L12 10.5h8.25L9.75 21.75 12 13.5H3.75z"
/>
</svg>
}
disabled={isDeleting}
onClick={() => setIsActivateConfirmModalVisible(true)}
className="self-end"
@@ -138,20 +119,16 @@ const CustomDomainActivate = ({ projectRef, customDomain }: CustomDomainActivate
size="small"
loading={isCheckingRecord || isActivating}
visible={isActivateConfirmModalVisible}
title={
<>
Are you sure you want to activate the custom domain{' '}
<code className="text-sm">{customDomain.hostname}</code> for the project?
</>
}
title="Activate custom domain"
confirmLabel="Activate"
confirmLabelLoading="Activating"
onCancel={() => setIsActivateConfirmModalVisible(false)}
onConfirm={onActivateCustomDomain}
>
<p className="text-sm">
This will activate the custom domain <code>{customDomain.hostname}</code>. Your project's
Supabase domain will also remain active.
Activating <code className="text-code-inline !break-normal">{customDomain.hostname}</code>{' '}
will make it visible to users in place of your project’s Supabase domain. The Supabase
domain will continue to work too.
</p>
</ConfirmationModal>
</>
@@ -8,7 +8,7 @@ import type { CustomDomainResponse } from 'data/custom-domains/custom-domains-qu
import { DOCS_URL } from 'lib/constants'
import { Trash } from 'lucide-react'
import { Button } from 'ui'
import ConfirmModal from 'ui-patterns/Dialogs/ConfirmDialog'
import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal'
export type CustomDomainDeleteProps = {
projectRef?: string
@@ -17,14 +17,15 @@ export type CustomDomainDeleteProps = {
const CustomDomainDelete = ({ projectRef, customDomain }: CustomDomainDeleteProps) => {
const [isDeleteConfirmModalVisible, setIsDeleteConfirmModalVisible] = useState(false)
const { mutate: deleteCustomDomain } = useCustomDomainDeleteMutation({
onSuccess: () => {
toast.success(
`Successfully deleted custom domain. It may take a few seconds before your custom domain is fully removed, hence you may need to refresh your browser.`
)
setIsDeleteConfirmModalVisible(false)
},
})
const { mutate: deleteCustomDomain, isPending: isDeletingCustomDomain } =
useCustomDomainDeleteMutation({
onSuccess: () => {
toast.success(
`Successfully deleted custom domain. Refresh your browser to see the changes.`
)
setIsDeleteConfirmModalVisible(false)
},
})
const onDeleteCustomDomain = async () => {
if (!projectRef) return console.error('Project ref is required')
@@ -39,7 +40,9 @@ const CustomDomainDelete = ({ projectRef, customDomain }: CustomDomainDeleteProp
<div className="flex items-center space-x-2">
<code className="text-lg mx-0 flex items-center space-x-2">
<div className="h-2 w-2 rounded-full bg-brand" />
<span>{customDomain.hostname}</span>
<span>
<code className="text-code-inline">{customDomain.hostname}</code>
</span>
</code>
</div>
<p className="text-sm text-foreground-light">
@@ -58,27 +61,27 @@ const CustomDomainDelete = ({ projectRef, customDomain }: CustomDomainDeleteProp
icon={<Trash />}
onClick={() => setIsDeleteConfirmModalVisible(true)}
>
Delete Custom Domain
Delete custom domain
</Button>
</div>
</Panel.Content>
<ConfirmModal
danger
<ConfirmationModal
visible={isDeleteConfirmModalVisible}
// @ts-ignore
title={
<div>
Are you sure you want to delete the custom domain{' '}
<code className="text-sm">{customDomain.hostname}</code> for the project?
</div>
}
description="Your custom domain will be deactivated. You will need to re-verify your domain if you want to use it again."
buttonLabel="Delete"
buttonLoadingLabel="Deleting"
onSelectCancel={() => setIsDeleteConfirmModalVisible(false)}
onSelectConfirm={onDeleteCustomDomain}
/>
variant="destructive"
title="Delete custom domain"
confirmLabel="Delete"
confirmLabelLoading="Deleting"
loading={isDeletingCustomDomain}
onCancel={() => setIsDeleteConfirmModalVisible(false)}
onConfirm={onDeleteCustomDomain}
>
<p className="text-sm">
Are you sure you want to delete the custom domain{' '}
<code className="text-code-inline !break-normal">{customDomain.hostname}</code> for your
project? You will need to re-verify this domain if you want to use it again.
</p>
</ConfirmationModal>
</>
)
}
@@ -1,9 +1,9 @@
import { AlertCircle, HelpCircle, RefreshCw } from 'lucide-react'
import Link from 'next/link'
import { AlertCircle, RefreshCw } from 'lucide-react'
import { toast } from 'sonner'
import { useParams } from 'common'
import { DocsButton } from 'components/ui/DocsButton'
import { InlineLink } from 'components/ui/InlineLink'
import Panel from 'components/ui/Panel'
import { useProjectSettingsV2Query } from 'data/config/project-settings-v2-query'
import { useCustomDomainDeleteMutation } from 'data/custom-domains/custom-domains-delete-mutation'
@@ -18,6 +18,7 @@ import {
Button,
WarningIcon,
} from 'ui'
import { Admonition } from 'ui-patterns/admonition'
import DNSRecord from './DNSRecord'
import { DNSTableHeaders } from './DNSTableHeaders'
@@ -83,7 +84,7 @@ const CustomDomainVerify = () => {
<div>
<h4 className="text-foreground mb-2">
Configure TXT verification for your custom domain{' '}
<code className="text-sm">{customDomain?.hostname}</code>
<code className="text-code-inline">{customDomain?.hostname}</code>
</h4>
<p className="text-sm text-foreground-light">
Set the following TXT record(s) in your DNS provider, then click verify to confirm your
@@ -94,47 +95,30 @@ const CustomDomainVerify = () => {
</p>
{!isValidating && (
<div className="mt-4 mb-2">
<Alert_Shadcn_ variant="default">
{isNotVerifiedYet ? (
<AlertCircle className="text-foreground-light" strokeWidth={1.5} />
) : (
<HelpCircle className="text-foreground-light" strokeWidth={1.5} />
)}
<AlertTitle_Shadcn_>
{isNotVerifiedYet
<Admonition
type="note"
title={
isNotVerifiedYet
? 'Unable to verify records from DNS provider yet.'
: 'Please note that it may take up to 24 hours for the DNS records to propagate.'}
</AlertTitle_Shadcn_>
<AlertDescription_Shadcn_>
<div>
{isNotVerifiedYet && (
<p>
Please check again soon. Note that it may take up to 24 hours for changes in
DNS records to propagate.
</p>
)}
<p>
You may also visit{' '}
<Link
target="_blank"
rel="noreferrer"
href={`https://whatsmydns.net/#TXT/${customDomain?.ssl.txt_name}`}
className="text-brand"
>
here
</Link>{' '}
to check if your DNS has been propagated successfully before clicking verify.
</p>
{isNotVerifiedYet && (
<p className="mt-1 text-foreground-lighter">
Some registrars will require you to remove the domain name when creating DNS
records. As an example, to create a record for `foo.app.example.com`, you
would need to create an entry for `foo.app`.
</p>
)}
</div>
</AlertDescription_Shadcn_>
</Alert_Shadcn_>
: 'Please note that it may take up to 24 hours for the DNS records to propagate.'
}
>
<p>
You may also visit{' '}
<InlineLink href={`https://whatsmydns.net/#TXT/${customDomain?.ssl.txt_name}`}>
here
</InlineLink>{' '}
to check if your DNS has been propagated successfully before clicking verify.
</p>
{isNotVerifiedYet && (
<p className="mt-1">
Some registrars will require you to remove the domain name when creating DNS
records. As an example, to create a record for{' '}
<code className="text-code-inline">foo.app.example.com</code>, you would need to
create an entry for <code className="text-code-inline">foo.app</code>.
</p>
)}
</Admonition>
</div>
)}
</div>
@@ -22,7 +22,7 @@ import {
DropdownMenuTrigger,
cn,
} from 'ui'
import ConfirmModal from 'ui-patterns/Dialogs/ConfirmDialog'
import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal'
const RestartServerButton = () => {
const router = useRouter()
@@ -169,22 +169,21 @@ const RestartServerButton = () => {
</Button>
)}
<ConfirmModal
danger
<ConfirmationModal
visible={serviceToRestart !== undefined}
variant="destructive"
title={`Restart ${serviceToRestart}`}
// @ts-ignore
description={
<>
Are you sure you want to restart the{' '}
<span className="text-foreground">{serviceToRestart}</span>? There will be a few minutes
of downtime.
Are you sure you want to restart your {serviceToRestart}? There will be a few minutes of
downtime.
</>
}
buttonLabel="Restart"
buttonLoadingLabel="Restarting"
onSelectCancel={() => setServiceToRestart(undefined)}
onSelectConfirm={async () => {
confirmLabel="Restart"
confirmLabelLoading="Restarting"
loading={isLoading}
onCancel={() => setServiceToRestart(undefined)}
onConfirm={async () => {
if (serviceToRestart === 'project') {
await requestProjectRestart()
} else if (serviceToRestart === 'database') {
@@ -14,7 +14,7 @@ import { usePaginatedBucketsQuery } from 'data/storage/buckets-query'
import { useDebouncedValue } from 'hooks/misc/useDebouncedValue'
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
import { GenericSkeletonLoader } from 'ui-patterns'
import ConfirmModal from 'ui-patterns/Dialogs/ConfirmDialog'
import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal'
import { PageContainer } from 'ui-patterns/PageContainer'
import {
PageSection,
@@ -73,13 +73,17 @@ export const StoragePolicies = () => {
onError: () => {},
})
const { mutateAsync: updateDatabasePolicy } = useDatabasePolicyUpdateMutation()
const { mutate: deleteDatabasePolicy } = useDatabasePolicyDeleteMutation({
onSuccess: async () => {
await refetch()
toast.success('Successfully deleted policy!')
setSelectedPolicyToDelete(undefined)
},
})
const { mutate: deleteDatabasePolicy, isPending: isDeletingPolicy } =
useDatabasePolicyDeleteMutation({
onSuccess: async () => {
await refetch()
toast.success('Successfully deleted policy!')
setSelectedPolicyToDelete(undefined)
},
onError: (error: any) => {
toast.error(`Failed to delete policy: ${error.message}`)
},
})
// Only use storage policy editor when creating new policies for buckets
const showStoragePolicyEditor =
@@ -318,15 +322,16 @@ export const StoragePolicies = () => {
onSaveSuccess={onSavePolicySuccess}
/>
<ConfirmModal
danger
<ConfirmationModal
visible={!isEmpty(selectedPolicyToDelete)}
title="Confirm to delete policy"
description={`This is permanent! Are you sure you want to delete the policy "${selectedPolicyToDelete?.name}"`}
buttonLabel="Delete"
buttonLoadingLabel="Deleting"
onSelectCancel={onCancelPolicyDelete}
onSelectConfirm={onDeletePolicy}
variant="destructive"
title="Delete policy"
description={`Are you sure you want to delete the policy “${selectedPolicyToDelete?.name}”? This action cannot be undone.`}
confirmLabel="Delete"
confirmLabelLoading="Deleting"
loading={isDeletingPolicy}
onCancel={onCancelPolicyDelete}
onConfirm={onDeletePolicy}
/>
</>
)
@@ -43,7 +43,6 @@ import {
TooltipTrigger,
cn,
} from 'ui'
import ConfirmModal from 'ui-patterns/Dialogs/ConfirmDialog'
import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal'
import { RoleImpersonationPopover } from '../RoleImpersonationSelector/RoleImpersonationPopover'
import ViewEntityAutofixSecurityModal from './ViewEntityAutofixSecurityModal'
@@ -78,7 +77,7 @@ export const GridHeaderActions = ({ table, isRefetching }: GridHeaderActionsProp
const { realtimeAll: realtimeEnabled } = useIsFeatureEnabled(['realtime:all'])
const { isSchemaLocked } = useIsProtectedSchema({ schema: table.schema })
const { mutate: updateTable } = useTableUpdateMutation({
const { mutate: updateTable, isPending: isUpdatingTable } = useTableUpdateMutation({
onError: (error) => {
toast.error(`Failed to toggle RLS: ${error.message}`)
},
@@ -592,15 +591,18 @@ export const GridHeaderActions = ({ table, isRefetching }: GridHeaderActionsProp
/>
{isTable && (
<ConfirmModal
danger={table.rls_enabled}
<ConfirmationModal
visible={rlsConfirmModalOpen}
title="Enable Row Level Security"
description="Are you sure you want to enable Row Level Security for this table?"
buttonLabel="Enable RLS"
buttonLoadingLabel="Updating"
onSelectCancel={closeConfirmModal}
onSelectConfirm={onToggleRLS}
variant={table.rls_enabled ? 'destructive' : 'default'}
title={`${table.rls_enabled ? 'Disable' : 'Enable'} Row Level Security`}
description={`Are you sure you want to ${
table.rls_enabled ? 'disable' : 'enable'
} Row Level Security for this table?`}
confirmLabel={`${table.rls_enabled ? 'Disable' : 'Enable'} RLS`}
confirmLabelLoading={`${table.rls_enabled ? 'Disabling' : 'Enabling'} RLS`}
loading={isUpdatingTable}
onCancel={closeConfirmModal}
onConfirm={onToggleRLS}
/>
)}
</div>
@@ -108,11 +108,7 @@ const NavigationItem: React.FC<NavigationItemProps> = ({ item, onClick, ...props
)}
/>
{item.title}
{item.new && (
<Badge variant="success" className="capitalize">
New
</Badge>
)}
{item.new && <Badge variant="success">New</Badge>}
</Link>
)
}
+2 -2
View File
@@ -200,12 +200,12 @@ test.describe.serial('RLS Policies', () => {
// A confirmation modal appears when toggling RLS from the policies page
await expect(
page.getByRole('heading', { name: 'Confirm to disable Row Level Security' }),
page.getByRole('heading', { name: 'Disable Row Level Security' }),
'RLS disable confirmation modal should appear'
).toBeVisible({ timeout: 50000 })
// Confirm disabling RLS
await page.getByRole('button', { name: 'Confirm' }).click()
await page.getByRole('button', { name: 'Disable RLS' }).click()
// After confirming, the toggle button text should change to "Enable RLS"
await expect(
-4
View File
@@ -278,10 +278,6 @@
"import": "./src/DataInputs/Input.tsx",
"types": "./src/DataInputs/Input.tsx"
},
"./Dialogs/ConfirmDialog": {
"import": "./src/Dialogs/ConfirmDialog.tsx",
"types": "./src/Dialogs/ConfirmDialog.tsx"
},
"./Dialogs/ConfirmationModal": {
"import": "./src/Dialogs/ConfirmationModal.tsx",
"types": "./src/Dialogs/ConfirmationModal.tsx"
@@ -1,100 +0,0 @@
'use client'
import { useEffect, useState } from 'react'
import { Button, Form, Modal } from 'ui'
// [Joshen] As of 280222, let's just use ConfirmationModal as the one and only confirmation modal (Deprecate this)
interface ConfirmModalProps {
visible: boolean
danger?: boolean
title: string
description: string
size?: 'tiny' | 'small' | 'medium' | 'large' | 'xlarge' | 'xxlarge'
buttonLabel: string
buttonLoadingLabel?: string
onSelectCancel: () => void
onSelectConfirm: () => void
}
/** @deprecated use ConfirmationModal instead */
const ConfirmModal = ({
visible = false,
danger = false,
title = '',
description = '',
size = 'small',
buttonLabel = '',
buttonLoadingLabel = '',
onSelectCancel = () => {},
onSelectConfirm = () => {},
}: ConfirmModalProps) => {
useEffect(() => {
if (visible) {
setLoading(false)
}
}, [visible])
const [loading, setLoading] = useState(false)
const onConfirm = () => {
setLoading(true)
onSelectConfirm()
}
return (
<Modal
header={title}
visible={visible}
title={title}
description={description}
size={size}
hideFooter
onCancel={onSelectCancel}
>
<Form
initialValues={{}}
validateOnBlur
onSubmit={() => onConfirm()}
validate={() => {
return []
}}
>
{() => {
return (
<>
<Modal.Content>
<div className="flex items-center gap-2">
<Button
block
htmlType="button"
type="default"
onClick={onSelectCancel}
disabled={loading}
>
Cancel
</Button>
<Button
htmlType="submit"
block
type={danger ? 'danger' : 'primary'}
disabled={loading}
loading={loading}
>
{buttonLoadingLabel && loading
? buttonLoadingLabel
: buttonLabel
? buttonLabel
: 'Confirm'}
</Button>
</div>
</Modal.Content>
</>
)
}}
</Form>
</Modal>
)
}
export default ConfirmModal
@@ -141,7 +141,7 @@ export const ConfirmationModal = forwardRef<
onClick={onSubmit}
className="truncate"
>
{confirmLabel}
{loading && confirmLabelLoading ? confirmLabelLoading : confirmLabel}
</Button>
</div>
</DialogContent>