Revert "feat: lowercase operators support in the where clause is updated (#3657)" (#3697)

This reverts commit 0e04b779a94740e741fc0e49800c3633b76e8030.
This commit is contained in:
Nityananda Gohain 2023-10-11 17:35:53 +05:30 committed by GitHub
parent 0d3cbb1db2
commit f3c00e1a57
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 99 additions and 81 deletions

View File

@ -278,35 +278,23 @@ export const QUERY_BUILDER_SEARCH_VALUES = {
export const OPERATORS = { export const OPERATORS = {
IN: 'IN', IN: 'IN',
in: 'in',
NIN: 'NOT_IN', NIN: 'NOT_IN',
not_in: 'not_in',
LIKE: 'LIKE', LIKE: 'LIKE',
like: 'like',
NLIKE: 'NOT_LIKE', NLIKE: 'NOT_LIKE',
not_like: 'not_like',
REGEX: 'REGEX', REGEX: 'REGEX',
regex: 'regex',
NREGEX: 'NOT_REGEX', NREGEX: 'NOT_REGEX',
nregex: 'not_regex',
'=': '=', '=': '=',
'!=': '!=', '!=': '!=',
EXISTS: 'EXISTS', EXISTS: 'EXISTS',
exists: 'exists',
NOT_EXISTS: 'NOT_EXISTS', NOT_EXISTS: 'NOT_EXISTS',
not_exists: 'not_exists',
CONTAINS: 'CONTAINS', CONTAINS: 'CONTAINS',
contains: 'contains',
NOT_CONTAINS: 'NOT_CONTAINS', NOT_CONTAINS: 'NOT_CONTAINS',
not_contains: 'not_contains',
'>=': '>=', '>=': '>=',
'>': '>', '>': '>',
'<=': '<=', '<=': '<=',
'<': '<', '<': '<',
HAS: 'HAS', HAS: 'HAS',
has: 'has',
NHAS: 'NHAS', NHAS: 'NHAS',
nhas: 'nhas',
}; };
export const QUERY_BUILDER_OPERATORS_BY_TYPES = { export const QUERY_BUILDER_OPERATORS_BY_TYPES = {

View File

@ -3,42 +3,25 @@ import { parse } from 'papaparse';
import { orderByValueDelimiter } from '../OrderByFilter/utils'; import { orderByValueDelimiter } from '../OrderByFilter/utils';
const operators = /=|!=|>=|>|<=|<$/;
// eslint-disable-next-line no-useless-escape // eslint-disable-next-line no-useless-escape
export const tagRegexpV1 = /^\s*(.*?)\s*(IN|in|NOT_IN|nin|LIKE|like|NOT_LIKE|nlike|REGEX|regex|NOT_REGEX|nregex|=|!=|EXISTS|exists|NOT_EXISTS|nexists|CONTAINS|contains|NOT_CONTAINS|ncontains|>=|>|<=|<|HAS|has|NHAS|nhas)\s*(.*)$/g; export const tagRegexp = /^\s*(.*?)\s*(IN|NOT_IN|LIKE|NOT_LIKE|REGEX|NOT_REGEX|=|!=|EXISTS|NOT_EXISTS|CONTAINS|NOT_CONTAINS|>=|>|<=|<|HAS|NHAS)\s*(.*)$/g;
export const tagRegexpV2 = /^\s*(.+?)\s+(IN|in|NOT_IN|nin|LIKE|like|NOT_LIKE|nlike|REGEX|regex|NOT_REGEX|nregex|EXISTS|exists|NOT_EXISTS|nexists|CONTAINS|contains|NOT_CONTAINS|ncontains|HAS|has|NHAS|nhas|=|!=|>=|>|<=|<)\s*(.*)$/g;
export function isInNInOperator(value: string): boolean { export function isInNInOperator(value: string): boolean {
return value === OPERATORS.IN || value === OPERATORS.NIN; return value === OPERATORS.IN || value === OPERATORS.NIN;
} }
function endsWithOperator(inputString: string): boolean {
return operators.test(inputString);
}
interface ITagToken { interface ITagToken {
tagKey: string; tagKey: string;
tagOperator: string; tagOperator: string;
tagValue: string[]; tagValue: string[];
} }
export function getMatchRegex(str: string): RegExp {
if (endsWithOperator(str)) {
return tagRegexpV1;
}
return tagRegexpV2;
}
export function getTagToken(tag: string): ITagToken { export function getTagToken(tag: string): ITagToken {
const matches = tag?.matchAll(getMatchRegex(tag)); const matches = tag?.matchAll(tagRegexp);
const [match] = matches ? Array.from(matches) : []; const [match] = matches ? Array.from(matches) : [];
if (match) { if (match) {
const [, matchTagKey, matchTagOperator, matchTagValue] = match; const [, matchTagKey, matchTagOperator, matchTagValue] = match;
return { return {
tagKey: matchTagKey, tagKey: matchTagKey,
tagOperator: matchTagOperator, tagOperator: matchTagOperator,
@ -68,11 +51,65 @@ export function getRemovePrefixFromKey(tag: string): string {
} }
export function getOperatorValue(op: string): string { export function getOperatorValue(op: string): string {
return op.toLocaleLowerCase(); switch (op) {
case 'IN':
return 'in';
case 'NOT_IN':
return 'nin';
case OPERATORS.REGEX:
return 'regex';
case OPERATORS.HAS:
return 'has';
case OPERATORS.NHAS:
return 'nhas';
case OPERATORS.NREGEX:
return 'nregex';
case 'LIKE':
return 'like';
case 'NOT_LIKE':
return 'nlike';
case 'EXISTS':
return 'exists';
case 'NOT_EXISTS':
return 'nexists';
case 'CONTAINS':
return 'contains';
case 'NOT_CONTAINS':
return 'ncontains';
default:
return op;
}
} }
export function getOperatorFromValue(op: string): string { export function getOperatorFromValue(op: string): string {
return op.toLocaleLowerCase(); switch (op) {
case 'in':
return 'IN';
case 'nin':
return 'NOT_IN';
case 'like':
return 'LIKE';
case 'regex':
return OPERATORS.REGEX;
case 'nregex':
return OPERATORS.NREGEX;
case 'nlike':
return 'NOT_LIKE';
case 'exists':
return 'EXISTS';
case 'nexists':
return 'NOT_EXISTS';
case 'contains':
return 'CONTAINS';
case 'ncontains':
return 'NOT_CONTAINS';
case 'has':
return OPERATORS.HAS;
case 'nhas':
return OPERATORS.NHAS;
default:
return op;
}
} }
export function replaceStringWithMaxLength( export function replaceStringWithMaxLength(

View File

@ -1,8 +1,8 @@
import { import {
getMatchRegex,
getRemovePrefixFromKey, getRemovePrefixFromKey,
getTagToken, getTagToken,
replaceStringWithMaxLength, replaceStringWithMaxLength,
tagRegexp,
} from 'container/QueryBuilder/filters/QueryBuilderSearch/utils'; } from 'container/QueryBuilder/filters/QueryBuilderSearch/utils';
import { Option } from 'container/QueryBuilder/type'; import { Option } from 'container/QueryBuilder/type';
import { parse } from 'papaparse'; import { parse } from 'papaparse';
@ -33,7 +33,7 @@ export const useAutoComplete = (
searchKey, searchKey,
); );
const [key, operator, result] = useSetCurrentKeyAndOperator(searchValue); const [key, operator, result] = useSetCurrentKeyAndOperator(searchValue, keys);
const handleSearch = (value: string): void => { const handleSearch = (value: string): void => {
const prefixFreeValue = getRemovePrefixFromKey(getTagToken(value).tagKey); const prefixFreeValue = getRemovePrefixFromKey(getTagToken(value).tagKey);
@ -58,7 +58,7 @@ export const useAutoComplete = (
(value: string): void => { (value: string): void => {
if (isMulti) { if (isMulti) {
setSearchValue((prev: string) => { setSearchValue((prev: string) => {
const matches = prev?.matchAll(getMatchRegex(prev)); const matches = prev?.matchAll(tagRegexp);
const [match] = matches ? Array.from(matches) : []; const [match] = matches ? Array.from(matches) : [];
const [, , , matchTagValue] = match; const [, , , matchTagValue] = match;
const data = parse(matchTagValue).data.flat(); const data = parse(matchTagValue).data.flat();

View File

@ -8,35 +8,23 @@ export type OperatorType =
const operatorTypeMapper: Record<string, OperatorType> = { const operatorTypeMapper: Record<string, OperatorType> = {
[OPERATORS.IN]: 'MULTIPLY_VALUE', [OPERATORS.IN]: 'MULTIPLY_VALUE',
[OPERATORS.in]: 'MULTIPLY_VALUE',
[OPERATORS.NIN]: 'MULTIPLY_VALUE', [OPERATORS.NIN]: 'MULTIPLY_VALUE',
[OPERATORS.not_in]: 'MULTIPLY_VALUE',
[OPERATORS.EXISTS]: 'NON_VALUE', [OPERATORS.EXISTS]: 'NON_VALUE',
[OPERATORS.exists]: 'NON_VALUE',
[OPERATORS.NOT_EXISTS]: 'NON_VALUE', [OPERATORS.NOT_EXISTS]: 'NON_VALUE',
[OPERATORS.not_exists]: 'NON_VALUE',
[OPERATORS['<=']]: 'SINGLE_VALUE', [OPERATORS['<=']]: 'SINGLE_VALUE',
[OPERATORS['<']]: 'SINGLE_VALUE', [OPERATORS['<']]: 'SINGLE_VALUE',
[OPERATORS['>=']]: 'SINGLE_VALUE', [OPERATORS['>=']]: 'SINGLE_VALUE',
[OPERATORS['>']]: 'SINGLE_VALUE', [OPERATORS['>']]: 'SINGLE_VALUE',
[OPERATORS.LIKE]: 'SINGLE_VALUE', [OPERATORS.LIKE]: 'SINGLE_VALUE',
[OPERATORS.like]: 'SINGLE_VALUE',
[OPERATORS.NLIKE]: 'SINGLE_VALUE', [OPERATORS.NLIKE]: 'SINGLE_VALUE',
[OPERATORS.not_like]: 'SINGLE_VALUE',
[OPERATORS.REGEX]: 'SINGLE_VALUE', [OPERATORS.REGEX]: 'SINGLE_VALUE',
[OPERATORS.regex]: 'SINGLE_VALUE',
[OPERATORS.NREGEX]: 'SINGLE_VALUE', [OPERATORS.NREGEX]: 'SINGLE_VALUE',
[OPERATORS.nregex]: 'SINGLE_VALUE',
[OPERATORS.CONTAINS]: 'SINGLE_VALUE', [OPERATORS.CONTAINS]: 'SINGLE_VALUE',
[OPERATORS.contains]: 'SINGLE_VALUE',
[OPERATORS.NOT_CONTAINS]: 'SINGLE_VALUE', [OPERATORS.NOT_CONTAINS]: 'SINGLE_VALUE',
[OPERATORS.not_contains]: 'SINGLE_VALUE',
[OPERATORS['=']]: 'SINGLE_VALUE', [OPERATORS['=']]: 'SINGLE_VALUE',
[OPERATORS['!=']]: 'SINGLE_VALUE', [OPERATORS['!=']]: 'SINGLE_VALUE',
[OPERATORS.HAS]: 'SINGLE_VALUE', [OPERATORS.HAS]: 'SINGLE_VALUE',
[OPERATORS.has]: 'SINGLE_VALUE',
[OPERATORS.NHAS]: 'SINGLE_VALUE', [OPERATORS.NHAS]: 'SINGLE_VALUE',
[OPERATORS.nhas]: 'SINGLE_VALUE',
}; };
export const useOperatorType = (operator: string): OperatorType => export const useOperatorType = (operator: string): OperatorType =>

View File

@ -81,8 +81,8 @@ export const useOptions = (
const getKeyOperatorOptions = useCallback( const getKeyOperatorOptions = useCallback(
(key: string) => { (key: string) => {
const operatorsOptions = operators?.map((operator) => ({ const operatorsOptions = operators?.map((operator) => ({
value: `${key} ${operator.toLowerCase()} `, value: `${key} ${operator} `,
label: `${key} ${operator.toLowerCase()} `, label: `${key} ${operator} `,
})); }));
if (whereClauseConfig) { if (whereClauseConfig) {
return [ return [
@ -148,28 +148,26 @@ export const useOptions = (
return useMemo( return useMemo(
() => () =>
options (
.filter( options.filter(
(option, index, self) => (option, index, self) =>
index === index ===
self.findIndex( self.findIndex(
(o) => o.label === option.label && o.value === option.value, // to remove duplicate & empty options from list (o) => o.label === option.label && o.value === option.value, // to remove duplicate & empty options from list
) && option.value !== '', ) && option.value !== '',
) ) || []
.map((option) => { ).map((option) => {
const { tagValue } = getTagToken(searchValue); const { tagValue } = getTagToken(searchValue);
if (isMulti) { if (isMulti) {
return { return {
...option, ...option,
selected: Array.isArray(tagValue) selected: tagValue
? tagValue .filter((i) => i.trim().replace(/^\s+/, '') === option.value)
?.filter((i) => i.trim().replace(/^\s+/, '') === option.value) .includes(option.value),
?.includes(option.value) };
: String(tagValue).includes(option.value), }
}; return option;
} }),
return option;
}),
[isMulti, options, searchValue], [isMulti, options, searchValue],
); );
}; };

View File

@ -1,24 +1,32 @@
import { getTagToken } from 'container/QueryBuilder/filters/QueryBuilderSearch/utils'; import {
import { useMemo, useRef } from 'react'; getRemovePrefixFromKey,
getTagToken,
} from 'container/QueryBuilder/filters/QueryBuilderSearch/utils';
import { useMemo } from 'react';
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
type ICurrentKeyAndOperator = [string, string, string[]]; type ICurrentKeyAndOperator = [string, string, string[]];
export const useSetCurrentKeyAndOperator = ( export const useSetCurrentKeyAndOperator = (
value: string, value: string,
keys: BaseAutocompleteData[],
): ICurrentKeyAndOperator => { ): ICurrentKeyAndOperator => {
const keyRef = useRef<string>(''); const [key, operator, result] = useMemo(() => {
const operatorRef = useRef<string>(''); let key = '';
let operator = '';
const result = useMemo(() => {
let result: string[] = []; let result: string[] = [];
const { tagKey, tagOperator, tagValue } = getTagToken(value); const { tagKey, tagOperator, tagValue } = getTagToken(value);
const isSuggestKey = keys?.some(
(el) => el?.key === getRemovePrefixFromKey(tagKey),
);
if (isSuggestKey || keys.length === 0) {
key = tagKey || '';
operator = tagOperator || '';
result = tagValue || [];
}
keyRef.current = tagKey || ''; return [key, operator, result];
operatorRef.current = tagOperator || ''; }, [value, keys]);
result = tagValue || [];
return result; return [key, operator, result];
}, [value]);
return [keyRef.current, operatorRef.current, result];
}; };

View File

@ -74,7 +74,6 @@ export const useTag = (
const handleAddTag = useCallback( const handleAddTag = useCallback(
(value: string): void => { (value: string): void => {
const { tagKey } = getTagToken(value); const { tagKey } = getTagToken(value);
const [key, id] = tagKey.split('-'); const [key, id] = tagKey.split('-');
if (id === 'custom') { if (id === 'custom') {