mirror of
https://github.com/SigNoz/signoz.git
synced 2025-12-24 02:46:27 +00:00
fix: update styles
This commit is contained in:
parent
e319394ac4
commit
de3497d439
@ -145,6 +145,17 @@
|
|||||||
background: var(--bg-ink-100) !important;
|
background: var(--bg-ink-100) !important;
|
||||||
opacity: 0.5 !important;
|
opacity: 0.5 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cm-function {
|
||||||
|
color: var(--bg-robin-500) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chip-decorator {
|
||||||
|
background: rgba(36, 40, 52, 1) !important;
|
||||||
|
color: var(--bg-vanilla-100) !important;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 2px 8px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.cm-selectionBackground {
|
.cm-selectionBackground {
|
||||||
|
|||||||
@ -1,3 +1,8 @@
|
|||||||
|
/* eslint-disable import/no-extraneous-dependencies */
|
||||||
|
/* eslint-disable no-cond-assign */
|
||||||
|
/* eslint-disable no-restricted-syntax */
|
||||||
|
/* eslint-disable class-methods-use-this */
|
||||||
|
/* eslint-disable react/no-this-in-sfc */
|
||||||
/* eslint-disable sonarjs/cognitive-complexity */
|
/* eslint-disable sonarjs/cognitive-complexity */
|
||||||
import './QueryAggregation.styles.scss';
|
import './QueryAggregation.styles.scss';
|
||||||
|
|
||||||
@ -8,8 +13,14 @@ import {
|
|||||||
CompletionResult,
|
CompletionResult,
|
||||||
} from '@codemirror/autocomplete';
|
} from '@codemirror/autocomplete';
|
||||||
import { javascript } from '@codemirror/lang-javascript';
|
import { javascript } from '@codemirror/lang-javascript';
|
||||||
|
import { RangeSetBuilder } from '@codemirror/state';
|
||||||
import { copilot } from '@uiw/codemirror-theme-copilot';
|
import { copilot } from '@uiw/codemirror-theme-copilot';
|
||||||
import CodeMirror, { EditorView } from '@uiw/react-codemirror';
|
import CodeMirror, {
|
||||||
|
Decoration,
|
||||||
|
EditorView,
|
||||||
|
ViewPlugin,
|
||||||
|
ViewUpdate,
|
||||||
|
} from '@uiw/react-codemirror';
|
||||||
import { getAggregateAttribute } from 'api/queryBuilder/getAggregateAttribute';
|
import { getAggregateAttribute } from 'api/queryBuilder/getAggregateAttribute';
|
||||||
import { QueryBuilderKeys } from 'constants/queryBuilder';
|
import { QueryBuilderKeys } from 'constants/queryBuilder';
|
||||||
import { tracesAggregateOperatorOptions } from 'constants/queryBuilderOperators';
|
import { tracesAggregateOperatorOptions } from 'constants/queryBuilderOperators';
|
||||||
@ -19,6 +30,10 @@ import { useQuery } from 'react-query';
|
|||||||
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||||
import { TracesAggregatorOperator } from 'types/common/queryBuilder';
|
import { TracesAggregatorOperator } from 'types/common/queryBuilder';
|
||||||
|
|
||||||
|
const chipDecoration = Decoration.mark({
|
||||||
|
class: 'chip-decorator',
|
||||||
|
});
|
||||||
|
|
||||||
const operatorArgMeta: Record<
|
const operatorArgMeta: Record<
|
||||||
string,
|
string,
|
||||||
{ acceptsArgs: boolean; multiple: boolean }
|
{ acceptsArgs: boolean; multiple: boolean }
|
||||||
@ -91,6 +106,7 @@ function getFunctionContextAtCursor(
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line react/no-this-in-sfc
|
||||||
function QueryAggregationSelect(): JSX.Element {
|
function QueryAggregationSelect(): JSX.Element {
|
||||||
const { currentQuery } = useQueryBuilder();
|
const { currentQuery } = useQueryBuilder();
|
||||||
const queryData = currentQuery.builder.queryData[0];
|
const queryData = currentQuery.builder.queryData[0];
|
||||||
@ -126,16 +142,76 @@ function QueryAggregationSelect(): JSX.Element {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Get valid function names (lowercase)
|
||||||
|
const validFunctions = useMemo(
|
||||||
|
() => tracesAggregateOperatorOptions.map((op) => op.value.toLowerCase()),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
// Memoized chipPlugin that highlights valid function calls like count(), max(arg), min(arg)
|
||||||
|
const chipPlugin = useMemo(
|
||||||
|
() =>
|
||||||
|
ViewPlugin.fromClass(
|
||||||
|
class {
|
||||||
|
decorations: import('@codemirror/view').DecorationSet;
|
||||||
|
|
||||||
|
constructor(view: EditorView) {
|
||||||
|
this.decorations = this.buildDecorations(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
update(update: ViewUpdate): void {
|
||||||
|
if (update.docChanged || update.viewportChanged) {
|
||||||
|
this.decorations = this.buildDecorations(update.view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buildDecorations(
|
||||||
|
view: EditorView,
|
||||||
|
): import('@codemirror/view').DecorationSet {
|
||||||
|
const builder = new RangeSetBuilder<Decoration>();
|
||||||
|
for (const { from, to } of view.visibleRanges) {
|
||||||
|
const text = view.state.doc.sliceString(from, to);
|
||||||
|
|
||||||
|
const regex = /\b([a-zA-Z_][\w]*)\s*\(([^)]*)\)/g;
|
||||||
|
let match;
|
||||||
|
|
||||||
|
while ((match = regex.exec(text)) !== null) {
|
||||||
|
const func = match[1].toLowerCase();
|
||||||
|
|
||||||
|
if (validFunctions.includes(func)) {
|
||||||
|
const start = from + match.index;
|
||||||
|
const end = start + match[0].length;
|
||||||
|
|
||||||
|
builder.add(start, end, chipDecoration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return builder.finish();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
decorations: (v: any): import('@codemirror/view').DecorationSet =>
|
||||||
|
v.decorations,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
[validFunctions],
|
||||||
|
) as any;
|
||||||
|
|
||||||
const operatorCompletions: Completion[] = tracesAggregateOperatorOptions.map(
|
const operatorCompletions: Completion[] = tracesAggregateOperatorOptions.map(
|
||||||
(op) => ({
|
(op) => ({
|
||||||
label: op.value,
|
label: op.value,
|
||||||
type: 'function',
|
type: 'function',
|
||||||
info: op.label,
|
info: op.label,
|
||||||
apply: (view: EditorView): void => {
|
apply: (
|
||||||
|
view: EditorView,
|
||||||
|
completion: Completion,
|
||||||
|
from: number,
|
||||||
|
to: number,
|
||||||
|
): void => {
|
||||||
const insertText = `${op.value}()`;
|
const insertText = `${op.value}()`;
|
||||||
const cursorPos = view.state.selection.main.from + op.value.length + 1; // after '('
|
const cursorPos = from + op.value.length + 1; // after '('
|
||||||
view.dispatch({
|
view.dispatch({
|
||||||
changes: { from: view.state.selection.main.from, insert: insertText },
|
changes: { from, to, insert: insertText },
|
||||||
selection: { anchor: cursorPos },
|
selection: { anchor: cursorPos },
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -150,13 +226,15 @@ function QueryAggregationSelect(): JSX.Element {
|
|||||||
label: attributeKey.key,
|
label: attributeKey.key,
|
||||||
type: 'variable',
|
type: 'variable',
|
||||||
info: attributeKey.dataType,
|
info: attributeKey.dataType,
|
||||||
apply: (view: EditorView, completion: Completion): void => {
|
apply: (
|
||||||
const currentText = view.state.sliceDoc(
|
view: EditorView,
|
||||||
0,
|
completion: Completion,
|
||||||
view.state.selection.main.from,
|
from: number,
|
||||||
);
|
to: number,
|
||||||
|
): void => {
|
||||||
|
const currentText = view.state.sliceDoc(0, from);
|
||||||
const lastOpenParen = currentText.lastIndexOf('(');
|
const lastOpenParen = currentText.lastIndexOf('(');
|
||||||
const endPos = view.state.selection.main.from;
|
const endPos = from;
|
||||||
// Find the last comma before the cursor, but after the last open paren
|
// Find the last comma before the cursor, but after the last open paren
|
||||||
const lastComma = currentText.lastIndexOf(',', endPos - 1);
|
const lastComma = currentText.lastIndexOf(',', endPos - 1);
|
||||||
const startPos =
|
const startPos =
|
||||||
@ -170,7 +248,7 @@ function QueryAggregationSelect(): JSX.Element {
|
|||||||
insertText = completion.label;
|
insertText = completion.label;
|
||||||
}
|
}
|
||||||
view.dispatch({
|
view.dispatch({
|
||||||
changes: { from: endPos, insert: insertText },
|
changes: { from: endPos, to, insert: insertText },
|
||||||
selection: { anchor: endPos + insertText.length },
|
selection: { anchor: endPos + insertText.length },
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -188,6 +266,15 @@ function QueryAggregationSelect(): JSX.Element {
|
|||||||
const cursorPos = context.pos;
|
const cursorPos = context.pos;
|
||||||
const funcName = getFunctionContextAtCursor(text, cursorPos);
|
const funcName = getFunctionContextAtCursor(text, cursorPos);
|
||||||
|
|
||||||
|
// Do not show suggestions if inside count()
|
||||||
|
if (
|
||||||
|
funcName === TracesAggregatorOperator.COUNT &&
|
||||||
|
cursorPos > 0 &&
|
||||||
|
text[cursorPos - 1] !== ')'
|
||||||
|
) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// If inside a function that accepts args, show field suggestions
|
// If inside a function that accepts args, show field suggestions
|
||||||
if (funcName && operatorArgMeta[funcName]?.acceptsArgs) {
|
if (funcName && operatorArgMeta[funcName]?.acceptsArgs) {
|
||||||
if (isLoadingFields) {
|
if (isLoadingFields) {
|
||||||
@ -233,6 +320,7 @@ function QueryAggregationSelect(): JSX.Element {
|
|||||||
width="100%"
|
width="100%"
|
||||||
theme={copilot}
|
theme={copilot}
|
||||||
extensions={[
|
extensions={[
|
||||||
|
chipPlugin,
|
||||||
aggregatorAutocomplete,
|
aggregatorAutocomplete,
|
||||||
javascript({ jsx: false, typescript: false }),
|
javascript({ jsx: false, typescript: false }),
|
||||||
]}
|
]}
|
||||||
|
|||||||
@ -21,7 +21,6 @@ import CodeMirror, { EditorView, Extension } from '@uiw/react-codemirror';
|
|||||||
import { Card, Collapse, Space, Tag, Typography } from 'antd';
|
import { Card, Collapse, Space, Tag, Typography } from 'antd';
|
||||||
import { getValueSuggestions } from 'api/querySuggestions/getValueSuggestion';
|
import { getValueSuggestions } from 'api/querySuggestions/getValueSuggestion';
|
||||||
import { useGetQueryKeySuggestions } from 'hooks/querySuggestions/useGetQueryKeySuggestions';
|
import { useGetQueryKeySuggestions } from 'hooks/querySuggestions/useGetQueryKeySuggestions';
|
||||||
import cloneDeep from 'lodash-es/cloneDeep';
|
|
||||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import {
|
import {
|
||||||
IDetailedError,
|
IDetailedError,
|
||||||
@ -30,7 +29,6 @@ import {
|
|||||||
} from 'types/antlrQueryTypes';
|
} from 'types/antlrQueryTypes';
|
||||||
import { QueryKeySuggestionsProps } from 'types/api/querySuggestions/types';
|
import { QueryKeySuggestionsProps } from 'types/api/querySuggestions/types';
|
||||||
import { queryOperatorSuggestions, validateQuery } from 'utils/antlrQueryUtils';
|
import { queryOperatorSuggestions, validateQuery } from 'utils/antlrQueryUtils';
|
||||||
import { detectContext } from 'utils/antlrQueryUtils2';
|
|
||||||
import { getQueryContextAtCursor } from 'utils/queryContextUtils';
|
import { getQueryContextAtCursor } from 'utils/queryContextUtils';
|
||||||
|
|
||||||
const { Text } = Typography;
|
const { Text } = Typography;
|
||||||
@ -649,12 +647,6 @@ function QuerySearch(): JSX.Element {
|
|||||||
// Get the query context at the cursor position
|
// Get the query context at the cursor position
|
||||||
const queryContext = getQueryContextAtCursor(query, cursorPos.ch);
|
const queryContext = getQueryContextAtCursor(query, cursorPos.ch);
|
||||||
|
|
||||||
// Get the query context at the cursor position
|
|
||||||
const queryContext2 = detectContext(query, cursorPos.ch);
|
|
||||||
|
|
||||||
console.log('queryContext', queryContext);
|
|
||||||
console.log('queryContext2', cloneDeep(queryContext2));
|
|
||||||
|
|
||||||
// Define autocomplete options based on the context
|
// Define autocomplete options based on the context
|
||||||
let options: {
|
let options: {
|
||||||
label: string;
|
label: string;
|
||||||
@ -1043,7 +1035,7 @@ function QuerySearch(): JSX.Element {
|
|||||||
override: [myCompletions],
|
override: [myCompletions],
|
||||||
defaultKeymap: true,
|
defaultKeymap: true,
|
||||||
closeOnBlur: false,
|
closeOnBlur: false,
|
||||||
// activateOnTyping: true,
|
activateOnTyping: true,
|
||||||
maxRenderedOptions: 50,
|
maxRenderedOptions: 50,
|
||||||
}),
|
}),
|
||||||
javascript({ jsx: false, typescript: false }),
|
javascript({ jsx: false, typescript: false }),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user