QueryError.tsx105 lines · main
1import styles from '@ui/layout/ai-icon-animation/ai-icon-animation-style.module.css'
2import { initial, last } from 'lodash'
3import { Dispatch, SetStateAction } from 'react'
4import {
5 Alert,
6 AlertTitle,
7 Button,
8 cn,
9 Collapsible,
10 CollapsibleContent,
11 CollapsibleTrigger,
12} from 'ui'
13
14import { QueryResponseError } from '@/data/sql/execute-sql-mutation'
15
16export const QueryError = ({
17 error,
18 open,
19 setOpen,
20}: {
21 error: QueryResponseError
22 open: boolean
23 setOpen: Dispatch<SetStateAction<boolean>>
24}) => {
25 const formattedError =
26 (error?.message?.split('\n') ?? [])?.filter((x: string) => x.length > 0) ?? []
27
28 return (
29 <div className="flex flex-col gap-y-3 px-5">
30 <Alert variant="destructive">
31 <svg
32 xmlns="http://www.w3.org/2000/svg"
33 viewBox="0 0 20 20"
34 fill="currentColor"
35 className="w-5 h-5"
36 >
37 <path
38 fillRule="evenodd"
39 clipRule="evenodd"
40 d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-8-5a.75.75 0 01.75.75v4.5a.75.75 0 01-1.5 0v-4.5A.75.75 0 0110 5zm0 10a1 1 0 100-2 1 1 0 000 2z"
41 />
42 </svg>
43 <div className="flex flex-col gap-3">
44 <AlertTitle className="m-0">Error running SQL query</AlertTitle>
45
46 <Collapsible
47 defaultOpen
48 className="flex flex-col gap-3"
49 open={open}
50 onOpenChange={() => setOpen(!open)}
51 >
52 <div className="flex gap-2">
53 <CollapsibleTrigger asChild>
54 <Button
55 size="tiny"
56 type="outline"
57 className={cn('group', styles['ai-icon__container--allow-hover-effect'])}
58 >
59 {open ? 'Hide error details' : 'Show error details'}
60 </Button>
61 </CollapsibleTrigger>
62 </div>
63 <CollapsibleContent className="overflow-auto">
64 {formattedError.length > 0 ? (
65 formattedError.map((x: string, i: number) => (
66 <pre key={`error-${i}`} className="font-mono text-xs whitespace-pre-wrap">
67 {x
68 .split(' ')
69 .reduce((arr, cur) => {
70 // Split the ERROR string so that it can be wrapped in a red span
71 const l = last(arr)
72
73 if (l && l !== 'ERROR:') {
74 return initial(arr).concat([[l, cur].join(' ')])
75 }
76
77 if (l === '') {
78 return arr.concat([' '])
79 }
80
81 return arr.concat([cur])
82 }, [] as string[])
83 .map((str, index) => {
84 return (
85 <span
86 key={index}
87 className={cn('break-all', str === 'ERROR:' && 'text-destructive')}
88 >
89 {str}
90 </span>
91 )
92 })}
93 </pre>
94 ))
95 ) : (
96 <p className="font-mono text-xs">{error.error}</p>
97 )}
98 </CollapsibleContent>
99 </Collapsible>
100 </div>
101 </Alert>
102 <div className="overflow-x-auto"></div>
103 </div>
104 )
105}