@sqlrooms/sql-editor 0.27.0-rc.2 → 0.27.0-rc.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/SqlEditorSlice.d.ts.map +1 -1
- package/dist/SqlEditorSlice.js +15 -0
- package/dist/SqlEditorSlice.js.map +1 -1
- package/dist/SqlMonacoEditor.d.ts +10 -2
- package/dist/SqlMonacoEditor.d.ts.map +1 -1
- package/dist/SqlMonacoEditor.js +101 -68
- package/dist/SqlMonacoEditor.js.map +1 -1
- package/dist/components/CreateTableModal.d.ts +1 -1
- package/dist/components/CreateTableModal.d.ts.map +1 -1
- package/dist/components/CreateTableModal.js +81 -6
- package/dist/components/CreateTableModal.js.map +1 -1
- package/dist/components/QueryEditorPanelTabsList.d.ts.map +1 -1
- package/dist/components/QueryEditorPanelTabsList.js +1 -1
- package/dist/components/QueryEditorPanelTabsList.js.map +1 -1
- package/dist/components/QueryResultPanel.d.ts +16 -1
- package/dist/components/QueryResultPanel.d.ts.map +1 -1
- package/dist/components/QueryResultPanel.js +75 -8
- package/dist/components/QueryResultPanel.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +10 -10
|
@@ -3,7 +3,7 @@ import { zodResolver } from '@hookform/resolvers/zod';
|
|
|
3
3
|
import { makeQualifiedTableName } from '@sqlrooms/duckdb';
|
|
4
4
|
import { Alert, AlertDescription, Button, Checkbox, Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, Form, FormControl, FormField, FormItem, FormLabel, FormMessage, Input, Label, Popover, PopoverContent, PopoverTrigger, Spinner, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, cn, } from '@sqlrooms/ui';
|
|
5
5
|
import { Check, ChevronsUpDown, HelpCircle } from 'lucide-react';
|
|
6
|
-
import { useCallback, useMemo, useState } from 'react';
|
|
6
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
7
7
|
import { useForm } from 'react-hook-form';
|
|
8
8
|
import * as z from 'zod';
|
|
9
9
|
import { useStoreWithSqlEditor } from '../SqlEditorSlice';
|
|
@@ -21,6 +21,15 @@ const formSchema = z.object({
|
|
|
21
21
|
temp: z.boolean(),
|
|
22
22
|
view: z.boolean(),
|
|
23
23
|
});
|
|
24
|
+
const isAbortError = (err) => {
|
|
25
|
+
if (err instanceof DOMException) {
|
|
26
|
+
return err.name === 'AbortError';
|
|
27
|
+
}
|
|
28
|
+
if (err instanceof Error) {
|
|
29
|
+
return err.name === 'AbortError' || /cancelled|canceled/i.test(err.message);
|
|
30
|
+
}
|
|
31
|
+
return false;
|
|
32
|
+
};
|
|
24
33
|
/**
|
|
25
34
|
* Compact searchable combobox for selecting schema or database.
|
|
26
35
|
*/
|
|
@@ -35,7 +44,7 @@ const SchemaCombobox = ({ value, onChange, options, placeholder, searchPlacehold
|
|
|
35
44
|
* Compact checkbox option with clickable label and tooltip.
|
|
36
45
|
*/
|
|
37
46
|
const OptionCheckbox = ({ id, label, tooltip, checked, onCheckedChange, disabled }) => (_jsxs("div", { className: "flex items-center gap-1.5", children: [_jsx(Checkbox, { id: id, checked: checked, onCheckedChange: onCheckedChange, disabled: disabled, className: "h-3.5 w-3.5" }), _jsx(Label, { htmlFor: id, className: cn('cursor-pointer text-xs font-normal', disabled && 'cursor-not-allowed opacity-50'), children: label }), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(HelpCircle, { className: "text-muted-foreground h-3 w-3 cursor-help" }) }), _jsx(TooltipContent, { side: "top", className: "max-w-[200px] text-xs", children: tooltip })] })] }));
|
|
38
|
-
const CreateTableForm = ({ query, onClose, editDataSource, allowMultipleStatements = false, showSchemaSelection = false, onAddOrUpdateSqlQuery, initialValues, }) => {
|
|
47
|
+
const CreateTableForm = ({ query, onClose, onRequestClose, editDataSource, allowMultipleStatements = false, showSchemaSelection = false, onAddOrUpdateSqlQuery, initialValues, onSubmittingChange, onRegisterCancel, }) => {
|
|
39
48
|
const connector = useStoreWithSqlEditor((state) => state.db.connector);
|
|
40
49
|
const createTableFromQuery = useStoreWithSqlEditor((state) => state.db.createTableFromQuery);
|
|
41
50
|
const refreshTableSchemas = useStoreWithSqlEditor((state) => state.db.refreshTableSchemas);
|
|
@@ -77,12 +86,26 @@ const CreateTableForm = ({ query, onClose, editDataSource, allowMultipleStatemen
|
|
|
77
86
|
},
|
|
78
87
|
});
|
|
79
88
|
const isSubmitting = form.formState.isSubmitting;
|
|
89
|
+
const [isCancelling, setIsCancelling] = useState(false);
|
|
90
|
+
const abortControllerRef = useRef(null);
|
|
91
|
+
useEffect(() => {
|
|
92
|
+
return () => {
|
|
93
|
+
abortControllerRef.current?.abort();
|
|
94
|
+
abortControllerRef.current = null;
|
|
95
|
+
};
|
|
96
|
+
}, []);
|
|
97
|
+
useEffect(() => {
|
|
98
|
+
onSubmittingChange?.(isSubmitting);
|
|
99
|
+
}, [isSubmitting, onSubmittingChange]);
|
|
80
100
|
const onSubmit = useCallback(async (values) => {
|
|
101
|
+
const abortController = new AbortController();
|
|
102
|
+
abortControllerRef.current = abortController;
|
|
103
|
+
setIsCancelling(false);
|
|
81
104
|
try {
|
|
82
105
|
const { tableName, query, schema, database, replace, temp, view } = values;
|
|
83
106
|
if (onAddOrUpdateSqlQuery) {
|
|
84
107
|
// Legacy path: use the callback
|
|
85
|
-
await onAddOrUpdateSqlQuery(tableName, query, editDataSource?.tableName);
|
|
108
|
+
await onAddOrUpdateSqlQuery(tableName, query, editDataSource?.tableName, abortController.signal);
|
|
86
109
|
}
|
|
87
110
|
else {
|
|
88
111
|
// New path: call createTableFromQuery directly
|
|
@@ -94,6 +117,7 @@ const CreateTableForm = ({ query, onClose, editDataSource, allowMultipleStatemen
|
|
|
94
117
|
temp,
|
|
95
118
|
view,
|
|
96
119
|
allowMultipleStatements,
|
|
120
|
+
abortSignal: abortController.signal,
|
|
97
121
|
});
|
|
98
122
|
// Refresh table schemas to show the new table
|
|
99
123
|
await refreshTableSchemas();
|
|
@@ -102,8 +126,15 @@ const CreateTableForm = ({ query, onClose, editDataSource, allowMultipleStatemen
|
|
|
102
126
|
onClose();
|
|
103
127
|
}
|
|
104
128
|
catch (err) {
|
|
129
|
+
if (isAbortError(err)) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
105
132
|
form.setError('root', { type: 'manual', message: `${err}` });
|
|
106
133
|
}
|
|
134
|
+
finally {
|
|
135
|
+
abortControllerRef.current = null;
|
|
136
|
+
setIsCancelling(false);
|
|
137
|
+
}
|
|
107
138
|
}, [
|
|
108
139
|
onAddOrUpdateSqlQuery,
|
|
109
140
|
editDataSource?.tableName,
|
|
@@ -116,13 +147,22 @@ const CreateTableForm = ({ query, onClose, editDataSource, allowMultipleStatemen
|
|
|
116
147
|
const watchView = form.watch('view');
|
|
117
148
|
const watchTemp = form.watch('temp');
|
|
118
149
|
const watchTableName = form.watch('tableName');
|
|
150
|
+
const handleCancel = useCallback(async () => {
|
|
151
|
+
if (abortControllerRef.current) {
|
|
152
|
+
setIsCancelling(true);
|
|
153
|
+
abortControllerRef.current.abort();
|
|
154
|
+
}
|
|
155
|
+
}, []);
|
|
156
|
+
useEffect(() => {
|
|
157
|
+
onRegisterCancel?.(handleCancel);
|
|
158
|
+
}, [handleCancel, onRegisterCancel]);
|
|
119
159
|
return (_jsx(TooltipProvider, { delayDuration: 200, children: _jsx(Form, { ...form, children: _jsxs("form", { onSubmit: form.handleSubmit(onSubmit), className: "space-y-4", children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: editDataSource
|
|
120
160
|
? 'Edit table query'
|
|
121
161
|
: watchView
|
|
122
162
|
? 'Create view from query'
|
|
123
163
|
: 'Create table from query' }), !editDataSource && (_jsx(DialogDescription, { children: watchView
|
|
124
164
|
? 'Create a new view from an SQL query.'
|
|
125
|
-
: 'Create a new table from the results of an SQL query.' }))] }), form.formState.errors.root && (_jsx(Alert, { variant: "destructive", children: _jsx(AlertDescription, { className: "whitespace-pre-wrap font-mono text-xs", children: form.formState.errors.root.message }) })), _jsxs("div", { className: "flex items-
|
|
165
|
+
: 'Create a new table from the results of an SQL query.' }))] }), form.formState.errors.root && (_jsx(Alert, { variant: "destructive", children: _jsx(AlertDescription, { className: "whitespace-pre-wrap font-mono text-xs", children: form.formState.errors.root.message }) })), _jsxs("div", { className: "flex items-start gap-3", children: [_jsx(FormField, { control: form.control, name: "tableName", render: ({ field }) => (_jsxs(FormItem, { className: "min-w-0 flex-[2]", children: [_jsx(FormLabel, { className: "text-xs", children: watchView ? 'View name' : 'Table name' }), _jsx(FormControl, { children: _jsx(Input, { ...field, className: "h-9 font-mono text-xs", autoFocus: true, disabled: isSubmitting }) }), _jsx(FormMessage, { className: "text-xs" })] })) }), showSchemaSelection && (_jsxs(_Fragment, { children: [_jsx(FormField, { control: form.control, name: "schema", render: ({ field }) => (_jsxs(FormItem, { className: "min-w-0 flex-1", children: [_jsx(FormLabel, { className: "text-xs", children: "Schema" }), _jsx(FormControl, { children: _jsx(SchemaCombobox, { value: field.value, onChange: field.onChange, options: schemas, placeholder: "Schema...", searchPlaceholder: "Search...", emptyMessage: "No schemas.", disabled: isSubmitting }) })] })) }), (databases.length > 1 || watchTemp) && (_jsx(FormField, { control: form.control, name: "database", render: ({ field }) => (_jsxs(FormItem, { className: "min-w-0 flex-1", children: [_jsx(FormLabel, { className: "text-xs", children: "Database" }), _jsx(FormControl, { children: _jsx(SchemaCombobox, { value: watchTemp ? 'temp' : field.value, onChange: field.onChange, options: databases, placeholder: "Database...", searchPlaceholder: "Search...", emptyMessage: "No databases.", disabled: isSubmitting || watchTemp }) })] })) }))] }))] }), _jsx(FormField, { control: form.control, name: "query", render: ({ field }) => (_jsxs(FormItem, { className: "relative flex h-[200px] flex-col", children: [_jsx(FormControl, { children: _jsx(SqlMonacoEditor, { connector: connector, value: field.value, onChange: field.onChange, className: "absolute inset-0 h-full w-full", options: {
|
|
126
166
|
scrollBeyondLastLine: false,
|
|
127
167
|
automaticLayout: true,
|
|
128
168
|
minimap: { enabled: false },
|
|
@@ -131,11 +171,46 @@ const CreateTableForm = ({ query, onClose, editDataSource, allowMultipleStatemen
|
|
|
131
171
|
lineNumbers: 'off',
|
|
132
172
|
readOnly: isSubmitting,
|
|
133
173
|
fixedOverflowWidgets: false, // default true doesn't work well in a modal
|
|
134
|
-
} }) }), _jsx(FormMessage, { className: "text-xs" })] })) }), !onAddOrUpdateSqlQuery && (_jsxs("div", { className: "flex items-center gap-6 rounded-md border px-3 py-2", children: [_jsx(FormField, { control: form.control, name: "view", render: ({ field }) => (_jsx(OptionCheckbox, { id: "create-table-view", label: "View", tooltip: "Create a view instead of a table. Views store the query, not the data.", checked: field.value, onCheckedChange: field.onChange, disabled: isSubmitting })) }), _jsx(FormField, { control: form.control, name: "replace", render: ({ field }) => (_jsx(OptionCheckbox, { id: "create-table-replace", label: "Overwrite", tooltip: `Overwrite existing ${watchView ? 'view' : 'table'} with the same name if it exists.`, checked: field.value, onCheckedChange: field.onChange, disabled: isSubmitting })) })] })), _jsxs(DialogFooter, { children: [_jsx(Button, { type: "button", variant: "outline", onClick:
|
|
174
|
+
} }) }), _jsx(FormMessage, { className: "text-xs" })] })) }), !onAddOrUpdateSqlQuery && (_jsxs("div", { className: "flex items-center gap-6 rounded-md border px-3 py-2", children: [_jsx(FormField, { control: form.control, name: "view", render: ({ field }) => (_jsx(OptionCheckbox, { id: "create-table-view", label: "View", tooltip: "Create a view instead of a table. Views store the query, not the data.", checked: field.value, onCheckedChange: field.onChange, disabled: isSubmitting })) }), _jsx(FormField, { control: form.control, name: "replace", render: ({ field }) => (_jsx(OptionCheckbox, { id: "create-table-replace", label: "Overwrite", tooltip: `Overwrite existing ${watchView ? 'view' : 'table'} with the same name if it exists.`, checked: field.value, onCheckedChange: field.onChange, disabled: isSubmitting })) })] })), _jsxs(DialogFooter, { children: [_jsx(Button, { type: "button", variant: "outline", onClick: onRequestClose, children: "Close" }), _jsxs(Button, { type: isSubmitting ? 'button' : 'submit', onClick: isSubmitting ? handleCancel : undefined, disabled: isSubmitting ? isCancelling : !watchTableName?.trim(), children: [isSubmitting && _jsx(Spinner, { className: "mr-2" }), isSubmitting
|
|
175
|
+
? isCancelling
|
|
176
|
+
? 'Cancelling...'
|
|
177
|
+
: 'Cancel'
|
|
178
|
+
: editDataSource
|
|
179
|
+
? 'Update'
|
|
180
|
+
: 'Create'] })] })] }) }) }));
|
|
135
181
|
};
|
|
136
182
|
const CreateTableModal = (props) => {
|
|
137
183
|
const { isOpen, onClose, query, editDataSource, allowMultipleStatements, showSchemaSelection, onAddOrUpdateSqlQuery, className, initialValues, } = props;
|
|
138
|
-
|
|
184
|
+
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
185
|
+
const [isConfirmOpen, setIsConfirmOpen] = useState(false);
|
|
186
|
+
const cancelRef = useRef(null);
|
|
187
|
+
const resetState = useCallback(() => {
|
|
188
|
+
setIsSubmitting(false);
|
|
189
|
+
setIsConfirmOpen(false);
|
|
190
|
+
cancelRef.current = null;
|
|
191
|
+
}, []);
|
|
192
|
+
const handleClose = useCallback(() => {
|
|
193
|
+
resetState();
|
|
194
|
+
onClose();
|
|
195
|
+
}, [onClose, resetState]);
|
|
196
|
+
const handleRequestClose = useCallback(() => {
|
|
197
|
+
if (!isSubmitting) {
|
|
198
|
+
handleClose();
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
setIsConfirmOpen(true);
|
|
202
|
+
}, [handleClose, isSubmitting]);
|
|
203
|
+
const handleConfirmClose = useCallback(() => {
|
|
204
|
+
cancelRef.current?.();
|
|
205
|
+
handleClose();
|
|
206
|
+
}, [handleClose]);
|
|
207
|
+
return (_jsxs(Dialog, { open: isOpen, onOpenChange: (open) => {
|
|
208
|
+
if (!open) {
|
|
209
|
+
handleRequestClose();
|
|
210
|
+
}
|
|
211
|
+
}, children: [_jsx(DialogContent, { className: cn('w-3xl max-w-[80%]', className), children: isOpen && (_jsx(CreateTableForm, { query: query, onClose: handleClose, onRequestClose: handleRequestClose, editDataSource: editDataSource, allowMultipleStatements: allowMultipleStatements, showSchemaSelection: showSchemaSelection, onAddOrUpdateSqlQuery: onAddOrUpdateSqlQuery, initialValues: initialValues, onSubmittingChange: setIsSubmitting, onRegisterCancel: (cancel) => {
|
|
212
|
+
cancelRef.current = cancel;
|
|
213
|
+
} })) }), _jsx(Dialog, { open: isConfirmOpen, onOpenChange: setIsConfirmOpen, children: _jsxs(DialogContent, { className: "max-w-md", children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: "Cancel running query?" }), _jsx(DialogDescription, { children: "A query is still running. Cancelling it will stop the query and close this dialog." })] }), _jsxs(DialogFooter, { children: [_jsx(Button, { type: "button", variant: "outline", onClick: () => setIsConfirmOpen(false), children: "Keep running" }), _jsx(Button, { type: "button", onClick: handleConfirmClose, children: "Cancel & close" })] })] }) })] }));
|
|
139
214
|
};
|
|
140
215
|
export default CreateTableModal;
|
|
141
216
|
//# sourceMappingURL=CreateTableModal.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CreateTableModal.js","sourceRoot":"","sources":["../../src/components/CreateTableModal.tsx"],"names":[],"mappings":"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","sourcesContent":["import {zodResolver} from '@hookform/resolvers/zod';\nimport {makeQualifiedTableName} from '@sqlrooms/duckdb';\nimport {SqlQueryDataSource} from '@sqlrooms/room-shell';\nimport {\n Alert,\n AlertDescription,\n Button,\n Checkbox,\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n Form,\n FormControl,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n Input,\n Label,\n Popover,\n PopoverContent,\n PopoverTrigger,\n Spinner,\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n cn,\n} from '@sqlrooms/ui';\nimport {Check, ChevronsUpDown, HelpCircle} from 'lucide-react';\nimport {FC, useCallback, useMemo, useState} from 'react';\nimport {useForm} from 'react-hook-form';\nimport * as z from 'zod';\nimport {useStoreWithSqlEditor} from '../SqlEditorSlice';\nimport {SqlMonacoEditor} from '../SqlMonacoEditor';\n\nconst VALID_TABLE_OR_COLUMN_REGEX = /^[a-zA-Z_][a-zA-Z0-9_]{0,62}$/;\n\nconst formSchema = z.object({\n tableName: z\n .string()\n .min(1, 'Table name is required')\n .regex(\n VALID_TABLE_OR_COLUMN_REGEX,\n 'Only letters, digits and underscores are allowed; should not start with a digit',\n ),\n query: z.string().min(1, 'Query is required'),\n schema: z.string().optional(),\n database: z.string().optional(),\n replace: z.boolean(),\n temp: z.boolean(),\n view: z.boolean(),\n});\n\ntype FormValues = z.infer<typeof formSchema>;\n\n/**\n * Initial values for the create table form.\n */\nexport type CreateTableFormInitialValues = Partial<{\n tableName: string;\n replace: boolean;\n temp: boolean;\n view: boolean;\n schema: string;\n database: string;\n}>;\n\nexport type CreateTableModalProps = {\n query: string;\n isOpen: boolean;\n onClose: () => void;\n editDataSource?: SqlQueryDataSource;\n /**\n * Allow multiple statements in the query. When true, preceding statements\n * will be executed before the final SELECT is wrapped in CREATE TABLE/VIEW.\n */\n allowMultipleStatements?: boolean;\n /**\n * Show schema/database selection UI.\n * @default false\n */\n showSchemaSelection?: boolean;\n /**\n * @deprecated Use createTableFromQuery directly instead.\n * When not provided, the modal will call createTableFromQuery directly.\n */\n onAddOrUpdateSqlQuery?: (\n tableName: string,\n query: string,\n oldTableName?: string,\n ) => Promise<void>;\n /**\n * Additional class name for the dialog content.\n */\n className?: string;\n /**\n * Initial values for the form fields.\n */\n initialValues?: CreateTableFormInitialValues;\n};\n\ntype CreateTableFormProps = {\n query: string;\n onClose: () => void;\n editDataSource?: SqlQueryDataSource;\n allowMultipleStatements?: boolean;\n showSchemaSelection?: boolean;\n onAddOrUpdateSqlQuery?: (\n tableName: string,\n query: string,\n oldTableName?: string,\n ) => Promise<void>;\n initialValues?: CreateTableFormInitialValues;\n};\n\n/**\n * Compact searchable combobox for selecting schema or database.\n */\nconst SchemaCombobox: FC<{\n value: string | undefined;\n onChange: (value: string | undefined) => void;\n options: string[];\n placeholder: string;\n searchPlaceholder: string;\n emptyMessage: string;\n disabled?: boolean;\n}> = ({\n value,\n onChange,\n options,\n placeholder,\n searchPlaceholder,\n emptyMessage,\n disabled,\n}) => {\n const [open, setOpen] = useState(false);\n\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <Button\n variant=\"outline\"\n role=\"combobox\"\n aria-expanded={open}\n className=\"h-9 w-full min-w-0 justify-between font-mono text-xs\"\n disabled={disabled}\n >\n <span className=\"min-w-0 truncate\">{value || placeholder}</span>\n <ChevronsUpDown className=\"ml-1 h-3 w-3 shrink-0 opacity-50\" />\n </Button>\n </PopoverTrigger>\n <PopoverContent className=\"w-[180px] p-0\">\n <Command>\n <CommandInput placeholder={searchPlaceholder} className=\"text-xs\" />\n <CommandList>\n <CommandEmpty className=\"text-xs\">{emptyMessage}</CommandEmpty>\n <CommandGroup>\n {options.map((option) => (\n <CommandItem\n key={option}\n value={option}\n className=\"text-xs\"\n onSelect={(currentValue) => {\n onChange(currentValue === value ? undefined : currentValue);\n setOpen(false);\n }}\n >\n <Check\n className={cn(\n 'mr-2 h-3 w-3',\n value === option ? 'opacity-100' : 'opacity-0',\n )}\n />\n {option}\n </CommandItem>\n ))}\n </CommandGroup>\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n );\n};\n\n/**\n * Compact checkbox option with clickable label and tooltip.\n */\nconst OptionCheckbox: FC<{\n id: string;\n label: string;\n tooltip: string;\n checked: boolean;\n onCheckedChange: (checked: boolean) => void;\n disabled?: boolean;\n}> = ({id, label, tooltip, checked, onCheckedChange, disabled}) => (\n <div className=\"flex items-center gap-1.5\">\n <Checkbox\n id={id}\n checked={checked}\n onCheckedChange={onCheckedChange}\n disabled={disabled}\n className=\"h-3.5 w-3.5\"\n />\n <Label\n htmlFor={id}\n className={cn(\n 'cursor-pointer text-xs font-normal',\n disabled && 'cursor-not-allowed opacity-50',\n )}\n >\n {label}\n </Label>\n <Tooltip>\n <TooltipTrigger asChild>\n <HelpCircle className=\"text-muted-foreground h-3 w-3 cursor-help\" />\n </TooltipTrigger>\n <TooltipContent side=\"top\" className=\"max-w-[200px] text-xs\">\n {tooltip}\n </TooltipContent>\n </Tooltip>\n </div>\n);\n\nconst CreateTableForm: FC<CreateTableFormProps> = ({\n query,\n onClose,\n editDataSource,\n allowMultipleStatements = false,\n showSchemaSelection = false,\n onAddOrUpdateSqlQuery,\n initialValues,\n}) => {\n const connector = useStoreWithSqlEditor((state) => state.db.connector);\n const createTableFromQuery = useStoreWithSqlEditor(\n (state) => state.db.createTableFromQuery,\n );\n const refreshTableSchemas = useStoreWithSqlEditor(\n (state) => state.db.refreshTableSchemas,\n );\n const tables = useStoreWithSqlEditor((state) => state.db.tables);\n const currentSchema = useStoreWithSqlEditor(\n (state) => state.db.currentSchema,\n );\n const currentDatabase = useStoreWithSqlEditor(\n (state) => state.db.currentDatabase,\n );\n\n // Extract unique schemas and databases from tables (excluding system ones)\n const {schemas, databases} = useMemo(() => {\n const schemaSet = new Set<string>();\n const databaseSet = new Set<string>();\n\n for (const table of tables) {\n if (table.table.schema && !table.table.schema.startsWith('pg_')) {\n schemaSet.add(table.table.schema);\n }\n if (table.table.database) {\n databaseSet.add(table.table.database);\n }\n }\n\n // Ensure current schema/database are included\n if (currentSchema) schemaSet.add(currentSchema);\n if (currentDatabase) databaseSet.add(currentDatabase);\n\n return {\n schemas: Array.from(schemaSet).sort(),\n databases: Array.from(databaseSet).sort(),\n };\n }, [tables, currentSchema, currentDatabase]);\n\n const form = useForm<FormValues>({\n resolver: zodResolver(formSchema as any),\n defaultValues: {\n tableName: editDataSource?.tableName ?? initialValues?.tableName ?? '',\n query: editDataSource?.sqlQuery ?? query.trim(),\n schema: initialValues?.schema ?? currentSchema,\n database: initialValues?.database ?? currentDatabase,\n replace: initialValues?.replace ?? false,\n temp: initialValues?.temp ?? false,\n view: initialValues?.view ?? false,\n },\n });\n\n const isSubmitting = form.formState.isSubmitting;\n\n const onSubmit = useCallback(\n async (values: FormValues) => {\n try {\n const {tableName, query, schema, database, replace, temp, view} =\n values;\n\n if (onAddOrUpdateSqlQuery) {\n // Legacy path: use the callback\n await onAddOrUpdateSqlQuery(\n tableName,\n query,\n editDataSource?.tableName,\n );\n } else {\n // New path: call createTableFromQuery directly\n const qualifiedName =\n schema || database\n ? makeQualifiedTableName({table: tableName, schema, database})\n : tableName;\n\n await createTableFromQuery(qualifiedName, query, {\n replace,\n temp,\n view,\n allowMultipleStatements,\n });\n\n // Refresh table schemas to show the new table\n await refreshTableSchemas();\n }\n\n form.reset();\n onClose();\n } catch (err) {\n form.setError('root', {type: 'manual', message: `${err}`});\n }\n },\n [\n onAddOrUpdateSqlQuery,\n editDataSource?.tableName,\n createTableFromQuery,\n allowMultipleStatements,\n refreshTableSchemas,\n onClose,\n form,\n ],\n );\n\n const watchView = form.watch('view');\n const watchTemp = form.watch('temp');\n const watchTableName = form.watch('tableName');\n\n return (\n <TooltipProvider delayDuration={200}>\n <Form {...form}>\n <form onSubmit={form.handleSubmit(onSubmit)} className=\"space-y-4\">\n <DialogHeader>\n <DialogTitle>\n {editDataSource\n ? 'Edit table query'\n : watchView\n ? 'Create view from query'\n : 'Create table from query'}\n </DialogTitle>\n {!editDataSource && (\n <DialogDescription>\n {watchView\n ? 'Create a new view from an SQL query.'\n : 'Create a new table from the results of an SQL query.'}\n </DialogDescription>\n )}\n </DialogHeader>\n\n {form.formState.errors.root && (\n <Alert variant=\"destructive\">\n <AlertDescription className=\"whitespace-pre-wrap font-mono text-xs\">\n {form.formState.errors.root.message}\n </AlertDescription>\n </Alert>\n )}\n\n {/* Table name, schema, database in single row */}\n <div className=\"flex items-end gap-3\">\n <FormField\n control={form.control}\n name=\"tableName\"\n render={({field}) => (\n <FormItem className=\"min-w-0 flex-[2]\">\n <FormLabel className=\"text-xs\">\n {watchView ? 'View name' : 'Table name'}\n </FormLabel>\n <FormControl>\n <Input\n {...field}\n className=\"h-9 font-mono text-xs\"\n autoFocus\n disabled={isSubmitting}\n />\n </FormControl>\n <FormMessage className=\"text-xs\" />\n </FormItem>\n )}\n />\n\n {showSchemaSelection && (\n <>\n <FormField\n control={form.control}\n name=\"schema\"\n render={({field}) => (\n <FormItem className=\"min-w-0 flex-1\">\n <FormLabel className=\"text-xs\">Schema</FormLabel>\n <FormControl>\n <SchemaCombobox\n value={field.value}\n onChange={field.onChange}\n options={schemas}\n placeholder=\"Schema...\"\n searchPlaceholder=\"Search...\"\n emptyMessage=\"No schemas.\"\n disabled={isSubmitting}\n />\n </FormControl>\n </FormItem>\n )}\n />\n\n {(databases.length > 1 || watchTemp) && (\n <FormField\n control={form.control}\n name=\"database\"\n render={({field}) => (\n <FormItem className=\"min-w-0 flex-1\">\n <FormLabel className=\"text-xs\">Database</FormLabel>\n <FormControl>\n <SchemaCombobox\n value={watchTemp ? 'temp' : field.value}\n onChange={field.onChange}\n options={databases}\n placeholder=\"Database...\"\n searchPlaceholder=\"Search...\"\n emptyMessage=\"No databases.\"\n disabled={isSubmitting || watchTemp}\n />\n </FormControl>\n </FormItem>\n )}\n />\n )}\n </>\n )}\n </div>\n\n <FormField\n control={form.control}\n name=\"query\"\n render={({field}) => (\n <FormItem className=\"relative flex h-[200px] flex-col\">\n <FormControl>\n <SqlMonacoEditor\n connector={connector}\n value={field.value}\n onChange={field.onChange}\n className=\"absolute inset-0 h-full w-full\"\n options={{\n scrollBeyondLastLine: false,\n automaticLayout: true,\n minimap: {enabled: false},\n wordWrap: 'on',\n folding: false,\n lineNumbers: 'off',\n readOnly: isSubmitting,\n fixedOverflowWidgets: false, // default true doesn't work well in a modal\n }}\n />\n </FormControl>\n <FormMessage className=\"text-xs\" />\n </FormItem>\n )}\n />\n\n {/* Compact options row */}\n {!onAddOrUpdateSqlQuery && (\n <div className=\"flex items-center gap-6 rounded-md border px-3 py-2\">\n <FormField\n control={form.control}\n name=\"view\"\n render={({field}) => (\n <OptionCheckbox\n id=\"create-table-view\"\n label=\"View\"\n tooltip=\"Create a view instead of a table. Views store the query, not the data.\"\n checked={field.value}\n onCheckedChange={field.onChange}\n disabled={isSubmitting}\n />\n )}\n />\n\n {/* <FormField\n control={form.control}\n name=\"temp\"\n render={({field}) => (\n <OptionCheckbox\n id=\"create-table-temp\"\n label=\"Temporary\"\n tooltip={`${watchView ? 'View' : 'Table'} will be deleted when the session ends.`}\n checked={field.value}\n onCheckedChange={field.onChange}\n disabled={isSubmitting}\n />\n )}\n /> */}\n\n <FormField\n control={form.control}\n name=\"replace\"\n render={({field}) => (\n <OptionCheckbox\n id=\"create-table-replace\"\n label=\"Overwrite\"\n tooltip={`Overwrite existing ${watchView ? 'view' : 'table'} with the same name if it exists.`}\n checked={field.value}\n onCheckedChange={field.onChange}\n disabled={isSubmitting}\n />\n )}\n />\n </div>\n )}\n\n <DialogFooter>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={onClose}\n disabled={isSubmitting}\n >\n Cancel\n </Button>\n <Button\n type=\"submit\"\n disabled={isSubmitting || !watchTableName?.trim()}\n >\n {isSubmitting && <Spinner className=\"mr-2\" />}\n {editDataSource ? 'Update' : 'Create'}\n </Button>\n </DialogFooter>\n </form>\n </Form>\n </TooltipProvider>\n );\n};\n\nconst CreateTableModal: FC<CreateTableModalProps> = (props) => {\n const {\n isOpen,\n onClose,\n query,\n editDataSource,\n allowMultipleStatements,\n showSchemaSelection,\n onAddOrUpdateSqlQuery,\n className,\n initialValues,\n } = props;\n\n return (\n <Dialog open={isOpen} onOpenChange={(open) => !open && onClose()}>\n <DialogContent className={cn('w-3xl max-w-[80%]', className)}>\n {isOpen && (\n <CreateTableForm\n query={query}\n onClose={onClose}\n editDataSource={editDataSource}\n allowMultipleStatements={allowMultipleStatements}\n showSchemaSelection={showSchemaSelection}\n onAddOrUpdateSqlQuery={onAddOrUpdateSqlQuery}\n initialValues={initialValues}\n />\n )}\n </DialogContent>\n </Dialog>\n );\n};\n\nexport default CreateTableModal;\n"]}
|
|
1
|
+
{"version":3,"file":"CreateTableModal.js","sourceRoot":"","sources":["../../src/components/CreateTableModal.tsx"],"names":[],"mappings":"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","sourcesContent":["import {zodResolver} from '@hookform/resolvers/zod';\nimport {makeQualifiedTableName} from '@sqlrooms/duckdb';\nimport {SqlQueryDataSource} from '@sqlrooms/room-shell';\nimport {\n Alert,\n AlertDescription,\n Button,\n Checkbox,\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n Form,\n FormControl,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n Input,\n Label,\n Popover,\n PopoverContent,\n PopoverTrigger,\n Spinner,\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n cn,\n} from '@sqlrooms/ui';\nimport {Check, ChevronsUpDown, HelpCircle} from 'lucide-react';\nimport {FC, useCallback, useEffect, useMemo, useRef, useState} from 'react';\nimport {useForm} from 'react-hook-form';\nimport * as z from 'zod';\nimport {useStoreWithSqlEditor} from '../SqlEditorSlice';\nimport {SqlMonacoEditor} from '../SqlMonacoEditor';\n\nconst VALID_TABLE_OR_COLUMN_REGEX = /^[a-zA-Z_][a-zA-Z0-9_]{0,62}$/;\n\nconst formSchema = z.object({\n tableName: z\n .string()\n .min(1, 'Table name is required')\n .regex(\n VALID_TABLE_OR_COLUMN_REGEX,\n 'Only letters, digits and underscores are allowed; should not start with a digit',\n ),\n query: z.string().min(1, 'Query is required'),\n schema: z.string().optional(),\n database: z.string().optional(),\n replace: z.boolean(),\n temp: z.boolean(),\n view: z.boolean(),\n});\n\ntype FormValues = z.infer<typeof formSchema>;\n\n/**\n * Initial values for the create table form.\n */\nexport type CreateTableFormInitialValues = Partial<{\n tableName: string;\n replace: boolean;\n temp: boolean;\n view: boolean;\n schema: string;\n database: string;\n}>;\n\nexport type CreateTableModalProps = {\n query: string;\n isOpen: boolean;\n onClose: () => void;\n editDataSource?: SqlQueryDataSource;\n /**\n * Allow multiple statements in the query. When true, preceding statements\n * will be executed before the final SELECT is wrapped in CREATE TABLE/VIEW.\n */\n allowMultipleStatements?: boolean;\n /**\n * Show schema/database selection UI.\n * @default false\n */\n showSchemaSelection?: boolean;\n /**\n * @deprecated Use createTableFromQuery directly instead.\n * When not provided, the modal will call createTableFromQuery directly.\n */\n onAddOrUpdateSqlQuery?: (\n tableName: string,\n query: string,\n oldTableName?: string,\n abortSignal?: AbortSignal,\n ) => Promise<void>;\n /**\n * Additional class name for the dialog content.\n */\n className?: string;\n /**\n * Initial values for the form fields.\n */\n initialValues?: CreateTableFormInitialValues;\n};\n\ntype CreateTableFormProps = {\n query: string;\n onClose: () => void;\n onRequestClose: () => void;\n editDataSource?: SqlQueryDataSource;\n allowMultipleStatements?: boolean;\n showSchemaSelection?: boolean;\n onAddOrUpdateSqlQuery?: (\n tableName: string,\n query: string,\n oldTableName?: string,\n abortSignal?: AbortSignal,\n ) => Promise<void>;\n initialValues?: CreateTableFormInitialValues;\n onSubmittingChange?: (isSubmitting: boolean) => void;\n onRegisterCancel?: (cancel: () => void) => void;\n};\n\nconst isAbortError = (err: unknown): boolean => {\n if (err instanceof DOMException) {\n return err.name === 'AbortError';\n }\n if (err instanceof Error) {\n return err.name === 'AbortError' || /cancelled|canceled/i.test(err.message);\n }\n return false;\n};\n\n/**\n * Compact searchable combobox for selecting schema or database.\n */\nconst SchemaCombobox: FC<{\n value: string | undefined;\n onChange: (value: string | undefined) => void;\n options: string[];\n placeholder: string;\n searchPlaceholder: string;\n emptyMessage: string;\n disabled?: boolean;\n}> = ({\n value,\n onChange,\n options,\n placeholder,\n searchPlaceholder,\n emptyMessage,\n disabled,\n}) => {\n const [open, setOpen] = useState(false);\n\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <Button\n variant=\"outline\"\n role=\"combobox\"\n aria-expanded={open}\n className=\"h-9 w-full min-w-0 justify-between font-mono text-xs\"\n disabled={disabled}\n >\n <span className=\"min-w-0 truncate\">{value || placeholder}</span>\n <ChevronsUpDown className=\"ml-1 h-3 w-3 shrink-0 opacity-50\" />\n </Button>\n </PopoverTrigger>\n <PopoverContent className=\"w-[180px] p-0\">\n <Command>\n <CommandInput placeholder={searchPlaceholder} className=\"text-xs\" />\n <CommandList>\n <CommandEmpty className=\"text-xs\">{emptyMessage}</CommandEmpty>\n <CommandGroup>\n {options.map((option) => (\n <CommandItem\n key={option}\n value={option}\n className=\"text-xs\"\n onSelect={(currentValue) => {\n onChange(currentValue === value ? undefined : currentValue);\n setOpen(false);\n }}\n >\n <Check\n className={cn(\n 'mr-2 h-3 w-3',\n value === option ? 'opacity-100' : 'opacity-0',\n )}\n />\n {option}\n </CommandItem>\n ))}\n </CommandGroup>\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n );\n};\n\n/**\n * Compact checkbox option with clickable label and tooltip.\n */\nconst OptionCheckbox: FC<{\n id: string;\n label: string;\n tooltip: string;\n checked: boolean;\n onCheckedChange: (checked: boolean) => void;\n disabled?: boolean;\n}> = ({id, label, tooltip, checked, onCheckedChange, disabled}) => (\n <div className=\"flex items-center gap-1.5\">\n <Checkbox\n id={id}\n checked={checked}\n onCheckedChange={onCheckedChange}\n disabled={disabled}\n className=\"h-3.5 w-3.5\"\n />\n <Label\n htmlFor={id}\n className={cn(\n 'cursor-pointer text-xs font-normal',\n disabled && 'cursor-not-allowed opacity-50',\n )}\n >\n {label}\n </Label>\n <Tooltip>\n <TooltipTrigger asChild>\n <HelpCircle className=\"text-muted-foreground h-3 w-3 cursor-help\" />\n </TooltipTrigger>\n <TooltipContent side=\"top\" className=\"max-w-[200px] text-xs\">\n {tooltip}\n </TooltipContent>\n </Tooltip>\n </div>\n);\n\nconst CreateTableForm: FC<CreateTableFormProps> = ({\n query,\n onClose,\n onRequestClose,\n editDataSource,\n allowMultipleStatements = false,\n showSchemaSelection = false,\n onAddOrUpdateSqlQuery,\n initialValues,\n onSubmittingChange,\n onRegisterCancel,\n}) => {\n const connector = useStoreWithSqlEditor((state) => state.db.connector);\n const createTableFromQuery = useStoreWithSqlEditor(\n (state) => state.db.createTableFromQuery,\n );\n const refreshTableSchemas = useStoreWithSqlEditor(\n (state) => state.db.refreshTableSchemas,\n );\n const tables = useStoreWithSqlEditor((state) => state.db.tables);\n const currentSchema = useStoreWithSqlEditor(\n (state) => state.db.currentSchema,\n );\n const currentDatabase = useStoreWithSqlEditor(\n (state) => state.db.currentDatabase,\n );\n\n // Extract unique schemas and databases from tables (excluding system ones)\n const {schemas, databases} = useMemo(() => {\n const schemaSet = new Set<string>();\n const databaseSet = new Set<string>();\n\n for (const table of tables) {\n if (table.table.schema && !table.table.schema.startsWith('pg_')) {\n schemaSet.add(table.table.schema);\n }\n if (table.table.database) {\n databaseSet.add(table.table.database);\n }\n }\n\n // Ensure current schema/database are included\n if (currentSchema) schemaSet.add(currentSchema);\n if (currentDatabase) databaseSet.add(currentDatabase);\n\n return {\n schemas: Array.from(schemaSet).sort(),\n databases: Array.from(databaseSet).sort(),\n };\n }, [tables, currentSchema, currentDatabase]);\n\n const form = useForm<FormValues>({\n resolver: zodResolver(formSchema as any),\n defaultValues: {\n tableName: editDataSource?.tableName ?? initialValues?.tableName ?? '',\n query: editDataSource?.sqlQuery ?? query.trim(),\n schema: initialValues?.schema ?? currentSchema,\n database: initialValues?.database ?? currentDatabase,\n replace: initialValues?.replace ?? false,\n temp: initialValues?.temp ?? false,\n view: initialValues?.view ?? false,\n },\n });\n\n const isSubmitting = form.formState.isSubmitting;\n const [isCancelling, setIsCancelling] = useState(false);\n const abortControllerRef = useRef<AbortController | null>(null);\n\n useEffect(() => {\n return () => {\n abortControllerRef.current?.abort();\n abortControllerRef.current = null;\n };\n }, []);\n useEffect(() => {\n onSubmittingChange?.(isSubmitting);\n }, [isSubmitting, onSubmittingChange]);\n\n const onSubmit = useCallback(\n async (values: FormValues) => {\n const abortController = new AbortController();\n abortControllerRef.current = abortController;\n setIsCancelling(false);\n try {\n const {tableName, query, schema, database, replace, temp, view} =\n values;\n\n if (onAddOrUpdateSqlQuery) {\n // Legacy path: use the callback\n await onAddOrUpdateSqlQuery(\n tableName,\n query,\n editDataSource?.tableName,\n abortController.signal,\n );\n } else {\n // New path: call createTableFromQuery directly\n const qualifiedName =\n schema || database\n ? makeQualifiedTableName({table: tableName, schema, database})\n : tableName;\n\n await createTableFromQuery(qualifiedName, query, {\n replace,\n temp,\n view,\n allowMultipleStatements,\n abortSignal: abortController.signal,\n });\n\n // Refresh table schemas to show the new table\n await refreshTableSchemas();\n }\n\n form.reset();\n onClose();\n } catch (err) {\n if (isAbortError(err)) {\n return;\n }\n form.setError('root', {type: 'manual', message: `${err}`});\n } finally {\n abortControllerRef.current = null;\n setIsCancelling(false);\n }\n },\n [\n onAddOrUpdateSqlQuery,\n editDataSource?.tableName,\n createTableFromQuery,\n allowMultipleStatements,\n refreshTableSchemas,\n onClose,\n form,\n ],\n );\n\n const watchView = form.watch('view');\n const watchTemp = form.watch('temp');\n const watchTableName = form.watch('tableName');\n\n const handleCancel = useCallback(async () => {\n if (abortControllerRef.current) {\n setIsCancelling(true);\n abortControllerRef.current.abort();\n }\n }, []);\n useEffect(() => {\n onRegisterCancel?.(handleCancel);\n }, [handleCancel, onRegisterCancel]);\n\n return (\n <TooltipProvider delayDuration={200}>\n <Form {...form}>\n <form onSubmit={form.handleSubmit(onSubmit)} className=\"space-y-4\">\n <DialogHeader>\n <DialogTitle>\n {editDataSource\n ? 'Edit table query'\n : watchView\n ? 'Create view from query'\n : 'Create table from query'}\n </DialogTitle>\n {!editDataSource && (\n <DialogDescription>\n {watchView\n ? 'Create a new view from an SQL query.'\n : 'Create a new table from the results of an SQL query.'}\n </DialogDescription>\n )}\n </DialogHeader>\n\n {form.formState.errors.root && (\n <Alert variant=\"destructive\">\n <AlertDescription className=\"whitespace-pre-wrap font-mono text-xs\">\n {form.formState.errors.root.message}\n </AlertDescription>\n </Alert>\n )}\n\n {/* Table name, schema, database in single row */}\n <div className=\"flex items-start gap-3\">\n <FormField\n control={form.control}\n name=\"tableName\"\n render={({field}) => (\n <FormItem className=\"min-w-0 flex-[2]\">\n <FormLabel className=\"text-xs\">\n {watchView ? 'View name' : 'Table name'}\n </FormLabel>\n <FormControl>\n <Input\n {...field}\n className=\"h-9 font-mono text-xs\"\n autoFocus\n disabled={isSubmitting}\n />\n </FormControl>\n <FormMessage className=\"text-xs\" />\n </FormItem>\n )}\n />\n\n {showSchemaSelection && (\n <>\n <FormField\n control={form.control}\n name=\"schema\"\n render={({field}) => (\n <FormItem className=\"min-w-0 flex-1\">\n <FormLabel className=\"text-xs\">Schema</FormLabel>\n <FormControl>\n <SchemaCombobox\n value={field.value}\n onChange={field.onChange}\n options={schemas}\n placeholder=\"Schema...\"\n searchPlaceholder=\"Search...\"\n emptyMessage=\"No schemas.\"\n disabled={isSubmitting}\n />\n </FormControl>\n </FormItem>\n )}\n />\n\n {(databases.length > 1 || watchTemp) && (\n <FormField\n control={form.control}\n name=\"database\"\n render={({field}) => (\n <FormItem className=\"min-w-0 flex-1\">\n <FormLabel className=\"text-xs\">Database</FormLabel>\n <FormControl>\n <SchemaCombobox\n value={watchTemp ? 'temp' : field.value}\n onChange={field.onChange}\n options={databases}\n placeholder=\"Database...\"\n searchPlaceholder=\"Search...\"\n emptyMessage=\"No databases.\"\n disabled={isSubmitting || watchTemp}\n />\n </FormControl>\n </FormItem>\n )}\n />\n )}\n </>\n )}\n </div>\n\n <FormField\n control={form.control}\n name=\"query\"\n render={({field}) => (\n <FormItem className=\"relative flex h-[200px] flex-col\">\n <FormControl>\n <SqlMonacoEditor\n connector={connector}\n value={field.value}\n onChange={field.onChange}\n className=\"absolute inset-0 h-full w-full\"\n options={{\n scrollBeyondLastLine: false,\n automaticLayout: true,\n minimap: {enabled: false},\n wordWrap: 'on',\n folding: false,\n lineNumbers: 'off',\n readOnly: isSubmitting,\n fixedOverflowWidgets: false, // default true doesn't work well in a modal\n }}\n />\n </FormControl>\n <FormMessage className=\"text-xs\" />\n </FormItem>\n )}\n />\n\n {/* Compact options row */}\n {!onAddOrUpdateSqlQuery && (\n <div className=\"flex items-center gap-6 rounded-md border px-3 py-2\">\n <FormField\n control={form.control}\n name=\"view\"\n render={({field}) => (\n <OptionCheckbox\n id=\"create-table-view\"\n label=\"View\"\n tooltip=\"Create a view instead of a table. Views store the query, not the data.\"\n checked={field.value}\n onCheckedChange={field.onChange}\n disabled={isSubmitting}\n />\n )}\n />\n\n {/* <FormField\n control={form.control}\n name=\"temp\"\n render={({field}) => (\n <OptionCheckbox\n id=\"create-table-temp\"\n label=\"Temporary\"\n tooltip={`${watchView ? 'View' : 'Table'} will be deleted when the session ends.`}\n checked={field.value}\n onCheckedChange={field.onChange}\n disabled={isSubmitting}\n />\n )}\n /> */}\n\n <FormField\n control={form.control}\n name=\"replace\"\n render={({field}) => (\n <OptionCheckbox\n id=\"create-table-replace\"\n label=\"Overwrite\"\n tooltip={`Overwrite existing ${watchView ? 'view' : 'table'} with the same name if it exists.`}\n checked={field.value}\n onCheckedChange={field.onChange}\n disabled={isSubmitting}\n />\n )}\n />\n </div>\n )}\n\n <DialogFooter>\n <Button type=\"button\" variant=\"outline\" onClick={onRequestClose}>\n Close\n </Button>\n <Button\n type={isSubmitting ? 'button' : 'submit'}\n onClick={isSubmitting ? handleCancel : undefined}\n disabled={isSubmitting ? isCancelling : !watchTableName?.trim()}\n >\n {isSubmitting && <Spinner className=\"mr-2\" />}\n {isSubmitting\n ? isCancelling\n ? 'Cancelling...'\n : 'Cancel'\n : editDataSource\n ? 'Update'\n : 'Create'}\n </Button>\n </DialogFooter>\n </form>\n </Form>\n </TooltipProvider>\n );\n};\n\nconst CreateTableModal: FC<CreateTableModalProps> = (props) => {\n const {\n isOpen,\n onClose,\n query,\n editDataSource,\n allowMultipleStatements,\n showSchemaSelection,\n onAddOrUpdateSqlQuery,\n className,\n initialValues,\n } = props;\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [isConfirmOpen, setIsConfirmOpen] = useState(false);\n const cancelRef = useRef<(() => void) | null>(null);\n\n const resetState = useCallback(() => {\n setIsSubmitting(false);\n setIsConfirmOpen(false);\n cancelRef.current = null;\n }, []);\n\n const handleClose = useCallback(() => {\n resetState();\n onClose();\n }, [onClose, resetState]);\n\n const handleRequestClose = useCallback(() => {\n if (!isSubmitting) {\n handleClose();\n return;\n }\n setIsConfirmOpen(true);\n }, [handleClose, isSubmitting]);\n\n const handleConfirmClose = useCallback(() => {\n cancelRef.current?.();\n handleClose();\n }, [handleClose]);\n\n return (\n <Dialog\n open={isOpen}\n onOpenChange={(open) => {\n if (!open) {\n handleRequestClose();\n }\n }}\n >\n <DialogContent className={cn('w-3xl max-w-[80%]', className)}>\n {isOpen && (\n <CreateTableForm\n query={query}\n onClose={handleClose}\n onRequestClose={handleRequestClose}\n editDataSource={editDataSource}\n allowMultipleStatements={allowMultipleStatements}\n showSchemaSelection={showSchemaSelection}\n onAddOrUpdateSqlQuery={onAddOrUpdateSqlQuery}\n initialValues={initialValues}\n onSubmittingChange={setIsSubmitting}\n onRegisterCancel={(cancel) => {\n cancelRef.current = cancel;\n }}\n />\n )}\n </DialogContent>\n <Dialog open={isConfirmOpen} onOpenChange={setIsConfirmOpen}>\n <DialogContent className=\"max-w-md\">\n <DialogHeader>\n <DialogTitle>Cancel running query?</DialogTitle>\n <DialogDescription>\n A query is still running. Cancelling it will stop the query and\n close this dialog.\n </DialogDescription>\n </DialogHeader>\n <DialogFooter>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => setIsConfirmOpen(false)}\n >\n Keep running\n </Button>\n <Button type=\"button\" onClick={handleConfirmClose}>\n Cancel & close\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n </Dialog>\n );\n};\n\nexport default CreateTableModal;\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QueryEditorPanelTabsList.d.ts","sourceRoot":"","sources":["../../src/components/QueryEditorPanelTabsList.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAKnD,eAAO,MAAM,wBAAwB,EAAE,KAAK,CAAC,EAAE,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAC,
|
|
1
|
+
{"version":3,"file":"QueryEditorPanelTabsList.d.ts","sourceRoot":"","sources":["../../src/components/QueryEditorPanelTabsList.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAKnD,eAAO,MAAM,wBAAwB,EAAE,KAAK,CAAC,EAAE,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAC,CAuInE,CAAC"}
|
|
@@ -46,6 +46,6 @@ export const QueryEditorPanelTabsList = ({ className, }) => {
|
|
|
46
46
|
setQueryToDelete(null);
|
|
47
47
|
}
|
|
48
48
|
}, [queryToDelete, deleteQueryTab]);
|
|
49
|
-
return (_jsxs(_Fragment, { children: [
|
|
49
|
+
return (_jsxs(_Fragment, { children: [_jsxs(TabStrip, { className: className, tabs: queries, openTabs: openTabs, selectedTabId: selectedQueryId, onClose: closeQueryTab, onOpenTabsChange: setOpenTabs, onSelect: setSelectedQueryId, onCreate: createQueryTab, onRename: renameQueryTab, renderTabMenu: (tab) => (_jsxs(_Fragment, { children: [_jsxs(TabStrip.MenuItem, { onClick: () => handleRenameRequest(tab.id), children: [_jsx(PencilIcon, { className: "mr-2 h-4 w-4" }), "Rename"] }), _jsx(TabStrip.MenuSeparator, {}), _jsxs(TabStrip.MenuItem, { variant: "destructive", onClick: () => handleDelete(tab.id), children: [_jsx(TrashIcon, { className: "mr-2 h-4 w-4" }), "Delete"] })] })), renderSearchItemActions: (tab) => (_jsxs(_Fragment, { children: [_jsx(TabStrip.SearchItemAction, { icon: _jsx(PencilIcon, { className: "h-3 w-3", size: 5 }), "aria-label": `Rename ${tab.name}`, onClick: () => handleRenameRequest(tab.id) }), _jsx(TabStrip.SearchItemAction, { icon: _jsx(TrashIcon, { className: "h-3 w-3" }), "aria-label": `Delete ${tab.name}`, onClick: () => handleDelete(tab.id) })] })), children: [_jsx(TabStrip.SearchDropdown, { sortSearchItems: "recent", getTabLastOpenedAt: (tab) => tab.lastOpenedAt }), _jsx(TabStrip.Tabs, {}), _jsx(TabStrip.NewButton, {})] }), _jsx(DeleteSqlQueryModal, { isOpen: queryToDelete !== null, onClose: () => setQueryToDelete(null), onConfirm: handleConfirmDelete }), _jsx(RenameSqlQueryModal, { isOpen: queryToRename !== null, onClose: () => setQueryToRename(null), initialName: queryToRename?.name ?? '', onRename: handleFinishRename })] }));
|
|
50
50
|
};
|
|
51
51
|
//# sourceMappingURL=QueryEditorPanelTabsList.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QueryEditorPanelTabsList.js","sourceRoot":"","sources":["../../src/components/QueryEditorPanelTabsList.tsx"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"QueryEditorPanelTabsList.js","sourceRoot":"","sources":["../../src/components/QueryEditorPanelTabsList.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAC,QAAQ,EAAC,MAAM,cAAc,CAAC;AACtC,OAAO,EAAC,UAAU,EAAE,SAAS,EAAC,MAAM,cAAc,CAAC;AACnD,OAAc,EAAC,WAAW,EAAE,QAAQ,EAAC,MAAM,OAAO,CAAC;AACnD,OAAO,EAAC,qBAAqB,EAAC,MAAM,mBAAmB,CAAC;AACxD,OAAO,mBAAmB,MAAM,uBAAuB,CAAC;AACxD,OAAO,mBAAmB,MAAM,uBAAuB,CAAC;AAExD,MAAM,CAAC,MAAM,wBAAwB,GAAmC,CAAC,EACvE,SAAS,GACV,EAAE,EAAE;IACH,MAAM,OAAO,GAAG,qBAAqB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACzE,MAAM,QAAQ,GAAG,qBAAqB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC3E,MAAM,eAAe,GAAG,qBAAqB,CAC3C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,eAAe,CAC1C,CAAC;IAEF,MAAM,cAAc,GAAG,qBAAqB,CAC1C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,cAAc,CAClC,CAAC;IACF,MAAM,aAAa,GAAG,qBAAqB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;IAC9E,MAAM,kBAAkB,GAAG,qBAAqB,CAC9C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,kBAAkB,CACtC,CAAC;IACF,MAAM,cAAc,GAAG,qBAAqB,CAC1C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,cAAc,CAClC,CAAC;IACF,MAAM,cAAc,GAAG,qBAAqB,CAC1C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,cAAc,CAClC,CAAC;IACF,MAAM,WAAW,GAAG,qBAAqB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IAE1E,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IACxE,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAGxC,IAAI,CAAC,CAAC;IAEhB,MAAM,mBAAmB,GAAG,WAAW,CACrC,CAAC,OAAe,EAAE,EAAE;QAClB,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,CAAC;QACpD,IAAI,KAAK,EAAE,CAAC;YACV,gBAAgB,CAAC,EAAC,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAC,CAAC,CAAC;QACpD,CAAC;IACH,CAAC,EACD,CAAC,OAAO,CAAC,CACV,CAAC;IAEF,MAAM,kBAAkB,GAAG,WAAW,CACpC,CAAC,OAAe,EAAE,EAAE;QAClB,IAAI,aAAa,EAAE,CAAC;YAClB,cAAc,CAAC,aAAa,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;QAC5C,CAAC;QACD,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACzB,CAAC,EACD,CAAC,aAAa,EAAE,cAAc,CAAC,CAChC,CAAC;IAEF,MAAM,YAAY,GAAG,WAAW,CAC9B,CAAC,OAAe,EAAE,EAAE;QAClB,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,CAAC;QACpD,0EAA0E;QAC1E,IAAI,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YACvC,cAAc,CAAC,OAAO,CAAC,CAAC;QAC1B,CAAC;aAAM,CAAC;YACN,qCAAqC;YACrC,gBAAgB,CAAC,OAAO,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC,EACD,CAAC,OAAO,EAAE,cAAc,CAAC,CAC1B,CAAC;IAEF,MAAM,mBAAmB,GAAG,WAAW,CAAC,GAAG,EAAE;QAC3C,IAAI,aAAa,EAAE,CAAC;YAClB,cAAc,CAAC,aAAa,CAAC,CAAC;YAC9B,gBAAgB,CAAC,IAAI,CAAC,CAAC;QACzB,CAAC;IACH,CAAC,EAAE,CAAC,aAAa,EAAE,cAAc,CAAC,CAAC,CAAC;IAEpC,OAAO,CACL,8BACE,MAAC,QAAQ,IACP,SAAS,EAAE,SAAS,EACpB,IAAI,EAAE,OAAO,EACb,QAAQ,EAAE,QAAQ,EAClB,aAAa,EAAE,eAAe,EAC9B,OAAO,EAAE,aAAa,EACtB,gBAAgB,EAAE,WAAW,EAC7B,QAAQ,EAAE,kBAAkB,EAC5B,QAAQ,EAAE,cAAc,EACxB,QAAQ,EAAE,cAAc,EACxB,aAAa,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,CACtB,8BACE,MAAC,QAAQ,CAAC,QAAQ,IAAC,OAAO,EAAE,GAAG,EAAE,CAAC,mBAAmB,CAAC,GAAG,CAAC,EAAE,CAAC,aAC3D,KAAC,UAAU,IAAC,SAAS,EAAC,cAAc,GAAG,cAErB,EACpB,KAAC,QAAQ,CAAC,aAAa,KAAG,EAC1B,MAAC,QAAQ,CAAC,QAAQ,IAChB,OAAO,EAAC,aAAa,EACrB,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,aAEnC,KAAC,SAAS,IAAC,SAAS,EAAC,cAAc,GAAG,cAEpB,IACnB,CACJ,EACD,uBAAuB,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,CAChC,8BACE,KAAC,QAAQ,CAAC,gBAAgB,IACxB,IAAI,EAAE,KAAC,UAAU,IAAC,SAAS,EAAC,SAAS,EAAC,IAAI,EAAE,CAAC,GAAI,gBACrC,UAAU,GAAG,CAAC,IAAI,EAAE,EAChC,OAAO,EAAE,GAAG,EAAE,CAAC,mBAAmB,CAAC,GAAG,CAAC,EAAE,CAAC,GAC1C,EACF,KAAC,QAAQ,CAAC,gBAAgB,IACxB,IAAI,EAAE,KAAC,SAAS,IAAC,SAAS,EAAC,SAAS,GAAG,gBAC3B,UAAU,GAAG,CAAC,IAAI,EAAE,EAChC,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,GACnC,IACD,CACJ,aAED,KAAC,QAAQ,CAAC,cAAc,IACtB,eAAe,EAAC,QAAQ,EACxB,kBAAkB,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,YAAkC,GACnE,EACF,KAAC,QAAQ,CAAC,IAAI,KAAG,EACjB,KAAC,QAAQ,CAAC,SAAS,KAAG,IACb,EAEX,KAAC,mBAAmB,IAClB,MAAM,EAAE,aAAa,KAAK,IAAI,EAC9B,OAAO,EAAE,GAAG,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,EACrC,SAAS,EAAE,mBAAmB,GAC9B,EACF,KAAC,mBAAmB,IAClB,MAAM,EAAE,aAAa,KAAK,IAAI,EAC9B,OAAO,EAAE,GAAG,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,EACrC,WAAW,EAAE,aAAa,EAAE,IAAI,IAAI,EAAE,EACtC,QAAQ,EAAE,kBAAkB,GAC5B,IACD,CACJ,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import {TabStrip} from '@sqlrooms/ui';\nimport {PencilIcon, TrashIcon} from 'lucide-react';\nimport React, {useCallback, useState} from 'react';\nimport {useStoreWithSqlEditor} from '../SqlEditorSlice';\nimport DeleteSqlQueryModal from './DeleteSqlQueryModal';\nimport RenameSqlQueryModal from './RenameSqlQueryModal';\n\nexport const QueryEditorPanelTabsList: React.FC<{className?: string}> = ({\n className,\n}) => {\n const queries = useStoreWithSqlEditor((s) => s.sqlEditor.config.queries);\n const openTabs = useStoreWithSqlEditor((s) => s.sqlEditor.config.openTabs);\n const selectedQueryId = useStoreWithSqlEditor(\n (s) => s.sqlEditor.config.selectedQueryId,\n );\n\n const renameQueryTab = useStoreWithSqlEditor(\n (s) => s.sqlEditor.renameQueryTab,\n );\n const closeQueryTab = useStoreWithSqlEditor((s) => s.sqlEditor.closeQueryTab);\n const setSelectedQueryId = useStoreWithSqlEditor(\n (s) => s.sqlEditor.setSelectedQueryId,\n );\n const createQueryTab = useStoreWithSqlEditor(\n (s) => s.sqlEditor.createQueryTab,\n );\n const deleteQueryTab = useStoreWithSqlEditor(\n (s) => s.sqlEditor.deleteQueryTab,\n );\n const setOpenTabs = useStoreWithSqlEditor((s) => s.sqlEditor.setOpenTabs);\n\n const [queryToDelete, setQueryToDelete] = useState<string | null>(null);\n const [queryToRename, setQueryToRename] = useState<{\n id: string;\n name: string;\n } | null>(null);\n\n const handleRenameRequest = useCallback(\n (queryId: string) => {\n const query = queries.find((q) => q.id === queryId);\n if (query) {\n setQueryToRename({id: queryId, name: query.name});\n }\n },\n [queries],\n );\n\n const handleFinishRename = useCallback(\n (newName: string) => {\n if (queryToRename) {\n renameQueryTab(queryToRename.id, newName);\n }\n setQueryToRename(null);\n },\n [queryToRename, renameQueryTab],\n );\n\n const handleDelete = useCallback(\n (queryId: string) => {\n const query = queries.find((q) => q.id === queryId);\n // If query is empty (no content), delete immediately without confirmation\n if (query && query.query.trim() === '') {\n deleteQueryTab(queryId);\n } else {\n // Otherwise, show confirmation modal\n setQueryToDelete(queryId);\n }\n },\n [queries, deleteQueryTab],\n );\n\n const handleConfirmDelete = useCallback(() => {\n if (queryToDelete) {\n deleteQueryTab(queryToDelete);\n setQueryToDelete(null);\n }\n }, [queryToDelete, deleteQueryTab]);\n\n return (\n <>\n <TabStrip\n className={className}\n tabs={queries}\n openTabs={openTabs}\n selectedTabId={selectedQueryId}\n onClose={closeQueryTab}\n onOpenTabsChange={setOpenTabs}\n onSelect={setSelectedQueryId}\n onCreate={createQueryTab}\n onRename={renameQueryTab}\n renderTabMenu={(tab) => (\n <>\n <TabStrip.MenuItem onClick={() => handleRenameRequest(tab.id)}>\n <PencilIcon className=\"mr-2 h-4 w-4\" />\n Rename\n </TabStrip.MenuItem>\n <TabStrip.MenuSeparator />\n <TabStrip.MenuItem\n variant=\"destructive\"\n onClick={() => handleDelete(tab.id)}\n >\n <TrashIcon className=\"mr-2 h-4 w-4\" />\n Delete\n </TabStrip.MenuItem>\n </>\n )}\n renderSearchItemActions={(tab) => (\n <>\n <TabStrip.SearchItemAction\n icon={<PencilIcon className=\"h-3 w-3\" size={5} />}\n aria-label={`Rename ${tab.name}`}\n onClick={() => handleRenameRequest(tab.id)}\n />\n <TabStrip.SearchItemAction\n icon={<TrashIcon className=\"h-3 w-3\" />}\n aria-label={`Delete ${tab.name}`}\n onClick={() => handleDelete(tab.id)}\n />\n </>\n )}\n >\n <TabStrip.SearchDropdown\n sortSearchItems=\"recent\"\n getTabLastOpenedAt={(tab) => tab.lastOpenedAt as number | undefined}\n />\n <TabStrip.Tabs />\n <TabStrip.NewButton />\n </TabStrip>\n\n <DeleteSqlQueryModal\n isOpen={queryToDelete !== null}\n onClose={() => setQueryToDelete(null)}\n onConfirm={handleConfirmDelete}\n />\n <RenameSqlQueryModal\n isOpen={queryToRename !== null}\n onClose={() => setQueryToRename(null)}\n initialName={queryToRename?.name ?? ''}\n onRename={handleFinishRename}\n />\n </>\n );\n};\n"]}
|
|
@@ -22,7 +22,10 @@ export interface QueryResultPanelProps {
|
|
|
22
22
|
row: Row<any>;
|
|
23
23
|
event: React.MouseEvent<HTMLTableRowElement>;
|
|
24
24
|
}) => void;
|
|
25
|
+
/** Custom content to render in the error state (e.g., QueryResultPanel.AskAi) */
|
|
26
|
+
children?: React.ReactNode;
|
|
25
27
|
/**
|
|
28
|
+
* @deprecated Use children with QueryResultPanel.AskAi instead
|
|
26
29
|
* Called when the "Ask AI" button is clicked on an error message.
|
|
27
30
|
* Receives the current query and error text.
|
|
28
31
|
*/
|
|
@@ -30,5 +33,17 @@ export interface QueryResultPanelProps {
|
|
|
30
33
|
/** Custom value formatter for arrow data */
|
|
31
34
|
formatValue?: ArrowDataTableValueFormatter;
|
|
32
35
|
}
|
|
33
|
-
export
|
|
36
|
+
export interface QueryResultPanelAskAiProps {
|
|
37
|
+
/** Called when clicked with the current query and error message */
|
|
38
|
+
onClick?: (query: string, error: string) => void;
|
|
39
|
+
/** Custom icon (defaults to MessageCircleQuestion) */
|
|
40
|
+
icon?: React.ReactNode;
|
|
41
|
+
/** Custom className */
|
|
42
|
+
className?: string;
|
|
43
|
+
/** Tooltip text to display on hover */
|
|
44
|
+
tooltipContent?: string;
|
|
45
|
+
}
|
|
46
|
+
export declare const QueryResultPanel: React.FC<QueryResultPanelProps> & {
|
|
47
|
+
AskAi: React.ForwardRefExoticComponent<QueryResultPanelAskAiProps & React.RefAttributes<HTMLButtonElement>>;
|
|
48
|
+
};
|
|
34
49
|
//# sourceMappingURL=QueryResultPanel.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QueryResultPanel.d.ts","sourceRoot":"","sources":["../../src/components/QueryResultPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,EAGL,4BAA4B,EAC7B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"QueryResultPanel.d.ts","sourceRoot":"","sources":["../../src/components/QueryResultPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,EAGL,4BAA4B,EAC7B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,uBAAuB,CAAC;AAW/C,OAAO,KAAK,MAAM,OAAO,CAAC;AAgC1B,MAAM,WAAW,qBAAqB;IACpC,oCAAoC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yDAAyD;IACzD,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC;IACnD,wFAAwF;IACxF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE;QAClB,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,mBAAmB,CAAC,CAAC;KAC9C,KAAK,IAAI,CAAC;IACX;;OAEG;IACH,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE;QACxB,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,mBAAmB,CAAC,CAAC;KAC9C,KAAK,IAAI,CAAC;IACX,iFAAiF;IACjF,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3D,4CAA4C;IAC5C,WAAW,CAAC,EAAE,4BAA4B,CAAC;CAC5C;AAiLD,MAAM,WAAW,0BAA0B;IACzC,mEAAmE;IACnE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACjD,sDAAsD;IACtD,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,uBAAuB;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uCAAuC;IACvC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AA4CD,eAAO,MAAM,gBAAgB;;CAE3B,CAAC"}
|
|
@@ -1,12 +1,38 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { DataTablePaginated, useArrowDataTable, } from '@sqlrooms/data-table';
|
|
3
|
-
import { cn, SpinnerPane, Button } from '@sqlrooms/ui';
|
|
3
|
+
import { cn, SpinnerPane, Button, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from '@sqlrooms/ui';
|
|
4
4
|
import { formatCount } from '@sqlrooms/utils';
|
|
5
5
|
import React from 'react';
|
|
6
6
|
import { isQueryWithResult, useStoreWithSqlEditor } from '../SqlEditorSlice';
|
|
7
7
|
import { MessageCircleQuestion } from 'lucide-react';
|
|
8
8
|
import { QueryResultLimitSelect } from './QueryResultLimitSelect';
|
|
9
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Turns DuckDB's EXPLAIN result table into a readable plan string.
|
|
11
|
+
* Prefer the `explain_value` column (DuckDB default); otherwise fall back
|
|
12
|
+
* to the first column and join all rows with newlines.
|
|
13
|
+
*/
|
|
14
|
+
function arrowTableToExplainText(result) {
|
|
15
|
+
if (!result)
|
|
16
|
+
return '';
|
|
17
|
+
const numRows = result.numRows ?? 0;
|
|
18
|
+
const fields = result.schema?.fields ?? [];
|
|
19
|
+
const fieldNames = fields.map((f) => f.name);
|
|
20
|
+
const hasExplainValueColumn = fieldNames.includes('explain_value');
|
|
21
|
+
const columnName = hasExplainValueColumn ? 'explain_value' : fieldNames[0];
|
|
22
|
+
if (!columnName)
|
|
23
|
+
return '';
|
|
24
|
+
const col = result.getChild?.(columnName);
|
|
25
|
+
if (!col)
|
|
26
|
+
return '';
|
|
27
|
+
const lines = [];
|
|
28
|
+
for (let i = 0; i < numRows; i++) {
|
|
29
|
+
const v = col.get(i);
|
|
30
|
+
if (v != null && String(v).length > 0)
|
|
31
|
+
lines.push(String(v));
|
|
32
|
+
}
|
|
33
|
+
return lines.join('\n');
|
|
34
|
+
}
|
|
35
|
+
const QueryResultPanelRoot = ({ className, renderActions, fontSize = 'text-xs', onRowClick, onRowDoubleClick, children, onAskAiAboutError, formatValue, }) => {
|
|
10
36
|
const queryResult = useStoreWithSqlEditor((s) => {
|
|
11
37
|
const selectedId = s.sqlEditor.config.selectedQueryId;
|
|
12
38
|
return s.sqlEditor.queryResultsById[selectedId];
|
|
@@ -15,12 +41,21 @@ export const QueryResultPanel = ({ className, renderActions, fontSize = 'text-xs
|
|
|
15
41
|
const setQueryResultLimit = useStoreWithSqlEditor((s) => s.sqlEditor.setQueryResultLimit);
|
|
16
42
|
const queryResultLimit = useStoreWithSqlEditor((s) => s.sqlEditor.queryResultLimit);
|
|
17
43
|
const queryResultLimitOptions = useStoreWithSqlEditor((s) => s.sqlEditor.queryResultLimitOptions);
|
|
18
|
-
const
|
|
44
|
+
const tableForDataTable = isQueryWithResult(queryResult) && queryResult.type !== 'explain'
|
|
45
|
+
? queryResult.result
|
|
46
|
+
: undefined;
|
|
47
|
+
const arrowTableData = useArrowDataTable(tableForDataTable, { formatValue });
|
|
48
|
+
const explainText = React.useMemo(() => {
|
|
49
|
+
if (queryResult?.status !== 'success' || queryResult.type !== 'explain') {
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
return arrowTableToExplainText(queryResult.result);
|
|
53
|
+
}, [queryResult]);
|
|
19
54
|
const handleAskAiAboutError = React.useCallback(() => {
|
|
20
55
|
if (queryResult?.status === 'error' && onAskAiAboutError) {
|
|
21
56
|
const currentQuery = getCurrentQuery();
|
|
22
57
|
const errorText = queryResult.error;
|
|
23
|
-
onAskAiAboutError(currentQuery, errorText);
|
|
58
|
+
onAskAiAboutError?.(currentQuery, errorText);
|
|
24
59
|
}
|
|
25
60
|
}, [queryResult, getCurrentQuery, onAskAiAboutError]);
|
|
26
61
|
if (!queryResult) {
|
|
@@ -33,13 +68,45 @@ export const QueryResultPanel = ({ className, renderActions, fontSize = 'text-xs
|
|
|
33
68
|
return (_jsx("div", { className: "p-5 font-mono text-xs leading-tight text-red-500", children: "Query was aborted" }));
|
|
34
69
|
}
|
|
35
70
|
if (queryResult?.status === 'error') {
|
|
36
|
-
|
|
71
|
+
// Backward compat: if no children but onAskAiAboutError is provided, render default button
|
|
72
|
+
const errorActions = children ?? (onAskAiAboutError && (_jsx(Button, { variant: "ghost", size: "icon", className: "h-8 w-8", onClick: handleAskAiAboutError, title: "Ask AI for help", children: _jsx(MessageCircleQuestion, { className: "h-4 w-4" }) })));
|
|
73
|
+
return (_jsxs("div", { className: "relative h-full w-full overflow-auto p-5", children: [errorActions && (_jsx("div", { className: "absolute top-2 right-2", children: errorActions })), _jsx("pre", { className: cn('text-xs leading-tight whitespace-pre-wrap text-red-500', errorActions && 'pr-12'), children: queryResult.error })] }));
|
|
37
74
|
}
|
|
38
75
|
if (queryResult?.status === 'success') {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
76
|
+
const contentWrapperClassName = cn('relative flex h-full w-full flex-grow flex-col overflow-hidden', className);
|
|
77
|
+
// Result shows the EXPLAIN schema
|
|
78
|
+
if (queryResult.type === 'explain') {
|
|
79
|
+
return (_jsx("div", { className: contentWrapperClassName, children: _jsxs("div", { className: "flex h-full w-full flex-col overflow-hidden", children: [_jsx("pre", { className: "flex-1 overflow-auto p-4 font-mono text-xs leading-tight break-words whitespace-pre-wrap", children: explainText }), _jsxs("div", { className: "bg-background flex w-full items-center gap-2 px-4 py-1", children: [_jsx("div", { className: "font-mono text-xs", children: "EXPLAIN" }), _jsx("div", { className: "flex-1" }), renderActions
|
|
80
|
+
? renderActions(queryResult.lastQueryStatement)
|
|
81
|
+
: undefined] })] }) }));
|
|
82
|
+
}
|
|
83
|
+
// Result shows the SELECT/PRAGMA table
|
|
84
|
+
if (isQueryWithResult(queryResult)) {
|
|
85
|
+
return (_jsx("div", { className: contentWrapperClassName, children: _jsxs("div", { className: "flex h-full w-full flex-col", children: [_jsx(DataTablePaginated, { ...arrowTableData, className: "flex-grow overflow-hidden", fontSize: fontSize, isFetching: false, onRowClick: onRowClick, onRowDoubleClick: onRowDoubleClick }), _jsxs("div", { className: "bg-background flex w-full items-center gap-2 px-4 py-1", children: [queryResult.result ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "font-mono text-xs", children: `${formatCount(queryResult.result.numRows ?? 0)} rows` }), queryResult.type === 'select' ? (_jsx(QueryResultLimitSelect, { value: queryResultLimit, onChange: setQueryResultLimit, options: queryResultLimitOptions })) : null] })) : null, _jsx("div", { className: "flex-1" }), renderActions
|
|
86
|
+
? renderActions(queryResult.lastQueryStatement)
|
|
87
|
+
: undefined] })] }) }));
|
|
88
|
+
}
|
|
89
|
+
// Fallback message to show when the query result is not a SELECT/PRAGMA or EXPLAIN
|
|
90
|
+
return (_jsx("div", { className: contentWrapperClassName, children: _jsx("pre", { className: "p-4 text-xs leading-tight text-green-500", children: "Successfully executed query" }) }));
|
|
42
91
|
}
|
|
43
92
|
return null;
|
|
44
93
|
};
|
|
94
|
+
const QueryResultPanelAskAi = React.forwardRef(({ onClick, icon, className, tooltipContent = 'Ask AI for help' }, ref) => {
|
|
95
|
+
const queryResult = useStoreWithSqlEditor((s) => {
|
|
96
|
+
const selectedId = s.sqlEditor.config.selectedQueryId;
|
|
97
|
+
return s.sqlEditor.queryResultsById[selectedId];
|
|
98
|
+
});
|
|
99
|
+
const getCurrentQuery = useStoreWithSqlEditor((s) => s.sqlEditor.getCurrentQuery);
|
|
100
|
+
// Only render in error state
|
|
101
|
+
if (queryResult?.status !== 'error')
|
|
102
|
+
return null;
|
|
103
|
+
const handleClick = () => {
|
|
104
|
+
onClick?.(getCurrentQuery(), queryResult.error);
|
|
105
|
+
};
|
|
106
|
+
return (_jsx(TooltipProvider, { delayDuration: 200, children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { ref: ref, variant: "ghost", size: "icon", className: cn('h-8 w-8', className), onClick: handleClick, children: icon ?? _jsx(MessageCircleQuestion, { className: "h-4 w-4" }) }) }), _jsx(TooltipContent, { children: _jsx("p", { className: "text-xs", children: tooltipContent }) })] }) }));
|
|
107
|
+
});
|
|
108
|
+
QueryResultPanelAskAi.displayName = 'QueryResultPanel.AskAi';
|
|
109
|
+
export const QueryResultPanel = Object.assign(QueryResultPanelRoot, {
|
|
110
|
+
AskAi: QueryResultPanelAskAi,
|
|
111
|
+
});
|
|
45
112
|
//# sourceMappingURL=QueryResultPanel.js.map
|