mirror of
https://github.com/supabase/supabase.git
synced 2026-05-24 20:58:45 +08:00
* start * added panels * remove stuff * fixes and refinements * clean up * remove old assistant panel * resizable assistant kinda * use icon * Add missing package * remove canvas * add suggestions * updated empty state if no tables exist * fix table condition * Implement diffing if using assistant in sql editor * Reinstate old assistant in SQL editor if feature preview is off * pane size adjustment * assistant button corners * Add SQL snippet content to assistant if opening assistant in sql editor * Add the necessary checks for opt in and hipaa * revert adding snippet to assistant when opening assistant in sql editor * Add cmd i shortcut * Add admonitions for when disablePrompt is toggled on, and if no api key is set. Add footer note RE rate limitation * Bump ai package in packages * some fixes for backwards compability depending on feature preview toggled * Rename feature preview property for new assistant * Smol fix * Prevent SQL snippet from running until message is finished * only loading last message * fix z-index * save chat state to global state * add debug to failed ai queries * Add basic contextual invalidation * Add explain code action to SQL editor * Add link to abort ongoing queries from SqlSnippet * Update feature preview content * Fix * Fix * Fix * Te4st * Fix tests * ONly show ai button within a project * Fix PH tracking * Beef up a bit more event tracking * Rough fix to padding when assistant is open * A bit more telemetry stuff * Update prompts * fix rls editing via assistant * Update generate-v3.ts prompt to get auth schema too * Add policy satement to assistant when editing * Address all comments * fixc * Fix SqlSnippet not taking full width on larger viewports * Adjust max width --------- Co-authored-by: Saxon Fletcher <saxonafletcher@gmail.com>
129 lines
4.6 KiB
TypeScript
129 lines
4.6 KiB
TypeScript
import { PermissionAction } from '@supabase/shared-types/out/constants'
|
|
import { isNull, partition } from 'lodash'
|
|
import { AlertCircle, Search } from 'lucide-react'
|
|
import { useEffect, useState } from 'react'
|
|
|
|
import { useParams } from 'common'
|
|
import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext'
|
|
import { DocsButton } from 'components/ui/DocsButton'
|
|
import InformationBox from 'components/ui/InformationBox'
|
|
import NoSearchResults from 'components/ui/NoSearchResults'
|
|
import ShimmeringLoader from 'components/ui/ShimmeringLoader'
|
|
import { useDatabaseExtensionsQuery } from 'data/database-extensions/database-extensions-query'
|
|
import { useCheckPermissions, usePermissionsLoaded } from 'hooks/misc/useCheckPermissions'
|
|
import { Input } from 'ui'
|
|
import ExtensionCard from './ExtensionCard'
|
|
import ExtensionCardSkeleton from './ExtensionCardSkeleton'
|
|
import { HIDDEN_EXTENSIONS, SEARCH_TERMS } from './Extensions.constants'
|
|
|
|
const Extensions = () => {
|
|
const { filter } = useParams()
|
|
const { project } = useProjectContext()
|
|
const [filterString, setFilterString] = useState<string>('')
|
|
|
|
const { data, isLoading } = useDatabaseExtensionsQuery({
|
|
projectRef: project?.ref,
|
|
connectionString: project?.connectionString,
|
|
})
|
|
|
|
const extensions =
|
|
filterString.length === 0
|
|
? data ?? []
|
|
: (data ?? []).filter((ext) => {
|
|
const nameMatchesSearch = ext.name.toLowerCase().includes(filterString.toLowerCase())
|
|
const searchTermsMatchesSearch = (SEARCH_TERMS[ext.name] || []).some((x) =>
|
|
x.includes(filterString.toLowerCase())
|
|
)
|
|
return nameMatchesSearch || searchTermsMatchesSearch
|
|
})
|
|
const extensionsWithoutHidden = extensions.filter((ext) => !HIDDEN_EXTENSIONS.includes(ext.name))
|
|
const [enabledExtensions, disabledExtensions] = partition(
|
|
extensionsWithoutHidden,
|
|
(ext) => !isNull(ext.installed_version)
|
|
)
|
|
|
|
const canUpdateExtensions = useCheckPermissions(
|
|
PermissionAction.TENANT_SQL_ADMIN_WRITE,
|
|
'extensions'
|
|
)
|
|
const isPermissionsLoaded = usePermissionsLoaded()
|
|
|
|
useEffect(() => {
|
|
if (filter !== undefined) setFilterString(filter as string)
|
|
}, [filter])
|
|
|
|
return (
|
|
<>
|
|
<div className="mb-4">
|
|
<div className="flex items-center justify-between">
|
|
<Input
|
|
size="tiny"
|
|
placeholder="Search for an extension"
|
|
value={filterString}
|
|
onChange={(e) => setFilterString(e.target.value)}
|
|
className="w-52"
|
|
icon={<Search size={14} />}
|
|
/>
|
|
<DocsButton href="https://supabase.com/docs/guides/database/extensions" />
|
|
</div>
|
|
</div>
|
|
|
|
{isPermissionsLoaded && !canUpdateExtensions && (
|
|
<InformationBox
|
|
icon={<AlertCircle className="text-foreground-light" size={18} strokeWidth={2} />}
|
|
title="You need additional permissions to update database extensions"
|
|
/>
|
|
)}
|
|
|
|
{isLoading ? (
|
|
<div className="my-8 w-full space-y-12">
|
|
<div className="space-y-4">
|
|
<ShimmeringLoader className="h-[28px] w-40" />
|
|
|
|
<div className="mb-4 grid grid-cols-1 gap-3 md:grid-cols-2 xl:grid-cols-3">
|
|
{Array.from({ length: 6 }).map((_, index) => (
|
|
<ExtensionCardSkeleton key={index} index={index} />
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
) : (
|
|
<>
|
|
{extensions.length === 0 && (
|
|
<NoSearchResults
|
|
searchString={filterString}
|
|
onResetFilter={() => setFilterString('')}
|
|
/>
|
|
)}
|
|
|
|
<div className="my-8 w-full space-y-12">
|
|
{enabledExtensions.length > 0 && (
|
|
<div className="space-y-4">
|
|
<h4 className="text-lg">Enabled extensions</h4>
|
|
<div className="mb-4 grid grid-cols-1 gap-3 md:grid-cols-2 xl:grid-cols-3">
|
|
{enabledExtensions.map((extension) => (
|
|
<ExtensionCard key={extension.name} extension={extension} />
|
|
))}
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{disabledExtensions.length > 0 && (
|
|
<div className="space-y-4">
|
|
<h4 className="text-lg">Available extensions</h4>
|
|
<div className="mb-4 grid grid-cols-1 gap-3 md:grid-cols-2 xl:grid-cols-3">
|
|
{disabledExtensions.map((extension) => (
|
|
<ExtensionCard key={extension.name} extension={extension} />
|
|
))}
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</>
|
|
)}
|
|
</>
|
|
)
|
|
}
|
|
|
|
export default Extensions
|