@finos/legend-query-builder 4.14.69 → 4.14.71

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. package/lib/__lib__/QueryBuilderTesting.d.ts +1 -0
  2. package/lib/__lib__/QueryBuilderTesting.d.ts.map +1 -1
  3. package/lib/__lib__/QueryBuilderTesting.js +1 -0
  4. package/lib/__lib__/QueryBuilderTesting.js.map +1 -1
  5. package/lib/components/QueryBuilderConstantExpressionPanel.d.ts.map +1 -1
  6. package/lib/components/QueryBuilderConstantExpressionPanel.js +2 -1
  7. package/lib/components/QueryBuilderConstantExpressionPanel.js.map +1 -1
  8. package/lib/components/explorer/QueryBuilderExplorerPanel.d.ts +1 -0
  9. package/lib/components/explorer/QueryBuilderExplorerPanel.d.ts.map +1 -1
  10. package/lib/components/explorer/QueryBuilderExplorerPanel.js +87 -52
  11. package/lib/components/explorer/QueryBuilderExplorerPanel.js.map +1 -1
  12. package/lib/components/explorer/QueryBuilderPropertySearchPanel.d.ts +4 -0
  13. package/lib/components/explorer/QueryBuilderPropertySearchPanel.d.ts.map +1 -1
  14. package/lib/components/explorer/QueryBuilderPropertySearchPanel.js +172 -108
  15. package/lib/components/explorer/QueryBuilderPropertySearchPanel.js.map +1 -1
  16. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.d.ts.map +1 -1
  17. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.js +2 -1
  18. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.js.map +1 -1
  19. package/lib/components/fetch-structure/QueryBuilderTDSPanel.d.ts.map +1 -1
  20. package/lib/components/fetch-structure/QueryBuilderTDSPanel.js +29 -18
  21. package/lib/components/fetch-structure/QueryBuilderTDSPanel.js.map +1 -1
  22. package/lib/components/fetch-structure/QueryBuilderTDSWindowPanel.d.ts.map +1 -1
  23. package/lib/components/fetch-structure/QueryBuilderTDSWindowPanel.js +13 -4
  24. package/lib/components/fetch-structure/QueryBuilderTDSWindowPanel.js.map +1 -1
  25. package/lib/components/filter/QueryBuilderFilterPanel.d.ts.map +1 -1
  26. package/lib/components/filter/QueryBuilderFilterPanel.js +4 -3
  27. package/lib/components/filter/QueryBuilderFilterPanel.js.map +1 -1
  28. package/lib/components/result/QueryBuilderResultPanel.d.ts +12 -0
  29. package/lib/components/result/QueryBuilderResultPanel.d.ts.map +1 -1
  30. package/lib/components/result/QueryBuilderResultPanel.js +60 -8
  31. package/lib/components/result/QueryBuilderResultPanel.js.map +1 -1
  32. package/lib/components/shared/QueryBuilderFilterHelper.d.ts.map +1 -1
  33. package/lib/components/shared/QueryBuilderFilterHelper.js +3 -0
  34. package/lib/components/shared/QueryBuilderFilterHelper.js.map +1 -1
  35. package/lib/components/shared/QueryBuilderPropertyInfoTooltip.d.ts +11 -0
  36. package/lib/components/shared/QueryBuilderPropertyInfoTooltip.d.ts.map +1 -1
  37. package/lib/components/shared/QueryBuilderPropertyInfoTooltip.js +6 -3
  38. package/lib/components/shared/QueryBuilderPropertyInfoTooltip.js.map +1 -1
  39. package/lib/graph-manager/QueryBuilderConfig.d.ts +4 -0
  40. package/lib/graph-manager/QueryBuilderConfig.d.ts.map +1 -1
  41. package/lib/graph-manager/QueryBuilderConfig.js +5 -0
  42. package/lib/graph-manager/QueryBuilderConfig.js.map +1 -1
  43. package/lib/index.css +2 -2
  44. package/lib/index.css.map +1 -1
  45. package/lib/package.json +1 -1
  46. package/lib/stores/QueryBuilderConstantsState.d.ts +1 -0
  47. package/lib/stores/QueryBuilderConstantsState.d.ts.map +1 -1
  48. package/lib/stores/QueryBuilderConstantsState.js +6 -1
  49. package/lib/stores/QueryBuilderConstantsState.js.map +1 -1
  50. package/lib/stores/QueryBuilderResultState.d.ts +11 -3
  51. package/lib/stores/QueryBuilderResultState.d.ts.map +1 -1
  52. package/lib/stores/QueryBuilderResultState.js +47 -4
  53. package/lib/stores/QueryBuilderResultState.js.map +1 -1
  54. package/lib/stores/QueryBuilderValueSpecificationBuilderHelper.d.ts +4 -0
  55. package/lib/stores/QueryBuilderValueSpecificationBuilderHelper.d.ts.map +1 -1
  56. package/lib/stores/explorer/QueryBuilderExplorerState.d.ts +3 -1
  57. package/lib/stores/explorer/QueryBuilderExplorerState.d.ts.map +1 -1
  58. package/lib/stores/explorer/QueryBuilderExplorerState.js +63 -8
  59. package/lib/stores/explorer/QueryBuilderExplorerState.js.map +1 -1
  60. package/lib/stores/explorer/QueryBuilderFuzzySearchAdvancedConfigState.d.ts +24 -0
  61. package/lib/stores/explorer/QueryBuilderFuzzySearchAdvancedConfigState.d.ts.map +1 -0
  62. package/lib/stores/explorer/QueryBuilderFuzzySearchAdvancedConfigState.js +39 -0
  63. package/lib/stores/explorer/QueryBuilderFuzzySearchAdvancedConfigState.js.map +1 -0
  64. package/lib/stores/explorer/QueryBuilderPropertySearchState.d.ts +8 -4
  65. package/lib/stores/explorer/QueryBuilderPropertySearchState.d.ts.map +1 -1
  66. package/lib/stores/explorer/QueryBuilderPropertySearchState.js +204 -114
  67. package/lib/stores/explorer/QueryBuilderPropertySearchState.js.map +1 -1
  68. package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.d.ts.map +1 -1
  69. package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.js +8 -1
  70. package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.js.map +1 -1
  71. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionValueSpecificationBuilder.d.ts.map +1 -1
  72. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionValueSpecificationBuilder.js +12 -1
  73. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionValueSpecificationBuilder.js.map +1 -1
  74. package/lib/stores/filter/QueryBuilderFilterState.d.ts +8 -1
  75. package/lib/stores/filter/QueryBuilderFilterState.d.ts.map +1 -1
  76. package/lib/stores/filter/QueryBuilderFilterState.js +27 -10
  77. package/lib/stores/filter/QueryBuilderFilterState.js.map +1 -1
  78. package/package.json +8 -8
  79. package/src/__lib__/QueryBuilderTesting.ts +1 -0
  80. package/src/components/QueryBuilderConstantExpressionPanel.tsx +2 -1
  81. package/src/components/explorer/QueryBuilderExplorerPanel.tsx +220 -114
  82. package/src/components/explorer/QueryBuilderPropertySearchPanel.tsx +618 -388
  83. package/src/components/fetch-structure/QueryBuilderPostFilterPanel.tsx +5 -2
  84. package/src/components/fetch-structure/QueryBuilderTDSPanel.tsx +78 -44
  85. package/src/components/fetch-structure/QueryBuilderTDSWindowPanel.tsx +63 -10
  86. package/src/components/filter/QueryBuilderFilterPanel.tsx +4 -2
  87. package/src/components/result/QueryBuilderResultPanel.tsx +207 -20
  88. package/src/components/shared/QueryBuilderFilterHelper.ts +8 -0
  89. package/src/components/shared/QueryBuilderPropertyInfoTooltip.tsx +13 -3
  90. package/src/graph-manager/QueryBuilderConfig.ts +6 -0
  91. package/src/stores/QueryBuilderConstantsState.ts +16 -1
  92. package/src/stores/QueryBuilderResultState.ts +64 -10
  93. package/src/stores/QueryBuilderValueSpecificationBuilderHelper.ts +5 -0
  94. package/src/stores/explorer/QueryBuilderExplorerState.ts +92 -8
  95. package/src/stores/explorer/QueryBuilderFuzzySearchAdvancedConfigState.ts +46 -0
  96. package/src/stores/explorer/QueryBuilderPropertySearchState.ts +280 -142
  97. package/src/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.ts +8 -1
  98. package/src/stores/fetch-structure/tds/projection/QueryBuilderProjectionValueSpecificationBuilder.ts +15 -2
  99. package/src/stores/filter/QueryBuilderFilterState.ts +34 -11
  100. package/tsconfig.json +1 -0
@@ -14,7 +14,6 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- import { useMemo, useRef, useState } from 'react';
18
17
  import {
19
18
  clsx,
20
19
  CheckSquareIcon,
@@ -25,21 +24,29 @@ import {
25
24
  ResizablePanel,
26
25
  ResizablePanelSplitterLine,
27
26
  InfoCircleIcon,
28
- TimesIcon,
29
- SearchIcon,
30
27
  useDragPreviewLayer,
31
28
  PanelLoadingIndicator,
32
29
  BlankPanelContent,
33
- CogIcon,
30
+ ChevronDownIcon,
31
+ ChevronRightIcon,
32
+ ShareBoxIcon,
33
+ Tooltip,
34
+ BaseRadioGroup,
35
+ ClickAwayListener,
34
36
  } from '@finos/legend-art';
35
37
  import {
38
+ CORE_PURE_PATH,
36
39
  Class,
40
+ ELEMENT_PATH_DELIMITER,
37
41
  Enumeration,
42
+ PROPERTY_ACCESSOR,
43
+ PURE_DOC_TAG,
44
+ TYPE_CAST_TOKEN,
38
45
  getAllClassProperties,
39
46
  getAllOwnClassProperties,
40
47
  } from '@finos/legend-graph';
41
48
  import {
42
- debounce,
49
+ ADVANCED_FUZZY_SEARCH_MODE,
43
50
  guaranteeNonNullable,
44
51
  prettyCONSTName,
45
52
  } from '@finos/legend-shared';
@@ -56,59 +63,171 @@ import {
56
63
  } from '../../stores/explorer/QueryBuilderExplorerState.js';
57
64
  import type { QueryBuilderState } from '../../stores/QueryBuilderState.js';
58
65
  import {
66
+ QUERY_BUILDER_EXPLORER_SEARCH_INPUT_NAME,
59
67
  QueryBuilderSubclassInfoTooltip,
60
68
  renderPropertyTypeIcon,
61
69
  } from './QueryBuilderExplorerPanel.js';
62
70
  import { QueryBuilderPropertyInfoTooltip } from '../shared/QueryBuilderPropertyInfoTooltip.js';
63
71
  import { QUERY_BUILDER_TEST_ID } from '../../__lib__/QueryBuilderTesting.js';
64
- import { FuzzySearchAdvancedConfigMenu } from '@finos/legend-lego/application';
72
+ import { DocumentationLink } from '@finos/legend-lego/application';
73
+ import { LEGEND_APPLICATION_DOCUMENTATION_KEY } from '@finos/legend-application';
65
74
 
66
- const prettyPropertyNameFromNodeId = (name: string): string => {
67
- let propNameArray = name.split('.');
68
- propNameArray = propNameArray.map(prettyCONSTName);
69
- let propName = '';
70
- propNameArray.forEach((p) => {
71
- propName = `${propName + p}/`;
72
- });
73
- propName = propName.slice(0, -1);
74
- return propName;
75
- };
75
+ export const prettyPropertyNameFromNodeId = (
76
+ name: string,
77
+ spaceBetweenSlash?: boolean,
78
+ ): string =>
79
+ name
80
+ .split(TYPE_CAST_TOKEN)
81
+ .map((p) =>
82
+ p.replace(new RegExp(String.raw`.*${ELEMENT_PATH_DELIMITER}`), ''),
83
+ )
84
+ .filter((p) => p !== '')
85
+ .map((p) =>
86
+ p
87
+ .split(PROPERTY_ACCESSOR)
88
+ .map(prettyCONSTName)
89
+ .join(spaceBetweenSlash ? ' / ' : '/'),
90
+ )
91
+ .join(TYPE_CAST_TOKEN);
76
92
 
77
- const prettyPropertyNameForSubType = (name: string): string => {
78
- let propNameArray = name.split('@');
93
+ export const prettyPropertyNameForSubType = (
94
+ name: string,
95
+ spaceBetweenSlash?: boolean,
96
+ ): string => {
97
+ let propNameArray = name.split(TYPE_CAST_TOKEN);
79
98
  propNameArray = propNameArray
80
- .map((p) => p.replace(/.*::/, ''))
81
- .filter((p) => p !== '')
82
- .map((p) => prettyCONSTName(p));
83
- let propName = '';
84
- propNameArray.slice(0, -1).forEach((p) => {
85
- propName = `${propName}(@${p})/`;
86
- });
99
+ .map((p) =>
100
+ p.replace(new RegExp(String.raw`.*${ELEMENT_PATH_DELIMITER}`), ''),
101
+ )
102
+ .filter((p) => p !== '');
103
+ let propName = propNameArray
104
+ .slice(0, -1)
105
+ .map(
106
+ (p) =>
107
+ `(${TYPE_CAST_TOKEN}${p
108
+ .split(PROPERTY_ACCESSOR)
109
+ .map((sp) => prettyCONSTName(sp))
110
+ .join(spaceBetweenSlash ? ' / ' : '/')})`,
111
+ )
112
+ .join(spaceBetweenSlash ? ' / ' : '/');
113
+ propName += spaceBetweenSlash ? ' / ' : '/';
87
114
  propNameArray = guaranteeNonNullable(
88
115
  propNameArray[propNameArray.length - 1],
89
- ).split('.');
116
+ ).split(PROPERTY_ACCESSOR);
90
117
  propNameArray = propNameArray.map((p) => prettyCONSTName(p));
91
- propName = `${propName}(@${propNameArray[0]})/`;
118
+ propName = `${propName}(${TYPE_CAST_TOKEN}${propNameArray[0]})${spaceBetweenSlash ? ' / ' : '/'}`;
92
119
  propNameArray.slice(1).forEach((p) => {
93
- propName = `${propName + p}/`;
120
+ propName = `${propName + p}${spaceBetweenSlash ? ' / ' : '/'}`;
94
121
  });
95
- propName = propName.slice(0, -1);
122
+ propName = propName.slice(0, spaceBetweenSlash ? -3 : -1);
96
123
  return propName;
97
124
  };
98
125
 
99
- const prettyPropertyNameForSubTypeClass = (name: string): string => {
100
- let propNameArray = name.split('@');
101
- propNameArray = propNameArray
102
- .map((p) => p.replace(/.*::/, ''))
103
- .filter((p) => p !== '')
104
- .map((p) => prettyCONSTName(p));
105
- let propName = '';
106
- propNameArray.forEach((p) => {
107
- propName = `${propName}@${p}`;
126
+ export const formatTextWithHighlightedMatches = (
127
+ displayText: string,
128
+ searchText: string,
129
+ className: string,
130
+ id: string,
131
+ ): React.ReactNode => {
132
+ // Get ranges to highlight
133
+ const highlightRanges: [number, number][] = [];
134
+ searchText
135
+ .split(/\/| /)
136
+ .filter((word) => word.trim().length > 0)
137
+ .forEach((word) => {
138
+ const regex = new RegExp(word, 'gi');
139
+ let match;
140
+ while ((match = regex.exec(displayText))) {
141
+ highlightRanges.push([match.index, match.index + word.length]);
142
+ }
143
+ });
144
+
145
+ // Combine any overlapping highlight ranges
146
+ const combinedHighlightRanges: [number, number][] = [];
147
+ highlightRanges.sort((a, b) => a[0] - b[0]);
148
+ highlightRanges.forEach((range) => {
149
+ if (!combinedHighlightRanges.length) {
150
+ combinedHighlightRanges.push(range);
151
+ } else {
152
+ const lastRange =
153
+ combinedHighlightRanges[combinedHighlightRanges.length - 1];
154
+ if (lastRange !== undefined && range[0] <= lastRange[1]) {
155
+ lastRange[1] = Math.max(lastRange[1], range[1]);
156
+ } else {
157
+ combinedHighlightRanges.push(range);
158
+ }
159
+ }
108
160
  });
109
- return propName;
161
+
162
+ // Return the property name if there are no highlight ranges
163
+ if (!combinedHighlightRanges.length) {
164
+ return <span>{displayText}</span>;
165
+ }
166
+
167
+ // Create formatted node
168
+ const formattedNode: React.ReactNode[] = [];
169
+ if (combinedHighlightRanges[0]![0] > 0) {
170
+ formattedNode.push(
171
+ <span
172
+ key={`${id}-0-${displayText.substring(0, combinedHighlightRanges[0]![0])}`}
173
+ >
174
+ {displayText.substring(0, combinedHighlightRanges[0]![0])}
175
+ </span>,
176
+ );
177
+ }
178
+
179
+ combinedHighlightRanges.forEach((range, index) => {
180
+ formattedNode.push(
181
+ <span
182
+ key={`${id}-${index * 2}-${displayText.substring(range[0], range[1])}`}
183
+ className={`${className}--highlight`}
184
+ >
185
+ {displayText.substring(range[0], range[1])}
186
+ </span>,
187
+ );
188
+ if (
189
+ index < combinedHighlightRanges.length - 1 &&
190
+ range[1] < displayText.length
191
+ ) {
192
+ formattedNode.push(
193
+ <span
194
+ key={`${id}-${index * 2 + 1}--${displayText.substring(
195
+ range[1],
196
+ combinedHighlightRanges[index + 1]![0],
197
+ )}`}
198
+ >
199
+ {displayText.substring(
200
+ range[1],
201
+ combinedHighlightRanges[index + 1]![0],
202
+ )}
203
+ </span>,
204
+ );
205
+ }
206
+ });
207
+ if (
208
+ combinedHighlightRanges[combinedHighlightRanges.length - 1]![1] <
209
+ displayText.length
210
+ ) {
211
+ formattedNode.push(
212
+ <span
213
+ key={`${id}-${combinedHighlightRanges.length * 2 + 2}-${displayText.substring(
214
+ combinedHighlightRanges[combinedHighlightRanges.length - 1]![1],
215
+ )}`}
216
+ >
217
+ {displayText.substring(
218
+ combinedHighlightRanges[combinedHighlightRanges.length - 1]![1],
219
+ )}
220
+ </span>,
221
+ );
222
+ }
223
+ return formattedNode;
110
224
  };
111
225
 
226
+ const QUERY_BUILDER_PROPERTY_SEARCH_LABEL_TEXT_CLASS =
227
+ 'query-builder-property-search-panel__node__label';
228
+ const QUERY_BUILDER_PROPERTY_SEARCH_DOC_TEXT_CLASS =
229
+ 'query-builder-property-search-panel__node__doc';
230
+
112
231
  const QueryBuilderTreeNodeViewer = observer(
113
232
  (props: {
114
233
  node: QueryBuilderExplorerTreeNodeData;
@@ -119,8 +238,9 @@ const QueryBuilderTreeNodeViewer = observer(
119
238
  }) => {
120
239
  const { node, queryBuilderState, explorerState, level, stepPaddingInRem } =
121
240
  props;
122
- const [isExpandable, setIsExpandable] = useState(false);
241
+ const isExpandable = Boolean(node.childrenIds.length);
123
242
  const propertySearchState = explorerState.propertySearchState;
243
+
124
244
  const [, dragConnector, dragPreviewConnector] = useDrag<{
125
245
  node?: QueryBuilderExplorerTreePropertyNodeData;
126
246
  }>(
@@ -143,6 +263,7 @@ const QueryBuilderTreeNodeViewer = observer(
143
263
  }),
144
264
  [node],
145
265
  );
266
+
146
267
  useDragPreviewLayer(dragPreviewConnector);
147
268
 
148
269
  const getChildrenNodes = (): QueryBuilderExplorerTreeNodeData[] => {
@@ -177,20 +298,55 @@ const QueryBuilderTreeNodeViewer = observer(
177
298
  }
178
299
  return childNodes;
179
300
  };
301
+
302
+ const handleHighlightNode = (): void => {
303
+ explorerState.propertySearchState.setIsSearchPanelOpen(false);
304
+ explorerState.propertySearchState.resetSearch();
305
+ explorerState.highlightTreeNode(node.id);
306
+ };
307
+
180
308
  const parentNode = propertySearchState.indexedExplorerTreeNodes.find(
181
309
  (pn) =>
182
310
  node instanceof QueryBuilderExplorerTreePropertyNodeData &&
183
311
  node.parentId === pn.id,
184
312
  );
313
+
185
314
  const propertyName =
186
315
  parentNode instanceof QueryBuilderExplorerTreeSubTypeNodeData
187
- ? prettyPropertyNameForSubType(node.id)
188
- : node instanceof QueryBuilderExplorerTreeSubTypeNodeData
189
- ? prettyPropertyNameForSubTypeClass(node.id)
190
- : prettyPropertyNameFromNodeId(node.id);
316
+ ? prettyPropertyNameForSubType(node.id, true)
317
+ : prettyPropertyNameFromNodeId(node.id, true);
318
+
319
+ const nodeExpandIcon = isExpandable ? (
320
+ node.isOpen ? (
321
+ <ChevronDownIcon />
322
+ ) : (
323
+ <ChevronRightIcon />
324
+ )
325
+ ) : (
326
+ <div />
327
+ );
328
+
329
+ const docText: string | null =
330
+ node instanceof QueryBuilderExplorerTreePropertyNodeData
331
+ ? (node.property.taggedValues.find(
332
+ (taggedValue) =>
333
+ taggedValue.tag.ownerReference.value.path ===
334
+ CORE_PURE_PATH.PROFILE_DOC &&
335
+ taggedValue.tag.value.value === PURE_DOC_TAG,
336
+ )?.value ?? null)
337
+ : null;
338
+ const formattedDocText =
339
+ docText !== null
340
+ ? formatTextWithHighlightedMatches(
341
+ docText,
342
+ propertySearchState.searchText,
343
+ QUERY_BUILDER_PROPERTY_SEARCH_DOC_TEXT_CLASS,
344
+ `${node.id}_doc`,
345
+ )
346
+ : null;
191
347
 
192
348
  return (
193
- <div>
349
+ <>
194
350
  <div
195
351
  className="tree-view__node__container query-builder-property-search-panel__node__container"
196
352
  ref={dragConnector}
@@ -198,7 +354,7 @@ const QueryBuilderTreeNodeViewer = observer(
198
354
  paddingLeft: `${(level - 1) * stepPaddingInRem + 0.5}rem`,
199
355
  display: 'flex',
200
356
  }}
201
- onClick={(): void => setIsExpandable(!isExpandable)}
357
+ onClick={(): void => node.setIsOpen(!node.isOpen)}
202
358
  // Temporarily hide away the panel when we drag-and-drop the properties
203
359
  onDrag={(): void => propertySearchState.setIsSearchPanelHidden(true)}
204
360
  onDragEnd={(): void =>
@@ -206,52 +362,89 @@ const QueryBuilderTreeNodeViewer = observer(
206
362
  }
207
363
  >
208
364
  <div className="tree-view__node__icon query-builder-property-search-panel__node__icon">
365
+ <div className="query-builder-property-search-panel__expand-icon">
366
+ {nodeExpandIcon}
367
+ </div>
209
368
  <div className="query-builder-property-search-panel__type-icon">
210
369
  {renderPropertyTypeIcon(node.type)}
211
370
  </div>
212
371
  </div>
213
- <div className="tree-view__node__label query-builder-property-search-panel__node__label query-builder-property-search-panel__node__label--with-action">
214
- {propertyName}
372
+ <div className="query-builder-property-search-panel__node__content">
373
+ <div className="tree-view__node__label query-builder-property-search-panel__node__label">
374
+ {formatTextWithHighlightedMatches(
375
+ propertyName,
376
+ propertySearchState.searchText,
377
+ QUERY_BUILDER_PROPERTY_SEARCH_LABEL_TEXT_CLASS,
378
+ node.id,
379
+ )}
380
+ </div>
381
+ <div className="tree-view__node__label query-builder-property-search-panel__node__doc">
382
+ {formattedDocText}
383
+ </div>
215
384
  </div>
216
385
  <div className="query-builder-property-search-panel__node__actions">
217
386
  {node instanceof QueryBuilderExplorerTreePropertyNodeData && (
218
- <QueryBuilderPropertyInfoTooltip
219
- title={propertyName}
220
- property={node.property}
221
- path={node.id}
222
- isMapped={node.mappingData.mapped}
223
- >
224
- <div className="query-builder-property-search-panel__node__action query-builder-property-search-panel__node__info">
225
- <InfoCircleIcon />
226
- </div>
227
- </QueryBuilderPropertyInfoTooltip>
387
+ <>
388
+ <QueryBuilderPropertyInfoTooltip
389
+ title={propertyName}
390
+ property={node.property}
391
+ path={node.id}
392
+ isMapped={node.mappingData.mapped}
393
+ >
394
+ <div
395
+ title="Property info"
396
+ className="query-builder-property-search-panel__node__action query-builder-property-search-panel__node__info"
397
+ >
398
+ <InfoCircleIcon />
399
+ </div>
400
+ </QueryBuilderPropertyInfoTooltip>
401
+ <button
402
+ onClick={handleHighlightNode}
403
+ title="Show in tree"
404
+ className="query-builder-property-search-panel__node__action query-builder-property-search-panel__node__highlight"
405
+ >
406
+ <ShareBoxIcon />
407
+ </button>
408
+ </>
228
409
  )}
229
410
  {node instanceof QueryBuilderExplorerTreeSubTypeNodeData && (
230
- <QueryBuilderSubclassInfoTooltip
231
- subclass={node.subclass}
232
- path={node.id}
233
- isMapped={node.mappingData.mapped}
234
- multiplicity={node.multiplicity}
235
- >
236
- <div className="query-builder-property-search-panel__node__action query-builder-property-search-panel__node__info">
237
- <InfoCircleIcon />
238
- </div>
239
- </QueryBuilderSubclassInfoTooltip>
411
+ <>
412
+ <QueryBuilderSubclassInfoTooltip
413
+ subclass={node.subclass}
414
+ path={node.id}
415
+ isMapped={node.mappingData.mapped}
416
+ multiplicity={node.multiplicity}
417
+ >
418
+ <div
419
+ title="Property info"
420
+ className="query-builder-property-search-panel__node__action query-builder-property-search-panel__node__info"
421
+ >
422
+ <InfoCircleIcon />
423
+ </div>
424
+ </QueryBuilderSubclassInfoTooltip>
425
+ <button
426
+ onClick={handleHighlightNode}
427
+ title="Show in tree"
428
+ className="query-builder-property-search-panel__node__action query-builder-property-search-panel__node__highlight"
429
+ >
430
+ <ShareBoxIcon />
431
+ </button>
432
+ </>
240
433
  )}
241
434
  </div>
242
435
  </div>
243
- {isExpandable &&
436
+ {node.isOpen &&
244
437
  getChildrenNodes().map((childNode) => (
245
438
  <QueryBuilderTreeNodeViewer
246
- key={childNode.id}
439
+ key={`${node.id}>${childNode.id}`}
247
440
  node={childNode}
248
441
  queryBuilderState={queryBuilderState}
249
- level={1}
442
+ level={level + 1}
250
443
  stepPaddingInRem={2}
251
444
  explorerState={queryBuilderState.explorerState}
252
445
  />
253
446
  ))}
254
- </div>
447
+ </>
255
448
  );
256
449
  },
257
450
  );
@@ -260,41 +453,54 @@ export const QueryBuilderPropertySearchPanel = observer(
260
453
  (props: {
261
454
  queryBuilderState: QueryBuilderState;
262
455
  triggerElement: HTMLElement | null;
456
+ clearSearch: () => void;
263
457
  }) => {
264
- const { queryBuilderState, triggerElement } = props;
458
+ const { queryBuilderState, triggerElement, clearSearch } = props;
265
459
  const explorerState = queryBuilderState.explorerState;
266
460
  const propertySearchState = explorerState.propertySearchState;
267
- const searchInputRef = useRef<HTMLInputElement>(null);
268
- const searchConfigTriggerRef = useRef<HTMLButtonElement>(null);
269
461
 
270
- // search text
271
- const debouncedSearchProperty = useMemo(
272
- () => debounce(() => propertySearchState.search(), 100),
273
- [propertySearchState],
274
- );
275
- const onSearchPropertyTextChange: React.ChangeEventHandler<
276
- HTMLInputElement
277
- > = (event) => {
278
- propertySearchState.setSearchText(event.target.value);
279
- debouncedSearchProperty();
462
+ const handleClose = (event: MouseEvent | TouchEvent): void => {
463
+ if (
464
+ event.target instanceof HTMLInputElement &&
465
+ event.target.name === QUERY_BUILDER_EXPLORER_SEARCH_INPUT_NAME
466
+ ) {
467
+ return;
468
+ }
469
+ clearSearch();
470
+ propertySearchState.setIsSearchPanelOpen(false);
280
471
  };
281
472
 
282
- // search actions
283
- const clearSearch = (): void => {
284
- propertySearchState.resetSearch();
473
+ const handleSearchMode: React.ChangeEventHandler<HTMLInputElement> = (
474
+ event,
475
+ ): void => {
476
+ const searchMode = event.target.value as ADVANCED_FUZZY_SEARCH_MODE;
477
+ propertySearchState.searchConfigurationState.setCurrentMode(searchMode);
285
478
  };
286
- const toggleSearchConfigMenu = (): void =>
287
- propertySearchState.setShowSearchConfigurationMenu(
288
- !propertySearchState.showSearchConfigurationMenu,
479
+
480
+ const handleToggleIncludeSubTypes = () => {
481
+ (async () => {
482
+ propertySearchState.searchConfigurationState.setIncludeSubTypes(
483
+ !propertySearchState.searchConfigurationState.includeSubTypes,
484
+ );
485
+ await propertySearchState.initialize();
486
+ await propertySearchState.search();
487
+ })().catch(
488
+ propertySearchState.queryBuilderState.applicationStore
489
+ .alertUnhandledError,
289
490
  );
290
- const closeSearchConfigMenu = (): void =>
291
- propertySearchState.setShowSearchConfigurationMenu(false);
491
+ };
292
492
 
293
- // life-cycle
294
- const handleEnter = (): void => searchInputRef.current?.focus();
295
- const handleClose = (): void => {
296
- clearSearch();
297
- propertySearchState.setIsSearchPanelOpen(false);
493
+ const handleToggleIncludeDocumentation = () => {
494
+ (async () => {
495
+ propertySearchState.searchConfigurationState.setIncludeDocumentation(
496
+ !propertySearchState.searchConfigurationState.includeDocumentation,
497
+ );
498
+ await propertySearchState.initialize();
499
+ await propertySearchState.search();
500
+ })().catch(
501
+ propertySearchState.queryBuilderState.applicationStore
502
+ .alertUnhandledError,
503
+ );
298
504
  };
299
505
 
300
506
  return (
@@ -311,319 +517,343 @@ export const QueryBuilderPropertySearchPanel = observer(
311
517
  })}
312
518
  anchorEl={triggerElement}
313
519
  onClose={handleClose}
520
+ hideBackdrop={true}
521
+ disableAutoFocus={true}
522
+ disableEnforceFocus={true}
314
523
  anchorOrigin={{
315
- vertical: 'bottom',
524
+ vertical: 40,
316
525
  horizontal: 'left',
317
526
  }}
318
527
  transformOrigin={{
319
528
  vertical: 'top',
320
529
  horizontal: 'center',
321
530
  }}
322
- TransitionProps={{ onEnter: handleEnter }}
323
531
  >
324
- <div
325
- data-testid={
326
- QUERY_BUILDER_TEST_ID.QUERY_BUILDER_PROPERTY_SEARCH_PANEL
327
- }
328
- className="query-builder-property-search-panel"
329
- >
330
- <div className="query-builder-property-search-panel__header">
331
- <div className="query-builder-property-search-panel__input__container">
332
- <input
333
- ref={searchInputRef}
334
- className={clsx(
335
- 'query-builder-property-search-panel__input input--dark',
336
- {
337
- 'query-builder-property-search-panel__input--searching':
338
- propertySearchState.searchText,
339
- },
340
- )}
341
- spellCheck={false}
342
- onChange={onSearchPropertyTextChange}
343
- value={propertySearchState.searchText}
344
- placeholder="Search for a property by name or documentation"
345
- />
346
- {propertySearchState.searchText && (
347
- <div className="query-builder-property-search-panel__input__search__count">
348
- {propertySearchState.filteredSearchResults.length +
349
- (propertySearchState.isOverSearchLimit &&
350
- propertySearchState.filteredSearchResults.length !== 0
351
- ? '+'
352
- : '')}
353
- </div>
354
- )}
355
- <button
356
- ref={searchConfigTriggerRef}
357
- className={clsx(
358
- 'query-builder-property-search-panel__input__search__config__trigger',
359
- {
360
- 'query-builder-property-search-panel__input__search__config__trigger--toggled':
361
- propertySearchState.showSearchConfigurationMenu,
362
- 'query-builder-property-search-panel__input__search__config__trigger--active':
363
- propertySearchState.searchConfigurationState
364
- .isAdvancedSearchActive,
365
- },
366
- )}
367
- tabIndex={-1}
368
- onClick={toggleSearchConfigMenu}
369
- title="Click to toggle search config menu"
370
- >
371
- <CogIcon />
372
- </button>
373
- <BasePopover
374
- open={Boolean(propertySearchState.showSearchConfigurationMenu)}
375
- TransitionProps={{
376
- onEnter: handleEnter,
377
- }}
378
- anchorEl={searchConfigTriggerRef.current}
379
- onClose={closeSearchConfigMenu}
380
- anchorOrigin={{
381
- vertical: 'bottom',
382
- horizontal: 'center',
383
- }}
384
- transformOrigin={{
385
- vertical: 'top',
386
- horizontal: 'center',
387
- }}
388
- >
389
- <FuzzySearchAdvancedConfigMenu
390
- configState={propertySearchState.searchConfigurationState}
391
- />
392
- </BasePopover>
393
- {!propertySearchState.searchText ? (
394
- <>
395
- <div className="query-builder-property-search-panel__input__search__icon">
396
- <SearchIcon />
397
- </div>
398
- </>
399
- ) : (
400
- <button
401
- className="query-builder-property-search-panel__input__clear-btn"
402
- tabIndex={-1}
403
- onClick={clearSearch}
404
- title="Clear"
405
- >
406
- <TimesIcon />
407
- </button>
408
- )}
409
- </div>
410
- <button
411
- className="btn btn--dark query-builder-property-search-panel__close-btn"
412
- tabIndex={-1}
413
- title="Close"
414
- onClick={handleClose}
415
- >
416
- <TimesIcon />
417
- </button>
418
- </div>
419
- <div className="query-builder-property-search-panel__content">
420
- <ResizablePanelGroup orientation="vertical">
421
- <ResizablePanel size={150}>
422
- <div className="query-builder-property-search-panel__config">
423
- <div className="query-builder-property-search-panel__form__section">
424
- <div className="query-builder-property-search-panel__form__section__header__label">
425
- By type
532
+ <ClickAwayListener onClickAway={handleClose}>
533
+ <div
534
+ data-testid={
535
+ QUERY_BUILDER_TEST_ID.QUERY_BUILDER_PROPERTY_SEARCH_PANEL
536
+ }
537
+ className="query-builder-property-search-panel"
538
+ >
539
+ <div className="query-builder-property-search-panel__content">
540
+ <ResizablePanelGroup orientation="vertical">
541
+ <ResizablePanel size={175}>
542
+ <div className="query-builder-property-search-panel__config">
543
+ <div className="query-builder-property-search-panel__form__section">
544
+ <div className="query-builder-property-search-panel__form__section__header__label">
545
+ Search Mode
546
+ <DocumentationLink
547
+ documentationKey={
548
+ LEGEND_APPLICATION_DOCUMENTATION_KEY.QUESTION_HOW_TO_USE_ADVANCED_SEARCH_SYNTAX
549
+ }
550
+ />
551
+ </div>
552
+ <div className="query-builder-property-search-panel__filter__element">
553
+ <BaseRadioGroup
554
+ className="query-builder-property-search-panel__search-mode__options"
555
+ value={
556
+ propertySearchState.searchConfigurationState
557
+ .currentMode
558
+ }
559
+ onChange={handleSearchMode}
560
+ row={false}
561
+ options={[
562
+ ADVANCED_FUZZY_SEARCH_MODE.STANDARD,
563
+ ADVANCED_FUZZY_SEARCH_MODE.INCLUDE,
564
+ ADVANCED_FUZZY_SEARCH_MODE.EXACT,
565
+ ADVANCED_FUZZY_SEARCH_MODE.INVERSE,
566
+ ]}
567
+ size={1}
568
+ />
569
+ </div>
426
570
  </div>
427
- <div className="query-builder-property-search-panel__filter__element">
428
- <button
429
- className={clsx(
430
- 'query-builder-property-search-panel__form__section__toggler__btn',
431
- {
432
- 'query-builder-property-search-panel__form__section__toggler__btn--toggled':
433
- propertySearchState.typeFilters.includes(
434
- QUERY_BUILDER_PROPERTY_SEARCH_TYPE.CLASS,
435
- ),
436
- },
437
- )}
438
- onClick={(): void => {
439
- propertySearchState.toggleFilterForType(
440
- QUERY_BUILDER_PROPERTY_SEARCH_TYPE.CLASS,
441
- );
442
- }}
443
- tabIndex={-1}
444
- >
445
- {propertySearchState.typeFilters.includes(
446
- QUERY_BUILDER_PROPERTY_SEARCH_TYPE.CLASS,
447
- ) ? (
448
- <CheckSquareIcon />
449
- ) : (
450
- <SquareIcon />
451
- )}
452
- </button>
453
- <div className="query-builder-property-search-panel__form__section__toggler__prompt">
454
- Class
571
+ <div className="query-builder-property-search-panel__form__section">
572
+ <div className="query-builder-property-search-panel__form__section__header__label">
573
+ Documentation
574
+ <Tooltip
575
+ TransitionProps={{
576
+ timeout: 0,
577
+ }}
578
+ title={
579
+ <div>
580
+ Include &quot;doc&quot; type tagged values in
581
+ search results
582
+ </div>
583
+ }
584
+ >
585
+ <div className="query-builder-property-search-panel__tagged-values__tooltip">
586
+ <InfoCircleIcon />
587
+ </div>
588
+ </Tooltip>
589
+ </div>
590
+ <div className="query-builder-property-search-panel__filter__element">
591
+ <button
592
+ className={clsx(
593
+ 'query-builder-property-search-panel__form__section__toggler__btn',
594
+ {
595
+ 'query-builder-property-search-panel__form__section__toggler__btn--toggled':
596
+ propertySearchState.searchConfigurationState
597
+ .includeDocumentation,
598
+ },
599
+ )}
600
+ onClick={handleToggleIncludeDocumentation}
601
+ tabIndex={-1}
602
+ >
603
+ {propertySearchState.searchConfigurationState
604
+ .includeDocumentation ? (
605
+ <CheckSquareIcon />
606
+ ) : (
607
+ <SquareIcon />
608
+ )}
609
+ </button>
610
+ <div className="query-builder-property-search-panel__form__section__toggler__prompt">
611
+ Include
612
+ </div>
455
613
  </div>
456
614
  </div>
457
- <div className="query-builder-property-search-panel__filter__element">
458
- <button
459
- className={clsx(
460
- 'query-builder-property-search-panel__form__section__toggler__btn',
461
- {
462
- 'query-builder-property-search-panel__form__section__toggler__btn--toggled':
463
- propertySearchState.typeFilters.includes(
464
- QUERY_BUILDER_PROPERTY_SEARCH_TYPE.STRING,
465
- ),
466
- },
467
- )}
468
- onClick={(): void => {
469
- propertySearchState.toggleFilterForType(
470
- QUERY_BUILDER_PROPERTY_SEARCH_TYPE.STRING,
471
- );
472
- }}
473
- tabIndex={-1}
474
- >
475
- {propertySearchState.typeFilters.includes(
476
- QUERY_BUILDER_PROPERTY_SEARCH_TYPE.STRING,
477
- ) ? (
478
- <CheckSquareIcon />
479
- ) : (
480
- <SquareIcon />
481
- )}
482
- </button>
483
- <div className="query-builder-property-search-panel__form__section__toggler__prompt">
484
- String
615
+ <div className="query-builder-property-search-panel__form__section">
616
+ <div className="query-builder-property-search-panel__form__section__header__label">
617
+ Sub-types
618
+ </div>
619
+ <div className="query-builder-property-search-panel__filter__element">
620
+ <button
621
+ className={clsx(
622
+ 'query-builder-property-search-panel__form__section__toggler__btn',
623
+ {
624
+ 'query-builder-property-search-panel__form__section__toggler__btn--toggled':
625
+ propertySearchState.searchConfigurationState
626
+ .includeSubTypes,
627
+ },
628
+ )}
629
+ onClick={handleToggleIncludeSubTypes}
630
+ tabIndex={-1}
631
+ >
632
+ {propertySearchState.searchConfigurationState
633
+ .includeSubTypes ? (
634
+ <CheckSquareIcon />
635
+ ) : (
636
+ <SquareIcon />
637
+ )}
638
+ </button>
639
+ <div className="query-builder-property-search-panel__form__section__toggler__prompt">
640
+ Include
641
+ </div>
485
642
  </div>
486
643
  </div>
487
- <div className="query-builder-property-search-panel__filter__element">
488
- <button
489
- className={clsx(
490
- 'query-builder-property-search-panel__form__section__toggler__btn',
491
- {
492
- 'query-builder-property-search-panel__form__section__toggler__btn--toggled':
493
- propertySearchState.typeFilters.includes(
494
- QUERY_BUILDER_PROPERTY_SEARCH_TYPE.BOOLEAN,
495
- ),
496
- },
497
- )}
498
- onClick={(): void => {
499
- propertySearchState.toggleFilterForType(
644
+ <div className="query-builder-property-search-panel__form__section">
645
+ <div className="query-builder-property-search-panel__form__section__header__label">
646
+ By type
647
+ </div>
648
+ <div className="query-builder-property-search-panel__filter__element">
649
+ <button
650
+ className={clsx(
651
+ 'query-builder-property-search-panel__form__section__toggler__btn',
652
+ {
653
+ 'query-builder-property-search-panel__form__section__toggler__btn--toggled':
654
+ propertySearchState.typeFilters.includes(
655
+ QUERY_BUILDER_PROPERTY_SEARCH_TYPE.CLASS,
656
+ ),
657
+ },
658
+ )}
659
+ onClick={(): void => {
660
+ propertySearchState.toggleFilterForType(
661
+ QUERY_BUILDER_PROPERTY_SEARCH_TYPE.CLASS,
662
+ );
663
+ }}
664
+ tabIndex={-1}
665
+ >
666
+ {propertySearchState.typeFilters.includes(
667
+ QUERY_BUILDER_PROPERTY_SEARCH_TYPE.CLASS,
668
+ ) ? (
669
+ <CheckSquareIcon />
670
+ ) : (
671
+ <SquareIcon />
672
+ )}
673
+ </button>
674
+ <div className="query-builder-property-search-panel__form__section__toggler__prompt">
675
+ Class
676
+ </div>
677
+ </div>
678
+ <div className="query-builder-property-search-panel__filter__element">
679
+ <button
680
+ className={clsx(
681
+ 'query-builder-property-search-panel__form__section__toggler__btn',
682
+ {
683
+ 'query-builder-property-search-panel__form__section__toggler__btn--toggled':
684
+ propertySearchState.typeFilters.includes(
685
+ QUERY_BUILDER_PROPERTY_SEARCH_TYPE.STRING,
686
+ ),
687
+ },
688
+ )}
689
+ onClick={(): void => {
690
+ propertySearchState.toggleFilterForType(
691
+ QUERY_BUILDER_PROPERTY_SEARCH_TYPE.STRING,
692
+ );
693
+ }}
694
+ tabIndex={-1}
695
+ >
696
+ {propertySearchState.typeFilters.includes(
697
+ QUERY_BUILDER_PROPERTY_SEARCH_TYPE.STRING,
698
+ ) ? (
699
+ <CheckSquareIcon />
700
+ ) : (
701
+ <SquareIcon />
702
+ )}
703
+ </button>
704
+ <div className="query-builder-property-search-panel__form__section__toggler__prompt">
705
+ String
706
+ </div>
707
+ </div>
708
+ <div className="query-builder-property-search-panel__filter__element">
709
+ <button
710
+ className={clsx(
711
+ 'query-builder-property-search-panel__form__section__toggler__btn',
712
+ {
713
+ 'query-builder-property-search-panel__form__section__toggler__btn--toggled':
714
+ propertySearchState.typeFilters.includes(
715
+ QUERY_BUILDER_PROPERTY_SEARCH_TYPE.BOOLEAN,
716
+ ),
717
+ },
718
+ )}
719
+ onClick={(): void => {
720
+ propertySearchState.toggleFilterForType(
721
+ QUERY_BUILDER_PROPERTY_SEARCH_TYPE.BOOLEAN,
722
+ );
723
+ }}
724
+ tabIndex={-1}
725
+ >
726
+ {propertySearchState.typeFilters.includes(
500
727
  QUERY_BUILDER_PROPERTY_SEARCH_TYPE.BOOLEAN,
501
- );
502
- }}
503
- tabIndex={-1}
504
- >
505
- {propertySearchState.typeFilters.includes(
506
- QUERY_BUILDER_PROPERTY_SEARCH_TYPE.BOOLEAN,
507
- ) ? (
508
- <CheckSquareIcon />
509
- ) : (
510
- <SquareIcon />
511
- )}
512
- </button>
513
- <div className="query-builder-property-search-panel__form__section__toggler__prompt">
514
- Boolean
728
+ ) ? (
729
+ <CheckSquareIcon />
730
+ ) : (
731
+ <SquareIcon />
732
+ )}
733
+ </button>
734
+ <div className="query-builder-property-search-panel__form__section__toggler__prompt">
735
+ Boolean
736
+ </div>
515
737
  </div>
516
- </div>
517
- <div className="query-builder-property-search-panel__filter__element">
518
- <button
519
- className={clsx(
520
- 'query-builder-property-search-panel__form__section__toggler__btn',
521
- {
522
- 'query-builder-property-search-panel__form__section__toggler__btn--toggled':
523
- propertySearchState.typeFilters.includes(
524
- QUERY_BUILDER_PROPERTY_SEARCH_TYPE.NUMBER,
525
- ),
526
- },
527
- )}
528
- onClick={(): void => {
529
- propertySearchState.toggleFilterForType(
738
+ <div className="query-builder-property-search-panel__filter__element">
739
+ <button
740
+ className={clsx(
741
+ 'query-builder-property-search-panel__form__section__toggler__btn',
742
+ {
743
+ 'query-builder-property-search-panel__form__section__toggler__btn--toggled':
744
+ propertySearchState.typeFilters.includes(
745
+ QUERY_BUILDER_PROPERTY_SEARCH_TYPE.NUMBER,
746
+ ),
747
+ },
748
+ )}
749
+ onClick={(): void => {
750
+ propertySearchState.toggleFilterForType(
751
+ QUERY_BUILDER_PROPERTY_SEARCH_TYPE.NUMBER,
752
+ );
753
+ }}
754
+ tabIndex={-1}
755
+ >
756
+ {propertySearchState.typeFilters.includes(
530
757
  QUERY_BUILDER_PROPERTY_SEARCH_TYPE.NUMBER,
531
- );
532
- }}
533
- tabIndex={-1}
534
- >
535
- {propertySearchState.typeFilters.includes(
536
- QUERY_BUILDER_PROPERTY_SEARCH_TYPE.NUMBER,
537
- ) ? (
538
- <CheckSquareIcon />
539
- ) : (
540
- <SquareIcon />
541
- )}
542
- </button>
543
- <div className="query-builder-property-search-panel__form__section__toggler__prompt">
544
- Number
758
+ ) ? (
759
+ <CheckSquareIcon />
760
+ ) : (
761
+ <SquareIcon />
762
+ )}
763
+ </button>
764
+ <div className="query-builder-property-search-panel__form__section__toggler__prompt">
765
+ Number
766
+ </div>
545
767
  </div>
546
- </div>
547
- <div className="query-builder-property-search-panel__filter__element">
548
- <button
549
- className={clsx(
550
- 'query-builder-property-search-panel__form__section__toggler__btn',
551
- {
552
- 'query-builder-property-search-panel__form__section__toggler__btn--toggled':
553
- propertySearchState.typeFilters.includes(
554
- QUERY_BUILDER_PROPERTY_SEARCH_TYPE.DATE,
555
- ),
556
- },
557
- )}
558
- onClick={(): void => {
559
- propertySearchState.toggleFilterForType(
768
+ <div className="query-builder-property-search-panel__filter__element">
769
+ <button
770
+ className={clsx(
771
+ 'query-builder-property-search-panel__form__section__toggler__btn',
772
+ {
773
+ 'query-builder-property-search-panel__form__section__toggler__btn--toggled':
774
+ propertySearchState.typeFilters.includes(
775
+ QUERY_BUILDER_PROPERTY_SEARCH_TYPE.DATE,
776
+ ),
777
+ },
778
+ )}
779
+ onClick={(): void => {
780
+ propertySearchState.toggleFilterForType(
781
+ QUERY_BUILDER_PROPERTY_SEARCH_TYPE.DATE,
782
+ );
783
+ }}
784
+ tabIndex={-1}
785
+ >
786
+ {propertySearchState.typeFilters.includes(
560
787
  QUERY_BUILDER_PROPERTY_SEARCH_TYPE.DATE,
561
- );
562
- }}
563
- tabIndex={-1}
564
- >
565
- {propertySearchState.typeFilters.includes(
566
- QUERY_BUILDER_PROPERTY_SEARCH_TYPE.DATE,
567
- ) ? (
568
- <CheckSquareIcon />
569
- ) : (
570
- <SquareIcon />
571
- )}
572
- </button>
573
- <div className="query-builder-property-search-panel__form__section__toggler__prompt">
574
- Date
788
+ ) ? (
789
+ <CheckSquareIcon />
790
+ ) : (
791
+ <SquareIcon />
792
+ )}
793
+ </button>
794
+ <div className="query-builder-property-search-panel__form__section__toggler__prompt">
795
+ Date
796
+ </div>
575
797
  </div>
576
798
  </div>
577
799
  </div>
578
- </div>
579
- </ResizablePanel>
580
- <ResizablePanelSplitter>
581
- <ResizablePanelSplitterLine color="var(--color-dark-grey-200)" />
582
- </ResizablePanelSplitter>
583
- <ResizablePanel>
584
- {propertySearchState.searchState.isInProgress && (
585
- <PanelLoadingIndicator isLoading={true} />
586
- )}
587
- <div className="query-builder-property-search-panel__results">
588
- {!propertySearchState.searchState.isInProgress && (
589
- <>
590
- {Boolean(
591
- propertySearchState.filteredSearchResults.length,
592
- ) &&
593
- propertySearchState.filteredSearchResults.map(
594
- (node) => (
595
- <QueryBuilderTreeNodeViewer
596
- key={node.id}
597
- node={node}
598
- queryBuilderState={queryBuilderState}
599
- level={1}
600
- stepPaddingInRem={0}
601
- explorerState={queryBuilderState.explorerState}
602
- />
603
- ),
604
- )}
605
- {!propertySearchState.filteredSearchResults.length &&
606
- propertySearchState.searchText && (
607
- <BlankPanelContent>
608
- <div className="query-builder-property-search-panel__result-placeholder__text">
609
- No result
610
- </div>
611
- <div className="query-builder-property-search-panel__result-placeholder__tips">
612
- Tips: Navigate deeper into the explorer tree to
613
- improve the scope and accuracy of the search
614
- </div>
615
- </BlankPanelContent>
616
- )}
617
- </>
800
+ </ResizablePanel>
801
+ <ResizablePanelSplitter>
802
+ <ResizablePanelSplitterLine color="var(--color-dark-grey-200)" />
803
+ </ResizablePanelSplitter>
804
+ <ResizablePanel>
805
+ {(propertySearchState.initializationState.isInProgress ||
806
+ propertySearchState.searchState.isInProgress) && (
807
+ <PanelLoadingIndicator isLoading={true} />
618
808
  )}
619
- {propertySearchState.searchState.isInProgress && (
620
- <BlankPanelContent>Searching...</BlankPanelContent>
621
- )}
622
- </div>
623
- </ResizablePanel>
624
- </ResizablePanelGroup>
809
+ <div className="query-builder-property-search-panel__results">
810
+ {!propertySearchState.initializationState.isInProgress &&
811
+ !propertySearchState.searchState.isInProgress && (
812
+ <>
813
+ {Boolean(
814
+ propertySearchState.filteredSearchResults.length,
815
+ ) &&
816
+ propertySearchState.filteredSearchResults.map(
817
+ (node) => (
818
+ <QueryBuilderTreeNodeViewer
819
+ key={node.id}
820
+ node={node}
821
+ queryBuilderState={queryBuilderState}
822
+ level={1}
823
+ stepPaddingInRem={0}
824
+ explorerState={
825
+ queryBuilderState.explorerState
826
+ }
827
+ />
828
+ ),
829
+ )}
830
+ {!propertySearchState.filteredSearchResults.length &&
831
+ propertySearchState.searchText && (
832
+ <BlankPanelContent>
833
+ <div className="query-builder-property-search-panel__result-placeholder__text">
834
+ No result
835
+ </div>
836
+ <div className="query-builder-property-search-panel__result-placeholder__tips">
837
+ Tips: Navigate deeper into the explorer tree
838
+ to improve the scope and accuracy of the
839
+ search
840
+ </div>
841
+ </BlankPanelContent>
842
+ )}
843
+ </>
844
+ )}
845
+ {propertySearchState.initializationState.isInProgress && (
846
+ <BlankPanelContent>Initializing...</BlankPanelContent>
847
+ )}
848
+ {propertySearchState.searchState.isInProgress && (
849
+ <BlankPanelContent>Searching...</BlankPanelContent>
850
+ )}
851
+ </div>
852
+ </ResizablePanel>
853
+ </ResizablePanelGroup>
854
+ </div>
625
855
  </div>
626
- </div>
856
+ </ClickAwayListener>
627
857
  </BasePopover>
628
858
  );
629
859
  },