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