diff --git a/frontend/src/container/Logs/index.tsx b/frontend/src/container/Logs/index.tsx index b2cd1eb3a0..9139d7c9e2 100644 --- a/frontend/src/container/Logs/index.tsx +++ b/frontend/src/container/Logs/index.tsx @@ -6,24 +6,17 @@ import LogsAggregate from 'container/LogsAggregate'; import LogsFilters from 'container/LogsFilters'; import SearchFilter from 'container/LogsSearchFilter'; import LogsTable from 'container/LogsTable'; -import React, { memo, useEffect, useMemo } from 'react'; +import useUrlQuery from 'hooks/useUrlQuery'; +import React, { memo, useEffect } from 'react'; import { connect, useDispatch } from 'react-redux'; -import { useLocation } from 'react-router-dom'; import { bindActionCreators, Dispatch } from 'redux'; import { ThunkDispatch } from 'redux-thunk'; import { GetLogsFields } from 'store/actions/logs/getFields'; import AppActions from 'types/actions'; import { SET_SEARCH_QUERY_STRING } from 'types/actions/logs'; -interface LogsProps { - getLogsFields: VoidFunction; -} function Logs({ getLogsFields }: LogsProps): JSX.Element { - const { search } = useLocation(); - - const urlQuery = useMemo(() => { - return new URLSearchParams(search); - }, [search]); + const urlQuery = useUrlQuery(); const dispatch = useDispatch(); @@ -58,6 +51,8 @@ function Logs({ getLogsFields }: LogsProps): JSX.Element { ); } +type LogsProps = DispatchProps; + interface DispatchProps { getLogsFields: () => (dispatch: Dispatch) => void; } diff --git a/frontend/src/container/LogsSearchFilter/SearchFields/QueryBuilder/QueryBuilder.tsx b/frontend/src/container/LogsSearchFilter/SearchFields/QueryBuilder/QueryBuilder.tsx index 1014fa7945..0723d2378e 100644 --- a/frontend/src/container/LogsSearchFilter/SearchFields/QueryBuilder/QueryBuilder.tsx +++ b/frontend/src/container/LogsSearchFilter/SearchFields/QueryBuilder/QueryBuilder.tsx @@ -22,10 +22,11 @@ import { v4 } from 'uuid'; import FieldKey from '../FieldKey'; import { QueryConditionContainer, QueryFieldContainer } from '../styles'; import { createParsedQueryStructure } from '../utils'; +import { hashCode, parseQuery } from './utils'; const { Option } = Select; interface QueryFieldProps { - query: { value: string | string[]; type: string }[]; + query: Query; queryIndex: number; onUpdate: (query: unknown, queryIndex: number) => void; onDelete: (queryIndex: number) => void; @@ -49,12 +50,12 @@ function QueryField({ } return ''; }; + const fieldType = useMemo(() => getFieldType(query[0].value as string), [ query, ]); const handleChange = (qIdx: number, value: string): void => { query[qIdx].value = value || ''; - if (qIdx === 1) { if (Object.values(QueryOperatorsMultiVal).includes(value)) { if (!Array.isArray(query[2].value)) { @@ -166,17 +167,8 @@ function QueryConditionField({ ); } -const hashCode = (s: string): string => { - if (!s) { - return '0'; - } - return `${Math.abs( - s.split('').reduce((a, b) => { - a = (a << 5) - a + b.charCodeAt(0); - return a & a; - }, 0), - )}`; -}; + +export type Query = { value: string | string[]; type: string }[]; function QueryBuilder({ updateParsedQuery, @@ -201,12 +193,9 @@ function QueryBuilder({ } }, [parsedQuery]); - const handleUpdate = ( - query: { value: string | string[]; type: string }[], - queryIndex: number, - ): void => { + const handleUpdate = (query: Query, queryIndex: number): void => { const updatedParsedQuery = generatedQueryStructure; - updatedParsedQuery[queryIndex] = query as never; + updatedParsedQuery[queryIndex] = parseQuery(query) as never; const flatParsedQuery = flatten(updatedParsedQuery).filter((q) => q.value); keyPrefixRef.current = hashCode(JSON.stringify(flatParsedQuery)); diff --git a/frontend/src/container/LogsSearchFilter/SearchFields/QueryBuilder/utils.ts b/frontend/src/container/LogsSearchFilter/SearchFields/QueryBuilder/utils.ts new file mode 100644 index 0000000000..2641d8af35 --- /dev/null +++ b/frontend/src/container/LogsSearchFilter/SearchFields/QueryBuilder/utils.ts @@ -0,0 +1,37 @@ +import _set from 'lodash-es/set'; + +import { Query } from './QueryBuilder'; + +export const parseQuery = (queries: Query): Query => { + if (Array.isArray(queries)) { + const isContainsPresent = queries.find((e) => e.value === 'CONTAINS'); + if (isContainsPresent) { + // find the index of VALUE to update + const valueIndex = queries.findIndex((e) => e.type === 'QUERY_VALUE'); + if (valueIndex > -1) { + // update the value to wrap with "" + _set( + queries, + [valueIndex, 'value'], + `'${queries[valueIndex].value || ''}'`, + ); + } + return queries; + } + } + return queries; +}; + +export const hashCode = (s: string): string => { + if (!s) { + return '0'; + } + return `${Math.abs( + s.split('').reduce((a, b) => { + // eslint-disable-next-line no-bitwise, no-param-reassign + a = (a << 5) - a + b.charCodeAt(0); + // eslint-disable-next-line no-bitwise + return a & a; + }, 0), + )}`; +}; diff --git a/frontend/src/container/LogsSearchFilter/SearchFields/utils.ts b/frontend/src/container/LogsSearchFilter/SearchFields/utils.ts index 059392f36d..ae091dc061 100644 --- a/frontend/src/container/LogsSearchFilter/SearchFields/utils.ts +++ b/frontend/src/container/LogsSearchFilter/SearchFields/utils.ts @@ -2,9 +2,14 @@ // @ts-ignore // @ts-nocheck -import { QueryTypes } from 'lib/logql/tokens'; +import { QueryTypes, QueryOperatorsSingleVal } from 'lib/logql/tokens'; -export const queryKOVPair = () => [ +export interface QueryFields { + type: keyof typeof QueryTypes; + value: string; +} + +export const queryKOVPair = (): QueryFields[] => [ { type: QueryTypes.QUERY_KEY, value: null, diff --git a/frontend/src/container/LogsTable/index.tsx b/frontend/src/container/LogsTable/index.tsx index 974e77f7fe..7997fac91f 100644 --- a/frontend/src/container/LogsTable/index.tsx +++ b/frontend/src/container/LogsTable/index.tsx @@ -15,9 +15,6 @@ import { ILogsReducer } from 'types/reducer/logs'; import { Container, Heading } from './styles'; -interface LogsTableProps { - getLogs: (props: Parameters[0]) => ReturnType; -} function LogsTable({ getLogs }: LogsTableProps): JSX.Element { const { searchFilter: { queryString }, @@ -51,6 +48,7 @@ function LogsTable({ getLogs }: LogsTableProps): JSX.Element { if (isLoading) { return ; } + return ( @@ -86,4 +84,8 @@ const mapDispatchToProps = ( getLogs: bindActionCreators(getLogs, dispatch), }); +interface LogsTableProps { + getLogs: (props: Parameters[0]) => ReturnType; +} + export default connect(null, mapDispatchToProps)(memo(LogsTable));