PolicyEditorPanelHeader.tsx 5.1 KB

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