Files
supabase/apps/studio/components/interfaces/Integrations/Vault/Secrets/AddNewSecretModal.tsx
Joshen Lim e48c909b31 Chore/deprecate use query state with select part 04 (#42747)
## Context

Related to FE-2461

More refactoring to clean up usage of `useQueryStateWithSelect`, in the
following pages
- Auth OAuth Apps
- Cron Jobs
- Vaults Secrets Management
- Database Hooks
- Wrappers

## To test

In each of those pages, verify that
- [ ] Clicking the "new" cta updates the URL params, and refreshing
should re-open the sheet
- [ ] Editing an existing item should update URL params, and refreshing
should re-open the sheet with the right item
- Verify that if the URL param has the wrong id, page should not open
the sheet, show a toast, and reset the URL param
- [ ] Deleting an existing item should update URL params, and refreshing
should re-open the sheet with the right item
- Verify that if the URL param has the wrong id, page should not open
the sheet, show a toast, and reset the URL param

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
* Added "item not found" toasts and clearer feedback after
create/update/delete actions; prevent opening create flows when server
features are disabled.

* **Style**
* Standardized button labels, sizes and modal/dialog spacing; refined
table column widths and inline code formatting for readability.

* **Refactor**
* Simplified UI state flows across OAuth Apps, Hooks/Webhooks, Cron
Jobs, Vault Secrets, and Wrappers to use consistent URL-driven
interactions and centralized modals.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-02-13 16:18:28 +08:00

113 lines
3.5 KiB
TypeScript

import { useVaultSecretCreateMutation } from 'data/vault/vault-secret-create-mutation'
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
import { Eye, EyeOff } from 'lucide-react'
import { parseAsBoolean, useQueryState } from 'nuqs'
import { useEffect, useState } from 'react'
import { toast } from 'sonner'
import { Button, Form, Input, Modal } from 'ui'
export const AddNewSecretModal = () => {
const { data: project } = useSelectedProjectQuery()
const [showSecretValue, setShowSecretValue] = useState(false)
const { mutateAsync: addSecret } = useVaultSecretCreateMutation()
const [showAddSecretModal, setShowAddSecretModal] = useQueryState(
'new',
parseAsBoolean.withDefault(false)
)
useEffect(() => {
if (showAddSecretModal) {
setShowSecretValue(false)
}
}, [showAddSecretModal])
const validate = (values: any) => {
const errors: any = {}
if (values.name.length === 0) errors.name = 'Please provide a name for your secret'
if (values.secret.length === 0) errors.secret = 'Please enter your secret value'
return errors
}
const onAddNewSecret = async (values: any, { setSubmitting }: any) => {
if (!project) return console.error('Project is required')
setSubmitting(true)
try {
setSubmitting(true)
await addSecret({
projectRef: project.ref,
connectionString: project?.connectionString,
name: values.name,
description: values.description,
secret: values.secret,
})
toast.success(`Successfully added new secret ${values.name}`)
setShowAddSecretModal(null)
} catch (error: any) {
// [Joshen] No error handler required as they are all handled within the mutations already
} finally {
setSubmitting(false)
}
}
return (
<Modal
hideFooter
size="medium"
visible={showAddSecretModal}
onCancel={() => setShowAddSecretModal(null)}
header="Add new secret"
>
<Form
id="add-new-secret-form"
initialValues={{ name: '', description: '', secret: '' }}
validate={validate}
validateOnBlur={false}
onSubmit={onAddNewSecret}
>
{({ isSubmitting }: any) => {
return (
<>
<Modal.Content className="space-y-4">
<Input id="name" label="Name" />
<Input id="description" label="Description" labelOptional="Optional" />
<Input
id="secret"
type={showSecretValue ? 'text' : 'password'}
label="Secret value"
actions={
<div className="mr-1">
<Button
type="default"
icon={showSecretValue ? <EyeOff /> : <Eye />}
onClick={() => setShowSecretValue(!showSecretValue)}
/>
</div>
}
/>
</Modal.Content>
<Modal.Separator />
<Modal.Content className="flex items-center justify-end space-x-2">
<Button
type="default"
disabled={isSubmitting}
onClick={() => setShowAddSecretModal(null)}
>
Cancel
</Button>
<Button htmlType="submit" disabled={isSubmitting} loading={isSubmitting}>
Add secret
</Button>
</Modal.Content>
</>
)
}}
</Form>
</Modal>
)
}