import { createSlice, PayloadAction } from '@reduxjs/toolkit'; import React, { useEffect, useReducer } from 'react'; import { LokiDatasource } from '../../datasource'; import { LokiQuery } from '../../types'; import { lokiQueryModeller } from '../LokiQueryModeller'; import { buildVisualQueryFromString } from '../parsing'; import { LokiVisualQuery } from '../types'; import { LokiQueryBuilder } from './LokiQueryBuilder'; import { QueryPreview } from './QueryPreview'; export interface Props { query: LokiQuery; datasource: LokiDatasource; onChange: (update: LokiQuery) => void; onRunQuery: () => void; showRawQuery: boolean; } export interface State { visQuery?: LokiVisualQuery; expr: string; } /** * This component is here just to contain the translation logic between string query and the visual query builder model. */ export function LokiQueryBuilderContainer(props: Props) { const { query, onChange, onRunQuery, datasource, showRawQuery } = props; const [state, dispatch] = useReducer(stateSlice.reducer, { expr: query.expr, // Use initial visual query only if query.expr is empty string visQuery: query.expr === '' ? { labels: [], operations: [{ id: '__line_contains', params: [''] }], } : undefined, }); // Only rebuild visual query if expr changes from outside useEffect(() => { dispatch(exprChanged(query.expr)); }, [query.expr]); const onVisQueryChange = (visQuery: LokiVisualQuery) => { const expr = lokiQueryModeller.renderQuery(visQuery); dispatch(visualQueryChange({ visQuery, expr })); onChange({ ...props.query, expr: expr }); }; if (!state.visQuery) { return null; } return ( <> {showRawQuery && } ); } const stateSlice = createSlice({ name: 'loki-builder-container', initialState: { expr: '' } as State, reducers: { visualQueryChange: (state, action: PayloadAction<{ visQuery: LokiVisualQuery; expr: string }>) => { state.expr = action.payload.expr; state.visQuery = action.payload.visQuery; }, exprChanged: (state, action: PayloadAction) => { if (!state.visQuery || state.expr !== action.payload) { state.expr = action.payload; const parseResult = buildVisualQueryFromString(action.payload); state.visQuery = parseResult.query; } }, }, }); const { visualQueryChange, exprChanged } = stateSlice.actions;