|
| 1 | +import { DateTimeUtil } from '../date-common/util/date-time.util'; |
| 2 | +import { EntityType, FieldType } from '../grids/common/grid.interface'; |
| 3 | +import { GridColumnDataType } from './data-util'; |
| 4 | +import { IFilteringOperation, IgxBooleanFilteringOperand, IgxDateFilteringOperand, IgxDateTimeFilteringOperand, IgxFilteringOperand, IgxNumberFilteringOperand, IgxStringFilteringOperand, IgxTimeFilteringOperand } from './filtering-condition'; |
1 | 5 | import { IFilteringExpression } from './filtering-expression.interface'; |
2 | | -import { IFilteringExpressionsTree } from './filtering-expressions-tree'; |
| 6 | +import { IExpressionTree, IFilteringExpressionsTree } from './filtering-expressions-tree'; |
3 | 7 |
|
4 | 8 | export class ExpressionsTreeUtil { |
5 | 9 | /** |
@@ -54,3 +58,163 @@ export class ExpressionsTreeUtil { |
54 | 58 | return false; |
55 | 59 | } |
56 | 60 | } |
| 61 | + |
| 62 | +/** |
| 63 | + * Recreates the search value for a given expression. |
| 64 | + * @param searchValue The search value to recreate. |
| 65 | + * @param dataType The data type of the field. |
| 66 | + * @returns The recreated search value. |
| 67 | + */ |
| 68 | +function recreateSearchValue(searchValue: any, dataType: string): any { |
| 69 | + if (!dataType) { |
| 70 | + return searchValue; |
| 71 | + } |
| 72 | + // In ESF, values are stored as a Set. |
| 73 | + // Those values are converted to an array before returning string in the stringifyCallback |
| 74 | + // now we need to convert those back to Set |
| 75 | + if (Array.isArray(searchValue)) { |
| 76 | + return new Set(searchValue); |
| 77 | + } else if ((dataType.toLowerCase().includes('date') || dataType.toLowerCase().includes('time')) && !(searchValue instanceof Date)) { |
| 78 | + return DateTimeUtil.parseIsoDate(searchValue) ?? searchValue; |
| 79 | + } |
| 80 | + |
| 81 | + return searchValue; |
| 82 | +} |
| 83 | + |
| 84 | +/** |
| 85 | + * Returns the filtering logic function for a given dataType and condition (contains, greaterThan, etc.) |
| 86 | + * @param dataType The data type of the field. |
| 87 | + * @param name The name of the filtering condition. |
| 88 | + * @returns The filtering logic function. |
| 89 | + */ |
| 90 | +function getFilteringCondition(dataType: string, name: string): IFilteringOperation { |
| 91 | + let filters: IgxFilteringOperand; |
| 92 | + switch (dataType) { |
| 93 | + case GridColumnDataType.Boolean: |
| 94 | + filters = IgxBooleanFilteringOperand.instance(); |
| 95 | + break; |
| 96 | + case GridColumnDataType.Number: |
| 97 | + case GridColumnDataType.Currency: |
| 98 | + case GridColumnDataType.Percent: |
| 99 | + filters = IgxNumberFilteringOperand.instance(); |
| 100 | + break; |
| 101 | + case GridColumnDataType.Date: |
| 102 | + filters = IgxDateFilteringOperand.instance(); |
| 103 | + break; |
| 104 | + case GridColumnDataType.Time: |
| 105 | + filters = IgxTimeFilteringOperand.instance(); |
| 106 | + break; |
| 107 | + case GridColumnDataType.DateTime: |
| 108 | + filters = IgxDateTimeFilteringOperand.instance(); |
| 109 | + break; |
| 110 | + case GridColumnDataType.String: |
| 111 | + default: |
| 112 | + filters = IgxStringFilteringOperand.instance(); |
| 113 | + break; |
| 114 | + } |
| 115 | + return filters.condition(name); |
| 116 | +} |
| 117 | + |
| 118 | +/** |
| 119 | + * Recreates the IFilteringOperation for a given expression. |
| 120 | + * If the `logic` is already populated - it will return the original IFilteringOperation |
| 121 | + * of the expression. |
| 122 | + * @param expression The expression for which to resolve the IFilteringOperation. |
| 123 | + * @param dataType The data type of the field. |
| 124 | + * @returns The IFilteringOperation for the given expression. |
| 125 | + */ |
| 126 | +function recreateOperatorFromDataType(expression: IFilteringExpression, dataType: string): IFilteringOperation { |
| 127 | + if (!expression.condition?.logic) { |
| 128 | + return getFilteringCondition(dataType, expression.conditionName || expression.condition?.name); |
| 129 | + } |
| 130 | + |
| 131 | + return expression.condition; |
| 132 | +} |
| 133 | + |
| 134 | +/** |
| 135 | + * Recreates an expression from the given fields by applying the correct operands |
| 136 | + * and adjusting the search value to be the correct type. |
| 137 | + * @param expression The expression to recreate. |
| 138 | + * @param fields An array of fields to use for recreating the expression. |
| 139 | + * @returns The recreated expression. |
| 140 | + */ |
| 141 | +function recreateExpression(expression: IFilteringExpression, fields: FieldType[]): IFilteringExpression { |
| 142 | + const field = fields?.find(f => f.field === expression.fieldName); |
| 143 | + |
| 144 | + if (field && !expression.condition?.logic) { |
| 145 | + if (!field.filters) { |
| 146 | + expression.condition = recreateOperatorFromDataType(expression, field.dataType); |
| 147 | + } else { |
| 148 | + expression.condition = field.filters.condition(expression.conditionName || expression.condition?.name); |
| 149 | + } |
| 150 | + } |
| 151 | + |
| 152 | + if (!expression.condition) { |
| 153 | + throw Error('Wrong `conditionName`, `condition` or `field` provided0!'); |
| 154 | + } |
| 155 | + |
| 156 | + if (!expression.conditionName) { |
| 157 | + expression.conditionName = expression.condition?.name; |
| 158 | + } |
| 159 | + |
| 160 | + expression.searchVal = recreateSearchValue(expression.searchVal, field?.dataType); |
| 161 | + |
| 162 | + return expression; |
| 163 | +} |
| 164 | + |
| 165 | +/** |
| 166 | + * Checks if the given entry is an IExpressionTree. |
| 167 | + * @param entry The entry to check. |
| 168 | + * @returns True if the entry is an IExpressionTree, false otherwise. |
| 169 | + */ |
| 170 | +export function isTree(entry: IExpressionTree | IFilteringExpression): entry is IExpressionTree { |
| 171 | + return 'operator' in entry; |
| 172 | +} |
| 173 | + |
| 174 | +/** |
| 175 | + * Recreates the tree from a given array of entities by applying the correct operands |
| 176 | + * for each expression and adjusting the search values to be the correct type. |
| 177 | + * @param tree The expression tree to recreate. |
| 178 | + * @param entities An array of entities to use for recreating the tree. |
| 179 | + * @returns The recreated expression tree. |
| 180 | + */ |
| 181 | +export function recreateTree(tree: IExpressionTree, entities: EntityType[]): IExpressionTree { |
| 182 | + const entity = entities.find(e => e.name === tree.entity); |
| 183 | + |
| 184 | + for (let i = 0; i < tree.filteringOperands.length; i++) { |
| 185 | + const operand = tree.filteringOperands[i]; |
| 186 | + if (isTree(operand)) { |
| 187 | + tree.filteringOperands[i] = recreateTree(operand, entities); |
| 188 | + } else { |
| 189 | + if (operand.searchTree) { |
| 190 | + operand.searchTree = recreateTree(operand.searchTree, entities); |
| 191 | + } |
| 192 | + tree.filteringOperands[i] = recreateExpression(operand, entity?.fields); |
| 193 | + } |
| 194 | + } |
| 195 | + |
| 196 | + return tree; |
| 197 | +} |
| 198 | + |
| 199 | +/** |
| 200 | + * Recreates the tree from a given array of fields by applying the correct operands. |
| 201 | + * It is recommended to use `recreateTree` if there will be multiple entities in the tree |
| 202 | + * with potentially colliding field names. |
| 203 | + * @param tree The expression tree to recreate. |
| 204 | + * @param fields An array of fields to use for recreating the tree. |
| 205 | + */ |
| 206 | +export function recreateTreeFromFields(tree: IExpressionTree, fields: FieldType[]): IExpressionTree { |
| 207 | + for (let i = 0; i < tree.filteringOperands.length; i++) { |
| 208 | + const operand = tree.filteringOperands[i]; |
| 209 | + if (isTree(operand)) { |
| 210 | + tree.filteringOperands[i] = recreateTreeFromFields(operand, fields); |
| 211 | + } else { |
| 212 | + if (operand.searchTree) { |
| 213 | + operand.searchTree = recreateTreeFromFields(operand.searchTree, fields); |
| 214 | + } |
| 215 | + tree.filteringOperands[i] = recreateExpression(operand, fields); |
| 216 | + } |
| 217 | + } |
| 218 | + |
| 219 | + return tree; |
| 220 | +} |
0 commit comments