LogsExplorerHeader.tsx 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. import { BookOpen, Check, ChevronsUpDown, Copy, ExternalLink, List, X } from 'lucide-react'
  2. import Link from 'next/link'
  3. import { useState } from 'react'
  4. import { logConstants } from 'shared-data'
  5. import {
  6. Button,
  7. cn,
  8. Command,
  9. CommandEmpty,
  10. CommandGroup,
  11. CommandInput,
  12. CommandItem,
  13. CommandList,
  14. copyToClipboard,
  15. Popover,
  16. PopoverContent,
  17. PopoverTrigger,
  18. SidePanel,
  19. Tooltip,
  20. TooltipContent,
  21. TooltipTrigger,
  22. } from 'ui'
  23. import { DocsButton } from '../DocsButton'
  24. import { LOGS_EXPLORER_DOCS_URL } from '@/components/interfaces/Settings/Logs/Logs.constants'
  25. import Table from '@/components/to-be-cleaned/Table'
  26. import { DOCS_URL } from '@/lib/constants'
  27. export interface LogsExplorerHeaderProps {
  28. subtitle?: string
  29. }
  30. const LogsExplorerHeader = ({ subtitle }: LogsExplorerHeaderProps) => {
  31. const [showReference, setShowReference] = useState(false)
  32. const [open, setOpen] = useState(false)
  33. const [selectedSchema, setSelectedSchema] = useState(logConstants.schemas[0])
  34. return (
  35. <div className="flex flex-col md:flex-row md:items-center gap-4 md:gap-8 transition-all pb-6 justify-between">
  36. <div className="flex flex-col md:flex-row md:items-center gap-3">
  37. <div className="flex flex-row items-center gap-3">
  38. <div className="flex h-6 w-6 items-center justify-center rounded-sm border border-brand-600 bg-brand-300 text-brand">
  39. <List size={14} strokeWidth={3} />
  40. </div>
  41. <h1>Logs Explorer</h1>
  42. </div>
  43. {subtitle && <span className="text-2xl text-foreground-light">{subtitle}</span>}
  44. </div>
  45. <div className="flex flex-row gap-2">
  46. <DocsButton href={LOGS_EXPLORER_DOCS_URL} />
  47. <SidePanel
  48. size="large"
  49. header={
  50. <div className="flex flex-row justify-between items-center">
  51. <h3>Field Reference</h3>
  52. <Button
  53. type="text"
  54. className="px-1"
  55. onClick={() => setShowReference(false)}
  56. icon={<X size={18} strokeWidth={1.5} />}
  57. />
  58. </div>
  59. }
  60. visible={showReference}
  61. cancelText="Close"
  62. onCancel={() => setShowReference(false)}
  63. hideFooter
  64. triggerElement={
  65. <Button
  66. type="default"
  67. onClick={() => setShowReference(true)}
  68. icon={<BookOpen strokeWidth={1.5} />}
  69. >
  70. <span>Field Reference</span>
  71. </Button>
  72. }
  73. >
  74. <SidePanel.Content>
  75. <div className="pt-4 pb-2 space-y-1">
  76. <p className="text-sm">
  77. The following table shows all the available paths that can be queried from each
  78. respective source. Do note that to access nested keys, you would need to perform the
  79. necessary{' '}
  80. <Link
  81. href={`${DOCS_URL}/guides/platform/logs#unnesting-arrays`}
  82. target="_blank"
  83. rel="noreferrer"
  84. className="text-brand"
  85. >
  86. unnesting joins
  87. <ExternalLink
  88. size={14}
  89. className="ml-1 inline translate-y-[-2px]"
  90. strokeWidth={1.5}
  91. />
  92. </Link>
  93. </p>
  94. </div>
  95. </SidePanel.Content>
  96. <SidePanel.Separator />
  97. <div className="px-4 pb-4 flex flex-col gap-4">
  98. <Popover open={open} onOpenChange={setOpen}>
  99. <PopoverTrigger asChild>
  100. <Button
  101. type="default"
  102. role="combobox"
  103. size={'small'}
  104. aria-expanded={open}
  105. className="w-full justify-between"
  106. iconRight={<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />}
  107. >
  108. {selectedSchema?.name ?? 'Select source...'}
  109. </Button>
  110. </PopoverTrigger>
  111. <PopoverContent className="p-0" sameWidthAsTrigger>
  112. <Command>
  113. <CommandInput placeholder="Search source..." />
  114. <CommandList>
  115. <CommandEmpty>No source found.</CommandEmpty>
  116. <CommandGroup>
  117. {logConstants.schemas.map((schema) => (
  118. <CommandItem
  119. key={schema.reference}
  120. value={schema.reference}
  121. onSelect={() => {
  122. setSelectedSchema(schema)
  123. setOpen(false)
  124. }}
  125. >
  126. <Check
  127. className={cn(
  128. 'mr-2 h-4 w-4',
  129. selectedSchema === schema ? 'opacity-100' : 'opacity-0'
  130. )}
  131. />
  132. {schema.name}
  133. </CommandItem>
  134. ))}
  135. </CommandGroup>
  136. </CommandList>
  137. </Command>
  138. </PopoverContent>
  139. </Popover>
  140. <Table
  141. head={[
  142. <Table.th className="text-xs p-2!" key="path">
  143. Path
  144. </Table.th>,
  145. <Table.th key="type" className="text-xs p-2!">
  146. Type
  147. </Table.th>,
  148. ]}
  149. body={selectedSchema.fields.map((field) => (
  150. <Field key={field.path} field={field} />
  151. ))}
  152. />
  153. </div>
  154. </SidePanel>
  155. </div>
  156. </div>
  157. )
  158. }
  159. export default LogsExplorerHeader
  160. const Field = ({
  161. field,
  162. }: {
  163. field: {
  164. path: string
  165. type: string
  166. }
  167. }) => {
  168. const [isCopied, setIsCopied] = useState(false)
  169. return (
  170. <Table.tr>
  171. <Table.td
  172. className="font-mono text-xs p-2! cursor-pointer hover:text-foreground transition flex items-center space-x-2"
  173. onClick={() =>
  174. copyToClipboard(field.path, () => {
  175. setIsCopied(true)
  176. setTimeout(() => setIsCopied(false), 3000)
  177. })
  178. }
  179. >
  180. <span>{field.path}</span>
  181. {isCopied ? (
  182. <Tooltip>
  183. <TooltipTrigger>
  184. <Check size={14} strokeWidth={3} className="text-brand" />
  185. </TooltipTrigger>
  186. <TooltipContent side="bottom" className="font-sans">
  187. Copied
  188. </TooltipContent>
  189. </Tooltip>
  190. ) : (
  191. <Tooltip>
  192. <TooltipTrigger>
  193. <Copy size={14} />
  194. </TooltipTrigger>
  195. <TooltipContent side="bottom" className="font-sans">
  196. Copy value
  197. </TooltipContent>
  198. </Tooltip>
  199. )}
  200. </Table.td>
  201. <Table.td className="font-mono text-xs p-2!">{field.type}</Table.td>
  202. </Table.tr>
  203. )
  204. }