diff --git a/frontend/src/components/QueryBuilderV2/CodeMirrorWhereClause/CodeMirrorWhereClause.styles.scss b/frontend/src/components/QueryBuilderV2/CodeMirrorWhereClause/CodeMirrorWhereClause.styles.scss
index a9617c75325e..db2f77b9beac 100644
--- a/frontend/src/components/QueryBuilderV2/CodeMirrorWhereClause/CodeMirrorWhereClause.styles.scss
+++ b/frontend/src/components/QueryBuilderV2/CodeMirrorWhereClause/CodeMirrorWhereClause.styles.scss
@@ -18,6 +18,89 @@
border-color: var(--bg-robin-500);
background-color: var(--bg-ink-400);
}
+
+ .cm-content {
+ border-radius: 2px;
+ border: 1px solid var(--Slate-400, #1d212d);
+ background: var(--Ink-300, #16181d);
+ }
+
+ .cm-tooltip-autocomplete {
+ background: var(--bg-ink-300) !important;
+ border-radius: 2px !important;
+ font-size: 12px !important;
+ font-weight: 500 !important;
+ margin-top: -2px !important;
+ min-width: 400px !important;
+ position: relative !important;
+ top: 0px !important;
+ left: 0px !important;
+
+ border-radius: 4px;
+ border: 1px solid var(--bg-slate-200, #1d212d);
+
+ ul {
+ width: 100% !important;
+ max-width: 100% !important;
+
+ &::-webkit-scrollbar {
+ width: 0.3rem;
+ }
+ &::-webkit-scrollbar-corner {
+ background: transparent;
+ }
+ &::-webkit-scrollbar-thumb {
+ background: rgb(136, 136, 136);
+ border-radius: 0.625rem;
+ }
+ &::-webkit-scrollbar-track {
+ background: transparent;
+ }
+
+ li {
+ width: 100% !important;
+ max-width: 100% !important;
+ line-height: 24px !important;
+ padding: 4px 8px !important;
+
+ display: flex !important;
+ align-items: center !important;
+ gap: 8px !important;
+
+ .cm-completionIcon {
+ display: none !important;
+ }
+
+ &[aria-selected='true'] {
+ background-color: rgba(78, 116, 248, 0.7) !important;
+ }
+ }
+ }
+ }
+
+ .cm-gutters {
+ display: none !important;
+ }
+
+ .cm-line {
+ line-height: 1.8 !important;
+ background: var(--bg-ink-300) !important;
+
+ ::-moz-selection {
+ background: var(--bg-ink-100) !important;
+ opacity: 0.5 !important;
+ }
+
+ ::selection {
+ background: var(--bg-ink-100) !important;
+ opacity: 0.5 !important;
+ }
+ }
+
+ .cm-selectionBackground {
+ background: var(--bg-ink-100) !important;
+ opacity: 0.5 !important;
+ }
}
.cursor-position {
@@ -29,11 +112,12 @@
display: inline-flex;
align-items: center;
margin-bottom: 8px;
+ margin-top: 8px;
}
.query-validation {
display: flex;
- align-items: center;
+ flex-direction: column;
gap: 8px;
margin-bottom: 8px;
@@ -56,20 +140,39 @@
background-color: rgba(235, 87, 87, 0.1);
color: #eb5757;
}
+
+ .query-validation-status {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ }
+
+ .query-validation-errors {
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+
+ .query-validation-error {
+ display: flex;
+ flex-direction: row;
+ gap: 16px;
+
+ font-size: 12px;
+ font-family: 'Space Mono', monospace !important;
+ color: var(--bg-cherry-500);
+ }
+ }
}
.query-context {
padding: 12px;
- background-color: var(--bg-vanilla-200);
+ background-color: var(--bg-ink-400);
border-radius: 4px;
border-left: 3px solid var(--bg-robin-500);
+ color: var(--bg-ink-300) !important;
- h3 {
- margin-top: 0;
- margin-bottom: 8px;
- font-size: 14px;
- font-weight: 600;
- color: var(--bg-ink-300);
+ .ant-card-head {
+ color: var(--bg-vanilla-300) !important;
}
.context-details {
@@ -82,7 +185,7 @@
font-size: 13px;
strong {
- color: var(--bg-ink-300);
+ color: var(--bg-vanilla-300);
margin-right: 4px;
}
}
diff --git a/frontend/src/components/QueryBuilderV2/CodeMirrorWhereClause/CodeMirrorWhereClause.tsx b/frontend/src/components/QueryBuilderV2/CodeMirrorWhereClause/CodeMirrorWhereClause.tsx
index 0aded7a50cba..99991cb5086d 100644
--- a/frontend/src/components/QueryBuilderV2/CodeMirrorWhereClause/CodeMirrorWhereClause.tsx
+++ b/frontend/src/components/QueryBuilderV2/CodeMirrorWhereClause/CodeMirrorWhereClause.tsx
@@ -5,12 +5,7 @@
import './CodeMirrorWhereClause.styles.scss';
-import {
- CheckCircleFilled,
- CloseCircleFilled,
- InfoCircleOutlined,
- QuestionCircleOutlined,
-} from '@ant-design/icons';
+import { CheckCircleFilled, CloseCircleFilled } from '@ant-design/icons';
import {
autocompletion,
CompletionContext,
@@ -20,12 +15,15 @@ import {
import { javascript } from '@codemirror/lang-javascript';
import { copilot } from '@uiw/codemirror-theme-copilot';
import CodeMirror, { EditorView, Extension } from '@uiw/react-codemirror';
-import { Badge, Card, Divider, Space, Tooltip, Typography } from 'antd';
+import { Badge, Card, Divider, Space, Typography } from 'antd';
import { getValueSuggestions } from 'api/querySuggestions/getValueSuggestion';
import { useGetQueryKeySuggestions } from 'hooks/querySuggestions/useGetQueryKeySuggestions';
-// import { useGetQueryKeyValueSuggestions } from 'hooks/querySuggestions/useGetQueryKeyValueSuggestions';
import { useCallback, useEffect, useRef, useState } from 'react';
-import { IQueryContext, IValidationResult } from 'types/antlrQueryTypes';
+import {
+ IDetailedError,
+ IQueryContext,
+ IValidationResult,
+} from 'types/antlrQueryTypes';
import { QueryKeySuggestionsProps } from 'types/api/querySuggestions/types';
import {
getQueryContextAtCursor,
@@ -33,7 +31,7 @@ import {
validateQuery,
} from 'utils/antlrQueryUtils';
-const { Text, Title } = Typography;
+const { Text } = Typography;
function collapseSpacesOutsideStrings(): Extension {
return EditorView.inputHandler.of((view, from, to, text) => {
@@ -244,7 +242,7 @@ function CodeMirrorWhereClause(): JSX.Element {
setValidation({
isValid: false,
message: 'Failed to process query',
- errors: [error instanceof Error ? error.message : 'Unknown error'],
+ errors: [error as IDetailedError],
});
}
}, []);
@@ -289,15 +287,7 @@ function CodeMirrorWhereClause(): JSX.Element {
// text = 'Parenthesis';
// }
- return (
-
Token: {queryContext.currentToken} diff --git a/frontend/src/types/antlrQueryTypes.ts b/frontend/src/types/antlrQueryTypes.ts index 1ecfc30a9b5b..9a23c4f346ff 100644 --- a/frontend/src/types/antlrQueryTypes.ts +++ b/frontend/src/types/antlrQueryTypes.ts @@ -1,7 +1,7 @@ export interface IValidationResult { isValid: boolean; message: string; - errors: string[]; + errors: IDetailedError[]; } export interface IToken { diff --git a/frontend/src/utils/antlrQueryUtils.ts b/frontend/src/utils/antlrQueryUtils.ts index 722ae30a0e97..0d69766ea00e 100644 --- a/frontend/src/utils/antlrQueryUtils.ts +++ b/frontend/src/utils/antlrQueryUtils.ts @@ -92,14 +92,22 @@ class QueryErrorListener { getFormattedErrors(): string[] { return this.errors.map((error) => { - let message = `Line ${error.line}:${error.column} - ${error.message}`; + const { + offendingSymbol, + expectedTokens, + message: errorMessage, + line, + column, + } = error; - if (error.offendingSymbol && error.offendingSymbol !== 'undefined') { - message += `\nOffending symbol: '${error.offendingSymbol}'`; + let message = `Line ${line}:${column} - ${errorMessage}`; + + if (offendingSymbol && offendingSymbol !== 'undefined') { + message += `\n Symbol: '${offendingSymbol}'`; } - if (error.expectedTokens && error.expectedTokens.length > 0) { - message += `\nExpected: ${error.expectedTokens.join(', ')}`; + if (expectedTokens && expectedTokens.length > 0) { + message += `\n Expected: ${expectedTokens.join(', ')}`; } return message; @@ -113,7 +121,15 @@ export const validateQuery = (query: string): IValidationResult => { return { isValid: false, message: 'Query cannot be empty', - errors: ['Query cannot be empty'], + errors: [ + { + message: 'Query cannot be empty', + line: 0, + column: 0, + offendingSymbol: '', + expectedTokens: [], + }, + ], }; } @@ -133,16 +149,14 @@ export const validateQuery = (query: string): IValidationResult => { parser.addErrorListener(errorListener); // Try parsing - const parsedTree = parser.query(); - - console.log('parsedTree', parsedTree); + parser.query(); // Check if any errors were captured if (errorListener.hasErrors()) { return { isValid: false, message: 'Query syntax error', - errors: errorListener.getFormattedErrors(), + errors: errorListener.getErrors(), }; } @@ -154,10 +168,18 @@ export const validateQuery = (query: string): IValidationResult => { } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Invalid query syntax'; + + const detailedError: IDetailedError = { + message: errorMessage, + line: 0, + column: 0, + offendingSymbol: '', + expectedTokens: [], + }; return { isValid: false, message: 'Invalid query syntax', - errors: [errorMessage], + errors: [detailedError], }; } };