PromQueryBuilderContainer.tsx 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. import { createSlice, PayloadAction } from '@reduxjs/toolkit';
  2. import React, { useEffect, useReducer } from 'react';
  3. import { PanelData } from '@grafana/data';
  4. import { PrometheusDatasource } from '../../datasource';
  5. import { PromQuery } from '../../types';
  6. import { promQueryModeller } from '../PromQueryModeller';
  7. import { buildVisualQueryFromString } from '../parsing';
  8. import { PromVisualQuery } from '../types';
  9. import { PromQueryBuilder } from './PromQueryBuilder';
  10. import { QueryPreview } from './QueryPreview';
  11. export interface Props {
  12. query: PromQuery;
  13. datasource: PrometheusDatasource;
  14. onChange: (update: PromQuery) => void;
  15. onRunQuery: () => void;
  16. data?: PanelData;
  17. showRawQuery?: boolean;
  18. }
  19. export interface State {
  20. visQuery?: PromVisualQuery;
  21. expr: string;
  22. }
  23. /**
  24. * This component is here just to contain the translation logic between string query and the visual query builder model.
  25. */
  26. export function PromQueryBuilderContainer(props: Props) {
  27. const { query, onChange, onRunQuery, datasource, data, showRawQuery } = props;
  28. const [state, dispatch] = useReducer(stateSlice.reducer, { expr: query.expr });
  29. // Only rebuild visual query if expr changes from outside
  30. useEffect(() => {
  31. dispatch(exprChanged(query.expr));
  32. }, [query.expr]);
  33. const onVisQueryChange = (visQuery: PromVisualQuery) => {
  34. const expr = promQueryModeller.renderQuery(visQuery);
  35. dispatch(visualQueryChange({ visQuery, expr }));
  36. onChange({ ...props.query, expr: expr });
  37. };
  38. if (!state.visQuery) {
  39. return null;
  40. }
  41. return (
  42. <>
  43. <PromQueryBuilder
  44. query={state.visQuery}
  45. datasource={datasource}
  46. onChange={onVisQueryChange}
  47. onRunQuery={onRunQuery}
  48. data={data}
  49. />
  50. {showRawQuery && <QueryPreview query={query.expr} />}
  51. </>
  52. );
  53. }
  54. const stateSlice = createSlice({
  55. name: 'prom-builder-container',
  56. initialState: { expr: '' } as State,
  57. reducers: {
  58. visualQueryChange: (state, action: PayloadAction<{ visQuery: PromVisualQuery; expr: string }>) => {
  59. state.expr = action.payload.expr;
  60. state.visQuery = action.payload.visQuery;
  61. },
  62. exprChanged: (state, action: PayloadAction<string>) => {
  63. if (!state.visQuery || state.expr !== action.payload) {
  64. state.expr = action.payload;
  65. const parseResult = buildVisualQueryFromString(action.payload);
  66. state.visQuery = parseResult.query;
  67. }
  68. },
  69. },
  70. });
  71. const { visualQueryChange, exprChanged } = stateSlice.actions;