@itwin/grouping-mapping-widget 0.9.1 → 0.9.3

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.
Files changed (83) hide show
  1. package/lib/cjs/grouping-mapping-widget.d.ts +2 -2
  2. package/lib/cjs/grouping-mapping-widget.js +7 -1
  3. package/lib/cjs/grouping-mapping-widget.js.map +1 -1
  4. package/lib/cjs/test/GroupingMappingCustomUI.test.js +44 -53
  5. package/lib/cjs/test/GroupingMappingCustomUI.test.js.map +1 -1
  6. package/lib/cjs/test/QueryBuilder.test.js +30 -2
  7. package/lib/cjs/test/QueryBuilder.test.js.map +1 -1
  8. package/lib/cjs/test/QueryBuilder.testdata.js +471 -7
  9. package/lib/cjs/test/QueryBuilder.testdata.js.map +1 -1
  10. package/lib/cjs/test/QueryBuilderTestData.d.ts +3 -1
  11. package/lib/cjs/test/QueryBuilderTestData.js.map +1 -1
  12. package/lib/cjs/widget/components/GroupAction.js +2 -21
  13. package/lib/cjs/widget/components/GroupAction.js.map +1 -1
  14. package/lib/cjs/widget/components/GroupQueryBuilderContainer.d.ts +3 -2
  15. package/lib/cjs/widget/components/GroupQueryBuilderContainer.js +38 -45
  16. package/lib/cjs/widget/components/GroupQueryBuilderContainer.js.map +1 -1
  17. package/lib/cjs/widget/components/Grouping.js +1 -1
  18. package/lib/cjs/widget/components/Grouping.js.map +1 -1
  19. package/lib/cjs/widget/components/Grouping.scss +1 -1
  20. package/lib/cjs/widget/components/QueryBuilder.d.ts +35 -21
  21. package/lib/cjs/widget/components/QueryBuilder.js +153 -181
  22. package/lib/cjs/widget/components/QueryBuilder.js.map +1 -1
  23. package/lib/cjs/widget/components/context/PropertyGridWrapperContext.d.ts +15 -0
  24. package/lib/cjs/widget/components/context/{GroupQueryBuilderContext.js → PropertyGridWrapperContext.js} +13 -9
  25. package/lib/cjs/widget/components/context/PropertyGridWrapperContext.js.map +1 -0
  26. package/lib/cjs/widget/components/property-grid/PropertyGrid.d.ts +1 -1
  27. package/lib/cjs/widget/components/property-grid/PropertyGrid.js +2 -2
  28. package/lib/cjs/widget/components/property-grid/PropertyGrid.js.map +1 -1
  29. package/lib/cjs/widget/components/property-grid/PropertyGridWrapper.d.ts +10 -4
  30. package/lib/cjs/widget/components/property-grid/PropertyGridWrapper.js +18 -8
  31. package/lib/cjs/widget/components/property-grid/PropertyGridWrapper.js.map +1 -1
  32. package/lib/cjs/widget/components/property-grid/PropertyView.d.ts +1 -1
  33. package/lib/cjs/widget/components/property-grid/PropertyView.js +46 -60
  34. package/lib/cjs/widget/components/property-grid/PropertyView.js.map +1 -1
  35. package/lib/cjs/widget/components/viewerUtils.js +1 -3
  36. package/lib/cjs/widget/components/viewerUtils.js.map +1 -1
  37. package/lib/esm/grouping-mapping-widget.d.ts +2 -2
  38. package/lib/esm/grouping-mapping-widget.js +2 -1
  39. package/lib/esm/grouping-mapping-widget.js.map +1 -1
  40. package/lib/esm/test/GroupingMappingCustomUI.test.js +45 -54
  41. package/lib/esm/test/GroupingMappingCustomUI.test.js.map +1 -1
  42. package/lib/esm/test/QueryBuilder.test.js +31 -3
  43. package/lib/esm/test/QueryBuilder.test.js.map +1 -1
  44. package/lib/esm/test/QueryBuilder.testdata.js +471 -7
  45. package/lib/esm/test/QueryBuilder.testdata.js.map +1 -1
  46. package/lib/esm/test/QueryBuilderTestData.d.ts +3 -1
  47. package/lib/esm/test/QueryBuilderTestData.js.map +1 -1
  48. package/lib/esm/widget/components/GroupAction.js +2 -21
  49. package/lib/esm/widget/components/GroupAction.js.map +1 -1
  50. package/lib/esm/widget/components/GroupQueryBuilderContainer.d.ts +3 -2
  51. package/lib/esm/widget/components/GroupQueryBuilderContainer.js +34 -25
  52. package/lib/esm/widget/components/GroupQueryBuilderContainer.js.map +1 -1
  53. package/lib/esm/widget/components/Grouping.js +1 -1
  54. package/lib/esm/widget/components/Grouping.js.map +1 -1
  55. package/lib/esm/widget/components/Grouping.scss +1 -1
  56. package/lib/esm/widget/components/QueryBuilder.d.ts +35 -21
  57. package/lib/esm/widget/components/QueryBuilder.js +153 -181
  58. package/lib/esm/widget/components/QueryBuilder.js.map +1 -1
  59. package/lib/esm/widget/components/context/PropertyGridWrapperContext.d.ts +15 -0
  60. package/lib/esm/widget/components/context/{GroupQueryBuilderContext.js → PropertyGridWrapperContext.js} +11 -8
  61. package/lib/esm/widget/components/context/PropertyGridWrapperContext.js.map +1 -0
  62. package/lib/esm/widget/components/property-grid/PropertyGrid.d.ts +1 -1
  63. package/lib/esm/widget/components/property-grid/PropertyGrid.js +2 -2
  64. package/lib/esm/widget/components/property-grid/PropertyGrid.js.map +1 -1
  65. package/lib/esm/widget/components/property-grid/PropertyGridWrapper.d.ts +10 -4
  66. package/lib/esm/widget/components/property-grid/PropertyGridWrapper.js +16 -6
  67. package/lib/esm/widget/components/property-grid/PropertyGridWrapper.js.map +1 -1
  68. package/lib/esm/widget/components/property-grid/PropertyView.d.ts +1 -1
  69. package/lib/esm/widget/components/property-grid/PropertyView.js +32 -30
  70. package/lib/esm/widget/components/property-grid/PropertyView.js.map +1 -1
  71. package/lib/esm/widget/components/viewerUtils.js +1 -3
  72. package/lib/esm/widget/components/viewerUtils.js.map +1 -1
  73. package/package.json +1 -1
  74. package/lib/cjs/api/GroupQueryBuilderApi.d.ts +0 -15
  75. package/lib/cjs/api/GroupQueryBuilderApi.js +0 -27
  76. package/lib/cjs/api/GroupQueryBuilderApi.js.map +0 -1
  77. package/lib/cjs/widget/components/context/GroupQueryBuilderContext.d.ts +0 -16
  78. package/lib/cjs/widget/components/context/GroupQueryBuilderContext.js.map +0 -1
  79. package/lib/esm/api/GroupQueryBuilderApi.d.ts +0 -15
  80. package/lib/esm/api/GroupQueryBuilderApi.js +0 -23
  81. package/lib/esm/api/GroupQueryBuilderApi.js.map +0 -1
  82. package/lib/esm/widget/components/context/GroupQueryBuilderContext.d.ts +0 -16
  83. package/lib/esm/widget/components/context/GroupQueryBuilderContext.js.map +0 -1
@@ -5,19 +5,37 @@ const appui_abstract_1 = require("@itwin/appui-abstract");
5
5
  const itwinui_react_1 = require("@itwin/itwinui-react");
6
6
  /* This class is to build adaptive and dynamic query for find similar property selections */
7
7
  class QueryBuilder {
8
- /**
9
- *
10
- */
11
8
  constructor(provider) {
12
- this.addRelatedPropertyToQuery = (unionIndex, isAspect) => (className, propertyName, propertyValue, needsQuote) => this.addPropertyToQuery(unionIndex, className, propertyName, propertyValue, isAspect, needsQuote, false, true);
13
- this.whereSegment = (baseClass, baseClassName) => {
14
- const segments = [];
15
- const properties = baseClass.properties;
16
- for (let i = 0; i < properties.length; i++) {
17
- const prefix = i === 0 ? "WHERE" : "AND";
18
- segments.push(this.propertySegment(baseClassName, properties[i], prefix));
9
+ this.resetQuery = () => {
10
+ this.query = undefined;
11
+ };
12
+ this._propertyMap = new Map();
13
+ this.regenerateQuery = () => {
14
+ this.resetQuery();
15
+ for (const property of this._propertyMap.values()) {
16
+ this.buildProperty(property.propertyRecord, property.propertiesField);
19
17
  }
20
- return segments.join("");
18
+ };
19
+ this.relationalJoinSegments = (classes, querySegments) => {
20
+ var _a;
21
+ for (const queryClass of classes) {
22
+ for (const classJoin of queryClass.classJoins) {
23
+ const querySegment = [
24
+ ...(_a = querySegments.get(classJoin.joinClassName)) !== null && _a !== void 0 ? _a : [],
25
+ `${queryClass.className}.${classJoin.classProperty} = ${classJoin.joinClassName}.${classJoin.joinClassProperty}`,
26
+ ];
27
+ querySegments.set(classJoin.joinClassName, querySegment);
28
+ }
29
+ }
30
+ return querySegments;
31
+ };
32
+ this.propertyQuerySegment = (className, property, needsQuote) => {
33
+ if (this.isFloat(property.value))
34
+ return `ROUND(${className}.${property.name}, ` +
35
+ `${QueryBuilder.DEFAULT_DOUBLE_PRECISION}) = ` +
36
+ `${Number(property.value).toFixed(QueryBuilder.DEFAULT_DOUBLE_PRECISION)}`;
37
+ const propertyValue = needsQuote ? `'${property.value}'` : property.value;
38
+ return `${className}.${property.name} = ${propertyValue}`;
21
39
  };
22
40
  this.dataProvider = provider;
23
41
  }
@@ -27,7 +45,7 @@ class QueryBuilder {
27
45
  return (classInfo === null || classInfo === void 0 ? void 0 : classInfo.name) === "BisCore:GeometricElement3dIsInCategory";
28
46
  }
29
47
  async addProperty(prop) {
30
- var _a, _b, _c, _d, _e, _f, _g;
48
+ var _a;
31
49
  // TODO: only handle primitive properties now
32
50
  if (((_a = prop.value) === null || _a === void 0 ? void 0 : _a.valueFormat) !== appui_abstract_1.PropertyValueFormat.Primitive) {
33
51
  itwinui_react_1.toaster.warning("Only primitive types are supported for now.");
@@ -36,6 +54,24 @@ class QueryBuilder {
36
54
  if (prop.value.value === undefined) {
37
55
  return false;
38
56
  }
57
+ const propertyField = (await this.dataProvider.getFieldByPropertyRecord(prop));
58
+ if (!propertyField) {
59
+ itwinui_react_1.toaster.negative("Error. Failed to fetch field for this property record.");
60
+ return false;
61
+ }
62
+ this._propertyMap.set(JSON.stringify(propertyField.getFieldDescriptor()), { propertyRecord: prop, propertiesField: propertyField });
63
+ return true;
64
+ }
65
+ async removeProperty(prop) {
66
+ const propertyField = (await this.dataProvider.getFieldByPropertyRecord(prop));
67
+ this._propertyMap.delete(JSON.stringify(propertyField.getFieldDescriptor()));
68
+ }
69
+ buildProperty(prop, propertiesField) {
70
+ var _a, _b, _c;
71
+ if (((_a = prop.value) === null || _a === void 0 ? void 0 : _a.valueFormat) !== appui_abstract_1.PropertyValueFormat.Primitive || prop.value.value === undefined) {
72
+ itwinui_react_1.toaster.negative("Error. An unexpected error has occured while building a query.");
73
+ return;
74
+ }
39
75
  function replaceAll(str, match, replacement) {
40
76
  return str.split(match).join(replacement);
41
77
  }
@@ -45,41 +81,36 @@ class QueryBuilder {
45
81
  String(prop.value.value).indexOf("'") >= 0) {
46
82
  prop.value.value = replaceAll(prop.value.value.toString(), "'", "''");
47
83
  }
48
- // get descriptor
49
- const descriptor = await ((_b = this.dataProvider) === null || _b === void 0 ? void 0 : _b.getContentDescriptor());
50
- const propertyField = (await ((_c = this.dataProvider) === null || _c === void 0 ? void 0 : _c.getFieldByPropertyRecord(prop)));
51
- if (!descriptor || !propertyField) {
52
- itwinui_react_1.toaster.negative("Error. Failed to fetch field for this property record.");
53
- return false;
54
- }
84
+ const pathToPrimaryClass = (_b = propertiesField.parent) === null || _b === void 0 ? void 0 : _b.pathToPrimaryClass;
55
85
  // get the special cases
56
86
  const isNavigation = prop.property.typename.toLowerCase() === "navigation";
57
- const isCategory = isNavigation && this.isCategory(propertyField);
58
- const isAspect = ((_d = propertyField.parent) === null || _d === void 0 ? void 0 : _d.pathToPrimaryClass.find((a) => {
87
+ const isCategory = isNavigation && this.isCategory(propertiesField);
88
+ const isAspect = (pathToPrimaryClass === null || pathToPrimaryClass === void 0 ? void 0 : pathToPrimaryClass.find((a) => {
59
89
  var _a, _b;
60
90
  return ((_a = a.relationshipInfo) === null || _a === void 0 ? void 0 : _a.name) ===
61
91
  QueryBuilder.UNIQUE_ASPECT_PRIMARY_CLASS ||
62
92
  ((_b = a.relationshipInfo) === null || _b === void 0 ? void 0 : _b.name) === QueryBuilder.MULTI_ASPECT_PRIMARY_CLASS;
63
93
  })) !== undefined;
64
- for (let i = 0; i < propertyField.properties.length; i++) {
65
- const className = propertyField.properties[i].property.classInfo.name.replace(":", ".");
94
+ for (let i = 0; i < propertiesField.properties.length; i++) {
95
+ const property = propertiesField.properties[i].property;
96
+ const className = property.classInfo.name.replace(":", ".");
66
97
  const propertyName = isNavigation
67
98
  ? isCategory
68
- ? `${propertyField.properties[i].property.name}.CodeValue`
69
- : `${propertyField.properties[i].property.name}.id`
70
- : propertyField.properties[i].property.name;
99
+ ? `${property.name}.CodeValue`
100
+ : `${property.name}.id`
101
+ : property.name;
71
102
  const propertyValue = isNavigation
72
103
  ? isCategory
73
- ? (_e = prop.value.displayValue) !== null && _e !== void 0 ? _e : ""
104
+ ? (_c = prop.value.displayValue) !== null && _c !== void 0 ? _c : ""
74
105
  : prop.value.value.id
75
106
  : prop.value.value;
76
107
  if (!isAspect &&
77
- ((_f = propertyField.parent) === null || _f === void 0 ? void 0 : _f.pathToPrimaryClass) &&
78
- ((_g = propertyField.parent) === null || _g === void 0 ? void 0 : _g.pathToPrimaryClass.length) > 0) {
79
- this.addRelatedProperty(i, propertyField, propertyName, propertyValue, isAspect);
108
+ pathToPrimaryClass &&
109
+ pathToPrimaryClass.length > 0) {
110
+ this.addRelatedToQuery(i, propertiesField, propertyName, propertyValue);
80
111
  }
81
112
  else {
82
- this.addPropertyToQuery(i, className, propertyName, propertyValue, isAspect, this.needsQuote(propertyField), isCategory, false);
113
+ this.addPropertyToQuery(i, className, propertyName, propertyValue, this.needsQuote(propertiesField), isCategory, isAspect);
83
114
  }
84
115
  }
85
116
  return true;
@@ -94,207 +125,148 @@ class QueryBuilder {
94
125
  }
95
126
  return false;
96
127
  }
97
- addRelatedProperty(unionIndex, propertyField, propertyName, propertyValue, isAspect) {
128
+ addRelatedToQuery(unionIndex, propertyField, propertyName, propertyValue) {
98
129
  var _a, _b;
99
- const addProperty = this.addRelatedPropertyToQuery(unionIndex, isAspect);
100
130
  const paths = [...((_b = (_a = propertyField.parent) === null || _a === void 0 ? void 0 : _a.pathToPrimaryClass) !== null && _b !== void 0 ? _b : [])];
101
131
  paths.reverse().forEach((path) => {
102
132
  var _a, _b, _c, _d, _e;
103
133
  const sourceClassName = (_a = path.sourceClassInfo) === null || _a === void 0 ? void 0 : _a.name.replace(":", ".");
104
134
  const targetClassName = (_b = path.targetClassInfo) === null || _b === void 0 ? void 0 : _b.name.replace(":", ".");
105
135
  const relClassName = (_c = path.relationshipInfo) === null || _c === void 0 ? void 0 : _c.name.replace(":", ".");
106
- const relPropertyName = path.isForwardRelationship
136
+ const relClassProperty = path.isForwardRelationship
107
137
  ? `SourceECInstanceId`
108
138
  : `TargetECInstanceId`;
109
139
  const relPropertyValue = path.isForwardRelationship
110
- ? `${relClassName}.TargetECInstanceId`
111
- : `${relClassName}.SourceECInstanceId`;
112
- addProperty(targetClassName, `ECInstanceId`, relPropertyValue, false);
113
- addProperty(relClassName, relPropertyName, `${sourceClassName}.ECInstanceId`, false);
140
+ ? `TargetECInstanceId`
141
+ : `SourceECInstanceId`;
142
+ this.addClassToQuery(unionIndex, targetClassName, `ECInstanceId`, relClassName, relPropertyValue);
143
+ this.addClassToQuery(unionIndex, relClassName, relClassProperty, sourceClassName, `ECInstanceId`);
114
144
  if (((_d = path.sourceClassInfo) === null || _d === void 0 ? void 0 : _d.name)
115
145
  === ((_e = propertyField.parent) === null || _e === void 0 ? void 0 : _e.contentClassInfo.name)) {
116
- addProperty(sourceClassName, propertyName, propertyValue, this.needsQuote(propertyField));
146
+ this.addPropertyToQuery(unionIndex, sourceClassName, propertyName, propertyValue, this.needsQuote(propertyField), false, false);
117
147
  }
118
148
  });
119
149
  }
120
- addPropertyToQuery(unionIndex, className, propertyName, propertyValue, isAspect, needsQuote, isCategory, isRelational) {
121
- if (this.query === undefined || this.query.unions.length === 0) {
150
+ addClassToQuery(unionIndex, className, classProperty, joinClassName, joinClassProperty) {
151
+ if (this.query === undefined) {
122
152
  this.query = { unions: [] };
123
153
  }
124
- const queryProperty = {
125
- name: propertyName,
126
- value: propertyValue,
127
- needsQuote,
128
- isCategory,
154
+ const classJoin = {
155
+ classProperty,
156
+ joinClassName,
157
+ joinClassProperty,
129
158
  };
130
159
  const queryClass = {
131
160
  className,
132
- isAspect,
133
- isRelational,
134
- properties: [
135
- queryProperty,
136
- ],
161
+ classJoins: [classJoin],
137
162
  };
138
163
  if (this.query.unions.length <= unionIndex) {
139
164
  this.query.unions.push({
140
- classes: [
141
- queryClass,
142
- ],
165
+ classes: [queryClass],
166
+ properties: [],
143
167
  });
144
168
  return;
145
169
  }
146
170
  const foundClass = this.query.unions[unionIndex].classes.find((c) => c.className === className);
147
171
  if (foundClass) {
148
- foundClass.isRelational = isRelational;
149
- if (!foundClass.properties.find((x) => x.name === propertyName)) {
150
- foundClass.properties.push(queryProperty);
151
- }
152
- }
153
- else {
154
- this.query.unions[unionIndex].classes.push(queryClass);
155
- }
156
- }
157
- async removeProperty(prop) {
158
- var _a, _b, _c, _d, _e;
159
- if (this.query === undefined || this.query.unions.length === 0) {
172
+ const foundJoin = foundClass.classJoins.find((join) => join.classProperty === classProperty && join.joinClassName === joinClassName && join.joinClassProperty === joinClassProperty);
173
+ if (!foundJoin)
174
+ foundClass.classJoins.push(classJoin);
160
175
  return;
161
176
  }
162
- if (this.query.unions.length === 1 &&
163
- this.query.unions[0].classes.length === 0) {
164
- return;
177
+ this.query.unions[unionIndex].classes.push(queryClass);
178
+ }
179
+ addPropertyToQuery(unionIndex, className, propertyName, propertyValue, needsQuote, isCategory, isAspect) {
180
+ if (this.query === undefined) {
181
+ this.query = { unions: [] };
165
182
  }
166
- const descriptor = await ((_a = this.dataProvider) === null || _a === void 0 ? void 0 : _a.getContentDescriptor());
167
- const propertyField = (await ((_b = this.dataProvider) === null || _b === void 0 ? void 0 : _b.getFieldByPropertyRecord(prop)));
168
- if (!descriptor || !propertyField) {
183
+ const queryJoin = {
184
+ name: propertyName,
185
+ value: propertyValue,
186
+ needsQuote,
187
+ };
188
+ const queryProperty = {
189
+ className,
190
+ isCategory,
191
+ isAspect,
192
+ classProperties: [queryJoin],
193
+ };
194
+ if (this.query.unions.length <= unionIndex) {
195
+ this.query.unions.push({
196
+ classes: [],
197
+ properties: [queryProperty],
198
+ });
169
199
  return;
170
200
  }
171
- const isAspect = ((_c = propertyField.parent) === null || _c === void 0 ? void 0 : _c.pathToPrimaryClass.find((a) => {
172
- var _a, _b;
173
- return ((_a = a.relationshipInfo) === null || _a === void 0 ? void 0 : _a.name) ===
174
- QueryBuilder.UNIQUE_ASPECT_PRIMARY_CLASS ||
175
- ((_b = a.relationshipInfo) === null || _b === void 0 ? void 0 : _b.name) === QueryBuilder.MULTI_ASPECT_PRIMARY_CLASS;
176
- })) !== undefined;
177
- const isNavigation = prop.property.typename.toLowerCase() === "navigation";
178
- const isCategory = isNavigation && this.isCategory(propertyField);
179
- for (let i = 0; i < propertyField.properties.length; i++) {
180
- const propertyName = isNavigation
181
- ? isCategory
182
- ? `${propertyField.properties[i].property.name}.CodeValue`
183
- : `${propertyField.properties[i].property.name}.id`
184
- : propertyField.properties[i].property.name;
185
- const className = propertyField.properties[i].property.classInfo.name.replace(":", ".");
186
- if (!isAspect &&
187
- ((_d = propertyField.parent) === null || _d === void 0 ? void 0 : _d.pathToPrimaryClass) &&
188
- ((_e = propertyField.parent) === null || _e === void 0 ? void 0 : _e.pathToPrimaryClass.length) > 0) {
189
- this.removeRelatedProperty(i, propertyField, propertyName);
190
- }
191
- else {
192
- this.removePropertyFromQuery(i, className, propertyName);
193
- }
194
- }
195
- }
196
- removeRelatedProperty(unionIndex, propertyField, propertyName) {
197
- var _a, _b;
198
- const paths = [...((_b = (_a = propertyField.parent) === null || _a === void 0 ? void 0 : _a.pathToPrimaryClass) !== null && _b !== void 0 ? _b : [])];
199
- paths.reverse().forEach((path) => {
200
- var _a, _b, _c, _d, _e;
201
- const sourceClassName = (_a = path.sourceClassInfo) === null || _a === void 0 ? void 0 : _a.name.replace(":", ".");
202
- const targetClassName = (_b = path.targetClassInfo) === null || _b === void 0 ? void 0 : _b.name.replace(":", ".");
203
- const relClassName = (_c = path.relationshipInfo) === null || _c === void 0 ? void 0 : _c.name.replace(":", ".");
204
- this.removePropertyFromQuery(unionIndex, targetClassName, `ECInstanceId`);
205
- const relPropertyName = path.isForwardRelationship ? `SourceECInstanceId` : `TargetECInstanceId`;
206
- this.removePropertyFromQuery(unionIndex, relClassName, relPropertyName);
207
- if (((_d = path.sourceClassInfo) === null || _d === void 0 ? void 0 : _d.name) ===
208
- ((_e = propertyField.parent) === null || _e === void 0 ? void 0 : _e.contentClassInfo.name)) {
209
- this.removePropertyFromQuery(unionIndex, sourceClassName, propertyName);
210
- }
211
- });
212
- }
213
- removePropertyFromQuery(unionIndex, className, propertyName) {
214
- var _a, _b, _c, _d;
215
- const foundClass = (_a = this.query) === null || _a === void 0 ? void 0 : _a.unions[unionIndex].classes.find((c) => c.className === className);
216
- if (foundClass) {
217
- const foundPropertyIndex = foundClass.properties.findIndex((p) => p.name === propertyName);
218
- if (foundPropertyIndex > -1) {
219
- foundClass.properties.splice(foundPropertyIndex, 1);
220
- }
221
- if (foundClass.properties.length === 0) {
222
- // remove the entire class if all properties are removed
223
- const foundClassIndex = (_c = (_b = this.query) === null || _b === void 0 ? void 0 : _b.unions[unionIndex].classes.findIndex((c) => c.className === className)) !== null && _c !== void 0 ? _c : -1;
224
- if (foundClassIndex > -1) {
225
- (_d = this.query) === null || _d === void 0 ? void 0 : _d.unions[unionIndex].classes.splice(foundClassIndex, 1);
226
- }
201
+ const foundPropertyClass = this.query.unions[unionIndex].properties.find((p) => p.className === className);
202
+ if (foundPropertyClass) {
203
+ const foundJoin = foundPropertyClass === null || foundPropertyClass === void 0 ? void 0 : foundPropertyClass.classProperties.find((join) => join.name === propertyName);
204
+ if (foundJoin) {
205
+ foundJoin.value = propertyValue;
206
+ return;
227
207
  }
208
+ foundPropertyClass.classProperties.push(queryJoin);
209
+ return;
228
210
  }
211
+ this.query.unions[unionIndex].properties.push(queryProperty);
229
212
  }
230
213
  buildQueryString() {
214
+ var _a;
215
+ this.regenerateQuery();
231
216
  if (this.query === undefined ||
232
- this.query.unions.length === 0 ||
233
- this.query.unions[0].classes.length === 0) {
217
+ (this.query.unions.find((u) => u.classes.length === 0 && u.properties.length === 0))) {
234
218
  return "";
235
219
  }
236
220
  const unionSegments = [];
237
221
  for (const union of this.query.unions) {
238
- const querySegments = [];
239
222
  const baseClass = union.classes[0];
240
- const baseClassName = baseClass.className;
241
- const baseIdName = baseClass.isAspect
242
- ? `${baseClassName}.Element.id`
243
- : `${baseClassName}.ECInstanceId`;
244
- const selectSegment = `SELECT ${baseIdName}${baseClass.isAspect ? " ECInstanceId" : ""} FROM ${baseClassName}`;
245
- querySegments.push(selectSegment);
246
- if (union.classes.length > 1) {
247
- for (let i = 1; i < union.classes.length; i++) {
248
- const joinClass = union.classes[i];
249
- const joinClassName = joinClass.className;
250
- const joinIdName = joinClass.isAspect
251
- ? `${joinClassName}.Element.id`
252
- : `${joinClassName}.ECInstanceId`;
253
- const joinSegment = joinClass.isRelational
254
- ? ` JOIN ${joinClassName}`
255
- : ` JOIN ${joinClassName} ON ${joinIdName} = ${baseIdName}`;
256
- querySegments.push(joinSegment);
257
- for (let j = 0; j < joinClass.properties.length; j++) {
258
- const prefix = j === 0 && joinClass.isRelational ? "ON" : "AND";
259
- const propertySegment = this.propertySegment(joinClassName, joinClass.properties[j], prefix);
260
- querySegments.push(propertySegment);
261
- }
262
- // when base is regular property, link base to first joined relational property
263
- if (joinClass.isRelational && !baseClass.isRelational && i === 1) {
264
- querySegments.push(` AND ${joinIdName} = ${baseIdName}`);
265
- }
223
+ const baseProperty = union.properties[0];
224
+ const baseClassName = baseClass ? baseClass.className : baseProperty === null || baseProperty === void 0 ? void 0 : baseProperty.className;
225
+ const baseIdName = `${baseClassName}.ECInstanceId`;
226
+ const selectClause = this.selectClause(baseProperty, baseClass);
227
+ let querySegments = new Map();
228
+ querySegments = this.relationalJoinSegments(union.classes, querySegments);
229
+ const whereSegments = [];
230
+ for (const property of union.properties) {
231
+ if (property.isCategory) {
232
+ if (property.className !== baseClassName)
233
+ querySegments.set("BisCore.GeometricElement3d", [`BisCore.GeometricElement3d.ECInstanceId = ${baseIdName}`]);
234
+ querySegments.set("BisCore.Category", [`BisCore.Category.ECInstanceId = BisCore.GeometricElement3d.category.id`]);
235
+ whereSegments.push(this.categoryWhereQuery(property.classProperties[0].value.toString()));
236
+ continue;
266
237
  }
238
+ const joinIdName = property.isAspect
239
+ ? `${property.className}.Element.id`
240
+ : `${property.className}.ECInstanceId`;
241
+ if (!querySegments.has(property.className) && property.className !== baseClassName)
242
+ querySegments.set(property.className, [`${joinIdName} = ${baseIdName}`]);
243
+ for (const prop of property.classProperties) {
244
+ whereSegments.push(this.propertyQuerySegment(property.className, prop, prop.needsQuote));
245
+ }
246
+ }
247
+ const joinClauses = [];
248
+ for (const key of querySegments.keys()) {
249
+ joinClauses.push(`JOIN ${key} ON ${(_a = querySegments.get(key)) === null || _a === void 0 ? void 0 : _a.join(" AND ")}`);
267
250
  }
268
- const whereSegment = this.whereSegment(baseClass, baseClassName);
269
- querySegments.push(whereSegment);
270
- unionSegments.push(querySegments.join(""));
251
+ const whereClause = `WHERE ${whereSegments.join(" AND ")}`;
252
+ unionSegments.push([selectClause, ...joinClauses, whereClause].join(" "));
271
253
  }
272
254
  return unionSegments.join(" UNION ");
273
255
  }
274
- propertySegment(className, property, prefix) {
275
- const segments = [];
276
- if (property.isCategory) {
277
- segments.push(this.categoryQuery(property.value.toString()));
256
+ selectClause(baseProperty, baseClass) {
257
+ if (baseClass) {
258
+ return `SELECT ${baseClass.className}.ECInstanceId, ${baseClass.className}.ECClassId FROM ${baseClass.className}`;
278
259
  }
279
- else {
280
- if (property.needsQuote) {
281
- segments.push(` ${prefix} ${className}.${property.name}='${property.value}'`);
282
- }
283
- else {
284
- if (this.isFloat(property.value)) {
285
- segments.push(` ${prefix} ROUND(${className}.${property.name}, `);
286
- segments.push(`${QueryBuilder.DEFAULT_DOUBLE_PRECISION})=`);
287
- segments.push(`${Number(property.value).toFixed(QueryBuilder.DEFAULT_DOUBLE_PRECISION)}`);
288
- }
289
- else {
290
- segments.push(` ${prefix} ${className}.${property.name}=${property.value}`);
291
- }
292
- }
260
+ if (baseProperty) {
261
+ const baseIdName = baseProperty.isAspect
262
+ ? `${baseProperty.className}.Element.id ECInstanceId`
263
+ : `${baseProperty.className}.ECInstanceId, ${baseProperty.className}.ECClassId`;
264
+ return `SELECT ${baseIdName} FROM ${baseProperty.className}`;
293
265
  }
294
- return segments.join("");
266
+ return "";
295
267
  }
296
- categoryQuery(codeValue) {
297
- return ` JOIN bis.Category ON bis.Category.ECInstanceId = bis.GeometricElement3d.category.id AND ((bis.Category.CodeValue='${codeValue}') OR (bis.Category.UserLabel='${codeValue}'))`;
268
+ categoryWhereQuery(codeValue) {
269
+ return `((BisCore.Category.CodeValue = '${codeValue}') OR (BisCore.Category.UserLabel = '${codeValue}'))`;
298
270
  }
299
271
  isFloat(n) {
300
272
  return Number(n) === n && n % 1 !== 0;
@@ -1 +1 @@
1
- {"version":3,"file":"QueryBuilder.js","sourceRoot":"","sources":["../../../../src/widget/components/QueryBuilder.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*--------------------------------------------------------------------------------------------*/\nimport type { PresentationPropertyDataProvider } from \"@itwin/presentation-components\";\nimport type {\n InstanceKey,\n PropertiesField,\n} from \"@itwin/presentation-common\";\nimport type { Primitives, PropertyRecord } from \"@itwin/appui-abstract\";\nimport { PropertyValueFormat } from \"@itwin/appui-abstract\";\nimport { toaster } from \"@itwin/itwinui-react\";\n\nexport interface Query {\n unions: QueryUnion[];\n}\n\nexport interface QueryUnion {\n classes: QueryClass[];\n}\n\nexport interface QueryClass {\n // schemaName.className\n className: string;\n properties: QueryProperty[];\n isAspect: boolean;\n isRelational?: boolean;\n}\n\nexport interface QueryProperty {\n name: string;\n value: Primitives.Value;\n needsQuote: boolean;\n isCategory: boolean;\n}\n\n/* This class is to build adaptive and dynamic query for find similar property selections */\nexport class QueryBuilder {\n public static readonly MULTI_ASPECT_PRIMARY_CLASS =\n \"BisCore:ElementOwnsMultiAspects\";\n public static readonly UNIQUE_ASPECT_PRIMARY_CLASS =\n \"BisCore:ElementOwnsUniqueAspect\";\n public static readonly DEFAULT_DOUBLE_PRECISION = 4;\n\n public dataProvider: PresentationPropertyDataProvider | undefined;\n public query: Query | undefined;\n\n /**\n *\n */\n constructor(provider: PresentationPropertyDataProvider | undefined) {\n this.dataProvider = provider;\n }\n\n private isCategory(propertyField: PropertiesField): boolean {\n const classInfo =\n propertyField.properties[0].property.navigationPropertyInfo?.classInfo;\n return classInfo?.name === \"BisCore:GeometricElement3dIsInCategory\";\n }\n\n public async addProperty(prop: PropertyRecord): Promise<boolean> {\n // TODO: only handle primitive properties now\n if (prop.value?.valueFormat !== PropertyValueFormat.Primitive) {\n toaster.warning(\"Only primitive types are supported for now.\");\n return false;\n }\n if (prop.value.value === undefined) {\n return false;\n }\n\n function replaceAll(str: string, match: string, replacement: string) {\n return str.split(match).join(replacement);\n }\n // if property value has single quote, escape\n if (\n (typeof prop.value.value === \"string\" ||\n prop.value.value instanceof String) &&\n String(prop.value.value).indexOf(\"'\") >= 0\n ) {\n prop.value.value = replaceAll(prop.value.value.toString(), \"'\", \"''\");\n }\n\n // get descriptor\n const descriptor = await this.dataProvider?.getContentDescriptor();\n const propertyField = (await this.dataProvider?.getFieldByPropertyRecord(\n prop,\n )) as PropertiesField;\n\n if (!descriptor || !propertyField) {\n toaster.negative(\n \"Error. Failed to fetch field for this property record.\",\n );\n return false;\n }\n\n // get the special cases\n const isNavigation: boolean =\n prop.property.typename.toLowerCase() === \"navigation\";\n const isCategory: boolean = isNavigation && this.isCategory(propertyField);\n const isAspect: boolean =\n propertyField.parent?.pathToPrimaryClass.find(\n (a) =>\n a.relationshipInfo?.name ===\n QueryBuilder.UNIQUE_ASPECT_PRIMARY_CLASS ||\n a.relationshipInfo?.name === QueryBuilder.MULTI_ASPECT_PRIMARY_CLASS,\n ) !== undefined;\n\n for (let i = 0; i < propertyField.properties.length; i++) {\n const className = propertyField.properties[i].property.classInfo.name.replace(\":\", \".\");\n const propertyName = isNavigation\n ? isCategory\n ? `${propertyField.properties[i].property.name}.CodeValue`\n : `${propertyField.properties[i].property.name}.id`\n : propertyField.properties[i].property.name;\n const propertyValue = isNavigation\n ? isCategory\n ? prop.value.displayValue ?? \"\"\n : (prop.value.value as InstanceKey).id\n : prop.value.value;\n\n if (\n !isAspect &&\n propertyField.parent?.pathToPrimaryClass &&\n propertyField.parent?.pathToPrimaryClass.length > 0\n ) {\n this.addRelatedProperty(\n i,\n propertyField,\n propertyName,\n propertyValue,\n isAspect,\n );\n } else {\n this.addPropertyToQuery(\n i,\n className,\n propertyName,\n propertyValue,\n isAspect,\n this.needsQuote(propertyField),\n isCategory,\n false,\n );\n }\n }\n return true;\n }\n\n private needsQuote(propertyField: PropertiesField): boolean {\n // list of property types that need quote around property value\n if (propertyField.type.typeName.toLowerCase() === \"string\") {\n return true;\n }\n if (propertyField.type.typeName.toLowerCase() === \"uri\") {\n return true;\n }\n return false;\n }\n\n private addRelatedProperty(\n unionIndex: number,\n propertyField: PropertiesField,\n propertyName: string,\n propertyValue: Primitives.Value,\n isAspect: boolean,\n ) {\n const addProperty = this.addRelatedPropertyToQuery(unionIndex, isAspect);\n\n const paths = [...(propertyField.parent?.pathToPrimaryClass ?? [])];\n paths.reverse().forEach((path) => {\n const sourceClassName = path.sourceClassInfo?.name.replace(\":\", \".\");\n const targetClassName = path.targetClassInfo?.name.replace(\":\", \".\");\n const relClassName = path.relationshipInfo?.name.replace(\":\", \".\");\n\n const relPropertyName = path.isForwardRelationship\n ? `SourceECInstanceId`\n : `TargetECInstanceId`;\n\n const relPropertyValue = path.isForwardRelationship\n ? `${relClassName}.TargetECInstanceId`\n : `${relClassName}.SourceECInstanceId`;\n\n addProperty(\n targetClassName,\n `ECInstanceId`,\n relPropertyValue,\n false\n );\n\n addProperty(\n relClassName,\n relPropertyName,\n `${sourceClassName}.ECInstanceId`,\n false\n );\n\n if (path.sourceClassInfo?.name\n === propertyField.parent?.contentClassInfo.name) {\n addProperty(\n sourceClassName,\n propertyName,\n propertyValue,\n this.needsQuote(propertyField)\n );\n }\n });\n }\n\n private addRelatedPropertyToQuery = (\n unionIndex: number,\n isAspect: boolean,\n ) => (\n className: string,\n propertyName: string,\n propertyValue: Primitives.Value,\n needsQuote: boolean,\n ) => this.addPropertyToQuery(unionIndex, className, propertyName, propertyValue, isAspect, needsQuote, false, true);\n\n private addPropertyToQuery(\n unionIndex: number,\n className: string,\n propertyName: string,\n propertyValue: Primitives.Value,\n isAspect: boolean,\n needsQuote: boolean,\n isCategory: boolean,\n isRelational?: boolean,\n ) {\n if (this.query === undefined || this.query.unions.length === 0) {\n this.query = { unions: [] };\n }\n\n const queryProperty: QueryProperty = {\n name: propertyName,\n value: propertyValue,\n needsQuote,\n isCategory,\n };\n\n const queryClass: QueryClass = {\n className,\n isAspect,\n isRelational,\n properties: [\n queryProperty,\n ],\n };\n\n if (this.query.unions.length <= unionIndex) {\n this.query.unions.push({\n classes: [\n queryClass,\n ],\n });\n return;\n }\n\n const foundClass = this.query.unions[unionIndex].classes.find(\n (c) => c.className === className,\n );\n if (foundClass) {\n foundClass.isRelational = isRelational;\n if (!foundClass.properties.find((x) => x.name === propertyName)) {\n foundClass.properties.push(queryProperty);\n }\n } else {\n this.query.unions[unionIndex].classes.push(queryClass);\n }\n }\n\n public async removeProperty(prop: PropertyRecord) {\n if (this.query === undefined || this.query.unions.length === 0) {\n return;\n }\n if (\n this.query.unions.length === 1 &&\n this.query.unions[0].classes.length === 0\n ) {\n return;\n }\n\n const descriptor = await this.dataProvider?.getContentDescriptor();\n const propertyField = (await this.dataProvider?.getFieldByPropertyRecord(\n prop,\n )) as PropertiesField;\n if (!descriptor || !propertyField) {\n return;\n }\n\n const isAspect: boolean =\n propertyField.parent?.pathToPrimaryClass.find(\n (a) =>\n a.relationshipInfo?.name ===\n QueryBuilder.UNIQUE_ASPECT_PRIMARY_CLASS ||\n a.relationshipInfo?.name === QueryBuilder.MULTI_ASPECT_PRIMARY_CLASS,\n ) !== undefined;\n const isNavigation: boolean =\n prop.property.typename.toLowerCase() === \"navigation\";\n const isCategory: boolean = isNavigation && this.isCategory(propertyField);\n\n for (let i = 0; i < propertyField.properties.length; i++) {\n const propertyName = isNavigation\n ? isCategory\n ? `${propertyField.properties[i].property.name}.CodeValue`\n : `${propertyField.properties[i].property.name}.id`\n : propertyField.properties[i].property.name;\n const className = propertyField.properties[i].property.classInfo.name.replace(\":\", \".\");\n\n if (\n !isAspect &&\n propertyField.parent?.pathToPrimaryClass &&\n propertyField.parent?.pathToPrimaryClass.length > 0\n ) {\n this.removeRelatedProperty(i, propertyField, propertyName);\n } else {\n this.removePropertyFromQuery(i, className, propertyName);\n }\n }\n }\n\n private removeRelatedProperty(\n unionIndex: number,\n propertyField: PropertiesField,\n propertyName: string,\n ) {\n const paths = [...(propertyField.parent?.pathToPrimaryClass ?? [])];\n paths.reverse().forEach((path) => {\n const sourceClassName = path.sourceClassInfo?.name.replace(\":\", \".\");\n const targetClassName = path.targetClassInfo?.name.replace(\":\", \".\");\n const relClassName = path.relationshipInfo?.name.replace(\":\", \".\");\n\n this.removePropertyFromQuery(\n unionIndex,\n targetClassName,\n `ECInstanceId`,\n );\n\n const relPropertyName = path.isForwardRelationship ? `SourceECInstanceId` : `TargetECInstanceId`;\n this.removePropertyFromQuery(\n unionIndex,\n relClassName,\n relPropertyName,\n );\n\n if (\n path.sourceClassInfo?.name ===\n propertyField.parent?.contentClassInfo.name\n ) {\n this.removePropertyFromQuery(\n unionIndex,\n sourceClassName,\n propertyName,\n );\n }\n });\n }\n\n private removePropertyFromQuery(\n unionIndex: number,\n className: string,\n propertyName: string,\n ) {\n const foundClass = this.query?.unions[unionIndex].classes.find(\n (c) => c.className === className,\n );\n if (foundClass) {\n const foundPropertyIndex = foundClass.properties.findIndex(\n (p) => p.name === propertyName,\n );\n if (foundPropertyIndex > -1) {\n foundClass.properties.splice(foundPropertyIndex, 1);\n }\n if (foundClass.properties.length === 0) {\n // remove the entire class if all properties are removed\n const foundClassIndex =\n this.query?.unions[unionIndex].classes.findIndex(\n (c) => c.className === className,\n ) ?? -1;\n if (foundClassIndex > -1) {\n this.query?.unions[unionIndex].classes.splice(foundClassIndex, 1);\n }\n }\n }\n }\n\n public buildQueryString() {\n if (\n this.query === undefined ||\n this.query.unions.length === 0 ||\n this.query.unions[0].classes.length === 0\n ) {\n return \"\";\n }\n\n const unionSegments: string[] = [];\n for (const union of this.query.unions) {\n const querySegments: string[] = [];\n\n const baseClass = union.classes[0];\n const baseClassName = baseClass.className;\n const baseIdName = baseClass.isAspect\n ? `${baseClassName}.Element.id`\n : `${baseClassName}.ECInstanceId`;\n\n const selectSegment = `SELECT ${baseIdName}${baseClass.isAspect ? \" ECInstanceId\" : \"\"} FROM ${baseClassName}`;\n querySegments.push(selectSegment);\n\n if (union.classes.length > 1) {\n for (let i = 1; i < union.classes.length; i++) {\n const joinClass = union.classes[i];\n const joinClassName = joinClass.className;\n const joinIdName = joinClass.isAspect\n ? `${joinClassName}.Element.id`\n : `${joinClassName}.ECInstanceId`;\n\n const joinSegment = joinClass.isRelational\n ? ` JOIN ${joinClassName}`\n : ` JOIN ${joinClassName} ON ${joinIdName} = ${baseIdName}`;\n querySegments.push(joinSegment);\n\n for (let j = 0; j < joinClass.properties.length; j++) {\n const prefix = j === 0 && joinClass.isRelational ? \"ON\" : \"AND\";\n const propertySegment = this.propertySegment(joinClassName, joinClass.properties[j], prefix);\n querySegments.push(propertySegment);\n }\n // when base is regular property, link base to first joined relational property\n if (joinClass.isRelational && !baseClass.isRelational && i === 1) {\n querySegments.push(` AND ${joinIdName} = ${baseIdName}`);\n }\n }\n }\n\n const whereSegment = this.whereSegment(baseClass, baseClassName);\n querySegments.push(whereSegment);\n\n unionSegments.push(querySegments.join(\"\"));\n }\n\n return unionSegments.join(\" UNION \");\n }\n\n private whereSegment = (\n baseClass: QueryClass,\n baseClassName: string\n ): string => {\n const segments: string[] = [];\n\n const properties = baseClass.properties;\n for (let i = 0; i < properties.length; i++) {\n const prefix = i === 0 ? \"WHERE\" : \"AND\";\n segments.push(this.propertySegment(baseClassName, properties[i], prefix));\n }\n\n return segments.join(\"\");\n }\n\n private propertySegment(\n className: string,\n property: QueryProperty,\n prefix: string\n ): string {\n const segments: string[] = [];\n\n if (property.isCategory) {\n segments.push(this.categoryQuery(property.value.toString()));\n } else {\n if (property.needsQuote) {\n segments.push(` ${prefix} ${className}.${property.name}='${property.value}'`);\n } else {\n if (this.isFloat(property.value)) {\n segments.push(` ${prefix} ROUND(${className}.${property.name}, `);\n segments.push(`${QueryBuilder.DEFAULT_DOUBLE_PRECISION})=`);\n segments.push(`${Number(property.value).toFixed(\n QueryBuilder.DEFAULT_DOUBLE_PRECISION\n )}`);\n } else {\n segments.push(` ${prefix} ${className}.${property.name}=${property.value}`);\n }\n }\n }\n\n return segments.join(\"\");\n }\n\n private categoryQuery(codeValue: string): string {\n return ` JOIN bis.Category ON bis.Category.ECInstanceId = bis.GeometricElement3d.category.id AND ((bis.Category.CodeValue='${codeValue}') OR (bis.Category.UserLabel='${codeValue}'))`;\n }\n\n private isFloat(n: unknown): boolean {\n return Number(n) === n && n % 1 !== 0;\n }\n}\n"]}
1
+ {"version":3,"file":"QueryBuilder.js","sourceRoot":"","sources":["../../../../src/widget/components/QueryBuilder.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*--------------------------------------------------------------------------------------------*/\nimport type { PresentationPropertyDataProvider } from \"@itwin/presentation-components\";\nimport type {\n InstanceKey,\n PropertiesField,\n} from \"@itwin/presentation-common\";\nimport type { Primitives, PropertyRecord } from \"@itwin/appui-abstract\";\nimport { PropertyValueFormat } from \"@itwin/appui-abstract\";\nimport { toaster } from \"@itwin/itwinui-react\";\n\nexport interface Query {\n unions: QueryUnion[];\n}\n\nexport interface QueryUnion {\n classes: QueryClass[];\n properties: QueryProperty[];\n}\n\nexport interface QueryClass {\n // schemaName.className\n className: string;\n classJoins: ClassJoin[];\n}\n\nexport interface ClassJoin {\n classProperty: string;\n joinClassName: string;\n joinClassProperty: string;\n}\n\nexport interface QueryProperty {\n className: string;\n classProperties: ClassProperty[];\n isCategory: boolean;\n isAspect: boolean;\n}\n\nexport interface ClassProperty {\n name: string;\n value: Primitives.Value;\n needsQuote: boolean;\n}\n\nexport interface AddedProperty {\n propertyRecord: PropertyRecord;\n propertiesField: PropertiesField;\n}\n\n/* This class is to build adaptive and dynamic query for find similar property selections */\nexport class QueryBuilder {\n private static readonly MULTI_ASPECT_PRIMARY_CLASS =\n \"BisCore:ElementOwnsMultiAspects\";\n private static readonly UNIQUE_ASPECT_PRIMARY_CLASS =\n \"BisCore:ElementOwnsUniqueAspect\";\n private static readonly DEFAULT_DOUBLE_PRECISION = 4;\n\n private dataProvider: PresentationPropertyDataProvider;\n private query: Query | undefined;\n\n constructor(provider: PresentationPropertyDataProvider) {\n this.dataProvider = provider;\n }\n\n public resetQuery = () => {\n this.query = undefined;\n }\n\n private isCategory(propertyField: PropertiesField): boolean {\n const classInfo =\n propertyField.properties[0].property.navigationPropertyInfo?.classInfo;\n return classInfo?.name === \"BisCore:GeometricElement3dIsInCategory\";\n }\n\n private _propertyMap: Map<string, AddedProperty> = new Map();\n\n private regenerateQuery = () => {\n this.resetQuery();\n\n for (const property of this._propertyMap.values()) {\n this.buildProperty(property.propertyRecord, property.propertiesField);\n }\n }\n\n public async addProperty(prop: PropertyRecord): Promise<boolean> {\n // TODO: only handle primitive properties now\n if (prop.value?.valueFormat !== PropertyValueFormat.Primitive) {\n toaster.warning(\"Only primitive types are supported for now.\");\n return false;\n }\n if (prop.value.value === undefined) {\n return false;\n }\n\n const propertyField = (await this.dataProvider.getFieldByPropertyRecord(\n prop,\n )) as PropertiesField;\n\n if (!propertyField) {\n toaster.negative(\n \"Error. Failed to fetch field for this property record.\",\n );\n return false;\n }\n\n this._propertyMap.set(JSON.stringify(propertyField.getFieldDescriptor()), { propertyRecord: prop, propertiesField: propertyField });\n return true;\n }\n\n public async removeProperty(prop: PropertyRecord) {\n const propertyField = (await this.dataProvider.getFieldByPropertyRecord(\n prop,\n )) as PropertiesField;\n\n this._propertyMap.delete(JSON.stringify(propertyField.getFieldDescriptor()));\n }\n\n private buildProperty(prop: PropertyRecord, propertiesField: PropertiesField) {\n if (prop.value?.valueFormat !== PropertyValueFormat.Primitive || prop.value.value === undefined) {\n toaster.negative(\n \"Error. An unexpected error has occured while building a query.\",\n );\n return;\n }\n\n function replaceAll(str: string, match: string, replacement: string) {\n return str.split(match).join(replacement);\n }\n // if property value has single quote, escape\n if (\n (typeof prop.value.value === \"string\" ||\n prop.value.value instanceof String) &&\n String(prop.value.value).indexOf(\"'\") >= 0\n ) {\n prop.value.value = replaceAll(prop.value.value.toString(), \"'\", \"''\");\n }\n\n const pathToPrimaryClass = propertiesField.parent?.pathToPrimaryClass;\n\n // get the special cases\n const isNavigation: boolean =\n prop.property.typename.toLowerCase() === \"navigation\";\n const isCategory: boolean = isNavigation && this.isCategory(propertiesField);\n\n const isAspect: boolean =\n pathToPrimaryClass?.find(\n (a) =>\n a.relationshipInfo?.name ===\n QueryBuilder.UNIQUE_ASPECT_PRIMARY_CLASS ||\n a.relationshipInfo?.name === QueryBuilder.MULTI_ASPECT_PRIMARY_CLASS,\n ) !== undefined;\n\n for (let i = 0; i < propertiesField.properties.length; i++) {\n const property = propertiesField.properties[i].property;\n\n const className = property.classInfo.name.replace(\":\", \".\");\n const propertyName = isNavigation\n ? isCategory\n ? `${property.name}.CodeValue`\n : `${property.name}.id`\n : property.name;\n const propertyValue = isNavigation\n ? isCategory\n ? prop.value.displayValue ?? \"\"\n : (prop.value.value as InstanceKey).id\n : prop.value.value;\n\n if (\n !isAspect &&\n pathToPrimaryClass &&\n pathToPrimaryClass.length > 0\n ) {\n this.addRelatedToQuery(\n i,\n propertiesField,\n propertyName,\n propertyValue,\n );\n } else {\n this.addPropertyToQuery(\n i,\n className,\n propertyName,\n propertyValue,\n this.needsQuote(propertiesField),\n isCategory,\n isAspect,\n );\n }\n }\n return true;\n }\n\n private needsQuote(propertyField: PropertiesField): boolean {\n // list of property types that need quote around property value\n if (propertyField.type.typeName.toLowerCase() === \"string\") {\n return true;\n }\n if (propertyField.type.typeName.toLowerCase() === \"uri\") {\n return true;\n }\n return false;\n }\n\n private addRelatedToQuery(\n unionIndex: number,\n propertyField: PropertiesField,\n propertyName: string,\n propertyValue: Primitives.Value,\n ) {\n const paths = [...(propertyField.parent?.pathToPrimaryClass ?? [])];\n paths.reverse().forEach((path) => {\n const sourceClassName = path.sourceClassInfo?.name.replace(\":\", \".\");\n const targetClassName = path.targetClassInfo?.name.replace(\":\", \".\");\n const relClassName = path.relationshipInfo?.name.replace(\":\", \".\");\n\n const relClassProperty = path.isForwardRelationship\n ? `SourceECInstanceId`\n : `TargetECInstanceId`;\n\n const relPropertyValue = path.isForwardRelationship\n ? `TargetECInstanceId`\n : `SourceECInstanceId`;\n\n this.addClassToQuery(\n unionIndex,\n targetClassName,\n `ECInstanceId`,\n relClassName,\n relPropertyValue\n );\n\n this.addClassToQuery(\n unionIndex,\n relClassName,\n relClassProperty,\n sourceClassName,\n `ECInstanceId`\n );\n\n if (path.sourceClassInfo?.name\n === propertyField.parent?.contentClassInfo.name) {\n this.addPropertyToQuery(\n unionIndex,\n sourceClassName,\n propertyName,\n propertyValue,\n this.needsQuote(propertyField),\n false,\n false,\n );\n }\n });\n }\n\n private addClassToQuery(\n unionIndex: number,\n className: string,\n classProperty: string,\n joinClassName: string,\n joinClassProperty: string,\n ) {\n if (this.query === undefined) {\n this.query = { unions: [] };\n }\n\n const classJoin: ClassJoin = {\n classProperty,\n joinClassName,\n joinClassProperty,\n };\n\n const queryClass: QueryClass = {\n className,\n classJoins: [classJoin],\n };\n\n if (this.query.unions.length <= unionIndex) {\n this.query.unions.push({\n classes: [queryClass],\n properties: [],\n });\n return;\n }\n\n const foundClass = this.query.unions[unionIndex].classes.find((c) =>\n c.className === className\n );\n\n if (foundClass) {\n const foundJoin = foundClass.classJoins.find((join) =>\n join.classProperty === classProperty && join.joinClassName === joinClassName && join.joinClassProperty === joinClassProperty\n );\n\n if (!foundJoin)\n foundClass.classJoins.push(classJoin);\n return;\n }\n\n this.query.unions[unionIndex].classes.push(queryClass);\n }\n\n private addPropertyToQuery(\n unionIndex: number,\n className: string,\n propertyName: string,\n propertyValue: Primitives.Value,\n needsQuote: boolean,\n isCategory: boolean,\n isAspect: boolean,\n ) {\n if (this.query === undefined) {\n this.query = { unions: [] };\n }\n\n const queryJoin: ClassProperty = {\n name: propertyName,\n value: propertyValue,\n needsQuote,\n };\n\n const queryProperty: QueryProperty = {\n className,\n isCategory,\n isAspect,\n classProperties: [queryJoin],\n };\n\n if (this.query.unions.length <= unionIndex) {\n this.query.unions.push({\n classes: [],\n properties: [queryProperty],\n });\n return;\n }\n\n const foundPropertyClass = this.query.unions[unionIndex].properties.find((p) =>\n p.className === className\n );\n\n if (foundPropertyClass) {\n const foundJoin = foundPropertyClass?.classProperties.find((join) =>\n join.name === propertyName\n );\n\n if (foundJoin) {\n foundJoin.value = propertyValue;\n return;\n }\n\n foundPropertyClass.classProperties.push(queryJoin);\n return;\n }\n\n this.query.unions[unionIndex].properties.push(queryProperty);\n }\n\n public buildQueryString() {\n this.regenerateQuery();\n if (\n this.query === undefined ||\n (this.query.unions.find((u) => u.classes.length === 0 && u.properties.length === 0))\n ) {\n return \"\";\n }\n\n const unionSegments: string[] = [];\n for (const union of this.query.unions) {\n\n const baseClass = union.classes[0];\n const baseProperty = union.properties[0];\n const baseClassName = baseClass ? baseClass.className : baseProperty?.className;\n const baseIdName = `${baseClassName}.ECInstanceId`;\n\n const selectClause = this.selectClause(baseProperty, baseClass);\n\n let querySegments: Map<string, string[]> = new Map();\n querySegments = this.relationalJoinSegments(union.classes, querySegments);\n\n const whereSegments: string[] = [];\n for (const property of union.properties) {\n if (property.isCategory) {\n if (property.className !== baseClassName)\n querySegments.set(\"BisCore.GeometricElement3d\", [`BisCore.GeometricElement3d.ECInstanceId = ${baseIdName}`]);\n\n querySegments.set(\"BisCore.Category\", [`BisCore.Category.ECInstanceId = BisCore.GeometricElement3d.category.id`]);\n whereSegments.push(this.categoryWhereQuery(property.classProperties[0].value.toString()));\n continue;\n }\n\n const joinIdName = property.isAspect\n ? `${property.className}.Element.id`\n : `${property.className}.ECInstanceId`;\n\n if (!querySegments.has(property.className) && property.className !== baseClassName)\n querySegments.set(property.className, [`${joinIdName} = ${baseIdName}`]);\n\n for (const prop of property.classProperties) {\n whereSegments.push(this.propertyQuerySegment(property.className, prop, prop.needsQuote));\n }\n }\n\n const joinClauses: string[] = [];\n for (const key of querySegments.keys()) {\n joinClauses.push(`JOIN ${key} ON ${querySegments.get(key)?.join(\" AND \")}`);\n }\n\n const whereClause = `WHERE ${whereSegments.join(\" AND \")}`;\n\n unionSegments.push([selectClause, ...joinClauses, whereClause].join(\" \"));\n }\n\n return unionSegments.join(\" UNION \");\n }\n\n private selectClause(baseProperty: QueryProperty | undefined, baseClass: QueryClass | undefined) {\n if (baseClass) {\n return `SELECT ${baseClass.className}.ECInstanceId, ${baseClass.className}.ECClassId FROM ${baseClass.className}`;\n }\n\n if (baseProperty) {\n const baseIdName = baseProperty.isAspect\n ? `${baseProperty.className}.Element.id ECInstanceId`\n : `${baseProperty.className}.ECInstanceId, ${baseProperty.className}.ECClassId`;\n\n return `SELECT ${baseIdName} FROM ${baseProperty.className}`;\n }\n\n return \"\";\n }\n\n private relationalJoinSegments = (classes: QueryClass[], querySegments: Map<string, string[]>): Map<string, string[]> => {\n for (const queryClass of classes) {\n for (const classJoin of queryClass.classJoins) {\n const querySegment = [\n ...querySegments.get(classJoin.joinClassName) ?? [],\n `${queryClass.className}.${classJoin.classProperty} = ${classJoin.joinClassName}.${classJoin.joinClassProperty}`,\n ];\n querySegments.set(classJoin.joinClassName, querySegment);\n }\n }\n\n return querySegments;\n }\n\n private propertyQuerySegment = (className: string, property: ClassProperty, needsQuote: boolean): string => {\n if (this.isFloat(property.value))\n return `ROUND(${className}.${property.name}, ` +\n `${QueryBuilder.DEFAULT_DOUBLE_PRECISION}) = ` +\n `${Number(property.value).toFixed(QueryBuilder.DEFAULT_DOUBLE_PRECISION)}`;\n\n const propertyValue = needsQuote ? `'${property.value}'` : property.value;\n return `${className}.${property.name} = ${propertyValue}`;\n }\n\n private categoryWhereQuery(codeValue: string): string {\n return `((BisCore.Category.CodeValue = '${codeValue}') OR (BisCore.Category.UserLabel = '${codeValue}'))`;\n }\n\n private isFloat(n: unknown): boolean {\n return Number(n) === n && n % 1 !== 0;\n }\n}\n"]}
@@ -0,0 +1,15 @@
1
+ import * as React from "react";
2
+ import type { PropertyRecord } from "@itwin/appui-abstract";
3
+ import type { QueryBuilder } from "../QueryBuilder";
4
+ export interface PropertySelection {
5
+ currentPropertyList: PropertyRecord[];
6
+ setCurrentPropertyList: (value: PropertyRecord[]) => void;
7
+ setQuery: (value: string) => void;
8
+ queryBuilder?: QueryBuilder;
9
+ setQueryBuilder: (value: QueryBuilder | undefined) => void;
10
+ isUpdating: boolean;
11
+ resetView: () => Promise<void>;
12
+ }
13
+ export declare const PropertyGridWrapperContext: React.Context<PropertySelection>;
14
+ export declare const usePropertyGridWrapper: () => PropertySelection;
15
+ //# sourceMappingURL=PropertyGridWrapperContext.d.ts.map
@@ -19,22 +19,26 @@ var __importStar = (this && this.__importStar) || function (mod) {
19
19
  return result;
20
20
  };
21
21
  Object.defineProperty(exports, "__esModule", { value: true });
22
- exports.GroupQueryBuilderContext = void 0;
22
+ exports.usePropertyGridWrapper = exports.PropertyGridWrapperContext = void 0;
23
23
  /*---------------------------------------------------------------------------------------------
24
24
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
25
25
  * See LICENSE.md in the project root for license terms and full copyright notice.
26
26
  *--------------------------------------------------------------------------------------------*/
27
27
  const React = __importStar(require("react"));
28
- const QueryBuilder_1 = require("../QueryBuilder");
29
- exports.GroupQueryBuilderContext = React.createContext({
28
+ exports.PropertyGridWrapperContext = React.createContext({
30
29
  currentPropertyList: [],
31
30
  setCurrentPropertyList: () => [],
32
- query: "",
33
31
  setQuery: () => "",
34
- queryBuilder: new QueryBuilder_1.QueryBuilder(undefined),
35
- setQueryBuilder: () => new QueryBuilder_1.QueryBuilder(undefined),
36
- isLoading: false,
37
- isRendering: false,
32
+ setQueryBuilder: () => undefined,
33
+ isUpdating: false,
38
34
  resetView: async () => { },
39
35
  });
40
- //# sourceMappingURL=GroupQueryBuilderContext.js.map
36
+ const usePropertyGridWrapper = () => {
37
+ const context = React.useContext(exports.PropertyGridWrapperContext);
38
+ if (!context) {
39
+ throw new Error("usePropertyGridWrapperContext should be used within a PropertyGridWrapperContext provider");
40
+ }
41
+ return context;
42
+ };
43
+ exports.usePropertyGridWrapper = usePropertyGridWrapper;
44
+ //# sourceMappingURL=PropertyGridWrapperContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PropertyGridWrapperContext.js","sourceRoot":"","sources":["../../../../../src/widget/components/context/PropertyGridWrapperContext.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAAA;;;+FAG+F;AAC/F,6CAA+B;AAclB,QAAA,0BAA0B,GAAG,KAAK,CAAC,aAAa,CAAoB;IAC/E,mBAAmB,EAAE,EAAE;IACvB,sBAAsB,EAAE,GAAG,EAAE,CAAC,EAAE;IAChC,QAAQ,EAAE,GAAG,EAAE,CAAC,EAAE;IAClB,eAAe,EAAE,GAAG,EAAE,CAAC,SAAS;IAChC,UAAU,EAAE,KAAK;IACjB,SAAS,EAAE,KAAK,IAAI,EAAE,GAAG,CAAC;CAC3B,CAAC,CAAC;AAEI,MAAM,sBAAsB,GAAG,GAAsB,EAAE;IAC5D,MAAM,OAAO,GAAG,KAAK,CAAC,UAAU,CAAC,kCAA0B,CAAC,CAAC;IAC7D,IAAI,CAAC,OAAO,EAAE;QACZ,MAAM,IAAI,KAAK,CACb,2FAA2F,CAC5F,CAAC;KACH;IACD,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC;AARW,QAAA,sBAAsB,0BAQjC","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*--------------------------------------------------------------------------------------------*/\nimport * as React from \"react\";\nimport type { PropertyRecord } from \"@itwin/appui-abstract\";\nimport type { QueryBuilder } from \"../QueryBuilder\";\n\nexport interface PropertySelection {\n currentPropertyList: PropertyRecord[];\n setCurrentPropertyList: (value: PropertyRecord[]) => void;\n setQuery: (value: string) => void;\n queryBuilder?: QueryBuilder;\n setQueryBuilder: (value: QueryBuilder | undefined) => void;\n isUpdating: boolean;\n resetView: () => Promise<void>;\n}\n\nexport const PropertyGridWrapperContext = React.createContext<PropertySelection>({\n currentPropertyList: [],\n setCurrentPropertyList: () => [],\n setQuery: () => \"\",\n setQueryBuilder: () => undefined,\n isUpdating: false,\n resetView: async () => { },\n});\n\nexport const usePropertyGridWrapper = (): PropertySelection => {\n const context = React.useContext(PropertyGridWrapperContext);\n if (!context) {\n throw new Error(\n \"usePropertyGridWrapperContext should be used within a PropertyGridWrapperContext provider\"\n );\n }\n return context;\n};\n"]}