@itwin/presentation-hierarchies 0.1.4 → 0.1.5

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
@@ -1,5 +1,13 @@
1
1
  # @itwin/presentation-hierarchies
2
2
 
3
+ ## 0.1.5
4
+
5
+ ### Patch Changes
6
+
7
+ - [#632](https://github.com/iTwin/presentation/pull/632): Fixed hierarchy filtering when multiple paths uses same instance with diffrent class name.
8
+ - Updated dependencies:
9
+ - @itwin/presentation-shared@0.3.1
10
+
3
11
  ## 0.1.4
4
12
 
5
13
  ### Patch Changes
@@ -1 +1 @@
1
- {"version":3,"file":"FilteringHierarchyDefinition.d.ts","sourceRoot":"","sources":["../../../../src/hierarchies/internal/FilteringHierarchyDefinition.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,yBAAyB,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACpF,OAAO,EAEL,yBAAyB,EACzB,mBAAmB,EACnB,wBAAwB,EAExB,4BAA4B,EAC5B,UAAU,EACV,iBAAiB,EACjB,gBAAgB,EACjB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAA2B,4BAA4B,EAAE,MAAM,4BAA4B,CAAC;AAGnG,gBAAgB;AAChB,MAAM,WAAW,0BAA0B;IACzC,cAAc,EAAE,yBAAyB,CAAC;IAC1C,MAAM,EAAE,mBAAmB,CAAC;IAC5B,mBAAmB,EAAE,4BAA4B,EAAE,CAAC;CACrD;AAED,gBAAgB;AAChB,qBAAa,4BAA6B,YAAW,mBAAmB;IACtE,OAAO,CAAC,eAAe,CAA4B;IACnD,OAAO,CAAC,OAAO,CAAsB;IACrC,OAAO,CAAC,oBAAoB,CAAiC;gBAE1C,KAAK,EAAE,0BAA0B;IAMpD,IAAW,cAAc,IAAI,gBAAgB,CAS5C;IAED,IAAW,eAAe,IAAI,iBAAiB,CAc9C;IAED,IAAW,SAAS,IAAI,UAAU,CAUjC;IAEY,oBAAoB,CAAC,KAAK,EAAE,yBAAyB,GAAG,OAAO,CAAC,wBAAwB,CAAC;IAsDtG,OAAO,CAAC,iBAAiB;CAU1B;AAqED,gBAAgB;AAEhB,eAAO,MAAM,uCAAuC,0BAA0B,CAAC;AAE/E,gBAAgB;AAEhB,eAAO,MAAM,gCAAgC,mBAAmB,CAAC;AAEjE,gBAAgB;AAEhB,eAAO,MAAM,yCAAyC,4BAA4B,CAAC;AAEnF,gBAAgB;AAChB,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,4BAA4B,EACjC,eAAe,EAAE,KAAK,CAAC;IAAE,EAAE,EAAE,WAAW,CAAC;IAAC,uBAAuB,EAAE,4BAA4B,EAAE,CAAA;CAAE,CAAC,EACpG,cAAc,EAAE,OAAO,EACvB,oBAAoB,EAAE,OAAO,EAC7B,uBAAuB,EAAE,OAAO,GAC/B,4BAA4B,CA+B9B"}
1
+ {"version":3,"file":"FilteringHierarchyDefinition.d.ts","sourceRoot":"","sources":["../../../../src/hierarchies/internal/FilteringHierarchyDefinition.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,yBAAyB,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACpF,OAAO,EAEL,yBAAyB,EACzB,mBAAmB,EACnB,wBAAwB,EAExB,4BAA4B,EAC5B,UAAU,EACV,iBAAiB,EACjB,gBAAgB,EACjB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAA2B,4BAA4B,EAAE,MAAM,4BAA4B,CAAC;AAGnG,gBAAgB;AAChB,MAAM,WAAW,0BAA0B;IACzC,cAAc,EAAE,yBAAyB,CAAC;IAC1C,MAAM,EAAE,mBAAmB,CAAC;IAC5B,mBAAmB,EAAE,4BAA4B,EAAE,CAAC;CACrD;AAED,gBAAgB;AAChB,qBAAa,4BAA6B,YAAW,mBAAmB;IACtE,OAAO,CAAC,eAAe,CAA4B;IACnD,OAAO,CAAC,OAAO,CAAsB;IACrC,OAAO,CAAC,oBAAoB,CAAiC;gBAE1C,KAAK,EAAE,0BAA0B;IAMpD,IAAW,cAAc,IAAI,gBAAgB,CAS5C;IAED,IAAW,eAAe,IAAI,iBAAiB,CAc9C;IAED,IAAW,SAAS,IAAI,UAAU,CAUjC;IAEY,oBAAoB,CAAC,KAAK,EAAE,yBAAyB,GAAG,OAAO,CAAC,wBAAwB,CAAC;IAwDtG,OAAO,CAAC,iBAAiB;CAU1B;AA+FD,gBAAgB;AAEhB,eAAO,MAAM,uCAAuC,0BAA0B,CAAC;AAE/E,gBAAgB;AAEhB,eAAO,MAAM,gCAAgC,mBAAmB,CAAC;AAEjE,gBAAgB;AAEhB,eAAO,MAAM,yCAAyC,4BAA4B,CAAC;AAEnF,gBAAgB;AAChB,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,4BAA4B,EACjC,eAAe,EAAE,KAAK,CAAC;IAAE,EAAE,EAAE,WAAW,CAAC;IAAC,uBAAuB,EAAE,4BAA4B,EAAE,CAAA;CAAE,CAAC,EACpG,cAAc,EAAE,OAAO,EACvB,oBAAoB,EAAE,OAAO,EAC7B,uBAAuB,EAAE,OAAO,GAC/B,4BAA4B,CA+B9B"}
@@ -67,7 +67,7 @@ class FilteringHierarchyDefinition {
67
67
  return false;
68
68
  }
69
69
  return id.key === definition.node.key;
70
- }, (def, matchingFilters, isFilterTarget) => {
70
+ }, this._classHierarchy, (def, matchingFilters, isFilterTarget) => {
71
71
  const filteredChildrenIdentifierPaths = matchingFilters.reduce((r, c) => [...r, ...c.childrenIdentifierPaths], new Array());
72
72
  return {
73
73
  ...def,
@@ -81,7 +81,7 @@ class FilteringHierarchyDefinition {
81
81
  return false;
82
82
  }
83
83
  return this._classHierarchy.classDerivesFrom(id.className, definition.fullClassName);
84
- }, (def, matchingFilters, isFilterTarget) => applyECInstanceIdsFilter(def, matchingFilters, isFilterTarget, !!isDirectParentFilterTarget, !!hasFilterTargetAncestor));
84
+ }, this._classHierarchy, (def, matchingFilters, isFilterTarget) => applyECInstanceIdsFilter(def, matchingFilters, isFilterTarget, !!isDirectParentFilterTarget, !!hasFilterTargetAncestor));
85
85
  }
86
86
  if (matchedDefinition) {
87
87
  filteredDefinitions.push(matchedDefinition);
@@ -101,7 +101,7 @@ class FilteringHierarchyDefinition {
101
101
  }
102
102
  }
103
103
  exports.FilteringHierarchyDefinition = FilteringHierarchyDefinition;
104
- async function matchFilters(definition, filteringProps, predicate, matchedDefinitionProcessor) {
104
+ async function matchFilters(definition, filteringProps, predicate, classHierarchy, matchedDefinitionProcessor) {
105
105
  const { filteredNodePaths, isDirectParentFilterTarget } = filteringProps;
106
106
  let isFilterTarget = false;
107
107
  const matchingFilters = [];
@@ -111,7 +111,7 @@ async function matchFilters(definition, filteringProps, predicate, matchedDefini
111
111
  }
112
112
  const nodeId = path[0];
113
113
  if (await predicate(nodeId)) {
114
- let childrenIdentifierPaths = matchingFilters.find(({ id }) => HierarchyNodeIdentifier_1.HierarchyNodeIdentifier.equal(id, nodeId))?.childrenIdentifierPaths;
114
+ let childrenIdentifierPaths = await findChildrenIdentifierPaths(matchingFilters, nodeId, classHierarchy);
115
115
  if (!childrenIdentifierPaths) {
116
116
  childrenIdentifierPaths = [];
117
117
  matchingFilters.push({
@@ -135,6 +135,23 @@ async function matchFilters(definition, filteringProps, predicate, matchedDefini
135
135
  }
136
136
  return undefined;
137
137
  }
138
+ async function findChildrenIdentifierPaths(filters, nodeId, classHierarchy) {
139
+ for (const filter of filters) {
140
+ if (await identifiersEqual(filter.id, nodeId, classHierarchy)) {
141
+ return filter.childrenIdentifierPaths;
142
+ }
143
+ }
144
+ return undefined;
145
+ }
146
+ async function identifiersEqual(lhs, rhs, classHierarchy) {
147
+ if (HierarchyNodeIdentifier_1.HierarchyNodeIdentifier.isInstanceNodeIdentifier(lhs) && HierarchyNodeIdentifier_1.HierarchyNodeIdentifier.isInstanceNodeIdentifier(rhs)) {
148
+ return (lhs.id === rhs.id &&
149
+ (lhs.className === rhs.className ||
150
+ (await classHierarchy.classDerivesFrom(lhs.className, rhs.className)) ||
151
+ (await classHierarchy.classDerivesFrom(rhs.className, lhs.className))));
152
+ }
153
+ return HierarchyNodeIdentifier_1.HierarchyNodeIdentifier.equal(lhs, rhs);
154
+ }
138
155
  function applyFilterAttributes(node, filteredChildrenIdentifierPaths, isFilterTarget, hasFilterTargetAncestor) {
139
156
  const shouldAutoExpand = !!filteredChildrenIdentifierPaths?.some((path) => !!path.length);
140
157
  const result = { ...node };
@@ -1 +1 @@
1
- {"version":3,"file":"FilteringHierarchyDefinition.js","sourceRoot":"","sources":["../../../../src/hierarchies/internal/FilteringHierarchyDefinition.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\nimport { ECClassHierarchyInspector, InstanceKey } from \"@itwin/presentation-shared\";\nimport {\n CustomHierarchyNodeDefinition,\n DefineHierarchyLevelProps,\n HierarchyDefinition,\n HierarchyLevelDefinition,\n HierarchyNodesDefinition,\n InstanceNodesQueryDefinition,\n NodeParser,\n NodePostProcessor,\n NodePreProcessor,\n} from \"../HierarchyDefinition\";\nimport { HierarchyNode, ParsedHierarchyNode, ParsedInstanceHierarchyNode, ProcessedHierarchyNode } from \"../HierarchyNode\";\nimport { HierarchyNodeIdentifier, HierarchyNodeIdentifiersPath } from \"../HierarchyNodeIdentifier\";\nimport { defaultNodesParser } from \"./TreeNodesReader\";\n\n/** @internal */\nexport interface FilteringQueryBuilderProps {\n classHierarchy: ECClassHierarchyInspector;\n source: HierarchyDefinition;\n nodeIdentifierPaths: HierarchyNodeIdentifiersPath[];\n}\n\n/** @internal */\nexport class FilteringHierarchyDefinition implements HierarchyDefinition {\n private _classHierarchy: ECClassHierarchyInspector;\n private _source: HierarchyDefinition;\n private _nodeIdentifierPaths: HierarchyNodeIdentifiersPath[];\n\n public constructor(props: FilteringQueryBuilderProps) {\n this._classHierarchy = props.classHierarchy;\n this._source = props.source;\n this._nodeIdentifierPaths = props.nodeIdentifierPaths;\n }\n\n public get preProcessNode(): NodePreProcessor {\n return async (node) => {\n const processedNode = this._source.preProcessNode ? await this._source.preProcessNode(node) : node;\n if (processedNode?.processingParams?.hideInHierarchy && processedNode.filtering?.isFilterTarget && !processedNode.filtering.hasFilterTargetAncestor) {\n // we want to hide target nodes if they have `hideInHierarchy` param, but only if they're not under another filter target\n return undefined;\n }\n return processedNode;\n };\n }\n\n public get postProcessNode(): NodePostProcessor {\n return async (node: ProcessedHierarchyNode) => {\n const processedNode = this._source.postProcessNode ? await this._source.postProcessNode(node) : node;\n if (\n // instance nodes get the auto-expand flag in `parseNode`, but grouping ones need to be handled during post-processing\n HierarchyNode.isClassGroupingNode(node) &&\n node.children.some(\n (child: ProcessedHierarchyNode) => child.filtering && (child.filtering.isFilterTarget || child.filtering.filteredChildrenIdentifierPaths),\n )\n ) {\n return Object.assign(processedNode, { autoExpand: true });\n }\n return processedNode;\n };\n }\n\n public get parseNode(): NodeParser {\n return (row: { [columnName: string]: any }): ParsedInstanceHierarchyNode => {\n const isFilterTarget: boolean = !!row[ECSQL_COLUMN_NAME_IsFilterTarget];\n const hasFilterTargetAncestor: boolean = !!row[ECSQL_COLUMN_NAME_HasFilterTargetAncestor];\n const parsedFilteredChildrenIdentifierPaths: HierarchyNodeIdentifiersPath[] | undefined = row[ECSQL_COLUMN_NAME_FilteredChildrenPaths]\n ? JSON.parse(row[ECSQL_COLUMN_NAME_FilteredChildrenPaths])\n : undefined;\n const defaultNode = (this._source.parseNode ?? defaultNodesParser)(row);\n return applyFilterAttributes(defaultNode, parsedFilteredChildrenIdentifierPaths, isFilterTarget, hasFilterTargetAncestor);\n };\n }\n\n public async defineHierarchyLevel(props: DefineHierarchyLevelProps): Promise<HierarchyLevelDefinition> {\n const sourceDefinitions = await this._source.defineHierarchyLevel(props);\n const { filteredNodePaths, isDirectParentFilterTarget, hasFilterTargetAncestor } = this.getFilteringProps(props.parentNode);\n if (!filteredNodePaths) {\n return sourceDefinitions;\n }\n\n const filteredDefinitions: HierarchyLevelDefinition = [];\n await Promise.all(\n sourceDefinitions.map(async (definition) => {\n let matchedDefinition: HierarchyNodesDefinition | undefined;\n if (HierarchyNodesDefinition.isCustomNode(definition)) {\n matchedDefinition = await matchFilters<{ key: string }>(\n definition,\n { filteredNodePaths, isDirectParentFilterTarget },\n async (id) => {\n if (!HierarchyNodeIdentifier.isCustomNodeIdentifier(id)) {\n return false;\n }\n return id.key === definition.node.key;\n },\n (def, matchingFilters, isFilterTarget) => {\n const filteredChildrenIdentifierPaths = matchingFilters.reduce(\n (r, c) => [...r, ...c.childrenIdentifierPaths],\n new Array<HierarchyNodeIdentifiersPath>(),\n );\n return {\n ...def,\n node: applyFilterAttributes(def.node, filteredChildrenIdentifierPaths, isFilterTarget, !!hasFilterTargetAncestor),\n };\n },\n );\n } else {\n matchedDefinition = await matchFilters<InstanceKey>(\n definition,\n { filteredNodePaths, isDirectParentFilterTarget },\n async (id) => {\n if (!HierarchyNodeIdentifier.isInstanceNodeIdentifier(id)) {\n return false;\n }\n return this._classHierarchy.classDerivesFrom(id.className, definition.fullClassName);\n },\n (def, matchingFilters, isFilterTarget) =>\n applyECInstanceIdsFilter(def, matchingFilters, isFilterTarget, !!isDirectParentFilterTarget, !!hasFilterTargetAncestor),\n );\n }\n if (matchedDefinition) {\n filteredDefinitions.push(matchedDefinition);\n }\n }),\n );\n return filteredDefinitions;\n }\n\n private getFilteringProps(parentNode: Pick<HierarchyNode, \"filtering\"> | undefined) {\n if (!parentNode) {\n return { filteredNodePaths: this._nodeIdentifierPaths, isDirectParentFilterTarget: false, hasFilterTargetAncestor: false };\n }\n return {\n filteredNodePaths: parentNode.filtering?.filteredChildrenIdentifierPaths,\n isDirectParentFilterTarget: parentNode.filtering?.isFilterTarget,\n hasFilterTargetAncestor: !!parentNode.filtering?.hasFilterTargetAncestor,\n };\n }\n}\n\nasync function matchFilters<\n TIdentifier extends HierarchyNodeIdentifier,\n TDefinition = TIdentifier extends InstanceKey ? InstanceNodesQueryDefinition : CustomHierarchyNodeDefinition,\n>(\n definition: TDefinition,\n filteringProps: { filteredNodePaths: HierarchyNodeIdentifiersPath[]; isDirectParentFilterTarget?: boolean },\n predicate: (id: HierarchyNodeIdentifier) => Promise<boolean>,\n matchedDefinitionProcessor: (\n def: TDefinition,\n matchingFilters: Array<{ id: TIdentifier; childrenIdentifierPaths: HierarchyNodeIdentifiersPath[] }>,\n isFilterTarget: boolean,\n ) => TDefinition,\n): Promise<TDefinition | undefined> {\n const { filteredNodePaths, isDirectParentFilterTarget } = filteringProps;\n let isFilterTarget = false;\n const matchingFilters: Array<{ id: TIdentifier; childrenIdentifierPaths: HierarchyNodeIdentifiersPath[] }> = [];\n for (const path of filteredNodePaths) {\n if (path.length === 0) {\n continue;\n }\n const nodeId = path[0];\n if (await predicate(nodeId)) {\n let childrenIdentifierPaths = matchingFilters.find(({ id }) => HierarchyNodeIdentifier.equal(id, nodeId))?.childrenIdentifierPaths;\n if (!childrenIdentifierPaths) {\n childrenIdentifierPaths = [];\n matchingFilters.push({\n // ideally, `predicate` would act as a type guard to guarantee that `id` is `TIdentifier`, but at the moment\n // async type guards aren't supported\n id: nodeId as TIdentifier,\n childrenIdentifierPaths,\n });\n }\n const remainingPath = path.slice(1);\n if (remainingPath.length > 0) {\n childrenIdentifierPaths.push(remainingPath);\n } else {\n isFilterTarget = true;\n }\n }\n }\n if (isDirectParentFilterTarget || matchingFilters.length > 0) {\n return matchedDefinitionProcessor(definition, matchingFilters, isFilterTarget);\n }\n return undefined;\n}\n\nfunction applyFilterAttributes<TNode extends ParsedHierarchyNode>(\n node: TNode,\n filteredChildrenIdentifierPaths: HierarchyNodeIdentifiersPath[] | undefined,\n isFilterTarget: boolean,\n hasFilterTargetAncestor: boolean,\n): TNode {\n const shouldAutoExpand = !!filteredChildrenIdentifierPaths?.some((path) => !!path.length);\n const result = { ...node };\n if (shouldAutoExpand) {\n result.autoExpand = true;\n }\n if (isFilterTarget || hasFilterTargetAncestor || filteredChildrenIdentifierPaths?.length) {\n result.filtering = {\n ...(isFilterTarget ? { isFilterTarget } : undefined),\n ...(hasFilterTargetAncestor ? { hasFilterTargetAncestor } : undefined),\n ...(!!filteredChildrenIdentifierPaths?.length ? { filteredChildrenIdentifierPaths } : undefined),\n };\n }\n return result;\n}\n\n/** @internal */\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport const ECSQL_COLUMN_NAME_FilteredChildrenPaths = \"FilteredChildrenPaths\";\n\n/** @internal */\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport const ECSQL_COLUMN_NAME_IsFilterTarget = \"IsFilterTarget\";\n\n/** @internal */\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport const ECSQL_COLUMN_NAME_HasFilterTargetAncestor = \"HasFilterTargetAncestor\";\n\n/** @internal */\nexport function applyECInstanceIdsFilter(\n def: InstanceNodesQueryDefinition,\n matchingFilters: Array<{ id: InstanceKey; childrenIdentifierPaths: HierarchyNodeIdentifiersPath[] }>,\n isFilterTarget: boolean,\n isParentFilterTarget: boolean,\n hasFilterTargetAncestor: boolean,\n): InstanceNodesQueryDefinition {\n if (matchingFilters.length === 0) {\n return def;\n }\n return {\n ...def,\n query: {\n ...def.query,\n ctes: [\n ...(def.query.ctes ?? []),\n // note: generally we'd use `VALUES (1,1),(2,2)`, but that doesn't work in ECSQL (https://github.com/iTwin/itwinjs-backlog/issues/865),\n // so using UNION as a workaround\n `FilteringInfo(ECInstanceId, FilteredChildrenPaths) AS (\n ${matchingFilters\n .map(({ id: key, childrenIdentifierPaths }) => `VALUES (${key.id}, '${JSON.stringify(childrenIdentifierPaths)}')`)\n .join(\" UNION ALL \")}\n )`,\n ],\n ecsql: `\n SELECT\n [q].*,\n ${isFilterTarget ? \"1\" : \"0\"} AS [${ECSQL_COLUMN_NAME_IsFilterTarget}],\n ${hasFilterTargetAncestor || isParentFilterTarget ? \"1\" : \"0\"} AS [${ECSQL_COLUMN_NAME_HasFilterTargetAncestor}],\n [f].[FilteredChildrenPaths] AS [${ECSQL_COLUMN_NAME_FilteredChildrenPaths}]\n FROM (\n ${def.query.ecsql}\n ) [q]\n ${isParentFilterTarget ? \"LEFT \" : \"\"} JOIN FilteringInfo [f] ON [f].[ECInstanceId] = [q].[ECInstanceId]\n `,\n },\n };\n}\n"]}
1
+ {"version":3,"file":"FilteringHierarchyDefinition.js","sourceRoot":"","sources":["../../../../src/hierarchies/internal/FilteringHierarchyDefinition.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\nimport { ECClassHierarchyInspector, InstanceKey } from \"@itwin/presentation-shared\";\nimport {\n CustomHierarchyNodeDefinition,\n DefineHierarchyLevelProps,\n HierarchyDefinition,\n HierarchyLevelDefinition,\n HierarchyNodesDefinition,\n InstanceNodesQueryDefinition,\n NodeParser,\n NodePostProcessor,\n NodePreProcessor,\n} from \"../HierarchyDefinition\";\nimport { HierarchyNode, ParsedHierarchyNode, ParsedInstanceHierarchyNode, ProcessedHierarchyNode } from \"../HierarchyNode\";\nimport { HierarchyNodeIdentifier, HierarchyNodeIdentifiersPath } from \"../HierarchyNodeIdentifier\";\nimport { defaultNodesParser } from \"./TreeNodesReader\";\n\n/** @internal */\nexport interface FilteringQueryBuilderProps {\n classHierarchy: ECClassHierarchyInspector;\n source: HierarchyDefinition;\n nodeIdentifierPaths: HierarchyNodeIdentifiersPath[];\n}\n\n/** @internal */\nexport class FilteringHierarchyDefinition implements HierarchyDefinition {\n private _classHierarchy: ECClassHierarchyInspector;\n private _source: HierarchyDefinition;\n private _nodeIdentifierPaths: HierarchyNodeIdentifiersPath[];\n\n public constructor(props: FilteringQueryBuilderProps) {\n this._classHierarchy = props.classHierarchy;\n this._source = props.source;\n this._nodeIdentifierPaths = props.nodeIdentifierPaths;\n }\n\n public get preProcessNode(): NodePreProcessor {\n return async (node) => {\n const processedNode = this._source.preProcessNode ? await this._source.preProcessNode(node) : node;\n if (processedNode?.processingParams?.hideInHierarchy && processedNode.filtering?.isFilterTarget && !processedNode.filtering.hasFilterTargetAncestor) {\n // we want to hide target nodes if they have `hideInHierarchy` param, but only if they're not under another filter target\n return undefined;\n }\n return processedNode;\n };\n }\n\n public get postProcessNode(): NodePostProcessor {\n return async (node: ProcessedHierarchyNode) => {\n const processedNode = this._source.postProcessNode ? await this._source.postProcessNode(node) : node;\n if (\n // instance nodes get the auto-expand flag in `parseNode`, but grouping ones need to be handled during post-processing\n HierarchyNode.isClassGroupingNode(node) &&\n node.children.some(\n (child: ProcessedHierarchyNode) => child.filtering && (child.filtering.isFilterTarget || child.filtering.filteredChildrenIdentifierPaths),\n )\n ) {\n return Object.assign(processedNode, { autoExpand: true });\n }\n return processedNode;\n };\n }\n\n public get parseNode(): NodeParser {\n return (row: { [columnName: string]: any }): ParsedInstanceHierarchyNode => {\n const isFilterTarget: boolean = !!row[ECSQL_COLUMN_NAME_IsFilterTarget];\n const hasFilterTargetAncestor: boolean = !!row[ECSQL_COLUMN_NAME_HasFilterTargetAncestor];\n const parsedFilteredChildrenIdentifierPaths: HierarchyNodeIdentifiersPath[] | undefined = row[ECSQL_COLUMN_NAME_FilteredChildrenPaths]\n ? JSON.parse(row[ECSQL_COLUMN_NAME_FilteredChildrenPaths])\n : undefined;\n const defaultNode = (this._source.parseNode ?? defaultNodesParser)(row);\n return applyFilterAttributes(defaultNode, parsedFilteredChildrenIdentifierPaths, isFilterTarget, hasFilterTargetAncestor);\n };\n }\n\n public async defineHierarchyLevel(props: DefineHierarchyLevelProps): Promise<HierarchyLevelDefinition> {\n const sourceDefinitions = await this._source.defineHierarchyLevel(props);\n const { filteredNodePaths, isDirectParentFilterTarget, hasFilterTargetAncestor } = this.getFilteringProps(props.parentNode);\n if (!filteredNodePaths) {\n return sourceDefinitions;\n }\n\n const filteredDefinitions: HierarchyLevelDefinition = [];\n await Promise.all(\n sourceDefinitions.map(async (definition) => {\n let matchedDefinition: HierarchyNodesDefinition | undefined;\n if (HierarchyNodesDefinition.isCustomNode(definition)) {\n matchedDefinition = await matchFilters<{ key: string }>(\n definition,\n { filteredNodePaths, isDirectParentFilterTarget },\n async (id) => {\n if (!HierarchyNodeIdentifier.isCustomNodeIdentifier(id)) {\n return false;\n }\n return id.key === definition.node.key;\n },\n this._classHierarchy,\n (def, matchingFilters, isFilterTarget) => {\n const filteredChildrenIdentifierPaths = matchingFilters.reduce(\n (r, c) => [...r, ...c.childrenIdentifierPaths],\n new Array<HierarchyNodeIdentifiersPath>(),\n );\n return {\n ...def,\n node: applyFilterAttributes(def.node, filteredChildrenIdentifierPaths, isFilterTarget, !!hasFilterTargetAncestor),\n };\n },\n );\n } else {\n matchedDefinition = await matchFilters<InstanceKey>(\n definition,\n { filteredNodePaths, isDirectParentFilterTarget },\n async (id) => {\n if (!HierarchyNodeIdentifier.isInstanceNodeIdentifier(id)) {\n return false;\n }\n return this._classHierarchy.classDerivesFrom(id.className, definition.fullClassName);\n },\n this._classHierarchy,\n (def, matchingFilters, isFilterTarget) =>\n applyECInstanceIdsFilter(def, matchingFilters, isFilterTarget, !!isDirectParentFilterTarget, !!hasFilterTargetAncestor),\n );\n }\n if (matchedDefinition) {\n filteredDefinitions.push(matchedDefinition);\n }\n }),\n );\n return filteredDefinitions;\n }\n\n private getFilteringProps(parentNode: Pick<HierarchyNode, \"filtering\"> | undefined) {\n if (!parentNode) {\n return { filteredNodePaths: this._nodeIdentifierPaths, isDirectParentFilterTarget: false, hasFilterTargetAncestor: false };\n }\n return {\n filteredNodePaths: parentNode.filtering?.filteredChildrenIdentifierPaths,\n isDirectParentFilterTarget: parentNode.filtering?.isFilterTarget,\n hasFilterTargetAncestor: !!parentNode.filtering?.hasFilterTargetAncestor,\n };\n }\n}\n\nasync function matchFilters<\n TIdentifier extends HierarchyNodeIdentifier,\n TDefinition = TIdentifier extends InstanceKey ? InstanceNodesQueryDefinition : CustomHierarchyNodeDefinition,\n>(\n definition: TDefinition,\n filteringProps: { filteredNodePaths: HierarchyNodeIdentifiersPath[]; isDirectParentFilterTarget?: boolean },\n predicate: (id: HierarchyNodeIdentifier) => Promise<boolean>,\n classHierarchy: ECClassHierarchyInspector,\n matchedDefinitionProcessor: (\n def: TDefinition,\n matchingFilters: Array<{ id: TIdentifier; childrenIdentifierPaths: HierarchyNodeIdentifiersPath[] }>,\n isFilterTarget: boolean,\n ) => TDefinition,\n): Promise<TDefinition | undefined> {\n const { filteredNodePaths, isDirectParentFilterTarget } = filteringProps;\n let isFilterTarget = false;\n const matchingFilters: Array<{ id: TIdentifier; childrenIdentifierPaths: HierarchyNodeIdentifiersPath[] }> = [];\n for (const path of filteredNodePaths) {\n if (path.length === 0) {\n continue;\n }\n const nodeId = path[0];\n if (await predicate(nodeId)) {\n let childrenIdentifierPaths = await findChildrenIdentifierPaths(matchingFilters, nodeId, classHierarchy);\n if (!childrenIdentifierPaths) {\n childrenIdentifierPaths = [];\n matchingFilters.push({\n // ideally, `predicate` would act as a type guard to guarantee that `id` is `TIdentifier`, but at the moment\n // async type guards aren't supported\n id: nodeId as TIdentifier,\n childrenIdentifierPaths,\n });\n }\n const remainingPath = path.slice(1);\n if (remainingPath.length > 0) {\n childrenIdentifierPaths.push(remainingPath);\n } else {\n isFilterTarget = true;\n }\n }\n }\n if (isDirectParentFilterTarget || matchingFilters.length > 0) {\n return matchedDefinitionProcessor(definition, matchingFilters, isFilterTarget);\n }\n return undefined;\n}\n\nasync function findChildrenIdentifierPaths<TIdentifier extends HierarchyNodeIdentifier>(\n filters: Array<{ id: TIdentifier; childrenIdentifierPaths: HierarchyNodeIdentifiersPath[] }>,\n nodeId: TIdentifier,\n classHierarchy: ECClassHierarchyInspector,\n) {\n for (const filter of filters) {\n if (await identifiersEqual(filter.id, nodeId, classHierarchy)) {\n return filter.childrenIdentifierPaths;\n }\n }\n return undefined;\n}\n\nasync function identifiersEqual<TIdentifier extends HierarchyNodeIdentifier>(lhs: TIdentifier, rhs: TIdentifier, classHierarchy: ECClassHierarchyInspector) {\n if (HierarchyNodeIdentifier.isInstanceNodeIdentifier(lhs) && HierarchyNodeIdentifier.isInstanceNodeIdentifier(rhs)) {\n return (\n lhs.id === rhs.id &&\n (lhs.className === rhs.className ||\n (await classHierarchy.classDerivesFrom(lhs.className, rhs.className)) ||\n (await classHierarchy.classDerivesFrom(rhs.className, lhs.className)))\n );\n }\n return HierarchyNodeIdentifier.equal(lhs, rhs);\n}\n\nfunction applyFilterAttributes<TNode extends ParsedHierarchyNode>(\n node: TNode,\n filteredChildrenIdentifierPaths: HierarchyNodeIdentifiersPath[] | undefined,\n isFilterTarget: boolean,\n hasFilterTargetAncestor: boolean,\n): TNode {\n const shouldAutoExpand = !!filteredChildrenIdentifierPaths?.some((path) => !!path.length);\n const result = { ...node };\n if (shouldAutoExpand) {\n result.autoExpand = true;\n }\n if (isFilterTarget || hasFilterTargetAncestor || filteredChildrenIdentifierPaths?.length) {\n result.filtering = {\n ...(isFilterTarget ? { isFilterTarget } : undefined),\n ...(hasFilterTargetAncestor ? { hasFilterTargetAncestor } : undefined),\n ...(!!filteredChildrenIdentifierPaths?.length ? { filteredChildrenIdentifierPaths } : undefined),\n };\n }\n return result;\n}\n\n/** @internal */\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport const ECSQL_COLUMN_NAME_FilteredChildrenPaths = \"FilteredChildrenPaths\";\n\n/** @internal */\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport const ECSQL_COLUMN_NAME_IsFilterTarget = \"IsFilterTarget\";\n\n/** @internal */\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport const ECSQL_COLUMN_NAME_HasFilterTargetAncestor = \"HasFilterTargetAncestor\";\n\n/** @internal */\nexport function applyECInstanceIdsFilter(\n def: InstanceNodesQueryDefinition,\n matchingFilters: Array<{ id: InstanceKey; childrenIdentifierPaths: HierarchyNodeIdentifiersPath[] }>,\n isFilterTarget: boolean,\n isParentFilterTarget: boolean,\n hasFilterTargetAncestor: boolean,\n): InstanceNodesQueryDefinition {\n if (matchingFilters.length === 0) {\n return def;\n }\n return {\n ...def,\n query: {\n ...def.query,\n ctes: [\n ...(def.query.ctes ?? []),\n // note: generally we'd use `VALUES (1,1),(2,2)`, but that doesn't work in ECSQL (https://github.com/iTwin/itwinjs-backlog/issues/865),\n // so using UNION as a workaround\n `FilteringInfo(ECInstanceId, FilteredChildrenPaths) AS (\n ${matchingFilters\n .map(({ id: key, childrenIdentifierPaths }) => `VALUES (${key.id}, '${JSON.stringify(childrenIdentifierPaths)}')`)\n .join(\" UNION ALL \")}\n )`,\n ],\n ecsql: `\n SELECT\n [q].*,\n ${isFilterTarget ? \"1\" : \"0\"} AS [${ECSQL_COLUMN_NAME_IsFilterTarget}],\n ${hasFilterTargetAncestor || isParentFilterTarget ? \"1\" : \"0\"} AS [${ECSQL_COLUMN_NAME_HasFilterTargetAncestor}],\n [f].[FilteredChildrenPaths] AS [${ECSQL_COLUMN_NAME_FilteredChildrenPaths}]\n FROM (\n ${def.query.ecsql}\n ) [q]\n ${isParentFilterTarget ? \"LEFT \" : \"\"} JOIN FilteringInfo [f] ON [f].[ECInstanceId] = [q].[ECInstanceId]\n `,\n },\n };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"FilteringHierarchyDefinition.d.ts","sourceRoot":"","sources":["../../../../src/hierarchies/internal/FilteringHierarchyDefinition.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,yBAAyB,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACpF,OAAO,EAEL,yBAAyB,EACzB,mBAAmB,EACnB,wBAAwB,EAExB,4BAA4B,EAC5B,UAAU,EACV,iBAAiB,EACjB,gBAAgB,EACjB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAA2B,4BAA4B,EAAE,MAAM,4BAA4B,CAAC;AAGnG,gBAAgB;AAChB,MAAM,WAAW,0BAA0B;IACzC,cAAc,EAAE,yBAAyB,CAAC;IAC1C,MAAM,EAAE,mBAAmB,CAAC;IAC5B,mBAAmB,EAAE,4BAA4B,EAAE,CAAC;CACrD;AAED,gBAAgB;AAChB,qBAAa,4BAA6B,YAAW,mBAAmB;IACtE,OAAO,CAAC,eAAe,CAA4B;IACnD,OAAO,CAAC,OAAO,CAAsB;IACrC,OAAO,CAAC,oBAAoB,CAAiC;gBAE1C,KAAK,EAAE,0BAA0B;IAMpD,IAAW,cAAc,IAAI,gBAAgB,CAS5C;IAED,IAAW,eAAe,IAAI,iBAAiB,CAc9C;IAED,IAAW,SAAS,IAAI,UAAU,CAUjC;IAEY,oBAAoB,CAAC,KAAK,EAAE,yBAAyB,GAAG,OAAO,CAAC,wBAAwB,CAAC;IAsDtG,OAAO,CAAC,iBAAiB;CAU1B;AAqED,gBAAgB;AAEhB,eAAO,MAAM,uCAAuC,0BAA0B,CAAC;AAE/E,gBAAgB;AAEhB,eAAO,MAAM,gCAAgC,mBAAmB,CAAC;AAEjE,gBAAgB;AAEhB,eAAO,MAAM,yCAAyC,4BAA4B,CAAC;AAEnF,gBAAgB;AAChB,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,4BAA4B,EACjC,eAAe,EAAE,KAAK,CAAC;IAAE,EAAE,EAAE,WAAW,CAAC;IAAC,uBAAuB,EAAE,4BAA4B,EAAE,CAAA;CAAE,CAAC,EACpG,cAAc,EAAE,OAAO,EACvB,oBAAoB,EAAE,OAAO,EAC7B,uBAAuB,EAAE,OAAO,GAC/B,4BAA4B,CA+B9B"}
1
+ {"version":3,"file":"FilteringHierarchyDefinition.d.ts","sourceRoot":"","sources":["../../../../src/hierarchies/internal/FilteringHierarchyDefinition.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,yBAAyB,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACpF,OAAO,EAEL,yBAAyB,EACzB,mBAAmB,EACnB,wBAAwB,EAExB,4BAA4B,EAC5B,UAAU,EACV,iBAAiB,EACjB,gBAAgB,EACjB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAA2B,4BAA4B,EAAE,MAAM,4BAA4B,CAAC;AAGnG,gBAAgB;AAChB,MAAM,WAAW,0BAA0B;IACzC,cAAc,EAAE,yBAAyB,CAAC;IAC1C,MAAM,EAAE,mBAAmB,CAAC;IAC5B,mBAAmB,EAAE,4BAA4B,EAAE,CAAC;CACrD;AAED,gBAAgB;AAChB,qBAAa,4BAA6B,YAAW,mBAAmB;IACtE,OAAO,CAAC,eAAe,CAA4B;IACnD,OAAO,CAAC,OAAO,CAAsB;IACrC,OAAO,CAAC,oBAAoB,CAAiC;gBAE1C,KAAK,EAAE,0BAA0B;IAMpD,IAAW,cAAc,IAAI,gBAAgB,CAS5C;IAED,IAAW,eAAe,IAAI,iBAAiB,CAc9C;IAED,IAAW,SAAS,IAAI,UAAU,CAUjC;IAEY,oBAAoB,CAAC,KAAK,EAAE,yBAAyB,GAAG,OAAO,CAAC,wBAAwB,CAAC;IAwDtG,OAAO,CAAC,iBAAiB;CAU1B;AA+FD,gBAAgB;AAEhB,eAAO,MAAM,uCAAuC,0BAA0B,CAAC;AAE/E,gBAAgB;AAEhB,eAAO,MAAM,gCAAgC,mBAAmB,CAAC;AAEjE,gBAAgB;AAEhB,eAAO,MAAM,yCAAyC,4BAA4B,CAAC;AAEnF,gBAAgB;AAChB,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,4BAA4B,EACjC,eAAe,EAAE,KAAK,CAAC;IAAE,EAAE,EAAE,WAAW,CAAC;IAAC,uBAAuB,EAAE,4BAA4B,EAAE,CAAA;CAAE,CAAC,EACpG,cAAc,EAAE,OAAO,EACvB,oBAAoB,EAAE,OAAO,EAC7B,uBAAuB,EAAE,OAAO,GAC/B,4BAA4B,CA+B9B"}
@@ -64,7 +64,7 @@ export class FilteringHierarchyDefinition {
64
64
  return false;
65
65
  }
66
66
  return id.key === definition.node.key;
67
- }, (def, matchingFilters, isFilterTarget) => {
67
+ }, this._classHierarchy, (def, matchingFilters, isFilterTarget) => {
68
68
  const filteredChildrenIdentifierPaths = matchingFilters.reduce((r, c) => [...r, ...c.childrenIdentifierPaths], new Array());
69
69
  return {
70
70
  ...def,
@@ -78,7 +78,7 @@ export class FilteringHierarchyDefinition {
78
78
  return false;
79
79
  }
80
80
  return this._classHierarchy.classDerivesFrom(id.className, definition.fullClassName);
81
- }, (def, matchingFilters, isFilterTarget) => applyECInstanceIdsFilter(def, matchingFilters, isFilterTarget, !!isDirectParentFilterTarget, !!hasFilterTargetAncestor));
81
+ }, this._classHierarchy, (def, matchingFilters, isFilterTarget) => applyECInstanceIdsFilter(def, matchingFilters, isFilterTarget, !!isDirectParentFilterTarget, !!hasFilterTargetAncestor));
82
82
  }
83
83
  if (matchedDefinition) {
84
84
  filteredDefinitions.push(matchedDefinition);
@@ -97,7 +97,7 @@ export class FilteringHierarchyDefinition {
97
97
  };
98
98
  }
99
99
  }
100
- async function matchFilters(definition, filteringProps, predicate, matchedDefinitionProcessor) {
100
+ async function matchFilters(definition, filteringProps, predicate, classHierarchy, matchedDefinitionProcessor) {
101
101
  const { filteredNodePaths, isDirectParentFilterTarget } = filteringProps;
102
102
  let isFilterTarget = false;
103
103
  const matchingFilters = [];
@@ -107,7 +107,7 @@ async function matchFilters(definition, filteringProps, predicate, matchedDefini
107
107
  }
108
108
  const nodeId = path[0];
109
109
  if (await predicate(nodeId)) {
110
- let childrenIdentifierPaths = matchingFilters.find(({ id }) => HierarchyNodeIdentifier.equal(id, nodeId))?.childrenIdentifierPaths;
110
+ let childrenIdentifierPaths = await findChildrenIdentifierPaths(matchingFilters, nodeId, classHierarchy);
111
111
  if (!childrenIdentifierPaths) {
112
112
  childrenIdentifierPaths = [];
113
113
  matchingFilters.push({
@@ -131,6 +131,23 @@ async function matchFilters(definition, filteringProps, predicate, matchedDefini
131
131
  }
132
132
  return undefined;
133
133
  }
134
+ async function findChildrenIdentifierPaths(filters, nodeId, classHierarchy) {
135
+ for (const filter of filters) {
136
+ if (await identifiersEqual(filter.id, nodeId, classHierarchy)) {
137
+ return filter.childrenIdentifierPaths;
138
+ }
139
+ }
140
+ return undefined;
141
+ }
142
+ async function identifiersEqual(lhs, rhs, classHierarchy) {
143
+ if (HierarchyNodeIdentifier.isInstanceNodeIdentifier(lhs) && HierarchyNodeIdentifier.isInstanceNodeIdentifier(rhs)) {
144
+ return (lhs.id === rhs.id &&
145
+ (lhs.className === rhs.className ||
146
+ (await classHierarchy.classDerivesFrom(lhs.className, rhs.className)) ||
147
+ (await classHierarchy.classDerivesFrom(rhs.className, lhs.className))));
148
+ }
149
+ return HierarchyNodeIdentifier.equal(lhs, rhs);
150
+ }
134
151
  function applyFilterAttributes(node, filteredChildrenIdentifierPaths, isFilterTarget, hasFilterTargetAncestor) {
135
152
  const shouldAutoExpand = !!filteredChildrenIdentifierPaths?.some((path) => !!path.length);
136
153
  const result = { ...node };
@@ -1 +1 @@
1
- {"version":3,"file":"FilteringHierarchyDefinition.js","sourceRoot":"","sources":["../../../../src/hierarchies/internal/FilteringHierarchyDefinition.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\nimport { ECClassHierarchyInspector, InstanceKey } from \"@itwin/presentation-shared\";\nimport {\n CustomHierarchyNodeDefinition,\n DefineHierarchyLevelProps,\n HierarchyDefinition,\n HierarchyLevelDefinition,\n HierarchyNodesDefinition,\n InstanceNodesQueryDefinition,\n NodeParser,\n NodePostProcessor,\n NodePreProcessor,\n} from \"../HierarchyDefinition\";\nimport { HierarchyNode, ParsedHierarchyNode, ParsedInstanceHierarchyNode, ProcessedHierarchyNode } from \"../HierarchyNode\";\nimport { HierarchyNodeIdentifier, HierarchyNodeIdentifiersPath } from \"../HierarchyNodeIdentifier\";\nimport { defaultNodesParser } from \"./TreeNodesReader\";\n\n/** @internal */\nexport interface FilteringQueryBuilderProps {\n classHierarchy: ECClassHierarchyInspector;\n source: HierarchyDefinition;\n nodeIdentifierPaths: HierarchyNodeIdentifiersPath[];\n}\n\n/** @internal */\nexport class FilteringHierarchyDefinition implements HierarchyDefinition {\n private _classHierarchy: ECClassHierarchyInspector;\n private _source: HierarchyDefinition;\n private _nodeIdentifierPaths: HierarchyNodeIdentifiersPath[];\n\n public constructor(props: FilteringQueryBuilderProps) {\n this._classHierarchy = props.classHierarchy;\n this._source = props.source;\n this._nodeIdentifierPaths = props.nodeIdentifierPaths;\n }\n\n public get preProcessNode(): NodePreProcessor {\n return async (node) => {\n const processedNode = this._source.preProcessNode ? await this._source.preProcessNode(node) : node;\n if (processedNode?.processingParams?.hideInHierarchy && processedNode.filtering?.isFilterTarget && !processedNode.filtering.hasFilterTargetAncestor) {\n // we want to hide target nodes if they have `hideInHierarchy` param, but only if they're not under another filter target\n return undefined;\n }\n return processedNode;\n };\n }\n\n public get postProcessNode(): NodePostProcessor {\n return async (node: ProcessedHierarchyNode) => {\n const processedNode = this._source.postProcessNode ? await this._source.postProcessNode(node) : node;\n if (\n // instance nodes get the auto-expand flag in `parseNode`, but grouping ones need to be handled during post-processing\n HierarchyNode.isClassGroupingNode(node) &&\n node.children.some(\n (child: ProcessedHierarchyNode) => child.filtering && (child.filtering.isFilterTarget || child.filtering.filteredChildrenIdentifierPaths),\n )\n ) {\n return Object.assign(processedNode, { autoExpand: true });\n }\n return processedNode;\n };\n }\n\n public get parseNode(): NodeParser {\n return (row: { [columnName: string]: any }): ParsedInstanceHierarchyNode => {\n const isFilterTarget: boolean = !!row[ECSQL_COLUMN_NAME_IsFilterTarget];\n const hasFilterTargetAncestor: boolean = !!row[ECSQL_COLUMN_NAME_HasFilterTargetAncestor];\n const parsedFilteredChildrenIdentifierPaths: HierarchyNodeIdentifiersPath[] | undefined = row[ECSQL_COLUMN_NAME_FilteredChildrenPaths]\n ? JSON.parse(row[ECSQL_COLUMN_NAME_FilteredChildrenPaths])\n : undefined;\n const defaultNode = (this._source.parseNode ?? defaultNodesParser)(row);\n return applyFilterAttributes(defaultNode, parsedFilteredChildrenIdentifierPaths, isFilterTarget, hasFilterTargetAncestor);\n };\n }\n\n public async defineHierarchyLevel(props: DefineHierarchyLevelProps): Promise<HierarchyLevelDefinition> {\n const sourceDefinitions = await this._source.defineHierarchyLevel(props);\n const { filteredNodePaths, isDirectParentFilterTarget, hasFilterTargetAncestor } = this.getFilteringProps(props.parentNode);\n if (!filteredNodePaths) {\n return sourceDefinitions;\n }\n\n const filteredDefinitions: HierarchyLevelDefinition = [];\n await Promise.all(\n sourceDefinitions.map(async (definition) => {\n let matchedDefinition: HierarchyNodesDefinition | undefined;\n if (HierarchyNodesDefinition.isCustomNode(definition)) {\n matchedDefinition = await matchFilters<{ key: string }>(\n definition,\n { filteredNodePaths, isDirectParentFilterTarget },\n async (id) => {\n if (!HierarchyNodeIdentifier.isCustomNodeIdentifier(id)) {\n return false;\n }\n return id.key === definition.node.key;\n },\n (def, matchingFilters, isFilterTarget) => {\n const filteredChildrenIdentifierPaths = matchingFilters.reduce(\n (r, c) => [...r, ...c.childrenIdentifierPaths],\n new Array<HierarchyNodeIdentifiersPath>(),\n );\n return {\n ...def,\n node: applyFilterAttributes(def.node, filteredChildrenIdentifierPaths, isFilterTarget, !!hasFilterTargetAncestor),\n };\n },\n );\n } else {\n matchedDefinition = await matchFilters<InstanceKey>(\n definition,\n { filteredNodePaths, isDirectParentFilterTarget },\n async (id) => {\n if (!HierarchyNodeIdentifier.isInstanceNodeIdentifier(id)) {\n return false;\n }\n return this._classHierarchy.classDerivesFrom(id.className, definition.fullClassName);\n },\n (def, matchingFilters, isFilterTarget) =>\n applyECInstanceIdsFilter(def, matchingFilters, isFilterTarget, !!isDirectParentFilterTarget, !!hasFilterTargetAncestor),\n );\n }\n if (matchedDefinition) {\n filteredDefinitions.push(matchedDefinition);\n }\n }),\n );\n return filteredDefinitions;\n }\n\n private getFilteringProps(parentNode: Pick<HierarchyNode, \"filtering\"> | undefined) {\n if (!parentNode) {\n return { filteredNodePaths: this._nodeIdentifierPaths, isDirectParentFilterTarget: false, hasFilterTargetAncestor: false };\n }\n return {\n filteredNodePaths: parentNode.filtering?.filteredChildrenIdentifierPaths,\n isDirectParentFilterTarget: parentNode.filtering?.isFilterTarget,\n hasFilterTargetAncestor: !!parentNode.filtering?.hasFilterTargetAncestor,\n };\n }\n}\n\nasync function matchFilters<\n TIdentifier extends HierarchyNodeIdentifier,\n TDefinition = TIdentifier extends InstanceKey ? InstanceNodesQueryDefinition : CustomHierarchyNodeDefinition,\n>(\n definition: TDefinition,\n filteringProps: { filteredNodePaths: HierarchyNodeIdentifiersPath[]; isDirectParentFilterTarget?: boolean },\n predicate: (id: HierarchyNodeIdentifier) => Promise<boolean>,\n matchedDefinitionProcessor: (\n def: TDefinition,\n matchingFilters: Array<{ id: TIdentifier; childrenIdentifierPaths: HierarchyNodeIdentifiersPath[] }>,\n isFilterTarget: boolean,\n ) => TDefinition,\n): Promise<TDefinition | undefined> {\n const { filteredNodePaths, isDirectParentFilterTarget } = filteringProps;\n let isFilterTarget = false;\n const matchingFilters: Array<{ id: TIdentifier; childrenIdentifierPaths: HierarchyNodeIdentifiersPath[] }> = [];\n for (const path of filteredNodePaths) {\n if (path.length === 0) {\n continue;\n }\n const nodeId = path[0];\n if (await predicate(nodeId)) {\n let childrenIdentifierPaths = matchingFilters.find(({ id }) => HierarchyNodeIdentifier.equal(id, nodeId))?.childrenIdentifierPaths;\n if (!childrenIdentifierPaths) {\n childrenIdentifierPaths = [];\n matchingFilters.push({\n // ideally, `predicate` would act as a type guard to guarantee that `id` is `TIdentifier`, but at the moment\n // async type guards aren't supported\n id: nodeId as TIdentifier,\n childrenIdentifierPaths,\n });\n }\n const remainingPath = path.slice(1);\n if (remainingPath.length > 0) {\n childrenIdentifierPaths.push(remainingPath);\n } else {\n isFilterTarget = true;\n }\n }\n }\n if (isDirectParentFilterTarget || matchingFilters.length > 0) {\n return matchedDefinitionProcessor(definition, matchingFilters, isFilterTarget);\n }\n return undefined;\n}\n\nfunction applyFilterAttributes<TNode extends ParsedHierarchyNode>(\n node: TNode,\n filteredChildrenIdentifierPaths: HierarchyNodeIdentifiersPath[] | undefined,\n isFilterTarget: boolean,\n hasFilterTargetAncestor: boolean,\n): TNode {\n const shouldAutoExpand = !!filteredChildrenIdentifierPaths?.some((path) => !!path.length);\n const result = { ...node };\n if (shouldAutoExpand) {\n result.autoExpand = true;\n }\n if (isFilterTarget || hasFilterTargetAncestor || filteredChildrenIdentifierPaths?.length) {\n result.filtering = {\n ...(isFilterTarget ? { isFilterTarget } : undefined),\n ...(hasFilterTargetAncestor ? { hasFilterTargetAncestor } : undefined),\n ...(!!filteredChildrenIdentifierPaths?.length ? { filteredChildrenIdentifierPaths } : undefined),\n };\n }\n return result;\n}\n\n/** @internal */\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport const ECSQL_COLUMN_NAME_FilteredChildrenPaths = \"FilteredChildrenPaths\";\n\n/** @internal */\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport const ECSQL_COLUMN_NAME_IsFilterTarget = \"IsFilterTarget\";\n\n/** @internal */\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport const ECSQL_COLUMN_NAME_HasFilterTargetAncestor = \"HasFilterTargetAncestor\";\n\n/** @internal */\nexport function applyECInstanceIdsFilter(\n def: InstanceNodesQueryDefinition,\n matchingFilters: Array<{ id: InstanceKey; childrenIdentifierPaths: HierarchyNodeIdentifiersPath[] }>,\n isFilterTarget: boolean,\n isParentFilterTarget: boolean,\n hasFilterTargetAncestor: boolean,\n): InstanceNodesQueryDefinition {\n if (matchingFilters.length === 0) {\n return def;\n }\n return {\n ...def,\n query: {\n ...def.query,\n ctes: [\n ...(def.query.ctes ?? []),\n // note: generally we'd use `VALUES (1,1),(2,2)`, but that doesn't work in ECSQL (https://github.com/iTwin/itwinjs-backlog/issues/865),\n // so using UNION as a workaround\n `FilteringInfo(ECInstanceId, FilteredChildrenPaths) AS (\n ${matchingFilters\n .map(({ id: key, childrenIdentifierPaths }) => `VALUES (${key.id}, '${JSON.stringify(childrenIdentifierPaths)}')`)\n .join(\" UNION ALL \")}\n )`,\n ],\n ecsql: `\n SELECT\n [q].*,\n ${isFilterTarget ? \"1\" : \"0\"} AS [${ECSQL_COLUMN_NAME_IsFilterTarget}],\n ${hasFilterTargetAncestor || isParentFilterTarget ? \"1\" : \"0\"} AS [${ECSQL_COLUMN_NAME_HasFilterTargetAncestor}],\n [f].[FilteredChildrenPaths] AS [${ECSQL_COLUMN_NAME_FilteredChildrenPaths}]\n FROM (\n ${def.query.ecsql}\n ) [q]\n ${isParentFilterTarget ? \"LEFT \" : \"\"} JOIN FilteringInfo [f] ON [f].[ECInstanceId] = [q].[ECInstanceId]\n `,\n },\n };\n}\n"]}
1
+ {"version":3,"file":"FilteringHierarchyDefinition.js","sourceRoot":"","sources":["../../../../src/hierarchies/internal/FilteringHierarchyDefinition.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\nimport { ECClassHierarchyInspector, InstanceKey } from \"@itwin/presentation-shared\";\nimport {\n CustomHierarchyNodeDefinition,\n DefineHierarchyLevelProps,\n HierarchyDefinition,\n HierarchyLevelDefinition,\n HierarchyNodesDefinition,\n InstanceNodesQueryDefinition,\n NodeParser,\n NodePostProcessor,\n NodePreProcessor,\n} from \"../HierarchyDefinition\";\nimport { HierarchyNode, ParsedHierarchyNode, ParsedInstanceHierarchyNode, ProcessedHierarchyNode } from \"../HierarchyNode\";\nimport { HierarchyNodeIdentifier, HierarchyNodeIdentifiersPath } from \"../HierarchyNodeIdentifier\";\nimport { defaultNodesParser } from \"./TreeNodesReader\";\n\n/** @internal */\nexport interface FilteringQueryBuilderProps {\n classHierarchy: ECClassHierarchyInspector;\n source: HierarchyDefinition;\n nodeIdentifierPaths: HierarchyNodeIdentifiersPath[];\n}\n\n/** @internal */\nexport class FilteringHierarchyDefinition implements HierarchyDefinition {\n private _classHierarchy: ECClassHierarchyInspector;\n private _source: HierarchyDefinition;\n private _nodeIdentifierPaths: HierarchyNodeIdentifiersPath[];\n\n public constructor(props: FilteringQueryBuilderProps) {\n this._classHierarchy = props.classHierarchy;\n this._source = props.source;\n this._nodeIdentifierPaths = props.nodeIdentifierPaths;\n }\n\n public get preProcessNode(): NodePreProcessor {\n return async (node) => {\n const processedNode = this._source.preProcessNode ? await this._source.preProcessNode(node) : node;\n if (processedNode?.processingParams?.hideInHierarchy && processedNode.filtering?.isFilterTarget && !processedNode.filtering.hasFilterTargetAncestor) {\n // we want to hide target nodes if they have `hideInHierarchy` param, but only if they're not under another filter target\n return undefined;\n }\n return processedNode;\n };\n }\n\n public get postProcessNode(): NodePostProcessor {\n return async (node: ProcessedHierarchyNode) => {\n const processedNode = this._source.postProcessNode ? await this._source.postProcessNode(node) : node;\n if (\n // instance nodes get the auto-expand flag in `parseNode`, but grouping ones need to be handled during post-processing\n HierarchyNode.isClassGroupingNode(node) &&\n node.children.some(\n (child: ProcessedHierarchyNode) => child.filtering && (child.filtering.isFilterTarget || child.filtering.filteredChildrenIdentifierPaths),\n )\n ) {\n return Object.assign(processedNode, { autoExpand: true });\n }\n return processedNode;\n };\n }\n\n public get parseNode(): NodeParser {\n return (row: { [columnName: string]: any }): ParsedInstanceHierarchyNode => {\n const isFilterTarget: boolean = !!row[ECSQL_COLUMN_NAME_IsFilterTarget];\n const hasFilterTargetAncestor: boolean = !!row[ECSQL_COLUMN_NAME_HasFilterTargetAncestor];\n const parsedFilteredChildrenIdentifierPaths: HierarchyNodeIdentifiersPath[] | undefined = row[ECSQL_COLUMN_NAME_FilteredChildrenPaths]\n ? JSON.parse(row[ECSQL_COLUMN_NAME_FilteredChildrenPaths])\n : undefined;\n const defaultNode = (this._source.parseNode ?? defaultNodesParser)(row);\n return applyFilterAttributes(defaultNode, parsedFilteredChildrenIdentifierPaths, isFilterTarget, hasFilterTargetAncestor);\n };\n }\n\n public async defineHierarchyLevel(props: DefineHierarchyLevelProps): Promise<HierarchyLevelDefinition> {\n const sourceDefinitions = await this._source.defineHierarchyLevel(props);\n const { filteredNodePaths, isDirectParentFilterTarget, hasFilterTargetAncestor } = this.getFilteringProps(props.parentNode);\n if (!filteredNodePaths) {\n return sourceDefinitions;\n }\n\n const filteredDefinitions: HierarchyLevelDefinition = [];\n await Promise.all(\n sourceDefinitions.map(async (definition) => {\n let matchedDefinition: HierarchyNodesDefinition | undefined;\n if (HierarchyNodesDefinition.isCustomNode(definition)) {\n matchedDefinition = await matchFilters<{ key: string }>(\n definition,\n { filteredNodePaths, isDirectParentFilterTarget },\n async (id) => {\n if (!HierarchyNodeIdentifier.isCustomNodeIdentifier(id)) {\n return false;\n }\n return id.key === definition.node.key;\n },\n this._classHierarchy,\n (def, matchingFilters, isFilterTarget) => {\n const filteredChildrenIdentifierPaths = matchingFilters.reduce(\n (r, c) => [...r, ...c.childrenIdentifierPaths],\n new Array<HierarchyNodeIdentifiersPath>(),\n );\n return {\n ...def,\n node: applyFilterAttributes(def.node, filteredChildrenIdentifierPaths, isFilterTarget, !!hasFilterTargetAncestor),\n };\n },\n );\n } else {\n matchedDefinition = await matchFilters<InstanceKey>(\n definition,\n { filteredNodePaths, isDirectParentFilterTarget },\n async (id) => {\n if (!HierarchyNodeIdentifier.isInstanceNodeIdentifier(id)) {\n return false;\n }\n return this._classHierarchy.classDerivesFrom(id.className, definition.fullClassName);\n },\n this._classHierarchy,\n (def, matchingFilters, isFilterTarget) =>\n applyECInstanceIdsFilter(def, matchingFilters, isFilterTarget, !!isDirectParentFilterTarget, !!hasFilterTargetAncestor),\n );\n }\n if (matchedDefinition) {\n filteredDefinitions.push(matchedDefinition);\n }\n }),\n );\n return filteredDefinitions;\n }\n\n private getFilteringProps(parentNode: Pick<HierarchyNode, \"filtering\"> | undefined) {\n if (!parentNode) {\n return { filteredNodePaths: this._nodeIdentifierPaths, isDirectParentFilterTarget: false, hasFilterTargetAncestor: false };\n }\n return {\n filteredNodePaths: parentNode.filtering?.filteredChildrenIdentifierPaths,\n isDirectParentFilterTarget: parentNode.filtering?.isFilterTarget,\n hasFilterTargetAncestor: !!parentNode.filtering?.hasFilterTargetAncestor,\n };\n }\n}\n\nasync function matchFilters<\n TIdentifier extends HierarchyNodeIdentifier,\n TDefinition = TIdentifier extends InstanceKey ? InstanceNodesQueryDefinition : CustomHierarchyNodeDefinition,\n>(\n definition: TDefinition,\n filteringProps: { filteredNodePaths: HierarchyNodeIdentifiersPath[]; isDirectParentFilterTarget?: boolean },\n predicate: (id: HierarchyNodeIdentifier) => Promise<boolean>,\n classHierarchy: ECClassHierarchyInspector,\n matchedDefinitionProcessor: (\n def: TDefinition,\n matchingFilters: Array<{ id: TIdentifier; childrenIdentifierPaths: HierarchyNodeIdentifiersPath[] }>,\n isFilterTarget: boolean,\n ) => TDefinition,\n): Promise<TDefinition | undefined> {\n const { filteredNodePaths, isDirectParentFilterTarget } = filteringProps;\n let isFilterTarget = false;\n const matchingFilters: Array<{ id: TIdentifier; childrenIdentifierPaths: HierarchyNodeIdentifiersPath[] }> = [];\n for (const path of filteredNodePaths) {\n if (path.length === 0) {\n continue;\n }\n const nodeId = path[0];\n if (await predicate(nodeId)) {\n let childrenIdentifierPaths = await findChildrenIdentifierPaths(matchingFilters, nodeId, classHierarchy);\n if (!childrenIdentifierPaths) {\n childrenIdentifierPaths = [];\n matchingFilters.push({\n // ideally, `predicate` would act as a type guard to guarantee that `id` is `TIdentifier`, but at the moment\n // async type guards aren't supported\n id: nodeId as TIdentifier,\n childrenIdentifierPaths,\n });\n }\n const remainingPath = path.slice(1);\n if (remainingPath.length > 0) {\n childrenIdentifierPaths.push(remainingPath);\n } else {\n isFilterTarget = true;\n }\n }\n }\n if (isDirectParentFilterTarget || matchingFilters.length > 0) {\n return matchedDefinitionProcessor(definition, matchingFilters, isFilterTarget);\n }\n return undefined;\n}\n\nasync function findChildrenIdentifierPaths<TIdentifier extends HierarchyNodeIdentifier>(\n filters: Array<{ id: TIdentifier; childrenIdentifierPaths: HierarchyNodeIdentifiersPath[] }>,\n nodeId: TIdentifier,\n classHierarchy: ECClassHierarchyInspector,\n) {\n for (const filter of filters) {\n if (await identifiersEqual(filter.id, nodeId, classHierarchy)) {\n return filter.childrenIdentifierPaths;\n }\n }\n return undefined;\n}\n\nasync function identifiersEqual<TIdentifier extends HierarchyNodeIdentifier>(lhs: TIdentifier, rhs: TIdentifier, classHierarchy: ECClassHierarchyInspector) {\n if (HierarchyNodeIdentifier.isInstanceNodeIdentifier(lhs) && HierarchyNodeIdentifier.isInstanceNodeIdentifier(rhs)) {\n return (\n lhs.id === rhs.id &&\n (lhs.className === rhs.className ||\n (await classHierarchy.classDerivesFrom(lhs.className, rhs.className)) ||\n (await classHierarchy.classDerivesFrom(rhs.className, lhs.className)))\n );\n }\n return HierarchyNodeIdentifier.equal(lhs, rhs);\n}\n\nfunction applyFilterAttributes<TNode extends ParsedHierarchyNode>(\n node: TNode,\n filteredChildrenIdentifierPaths: HierarchyNodeIdentifiersPath[] | undefined,\n isFilterTarget: boolean,\n hasFilterTargetAncestor: boolean,\n): TNode {\n const shouldAutoExpand = !!filteredChildrenIdentifierPaths?.some((path) => !!path.length);\n const result = { ...node };\n if (shouldAutoExpand) {\n result.autoExpand = true;\n }\n if (isFilterTarget || hasFilterTargetAncestor || filteredChildrenIdentifierPaths?.length) {\n result.filtering = {\n ...(isFilterTarget ? { isFilterTarget } : undefined),\n ...(hasFilterTargetAncestor ? { hasFilterTargetAncestor } : undefined),\n ...(!!filteredChildrenIdentifierPaths?.length ? { filteredChildrenIdentifierPaths } : undefined),\n };\n }\n return result;\n}\n\n/** @internal */\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport const ECSQL_COLUMN_NAME_FilteredChildrenPaths = \"FilteredChildrenPaths\";\n\n/** @internal */\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport const ECSQL_COLUMN_NAME_IsFilterTarget = \"IsFilterTarget\";\n\n/** @internal */\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport const ECSQL_COLUMN_NAME_HasFilterTargetAncestor = \"HasFilterTargetAncestor\";\n\n/** @internal */\nexport function applyECInstanceIdsFilter(\n def: InstanceNodesQueryDefinition,\n matchingFilters: Array<{ id: InstanceKey; childrenIdentifierPaths: HierarchyNodeIdentifiersPath[] }>,\n isFilterTarget: boolean,\n isParentFilterTarget: boolean,\n hasFilterTargetAncestor: boolean,\n): InstanceNodesQueryDefinition {\n if (matchingFilters.length === 0) {\n return def;\n }\n return {\n ...def,\n query: {\n ...def.query,\n ctes: [\n ...(def.query.ctes ?? []),\n // note: generally we'd use `VALUES (1,1),(2,2)`, but that doesn't work in ECSQL (https://github.com/iTwin/itwinjs-backlog/issues/865),\n // so using UNION as a workaround\n `FilteringInfo(ECInstanceId, FilteredChildrenPaths) AS (\n ${matchingFilters\n .map(({ id: key, childrenIdentifierPaths }) => `VALUES (${key.id}, '${JSON.stringify(childrenIdentifierPaths)}')`)\n .join(\" UNION ALL \")}\n )`,\n ],\n ecsql: `\n SELECT\n [q].*,\n ${isFilterTarget ? \"1\" : \"0\"} AS [${ECSQL_COLUMN_NAME_IsFilterTarget}],\n ${hasFilterTargetAncestor || isParentFilterTarget ? \"1\" : \"0\"} AS [${ECSQL_COLUMN_NAME_HasFilterTargetAncestor}],\n [f].[FilteredChildrenPaths] AS [${ECSQL_COLUMN_NAME_FilteredChildrenPaths}]\n FROM (\n ${def.query.ecsql}\n ) [q]\n ${isParentFilterTarget ? \"LEFT \" : \"\"} JOIN FilteringInfo [f] ON [f].[ECInstanceId] = [q].[ECInstanceId]\n `,\n },\n };\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itwin/presentation-hierarchies",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "A package for creating hierarchies based on data in iTwin.js iModels.",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -30,7 +30,7 @@
30
30
  "@itwin/core-geometry": "^4.6.0",
31
31
  "natural-compare-lite": "^1.4.0",
32
32
  "rxjs": "^7.8.1",
33
- "@itwin/presentation-shared": "^0.3.0"
33
+ "@itwin/presentation-shared": "^0.3.1"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@itwin/build-tools": "^4.6.0",