import { alphabet, formulasNames, initialFormulaBuilderFormValues, initialQueryBuilderFormValues, MAX_FORMULAS, MAX_QUERIES, PANEL_TYPES, } from 'constants/queryBuilder'; import { GRAPH_TYPES } from 'container/NewDashboard/ComponentsSlider'; import { createNewBuilderItemName } from 'lib/newQueryBuilder/createNewBuilderItemName'; import { getOperatorsBySourceAndPanelType } from 'lib/newQueryBuilder/getOperatorsBySourceAndPanelType'; import { createContext, PropsWithChildren, useCallback, useMemo, useState, } from 'react'; // ** Types import { IBuilderFormula, IBuilderQuery, } from 'types/api/queryBuilder/queryBuilderData'; import { DataSource, QueryBuilderContextType, QueryBuilderData, } from 'types/common/queryBuilder'; export const QueryBuilderContext = createContext({ queryBuilderData: { queryData: [], queryFormulas: [] }, initialDataSource: null, panelType: PANEL_TYPES.TIME_SERIES, resetQueryBuilderData: () => {}, resetQueryBuilderInfo: () => {}, handleSetQueryData: () => {}, handleSetFormulaData: () => {}, handleSetPanelType: () => {}, initQueryBuilderData: () => {}, setupInitialDataSource: () => {}, removeEntityByIndex: () => {}, addNewQuery: () => {}, addNewFormula: () => {}, }); const initialQueryBuilderData: QueryBuilderData = { queryData: [], queryFormulas: [], }; export function QueryBuilderProvider({ children, }: PropsWithChildren): JSX.Element { const [initialDataSource, setInitialDataSource] = useState( null, ); const [panelType, setPanelType] = useState( PANEL_TYPES.TIME_SERIES, ); const [queryBuilderData, setQueryBuilderData] = useState({ queryData: [], queryFormulas: [], }); const resetQueryBuilderInfo = useCallback((): void => { setInitialDataSource(null); setPanelType(PANEL_TYPES.TIME_SERIES); }, []); const resetQueryBuilderData = useCallback(() => { setQueryBuilderData(initialQueryBuilderData); }, []); const initQueryBuilderData = useCallback( (queryBuilderData: QueryBuilderData): void => { setQueryBuilderData(queryBuilderData); }, [], ); const removeEntityByIndex = useCallback( (type: keyof QueryBuilderData, index: number) => { setQueryBuilderData((prevState) => { const currentArray: (IBuilderQuery | IBuilderFormula)[] = prevState[type]; return { ...prevState, [type]: currentArray.filter((item, i) => index !== i), }; }); }, [], ); const createNewQuery = useCallback( (queries: IBuilderQuery[]): IBuilderQuery => { const existNames = queries.map((item) => item.queryName); const newQuery: IBuilderQuery = { ...initialQueryBuilderFormValues, queryName: createNewBuilderItemName({ existNames, sourceNames: alphabet }), expression: createNewBuilderItemName({ existNames, sourceNames: alphabet, }), ...(initialDataSource ? { dataSource: initialDataSource, aggregateOperator: getOperatorsBySourceAndPanelType({ dataSource: initialDataSource, panelType, })[0].value, } : {}), }; return newQuery; }, [initialDataSource, panelType], ); const createNewFormula = useCallback((formulas: IBuilderFormula[]) => { const existNames = formulas.map((item) => item.queryName); const newFormula: IBuilderFormula = { ...initialFormulaBuilderFormValues, queryName: createNewBuilderItemName({ existNames, sourceNames: formulasNames, }), }; return newFormula; }, []); const addNewQuery = useCallback(() => { setQueryBuilderData((prevState) => { if (prevState.queryData.length >= MAX_QUERIES) return prevState; const newQuery = createNewQuery(prevState.queryData); return { ...prevState, queryData: [...prevState.queryData, newQuery] }; }); }, [createNewQuery]); const addNewFormula = useCallback(() => { setQueryBuilderData((prevState) => { if (prevState.queryFormulas.length >= MAX_FORMULAS) return prevState; const newFormula = createNewFormula(prevState.queryFormulas); return { ...prevState, queryFormulas: [...prevState.queryFormulas, newFormula], }; }); }, [createNewFormula]); const setupInitialDataSource = useCallback( (newInitialDataSource: DataSource | null) => setInitialDataSource(newInitialDataSource), [], ); const updateQueryBuilderData = useCallback( (queries: IBuilderQuery[], index: number, newQueryData: IBuilderQuery) => queries.map((item, idx) => (index === idx ? newQueryData : item)), [], ); const updateFormulaBuilderData = useCallback( (formulas: IBuilderFormula[], index: number, newFormula: IBuilderFormula) => formulas.map((item, idx) => (index === idx ? newFormula : item)), [], ); const handleSetQueryData = useCallback( (index: number, newQueryData: IBuilderQuery): void => { setQueryBuilderData((prevState) => { const updatedQueryBuilderData = updateQueryBuilderData( prevState.queryData, index, newQueryData, ); return { ...prevState, queryData: updatedQueryBuilderData, }; }); }, [updateQueryBuilderData], ); const handleSetFormulaData = useCallback( (index: number, formulaData: IBuilderFormula): void => { setQueryBuilderData((prevState) => { const updatedFormulasBuilderData = updateFormulaBuilderData( prevState.queryFormulas, index, formulaData, ); return { ...prevState, queryFormulas: updatedFormulasBuilderData, }; }); }, [updateFormulaBuilderData], ); const handleSetPanelType = useCallback((newPanelType: GRAPH_TYPES) => { setPanelType(newPanelType); }, []); const contextValues: QueryBuilderContextType = useMemo( () => ({ queryBuilderData, initialDataSource, panelType, resetQueryBuilderData, resetQueryBuilderInfo, handleSetQueryData, handleSetFormulaData, handleSetPanelType, initQueryBuilderData, setupInitialDataSource, removeEntityByIndex, addNewQuery, addNewFormula, }), [ queryBuilderData, initialDataSource, panelType, resetQueryBuilderData, resetQueryBuilderInfo, handleSetQueryData, handleSetFormulaData, handleSetPanelType, initQueryBuilderData, setupInitialDataSource, removeEntityByIndex, addNewQuery, addNewFormula, ], ); return ( {children} ); }