@contrail/data-grouping 1.0.52 → 1.0.53-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,14 @@ Versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ### Added
11
+
12
+ - `DataGroupingProperty.valueFilter` (`{ mode: 'include' | 'exclude'; values: string[] }`): an optional, caller-supplied rule that restricts a multi-select grouping property's frames to the filter-selected values. Applied in `buildChildDataGroups` via the new `applyGroupingValueFilter` after `getDistinctValues` — pruning the fan-out to the included values (or dropping the excluded ones), while preserving the `(empty)` bucket. No-op for separate-frame mode (`groupMultiSelectInSeparateFrame`) and for non-multi-select grouping. Keeps this package decoupled from `@contrail/filters`: the caller translates its filter criteria into the rule. (VIBE-10759)
13
+
14
+ ### Fixed
15
+
16
+ - `(empty)` group membership now uses the same emptiness test as the distinct-value pass (extracted as `isEmptyGroupingValue`). The two previously diverged: items whose grouping value was an empty array or a whitespace-only string were dropped entirely (they created the `(empty)` frame but no item matched into it), and `false`/`0` values double-counted into `(empty)` on top of their own group. Only observable with `displayItemsWithEmptyGroupingValues = true`. (VIBE-10759)
17
+
10
18
  ## [1.0.50] - (initial changelog entry)
11
19
 
12
20
  - Initial changelog. Prior releases did not include a changelog.
@@ -1,6 +1,7 @@
1
1
  import { DataGroup, DataGroupStructure, DataGroupingProperty } from '../interfaces';
2
2
  import { TypePropertySortOrder } from '@contrail/types';
3
3
  export declare class DataGroupGenerator {
4
+ static isEmptyGroupingValue(value: any): boolean;
4
5
  static getDistinctValues(data: any, rootIndex: any, slugIndex?: any, rootAltIndex?: any, slugAltIndex?: any, groupMultiSelectInSeparateFrame?: boolean, sortOptions?: {
5
6
  sortOrder: TypePropertySortOrder;
6
7
  options: any;
@@ -8,6 +9,7 @@ export declare class DataGroupGenerator {
8
9
  isDate: boolean;
9
10
  isNumber: boolean;
10
11
  }, displayItemsWithEmptyGroupingValues?: boolean, displayOptionFrameWithNoData?: boolean): any[];
12
+ static applyGroupingValueFilter(distinctValues: Array<any>, groupingProperty: DataGroupingProperty, groupMultiSelectInSeparateFrame: boolean): Array<any>;
11
13
  static buildChildDataGroups(data: any, parentGroup: DataGroup, groupingProperties: Array<DataGroupingProperty>, leafNodeDataCount: any, currentDepth: any, groupMultiSelectInSeparateFrame?: boolean, displayItemsWithEmptyGroupingValues?: boolean, displayOptionFrameWithNoData?: boolean): void;
12
14
  static buildDataGroupStructure(data: Array<any>, groupingProperties: Array<DataGroupingProperty>, leafNodeDataCount: number, groupMultiSelectInSeparateFrame?: boolean, displayItemsWithEmptyGroupingValues?: boolean, displayOptionFrameWithNoData?: boolean): DataGroupStructure;
13
15
  static createPartitionedGroupsFromData(parentGroup: DataGroup, data: Array<any>, leafNodeDataCount: number): Array<DataGroup>;
@@ -4,6 +4,15 @@ exports.DataGroupGenerator = void 0;
4
4
  const util_1 = require("@contrail/util");
5
5
  const types_1 = require("@contrail/types");
6
6
  class DataGroupGenerator {
7
+ static isEmptyGroupingValue(value) {
8
+ return ((value === undefined ||
9
+ value === null ||
10
+ value === '' ||
11
+ (Array.isArray(value) && value.length === 0) ||
12
+ (typeof value === 'string' && value.trim() === '') ||
13
+ (typeof value === 'number' && isNaN(value))) &&
14
+ value !== false);
15
+ }
7
16
  static getDistinctValues(data, rootIndex, slugIndex = null, rootAltIndex = null, slugAltIndex = null, groupMultiSelectInSeparateFrame = false, sortOptions = { sortOrder: types_1.TypePropertySortOrder.ASCENDING, options: null }, propertyTypeOptions = { isDate: false, isNumber: false }, displayItemsWithEmptyGroupingValues = false, displayOptionFrameWithNoData = false) {
8
17
  const sortOrder = (sortOptions === null || sortOptions === void 0 ? void 0 : sortOptions.sortOrder) || types_1.TypePropertySortOrder.ASCENDING;
9
18
  const options = (sortOptions === null || sortOptions === void 0 ? void 0 : sortOptions.options) || null;
@@ -23,13 +32,7 @@ class DataGroupGenerator {
23
32
  }
24
33
  }
25
34
  let value = key;
26
- const isEmptyValue = (value === undefined ||
27
- value === null ||
28
- value === '' ||
29
- (Array.isArray(value) && value.length === 0) ||
30
- (typeof value === 'string' && value.trim() === '') ||
31
- (typeof value === 'number' && isNaN(value))) &&
32
- value !== false;
35
+ const isEmptyValue = DataGroupGenerator.isEmptyGroupingValue(value);
33
36
  if (isEmptyValue) {
34
37
  if (displayItemsWithEmptyGroupingValues) {
35
38
  hasEmptyValues = true;
@@ -111,6 +114,24 @@ class DataGroupGenerator {
111
114
  }
112
115
  return distinctValues;
113
116
  }
117
+ static applyGroupingValueFilter(distinctValues, groupingProperty, groupMultiSelectInSeparateFrame) {
118
+ var _a;
119
+ const rule = groupingProperty === null || groupingProperty === void 0 ? void 0 : groupingProperty.valueFilter;
120
+ if (!rule ||
121
+ !rule.values ||
122
+ rule.values.length === 0 ||
123
+ groupMultiSelectInSeparateFrame ||
124
+ ((_a = groupingProperty === null || groupingProperty === void 0 ? void 0 : groupingProperty.propertyDefinition) === null || _a === void 0 ? void 0 : _a.propertyType) !== types_1.PropertyType.MultiSelect) {
125
+ return distinctValues;
126
+ }
127
+ const ruleValues = new Set(rule.values);
128
+ return distinctValues.filter((value) => {
129
+ if (value === '(empty)') {
130
+ return true;
131
+ }
132
+ return rule.mode === 'exclude' ? !ruleValues.has(value) : ruleValues.has(value);
133
+ });
134
+ }
114
135
  static buildChildDataGroups(data, parentGroup, groupingProperties, leafNodeDataCount, currentDepth, groupMultiSelectInSeparateFrame = false, displayItemsWithEmptyGroupingValues = false, displayOptionFrameWithNoData = false) {
115
136
  var _a, _b, _c, _d, _e;
116
137
  const groupingProperty = groupingProperties[currentDepth];
@@ -128,11 +149,12 @@ class DataGroupGenerator {
128
149
  const sort = groupingProperty.sort || types_1.TypePropertySortOrder.ASCENDING;
129
150
  const options = ((_e = (_d = groupingProperty.propertyDefinition) === null || _d === void 0 ? void 0 : _d.options) === null || _e === void 0 ? void 0 : _e.map((x) => x.value)) || null;
130
151
  let distinctValues = this.getDistinctValues(data, rootIndex, slugIndex, rootAltIndex, slugAltIndex, groupMultiSelectInSeparateFrame, { sortOrder: sort, options }, propertyTypeOptions, displayItemsWithEmptyGroupingValues, displayOptionFrameWithNoData);
152
+ distinctValues = this.applyGroupingValueFilter(distinctValues, groupingProperty, groupMultiSelectInSeparateFrame);
131
153
  for (let val of distinctValues) {
132
154
  const groupData = data.filter((obj) => {
133
155
  const objVal = util_1.ObjectUtil.getBySlugs(obj, rootIndex, slugIndex) || util_1.ObjectUtil.getBySlugs(obj, rootAltIndex, slugAltIndex);
134
156
  if (val === '(empty)') {
135
- return !objVal;
157
+ return DataGroupGenerator.isEmptyGroupingValue(objVal);
136
158
  }
137
159
  if (propertyTypeOptions.isDate) {
138
160
  const objDate = objVal ? new Date(objVal).toISOString().split('T')[0] : null;
@@ -28,4 +28,8 @@ export interface DataGroupingProperty {
28
28
  typeRootSlug: string;
29
29
  sort: TypePropertySortOrder;
30
30
  isSecondaryGroup?: boolean;
31
+ valueFilter?: {
32
+ mode: 'include' | 'exclude';
33
+ values: Array<string>;
34
+ };
31
35
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contrail/data-grouping",
3
- "version": "1.0.52",
3
+ "version": "1.0.53-alpha.1",
4
4
  "description": "Utilities and interfaces for grouping data into hierarchial data structures based on properties.",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",