Skip to content

Commit f6c1648

Browse files
committed
code cleanup
1 parent de33c76 commit f6c1648

File tree

2 files changed

+282
-271
lines changed

2 files changed

+282
-271
lines changed

UI/web-app/src/components/HRQuerySource/HRQuerySource.base.tsx

Lines changed: 10 additions & 271 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ import { fetchAttributeValues } from '../../store/sqlMembershipSources.api';
2525
import { selectAttributes, selectSource, selectAttributeValues } from '../../store/sqlMembershipSources.slice';
2626
import { SqlMembershipAttribute, SqlMembershipAttributeValue } from '../../models';
2727
import { IFilterPart } from '../../models/IFilterPart';
28+
import { Group } from '../../models/Group';
29+
import { parseGroup, stringifyGroups } from './QuerySerializer';
2830

2931
export const getClassNames = classNamesFunction<HRQuerySourceStyleProps, HRQuerySourceStyles>();
3032

@@ -48,13 +50,6 @@ export const HRQuerySourceBase: React.FunctionComponent<HRQuerySourceProps> = (p
4850
[key: number]: IComboBoxOption[];
4951
};
5052

51-
interface Group {
52-
name: string;
53-
items: IFilterPart[];
54-
children: Group[];
55-
andOr: string;
56-
}
57-
5853
const dispatch = useDispatch<AppDispatch>();
5954
const orgLeaderDetails = useSelector(selectOrgLeaderDetails);
6055
const objectIdEmployeeIdMapping = useSelector(selectObjectIdEmployeeIdMapping);
@@ -146,266 +141,6 @@ export const HRQuerySourceBase: React.FunctionComponent<HRQuerySourceProps> = (p
146141
}
147142
}, [children]);
148143

149-
function stringifyGroup(group: Group, isChild?: boolean, childIndex?: number, childrenLength?: number): string {
150-
let result = '(';
151-
152-
result += `${group.items.map((item, index) => {
153-
if (index < group.items.length - 1) {
154-
return item.attribute + ' ' + item.equalityOperator + ' ' + item.value + ' ' + item.andOr;
155-
} else {
156-
return item.attribute + ' ' + item.equalityOperator + ' ' + item.value;
157-
}
158-
}).join(' ')}`;
159-
160-
if (group.children.length === 0) {
161-
result += ')';
162-
}
163-
164-
if (isChild) {
165-
if (childrenLength && childIndex !== childrenLength-1) result += ` ${group.andOr} `;
166-
}
167-
else {
168-
result += ` ${group.andOr} `;
169-
}
170-
171-
group.children.forEach((child, index) => {
172-
result += stringifyGroup(child, true, index, group.children.length);
173-
if (index < group.children.length - 1) {
174-
result += ' ';
175-
}
176-
});
177-
178-
if (group.children.length > 0) {
179-
result += ')';
180-
result += ` ${group.children[group.children.length-1].andOr} `;
181-
}
182-
183-
return result;
184-
}
185-
186-
function stringifyGroups(groups: Group[]): string {
187-
let result = '';
188-
189-
groups.forEach((group, index) => {
190-
result += stringifyGroup(group);
191-
if (index < groups.length - 1) {
192-
result += ' ';
193-
}
194-
});
195-
196-
return result;
197-
}
198-
199-
function parseFilterPart(part: string): IFilterPart {
200-
const operators = ["<=", ">=", "<>", "=", ">", "<"];
201-
let operatorFound = '';
202-
let operatorIndex = -1;
203-
204-
for (const operator of operators) {
205-
const index = part.indexOf(operator);
206-
if (index !== -1) {
207-
operatorFound = operator;
208-
operatorIndex = index;
209-
break;
210-
}
211-
}
212-
213-
if (operatorIndex === -1) {
214-
setFilterTextEnabled(true);
215-
}
216-
const attribute = part.slice(0, operatorIndex).trim();
217-
const value = part.slice(operatorIndex + operatorFound.length).trim();
218-
219-
return {
220-
attribute,
221-
equalityOperator: operatorFound,
222-
value,
223-
andOr: ""
224-
};
225-
}
226-
227-
function findPartsOfString(string: string, substringArray: { currentSegment: string, start: number; end: number }[]): { currentSegment: string, start: number; end: number, andOr: string }[] {
228-
const output: { currentSegment: string, start: number; end: number, andOr: "" }[] = [];
229-
let lastEnd = 0;
230-
231-
for (const substringInfo of substringArray) {
232-
const { currentSegment, start, end } = substringInfo;
233-
234-
// Add the segment between the end of the previous segment and the start of the current segment
235-
if (start > lastEnd) {
236-
output.push({
237-
currentSegment: string.substring(lastEnd, start),
238-
start: lastEnd,
239-
end: start - 1,
240-
andOr: ""
241-
});
242-
}
243-
244-
// Add the current segment
245-
output.push({ currentSegment, start, end, andOr: "" });
246-
247-
// Update lastEnd
248-
lastEnd = end + 1;
249-
}
250-
251-
// Add the remaining part of the string after the last segment
252-
if (lastEnd < string.length) {
253-
output.push({
254-
currentSegment: string.substring(lastEnd),
255-
start: lastEnd,
256-
end: string.length - 1,
257-
andOr: ""
258-
});
259-
}
260-
261-
return output;
262-
}
263-
264-
function appendAndOr(a: { currentSegment: string; start: number; end: number; andOr: string; }[]) {
265-
a.forEach((segment, index) => {
266-
let modifiedSegment = segment.currentSegment.trim();
267-
let startWord = '';
268-
let endWord = '';
269-
270-
const lowerCaseSegment = modifiedSegment.toLowerCase();
271-
272-
if (lowerCaseSegment.startsWith('and ')) {
273-
startWord = 'And';
274-
modifiedSegment = modifiedSegment.substring(4).trim();
275-
} else if (lowerCaseSegment.startsWith('or ')) {
276-
startWord = 'Or';
277-
modifiedSegment = modifiedSegment.substring(3).trim();
278-
}
279-
280-
if (lowerCaseSegment.endsWith(' and')) {
281-
endWord = 'And';
282-
modifiedSegment = modifiedSegment.substring(0, modifiedSegment.length - 4).trim();
283-
} else if (lowerCaseSegment.endsWith(' or')) {
284-
endWord = 'Or';
285-
modifiedSegment = modifiedSegment.substring(0, modifiedSegment.length - 3).trim();
286-
}
287-
288-
if (lowerCaseSegment === 'and') {
289-
startWord = 'And';
290-
modifiedSegment = '';
291-
} else if (lowerCaseSegment === 'or') {
292-
startWord = 'Or';
293-
modifiedSegment = '';
294-
}
295-
296-
if (startWord !== '') {
297-
a[index-1].andOr = startWord;
298-
}
299-
if (endWord !== '') {
300-
a[index].andOr = endWord;
301-
}
302-
303-
a[index].currentSegment = modifiedSegment;
304-
305-
if (modifiedSegment === '') {
306-
a.splice(index, 1);
307-
} else {
308-
a[index].currentSegment = modifiedSegment;
309-
}
310-
});
311-
return a;
312-
}
313-
314-
function parseGroup(input: string): Group[] {
315-
const groups: Group[] = [];
316-
let subStrings: { currentSegment: string, start: number; end: number}[] = [];
317-
let depth = 0;
318-
let currentSegment = '';
319-
let operators: string[] = [];
320-
321-
input = input.trim();
322-
let start: number = 0;
323-
let end: number = input.length - 1;
324-
325-
for (let i = 0; i < input.length; i++) {
326-
const char = input[i];
327-
328-
if (char === '(') {
329-
if (depth > 0) {
330-
currentSegment += char;
331-
}
332-
depth++;
333-
if (depth === 1) start = i;
334-
} else if (char === ')') {
335-
depth--;
336-
if (depth === 0) {
337-
end = i;
338-
subStrings.push({ currentSegment, start, end});
339-
currentSegment = '';
340-
} else {
341-
currentSegment += char;
342-
}
343-
} else if (depth === 0 && (input.substr(i, 3) === ' Or' || input.substr(i, 4) === ' And')) {
344-
operators.push(input.substr(i, input.substr(i, 4) === ' And' ? 4 : 3).trim());
345-
i += operators[operators.length - 1].length - 1;
346-
} else if (depth > 0) {
347-
currentSegment += char;
348-
}
349-
}
350-
351-
var allParts = findPartsOfString(input, subStrings);
352-
var allPartsWithAndOr = appendAndOr(allParts);
353-
354-
allPartsWithAndOr.forEach((currentSegment, i) => {
355-
groups.push(parseSegment(currentSegment.currentSegment));
356-
if (groups[i].children.length > 0 && groups[i].children && groups[i].children[groups[i].children.length-1].andOr !== null) {
357-
groups[i].children[groups[i].children.length-1].andOr = allPartsWithAndOr[i].andOr;
358-
}
359-
else if (allPartsWithAndOr[i].andOr !== '') groups[i].andOr = allPartsWithAndOr[i].andOr;
360-
361-
});
362-
return groups;
363-
}
364-
365-
function parseSegment(segment: string, groupOperator?: string): Group {
366-
if (segment.includes('(') && segment.includes(')')) {
367-
let children: Group[] = [];
368-
const innerSegments = segment.match(/\((.*?)\)/g)?.map(innerSegment => innerSegment.replace(/^\(|\)$/g, ''));
369-
const contentOutsideParentheses = segment.replace(/\s*\([^)]*\)\s*/g, '||').split('||');
370-
if (innerSegments) {
371-
innerSegments.forEach((innerSegment, index) => {
372-
const childGroup = parseSegment(innerSegment, contentOutsideParentheses && contentOutsideParentheses.length >= 0 ? contentOutsideParentheses[index+1] : "");
373-
children.push(childGroup);
374-
});
375-
}
376-
377-
let start = segment.indexOf('(');
378-
let end = segment.lastIndexOf(')');
379-
let remainingSegment = segment.substring(0, start) + segment.substring(end + 1);
380-
var match = remainingSegment.match(/\b(Or|And)\b/i);
381-
var operator = match ? match[1] : null;
382-
remainingSegment = remainingSegment.replace(/^\s*(Or|And)|\s*(Or|And)\s*$/gi, '').trim();
383-
if (remainingSegment) {
384-
return {
385-
name: '',
386-
items: parseSegment(remainingSegment).items,
387-
children: children,
388-
andOr: operator ?? ''
389-
};
390-
}
391-
}
392-
const items = segment.split(/ And | Or /gi).map(parseFilterPart);
393-
const operators = segment.match(/(?: And | Or )/gi) || [];
394-
395-
items.forEach((item, index) => {
396-
if (index < items.length - 1) {
397-
item.andOr = operators[index].trim();
398-
}
399-
});
400-
401-
return {
402-
name: '',
403-
items,
404-
children: [],
405-
andOr: groupOperator ?? ''
406-
};
407-
}
408-
409144
function setItemsBasedOnGroups(groups: Group[]) {
410145
let items: IFilterPart[] = [];
411146
groups.forEach(group => {
@@ -459,9 +194,13 @@ const checkType = (value: string, type: string | undefined): string => {
459194

460195
useEffect(() => {
461196
if (props.source.filter && !groupingEnabled && (props.source.filter.includes("(") || props.source.filter.includes(")"))) {
462-
const a = parseGroup(props.source.filter);
463-
const b = setItemsBasedOnGroups(a);
464-
setGroups(a);
197+
const groups = parseGroup(props.source.filter);
198+
if (groups.length <= 0) {
199+
setFilterTextEnabled(true);
200+
return;
201+
}
202+
const b = setItemsBasedOnGroups(groups);
203+
setGroups(groups);
465204
setGroupingEnabled(true);
466205
}
467206
else {
@@ -1891,7 +1630,7 @@ const checkType = (value: string, type: string | undefined): string => {
18911630
disabled={isEditingExistingJob}
18921631
/>
18931632

1894-
{(source.filter && filterTextEnabled) ?
1633+
{(source.filter && (filterTextEnabled || !attributes)) ?
18951634
(
18961635
<><div className={classNames.labelContainer}>
18971636
<Label>{strings.HROnboarding.filter}</Label>

0 commit comments

Comments
 (0)