| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- import type { PGPolicy } from '@supabase/pg-meta'
- import { Search } from 'lucide-react'
- import { useState } from 'react'
- import {
- Badge,
- cn,
- HoverCard,
- HoverCardContent,
- HoverCardTrigger,
- InputGroup,
- InputGroupAddon,
- InputGroupInput,
- } from 'ui'
- import { SimpleCodeBlock } from 'ui-patterns/SimpleCodeBlock'
- import {
- getGeneralPolicyTemplates,
- getQueuePolicyTemplates,
- getRealtimePolicyTemplates,
- } from '../PolicyEditorModal/PolicyEditorModal.constants'
- import { Markdown } from '@/components/interfaces/Markdown'
- import CardButton from '@/components/ui/CardButton'
- import CopyButton from '@/components/ui/CopyButton'
- import { NoSearchResults } from '@/components/ui/NoSearchResults'
- interface PolicyTemplatesProps {
- schema: string
- table: string
- selectedPolicy?: PGPolicy
- selectedTemplate?: string
- onSelectTemplate: (template: any) => void
- }
- export const PolicyTemplates = ({
- schema,
- table,
- selectedPolicy,
- selectedTemplate,
- onSelectTemplate,
- }: PolicyTemplatesProps) => {
- const [search, setSearch] = useState('')
- const templates =
- schema === 'realtime'
- ? getRealtimePolicyTemplates()
- : schema === 'pgmq'
- ? getQueuePolicyTemplates()
- : getGeneralPolicyTemplates(schema, table.length > 0 ? table : 'table_name')
- const baseTemplates =
- selectedPolicy !== undefined
- ? templates.filter((t) => t.command === selectedPolicy.command)
- : templates
- const filteredTemplates =
- search.length > 0
- ? baseTemplates.filter(
- (template) =>
- template.name.toLowerCase().includes(search.toLowerCase()) ||
- template.command.toLowerCase().includes(search.toLowerCase())
- )
- : baseTemplates
- return (
- <div className="h-full px-content py-content flex flex-col gap-3">
- <label className="sr-only" htmlFor="template-search">
- Search templates
- </label>
- <InputGroup>
- <InputGroupInput
- id="template-search"
- placeholder="Search templates"
- value={search}
- onChange={(e) => setSearch(e.target.value)}
- />
- <InputGroupAddon>
- <Search />
- </InputGroupAddon>
- </InputGroup>
- {search.length > 0 && filteredTemplates.length === 0 && (
- <NoSearchResults searchString={search} className="min-w-full" />
- )}
- <div className="flex flex-col gap-1.5">
- {filteredTemplates.map((template) => {
- return (
- <HoverCard key={template.id} openDelay={100} closeDelay={100}>
- <HoverCardTrigger>
- <CardButton
- title={template.name}
- titleClass="text-sm"
- className={cn(
- 'transition w-full',
- template.id === selectedTemplate
- ? 'border-stronger! bg-surface-200 hover:border-stronger!'
- : ''
- )}
- key={template.id}
- onClick={() => onSelectTemplate(template)}
- hideChevron
- fixedHeight={false}
- icon={
- <div className="min-w-16 flex items-start">
- <Badge
- className={cn(
- 'rounded-sm! font-mono',
- template.command === 'UPDATE'
- ? 'bg-blue-900/50 text-blue-200 border border-blue-800'
- : ''
- )}
- variant={
- template.command === 'ALL'
- ? 'default'
- : template.command === 'SELECT'
- ? 'success'
- : template.command === 'UPDATE'
- ? 'default'
- : template.command === 'DELETE'
- ? 'destructive'
- : 'warning'
- }
- >
- {template.command}
- </Badge>
- </div>
- }
- >
- <Markdown content={template.description} className="[&>p]:m-0 space-y-2" />
- </CardButton>
- </HoverCardTrigger>
- <HoverCardContent
- hideWhenDetached
- side="left"
- align="center"
- className="w-[500px] flex"
- animate="slide-in"
- >
- <SimpleCodeBlock
- showCopy={false}
- className="sql"
- parentClassName="p-0! [&>div>span]:text-xs"
- >
- {template.statement}
- </SimpleCodeBlock>
- <CopyButton
- iconOnly
- type="default"
- className="px-1 absolute top-1.5 right-1.5"
- text={template.statement}
- />
- </HoverCardContent>
- </HoverCard>
- )
- })}
- </div>
- </div>
- )
- }
|