PolicyEditorPanelHeader.tsx128 lines · main
1import type { PGPolicy } from '@supabase/pg-meta'
2import { ChevronDown, PanelLeftClose, PanelRightClose, X } from 'lucide-react'
3import { useState } from 'react'
4import {
5 cn,
6 Collapsible,
7 CollapsibleContent,
8 CollapsibleTrigger,
9 SheetClose,
10 SheetHeader,
11 SheetTitle,
12 Tooltip,
13 TooltipContent,
14 TooltipTrigger,
15} from 'ui'
16
17export const PolicyEditorPanelHeader = ({
18 selectedPolicy,
19 showTools,
20 setShowTools,
21}: {
22 selectedPolicy?: PGPolicy
23 showTools: boolean
24 setShowTools: (v: boolean) => void
25}) => {
26 const [showDetails, setShowDetails] = useState(false)
27
28 return (
29 <SheetHeader className={cn('py-3 flex flex-row justify-between items-start border-b')}>
30 <div className="flex flex-row gap-3 max-w-[75%] items-start">
31 <SheetClose
32 className={cn(
33 'text-muted hover:text ring-offset-background transition-opacity hover:opacity-100',
34 'focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2',
35 'transition disabled:pointer-events-none data-[state=open]:bg-secondary',
36 'mt-1.5'
37 )}
38 >
39 <X className="h-3 w-3" />
40 <span className="sr-only">Close</span>
41 </SheetClose>
42 <div className="h-[24px] w-px bg-border-overlay" />
43 <div>
44 <SheetTitle className="truncate">
45 {selectedPolicy !== undefined
46 ? `Update policy: ${selectedPolicy.name}`
47 : 'Create a new Row Level Security policy'}
48 </SheetTitle>
49 {selectedPolicy !== undefined && (
50 <Collapsible
51 className="-mt-1.5 pb-1.5"
52 open={showDetails}
53 onOpenChange={setShowDetails}
54 >
55 <CollapsibleTrigger className="group font-normal p-0 [&[data-state=open]>div>svg]:-rotate-180!">
56 <div className="flex items-center gap-x-2 w-full">
57 <p className="text-xs text-foreground-light group-hover:text-foreground transition">
58 View policy details
59 </p>
60 <ChevronDown
61 className="transition-transform duration-200"
62 strokeWidth={1.5}
63 size={14}
64 />
65 </div>
66 </CollapsibleTrigger>
67 <CollapsibleContent className="grid gap-1.5">
68 <div className="flex my-2">
69 <div>
70 <div className="text-xs flex items-start space-x-2 border-b py-1.5">
71 <p className="w-[110px] text-foreground-light">Name:</p>
72 <p className="pr-4">{selectedPolicy?.name}</p>
73 </div>
74 <div className="text-xs flex items-start space-x-2 border-b py-1.5">
75 <p className="w-[110px] text-foreground-light">Action:</p>
76 <p className="font-mono pr-4">{selectedPolicy?.action}</p>
77 </div>
78 <div className="text-xs flex items-start space-x-2 border-b py-1.5">
79 <p className="w-[110px] text-foreground-light">Command:</p>
80 <p className="font-mono pr-4">{selectedPolicy?.command}</p>
81 </div>
82 <div className="text-xs flex items-start space-x-2 border-b py-1.5">
83 <p className="w-[110px] text-foreground-light">Target roles:</p>
84 <p className="font-mono pr-4">{selectedPolicy?.roles.join(', ')}</p>
85 </div>
86 <div className="text-xs flex items-start space-x-2 border-b py-1.5">
87 <p className="w-[110px] text-foreground-light">USING expression:</p>
88 <p className="font-mono pr-4">{selectedPolicy?.definition}</p>
89 </div>
90 <div className="text-xs flex items-start space-x-2 pt-1.5">
91 <p className="w-[110px] text-foreground-light">CHECK expression:</p>
92 <p
93 className={`${selectedPolicy?.check ? '' : 'text-foreground-light'} font-mono pr-4`}
94 >
95 {selectedPolicy?.check ?? 'None'}
96 </p>
97 </div>
98 </div>
99 </div>
100 </CollapsibleContent>
101 </Collapsible>
102 )}
103 </div>
104 </div>
105 <Tooltip>
106 <TooltipTrigger asChild>
107 <button
108 aria-expanded={showTools}
109 aria-controls="ai-chat-assistant"
110 className={cn(
111 !showTools ? 'text-foreground-lighter' : 'text-light',
112 'mt-1 hover:text-foreground transition'
113 )}
114 onClick={() => setShowTools(!showTools)}
115 >
116 {!showTools ? (
117 <PanelLeftClose size={19} strokeWidth={1} />
118 ) : (
119 <PanelRightClose size={19} strokeWidth={1} />
120 )}
121 <span className="sr-only">{showTools ? 'Hide' : 'Show'} tools</span>
122 </button>
123 </TooltipTrigger>
124 <TooltipContent side="left">{showTools ? 'Hide' : 'Show'} tools</TooltipContent>
125 </Tooltip>
126 </SheetHeader>
127 )
128}