@finos/legend-application 7.2.1 → 8.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/lib/components/ActionAlert.d.ts +1 -0
  2. package/lib/components/ActionAlert.d.ts.map +1 -1
  3. package/lib/components/ActionAlert.js +2 -1
  4. package/lib/components/ActionAlert.js.map +1 -1
  5. package/lib/components/ApplicationStoreProvider.d.ts +3 -3
  6. package/lib/components/ApplicationStoreProvider.d.ts.map +1 -1
  7. package/lib/components/ApplicationStoreProviderTestUtils.d.ts +1 -1
  8. package/lib/components/ApplicationStoreProviderTestUtils.js.map +1 -1
  9. package/lib/components/BlockingAlert.d.ts +1 -0
  10. package/lib/components/BlockingAlert.d.ts.map +1 -1
  11. package/lib/components/NotificationManager.d.ts +1 -0
  12. package/lib/components/NotificationManager.d.ts.map +1 -1
  13. package/lib/components/VirtualAssistant.d.ts +1 -0
  14. package/lib/components/VirtualAssistant.d.ts.map +1 -1
  15. package/lib/components/VirtualAssistant.js +21 -12
  16. package/lib/components/VirtualAssistant.js.map +1 -1
  17. package/lib/components/shared/CustomDatePicker.d.ts.map +1 -1
  18. package/lib/components/shared/CustomDatePicker.js +31 -9
  19. package/lib/components/shared/CustomDatePicker.js.map +1 -1
  20. package/lib/components/shared/DocumentationLink.d.ts.map +1 -1
  21. package/lib/components/shared/DocumentationLink.js +11 -3
  22. package/lib/components/shared/DocumentationLink.js.map +1 -1
  23. package/lib/components/shared/LambdaEditor.d.ts +1 -0
  24. package/lib/components/shared/LambdaEditor.d.ts.map +1 -1
  25. package/lib/components/shared/LambdaParameterValuesEditor.d.ts +1 -0
  26. package/lib/components/shared/LambdaParameterValuesEditor.d.ts.map +1 -1
  27. package/lib/components/shared/TextSearchAdvancedConfigMenu.d.ts +23 -0
  28. package/lib/components/shared/TextSearchAdvancedConfigMenu.d.ts.map +1 -0
  29. package/lib/components/shared/TextSearchAdvancedConfigMenu.js +37 -0
  30. package/lib/components/shared/TextSearchAdvancedConfigMenu.js.map +1 -0
  31. package/lib/components/shared/execution-plan-viewer/ExecutionPlanViewer.d.ts.map +1 -1
  32. package/lib/components/shared/execution-plan-viewer/ExecutionPlanViewer.js +2 -2
  33. package/lib/components/shared/execution-plan-viewer/ExecutionPlanViewer.js.map +1 -1
  34. package/lib/const.d.ts +2 -0
  35. package/lib/const.d.ts.map +1 -1
  36. package/lib/const.js +2 -0
  37. package/lib/const.js.map +1 -1
  38. package/lib/index.css +2 -2
  39. package/lib/index.css.map +1 -1
  40. package/lib/index.d.ts +2 -0
  41. package/lib/index.d.ts.map +1 -1
  42. package/lib/index.js +2 -0
  43. package/lib/index.js.map +1 -1
  44. package/lib/stores/ApplicationStore.d.ts +4 -4
  45. package/lib/stores/ApplicationStore.d.ts.map +1 -1
  46. package/lib/stores/ApplicationStore.js +7 -4
  47. package/lib/stores/ApplicationStore.js.map +1 -1
  48. package/lib/stores/ApplicationStoreTestUtils.d.ts +1 -1
  49. package/lib/stores/ApplicationStoreTestUtils.js.map +1 -1
  50. package/lib/stores/ApplicationTelemetry.d.ts +5 -0
  51. package/lib/stores/ApplicationTelemetry.d.ts.map +1 -1
  52. package/lib/stores/ApplicationTelemetry.js.map +1 -1
  53. package/lib/stores/AssistantService.d.ts +21 -2
  54. package/lib/stores/AssistantService.d.ts.map +1 -1
  55. package/lib/stores/AssistantService.js +71 -14
  56. package/lib/stores/AssistantService.js.map +1 -1
  57. package/lib/stores/LegendApplicationDocumentation.d.ts +19 -0
  58. package/lib/stores/LegendApplicationDocumentation.d.ts.map +1 -0
  59. package/lib/stores/LegendApplicationDocumentation.js +20 -0
  60. package/lib/stores/LegendApplicationDocumentation.js.map +1 -0
  61. package/lib/stores/PureLanguageSupport.js +3 -3
  62. package/lib/stores/PureLanguageSupport.js.map +1 -1
  63. package/lib/stores/shared/LambdaParameterState.d.ts +7 -3
  64. package/lib/stores/shared/LambdaParameterState.d.ts.map +1 -1
  65. package/lib/stores/shared/LambdaParameterState.js +25 -2
  66. package/lib/stores/shared/LambdaParameterState.js.map +1 -1
  67. package/lib/stores/shared/TextSearchAdvancedConfigState.d.ts +30 -0
  68. package/lib/stores/shared/TextSearchAdvancedConfigState.d.ts.map +1 -0
  69. package/lib/stores/shared/TextSearchAdvancedConfigState.js +59 -0
  70. package/lib/stores/shared/TextSearchAdvancedConfigState.js.map +1 -0
  71. package/package.json +13 -13
  72. package/src/components/ActionAlert.tsx +1 -1
  73. package/src/components/ApplicationStoreProvider.tsx +3 -3
  74. package/src/components/ApplicationStoreProviderTestUtils.tsx +2 -2
  75. package/src/components/VirtualAssistant.tsx +127 -76
  76. package/src/components/shared/CustomDatePicker.tsx +40 -2
  77. package/src/components/shared/DocumentationLink.tsx +14 -3
  78. package/src/components/shared/TextSearchAdvancedConfigMenu.tsx +73 -0
  79. package/src/components/shared/execution-plan-viewer/ExecutionPlanViewer.tsx +3 -2
  80. package/src/const.ts +2 -0
  81. package/src/index.ts +3 -0
  82. package/src/stores/ApplicationStore.ts +10 -11
  83. package/src/stores/ApplicationStoreTestUtils.ts +2 -2
  84. package/src/stores/ApplicationTelemetry.ts +5 -0
  85. package/src/stores/AssistantService.ts +93 -18
  86. package/src/stores/LegendApplicationDocumentation.ts +19 -0
  87. package/src/stores/PureLanguageSupport.ts +3 -3
  88. package/src/stores/shared/LambdaParameterState.ts +36 -4
  89. package/src/stores/shared/TextSearchAdvancedConfigState.ts +65 -0
  90. package/tsconfig.json +3 -0
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Copyright (c) 2020-present, Goldman Sachs
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import { BaseRadioGroup, InfoCircleIcon } from '@finos/legend-art';
18
+ import { observer } from 'mobx-react-lite';
19
+ import { LEGEND_APPLICATION_DOCUMENTATION_KEY } from '../../stores/LegendApplicationDocumentation.js';
20
+ import {
21
+ ADVANCED_TEXT_SEARCH_MODE,
22
+ type TextSearchAdvancedConfigState,
23
+ } from '../../stores/shared/TextSearchAdvancedConfigState.js';
24
+ import { useApplicationStore } from '../ApplicationStoreProvider.js';
25
+
26
+ export const TextSearchAdvancedConfigMenu = observer(
27
+ (props: { configState: TextSearchAdvancedConfigState }) => {
28
+ const { configState } = props;
29
+ const applicationStore = useApplicationStore();
30
+
31
+ const handleSearchMode: React.ChangeEventHandler<HTMLInputElement> = (
32
+ event,
33
+ ): void => {
34
+ const searchMode = event.target.value as ADVANCED_TEXT_SEARCH_MODE;
35
+ configState.setCurrentMode(searchMode);
36
+ };
37
+ const seeDocumentation = (): void =>
38
+ applicationStore.assistantService.openDocumentationEntry(
39
+ LEGEND_APPLICATION_DOCUMENTATION_KEY.QUESTION_HOW_TO_USE_ADVANCED_SEARCH_SYNTAX,
40
+ );
41
+
42
+ return (
43
+ <div className="text-search-advanced-config__panel">
44
+ <div className="text-search-advanced-config__panel__header__label">
45
+ search config
46
+ <button
47
+ className="text-search-advanced-config__panel__header__hint"
48
+ tabIndex={-1}
49
+ onClick={seeDocumentation}
50
+ title="Click to see more details on advanced search"
51
+ >
52
+ <InfoCircleIcon />
53
+ </button>
54
+ </div>
55
+ <div>
56
+ <BaseRadioGroup
57
+ className="text-search-advanced-config__options"
58
+ value={configState.currentMode}
59
+ onChange={handleSearchMode}
60
+ row={false}
61
+ options={[
62
+ ADVANCED_TEXT_SEARCH_MODE.STANDARD,
63
+ ADVANCED_TEXT_SEARCH_MODE.INCLUDE,
64
+ ADVANCED_TEXT_SEARCH_MODE.EXACT,
65
+ ADVANCED_TEXT_SEARCH_MODE.INVERSE,
66
+ ]}
67
+ size={1}
68
+ />
69
+ </div>
70
+ </div>
71
+ );
72
+ },
73
+ );
@@ -31,6 +31,7 @@ import {
31
31
  MenuContent,
32
32
  DropdownMenu,
33
33
  BlankPanelContent,
34
+ PanelContent,
34
35
  } from '@finos/legend-art';
35
36
  import {
36
37
  addUniqueEntry,
@@ -517,14 +518,14 @@ export const ExecutionPlanViewer = observer(
517
518
  </div>
518
519
  </div>
519
520
  </div>
520
- <div className="panel__content">
521
+ <PanelContent>
521
522
  <TextInputEditor
522
523
  inputValue={executionPlanState.debugText}
523
524
  isReadOnly={true}
524
525
  language={EDITOR_LANGUAGE.TEXT}
525
526
  showMiniMap={true}
526
527
  />
527
- </div>
528
+ </PanelContent>
528
529
  </div>
529
530
  </ResizablePanel>
530
531
  </ResizablePanelGroup>
package/src/const.ts CHANGED
@@ -15,6 +15,8 @@
15
15
  */
16
16
 
17
17
  export const TAB_SIZE = 2;
18
+ export const DEFAULT_TYPEAHEAD_SEARCH_MINIMUM_SEARCH_LENGTH = 2;
19
+ export const DEFAULT_TYPEAHEAD_SEARCH_LIMIT = 10;
18
20
 
19
21
  export const MONOSPACED_FONT_FAMILY = 'Roboto Mono';
20
22
 
package/src/index.ts CHANGED
@@ -39,6 +39,9 @@ export * from './stores/AssistantService.js';
39
39
  export * from './stores/ApplicationNavigationContextService.js';
40
40
  export * from './stores/LegendApplicationPlugin.js';
41
41
 
42
+ export * from './components/shared/TextSearchAdvancedConfigMenu.js';
43
+ export * from './stores/shared/TextSearchAdvancedConfigState.js';
44
+
42
45
  export * from './stores/ApplicationStoreTestUtils.js';
43
46
 
44
47
  // ------------------------------------------- Shared components -------------------------------------------
@@ -25,7 +25,7 @@ import {
25
25
  isString,
26
26
  ApplicationError,
27
27
  } from '@finos/legend-shared';
28
- import { makeAutoObservable, action } from 'mobx';
28
+ import { action, makeObservable, observable } from 'mobx';
29
29
  import { APPLICATION_EVENT } from './ApplicationEvent.js';
30
30
  import type { LegendApplicationConfig } from '../application/LegendApplicationConfig.js';
31
31
  import type { WebApplicationNavigator } from './WebApplicationNavigator.js';
@@ -105,15 +105,15 @@ export class Notification {
105
105
 
106
106
  export type GenericLegendApplicationStore = ApplicationStore<
107
107
  LegendApplicationConfig,
108
- LegendApplicationPlugin
108
+ LegendApplicationPluginManager<LegendApplicationPlugin>
109
109
  >;
110
110
 
111
111
  export class ApplicationStore<
112
112
  T extends LegendApplicationConfig,
113
- V extends LegendApplicationPlugin,
113
+ V extends LegendApplicationPluginManager<LegendApplicationPlugin>,
114
114
  > {
115
- pluginManager: LegendApplicationPluginManager<V>;
116
115
  config: T;
116
+ pluginManager: V;
117
117
 
118
118
  // navigation
119
119
  navigator: WebApplicationNavigator;
@@ -144,13 +144,12 @@ export class ApplicationStore<
144
144
  */
145
145
  TEMPORARY__isLightThemeEnabled = false;
146
146
 
147
- constructor(
148
- config: T,
149
- navigator: WebApplicationNavigator,
150
- pluginManager: LegendApplicationPluginManager<V>,
151
- ) {
152
- makeAutoObservable(this, {
153
- navigator: false,
147
+ constructor(config: T, navigator: WebApplicationNavigator, pluginManager: V) {
148
+ makeObservable(this, {
149
+ notification: observable,
150
+ blockingAlertInfo: observable,
151
+ actionAlertInfo: observable,
152
+ TEMPORARY__isLightThemeEnabled: observable,
154
153
  setBlockingAlert: action,
155
154
  setActionAlertInfo: action,
156
155
  setNotification: action,
@@ -52,10 +52,10 @@ export const TEST__getGenericApplicationConfig = (
52
52
 
53
53
  export const TEST__getTestApplicationStore = <
54
54
  T extends LegendApplicationConfig,
55
- V extends LegendApplicationPlugin,
55
+ V extends LegendApplicationPluginManager<LegendApplicationPlugin>,
56
56
  >(
57
57
  config: T,
58
- pluginManager: LegendApplicationPluginManager<V>,
58
+ pluginManager: V,
59
59
  ): ApplicationStore<T, V> =>
60
60
  new ApplicationStore(
61
61
  config,
@@ -18,6 +18,11 @@ import type { TelemetryService } from '@finos/legend-shared';
18
18
  import { APPLICATION_EVENT } from './ApplicationEvent.js';
19
19
 
20
20
  type ApplicationLoaded_TelemetryData = {
21
+ application: {
22
+ name: string;
23
+ version: string;
24
+ env: string;
25
+ };
21
26
  browser: {
22
27
  userAgent: string;
23
28
  };
@@ -25,12 +25,15 @@ import {
25
25
  isNonNullable,
26
26
  ActionState,
27
27
  } from '@finos/legend-shared';
28
+ import { TextSearchAdvancedConfigState } from './shared/TextSearchAdvancedConfigState.js';
28
29
 
29
30
  export enum VIRTUAL_ASSISTANT_TAB {
30
31
  SEARCH = 'SEARCH',
31
32
  CONTEXTUAL_SUPPORT = 'CONTEXTUAL_SUPPORT',
32
33
  }
33
34
 
35
+ export const DOCUMENTATION_SEARCH_RESULTS_LIMIT = 100;
36
+
34
37
  export class VirtualAssistantDocumentationEntry {
35
38
  uuid = uuid();
36
39
  documentationKey: string;
@@ -77,9 +80,28 @@ export class VirtualAssistantContextualDocumentationEntry {
77
80
  }
78
81
  }
79
82
 
83
+ /**
84
+ * NOTE: since we're displaying the documentation entry in virtual assistant
85
+ * we want only user-friendly docs, we will discard anything that doesn't
86
+ * come with a title, or does not have any content/url
87
+ */
88
+ export const isValidVirtualAssistantDocumentationEntry = (
89
+ entry: DocumentationEntry,
90
+ ): boolean =>
91
+ Boolean(entry.title && (entry.url ?? entry.text ?? entry.markdownText));
92
+
93
+ /**
94
+ * Check if the documentation entry should be displayed in virtual assistant,
95
+ * i.e. it has some text content, rather just a link
96
+ */
97
+ export const shouldDisplayVirtualAssistantDocumentationEntry = (
98
+ entry: DocumentationEntry,
99
+ ): boolean =>
100
+ isValidVirtualAssistantDocumentationEntry(entry) &&
101
+ Boolean(entry.text ?? entry.markdownText);
102
+
80
103
  export class AssistantService {
81
104
  readonly applicationStore: GenericLegendApplicationStore;
82
- private readonly searchEngine: Fuse<DocumentationEntry>;
83
105
  /**
84
106
  * This key is used to allow programmatic re-rendering of the assistant panel
85
107
  */
@@ -87,19 +109,28 @@ export class AssistantService {
87
109
  isHidden = false;
88
110
  isOpen = false;
89
111
  selectedTab = VIRTUAL_ASSISTANT_TAB.SEARCH;
112
+ currentDocumentationEntry: VirtualAssistantDocumentationEntry | undefined;
90
113
 
91
- searchResults: VirtualAssistantDocumentationEntry[] = [];
92
- searchState = ActionState.create().pass();
114
+ // search text
115
+ private readonly searchEngine: Fuse<DocumentationEntry>;
116
+ searchConfigurationState: TextSearchAdvancedConfigState;
117
+ searchState = ActionState.create();
93
118
  searchText = '';
119
+ searchResults: VirtualAssistantDocumentationEntry[] = [];
120
+ showSearchConfigurationMenu = false;
121
+ isOverSearchLimit = false;
94
122
 
95
123
  constructor(applicationStore: GenericLegendApplicationStore) {
96
124
  makeObservable(this, {
97
125
  isHidden: observable,
98
126
  isOpen: observable,
99
127
  panelRenderingKey: observable,
128
+ isOverSearchLimit: observable,
100
129
  selectedTab: observable,
101
130
  searchText: observable,
102
131
  searchResults: observable,
132
+ currentDocumentationEntry: observable,
133
+ showSearchConfigurationMenu: observable,
103
134
  currentContextualDocumentationEntry: computed,
104
135
  setIsHidden: action,
105
136
  setIsOpen: action,
@@ -107,17 +138,16 @@ export class AssistantService {
107
138
  setSearchText: action,
108
139
  resetSearch: action,
109
140
  search: action,
141
+ openDocumentationEntry: action,
110
142
  refreshPanelRendering: action,
143
+ setShowSearchConfigurationMenu: action,
111
144
  });
112
145
 
113
146
  this.applicationStore = applicationStore;
114
147
  this.searchEngine = new Fuse(
115
- this.applicationStore.documentationService.getAllDocEntries().filter(
116
- (entry) =>
117
- // NOTE: since we're searching for user-friendly docs, we will discard anything that
118
- // doesn't come with a title, or does not have any content/url
119
- entry.title && (entry.url ?? entry.text ?? entry.markdownText),
120
- ),
148
+ this.applicationStore.documentationService
149
+ .getAllDocEntries()
150
+ .filter(isValidVirtualAssistantDocumentationEntry),
121
151
  {
122
152
  includeScore: true,
123
153
  shouldSort: true,
@@ -143,8 +173,14 @@ export class AssistantService {
143
173
  weight: 1,
144
174
  },
145
175
  ],
176
+ // extended search allows for exact word match through single quote
177
+ // See https://fusejs.io/examples.html#extended-search
178
+ useExtendedSearch: true,
146
179
  },
147
180
  );
181
+ this.searchConfigurationState = new TextSearchAdvancedConfigState(() => {
182
+ this.search();
183
+ });
148
184
  }
149
185
 
150
186
  get currentContextualDocumentationEntry():
@@ -159,6 +195,7 @@ export class AssistantService {
159
195
  this.applicationStore.documentationService.getContextualDocEntry(
160
196
  currentContext,
161
197
  );
198
+
162
199
  return currentContextualDocumentationEntry
163
200
  ? new VirtualAssistantContextualDocumentationEntry(
164
201
  currentContext,
@@ -168,19 +205,28 @@ export class AssistantService {
168
205
  this.applicationStore.documentationService.getDocEntry(entry),
169
206
  )
170
207
  .filter(isNonNullable)
171
- .filter(
172
- (entry) =>
173
- // NOTE: since we're searching for user-friendly docs, we will discard anything that
174
- // doesn't come with a title, or does not have any content/url
175
- //
176
- // We could also consider having a flag in each documentation entry to be hidden from users
177
- entry.title && (entry.url ?? entry.text ?? entry.markdownText),
178
- )
208
+ .filter(isValidVirtualAssistantDocumentationEntry)
179
209
  .map((entry) => new VirtualAssistantDocumentationEntry(entry)),
180
210
  )
181
211
  : undefined;
182
212
  }
183
213
 
214
+ openDocumentationEntry(docKey: string): void {
215
+ const matchingDocEntry = this.applicationStore.documentationService
216
+ .getAllDocEntries()
217
+ .find((entry) => entry._documentationKey === docKey);
218
+
219
+ if (matchingDocEntry) {
220
+ this.setIsOpen(true);
221
+ this.setIsHidden(false);
222
+ this.currentDocumentationEntry = new VirtualAssistantDocumentationEntry(
223
+ matchingDocEntry,
224
+ );
225
+ this.currentDocumentationEntry.setIsOpen(true);
226
+ this.resetSearch();
227
+ }
228
+ }
229
+
184
230
  setIsHidden(val: boolean): void {
185
231
  this.isHidden = val;
186
232
  }
@@ -222,10 +268,39 @@ export class AssistantService {
222
268
  }
223
269
 
224
270
  search(): void {
271
+ if (!this.searchText) {
272
+ this.searchResults = [];
273
+ return;
274
+ }
275
+ this.currentDocumentationEntry = undefined;
225
276
  this.searchState.inProgress();
226
277
  this.searchResults = Array.from(
227
- this.searchEngine.search(this.searchText).values(),
278
+ this.searchEngine
279
+ .search(
280
+ this.searchConfigurationState.generateSearchText(this.searchText),
281
+ {
282
+ // NOTE: search for limit + 1 item so we can know if there are more search results
283
+ limit: DOCUMENTATION_SEARCH_RESULTS_LIMIT + 1,
284
+ },
285
+ )
286
+ .values(),
228
287
  ).map((result) => new VirtualAssistantDocumentationEntry(result.item));
288
+
289
+ // check if the search results exceed the limit
290
+ if (this.searchResults.length > DOCUMENTATION_SEARCH_RESULTS_LIMIT) {
291
+ this.isOverSearchLimit = true;
292
+ this.searchResults = this.searchResults.slice(
293
+ 0,
294
+ DOCUMENTATION_SEARCH_RESULTS_LIMIT,
295
+ );
296
+ } else {
297
+ this.isOverSearchLimit = false;
298
+ }
299
+
229
300
  this.searchState.complete();
230
301
  }
302
+
303
+ setShowSearchConfigurationMenu(val: boolean): void {
304
+ this.showSearchConfigurationMenu = val;
305
+ }
231
306
  }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Copyright (c) 2020-present, Goldman Sachs
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ export enum LEGEND_APPLICATION_DOCUMENTATION_KEY {
18
+ QUESTION_HOW_TO_USE_ADVANCED_SEARCH_SYNTAX = 'question.how-to-use-advanced-search-syntax',
19
+ }
@@ -124,10 +124,7 @@ const generateLanguageMonarch = (
124
124
  PURE_ELEMENT_NAME.MEASURE,
125
125
  PURE_ELEMENT_NAME.PROFILE,
126
126
  PURE_ELEMENT_NAME.FUNCTION,
127
- PURE_ELEMENT_NAME.FLAT_DATA,
128
- PURE_ELEMENT_NAME.DATABASE,
129
127
  PURE_ELEMENT_NAME.MAPPING,
130
- PURE_ELEMENT_NAME.SERVICE,
131
128
  PURE_ELEMENT_NAME.RUNTIME,
132
129
  PURE_ELEMENT_NAME.CONNECTION,
133
130
  PURE_ELEMENT_NAME.FILE_GENERATION,
@@ -148,6 +145,9 @@ const generateLanguageMonarch = (
148
145
  * @modularize
149
146
  * See https://github.com/finos/legend-studio/issues/65
150
147
  */
148
+ PURE_ELEMENT_NAME.SERVICE,
149
+ PURE_ELEMENT_NAME.FLAT_DATA,
150
+ PURE_ELEMENT_NAME.DATABASE,
151
151
  PURE_CONNECTION_NAME.FLAT_DATA_CONNECTION,
152
152
  PURE_CONNECTION_NAME.RELATIONAL_DATABASE_CONNECTION,
153
153
  'Relational',
@@ -38,11 +38,13 @@ import {
38
38
  import {
39
39
  addUniqueEntry,
40
40
  deleteEntry,
41
+ type Hashable,
42
+ hashArray,
41
43
  IllegalStateError,
42
44
  isNonNullable,
43
45
  uuid,
44
46
  } from '@finos/legend-shared';
45
- import { makeObservable, observable, action } from 'mobx';
47
+ import { makeObservable, observable, action, computed } from 'mobx';
46
48
  import {
47
49
  genericType_setRawType,
48
50
  multiplicity_setLowerBound,
@@ -54,6 +56,11 @@ export enum PARAMETER_SUBMIT_ACTION {
54
56
  EXPORT = 'EXPORT',
55
57
  }
56
58
 
59
+ enum LAMABA_PARAMETER_HASH_STRUCTURE {
60
+ LAMBDA_PARAMETER_STATE = 'LAMBDA_PARAMETER_STATE',
61
+ LAMBDA_PARAMETERS_STATE = 'LAMBDA_PARAMETERS_STATE',
62
+ }
63
+
57
64
  export const buildParametersLetLambdaFunc = (
58
65
  graph: PureModel,
59
66
  lambdaParametersStates: LambdaParameterState[],
@@ -87,11 +94,13 @@ export const buildParametersLetLambdaFunc = (
87
94
  .filter(isNonNullable);
88
95
  return letlambdaFunction;
89
96
  };
90
- export class LambdaParameterState {
97
+
98
+ export class LambdaParameterState implements Hashable {
91
99
  readonly uuid = uuid();
92
100
  readonly parameter: VariableExpression;
93
101
  readonly graph: PureModel;
94
- observableContext: ObserverContext;
102
+ readonly observableContext: ObserverContext;
103
+
95
104
  value: ValueSpecification | undefined;
96
105
 
97
106
  constructor(
@@ -103,12 +112,20 @@ export class LambdaParameterState {
103
112
  value: observable,
104
113
  setValue: action,
105
114
  mockParameterValue: action,
115
+ hashCode: computed,
106
116
  });
107
117
  this.observableContext = observableContext;
108
118
  this.parameter = observe_VariableExpression(variableExpression);
109
119
  this.graph = graph;
110
120
  }
111
121
 
122
+ get hashCode(): string {
123
+ return hashArray([
124
+ LAMABA_PARAMETER_HASH_STRUCTURE.LAMBDA_PARAMETER_STATE,
125
+ this.parameter,
126
+ ]);
127
+ }
128
+
112
129
  mockParameterValue(): void {
113
130
  this.setValue(
114
131
  generateVariableExpressionMockValue(this.parameter, this.graph),
@@ -204,10 +221,24 @@ export class ParameterInstanceValuesEditorState {
204
221
  this.setShowModal(false);
205
222
  }
206
223
  }
207
- export class LambdaParametersState {
224
+
225
+ export class LambdaParametersState implements Hashable {
208
226
  parameterStates: LambdaParameterState[] = [];
209
227
  parameterValuesEditorState = new ParameterInstanceValuesEditorState();
210
228
 
229
+ constructor() {
230
+ makeObservable(this, {
231
+ hashCode: computed,
232
+ });
233
+ }
234
+
235
+ get hashCode(): string {
236
+ return hashArray([
237
+ LAMABA_PARAMETER_HASH_STRUCTURE.LAMBDA_PARAMETERS_STATE,
238
+ hashArray(this.parameterStates),
239
+ ]);
240
+ }
241
+
211
242
  addParameter(val: LambdaParameterState): void {
212
243
  addUniqueEntry(this.parameterStates, val);
213
244
  }
@@ -215,6 +246,7 @@ export class LambdaParametersState {
215
246
  removeParameter(val: LambdaParameterState): void {
216
247
  deleteEntry(this.parameterStates, val);
217
248
  }
249
+
218
250
  setParameters(val: LambdaParameterState[]): void {
219
251
  this.parameterStates = val;
220
252
  }
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Copyright (c) 2020-present, Goldman Sachs
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import { action, computed, makeObservable, observable } from 'mobx';
18
+
19
+ export enum ADVANCED_TEXT_SEARCH_MODE {
20
+ STANDARD = 'standard',
21
+ INCLUDE = 'include match',
22
+ EXACT = 'exact match',
23
+ INVERSE = 'excludes exact match',
24
+ }
25
+
26
+ export class TextSearchAdvancedConfigState {
27
+ currentMode = ADVANCED_TEXT_SEARCH_MODE.STANDARD;
28
+ onSearchModeChange: () => void;
29
+
30
+ constructor(onSearchModeChange: () => void) {
31
+ makeObservable(this, {
32
+ currentMode: observable,
33
+ isAdvancedSearchActive: computed,
34
+ setCurrentMode: action,
35
+ });
36
+
37
+ this.onSearchModeChange = onSearchModeChange;
38
+ }
39
+
40
+ get isAdvancedSearchActive(): boolean {
41
+ return this.currentMode !== ADVANCED_TEXT_SEARCH_MODE.STANDARD;
42
+ }
43
+
44
+ generateSearchText(val: string): string {
45
+ switch (this.currentMode) {
46
+ case ADVANCED_TEXT_SEARCH_MODE.INCLUDE: {
47
+ return `'"${val}"`;
48
+ }
49
+ case ADVANCED_TEXT_SEARCH_MODE.EXACT: {
50
+ return `="${val}"`;
51
+ }
52
+ case ADVANCED_TEXT_SEARCH_MODE.INVERSE: {
53
+ return `!"${val}"`;
54
+ }
55
+ default: {
56
+ return val;
57
+ }
58
+ }
59
+ }
60
+
61
+ setCurrentMode(val: ADVANCED_TEXT_SEARCH_MODE): void {
62
+ this.currentMode = val;
63
+ this.onSearchModeChange();
64
+ }
65
+ }
package/tsconfig.json CHANGED
@@ -40,6 +40,7 @@
40
40
  "./src/stores/AssistantService.ts",
41
41
  "./src/stores/DocumentationService.ts",
42
42
  "./src/stores/EventService.ts",
43
+ "./src/stores/LegendApplicationDocumentation.ts",
43
44
  "./src/stores/LegendApplicationPlugin.ts",
44
45
  "./src/stores/PureLanguageSupport.ts",
45
46
  "./src/stores/WebApplicationNavigator.ts",
@@ -47,6 +48,7 @@
47
48
  "./src/stores/shared/LambdaEditorState.ts",
48
49
  "./src/stores/shared/LambdaParameterState.ts",
49
50
  "./src/stores/shared/PackageableElementOption.ts",
51
+ "./src/stores/shared/TextSearchAdvancedConfigState.ts",
50
52
  "./src/stores/shared/ValueSpecificationModifierHelper.ts",
51
53
  "./src/application/LegendApplication.tsx",
52
54
  "./src/application/LegendApplicationPluginManager.tsx",
@@ -67,6 +69,7 @@
67
69
  "./src/components/shared/LambdaParameterValuesEditor.tsx",
68
70
  "./src/components/shared/PackageableElementOptionRenderer.tsx",
69
71
  "./src/components/shared/TextInputEditor.tsx",
72
+ "./src/components/shared/TextSearchAdvancedConfigMenu.tsx",
70
73
  "./src/components/shared/execution-plan-viewer/ExecutionPlanViewer.tsx",
71
74
  "./src/components/shared/execution-plan-viewer/SQLExecutionNodeViewer.tsx",
72
75
  "./src/stores/CJS__Fuse.cts"