mirror of
https://github.com/SigNoz/signoz.git
synced 2025-12-24 19:07:47 +00:00
feat: styling updates
This commit is contained in:
parent
bcb2824e07
commit
bbe4dcb6b8
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 (
|
||||
<Badge
|
||||
color={color}
|
||||
text={text}
|
||||
style={{
|
||||
color: 'black',
|
||||
}}
|
||||
/>
|
||||
);
|
||||
return <Badge color={color} text={text} />;
|
||||
};
|
||||
|
||||
function myCompletions(context: CompletionContext): CompletionResult | null {
|
||||
@ -380,33 +370,6 @@ function CodeMirrorWhereClause(): JSX.Element {
|
||||
};
|
||||
}
|
||||
|
||||
const customTheme = EditorView.theme({
|
||||
'&': {
|
||||
fontFamily: '"Space Mono", monospace', // Change to any font
|
||||
fontSize: '13px', // Set font size
|
||||
lineHeight: '1.8', // Set line height
|
||||
margin: '8px 0px',
|
||||
},
|
||||
'.cm-line': {
|
||||
lineHeight: '2.2', // Set line height
|
||||
},
|
||||
'.cm-gutters': {
|
||||
lineHeight: '1.8', // Set line height
|
||||
display: 'none',
|
||||
},
|
||||
'.cm-content': {
|
||||
lineHeight: '2.2', // Set line height
|
||||
borderRadius: '2px',
|
||||
border: '1px solid var(--bg-ink-400) !important',
|
||||
background: 'var(--bg-ink-400) !important',
|
||||
padding: '0px',
|
||||
},
|
||||
'.cm-focused': {
|
||||
border: '1px solid var(--bg-robin-500) !important',
|
||||
background: 'var(--bg-ink-400) !important',
|
||||
},
|
||||
});
|
||||
|
||||
// Add back the generateOptions function and useEffect
|
||||
const generateOptions = (data: any): any[] =>
|
||||
Object.values(data.keys).flatMap((items: any) =>
|
||||
@ -440,15 +403,7 @@ function CodeMirrorWhereClause(): JSX.Element {
|
||||
|
||||
return (
|
||||
<div className="code-mirror-where-clause">
|
||||
<Card
|
||||
size="small"
|
||||
title={<Title level={5}>Where Clause</Title>}
|
||||
extra={
|
||||
<Tooltip title="Write a query to filter your data">
|
||||
<QuestionCircleOutlined />
|
||||
</Tooltip>
|
||||
}
|
||||
>
|
||||
<Card size="small">
|
||||
<CodeMirror
|
||||
value={query}
|
||||
theme={copilot}
|
||||
@ -466,41 +421,57 @@ function CodeMirrorWhereClause(): JSX.Element {
|
||||
}),
|
||||
collapseSpacesOutsideStrings(),
|
||||
javascript({ jsx: false, typescript: false }),
|
||||
customTheme,
|
||||
// customTheme,
|
||||
]}
|
||||
basicSetup={{
|
||||
lineNumbers: false,
|
||||
}}
|
||||
/>
|
||||
|
||||
<Space className="cursor-position" size={4}>
|
||||
<InfoCircleOutlined />
|
||||
<Text style={{ color: 'black' }}>
|
||||
Line: {cursorPos.line}, Position: {cursorPos.ch}
|
||||
</Text>
|
||||
</Space>
|
||||
{query && (
|
||||
<>
|
||||
<Divider style={{ margin: '8px 0' }} />
|
||||
<Space direction="vertical" size={4}>
|
||||
<Text>Query:</Text>
|
||||
<Text code>{query}</Text>
|
||||
</Space>
|
||||
</>
|
||||
)}
|
||||
|
||||
<Divider style={{ margin: '8px 0' }} />
|
||||
{query && (
|
||||
<>
|
||||
<Divider style={{ margin: '8px 0' }} />
|
||||
|
||||
<div className="query-validation">
|
||||
<Text>Status:</Text>
|
||||
<div className={validation.isValid ? 'valid' : 'invalid'}>
|
||||
{validation.isValid ? (
|
||||
<>
|
||||
<CheckCircleFilled /> Valid
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<CloseCircleFilled /> Invalid
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
{validation.message && (
|
||||
<Tooltip title={validation.message}>
|
||||
<InfoCircleOutlined style={{ marginLeft: 8 }} />
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
<div className="query-validation">
|
||||
<div className="query-validation-status">
|
||||
<Text>Status:</Text>
|
||||
<div className={validation.isValid ? 'valid' : 'invalid'}>
|
||||
{validation.isValid ? (
|
||||
<Space>
|
||||
<CheckCircleFilled /> Valid
|
||||
</Space>
|
||||
) : (
|
||||
<Space>
|
||||
<CloseCircleFilled /> Invalid
|
||||
</Space>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="query-validation-errors">
|
||||
{validation.errors.map((error) => (
|
||||
<div key={error.message} className="query-validation-error">
|
||||
<div className="query-validation-error-line">
|
||||
{error.line}:{error.column}
|
||||
</div>
|
||||
|
||||
<div className="query-validation-error-message">{error.message}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</Card>
|
||||
|
||||
{queryContext && (
|
||||
@ -508,107 +479,43 @@ function CodeMirrorWhereClause(): JSX.Element {
|
||||
<div className="context-details">
|
||||
<Space direction="vertical" size={4}>
|
||||
<Space>
|
||||
<Text strong style={{ color: 'black' }}>
|
||||
Token:
|
||||
</Text>
|
||||
<Text code style={{ color: 'black' }}>
|
||||
{queryContext.currentToken || '-'}
|
||||
</Text>
|
||||
<Text strong>Token:</Text>
|
||||
<Text code>{queryContext.currentToken || '-'}</Text>
|
||||
</Space>
|
||||
<Space>
|
||||
<Text strong style={{ color: 'black' }}>
|
||||
Type:
|
||||
</Text>
|
||||
<Text style={{ color: 'black' }}>{queryContext.tokenType || '-'}</Text>
|
||||
<Text strong>Type:</Text>
|
||||
<Text>{queryContext.tokenType || '-'}</Text>
|
||||
</Space>
|
||||
<Space>
|
||||
<Text strong style={{ color: 'black' }}>
|
||||
Context:
|
||||
</Text>
|
||||
<Text strong>Context:</Text>
|
||||
{renderContextBadge()}
|
||||
</Space>
|
||||
|
||||
{/* Display the key-operator-value triplet when available */}
|
||||
{queryContext.keyToken && (
|
||||
<Space>
|
||||
<Text strong style={{ color: 'black' }}>
|
||||
Key:
|
||||
</Text>
|
||||
<Text code style={{ color: 'blue' }}>
|
||||
{queryContext.keyToken}
|
||||
</Text>
|
||||
<Text strong>Key:</Text>
|
||||
<Text code>{queryContext.keyToken}</Text>
|
||||
</Space>
|
||||
)}
|
||||
|
||||
{queryContext.operatorToken && (
|
||||
<Space>
|
||||
<Text strong style={{ color: 'black' }}>
|
||||
Operator:
|
||||
</Text>
|
||||
<Text code style={{ color: 'purple' }}>
|
||||
{queryContext.operatorToken}
|
||||
</Text>
|
||||
<Text strong>Operator:</Text>
|
||||
<Text code>{queryContext.operatorToken}</Text>
|
||||
</Space>
|
||||
)}
|
||||
|
||||
{queryContext.valueToken && (
|
||||
<Space>
|
||||
<Text strong style={{ color: 'black' }}>
|
||||
Value:
|
||||
</Text>
|
||||
<Text code style={{ color: 'green' }}>
|
||||
{queryContext.valueToken}
|
||||
</Text>
|
||||
<Text strong>Value:</Text>
|
||||
<Text code>{queryContext.valueToken}</Text>
|
||||
</Space>
|
||||
)}
|
||||
</Space>
|
||||
</div>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
<Card
|
||||
size="small"
|
||||
title="Query Examples"
|
||||
className="query-examples"
|
||||
style={{
|
||||
backgroundColor: 'var(--bg-vanilla-100)',
|
||||
color: 'black',
|
||||
}}
|
||||
>
|
||||
<div className="query-examples-list">Query Examples</div>
|
||||
<ul>
|
||||
<li>
|
||||
<Text code style={{ color: 'black' }}>
|
||||
status = 'error'
|
||||
</Text>
|
||||
</li>
|
||||
<li>
|
||||
<Text code style={{ color: 'black' }}>
|
||||
service = 'frontend' AND level = 'error'
|
||||
</Text>
|
||||
</li>
|
||||
<li>
|
||||
<Text code style={{ color: 'black' }}>
|
||||
message LIKE '%timeout%'
|
||||
</Text>
|
||||
</li>
|
||||
<li>
|
||||
<Text code style={{ color: 'black' }}>
|
||||
duration {'>'} 1000
|
||||
</Text>
|
||||
</li>
|
||||
<li>
|
||||
<Text code style={{ color: 'black' }}>
|
||||
tags IN ['prod', 'frontend']
|
||||
</Text>
|
||||
</li>
|
||||
<li>
|
||||
<Text code style={{ color: 'black' }}>
|
||||
NOT (status = 'error' OR level = 'error')
|
||||
</Text>
|
||||
</li>
|
||||
</ul>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -37,7 +37,13 @@ function QueryWhereClause(): JSX.Element {
|
||||
setValidation({
|
||||
isValid: false,
|
||||
message: 'Failed to process query',
|
||||
errors: [error instanceof Error ? error.message : 'Unknown error'],
|
||||
errors: [
|
||||
{
|
||||
message: error instanceof Error ? error.message : 'Unknown error',
|
||||
line: 0,
|
||||
column: 0,
|
||||
},
|
||||
],
|
||||
});
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
@ -79,7 +85,7 @@ function QueryWhereClause(): JSX.Element {
|
||||
|
||||
{queryContext && (
|
||||
<div className="query-context">
|
||||
<h3>Current Context</h3>
|
||||
<Text strong>Current Context</Text>
|
||||
<div className="context-details">
|
||||
<p>
|
||||
<strong>Token:</strong> {queryContext.currentToken}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
export interface IValidationResult {
|
||||
isValid: boolean;
|
||||
message: string;
|
||||
errors: string[];
|
||||
errors: IDetailedError[];
|
||||
}
|
||||
|
||||
export interface IToken {
|
||||
|
||||
@ -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],
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user