mirror of https://github.com/buster-so/buster.git
update fetching sql
This commit is contained in:
parent
16c6ea1d26
commit
49ec28142f
File diff suppressed because it is too large
Load Diff
|
@ -38,11 +38,11 @@
|
||||||
"@radix-ui/react-tooltip": "^1.1.8",
|
"@radix-ui/react-tooltip": "^1.1.8",
|
||||||
"@supabase/ssr": "^0.6.1",
|
"@supabase/ssr": "^0.6.1",
|
||||||
"@supabase/supabase-js": "^2.49.4",
|
"@supabase/supabase-js": "^2.49.4",
|
||||||
"@tanstack/query-sync-storage-persister": "^5.71.5",
|
"@tanstack/query-sync-storage-persister": "^5.71.10",
|
||||||
"@tanstack/react-form": "^1.1.4",
|
"@tanstack/react-form": "^1.1.4",
|
||||||
"@tanstack/react-query": "^5.71.5",
|
"@tanstack/react-query": "^5.71.10",
|
||||||
"@tanstack/react-query-devtools": "^5.71.5",
|
"@tanstack/react-query-devtools": "^5.71.10",
|
||||||
"@tanstack/react-query-persist-client": "^5.71.5",
|
"@tanstack/react-query-persist-client": "^5.71.10",
|
||||||
"@tanstack/react-table": "^8.21.2",
|
"@tanstack/react-table": "^8.21.2",
|
||||||
"@types/jest": "^29.5.14",
|
"@types/jest": "^29.5.14",
|
||||||
"@types/prettier": "^2.7.3",
|
"@types/prettier": "^2.7.3",
|
||||||
|
@ -74,7 +74,7 @@
|
||||||
"next-themes": "^0.4.6",
|
"next-themes": "^0.4.6",
|
||||||
"papaparse": "^5.5.2",
|
"papaparse": "^5.5.2",
|
||||||
"pluralize": "^8.0.0",
|
"pluralize": "^8.0.0",
|
||||||
"posthog-js": "^1.234.1",
|
"posthog-js": "^1.234.8",
|
||||||
"prettier": "^3.5.3",
|
"prettier": "^3.5.3",
|
||||||
"prettier-plugin-tailwindcss": "^0.6.11",
|
"prettier-plugin-tailwindcss": "^0.6.11",
|
||||||
"react": "^18",
|
"react": "^18",
|
||||||
|
@ -88,7 +88,7 @@
|
||||||
"rehype-raw": "^7.0.0",
|
"rehype-raw": "^7.0.0",
|
||||||
"remark-gfm": "^4.0.1",
|
"remark-gfm": "^4.0.1",
|
||||||
"sonner": "^2.0.3",
|
"sonner": "^2.0.3",
|
||||||
"tailwind-merge": "^3.0.2",
|
"tailwind-merge": "^3.1.0",
|
||||||
"ts-jest": "^29.3.1",
|
"ts-jest": "^29.3.1",
|
||||||
"use-context-selector": "^2.0.0",
|
"use-context-selector": "^2.0.0",
|
||||||
"utility-types": "^3.11.0",
|
"utility-types": "^3.11.0",
|
||||||
|
@ -99,15 +99,15 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@chromatic-com/storybook": "^3.2.6",
|
"@chromatic-com/storybook": "^3.2.6",
|
||||||
"@eslint/eslintrc": "^3",
|
"@eslint/eslintrc": "^3",
|
||||||
"@storybook/addon-controls": "^8.6.10",
|
"@storybook/addon-controls": "^8.6.12",
|
||||||
"@storybook/addon-essentials": "^8.6.10",
|
"@storybook/addon-essentials": "^8.6.12",
|
||||||
"@storybook/addon-interactions": "^8.6.10",
|
"@storybook/addon-interactions": "^8.6.12",
|
||||||
"@storybook/blocks": "^8.6.10",
|
"@storybook/blocks": "^8.6.12",
|
||||||
"@storybook/nextjs": "^8.6.10",
|
"@storybook/nextjs": "^8.6.12",
|
||||||
"@storybook/react": "^8.6.10",
|
"@storybook/react": "^8.6.12",
|
||||||
"@storybook/test": "^8.6.10",
|
"@storybook/test": "^8.6.12",
|
||||||
"@tailwindcss/postcss": "4.0.17",
|
"@tailwindcss/postcss": "4.1.2",
|
||||||
"@testing-library/react": "^16.2.0",
|
"@testing-library/react": "^16.3.0",
|
||||||
"@types/canvas-confetti": "^1.9.0",
|
"@types/canvas-confetti": "^1.9.0",
|
||||||
"@types/js-cookie": "^3.0.6",
|
"@types/js-cookie": "^3.0.6",
|
||||||
"@types/js-yaml": "^4.0.9",
|
"@types/js-yaml": "^4.0.9",
|
||||||
|
@ -123,9 +123,9 @@
|
||||||
"eslint-config-prettier": "^10.1.1",
|
"eslint-config-prettier": "^10.1.1",
|
||||||
"eslint-plugin-storybook": "^0.12.0",
|
"eslint-plugin-storybook": "^0.12.0",
|
||||||
"msw-storybook-addon": "^2.0.4",
|
"msw-storybook-addon": "^2.0.4",
|
||||||
"sass": "^1.86.0",
|
"sass": "^1.86.3",
|
||||||
"tailwind-scrollbar": "^4.0.1",
|
"tailwind-scrollbar": "^4.0.2",
|
||||||
"tailwindcss": "4.0.17",
|
"tailwindcss": "4.1.2",
|
||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7",
|
||||||
"typescript": "^5"
|
"typescript": "^5"
|
||||||
},
|
},
|
||||||
|
|
|
@ -15,8 +15,7 @@ export const DataContainer: React.FC<{
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
'bg-background rounded border shadow',
|
'bg-background relative h-full w-full overflow-hidden rounded border shadow',
|
||||||
'relative h-full w-full overflow-hidden',
|
|
||||||
className
|
className
|
||||||
)}>
|
)}>
|
||||||
<IndeterminateLinearLoader
|
<IndeterminateLinearLoader
|
||||||
|
|
|
@ -5,10 +5,11 @@ import { AppCodeEditor } from '@/components/ui/inputs/AppCodeEditor';
|
||||||
import { useBusterNotifications } from '@/context/BusterNotifications';
|
import { useBusterNotifications } from '@/context/BusterNotifications';
|
||||||
import { useMemoizedFn } from '@/hooks';
|
import { useMemoizedFn } from '@/hooks';
|
||||||
import { Button } from '@/components/ui/buttons/Button';
|
import { Button } from '@/components/ui/buttons/Button';
|
||||||
import React, { useState } from 'react';
|
import React, { useMemo, useState } from 'react';
|
||||||
import type { AppVerticalCodeSplitterProps } from './AppVerticalCodeSplitter';
|
import type { AppVerticalCodeSplitterProps } from './AppVerticalCodeSplitter';
|
||||||
import { cn } from '@/lib/classMerge';
|
import { cn } from '@/lib/classMerge';
|
||||||
import { ErrorClosableContainer } from '@/components/ui/error/ErrorClosableContainer';
|
import { ErrorClosableContainer } from '@/components/ui/error/ErrorClosableContainer';
|
||||||
|
import { FileCard } from '@/components/ui/card/FileCard';
|
||||||
|
|
||||||
export const SQLContainer: React.FC<{
|
export const SQLContainer: React.FC<{
|
||||||
className?: string;
|
className?: string;
|
||||||
|
@ -34,22 +35,9 @@ export const SQLContainer: React.FC<{
|
||||||
setIsRunning(false);
|
setIsRunning(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
const memoizedFooter = useMemo(() => {
|
||||||
<div
|
return (
|
||||||
className={cn(
|
<>
|
||||||
'flex h-full w-full flex-col overflow-hidden',
|
|
||||||
'bg-background rounded border',
|
|
||||||
className
|
|
||||||
)}>
|
|
||||||
<AppCodeEditor
|
|
||||||
className="overflow-hidden border-x-0 border-t-0"
|
|
||||||
value={sql}
|
|
||||||
onChange={setDatasetSQL}
|
|
||||||
onMetaEnter={onRunQueryPreflight}
|
|
||||||
variant={null}
|
|
||||||
/>
|
|
||||||
<div className="bg-border-color my-0! h-[0.5px] w-full" />
|
|
||||||
<div className="relative flex items-center justify-between px-4 py-2.5">
|
|
||||||
<Button onClick={onCopySQL}>Copy SQL</Button>
|
<Button onClick={onCopySQL}>Copy SQL</Button>
|
||||||
|
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
|
@ -77,10 +65,25 @@ export const SQLContainer: React.FC<{
|
||||||
Run
|
Run
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}, [disabledSave, isRunning, onCopySQL, onRunQueryPreflight, onSaveSQL, sql]);
|
||||||
|
|
||||||
{error && <ErrorClosableContainer error={error} />}
|
return (
|
||||||
</div>
|
<FileCard
|
||||||
</div>
|
className={className}
|
||||||
|
footerClassName="flex justify-between space-x-4"
|
||||||
|
footer={memoizedFooter}>
|
||||||
|
<AppCodeEditor
|
||||||
|
className="overflow-hidden border-x-0 border-t-0"
|
||||||
|
value={sql}
|
||||||
|
onChange={setDatasetSQL}
|
||||||
|
onMetaEnter={onRunQueryPreflight}
|
||||||
|
variant={null}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{error && <ErrorClosableContainer error={error} />}
|
||||||
|
</FileCard>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { cn } from '@/lib/classMerge';
|
||||||
import { Text } from '../typography';
|
import { Text } from '../typography';
|
||||||
|
|
||||||
interface FileCardProps {
|
interface FileCardProps {
|
||||||
fileName: string | React.ReactNode;
|
fileName?: string | React.ReactNode;
|
||||||
headerButtons?: React.ReactNode;
|
headerButtons?: React.ReactNode;
|
||||||
className?: string;
|
className?: string;
|
||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
|
@ -42,7 +42,9 @@ export const FileCard = React.memo(
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
|
||||||
{footer && (
|
{footer && (
|
||||||
<CardFooter className={cn('bg-background', footerClassName)}>{footer}</CardFooter>
|
<CardFooter className={cn('bg-background px-4 py-2.5', footerClassName)}>
|
||||||
|
{footer}
|
||||||
|
</CardFooter>
|
||||||
)}
|
)}
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
|
|
@ -52,16 +52,15 @@ export const MetricViewResults: React.FC<{ metricId: string }> = React.memo(({ m
|
||||||
metricId
|
metricId
|
||||||
});
|
});
|
||||||
|
|
||||||
if (res) {
|
if (res && res.data && res.data.length > 0) {
|
||||||
if (data && data.length > 0) {
|
const data = res.data;
|
||||||
const headerHeight = 50;
|
const headerHeight = 50;
|
||||||
const heightOfRow = 36;
|
const heightOfRow = 36;
|
||||||
const heightOfDataContainer = headerHeight + heightOfRow * (data.length || 0);
|
const heightOfDataContainer = headerHeight + heightOfRow * (data.length || 0);
|
||||||
const containerHeight = containerRef.current?.clientHeight || 0;
|
const containerHeight = containerRef.current?.clientHeight || 0;
|
||||||
const maxHeight = Math.floor(containerHeight * 0.6);
|
const maxHeight = Math.floor(containerHeight * 0.6);
|
||||||
const finalHeight = Math.min(heightOfDataContainer, maxHeight);
|
const finalHeight = Math.min(heightOfDataContainer, maxHeight);
|
||||||
appSplitterRef.current?.setSplitSizes(['auto', `${finalHeight}px`]);
|
appSplitterRef.current?.setSplitSizes(['auto', `${finalHeight}px`]);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
//
|
//
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { useRef } from 'react';
|
import React, { useRef, useEffect } from 'react';
|
||||||
import * as yaml from 'js-yaml';
|
import * as yaml from 'js-yaml';
|
||||||
import * as monaco from 'monaco-editor';
|
import * as monaco from 'monaco-editor';
|
||||||
import { type editor } from 'monaco-editor/esm/vs/editor/editor.api';
|
import { type editor } from 'monaco-editor/esm/vs/editor/editor.api';
|
||||||
|
@ -37,20 +37,29 @@ export const validateMetricYaml = (
|
||||||
try {
|
try {
|
||||||
parsed = yaml.load(content);
|
parsed = yaml.load(content);
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
// For parse errors, try to extract line information from the error message
|
// For parse errors, extract line and column information from the error
|
||||||
let lineNumber = 1;
|
let lineNumber = 1;
|
||||||
const lineMatch = error.message.match(/line (\d+)/i);
|
let columnNumber = 1;
|
||||||
if (lineMatch && lineMatch[1]) {
|
|
||||||
lineNumber = parseInt(lineMatch[1], 10);
|
// js-yaml errors include mark object with position information
|
||||||
|
if (error.mark) {
|
||||||
|
lineNumber = error.mark.line + 1; // Convert to 1-based line numbering
|
||||||
|
columnNumber = error.mark.column + 1; // Convert to 1-based column numbering
|
||||||
|
} else {
|
||||||
|
// Fallback to regex for older versions or different error types
|
||||||
|
const lineMatch = error.message.match(/line (\d+)/i);
|
||||||
|
if (lineMatch && lineMatch[1]) {
|
||||||
|
lineNumber = parseInt(lineMatch[1], 10);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
markers.push({
|
markers.push({
|
||||||
severity: monaco.MarkerSeverity.Error,
|
severity: monaco.MarkerSeverity.Error,
|
||||||
message: 'Invalid YAML 🤣: ' + error.message,
|
message: 'Invalid YAML: ' + error.message,
|
||||||
startLineNumber: lineNumber,
|
startLineNumber: lineNumber,
|
||||||
startColumn: 1,
|
startColumn: columnNumber,
|
||||||
endLineNumber: lineNumber,
|
endLineNumber: lineNumber,
|
||||||
endColumn: 1
|
endColumn: columnNumber + 1 // Highlight at least one character
|
||||||
});
|
});
|
||||||
return markers;
|
return markers;
|
||||||
}
|
}
|
||||||
|
@ -184,18 +193,70 @@ export const validateMetricYaml = (
|
||||||
return markers;
|
return markers;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Helper to configure Monaco YAML schema
|
||||||
|
const configureYamlSchema = (
|
||||||
|
monaco: typeof import('monaco-editor'),
|
||||||
|
editor: editor.IStandaloneCodeEditor
|
||||||
|
) => {
|
||||||
|
// This assumes you have monaco-yaml configured via yamlHelper.ts in the project
|
||||||
|
// The schema will help with validation and autocomplete
|
||||||
|
const model = editor.getModel();
|
||||||
|
if (model) {
|
||||||
|
// Check if the YAML language support exists
|
||||||
|
// This is dynamically added by monaco-yaml and may not be typed correctly
|
||||||
|
const yamlDefaults = (monaco.languages as any).yaml?.yamlDefaults;
|
||||||
|
if (yamlDefaults && typeof yamlDefaults.setDiagnosticsOptions === 'function') {
|
||||||
|
yamlDefaults.setDiagnosticsOptions({
|
||||||
|
validate: true,
|
||||||
|
schemas: [
|
||||||
|
{
|
||||||
|
uri: 'http://myserver/metric-yaml-schema.json',
|
||||||
|
fileMatch: ['*'],
|
||||||
|
schema: {
|
||||||
|
type: 'object',
|
||||||
|
required: ['Person', 'Place', 'Age', 'Siblings'],
|
||||||
|
properties: {
|
||||||
|
Person: { type: 'string' },
|
||||||
|
Place: { type: 'string' },
|
||||||
|
Age: { type: 'number' },
|
||||||
|
Siblings: {
|
||||||
|
type: 'object',
|
||||||
|
additionalProperties: { type: 'number' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const MyYamlEditor: React.FC = () => {
|
export const MyYamlEditor: React.FC = () => {
|
||||||
const editorRef = useRef<any>(null);
|
const editorRef = useRef<editor.IStandaloneCodeEditor | null>(null);
|
||||||
|
|
||||||
// Called once the Monaco editor is mounted
|
// Called once the Monaco editor is mounted
|
||||||
const editorDidMount = (editor: any, monacoInstance: typeof import('monaco-editor')) => {
|
const editorDidMount = (
|
||||||
|
editor: editor.IStandaloneCodeEditor,
|
||||||
|
monacoInstance: typeof import('monaco-editor')
|
||||||
|
) => {
|
||||||
editorRef.current = editor;
|
editorRef.current = editor;
|
||||||
|
|
||||||
// Lint the document on every change
|
// Try to configure YAML schema if monaco-yaml is properly loaded
|
||||||
|
try {
|
||||||
|
// Check if the YAML language support exists using type assertion
|
||||||
|
if ((monacoInstance.languages as any).yaml?.yamlDefaults) {
|
||||||
|
configureYamlSchema(monacoInstance, editor);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Failed to configure YAML schema:', err);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lint the document on every change using our custom validator
|
||||||
editor.onDidChangeModelContent(() => {
|
editor.onDidChangeModelContent(() => {
|
||||||
const value = editor.getValue();
|
const value = editor.getValue();
|
||||||
const markers = validateMetricYaml(value, monacoInstance);
|
const markers = validateMetricYaml(value, monacoInstance);
|
||||||
monacoInstance.editor.setModelMarkers(editor.getModel(), 'yaml', markers);
|
monacoInstance.editor.setModelMarkers(editor.getModel()!, 'yaml', markers);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -21,25 +21,25 @@
|
||||||
--text-3xs: 6px;
|
--text-3xs: 6px;
|
||||||
--text-3xs--line-height: 1;
|
--text-3xs--line-height: 1;
|
||||||
--text-2xs: 8px;
|
--text-2xs: 8px;
|
||||||
--text-2xs--line-height: 1.3;
|
--text-2xs--line-height: 1.25;
|
||||||
--text-xs: 11px;
|
--text-xs: 11px;
|
||||||
--text-xs--line-height: 1.3;
|
--text-xs--line-height: 1.25;
|
||||||
--text-sm: 12px;
|
--text-sm: 12px;
|
||||||
--text-sm--line-height: 1.3;
|
--text-sm--line-height: 1.25;
|
||||||
--text-base: 13px;
|
--text-base: 13px;
|
||||||
--text-base--line-height: 1.3;
|
--text-base--line-height: 1.25;
|
||||||
--text-md: 14px;
|
--text-md: 14px;
|
||||||
--text-md--line-height: 1.3;
|
--text-md--line-height: 1.25;
|
||||||
--text-lg: 16px;
|
--text-lg: 16px;
|
||||||
--text-lg--line-height: 1.3;
|
--text-lg--line-height: 1.25;
|
||||||
--text-xl: 18px;
|
--text-xl: 18px;
|
||||||
--text-xl--line-height: 1.3;
|
--text-xl--line-height: 1.25;
|
||||||
--text-2xl: 20px;
|
--text-2xl: 20px;
|
||||||
--text-2xl--line-height: 1.3;
|
--text-2xl--line-height: 1.25;
|
||||||
--text-3xl: 24px;
|
--text-3xl: 24px;
|
||||||
--text-3xl--line-height: 1.3;
|
--text-3xl--line-height: 1.25;
|
||||||
--text-4xl: 30px;
|
--text-4xl: 30px;
|
||||||
--text-4xl--line-height: 1.3;
|
--text-4xl--line-height: 1.25;
|
||||||
--text-size-inherit: inherit;
|
--text-size-inherit: inherit;
|
||||||
|
|
||||||
--text-icon-size: 16px;
|
--text-icon-size: 16px;
|
||||||
|
|
Loading…
Reference in New Issue