diff --git a/packages/ui/src/components/Command/APIKeys.tsx b/packages/ui/src/components/Command/APIKeys.tsx index 7fa58ffc988..caf228b3165 100644 --- a/packages/ui/src/components/Command/APIKeys.tsx +++ b/packages/ui/src/components/Command/APIKeys.tsx @@ -1,7 +1,7 @@ import { CommandGroup } from 'cmdk-supabase' import { useCommandMenu } from './CommandMenuProvider' import { Badge } from '../Badge' -import { CommandItem } from './Command.utils' +import { CommandItem, copyToClipboard } from './Command.utils' import { IconAlertCircle } from './../Icon/icons/IconAlertCircle' import ChildItem from './ChildItem' @@ -9,15 +9,6 @@ const APIKeys = ({ isSubItem = false }) => { const { setIsOpen, project } = useCommandMenu() const { apiKeys } = project ?? {} - const copyToClipboard = (str: string, callback = () => {}) => { - const focused = window.document.hasFocus() - if (focused) { - window.navigator?.clipboard?.writeText(str).then(callback) - } else { - console.warn('Unable to copy to clipboard') - } - } - return ( {apiKeys?.anon !== undefined && ( diff --git a/packages/ui/src/components/Command/Command.utils.tsx b/packages/ui/src/components/Command/Command.utils.tsx index 4be5db4f487..9d4fe97bed4 100644 --- a/packages/ui/src/components/Command/Command.utils.tsx +++ b/packages/ui/src/components/Command/Command.utils.tsx @@ -12,6 +12,15 @@ import { LoadingLine } from '../LoadingLine/LoadingLine' type CommandPrimitiveElement = React.ElementRef type CommandPrimitiveProps = React.ComponentPropsWithoutRef +export const copyToClipboard = (str: string, callback = () => {}) => { + const focused = window.document.hasFocus() + if (focused) { + window.navigator?.clipboard?.writeText(str).then(callback) + } else { + console.warn('Unable to copy to clipboard') + } +} + export const Command = React.forwardRef( ({ className, ...props }, ref) => ( { const router = useRouter() const commandInputRef = useRef>(null) - const { isOpen, setIsOpen, search, setSearch, pages, setPages, currentPage, site } = + const { isOpen, setIsOpen, search, setSearch, pages, setPages, currentPage, site, project } = useCommandMenu() const showCommandInput = !currentPage || !CHAT_ROUTES.includes(currentPage) @@ -201,11 +204,27 @@ const CommandMenu = ({ projectRef }: CommandMenuProps) => { setPages([...pages, COMMAND_ROUTES.API_KEYS])} + onSelect={() => { + setSearch('') + setPages([...pages, COMMAND_ROUTES.API_KEYS]) + }} > Get API keys + {project?.apiUrl !== undefined && ( + { + copyToClipboard(project?.apiUrl ?? '') + setIsOpen(false) + }} + className="space-x-2" + > + + Copy API URL + + )} )} @@ -221,7 +240,7 @@ const CommandMenu = ({ projectRef }: CommandMenuProps) => { key={item.url} type="link" onSelect={() => { - router.push(item.url) + router.push(itemUrl) setIsOpen(false) }} > @@ -260,7 +279,13 @@ const CommandMenu = ({ projectRef }: CommandMenuProps) => { )} - setPages([...pages, 'Theme'])}> + { + setSearch('') + setPages([...pages, 'Theme']) + }} + > Change theme diff --git a/packages/ui/src/components/Command/CommandMenuProvider.tsx b/packages/ui/src/components/Command/CommandMenuProvider.tsx index 8457c0ed97d..c9633c6b554 100644 --- a/packages/ui/src/components/Command/CommandMenuProvider.tsx +++ b/packages/ui/src/components/Command/CommandMenuProvider.tsx @@ -23,7 +23,7 @@ export interface CommandMenuContextValue { /** * Project metadata for easy retrieval */ - project?: { ref?: string; apiKeys?: { anon?: string; service?: string } } + project?: { ref?: string; apiKeys?: { anon?: string; service?: string }; apiUrl?: string } /** * Any additional metadata that CMDK component can use in its AI prompts */ @@ -58,6 +58,7 @@ export interface CommandMenuProviderProps { * Project's API keys, for easy access through CMDK */ apiKeys?: { anon?: string; service?: string } + apiUrl?: string /** * Opt in flag to use additional metadata in AI prompts */ @@ -77,6 +78,7 @@ const CommandMenuProvider = ({ site, projectRef, apiKeys, + apiUrl, metadata, isOptedInToAI = false, saveGeneratedSQL, @@ -89,7 +91,7 @@ const CommandMenuProvider = ({ const currentPage = pages[pages.length - 1] const actions: CommandMenuActions = { toggleTheme } - const project = projectRef !== undefined ? { ref: projectRef, apiKeys } : undefined + const project = projectRef !== undefined ? { ref: projectRef, apiKeys, apiUrl } : undefined useKeyboardEvents({ setIsOpen, currentPage, setSearch, setPages }) diff --git a/studio/components/interfaces/App/CommandMenuWrapper.tsx b/studio/components/interfaces/App/CommandMenuWrapper.tsx index 015fb2d8151..bd1d47edd5d 100644 --- a/studio/components/interfaces/App/CommandMenuWrapper.tsx +++ b/studio/components/interfaces/App/CommandMenuWrapper.tsx @@ -36,6 +36,7 @@ const CommandMenuWrapper = ({ children }: PropsWithChildren<{}>) => { anon: settings?.autoApiService?.defaultApiKey ?? undefined, service: settings?.autoApiService?.serviceApiKey ?? undefined, } + const apiUrl = `${settings?.autoApiService.protocol}://${settings?.autoApiService.endpoint}` const { data } = useEntityDefinitionsQuery( { @@ -100,6 +101,7 @@ const CommandMenuWrapper = ({ children }: PropsWithChildren<{}>) => { site="studio" projectRef={ref} apiKeys={apiKeys} + apiUrl={apiUrl} metadata={cmdkMetadata} isOptedInToAI={isOptedInToAI} saveGeneratedSQL={onSaveGeneratedSQL}