Home / Function/ RenameQueryModal() — supabase Function Reference

RenameQueryModal() — supabase Function Reference

Architecture documentation for the RenameQueryModal() function in RenameQueryModal.tsx from the supabase codebase.

Entity Profile

Dependency Diagram

graph TD
  4b6fea9d_dfff_bf3a_54d5_81712fa5470f["RenameQueryModal()"]
  4d7932db_0af7_b504_1c44_c9c88484caba["subscriptionHasHipaaAddon()"]
  4b6fea9d_dfff_bf3a_54d5_81712fa5470f -->|calls| 4d7932db_0af7_b504_1c44_c9c88484caba
  style 4b6fea9d_dfff_bf3a_54d5_81712fa5470f fill:#6366f1,stroke:#818cf8,color:#fff

Relationship Graph

Source Code

apps/studio/components/interfaces/SQLEditor/RenameQueryModal.tsx lines 32–223

const RenameQueryModal = ({
  snippet = {} as any,
  visible,
  onCancel,
  onComplete,
}: RenameQueryModalProps) => {
  const { ref } = useParams()
  const router = useRouter()
  const { data: organization } = useSelectedOrganizationQuery()

  const snapV2 = useSqlEditorV2StateSnapshot()
  const tabsSnap = useTabsStateSnapshot()
  const { data: subscription } = useOrgSubscriptionQuery(
    { orgSlug: organization?.slug },
    { enabled: visible }
  )
  const isSQLSnippet = snippet.type === 'sql'
  const { data: projectSettings } = useProjectSettingsV2Query({ projectRef: ref })

  // Customers on HIPAA plans should not have access to Supabase AI
  const hasHipaaAddon = subscriptionHasHipaaAddon(subscription) && projectSettings?.is_sensitive

  const { id, name, description } = snippet

  const [nameInput, setNameInput] = useState(name)
  const [descriptionInput, setDescriptionInput] = useState(description)

  const { mutate: titleSql, isPending: 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 { data: check } = useCheckOpenAIKeyQuery()
  const isApiKeySet = !!check?.hasKey

  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 })
      }

      const changedSnippet = await upsertContent({
        projectRef: ref,
        payload: {
          ...localSnippet,
          name: nameInput,
          description: descriptionInput,
        } as UpsertContentPayload,
      })

      if (IS_PLATFORM) {
        snapV2.renameSnippet({ id, name: nameInput, description: descriptionInput })

        const tabId = createTabId('sql', { id })
        tabsSnap.updateTab(tabId, { label: nameInput })
      } else if (changedSnippet) {
        // In self-hosted, the snippet also updates the id when renaming it. This code is to ensure the previous snippet
        // is removed, new one is added, tab state is updated and the router is updated.

        // remove the old snippet from the state without saving to API
        snapV2.removeSnippet(id, true)

        snapV2.addSnippet({ projectRef: ref, snippet: changedSnippet })

        // remove the tab for the old snippet if the snippet was open. Renaming can also happen when the tab is not open.
        const tabId = createTabId('sql', { id })
        if (tabsSnap.hasTab(tabId)) {
          tabsSnap.removeTab(tabId)
          await router.push(`/project/${ref}/sql/${changedSnippet.id}`)
        }
      }

      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 && (
                  <ButtonTooltip
                    type="default"
                    onClick={() => generateTitle()}
                    size="tiny"
                    disabled={isTitleGenerationLoading || !isApiKeySet}
                    tooltip={{
                      content: {
                        side: 'bottom',
                        text: isApiKeySet
                          ? undefined
                          : 'Add your "OPENAI_API_KEY" to your environment variables to use this feature.',
                      },
                    }}
                  >
                    <div className="flex items-center gap-1">
                      <div className="scale-75">
                        <AiIconAnimation loading={isTitleGenerationLoading} />
                      </div>
                      <span>Rename with Supabase AI</span>
                    </div>
                  </ButtonTooltip>
                )}
              </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>
  )
}

Subdomains

Frequently Asked Questions

What does RenameQueryModal() do?
RenameQueryModal() is a function in the supabase codebase.
What does RenameQueryModal() call?
RenameQueryModal() calls 1 function(s): subscriptionHasHipaaAddon.

Analyze Your Own Codebase

Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.

Try Supermodel Free