Files
supabase/apps/studio/components/interfaces/SQLEditor/RenameQueryModal.tsx
T
143f49414b Feat/tabs (#31071)
* init

* Update inner-side-menu.mdx

* chore: update SQL sidebar to use ui pattern components

* mor

* Update

* Update index.tsx

* init: merge table editor and sql editor and schema visualization together

* more

* move to valtio

* fix issue with Command+B shortcut

* now shows in treeviews if item is opened in tab

* Update ProjectLayout.tsx

* fix sidebar

* fix schema selector for non explorer version

* show schema name in tabs

* added schema names to tabs

* tabs have been updated to support preview tabs

* fix URL issue

* add empty state stuff

* Update SQLEditorNav.tsx

* preview tab works now

* more tabs stuff. 'new' tab also added

* new tab concept

* updates

* fix type errors

* remove unused files

* update test

* move back button, fix width issues on sidebar

* update sidebar logic

* Update ProjectLayout.tsx

* lots of updates. layouts now streamlined. localstorage for tabs in use

* moar

* bunch of new tab logic

* fix empty tab issue

* Update tabs.ts

* layouts switched

* new pages now have fixed layouts

* fix tabs

* fix code bg

* add tabs support for multiple project refs

* intialization issue

* update ID handling

* fixed isOpened state for SQL snippets

* remove old assistant because its bugging up panels

* preview style works in sql editor

* fix border

* removes preview tab if there is one

* fix background of loading skeleton

* lots of issues with types/icons/redirect

* new tab cards

* snippets in empty state now work

* moar stuff

* tabs now in feature flags

* Update tabs.ts

* Update tabs.ts

* moar

* add feature previews

* remove code not needed

* Update next-env.d.ts

* Delete FeaturePreviewModal.tsx

* fix typescript errors. remove more explorer stuff

* remove explorer files

* fixed issues with templates and quickstarts tab

* fixed active state when tabs are not opted in

* logic error

* fix open/highlight issue when opted out of tabs

* templates/quickstarts now displayed with new cards

* Update recent-items.tsx

* Update new-tab.tsx

* add icon back in

* add old empty state back in

* recent items updated to respect project ref

* localstorage cleanup on deletion

* moar

* overflow tabs now working

* correct tab names used for new sql templates/quickstarts

* ongoing queries fix

* cleanup

* update images

* Update RouteValidationWrapper.tsx

* Update AppLayout.tsx

* Update NavigationBar.tsx

* add headers back into side panels

* improve writing

* tabs now drag and drop a billion times better

* Update tabs.tsx

* Update tabs.tsx

* init issues on stores, which caused a race condition.

* fix hydration error

* fix new tab issue in sql

* Update ProjectLayout.tsx

* Update pnpm-lock.yaml

* Update new-tab.tsx

* move EditorMenuListSkeleton

* Fix type issues

* fixes: DESIGN-87

fixes: DESIGN-87

* refactor sort/filter components

* Update rules-set-button-text.tsx

* remove discussions for now

* small styling fixes

* Update FeaturePreviewModal.tsx

* Update FeaturePreviewModal.tsx

* Update RouteValidationWrapper.tsx

* revert

* revert

* revert

* revert

* revert

* more revert

* Update collapse-button.tsx

* Update SQLEditorTreeViewItem.tsx

* revert

* Update SchemaGraph.tsx

* Delete new-upcoming.tsx

* revert

* Update ProjectLayout.tsx

* fix home link

* Update table-editor.spec.ts

* test update

* Update table-editor.spec.ts

* Fix the playwright tests.

* layout fixes

* layout fix

* revert sort/filter

* Update LastSignInWrapper.tsx

* revert

* revert

* remove

* update file names

* revert

* revert

* revert

* Fix TreeView console error props

* Add guards in SQL Editor to ensure that feature preview tabs changes do not affect existing UI when flag is off

* Fix missing DefaultLayout in SQL editor templates + fix New tab

* Remove console log

* Remove DatabaseSelector for SQL editor on local

* Fix SQL editor shared favorites for local

* Fix test

* Ensure NewTab doesn't show up if flag is not toggled for SQL editor

* Decouple UI state changes from content-query and entity-types-infinite-query

* Fix tab closing unnecessary rerouting

* Beef up feature previews

* Fix create new table from table editor new tab

* Fix tabs getting incorrectly reset when going between table and SQL editors

* Fix last visited SQL snippet for both tabs and not tabs

* Fix last visited table for table editor tabs

* Clear dashboard history when closing last tab

* Fix loading dashboard history

* Add comment to refactor stores

* Ensure we only save up to 8 items for recent items for each type

* Remove unneccesary logic in tabs

* Smol style fix for DeleteAccountButton

* Smol fix

* Fix inability to close New tab

---------

Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
Co-authored-by: Alaister Young <a@alaisteryoung.com>
Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com>
2025-03-27 17:46:57 +08:00

193 lines
6.4 KiB
TypeScript

import { useEffect, useState } from 'react'
import { toast } from 'sonner'
import { useParams } from 'common'
import { useSqlTitleGenerateMutation } from 'data/ai/sql-title-mutation'
import { getContentById } from 'data/content/content-id-query'
import {
UpsertContentPayload,
useContentUpsertMutation,
} from 'data/content/content-upsert-mutation'
import { Snippet } from 'data/content/sql-folders-query'
import type { SqlSnippet } from 'data/content/sql-snippets-query'
import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query'
import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization'
import { useSqlEditorV2StateSnapshot } from 'state/sql-editor-v2'
import { createTabId, renameTab } from 'state/tabs'
import { AiIconAnimation, Button, Form, Input, Modal } from 'ui'
import { useIsSQLEditorTabsEnabled } from '../App/FeaturePreview/FeaturePreviewContext'
import { subscriptionHasHipaaAddon } from '../Billing/Subscription/Subscription.utils'
export interface RenameQueryModalProps {
snippet?: SqlSnippet | Snippet
visible: boolean
onCancel: () => void
onComplete: () => void
}
const RenameQueryModal = ({
snippet = {} as any,
visible,
onCancel,
onComplete,
}: RenameQueryModalProps) => {
const { ref } = useParams()
const organization = useSelectedOrganization()
const snapV2 = useSqlEditorV2StateSnapshot()
const { data: subscription } = useOrgSubscriptionQuery({ orgSlug: organization?.slug })
const isSQLSnippet = snippet.type === 'sql'
const isSQLEditorTabsEnabled = useIsSQLEditorTabsEnabled()
// Customers on HIPAA plans should not have access to Supabase AI
const hasHipaaAddon = subscriptionHasHipaaAddon(subscription)
const { id, name, description } = snippet
const [nameInput, setNameInput] = useState(name)
const [descriptionInput, setDescriptionInput] = useState(description)
const { mutate: titleSql, isLoading: isTitleGenerationLoading } = useSqlTitleGenerateMutation({
onSuccess: (data) => {
const { title, description } = data
setNameInput(title)
if (!descriptionInput) setDescriptionInput(description)
},
onError: (error) => {
toast.error(`Failed to rename query: ${error.message}`)
},
})
const generateTitle = async () => {
if ('content' in snippet && isSQLSnippet) {
titleSql({ sql: snippet.content.sql })
} else {
try {
const { content } = await getContentById({ projectRef: ref, id: snippet.id })
if ('sql' in content) {
titleSql({ sql: content.sql })
}
} catch (error) {
toast.error('Unable to generate title based on query contents')
}
}
}
const validate = () => {
const errors: any = {}
if (!nameInput) errors.name = 'Please enter a query name'
return errors
}
const { mutateAsync: upsertContent } = useContentUpsertMutation()
const onSubmit = async (values: any, { setSubmitting }: any) => {
if (!ref) return console.error('Project ref is required')
if (!id) return console.error('Snippet ID is required')
setSubmitting(true)
try {
let localSnippet = snippet
// [Joshen] For SQL V2 - content is loaded on demand so we need to fetch the data if its not already loaded in the valtio state
if (!('content' in localSnippet)) {
localSnippet = await getContentById({ projectRef: ref, id })
snapV2.addSnippet({ projectRef: ref, snippet: localSnippet })
}
await upsertContent({
projectRef: ref,
payload: {
...localSnippet,
name: nameInput,
description: descriptionInput,
} as UpsertContentPayload,
})
snapV2.renameSnippet({ id, name: nameInput, description: descriptionInput })
if (isSQLEditorTabsEnabled && ref) {
const tabId = createTabId('sql', { id })
renameTab(ref, tabId, nameInput)
}
toast.success('Successfully renamed snippet!')
if (onComplete) onComplete()
} catch (error: any) {
setSubmitting(false)
// [Joshen] We probably need some rollback cause all the saving is async
toast.error(`Failed to rename snippet: ${error.message}`)
}
}
useEffect(() => {
setNameInput(name)
setDescriptionInput(description)
}, [snippet.id])
return (
<Modal visible={visible} onCancel={onCancel} hideFooter header="Rename" size="small">
<Form
onReset={onCancel}
validateOnBlur
initialValues={{
name: name ?? '',
description: description ?? '',
}}
validate={validate}
onSubmit={onSubmit}
>
{({ isSubmitting }: { isSubmitting: boolean }) => (
<>
<Modal.Content className="space-y-4">
<Input
label="Name"
id="name"
name="name"
value={nameInput}
onChange={(e) => setNameInput(e.target.value)}
/>
<div className="flex w-full justify-end mt-2">
{!hasHipaaAddon && (
<Button
type="default"
onClick={() => generateTitle()}
size="tiny"
disabled={isTitleGenerationLoading}
>
<div className="flex items-center gap-1">
<div className="scale-75">
<AiIconAnimation loading={isTitleGenerationLoading} />
</div>
<span>Rename with Supabase AI</span>
</div>
</Button>
)}
</div>
<Input.TextArea
label="Description"
id="description"
placeholder="Describe query"
size="medium"
textAreaClassName="resize-none"
value={descriptionInput}
onChange={(e) => setDescriptionInput(e.target.value)}
/>
</Modal.Content>
<Modal.Separator />
<Modal.Content className="flex items-center justify-end gap-2">
<Button htmlType="reset" type="default" onClick={onCancel} disabled={isSubmitting}>
Cancel
</Button>
<Button htmlType="submit" loading={isSubmitting} disabled={isSubmitting}>
Rename query
</Button>
</Modal.Content>
</>
)}
</Form>
</Modal>
)
}
export default RenameQueryModal