mirror of
https://github.com/supabase/supabase.git
synced 2026-05-20 04:23:53 +08:00
Chore/update confirmation modal (#22328)
* Update confirmation modal * update all props * Update ExtensionCard.tsx * clen up
This commit is contained in:
committed by
GitHub
parent
ab39435862
commit
645273cb45
@@ -190,34 +190,30 @@ const Pagination = ({ isLoading: isLoadingRows = false }: PaginationProps) => {
|
||||
|
||||
<ConfirmationModal
|
||||
visible={isConfirmPreviousModalOpen}
|
||||
header="Confirm moving to previous page"
|
||||
buttonLabel="Confirm"
|
||||
onSelectCancel={() => setIsConfirmPreviousModalOpen(false)}
|
||||
onSelectConfirm={() => {
|
||||
title="Confirm moving to previous page"
|
||||
confirmLabel="Confirm"
|
||||
onCancel={() => setIsConfirmPreviousModalOpen(false)}
|
||||
onConfirm={() => {
|
||||
onConfirmPreviousPage()
|
||||
}}
|
||||
>
|
||||
<Modal.Content>
|
||||
<p className="py-4 text-sm text-foreground-light">
|
||||
The currently selected lines will be deselected, do you want to proceed?
|
||||
</p>
|
||||
</Modal.Content>
|
||||
<p className="py-4 text-sm text-foreground-light">
|
||||
The currently selected lines will be deselected, do you want to proceed?
|
||||
</p>
|
||||
</ConfirmationModal>
|
||||
|
||||
<ConfirmationModal
|
||||
visible={isConfirmNextModalOpen}
|
||||
header="Confirm moving to next page"
|
||||
buttonLabel="Confirm"
|
||||
onSelectCancel={() => setIsConfirmNextModalOpen(false)}
|
||||
onSelectConfirm={() => {
|
||||
title="Confirm moving to next page"
|
||||
confirmLabel="Confirm"
|
||||
onCancel={() => setIsConfirmNextModalOpen(false)}
|
||||
onConfirm={() => {
|
||||
onConfirmNextPage()
|
||||
}}
|
||||
>
|
||||
<Modal.Content>
|
||||
<p className="py-4 text-sm text-foreground-light">
|
||||
The currently selected lines will be deselected, do you want to proceed?
|
||||
</p>
|
||||
</Modal.Content>
|
||||
<p className="py-4 text-sm text-foreground-light">
|
||||
The currently selected lines will be deselected, do you want to proceed?
|
||||
</p>
|
||||
</ConfirmationModal>
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -77,20 +77,18 @@ const AccessTokenList = () => {
|
||||
</div>
|
||||
<ConfirmationModal
|
||||
visible={isOpen}
|
||||
danger={true}
|
||||
header="Confirm to delete"
|
||||
buttonLabel="Delete"
|
||||
buttonLoadingLabel="Deleting"
|
||||
onSelectCancel={() => setIsOpen(false)}
|
||||
onSelectConfirm={() => {
|
||||
variant={'destructive'}
|
||||
title="Confirm to delete"
|
||||
confirmLabel="Delete"
|
||||
confirmLabelLoading="Deleting"
|
||||
onCancel={() => setIsOpen(false)}
|
||||
onConfirm={() => {
|
||||
if (token) onDeleteToken(token.id)
|
||||
}}
|
||||
>
|
||||
<Modal.Content>
|
||||
<p className="py-4 text-sm text-foreground-light">
|
||||
{`This action cannot be undone. Are you sure you want to delete "${token?.name}" token?`}
|
||||
</p>
|
||||
</Modal.Content>
|
||||
<p className="py-4 text-sm text-foreground-light">
|
||||
{`This action cannot be undone. Are you sure you want to delete "${token?.name}" token?`}
|
||||
</p>
|
||||
</ConfirmationModal>
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -64,29 +64,27 @@ const FirstStep = ({ visible, name, enroll, setName, isEnrolling, onClose }: Fir
|
||||
<ConfirmationModal
|
||||
size="medium"
|
||||
visible={visible}
|
||||
header="Add a new authenticator app as a factor"
|
||||
buttonLabel="Generate QR"
|
||||
buttonLoadingLabel="Generating QR"
|
||||
buttonDisabled={name.length === 0}
|
||||
title="Add a new authenticator app as a factor"
|
||||
confirmLabel="Generate QR"
|
||||
confirmLabelLoading="Generating QR"
|
||||
disabled={name.length === 0}
|
||||
loading={isEnrolling}
|
||||
onSelectCancel={onClose}
|
||||
onSelectConfirm={() => {
|
||||
onCancel={onClose}
|
||||
onConfirm={() => {
|
||||
enroll({
|
||||
factorType: 'totp',
|
||||
friendlyName: name,
|
||||
})
|
||||
}}
|
||||
>
|
||||
<Modal.Content>
|
||||
<div className="pt-6 pb-5">
|
||||
<Input
|
||||
label="Provide a name to identify this app"
|
||||
descriptionText="A string will be randomly generated if a name is not provided"
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
</Modal.Content>
|
||||
<div className="pt-6 pb-5">
|
||||
<Input
|
||||
label="Provide a name to identify this app"
|
||||
descriptionText="A string will be randomly generated if a name is not provided"
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
</ConfirmationModal>
|
||||
)
|
||||
}
|
||||
@@ -152,65 +150,63 @@ const SecondStep = ({
|
||||
<ConfirmationModal
|
||||
size="medium"
|
||||
visible={visible}
|
||||
header={`Verify new factor ${factorName}`}
|
||||
buttonLabel="Confirm"
|
||||
buttonLoadingLabel="Confirming"
|
||||
title={`Verify new factor ${factorName}`}
|
||||
confirmLabel="Confirm"
|
||||
confirmLabelLoading="Confirming"
|
||||
loading={isVerifying}
|
||||
onSelectCancel={() => {
|
||||
onCancel={() => {
|
||||
// If a factor has been created (but not verified), unenroll it. This will be run as a
|
||||
// side effect so that it's not confusing to the user why the modal stays open while
|
||||
// unenrolling.
|
||||
if (factor) unenroll({ factorId: factor.id })
|
||||
}}
|
||||
onSelectConfirm={() => factor && challengeAndVerify({ factorId: factor.id, code })}
|
||||
onConfirm={() => factor && challengeAndVerify({ factorId: factor.id, code })}
|
||||
>
|
||||
<Modal.Content>
|
||||
<>
|
||||
<div className="py-4 pb-0 text-sm">
|
||||
<span>
|
||||
Use an authenticator app to scan the following QR code, and provide the code from the
|
||||
app to complete the enrolment.
|
||||
</span>
|
||||
<>
|
||||
<div className="py-4 pb-0 text-sm">
|
||||
<span>
|
||||
Use an authenticator app to scan the following QR code, and provide the code from the
|
||||
app to complete the enrolment.
|
||||
</span>
|
||||
</div>
|
||||
{isLoading && (
|
||||
<div className="pb-4 px-4">
|
||||
<GenericSkeletonLoader />
|
||||
</div>
|
||||
{isLoading && (
|
||||
<div className="pb-4 px-4">
|
||||
<GenericSkeletonLoader />
|
||||
)}
|
||||
{factor && (
|
||||
<>
|
||||
<div className="flex justify-center py-6">
|
||||
<div className="h-48 w-48 bg-white rounded">
|
||||
<img width={190} height={190} src={factor.totp.qr_code} alt={factor.totp.uri} />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{factor && (
|
||||
<>
|
||||
<div className="flex justify-center py-6">
|
||||
<div className="h-48 w-48 bg-white rounded">
|
||||
<img width={190} height={190} src={factor.totp.qr_code} alt={factor.totp.uri} />
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<InformationBox
|
||||
title="Unable to scan?"
|
||||
description={
|
||||
<Input
|
||||
copy
|
||||
disabled
|
||||
id="ref"
|
||||
size="small"
|
||||
label="You can also enter this secret key into your authenticator app"
|
||||
value={factor.totp.secret}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className="pt-2 pb-4">
|
||||
<Input
|
||||
label="Authentication code"
|
||||
value={code}
|
||||
placeholder="XXXXXX"
|
||||
onChange={(e) => setCode(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
</Modal.Content>
|
||||
<div>
|
||||
<InformationBox
|
||||
title="Unable to scan?"
|
||||
description={
|
||||
<Input
|
||||
copy
|
||||
disabled
|
||||
id="ref"
|
||||
size="small"
|
||||
label="You can also enter this secret key into your authenticator app"
|
||||
value={factor.totp.secret}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className="pt-2 pb-4">
|
||||
<Input
|
||||
label="Authentication code"
|
||||
value={code}
|
||||
placeholder="XXXXXX"
|
||||
onChange={(e) => setCode(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
</ConfirmationModal>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -34,45 +34,36 @@ const DeleteFactorModal = ({
|
||||
<ConfirmationModal
|
||||
size="medium"
|
||||
visible={visible}
|
||||
danger
|
||||
header="Confirm to delete factor"
|
||||
buttonLabel="Delete"
|
||||
buttonLoadingLabel="Deleting"
|
||||
variant={'destructive'}
|
||||
title="Confirm to delete factor"
|
||||
confirmLabel="Delete"
|
||||
confirmLabelLoading="Deleting"
|
||||
loading={isLoading}
|
||||
onSelectCancel={onClose}
|
||||
onSelectConfirm={() => factorId && unenroll({ factorId })}
|
||||
onCancel={onClose}
|
||||
onConfirm={() => factorId && unenroll({ factorId })}
|
||||
alert={{
|
||||
title: lastFactorToBeDeleted
|
||||
? 'Multi-factor authentication will be disabled'
|
||||
: 'This action cannot be undone',
|
||||
description: lastFactorToBeDeleted
|
||||
? 'There are no other factors that are set up once you delete this factor, as such your account will no longer be guarded by multi-factor authentication'
|
||||
: 'You will no longer be able to use this authenticator app for multi-factor authentication when signing in to the dashboard',
|
||||
}}
|
||||
>
|
||||
<Modal.Content className="py-6">
|
||||
<Alert_Shadcn_ variant="warning">
|
||||
<IconAlertTriangle strokeWidth={2} />
|
||||
<AlertTitle_Shadcn_>
|
||||
{lastFactorToBeDeleted
|
||||
? 'Multi-factor authentication will be disabled'
|
||||
: 'This action cannot be undone'}
|
||||
</AlertTitle_Shadcn_>
|
||||
<AlertDescription_Shadcn_>
|
||||
{lastFactorToBeDeleted
|
||||
? 'There are no other factors that are set up once you delete this factor, as such your account will no longer be guarded by multi-factor authentication'
|
||||
: 'You will no longer be able to use this authenticator app for multi-factor authentication when signing in to the dashboard'}
|
||||
</AlertDescription_Shadcn_>
|
||||
</Alert_Shadcn_>
|
||||
<div className="text-sm px-1 pt-4">
|
||||
<p>Before deleting this factor, consider:</p>
|
||||
<ul className="text-foreground-light py-1 list-disc mx-4 space-y-1">
|
||||
{lastFactorToBeDeleted ? (
|
||||
<>
|
||||
<li>Adding another authenticator app as a factor prior to deleting</li>
|
||||
<li>Ensure that your account does not need multi-factor authentication</li>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<li>Your backup authenticator app is still available to use</li>
|
||||
<li>Adding another authenticator app thereafter as a backup</li>
|
||||
</>
|
||||
)}
|
||||
</ul>
|
||||
</div>
|
||||
</Modal.Content>
|
||||
<p className="text-sm">Before deleting this factor, consider:</p>
|
||||
<ul className="text-sm text-foreground-light py-1 list-disc mx-4 space-y-1">
|
||||
{lastFactorToBeDeleted ? (
|
||||
<>
|
||||
<li>Adding another authenticator app as a factor prior to deleting</li>
|
||||
<li>Ensure that your account does not need multi-factor authentication</li>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<li>Your backup authenticator app is still available to use</li>
|
||||
<li>Adding another authenticator app thereafter as a backup</li>
|
||||
</>
|
||||
)}
|
||||
</ul>
|
||||
</ConfirmationModal>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -843,22 +843,20 @@ export const AIPolicyEditorPanel = memo(function ({
|
||||
|
||||
<ConfirmationModal
|
||||
visible={isClosingPolicyEditorPanel}
|
||||
header="Discard changes"
|
||||
buttonLabel="Discard"
|
||||
onSelectCancel={() => {
|
||||
title="Discard changes"
|
||||
confirmLabel="Discard"
|
||||
onCancel={() => {
|
||||
setIsClosingPolicyEditorPanel(false)
|
||||
}}
|
||||
onSelectConfirm={() => {
|
||||
onConfirm={() => {
|
||||
onSelectCancel()
|
||||
setIsClosingPolicyEditorPanel(false)
|
||||
}}
|
||||
>
|
||||
<Modal.Content>
|
||||
<p className="py-4 text-sm text-foreground-light">
|
||||
Are you sure you want to close the editor? Any unsaved changes on your policy and
|
||||
conversations with the Assistant will be lost.
|
||||
</p>
|
||||
</Modal.Content>
|
||||
<p className="text-sm text-foreground-light">
|
||||
Are you sure you want to close the editor? Any unsaved changes on your policy and
|
||||
conversations with the Assistant will be lost.
|
||||
</p>
|
||||
</ConfirmationModal>
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -187,21 +187,19 @@ const PolicyEditorModal = ({
|
||||
<div>
|
||||
<ConfirmationModal
|
||||
visible={isClosingPolicyEditorModal}
|
||||
header="Discard changes"
|
||||
buttonLabel="Discard"
|
||||
onSelectCancel={() => setIsClosingPolicyEditorModal(false)}
|
||||
onSelectConfirm={() => {
|
||||
title="Discard changes"
|
||||
confirmLabel="Discard"
|
||||
onCancel={() => setIsClosingPolicyEditorModal(false)}
|
||||
onConfirm={() => {
|
||||
onSelectCancel()
|
||||
setIsClosingPolicyEditorModal(false)
|
||||
setIsDirty(false)
|
||||
}}
|
||||
>
|
||||
<Modal.Content>
|
||||
<p className="py-4 text-sm text-foreground-light">
|
||||
There are unsaved changes. Are you sure you want to close the editor? Your changes
|
||||
will be lost.
|
||||
</p>
|
||||
</Modal.Content>
|
||||
<p className="text-sm text-foreground-light">
|
||||
There are unsaved changes. Are you sure you want to close the editor? Your changes will
|
||||
be lost.
|
||||
</p>
|
||||
</ConfirmationModal>
|
||||
{view === POLICY_MODAL_VIEWS.SELECTION ? (
|
||||
<PolicySelection
|
||||
|
||||
@@ -224,35 +224,30 @@ const UserDropdown = ({
|
||||
|
||||
<ConfirmationModal
|
||||
visible={isDeleteModalOpen}
|
||||
header="Confirm to delete"
|
||||
buttonLabel="Delete"
|
||||
buttonLoadingLabel="Delete"
|
||||
onSelectCancel={() => setIsDeleteModalOpen(false)}
|
||||
onSelectConfirm={() => {
|
||||
title="Confirm to delete"
|
||||
confirmLabel="Delete"
|
||||
onCancel={() => setIsDeleteModalOpen(false)}
|
||||
onConfirm={() => {
|
||||
handleDelete()
|
||||
}}
|
||||
>
|
||||
<Modal.Content>
|
||||
<p className="py-4 text-sm text-foreground-light">
|
||||
This is permanent! Are you sure you want to delete user {user.email}?
|
||||
</p>
|
||||
</Modal.Content>
|
||||
<p className="text-sm text-foreground-light">
|
||||
This is permanent! Are you sure you want to delete user {user.email}?
|
||||
</p>
|
||||
</ConfirmationModal>
|
||||
|
||||
<ConfirmationModal
|
||||
visible={isDeleteFactorsModalOpen}
|
||||
header="Confirm to delete"
|
||||
buttonLabel="Delete"
|
||||
onSelectCancel={() => setIsDeleteFactorsModalOpen(false)}
|
||||
onSelectConfirm={() => {
|
||||
title="Confirm to delete"
|
||||
confirmLabel="Delete"
|
||||
onCancel={() => setIsDeleteFactorsModalOpen(false)}
|
||||
onConfirm={() => {
|
||||
handleDeleteFactors()
|
||||
}}
|
||||
>
|
||||
<Modal.Content>
|
||||
<p className="py-4 text-sm text-foreground-light">
|
||||
This is permanent! Are you sure you want to delete the user's MFA factors?
|
||||
</p>
|
||||
</Modal.Content>
|
||||
<p className="text-sm text-foreground-light">
|
||||
This is permanent! Are you sure you want to delete the user's MFA factors?
|
||||
</p>
|
||||
</ConfirmationModal>
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -344,44 +344,28 @@ const BranchManagement = () => {
|
||||
/>
|
||||
|
||||
<ConfirmationModal
|
||||
danger
|
||||
variant={'destructive'}
|
||||
size="medium"
|
||||
loading={isDisabling}
|
||||
visible={showDisableBranching}
|
||||
header="Confirm disable branching for project"
|
||||
buttonLabel="Confirm disable branching"
|
||||
buttonLoadingLabel="Disabling branching..."
|
||||
onSelectConfirm={() => onConfirmDisableBranching()}
|
||||
onSelectCancel={() => setShowDisableBranching(false)}
|
||||
title="Confirm disable branching for project"
|
||||
confirmLabel="Confirm disable branching"
|
||||
confirmLabelLoading="Disabling branching..."
|
||||
onConfirm={() => onConfirmDisableBranching()}
|
||||
onCancel={() => setShowDisableBranching(false)}
|
||||
alert={{
|
||||
title: 'This action cannot be undone',
|
||||
description:
|
||||
'All database preview branches will be removed upon disabling branching. You may still re-enable branching again thereafter, but your existing preview branches will not be restored.',
|
||||
}}
|
||||
>
|
||||
<Modal.Content>
|
||||
<div className="py-6">
|
||||
<Alert_Shadcn_ variant="warning">
|
||||
<IconAlertTriangle strokeWidth={2} />
|
||||
<AlertTitle_Shadcn_>This action cannot be undone</AlertTitle_Shadcn_>
|
||||
<AlertDescription_Shadcn_>
|
||||
All database preview branches will be removed upon disabling branching. You may
|
||||
still re-enable branching again thereafter, but your existing preview branches will
|
||||
not be restored.
|
||||
</AlertDescription_Shadcn_>
|
||||
</Alert_Shadcn_>
|
||||
<ul className="mt-4 space-y-5">
|
||||
<li className="flex gap-3">
|
||||
<div>
|
||||
<strong className="text-sm">Before you disable branching, consider:</strong>
|
||||
<ul className="space-y-2 mt-2 text-sm text-foreground-light">
|
||||
<li className="list-disc ml-6">
|
||||
Your project no longer requires database previews.
|
||||
</li>
|
||||
<li className="list-disc ml-6">
|
||||
None of your database previews are currently being used in any app.
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</Modal.Content>
|
||||
<p className="text-sm">Before you disable branching, consider:</p>
|
||||
<ul className="space-y-2 mt-2 text-sm text-foreground-light">
|
||||
<li className="list-disc ml-6">Your project no longer requires database previews.</li>
|
||||
<li className="list-disc ml-6">
|
||||
None of your database previews are currently being used in any app.
|
||||
</li>
|
||||
</ul>
|
||||
</ConfirmationModal>
|
||||
|
||||
<CreateBranchModal visible={showCreateBranch} onClose={() => setShowCreateBranch(false)} />
|
||||
|
||||
@@ -244,22 +244,19 @@ export const BranchRow = ({
|
||||
</DropdownMenu>
|
||||
|
||||
<ConfirmationModal
|
||||
danger
|
||||
variant={'destructive'}
|
||||
visible={showConfirmResetModal}
|
||||
buttonLabel="Reset branch"
|
||||
header="Confirm branch reset"
|
||||
confirmLabel="Reset branch"
|
||||
title="Confirm branch reset"
|
||||
loading={isResetting}
|
||||
onSelectCancel={() => {
|
||||
onCancel={() => {
|
||||
setShowConfirmResetModal(false)
|
||||
}}
|
||||
onSelectConfirm={onConfirmReset}
|
||||
onConfirm={onConfirmReset}
|
||||
>
|
||||
<Modal.Content>
|
||||
<p className="py-4 text-sm text-foreground-light">
|
||||
Are you sure you want to reset the "{branch.name}" branch? All data will be
|
||||
deleted.
|
||||
</p>
|
||||
</Modal.Content>
|
||||
<p className="text-sm text-foreground-light">
|
||||
Are you sure you want to reset the "{branch.name}" branch? All data will be deleted.
|
||||
</p>
|
||||
</ConfirmationModal>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -107,26 +107,22 @@ const BackupsList = () => {
|
||||
</div>
|
||||
<ConfirmationModal
|
||||
size="medium"
|
||||
buttonLabel="Confirm restore"
|
||||
buttonLoadingLabel="Restoring"
|
||||
confirmLabel="Confirm restore"
|
||||
confirmLabelLoading="Restoring"
|
||||
visible={selectedBackup !== undefined}
|
||||
header="Confirm to restore from backup"
|
||||
title="Confirm to restore from backup"
|
||||
loading={isRestoring || isSuccessBackup}
|
||||
onSelectCancel={() => setSelectedBackup(undefined)}
|
||||
onSelectConfirm={() => {
|
||||
onCancel={() => setSelectedBackup(undefined)}
|
||||
onConfirm={() => {
|
||||
if (selectedBackup === undefined) return console.error('Backup required')
|
||||
restoreFromBackup({ ref: projectRef, backup: selectedBackup })
|
||||
}}
|
||||
>
|
||||
<Modal.Content>
|
||||
<div className="pt-6 pb-5">
|
||||
<p>
|
||||
Are you sure you want to restore from
|
||||
{dayjs(selectedBackup?.inserted_at).format('DD MMM YYYY')}? This will destroy any new
|
||||
data written since this backup was made.
|
||||
</p>
|
||||
</div>
|
||||
</Modal.Content>
|
||||
<p>
|
||||
Are you sure you want to restore from
|
||||
{dayjs(selectedBackup?.inserted_at).format('DD MMM YYYY')}? This will destroy any new data
|
||||
written since this backup was made.
|
||||
</p>
|
||||
</ConfirmationModal>
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -46,40 +46,32 @@ const DeleteEnumeratedTypeModal = ({
|
||||
|
||||
return (
|
||||
<ConfirmationModal
|
||||
danger
|
||||
variant={'destructive'}
|
||||
size="medium"
|
||||
loading={isDeleting}
|
||||
visible={visible}
|
||||
header={
|
||||
title={
|
||||
<>
|
||||
Confirm to delete enumerated type{' '}
|
||||
<code className="text-sm">{selectedEnumeratedType?.name}</code>
|
||||
</>
|
||||
}
|
||||
buttonLabel="Confirm delete"
|
||||
buttonLoadingLabel="Deleting..."
|
||||
onSelectConfirm={() => onConfirmDeleteType()}
|
||||
onSelectCancel={onClose}
|
||||
confirmLabel="Confirm delete"
|
||||
confirmLabelLoading="Deleting..."
|
||||
onCancel={onClose}
|
||||
onConfirm={() => onConfirmDeleteType()}
|
||||
alert={{
|
||||
title: 'This action cannot be undone',
|
||||
description:
|
||||
'You will need to re-create the enumerated type if you want to revert the deletion.',
|
||||
}}
|
||||
>
|
||||
<Modal.Content>
|
||||
<div className="py-6">
|
||||
<Alert_Shadcn_ variant="warning">
|
||||
<IconAlertTriangle strokeWidth={2} />
|
||||
<AlertTitle_Shadcn_>This action cannot be undone</AlertTitle_Shadcn_>
|
||||
<AlertDescription_Shadcn_>
|
||||
You will need to re-create the enumerated type if you want to revert the deletion.
|
||||
</AlertDescription_Shadcn_>
|
||||
</Alert_Shadcn_>
|
||||
<div className="mt-4">
|
||||
<strong className="text-sm">Before deleting this enumerated type, consider:</strong>
|
||||
<ul className="space-y-2 mt-2 text-sm text-foreground-light">
|
||||
<li className="list-disc ml-6">
|
||||
This enumerated type is no longer in use in any tables or functions
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</Modal.Content>
|
||||
<p className="text-sm">Before deleting this enumerated type, consider:</p>
|
||||
<ul className="space-y-2 mt-2 text-sm text-foreground-light">
|
||||
<li className="list-disc ml-6">
|
||||
This enumerated type is no longer in use in any tables or functions
|
||||
</li>
|
||||
</ul>
|
||||
</ConfirmationModal>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -139,17 +139,15 @@ const ExtensionCard = ({ extension }: ExtensionCardProps) => {
|
||||
/>
|
||||
<ConfirmationModal
|
||||
visible={isDisableModalOpen}
|
||||
header="Confirm to disable extension"
|
||||
buttonLabel="Disable"
|
||||
buttonLoadingLabel="Disabling"
|
||||
onSelectCancel={() => setIsDisableModalOpen(false)}
|
||||
onSelectConfirm={() => onConfirmDisable()}
|
||||
title="Confirm to disable extension"
|
||||
confirmLabel="Disable"
|
||||
confirmLabelLoading="Disabling"
|
||||
onCancel={() => setIsDisableModalOpen(false)}
|
||||
onConfirm={() => onConfirmDisable()}
|
||||
>
|
||||
<Modal.Content>
|
||||
<p className="py-4 text-sm text-foreground-light">
|
||||
Are you sure you want to turn OFF the "{extension.name}" extension?
|
||||
</p>
|
||||
</Modal.Content>
|
||||
<p className="text-sm text-foreground-light">
|
||||
Are you sure you want to turn OFF the "{extension.name}" extension?
|
||||
</p>
|
||||
</ConfirmationModal>
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -405,20 +405,18 @@ const CreateFunction = ({ func, visible, setVisible }: CreateFunctionProps) => {
|
||||
) : null}
|
||||
<ConfirmationModal
|
||||
visible={isClosingPanel}
|
||||
header="Discard changes"
|
||||
buttonLabel="Discard"
|
||||
onSelectCancel={() => setIsClosingPanel(false)}
|
||||
onSelectConfirm={() => {
|
||||
title="Discard changes"
|
||||
confirmLabel="Discard"
|
||||
onCancel={() => setIsClosingPanel(false)}
|
||||
onConfirm={() => {
|
||||
setIsClosingPanel(false)
|
||||
setVisible(!visible)
|
||||
}}
|
||||
>
|
||||
<Modal.Content>
|
||||
<p className="py-4 text-sm text-foreground-light">
|
||||
There are unsaved changes. Are you sure you want to close the panel? Your changes will
|
||||
be lost.
|
||||
</p>
|
||||
</Modal.Content>
|
||||
<p className="text-sm text-foreground-light">
|
||||
There are unsaved changes. Are you sure you want to close the panel? Your changes will
|
||||
be lost.
|
||||
</p>
|
||||
</ConfirmationModal>
|
||||
</SheetContent>
|
||||
</Sheet>
|
||||
|
||||
@@ -310,21 +310,19 @@ const EditHookPanel = ({ visible, selectedHook, onClose }: EditHookPanelProps) =
|
||||
</SidePanel>
|
||||
<ConfirmationModal
|
||||
visible={isClosingPanel}
|
||||
header="Discard changes"
|
||||
buttonLabel="Discard"
|
||||
onSelectCancel={() => setIsClosingPanel(false)}
|
||||
onSelectConfirm={() => {
|
||||
title="Discard changes"
|
||||
confirmLabel="Discard"
|
||||
onCancel={() => setIsClosingPanel(false)}
|
||||
onConfirm={() => {
|
||||
setIsClosingPanel(false)
|
||||
setIsEdited(false)
|
||||
onClose()
|
||||
}}
|
||||
>
|
||||
<Modal.Content>
|
||||
<p className="py-4 text-sm text-foreground-light">
|
||||
There are unsaved changes. Are you sure you want to close the panel? Your changes will
|
||||
be lost.
|
||||
</p>
|
||||
</Modal.Content>
|
||||
<p className="text-sm text-foreground-light">
|
||||
There are unsaved changes. Are you sure you want to close the panel? Your changes will be
|
||||
lost.
|
||||
</p>
|
||||
</ConfirmationModal>
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -278,48 +278,41 @@ const Indexes = () => {
|
||||
<CreateIndexSidePanel visible={showCreateIndex} onClose={() => setShowCreateIndex(false)} />
|
||||
|
||||
<ConfirmationModal
|
||||
danger
|
||||
variant="warning"
|
||||
size="medium"
|
||||
loading={isExecuting}
|
||||
visible={selectedIndexToDelete !== undefined}
|
||||
header={
|
||||
title={
|
||||
<>
|
||||
Confirm to delete index <code className="text-sm">{selectedIndexToDelete?.name}</code>
|
||||
</>
|
||||
}
|
||||
buttonLabel="Confirm delete"
|
||||
buttonLoadingLabel="Deleting..."
|
||||
onSelectConfirm={() =>
|
||||
confirmLabel="Confirm delete"
|
||||
confirmLabelLoading="Deleting..."
|
||||
onConfirm={() =>
|
||||
selectedIndexToDelete !== undefined ? onConfirmDeleteIndex(selectedIndexToDelete) : {}
|
||||
}
|
||||
onSelectCancel={() => setSelectedIndexToDelete(undefined)}
|
||||
onCancel={() => setSelectedIndexToDelete(undefined)}
|
||||
alert={{
|
||||
title: 'This action cannot be undone',
|
||||
description:
|
||||
'Deleting an index that is still in use will cause queries to slow down, and in some cases causing significant performance issues.',
|
||||
}}
|
||||
>
|
||||
<Modal.Content>
|
||||
<div className="py-6">
|
||||
<Alert_Shadcn_ variant="warning">
|
||||
<IconAlertTriangle strokeWidth={2} />
|
||||
<AlertTitle_Shadcn_>This action cannot be undone</AlertTitle_Shadcn_>
|
||||
<AlertDescription_Shadcn_>
|
||||
Deleting an index that is still in use will cause queries to slow down, and in some
|
||||
cases causing significant performance issues.
|
||||
</AlertDescription_Shadcn_>
|
||||
</Alert_Shadcn_>
|
||||
<ul className="mt-4 space-y-5">
|
||||
<li className="flex gap-3">
|
||||
<div>
|
||||
<strong className="text-sm">Before deleting this index, consider:</strong>
|
||||
<ul className="space-y-2 mt-2 text-sm text-foreground-light">
|
||||
<li className="list-disc ml-6">This index is no longer in use</li>
|
||||
<li className="list-disc ml-6">
|
||||
The table which the index is on is not currently in use, as dropping an index
|
||||
requires a short exclusive access lock on the table.
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</Modal.Content>
|
||||
<ul className="mt-4 space-y-5">
|
||||
<li className="flex gap-3">
|
||||
<div>
|
||||
<strong className="text-sm">Before deleting this index, consider:</strong>
|
||||
<ul className="space-y-2 mt-2 text-sm text-foreground-light">
|
||||
<li className="list-disc ml-6">This index is no longer in use</li>
|
||||
<li className="list-disc ml-6">
|
||||
The table which the index is on is not currently in use, as dropping an index
|
||||
requires a short exclusive access lock on the table.
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</ConfirmationModal>
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -173,21 +173,19 @@ const PublicationsList = ({ onSelectPublication = noop }: PublicationsListProps)
|
||||
|
||||
<ConfirmationModal
|
||||
visible={toggleListenEventValue !== null}
|
||||
header={`Confirm to toggle sending ${toggleListenEventValue?.event.event.toLowerCase()} events`}
|
||||
buttonLabel="Confirm"
|
||||
buttonLoadingLabel="Updating"
|
||||
onSelectCancel={() => setToggleListenEventValue(null)}
|
||||
onSelectConfirm={() => {
|
||||
title={`Confirm to toggle sending ${toggleListenEventValue?.event.event.toLowerCase()} events`}
|
||||
confirmLabel="Confirm"
|
||||
confirmLabelLoading="Updating"
|
||||
onCancel={() => setToggleListenEventValue(null)}
|
||||
onConfirm={() => {
|
||||
toggleListenEvent()
|
||||
}}
|
||||
>
|
||||
<Modal.Content>
|
||||
<p className="py-4 text-sm text-foreground-light">
|
||||
Are you sure you want to {toggleListenEventValue?.currentStatus ? 'stop' : 'start'}{' '}
|
||||
sending {toggleListenEventValue?.event.event.toLowerCase()} events for{' '}
|
||||
{toggleListenEventValue?.publication.name}?
|
||||
</p>
|
||||
</Modal.Content>
|
||||
<p className="text-sm text-foreground-light">
|
||||
Are you sure you want to {toggleListenEventValue?.currentStatus ? 'stop' : 'start'}{' '}
|
||||
sending {toggleListenEventValue?.event.event.toLowerCase()} events for{' '}
|
||||
{toggleListenEventValue?.publication.name}?
|
||||
</p>
|
||||
</ConfirmationModal>
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -383,20 +383,18 @@ const CreateTrigger = ({ trigger, visible, setVisible }: CreateTriggerProps) =>
|
||||
</CreateTriggerContext.Provider>
|
||||
<ConfirmationModal
|
||||
visible={isClosingPanel}
|
||||
header="Discard changes"
|
||||
buttonLabel="Discard"
|
||||
onSelectCancel={() => setIsClosingPanel(false)}
|
||||
onSelectConfirm={() => {
|
||||
title="Discard changes"
|
||||
confirmLabel="Discard"
|
||||
onCancel={() => setIsClosingPanel(false)}
|
||||
onConfirm={() => {
|
||||
setIsClosingPanel(false)
|
||||
setVisible(!visible)
|
||||
}}
|
||||
>
|
||||
<Modal.Content>
|
||||
<p className="py-4 text-sm text-foreground-light">
|
||||
There are unsaved changes. Are you sure you want to close the panel? Your changes
|
||||
will be lost.
|
||||
</p>
|
||||
</Modal.Content>
|
||||
<p className="text-sm text-foreground-light">
|
||||
There are unsaved changes. Are you sure you want to close the panel? Your changes
|
||||
will be lost.
|
||||
</p>
|
||||
</ConfirmationModal>
|
||||
</div>
|
||||
) : (
|
||||
|
||||
@@ -121,22 +121,20 @@ const EdgeFunctionSecrets = () => {
|
||||
<ConfirmationModal
|
||||
loading={isDeleting}
|
||||
visible={selectedSecret !== undefined}
|
||||
buttonLabel="Delete secret"
|
||||
buttonLoadingLabel="Deleting secret"
|
||||
header={`Confirm to delete secret "${selectedSecret?.name}"`}
|
||||
onSelectCancel={() => setSelectedSecret(undefined)}
|
||||
onSelectConfirm={() => {
|
||||
confirmLabel="Delete secret"
|
||||
confirmLabelLoading="Deleting secret"
|
||||
title={`Confirm to delete secret "${selectedSecret?.name}"`}
|
||||
onCancel={() => setSelectedSecret(undefined)}
|
||||
onConfirm={() => {
|
||||
if (selectedSecret !== undefined) {
|
||||
deleteSecret({ projectRef, secrets: [selectedSecret.name] })
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Modal.Content className="py-4">
|
||||
<p className="text-sm">
|
||||
Before removing this secret, do ensure that none of your edge functions are currently
|
||||
actively using this secret. This action cannot be undone.
|
||||
</p>
|
||||
</Modal.Content>
|
||||
<p className="text-sm">
|
||||
Before removing this secret, do ensure that none of your edge functions are currently
|
||||
actively using this secret. This action cannot be undone.
|
||||
</p>
|
||||
</ConfirmationModal>
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -137,29 +137,26 @@ const IntegrationConnectionItem = forwardRef<HTMLLIElement, IntegrationConnectio
|
||||
/>
|
||||
|
||||
<ConfirmationModal
|
||||
danger
|
||||
variant="destructive"
|
||||
size={type === 'GitHub' && isBranchingEnabled ? 'medium' : 'small'}
|
||||
visible={isOpen}
|
||||
header={`Confirm to delete ${type} connection`}
|
||||
buttonLabel="Delete connection"
|
||||
onSelectCancel={onCancel}
|
||||
onSelectConfirm={onConfirm}
|
||||
title={`Confirm to delete ${type} connection`}
|
||||
confirmLabel="Delete connection"
|
||||
onCancel={onCancel}
|
||||
onConfirm={onConfirm}
|
||||
alert={
|
||||
type === 'GitHub' && isBranchingEnabled
|
||||
? {
|
||||
title: 'Branching will be disabled for this project',
|
||||
description: ` Deleting this GitHub connection will remove all preview branches on this project,
|
||||
and also disable branching for ${project.name}`,
|
||||
}
|
||||
: {}
|
||||
}
|
||||
>
|
||||
<Modal.Content className="py-4 flex flex-col gap-y-4">
|
||||
{type === 'GitHub' && isBranchingEnabled && (
|
||||
<Alert_Shadcn_ variant="warning">
|
||||
<WarningIcon />
|
||||
<AlertTitle_Shadcn_>Branching will be disabled for this project</AlertTitle_Shadcn_>
|
||||
<AlertDescription_Shadcn_>
|
||||
Deleting this GitHub connection will remove all preview branches on this project,
|
||||
and also disable branching for {project.name}
|
||||
</AlertDescription_Shadcn_>
|
||||
</Alert_Shadcn_>
|
||||
)}
|
||||
<p className="text-sm text-foreground-light">
|
||||
This action cannot be undone. Are you sure you want to delete this {type} connection?
|
||||
</p>
|
||||
</Modal.Content>
|
||||
<p className="text-sm text-foreground-light">
|
||||
This action cannot be undone. Are you sure you want to delete this {type} connection?
|
||||
</p>
|
||||
</ConfirmationModal>
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -73,53 +73,46 @@ const SOC2 = () => {
|
||||
)}
|
||||
<ConfirmationModal
|
||||
visible={isOpen}
|
||||
header="Non-Disclosure Agreement to access Supabase's SOC2 Report"
|
||||
buttonLabel="I agree"
|
||||
buttonLoadingLabel="Downloading"
|
||||
onSelectCancel={() => setIsOpen(false)}
|
||||
size="large"
|
||||
onSelectConfirm={() => {
|
||||
title="Non-Disclosure Agreement to access Supabase's SOC2 Report"
|
||||
confirmLabel="I agree"
|
||||
confirmLabelLoading="Downloading"
|
||||
onCancel={() => setIsOpen(false)}
|
||||
onConfirm={() => {
|
||||
if (slug) fetchSOC2(slug)
|
||||
}}
|
||||
>
|
||||
<Modal.Content>
|
||||
<div className="py-4 text-sm text-foreground-light pl-30">
|
||||
<ol className="list-decimal list-inside">
|
||||
<li>The information that you are about to access is confidential.</li>
|
||||
<ol className="list-decimal list-inside text-sm text-foreground-light pl-30">
|
||||
<li>The information that you are about to access is confidential.</li>
|
||||
<li>
|
||||
Your access to our SOC 2 materials is governed by confidentiality obligations
|
||||
contained in the agreement between Supabase, Inc ("Supabase", "we", "our" or "us") and
|
||||
the Supabase customer that has authorized you to access our platform to obtain this
|
||||
information (our "Customer").
|
||||
</li>
|
||||
<li>
|
||||
You must ensure that you treat the information in our SOC 2 materials in accordance
|
||||
with those confidentiality obligations, as communicated to you by the Customer.
|
||||
</li>
|
||||
<li>
|
||||
By clicking "I agree" below or otherwise accessing our SOC 2 materials, you:
|
||||
<ol className="list-[lower-roman] list-inside pl-4">
|
||||
<li>acknowledge that you have read and understood this Confidentiality Notice;</li>
|
||||
<li>
|
||||
Your access to our SOC 2 materials is governed by confidentiality obligations
|
||||
contained in the agreement between Supabase, Inc ("Supabase", "we", "our" or "us")
|
||||
and the Supabase customer that has authorized you to access our platform to obtain
|
||||
this information (our "Customer").
|
||||
</li>
|
||||
<li>
|
||||
You must ensure that you treat the information in our SOC 2 materials in
|
||||
accordance with those confidentiality obligations, as communicated to you by the
|
||||
Customer.
|
||||
</li>
|
||||
<li>
|
||||
By clicking "I agree" below or otherwise accessing our SOC 2 materials, you:
|
||||
<ol className="list-[lower-roman] list-inside pl-4">
|
||||
<li>
|
||||
acknowledge that you have read and understood this Confidentiality Notice;
|
||||
</li>
|
||||
<li>
|
||||
confirm that you have been authorized by the Customer to access this
|
||||
information, and your use of our SOC 2 materials is subject to the
|
||||
confidentiality obligations owed by the Customer to us.
|
||||
</li>
|
||||
</ol>
|
||||
</li>
|
||||
<li>
|
||||
This Confidentiality Notice does not substitute or supersede any agreement between
|
||||
us and the Customer, or any internal rules or policies that the Customer requires
|
||||
you to comply with in your access to and use of confidential information. However,
|
||||
your failure to comply with this Confidentiality Notice may be used to determine
|
||||
whether the Customer has complied with its confidentiality obligations to us.
|
||||
confirm that you have been authorized by the Customer to access this information,
|
||||
and your use of our SOC 2 materials is subject to the confidentiality obligations
|
||||
owed by the Customer to us.
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</Modal.Content>
|
||||
</li>
|
||||
<li>
|
||||
This Confidentiality Notice does not substitute or supersede any agreement between us
|
||||
and the Customer, or any internal rules or policies that the Customer requires you to
|
||||
comply with in your access to and use of confidential information. However, your
|
||||
failure to comply with this Confidentiality Notice may be used to determine whether
|
||||
the Customer has complied with its confidentiality obligations to us.
|
||||
</li>
|
||||
</ol>
|
||||
</ConfirmationModal>
|
||||
</ScaffoldSectionContent>
|
||||
</ScaffoldSection>
|
||||
|
||||
@@ -190,18 +190,16 @@ const MemberActions = ({ member, roles }: MemberActionsProps) => {
|
||||
|
||||
<ConfirmationModal
|
||||
visible={isDeleteModalOpen}
|
||||
header="Confirm to remove"
|
||||
buttonLabel="Remove"
|
||||
onSelectCancel={() => setIsDeleteModalOpen(false)}
|
||||
onSelectConfirm={() => {
|
||||
title="Confirm to remove"
|
||||
confirmLabel="Remove"
|
||||
onCancel={() => setIsDeleteModalOpen(false)}
|
||||
onConfirm={() => {
|
||||
handleMemberDelete()
|
||||
}}
|
||||
>
|
||||
<Modal.Content>
|
||||
<p className="py-4 text-sm text-foreground-light">
|
||||
This is permanent! Are you sure you want to remove {member.primary_email}
|
||||
</p>
|
||||
</Modal.Content>
|
||||
<p className="text-sm text-foreground-light">
|
||||
This is permanent! Are you sure you want to remove {member.primary_email}
|
||||
</p>
|
||||
</ConfirmationModal>
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -143,18 +143,16 @@ const TeamSettings = () => {
|
||||
|
||||
<ConfirmationModal
|
||||
visible={isLeaveTeamModalOpen}
|
||||
header="Are you sure?"
|
||||
buttonLabel="Leave"
|
||||
onSelectCancel={() => setIsLeaveTeamModalOpen(false)}
|
||||
onSelectConfirm={() => {
|
||||
title="Are you sure?"
|
||||
confirmLabel="Leave"
|
||||
onCancel={() => setIsLeaveTeamModalOpen(false)}
|
||||
onConfirm={() => {
|
||||
leaveTeam()
|
||||
}}
|
||||
>
|
||||
<Modal.Content>
|
||||
<p className="py-4 text-sm text-foreground-light">
|
||||
Are you sure you want to leave this organization? This is permanent.
|
||||
</p>
|
||||
</Modal.Content>
|
||||
<p className="text-sm text-foreground-light">
|
||||
Are you sure you want to leave this organization? This is permanent.
|
||||
</p>
|
||||
</ConfirmationModal>
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
import { Modal } from 'ui'
|
||||
|
||||
import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal'
|
||||
|
||||
interface ApplyConfigModalProps {
|
||||
visible: boolean
|
||||
onSelectCancel: () => void
|
||||
onSelectConfirm: () => void
|
||||
}
|
||||
|
||||
export const ApplyConfigModal = (props: ApplyConfigModalProps) => {
|
||||
return (
|
||||
<ConfirmationModal
|
||||
header="Previously found messages will be lost"
|
||||
danger
|
||||
buttonLabel="Confirm"
|
||||
size="small"
|
||||
{...props}
|
||||
>
|
||||
<Modal.Content>
|
||||
<div className="py-4">
|
||||
<p className="text-sm text-foreground"></p>
|
||||
<p className="text-sm text-foreground-light">
|
||||
The realtime inspector will clear currently collected messages and start listening for
|
||||
new messages matching the updated filters.
|
||||
</p>
|
||||
</div>
|
||||
</Modal.Content>
|
||||
</ConfirmationModal>
|
||||
)
|
||||
}
|
||||
@@ -18,10 +18,10 @@ import {
|
||||
} from 'ui'
|
||||
|
||||
import Telemetry from 'lib/telemetry'
|
||||
import { ApplyConfigModal } from '../ApplyConfigModal'
|
||||
import { RealtimeConfig } from '../useRealtimeMessages'
|
||||
import { FilterSchema } from './FilterSchema'
|
||||
import { FilterTable } from './FilterTable'
|
||||
import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal'
|
||||
|
||||
interface RealtimeFilterPopoverProps {
|
||||
config: RealtimeConfig
|
||||
@@ -194,10 +194,14 @@ export const RealtimeFilterPopover = ({ config, onChangeConfig }: RealtimeFilter
|
||||
</div>
|
||||
</PopoverContent_Shadcn_>
|
||||
</Popover_Shadcn_>
|
||||
<ApplyConfigModal
|
||||
<ConfirmationModal
|
||||
title="Previously found messages will be lost"
|
||||
variant="destructive"
|
||||
confirmLabel="Confirm"
|
||||
size="small"
|
||||
visible={applyConfigOpen}
|
||||
onSelectCancel={() => setApplyConfigOpen(false)}
|
||||
onSelectConfirm={() => {
|
||||
onCancel={() => setApplyConfigOpen(false)}
|
||||
onConfirm={() => {
|
||||
Telemetry.sendEvent(
|
||||
{
|
||||
category: 'realtime_inspector',
|
||||
@@ -211,7 +215,12 @@ export const RealtimeFilterPopover = ({ config, onChangeConfig }: RealtimeFilter
|
||||
setApplyConfigOpen(false)
|
||||
setOpen(false)
|
||||
}}
|
||||
/>
|
||||
>
|
||||
<p className="text-sm text-foreground-light">
|
||||
The realtime inspector will clear currently collected messages and start listening for new
|
||||
messages matching the updated filters.
|
||||
</p>
|
||||
</ConfirmationModal>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -213,32 +213,31 @@ const JWTSettings = () => {
|
||||
</Panel>
|
||||
|
||||
<ConfirmationModal
|
||||
danger
|
||||
variant={'destructive'}
|
||||
size="medium"
|
||||
visible={isRegeneratingKey}
|
||||
header="Confirm to generate a new JWT secret"
|
||||
buttonLabel="Generate new secret"
|
||||
buttonLoadingLabel="Generating"
|
||||
onSelectCancel={() => setIsGeneratingKey(false)}
|
||||
onSelectConfirm={() => handleJwtSecretUpdate('ROLL', setIsGeneratingKey)}
|
||||
>
|
||||
<Modal.Content className="py-4 space-y-4">
|
||||
<Alert_Shadcn_ variant="warning">
|
||||
<IconAlertTriangle />
|
||||
<AlertTitle_Shadcn_>This will invalidate all existing API keys</AlertTitle_Shadcn_>
|
||||
<AlertDescription_Shadcn_>
|
||||
title="Confirm to generate a new JWT secret"
|
||||
confirmLabel="Generate new secret"
|
||||
confirmLabelLoading="Generating"
|
||||
onCancel={() => setIsGeneratingKey(false)}
|
||||
onConfirm={() => handleJwtSecretUpdate('ROLL', setIsGeneratingKey)}
|
||||
alert={{
|
||||
title: 'This will invalidate all existing API keys',
|
||||
description: (
|
||||
<>
|
||||
Generating a new JWT secret will invalidate <u className="text-foreground">all</u> of
|
||||
your API keys, including your <code className="text-xs">service_role</code> and{' '}
|
||||
<code className="text-xs">anon</code> keys. Your project will also be restarted during
|
||||
this process, which will terminate any existing connections. You may receive API
|
||||
errors for up to 2 minutes while the new secret is deployed.
|
||||
</AlertDescription_Shadcn_>
|
||||
</Alert_Shadcn_>
|
||||
<p className="text-foreground text-sm">
|
||||
This action cannot be undone and the old JWT secret will be lost. All existing API keys
|
||||
will be invalidated, and any open connections will be terminated.
|
||||
</p>
|
||||
</Modal.Content>
|
||||
</>
|
||||
),
|
||||
}}
|
||||
>
|
||||
<p className="text-foreground text-sm">
|
||||
This action cannot be undone and the old JWT secret will be lost. All existing API keys
|
||||
will be invalidated, and any open connections will be terminated.
|
||||
</p>
|
||||
</ConfirmationModal>
|
||||
|
||||
<Modal
|
||||
|
||||
@@ -106,28 +106,20 @@ const BannedIPs = () => {
|
||||
</FormPanel>
|
||||
|
||||
<ConfirmationModal
|
||||
danger
|
||||
variant="destructive"
|
||||
size="medium"
|
||||
loading={isUnbanning}
|
||||
visible={showUnban}
|
||||
header="Confirm Unban IP"
|
||||
buttonLabel="Confirm Unban"
|
||||
buttonLoadingLabel="Unbanning..."
|
||||
onSelectConfirm={onConfirmUnbanIP}
|
||||
onSelectCancel={() => setShowUnban(false)}
|
||||
>
|
||||
<Modal.Content>
|
||||
<div className="py-6">
|
||||
<Alert_Shadcn_ variant="warning">
|
||||
<IconAlertTriangle strokeWidth={2} />
|
||||
<AlertTitle_Shadcn_>This action cannot be undone</AlertTitle_Shadcn_>
|
||||
<AlertDescription_Shadcn_>
|
||||
Are you sure you want to unban this IP address {selectedIPToUnban}?
|
||||
</AlertDescription_Shadcn_>
|
||||
</Alert_Shadcn_>
|
||||
</div>
|
||||
</Modal.Content>
|
||||
</ConfirmationModal>
|
||||
title="Confirm Unban IP"
|
||||
confirmLabel="Confirm Unban"
|
||||
confirmLabelLoading="Unbanning..."
|
||||
onCancel={() => setShowUnban(false)}
|
||||
onConfirm={onConfirmUnbanIP}
|
||||
alert={{
|
||||
title: 'This action cannot be undone',
|
||||
description: `Are you sure you want to unban this IP address ${selectedIPToUnban}?`,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -147,20 +147,18 @@ const CustomDomainActivate = ({ projectRef, customDomain }: CustomDomainActivate
|
||||
size="small"
|
||||
loading={isCheckingRecord || isActivating}
|
||||
visible={isActivateConfirmModalVisible}
|
||||
header={
|
||||
<div>
|
||||
title={
|
||||
<>
|
||||
Are you sure you want to activate the custom domain{' '}
|
||||
<code className="text-sm">{customDomain.hostname}</code> for the project?
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
buttonLabel="Activate"
|
||||
buttonLoadingLabel="Activating"
|
||||
onSelectCancel={() => setIsActivateConfirmModalVisible(false)}
|
||||
onSelectConfirm={onActivateCustomDomain}
|
||||
confirmLabel="Activate"
|
||||
confirmLabelLoading="Activating"
|
||||
onCancel={() => setIsActivateConfirmModalVisible(false)}
|
||||
onConfirm={onActivateCustomDomain}
|
||||
>
|
||||
<Modal.Content className="py-3">
|
||||
<p className="text-sm">The existing Supabase subdomain will be deactivated.</p>
|
||||
</Modal.Content>
|
||||
<p className="text-sm">The existing Supabase subdomain will be deactivated.</p>
|
||||
</ConfirmationModal>
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -94,22 +94,19 @@ const PauseProjectButton = () => {
|
||||
) : null}
|
||||
</Tooltip.Root>
|
||||
<ConfirmationModal
|
||||
danger
|
||||
variant={'destructive'}
|
||||
visible={isModalOpen}
|
||||
loading={isPausing}
|
||||
header="Pause this project?"
|
||||
description=""
|
||||
buttonLabel="Pause project"
|
||||
buttonLoadingLabel="Pausing project"
|
||||
onSelectCancel={() => setIsModalOpen(false)}
|
||||
onSelectConfirm={requestPauseProject}
|
||||
title="Pause this project?"
|
||||
confirmLabel="Pause project"
|
||||
confirmLabelLoading="Pausing project"
|
||||
onCancel={() => setIsModalOpen(false)}
|
||||
onConfirm={requestPauseProject}
|
||||
>
|
||||
<Modal.Content className="py-4">
|
||||
<p className="text-foreground-light text-sm">
|
||||
Are you sure you want to pause this project? It will not be accessible until you unpause
|
||||
it.
|
||||
</p>
|
||||
</Modal.Content>
|
||||
<p className="text-foreground-light text-sm">
|
||||
Are you sure you want to pause this project? It will not be accessible until you unpause
|
||||
it.
|
||||
</p>
|
||||
</ConfirmationModal>
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -59,31 +59,24 @@ const DropAllReplicasConfirmationModal = ({
|
||||
|
||||
return (
|
||||
<ConfirmationModal
|
||||
danger
|
||||
variant={'destructive'}
|
||||
size="medium"
|
||||
loading={isRemoving}
|
||||
visible={visible}
|
||||
header="Confirm to drop all read replicas?"
|
||||
buttonLabel="Drop all replicas"
|
||||
buttonLoadingLabel="Dropping all replicas"
|
||||
onSelectCancel={() => onCancel()}
|
||||
onSelectConfirm={() => onConfirmRemove()}
|
||||
title="Confirm to drop all read replicas?"
|
||||
confirmLabel="Drop all replicas"
|
||||
confirmLabelLoading="Dropping all replicas"
|
||||
onCancel={() => onCancel()}
|
||||
onConfirm={() => onConfirmRemove()}
|
||||
alert={{
|
||||
title: 'This action cannot be undone',
|
||||
description: 'You may still deploy new replicas in this region thereafter',
|
||||
}}
|
||||
>
|
||||
<Modal.Content className="py-3">
|
||||
<Alert_Shadcn_ variant="warning">
|
||||
<IconAlertTriangle strokeWidth={2} />
|
||||
<AlertTitle_Shadcn_>This action cannot be undone</AlertTitle_Shadcn_>
|
||||
<AlertDescription_Shadcn_>
|
||||
You may still deploy new replicas in this region thereafter
|
||||
</AlertDescription_Shadcn_>
|
||||
</Alert_Shadcn_>
|
||||
<div className="text-sm px-1 pt-4">
|
||||
<p>Before deleting all replicas, consider:</p>
|
||||
<ul className="text-foreground-light py-1 list-disc mx-4 space-y-1">
|
||||
<li>Network traffic from this region may slow down</li>
|
||||
</ul>
|
||||
</div>
|
||||
</Modal.Content>
|
||||
<p className="text-sm">Before deleting all replicas, consider:</p>
|
||||
<ul className="text-sm text-foreground-light list-disc">
|
||||
<li>Network traffic from this region may slow down</li>
|
||||
</ul>
|
||||
</ConfirmationModal>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -43,34 +43,27 @@ const DropReplicaConfirmationModal = ({
|
||||
|
||||
return (
|
||||
<ConfirmationModal
|
||||
danger
|
||||
variant="destructive"
|
||||
size="medium"
|
||||
loading={isRemoving}
|
||||
visible={selectedReplica !== undefined}
|
||||
header={`Confirm to drop selected replica? (ID: ${formattedId})`}
|
||||
buttonLabel="Drop replica"
|
||||
buttonLoadingLabel="Dropping replica"
|
||||
onSelectCancel={() => onCancel()}
|
||||
onSelectConfirm={() => onConfirmRemove()}
|
||||
title={`Confirm to drop selected replica? (ID: ${formattedId})`}
|
||||
confirmLabel="Drop replica"
|
||||
confirmLabelLoading="Dropping replica"
|
||||
onCancel={() => onCancel()}
|
||||
onConfirm={() => onConfirmRemove()}
|
||||
alert={{
|
||||
title: 'This action cannot be undone',
|
||||
description: 'You may still deploy a new replica in this region thereafter',
|
||||
}}
|
||||
>
|
||||
<Modal.Content className="py-3">
|
||||
<Alert_Shadcn_ variant="warning">
|
||||
<IconAlertTriangle strokeWidth={2} />
|
||||
<AlertTitle_Shadcn_>This action cannot be undone</AlertTitle_Shadcn_>
|
||||
<AlertDescription_Shadcn_>
|
||||
You may still deploy a new replica in this region thereafter
|
||||
</AlertDescription_Shadcn_>
|
||||
</Alert_Shadcn_>
|
||||
<div className="text-sm px-1 pt-4">
|
||||
<p>Before deleting this replica, consider:</p>
|
||||
<ul className="text-foreground-light py-1 list-disc mx-4 space-y-1">
|
||||
<li>
|
||||
Network traffic from this region may slow down, especially if you have no other
|
||||
replicas in this region
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</Modal.Content>
|
||||
<p className="text-sm">Before deleting this replica, consider:</p>
|
||||
<ul className="text-sm text-foreground-light py-1 list-disc mx-4 space-y-1">
|
||||
<li>
|
||||
Network traffic from this region may slow down, especially if you have no other replicas
|
||||
in this region
|
||||
</li>
|
||||
</ul>
|
||||
</ConfirmationModal>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -285,24 +285,22 @@ const InstanceConfigurationUI = () => {
|
||||
{/* <ConfirmationModal
|
||||
size="medium"
|
||||
visible={selectedReplicaToRestart !== undefined}
|
||||
header="Confirm to restart selected replica?"
|
||||
buttonLabel="Restart replica"
|
||||
buttonLoadingLabel="Restarting replica"
|
||||
onSelectCancel={() => setSelectedReplicaToRestart(undefined)}
|
||||
onSelectConfirm={() => onConfirmRestartReplica()}
|
||||
title="Confirm to restart selected replica?"
|
||||
confirmLabel="Restart replica"
|
||||
confirmLabelLoading="Restarting replica"
|
||||
onCancel={() => setSelectedReplicaToRestart(undefined)}
|
||||
onConfirm={() => onConfirmRestartReplica()}
|
||||
>
|
||||
<Modal.Content className="py-3">
|
||||
<p className="text-sm">Before restarting the replica, consider:</p>
|
||||
<ul className="text-sm text-foreground-light py-1 list-disc mx-4 space-y-1">
|
||||
<li>
|
||||
Network traffic from this region may slow down while the replica is restarting,
|
||||
especially if you have no other replicas in this region
|
||||
</li>
|
||||
</ul>
|
||||
<p className="text-sm mt-2">
|
||||
Are you sure you want to restart this replica (ID: {selectedReplicaToRestart?.id}) now?{' '}
|
||||
</p>
|
||||
</Modal.Content>
|
||||
<p className="text-sm">Before restarting the replica, consider:</p>
|
||||
<ul className="text-sm text-foreground-light py-1 list-disc mx-4 space-y-1">
|
||||
<li>
|
||||
Network traffic from this region may slow down while the replica is restarting,
|
||||
especially if you have no other replicas in this region
|
||||
</li>
|
||||
</ul>
|
||||
<p className="text-sm mt-2">
|
||||
Are you sure you want to restart this replica (ID: {selectedReplicaToRestart?.id}) now?{' '}
|
||||
</p>
|
||||
</ConfirmationModal> */}
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -132,20 +132,18 @@ const SavedQueriesItem = ({ item }: SavedQueriesItemProps) => {
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
<ConfirmationModal
|
||||
danger
|
||||
variant="destructive"
|
||||
visible={showConfirmModal}
|
||||
buttonLabel="Delete query"
|
||||
header="Confirm to delete saved query"
|
||||
onSelectCancel={() => {
|
||||
confirmLabel="Delete query"
|
||||
title="Confirm to delete saved query"
|
||||
onCancel={() => {
|
||||
setShowConfirmModal(false)
|
||||
}}
|
||||
onSelectConfirm={onConfirmDelete}
|
||||
onConfirm={onConfirmDelete}
|
||||
>
|
||||
<Modal.Content>
|
||||
<p className="py-4 text-sm text-foreground-light">
|
||||
Are you sure you want to delete {item.name}?
|
||||
</p>
|
||||
</Modal.Content>
|
||||
<p className="text-sm text-foreground-light">
|
||||
Are you sure you want to delete {item.name}?
|
||||
</p>
|
||||
</ConfirmationModal>
|
||||
<UpdateSavedQueryModal
|
||||
visible={showUpdateModal}
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
import Link from 'next/link'
|
||||
import toast from 'react-hot-toast'
|
||||
import { Alert, Button, Checkbox, IconExternalLink, Modal } from 'ui'
|
||||
import {
|
||||
Alert,
|
||||
AlertDescription_Shadcn_,
|
||||
AlertTitle_Shadcn_,
|
||||
Alert_Shadcn_,
|
||||
Button,
|
||||
Checkbox,
|
||||
IconExternalLink,
|
||||
Modal,
|
||||
} from 'ui'
|
||||
|
||||
import type { SupaRow } from 'components/grid'
|
||||
import { formatFilterURLParams } from 'components/grid/SupabaseGrid.utils'
|
||||
@@ -220,40 +229,39 @@ const DeleteConfirmationDialogs = ({
|
||||
return (
|
||||
<>
|
||||
<ConfirmationModal
|
||||
danger
|
||||
variant="destructive"
|
||||
size="small"
|
||||
visible={snap.confirmationDialog?.type === 'column'}
|
||||
header={`Confirm deletion of column "${
|
||||
title={`Confirm deletion of column "${
|
||||
snap.confirmationDialog?.type === 'column' && snap.confirmationDialog.column.name
|
||||
}"`}
|
||||
buttonLabel="Delete"
|
||||
buttonLoadingLabel="Deleting"
|
||||
onSelectCancel={() => {
|
||||
confirmLabel="Delete"
|
||||
confirmLabelLoading="Deleting"
|
||||
onCancel={() => {
|
||||
snap.closeConfirmationDialog()
|
||||
}}
|
||||
onSelectConfirm={onConfirmDeleteColumn}
|
||||
onConfirm={onConfirmDeleteColumn}
|
||||
>
|
||||
<Modal.Content>
|
||||
<div className="py-4 space-y-4">
|
||||
<p className="text-sm text-foreground-light">
|
||||
Are you sure you want to delete the selected column? This action cannot be undone.
|
||||
</p>
|
||||
<Checkbox
|
||||
label="Drop column with cascade?"
|
||||
description="Deletes the column and its dependent objects"
|
||||
checked={isDeleteWithCascade}
|
||||
onChange={() => snap.toggleConfirmationIsWithCascade()}
|
||||
/>
|
||||
{isDeleteWithCascade && (
|
||||
<Alert
|
||||
withIcon
|
||||
variant="warning"
|
||||
title="Warning: Dropping with cascade may result in unintended consequences"
|
||||
>
|
||||
<p className="mb-4">
|
||||
All dependent objects will be removed, as will any objects that depend on them,
|
||||
recursively.
|
||||
</p>
|
||||
<div className="space-y-4">
|
||||
<p className="text-sm text-foreground-light">
|
||||
Are you sure you want to delete the selected column? This action cannot be undone.
|
||||
</p>
|
||||
<Checkbox
|
||||
label="Drop column with cascade?"
|
||||
description="Deletes the column and its dependent objects"
|
||||
checked={isDeleteWithCascade}
|
||||
onChange={() => snap.toggleConfirmationIsWithCascade()}
|
||||
/>
|
||||
{isDeleteWithCascade && (
|
||||
<Alert_Shadcn_
|
||||
variant="warning"
|
||||
title="Warning: Dropping with cascade may result in unintended consequences"
|
||||
>
|
||||
<AlertTitle_Shadcn_>
|
||||
All dependent objects will be removed, as will any objects that depend on them,
|
||||
recursively.
|
||||
</AlertTitle_Shadcn_>
|
||||
<AlertDescription_Shadcn_>
|
||||
<Button asChild size="tiny" type="default" icon={<IconExternalLink />}>
|
||||
<Link
|
||||
href="https://www.postgresql.org/docs/current/ddl-depend.html"
|
||||
@@ -263,85 +271,81 @@ const DeleteConfirmationDialogs = ({
|
||||
About dependency tracking
|
||||
</Link>
|
||||
</Button>
|
||||
</Alert>
|
||||
)}
|
||||
</div>
|
||||
</Modal.Content>
|
||||
</AlertDescription_Shadcn_>
|
||||
</Alert_Shadcn_>
|
||||
)}
|
||||
</div>
|
||||
</ConfirmationModal>
|
||||
|
||||
<ConfirmationModal
|
||||
danger
|
||||
variant={'destructive'}
|
||||
size="small"
|
||||
visible={snap.confirmationDialog?.type === 'table'}
|
||||
header={
|
||||
title={
|
||||
<span className="break-words">{`Confirm deletion of table "${selectedTable?.name}"`}</span>
|
||||
}
|
||||
buttonLabel="Delete"
|
||||
buttonLoadingLabel="Deleting"
|
||||
onSelectCancel={() => {
|
||||
confirmLabel="Delete"
|
||||
confirmLabelLoading="Deleting"
|
||||
onCancel={() => {
|
||||
snap.closeConfirmationDialog()
|
||||
}}
|
||||
onSelectConfirm={onConfirmDeleteTable}
|
||||
onConfirm={onConfirmDeleteTable}
|
||||
>
|
||||
<Modal.Content>
|
||||
<div className="py-4 space-y-4">
|
||||
<p className="text-sm text-foreground-light">
|
||||
Are you sure you want to delete the selected table? This action cannot be undone.
|
||||
</p>
|
||||
<Checkbox
|
||||
label="Drop table with cascade?"
|
||||
description="Deletes the table and its dependent objects"
|
||||
checked={isDeleteWithCascade}
|
||||
onChange={() => snap.toggleConfirmationIsWithCascade(!isDeleteWithCascade)}
|
||||
/>
|
||||
{isDeleteWithCascade && (
|
||||
<Alert
|
||||
withIcon
|
||||
variant="warning"
|
||||
title="Warning: Dropping with cascade may result in unintended consequences"
|
||||
>
|
||||
<p className="mb-4">
|
||||
All dependent objects will be removed, as will any objects that depend on them,
|
||||
recursively.
|
||||
</p>
|
||||
<Button asChild size="tiny" type="default" icon={<IconExternalLink />}>
|
||||
<Link
|
||||
href="https://www.postgresql.org/docs/current/ddl-depend.html"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
About dependency tracking
|
||||
</Link>
|
||||
</Button>
|
||||
</Alert>
|
||||
)}
|
||||
</div>
|
||||
</Modal.Content>
|
||||
<div className="space-y-4">
|
||||
<p className="text-sm text-foreground-light">
|
||||
Are you sure you want to delete the selected table? This action cannot be undone.
|
||||
</p>
|
||||
<Checkbox
|
||||
label="Drop table with cascade?"
|
||||
description="Deletes the table and its dependent objects"
|
||||
checked={isDeleteWithCascade}
|
||||
onChange={() => snap.toggleConfirmationIsWithCascade(!isDeleteWithCascade)}
|
||||
/>
|
||||
{isDeleteWithCascade && (
|
||||
<Alert
|
||||
withIcon
|
||||
variant="warning"
|
||||
title="Warning: Dropping with cascade may result in unintended consequences"
|
||||
>
|
||||
<p className="mb-4">
|
||||
All dependent objects will be removed, as will any objects that depend on them,
|
||||
recursively.
|
||||
</p>
|
||||
<Button asChild size="tiny" type="default" icon={<IconExternalLink />}>
|
||||
<Link
|
||||
href="https://www.postgresql.org/docs/current/ddl-depend.html"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
About dependency tracking
|
||||
</Link>
|
||||
</Button>
|
||||
</Alert>
|
||||
)}
|
||||
</div>
|
||||
</ConfirmationModal>
|
||||
|
||||
<ConfirmationModal
|
||||
danger
|
||||
variant={'destructive'}
|
||||
size="small"
|
||||
visible={snap.confirmationDialog?.type === 'row'}
|
||||
header={
|
||||
title={
|
||||
<span className="break-words">
|
||||
Confirm to delete the selected row{numRows > 1 && 's'}
|
||||
</span>
|
||||
}
|
||||
buttonLabel="Delete"
|
||||
buttonLoadingLabel="Deleting"
|
||||
onSelectCancel={() => snap.closeConfirmationDialog()}
|
||||
onSelectConfirm={() => onConfirmDeleteRow()}
|
||||
confirmLabel="Delete"
|
||||
confirmLabelLoading="Deleting"
|
||||
onCancel={() => snap.closeConfirmationDialog()}
|
||||
onConfirm={() => onConfirmDeleteRow()}
|
||||
>
|
||||
<Modal.Content>
|
||||
<div className="py-4 space-y-4">
|
||||
<p className="text-sm text-foreground-light">
|
||||
Are you sure you want to delete {isAllRowsSelected ? 'all' : 'the selected'}{' '}
|
||||
{numRows > 1 && `${numRows} `}row
|
||||
{numRows > 1 && 's'}? This action cannot be undone.
|
||||
</p>
|
||||
</div>
|
||||
</Modal.Content>
|
||||
<div className="space-y-4">
|
||||
<p className="text-sm text-foreground-light">
|
||||
Are you sure you want to delete {isAllRowsSelected ? 'all' : 'the selected'}{' '}
|
||||
{numRows > 1 && `${numRows} `}row
|
||||
{numRows > 1 && 's'}? This action cannot be undone.
|
||||
</p>
|
||||
</div>
|
||||
</ConfirmationModal>
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -267,13 +267,13 @@ const GridHeaderActions = ({ table, isViewSelected, isTableSelected }: GridHeade
|
||||
<ConfirmationModal
|
||||
visible={showEnableRealtime}
|
||||
loading={isTogglingRealtime}
|
||||
header={`${isRealtimeEnabled ? 'Disable' : 'Enable'} realtime for ${table.name}`}
|
||||
buttonLabel={`${isRealtimeEnabled ? 'Disable' : 'Enable'} realtime`}
|
||||
buttonLoadingLabel={`${isRealtimeEnabled ? 'Disabling' : 'Enabling'} realtime`}
|
||||
onSelectCancel={() => setShowEnableRealtime(false)}
|
||||
onSelectConfirm={() => toggleRealtime()}
|
||||
title={`${isRealtimeEnabled ? 'Disable' : 'Enable'} realtime for ${table.name}`}
|
||||
confirmLabel={`${isRealtimeEnabled ? 'Disable' : 'Enable'} realtime`}
|
||||
confirmLabelLoading={`${isRealtimeEnabled ? 'Disabling' : 'Enabling'} realtime`}
|
||||
onCancel={() => setShowEnableRealtime(false)}
|
||||
onConfirm={() => toggleRealtime()}
|
||||
>
|
||||
<Modal.Content className="py-4 space-y-2">
|
||||
<div className="space-y-2">
|
||||
<p className="text-sm">
|
||||
Once realtime has been {isRealtimeEnabled ? 'disabled' : 'enabled'}, the table will{' '}
|
||||
{isRealtimeEnabled ? 'no longer ' : ''}broadcast any changes to authorized subscribers.
|
||||
@@ -287,7 +287,7 @@ const GridHeaderActions = ({ table, isViewSelected, isTableSelected }: GridHeade
|
||||
settings.
|
||||
</p>
|
||||
)}
|
||||
</Modal.Content>
|
||||
</div>
|
||||
</ConfirmationModal>
|
||||
|
||||
<ConfirmModal
|
||||
|
||||
@@ -642,21 +642,19 @@ const SidePanelEditor = ({
|
||||
/>
|
||||
<ConfirmationModal
|
||||
visible={isClosingPanel}
|
||||
header="Discard changes"
|
||||
buttonLabel="Discard"
|
||||
onSelectCancel={() => setIsClosingPanel(false)}
|
||||
onSelectConfirm={() => {
|
||||
title="Discard changes"
|
||||
confirmLabel="Discard"
|
||||
onCancel={() => setIsClosingPanel(false)}
|
||||
onConfirm={() => {
|
||||
setIsClosingPanel(false)
|
||||
setIsEdited(false)
|
||||
snap.closeSidePanel()
|
||||
}}
|
||||
>
|
||||
<Modal.Content>
|
||||
<p className="py-4 text-sm text-foreground-light">
|
||||
There are unsaved changes. Are you sure you want to close the panel? Your changes will
|
||||
be lost.
|
||||
</p>
|
||||
</Modal.Content>
|
||||
<p className="text-sm text-foreground-light">
|
||||
There are unsaved changes. Are you sure you want to close the panel? Your changes will be
|
||||
lost.
|
||||
</p>
|
||||
</ConfirmationModal>
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -402,18 +402,16 @@ const TableEditor = ({
|
||||
|
||||
<ConfirmationModal
|
||||
visible={rlsConfirmVisible}
|
||||
header="Turn off Row Level Security"
|
||||
buttonLabel="Confirm"
|
||||
title="Turn off Row Level Security"
|
||||
confirmLabel="Confirm"
|
||||
size="medium"
|
||||
onSelectCancel={() => setRlsConfirmVisible(false)}
|
||||
onSelectConfirm={() => {
|
||||
onCancel={() => setRlsConfirmVisible(false)}
|
||||
onConfirm={() => {
|
||||
onUpdateField({ isRLSEnabled: !tableFields.isRLSEnabled })
|
||||
setRlsConfirmVisible(false)
|
||||
}}
|
||||
>
|
||||
<Modal.Content>
|
||||
<RLSDisableModalContent />
|
||||
</Modal.Content>
|
||||
<RLSDisableModalContent />
|
||||
</ConfirmationModal>
|
||||
</SidePanel.Content>
|
||||
|
||||
|
||||
@@ -287,13 +287,14 @@ const ReportsMenu = () => {
|
||||
}}
|
||||
/>
|
||||
<ConfirmationModal
|
||||
header="Delete custom report"
|
||||
buttonLabel="Delete report"
|
||||
buttonLoadingLabel="Deleting report"
|
||||
title="Delete custom report"
|
||||
confirmLabel="Delete report"
|
||||
confirmLabelLoading="Deleting report"
|
||||
size="medium"
|
||||
loading={deleteReport.isLoading}
|
||||
visible={deleteModalOpen}
|
||||
onSelectConfirm={async () => {
|
||||
onCancel={() => setDeleteModalOpen(false)}
|
||||
onConfirm={async () => {
|
||||
if (selectedReport) {
|
||||
if (!selectedReport.id) return
|
||||
await deleteReport.mutateAsync({
|
||||
@@ -305,17 +306,12 @@ const ReportsMenu = () => {
|
||||
}
|
||||
setDeleteModalOpen(false)
|
||||
}}
|
||||
onSelectCancel={() => setDeleteModalOpen(false)}
|
||||
>
|
||||
<Modal.Content>
|
||||
<div className="my-6">
|
||||
<div className="text-sm text-foreground-light grid gap-4">
|
||||
<div className="grid gap-1">
|
||||
<p>Are you sure you want to delete '{selectedReport?.name}'?</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-sm text-foreground-light grid gap-4">
|
||||
<div className="grid gap-1">
|
||||
<p>Are you sure you want to delete '{selectedReport?.name}'?</p>
|
||||
</div>
|
||||
</Modal.Content>
|
||||
</div>
|
||||
</ConfirmationModal>
|
||||
<CreateReportModal
|
||||
visible={showNewReportModal}
|
||||
|
||||
@@ -28,6 +28,7 @@ import type { SqlSnippet } from 'data/content/sql-snippets-query'
|
||||
import { useSqlEditorStateSnapshot } from 'state/sql-editor'
|
||||
import { CriticalIcon, WarningIcon } from 'ui-patterns/Icons/StatusIcons'
|
||||
import { QueryItemActions } from './QueryItemActions'
|
||||
import { Eye, Unlock } from 'lucide-react'
|
||||
|
||||
export interface QueryItemProps {
|
||||
tabInfo: SqlSnippet
|
||||
@@ -188,58 +189,50 @@ const QueryItem = ({
|
||||
onComplete={() => setRenameModalOpen(false)}
|
||||
/>
|
||||
<ConfirmationModal
|
||||
header="Confirm to delete query"
|
||||
buttonLabel="Delete query"
|
||||
buttonLoadingLabel="Deleting query"
|
||||
title="Confirm to delete query"
|
||||
confirmLabel="Delete query"
|
||||
confirmLabelLoading="Deleting query"
|
||||
size="medium"
|
||||
loading={isDeleting}
|
||||
visible={deleteModalOpen}
|
||||
onSelectConfirm={onConfirmDelete}
|
||||
onSelectCancel={() => setDeleteModalOpen(false)}
|
||||
variant={'destructive'}
|
||||
onCancel={() => setDeleteModalOpen(false)}
|
||||
onConfirm={onConfirmDelete}
|
||||
alert={
|
||||
visibility === 'project'
|
||||
? {
|
||||
title: 'This SQL snippet will be lost forever',
|
||||
description:
|
||||
'Deleting this query will remove it for all members of the project team.',
|
||||
}
|
||||
: {}
|
||||
}
|
||||
>
|
||||
<Modal.Content className="my-6 grid gap-1 text-sm text-foreground-light grid gap-4">
|
||||
{visibility === 'project' && (
|
||||
<Alert_Shadcn_ variant="destructive">
|
||||
<CriticalIcon />
|
||||
<AlertTitle_Shadcn_>This SQL snippet will be lost forever</AlertTitle_Shadcn_>
|
||||
<AlertDescription_Shadcn_>
|
||||
Deleting this query will remove it for all members of the project team.
|
||||
</AlertDescription_Shadcn_>
|
||||
</Alert_Shadcn_>
|
||||
)}
|
||||
<p>Are you sure you want to delete '{name}'?</p>
|
||||
</Modal.Content>
|
||||
<p className="text-sm">Are you sure you want to delete '{name}'?</p>
|
||||
</ConfirmationModal>
|
||||
<ConfirmationModal
|
||||
header="Confirm sharing query"
|
||||
title="Confirm sharing query"
|
||||
size="medium"
|
||||
buttonLabel="Share query"
|
||||
buttonLoadingLabel="Sharing query"
|
||||
confirmLabel="Share query"
|
||||
confirmLabelLoading="Sharing query"
|
||||
visible={shareModalOpen}
|
||||
onSelectConfirm={onConfirmShare}
|
||||
onSelectCancel={() => setShareModalOpen(false)}
|
||||
onCancel={() => setShareModalOpen(false)}
|
||||
onConfirm={onConfirmShare}
|
||||
alert={{
|
||||
title: 'This SQL query will become public to all team members',
|
||||
description: 'Anyone with access to the project can view it',
|
||||
}}
|
||||
>
|
||||
<Modal.Content className="my-6 text-sm text-foreground-light grid gap-4 grid gap-1">
|
||||
<Alert_Shadcn_ variant="warning">
|
||||
<WarningIcon />
|
||||
<AlertTitle_Shadcn_>
|
||||
This SQL query will become public to all team members
|
||||
</AlertTitle_Shadcn_>
|
||||
<AlertDescription_Shadcn_>
|
||||
Anyone with access to the project can view it
|
||||
</AlertDescription_Shadcn_>
|
||||
</Alert_Shadcn_>
|
||||
<ul className="mt-4 space-y-5">
|
||||
<li className="flex gap-3">
|
||||
<IconEye />
|
||||
<span>Project members will have read-only access to this query.</span>
|
||||
</li>
|
||||
<li className="flex gap-3">
|
||||
<IconUnlock />
|
||||
<span>Anyone will be able to duplicate it to their personal snippets.</span>
|
||||
</li>
|
||||
</ul>
|
||||
</Modal.Content>
|
||||
<ul className="text-sm text-foreground-light space-y-5">
|
||||
<li className="flex gap-3">
|
||||
<Eye />
|
||||
<span>Project members will have read-only access to this query.</span>
|
||||
</li>
|
||||
<li className="flex gap-3">
|
||||
<Unlock />
|
||||
<span>Anyone will be able to duplicate it to their personal snippets.</span>
|
||||
</li>
|
||||
</ul>
|
||||
</ConfirmationModal>
|
||||
<DownloadSnippetModal
|
||||
id={id as string}
|
||||
|
||||
@@ -349,35 +349,24 @@ const SideBarContent = () => {
|
||||
</div>
|
||||
|
||||
<ConfirmationModal
|
||||
header="Confirm to delete query"
|
||||
buttonLabel={`Delete ${selectedQueries.length.toLocaleString()} quer${selectedQueries.length > 1 ? 'ies' : 'y'}`}
|
||||
buttonLoadingLabel="Deleting query"
|
||||
title="Confirm to delete query"
|
||||
confirmLabel={`Delete ${selectedQueries.length.toLocaleString()} quer${selectedQueries.length > 1 ? 'ies' : 'y'}`}
|
||||
confirmLabelLoading="Deleting query"
|
||||
size="medium"
|
||||
loading={isDeleting}
|
||||
visible={showDeleteModal}
|
||||
onSelectConfirm={onConfirmDelete}
|
||||
onSelectCancel={() => setShowDeleteModal(false)}
|
||||
danger
|
||||
onConfirm={onConfirmDelete}
|
||||
onCancel={() => setShowDeleteModal(false)}
|
||||
variant={'destructive'}
|
||||
alert={{
|
||||
title: 'This action cannot be undone',
|
||||
description: 'The selected SQL snippets cannot be recovered once deleted',
|
||||
}}
|
||||
>
|
||||
<Modal.Content>
|
||||
<div className="my-6">
|
||||
<div className="text-sm text-foreground-light grid gap-4">
|
||||
<div className="grid gap-y-4">
|
||||
<Alert_Shadcn_ variant="destructive">
|
||||
<WarningIcon />
|
||||
<AlertTitle_Shadcn_>This action cannot be undone</AlertTitle_Shadcn_>
|
||||
<AlertDescription_Shadcn_>
|
||||
The selected SQL snippets cannot be recovered once deleted
|
||||
</AlertDescription_Shadcn_>
|
||||
</Alert_Shadcn_>
|
||||
<p>
|
||||
Are you sure you want to delete the selected {selectedQueries.length} quer
|
||||
{selectedQueries.length > 1 ? 'ies' : 'y'}?
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Modal.Content>
|
||||
<p className="text-sm text-foreground-light">
|
||||
Are you sure you want to delete the selected {selectedQueries.length} quer
|
||||
{selectedQueries.length > 1 ? 'ies' : 'y'}?
|
||||
</p>
|
||||
</ConfirmationModal>
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -40,24 +40,19 @@ export const EmptyBucketModal = ({ visible = false, bucket, onClose }: EmptyBuck
|
||||
|
||||
return (
|
||||
<ConfirmationModal
|
||||
danger
|
||||
variant={'destructive'}
|
||||
size="small"
|
||||
title={`Confirm to delete all contents from ${bucket?.name}`}
|
||||
confirmLabel="Empty bucket"
|
||||
visible={visible}
|
||||
onSelectCancel={() => onClose()}
|
||||
onSelectConfirm={onEmptyBucket}
|
||||
header={`Confirm to delete all contents from ${bucket?.name}`}
|
||||
buttonLabel="Empty bucket"
|
||||
onCancel={() => onClose()}
|
||||
onConfirm={onEmptyBucket}
|
||||
alert={{
|
||||
title: 'This action cannot be undone',
|
||||
description: 'The contents of your bucket cannot be recovered once deleted',
|
||||
}}
|
||||
>
|
||||
<Modal.Content className="py-4 space-y-2">
|
||||
<Alert_Shadcn_ variant="warning">
|
||||
<IconAlertTriangle strokeWidth={2} />
|
||||
<AlertTitle_Shadcn_>This action cannot be undone</AlertTitle_Shadcn_>
|
||||
<AlertDescription_Shadcn_>
|
||||
The contents of your bucket cannot be recovered once deleted
|
||||
</AlertDescription_Shadcn_>
|
||||
</Alert_Shadcn_>
|
||||
<p className="text-sm">Are you sure you want to empty the bucket "{bucket?.name}"?</p>
|
||||
</Modal.Content>
|
||||
<p className="text-sm">Are you sure you want to empty the bucket "{bucket?.name}"?</p>
|
||||
</ConfirmationModal>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,80 +1,135 @@
|
||||
import { MouseEventHandler, PropsWithChildren, useEffect, useState } from 'react'
|
||||
import { Button, Modal } from 'ui'
|
||||
'use client'
|
||||
|
||||
import { MouseEventHandler, forwardRef, useEffect, useState } from 'react'
|
||||
import {
|
||||
Admonition,
|
||||
Alert_Shadcn_,
|
||||
Button,
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogSection,
|
||||
DialogSectionSeparator,
|
||||
DialogTitle,
|
||||
cn,
|
||||
} from 'ui'
|
||||
import { DialogHeader } from 'ui/src/components/shadcn/ui/dialog'
|
||||
|
||||
export interface ConfirmationModalProps {
|
||||
visible: boolean
|
||||
danger?: boolean
|
||||
loading?: boolean
|
||||
header: string | JSX.Element
|
||||
description?: string
|
||||
size?: 'small' | 'tiny' | 'medium' | 'large'
|
||||
buttonLabel: string
|
||||
buttonLoadingLabel?: string
|
||||
buttonDisabled?: boolean
|
||||
onSelectCancel: () => void
|
||||
onSelectConfirm: () => void
|
||||
}
|
||||
|
||||
const ConfirmationModal = ({
|
||||
visible = false,
|
||||
loading: loading_ = false,
|
||||
danger = false,
|
||||
header = '',
|
||||
description = '',
|
||||
size = 'small',
|
||||
buttonLabel = '',
|
||||
buttonLoadingLabel = '',
|
||||
buttonDisabled = false,
|
||||
onSelectCancel = () => {},
|
||||
onSelectConfirm = () => {},
|
||||
children,
|
||||
}: PropsWithChildren<ConfirmationModalProps>) => {
|
||||
useEffect(() => {
|
||||
if (visible) {
|
||||
setLoading(false)
|
||||
}
|
||||
}, [visible])
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(loading_)
|
||||
}, [loading_])
|
||||
|
||||
const [loading, setLoading] = useState(false)
|
||||
|
||||
const onConfirm: MouseEventHandler<HTMLButtonElement> = (e) => {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
setLoading(true)
|
||||
onSelectConfirm()
|
||||
visible: boolean
|
||||
title: string | React.ReactNode
|
||||
size?: React.ComponentProps<typeof DialogContent>['size']
|
||||
confirmLabel?: string
|
||||
confirmLabelLoading?: string
|
||||
cancelLabel?: string
|
||||
onConfirm: () => void
|
||||
onCancel: () => void
|
||||
disabled?: boolean
|
||||
variant?: React.ComponentProps<typeof Alert_Shadcn_>['variant']
|
||||
alert?: {
|
||||
base?: React.ComponentProps<typeof Alert_Shadcn_>
|
||||
title?: string
|
||||
description?: string | React.ReactNode
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal
|
||||
layout="vertical"
|
||||
visible={visible}
|
||||
header={header}
|
||||
description={description}
|
||||
size={size}
|
||||
onCancel={onSelectCancel}
|
||||
customFooter={
|
||||
<div className="flex justify-end w-full items-center space-x-3">
|
||||
<Button type="default" disabled={loading} onClick={onSelectCancel}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
type={danger ? 'danger' : 'primary'}
|
||||
loading={loading}
|
||||
disabled={loading || buttonDisabled}
|
||||
onClick={onConfirm}
|
||||
>
|
||||
{(loading && buttonLoadingLabel) || buttonLabel}
|
||||
</Button>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
{children}
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
|
||||
const ConfirmationModal = forwardRef<
|
||||
React.ElementRef<typeof DialogContent>,
|
||||
React.ComponentPropsWithoutRef<typeof Dialog> & ConfirmationModalProps
|
||||
>(
|
||||
(
|
||||
{
|
||||
title,
|
||||
size = 'small',
|
||||
visible,
|
||||
onCancel,
|
||||
onConfirm,
|
||||
loading: loading_ = false,
|
||||
cancelLabel = 'Cancel',
|
||||
confirmLabel = 'Submit',
|
||||
confirmLabelLoading,
|
||||
alert,
|
||||
children,
|
||||
variant = 'default',
|
||||
disabled,
|
||||
...props
|
||||
},
|
||||
ref
|
||||
) => {
|
||||
useEffect(() => {
|
||||
if (visible) {
|
||||
setLoading(false)
|
||||
}
|
||||
}, [visible])
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(loading_)
|
||||
}, [loading_])
|
||||
|
||||
const [loading, setLoading] = useState(false)
|
||||
|
||||
const onSubmit: MouseEventHandler<HTMLButtonElement> = (e) => {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
setLoading(true)
|
||||
onConfirm()
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
open={visible}
|
||||
{...props}
|
||||
onOpenChange={() => {
|
||||
if (visible) {
|
||||
onCancel()
|
||||
}
|
||||
}}
|
||||
>
|
||||
<DialogContent ref={ref} className="p-0 gap-0 pb-5 !block" size={size}>
|
||||
<DialogHeader className={cn('border-b')} padding={'small'}>
|
||||
<DialogTitle className="">{title}</DialogTitle>
|
||||
</DialogHeader>
|
||||
{alert && (
|
||||
<Admonition
|
||||
type={variant as 'default' | 'destructive' | 'warning'}
|
||||
label={alert.title}
|
||||
description={alert.description}
|
||||
className="border-r-0 border-l-0 rounded-none -mt-px [&_svg]:ml-0.5 mb-0"
|
||||
{...alert?.base}
|
||||
/>
|
||||
)}
|
||||
{children && (
|
||||
<>
|
||||
<DialogSection padding={'small'}>{children}</DialogSection>
|
||||
<DialogSectionSeparator />
|
||||
</>
|
||||
)}
|
||||
<div className="flex gap-2 px-5 pt-5">
|
||||
<Button size="medium" block type="default" disabled={loading}>
|
||||
{cancelLabel}
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
block
|
||||
size="medium"
|
||||
type={
|
||||
variant === 'destructive' ? 'danger' : variant === 'warning' ? 'warning' : 'primary'
|
||||
}
|
||||
htmlType="submit"
|
||||
loading={loading}
|
||||
disabled={loading || disabled}
|
||||
onClick={onSubmit}
|
||||
className="truncate"
|
||||
>
|
||||
{confirmLabel}
|
||||
</Button>
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
ConfirmationModal.displayName = 'ConfirmationModal'
|
||||
|
||||
export default ConfirmationModal
|
||||
|
||||
@@ -5,15 +5,13 @@ import { ReactNode, forwardRef } from 'react'
|
||||
import { useForm } from 'react-hook-form'
|
||||
import {
|
||||
Admonition,
|
||||
AlertDescription_Shadcn_,
|
||||
AlertTitle_Shadcn_,
|
||||
Alert_Shadcn_,
|
||||
Button,
|
||||
DialogContent,
|
||||
DialogSectionSeparator,
|
||||
DialogSection,
|
||||
DialogTitle,
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogSection,
|
||||
DialogSectionSeparator,
|
||||
DialogTitle,
|
||||
FormControl_Shadcn_,
|
||||
FormDescription_Shadcn_,
|
||||
FormField_Shadcn_,
|
||||
@@ -21,15 +19,10 @@ import {
|
||||
FormLabel_Shadcn_,
|
||||
FormMessage_Shadcn_,
|
||||
Form_Shadcn_,
|
||||
IconAlertCircle,
|
||||
Input_Shadcn_,
|
||||
cn,
|
||||
} from 'ui'
|
||||
import {
|
||||
DIALOG_PADDING_X_SMALL,
|
||||
DIALOG_PADDING_Y_SMALL,
|
||||
DialogHeader,
|
||||
} from 'ui/src/components/shadcn/ui/dialog'
|
||||
import { DialogHeader } from 'ui/src/components/shadcn/ui/dialog'
|
||||
import { z } from 'zod'
|
||||
|
||||
export interface TextConfirmModalProps {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { cva } from 'class-variance-authority'
|
||||
import { forwardRef } from 'react'
|
||||
import React, { forwardRef } from 'react'
|
||||
import { cn } from '../../lib/utils/cn'
|
||||
import { Alert, AlertDescription, AlertTitle } from './../shadcn/ui/alert'
|
||||
|
||||
@@ -15,7 +15,7 @@ export interface AdmonitionProps {
|
||||
| 'warning'
|
||||
label?: string
|
||||
title?: string
|
||||
description?: string
|
||||
description?: string | React.ReactNode
|
||||
}
|
||||
|
||||
const admonitionToAlertMapping: Record<
|
||||
|
||||
Reference in New Issue
Block a user