@finos/legend-application-marketplace 0.2.3 → 0.2.4

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 (103) hide show
  1. package/lib/__lib__/LegendMarketplaceAppEvent.d.ts +2 -0
  2. package/lib/__lib__/LegendMarketplaceAppEvent.d.ts.map +1 -1
  3. package/lib/__lib__/LegendMarketplaceAppEvent.js +2 -0
  4. package/lib/__lib__/LegendMarketplaceAppEvent.js.map +1 -1
  5. package/lib/__lib__/LegendMarketplaceNavigation.d.ts +7 -1
  6. package/lib/__lib__/LegendMarketplaceNavigation.d.ts.map +1 -1
  7. package/lib/__lib__/LegendMarketplaceNavigation.js +9 -1
  8. package/lib/__lib__/LegendMarketplaceNavigation.js.map +1 -1
  9. package/lib/__lib__/LegendMarketplaceTelemetryHelper.d.ts +2 -1
  10. package/lib/__lib__/LegendMarketplaceTelemetryHelper.d.ts.map +1 -1
  11. package/lib/__lib__/LegendMarketplaceTelemetryHelper.js +10 -2
  12. package/lib/__lib__/LegendMarketplaceTelemetryHelper.js.map +1 -1
  13. package/lib/application/LegendMarketplaceWebApplication.d.ts.map +1 -1
  14. package/lib/application/LegendMarketplaceWebApplication.js +4 -1
  15. package/lib/application/LegendMarketplaceWebApplication.js.map +1 -1
  16. package/lib/application/providers/LegendMarketplaceFieldSearchResultsStoreProvider.d.ts +22 -0
  17. package/lib/application/providers/LegendMarketplaceFieldSearchResultsStoreProvider.d.ts.map +1 -0
  18. package/lib/application/providers/LegendMarketplaceFieldSearchResultsStoreProvider.js +37 -0
  19. package/lib/application/providers/LegendMarketplaceFieldSearchResultsStoreProvider.js.map +1 -0
  20. package/lib/components/AddToCart/CartDrawer.d.ts.map +1 -1
  21. package/lib/components/AddToCart/CartDrawer.js +36 -4
  22. package/lib/components/AddToCart/CartDrawer.js.map +1 -1
  23. package/lib/components/AddToCart/RecommendedAddOnsModal.d.ts +2 -1
  24. package/lib/components/AddToCart/RecommendedAddOnsModal.d.ts.map +1 -1
  25. package/lib/components/AddToCart/RecommendedAddOnsModal.js +23 -13
  26. package/lib/components/AddToCart/RecommendedAddOnsModal.js.map +1 -1
  27. package/lib/components/AddToCart/RecommendedItemsCard.d.ts +3 -1
  28. package/lib/components/AddToCart/RecommendedItemsCard.d.ts.map +1 -1
  29. package/lib/components/AddToCart/RecommendedItemsCard.js +14 -11
  30. package/lib/components/AddToCart/RecommendedItemsCard.js.map +1 -1
  31. package/lib/components/FieldSearchFiltersPanel/FieldSearchFiltersPanel.d.ts +23 -0
  32. package/lib/components/FieldSearchFiltersPanel/FieldSearchFiltersPanel.d.ts.map +1 -0
  33. package/lib/components/FieldSearchFiltersPanel/FieldSearchFiltersPanel.js +22 -0
  34. package/lib/components/FieldSearchFiltersPanel/FieldSearchFiltersPanel.js.map +1 -0
  35. package/lib/components/MarketplaceCard/FieldSearchResultListItem.d.ts +25 -0
  36. package/lib/components/MarketplaceCard/FieldSearchResultListItem.d.ts.map +1 -0
  37. package/lib/components/MarketplaceCard/FieldSearchResultListItem.js +58 -0
  38. package/lib/components/MarketplaceCard/FieldSearchResultListItem.js.map +1 -0
  39. package/lib/components/MarketplaceSearchFiltersPanel/MarketplaceSearchFiltersPanel.d.ts +10 -0
  40. package/lib/components/MarketplaceSearchFiltersPanel/MarketplaceSearchFiltersPanel.d.ts.map +1 -1
  41. package/lib/components/MarketplaceSearchFiltersPanel/MarketplaceSearchFiltersPanel.js +2 -2
  42. package/lib/components/MarketplaceSearchFiltersPanel/MarketplaceSearchFiltersPanel.js.map +1 -1
  43. package/lib/components/ProviderCard/LegendMarketplaceTerminalCard.d.ts.map +1 -1
  44. package/lib/components/ProviderCard/LegendMarketplaceTerminalCard.js +5 -2
  45. package/lib/components/ProviderCard/LegendMarketplaceTerminalCard.js.map +1 -1
  46. package/lib/components/SearchBar/LegendMarketplaceSearchBar.d.ts +2 -1
  47. package/lib/components/SearchBar/LegendMarketplaceSearchBar.d.ts.map +1 -1
  48. package/lib/components/SearchBar/LegendMarketplaceSearchBar.js +20 -7
  49. package/lib/components/SearchBar/LegendMarketplaceSearchBar.js.map +1 -1
  50. package/lib/index.css +2 -2
  51. package/lib/index.css.map +1 -1
  52. package/lib/package.json +1 -1
  53. package/lib/pages/Lakehouse/MarketplaceLakehouseHome.d.ts.map +1 -1
  54. package/lib/pages/Lakehouse/MarketplaceLakehouseHome.js +6 -4
  55. package/lib/pages/Lakehouse/MarketplaceLakehouseHome.js.map +1 -1
  56. package/lib/pages/Lakehouse/searchResults/LegendMarketplaceFieldSearchResults.d.ts +17 -0
  57. package/lib/pages/Lakehouse/searchResults/LegendMarketplaceFieldSearchResults.d.ts.map +1 -0
  58. package/lib/pages/Lakehouse/searchResults/LegendMarketplaceFieldSearchResults.js +126 -0
  59. package/lib/pages/Lakehouse/searchResults/LegendMarketplaceFieldSearchResults.js.map +1 -0
  60. package/lib/pages/Lakehouse/searchResults/LegendMarketplaceSearchResults.d.ts.map +1 -1
  61. package/lib/pages/Lakehouse/searchResults/LegendMarketplaceSearchResults.js +8 -3
  62. package/lib/pages/Lakehouse/searchResults/LegendMarketplaceSearchResults.js.map +1 -1
  63. package/lib/pages/TerminalsAddons/LegendMarketplaceTerminalsAddons.d.ts.map +1 -1
  64. package/lib/pages/TerminalsAddons/LegendMarketplaceTerminalsAddons.js +2 -2
  65. package/lib/pages/TerminalsAddons/LegendMarketplaceTerminalsAddons.js.map +1 -1
  66. package/lib/stores/cart/CartStore.d.ts +10 -3
  67. package/lib/stores/cart/CartStore.d.ts.map +1 -1
  68. package/lib/stores/cart/CartStore.js +66 -42
  69. package/lib/stores/cart/CartStore.js.map +1 -1
  70. package/lib/stores/lakehouse/LegendMarketplaceFieldSearchResultsStore.d.ts +63 -0
  71. package/lib/stores/lakehouse/LegendMarketplaceFieldSearchResultsStore.d.ts.map +1 -0
  72. package/lib/stores/lakehouse/LegendMarketplaceFieldSearchResultsStore.js +228 -0
  73. package/lib/stores/lakehouse/LegendMarketplaceFieldSearchResultsStore.js.map +1 -0
  74. package/lib/stores/lakehouse/LegendMarketplaceProductViewerStore.d.ts.map +1 -1
  75. package/lib/stores/lakehouse/LegendMarketplaceProductViewerStore.js +9 -13
  76. package/lib/stores/lakehouse/LegendMarketplaceProductViewerStore.js.map +1 -1
  77. package/lib/stores/lakehouse/fieldSearch/FieldSearchResultState.d.ts +40 -0
  78. package/lib/stores/lakehouse/fieldSearch/FieldSearchResultState.d.ts.map +1 -0
  79. package/lib/stores/lakehouse/fieldSearch/FieldSearchResultState.js +84 -0
  80. package/lib/stores/lakehouse/fieldSearch/FieldSearchResultState.js.map +1 -0
  81. package/package.json +8 -8
  82. package/src/__lib__/LegendMarketplaceAppEvent.ts +2 -0
  83. package/src/__lib__/LegendMarketplaceNavigation.ts +18 -1
  84. package/src/__lib__/LegendMarketplaceTelemetryHelper.ts +17 -1
  85. package/src/application/LegendMarketplaceWebApplication.tsx +13 -0
  86. package/src/application/providers/LegendMarketplaceFieldSearchResultsStoreProvider.tsx +67 -0
  87. package/src/components/AddToCart/CartDrawer.tsx +49 -4
  88. package/src/components/AddToCart/RecommendedAddOnsModal.tsx +86 -24
  89. package/src/components/AddToCart/RecommendedItemsCard.tsx +143 -120
  90. package/src/components/FieldSearchFiltersPanel/FieldSearchFiltersPanel.tsx +65 -0
  91. package/src/components/MarketplaceCard/FieldSearchResultListItem.tsx +163 -0
  92. package/src/components/MarketplaceSearchFiltersPanel/MarketplaceSearchFiltersPanel.tsx +2 -2
  93. package/src/components/ProviderCard/LegendMarketplaceTerminalCard.tsx +7 -0
  94. package/src/components/SearchBar/LegendMarketplaceSearchBar.tsx +44 -3
  95. package/src/pages/Lakehouse/MarketplaceLakehouseHome.tsx +9 -2
  96. package/src/pages/Lakehouse/searchResults/LegendMarketplaceFieldSearchResults.tsx +380 -0
  97. package/src/pages/Lakehouse/searchResults/LegendMarketplaceSearchResults.tsx +19 -1
  98. package/src/pages/TerminalsAddons/LegendMarketplaceTerminalsAddons.tsx +6 -2
  99. package/src/stores/cart/CartStore.ts +86 -51
  100. package/src/stores/lakehouse/LegendMarketplaceFieldSearchResultsStore.ts +309 -0
  101. package/src/stores/lakehouse/LegendMarketplaceProductViewerStore.ts +23 -30
  102. package/src/stores/lakehouse/fieldSearch/FieldSearchResultState.ts +122 -0
  103. package/tsconfig.json +6 -0
@@ -0,0 +1,309 @@
1
+ /**
2
+ * Copyright (c) 2026-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, flow, makeObservable, observable } from 'mobx';
18
+ import type { LegendMarketplaceBaseStore } from '../LegendMarketplaceBaseStore.js';
19
+ import {
20
+ ActionState,
21
+ assertErrorThrown,
22
+ isNonEmptyString,
23
+ LogEvent,
24
+ type GeneratorFn,
25
+ type PlainObject,
26
+ } from '@finos/legend-shared';
27
+ import {
28
+ FieldSearchType,
29
+ type FieldSearchRequest,
30
+ GroupedFieldSearchResponse,
31
+ type GroupedFieldSearchResponseMetadata,
32
+ } from '@finos/legend-server-marketplace';
33
+ import type { DataProductTypeFilter } from './LegendMarketplaceSearchResultsStore.js';
34
+ import { LEGEND_MARKETPLACE_APP_EVENT } from '../../__lib__/LegendMarketplaceAppEvent.js';
35
+ import { LegendMarketplaceTelemetryHelper } from '../../__lib__/LegendMarketplaceTelemetryHelper.js';
36
+ import { FieldSearchResultState } from './fieldSearch/FieldSearchResultState.js';
37
+
38
+ export class LegendMarketplaceFieldSearchResultsStore {
39
+ readonly marketplaceBaseStore: LegendMarketplaceBaseStore;
40
+ searchQuery: string | undefined = undefined;
41
+ fieldSearchResultStates: FieldSearchResultState[] = [];
42
+ responseMetadata: GroupedFieldSearchResponseMetadata | undefined = undefined;
43
+ page = 1;
44
+ itemsPerPage = 12;
45
+ errorMessage: string | undefined = undefined;
46
+ selectedProductTypes: Set<DataProductTypeFilter> =
47
+ new Set<DataProductTypeFilter>();
48
+ expandedRows: Set<string> = new Set<string>();
49
+ readonly loadState = ActionState.create();
50
+ private _currentFetchToken = 0;
51
+ private _abortController: AbortController | undefined = undefined;
52
+
53
+ constructor(marketplaceBaseStore: LegendMarketplaceBaseStore) {
54
+ this.marketplaceBaseStore = marketplaceBaseStore;
55
+
56
+ makeObservable<
57
+ LegendMarketplaceFieldSearchResultsStore,
58
+ '_currentFetchToken' | '_abortController'
59
+ >(this, {
60
+ searchQuery: observable,
61
+ fieldSearchResultStates: observable,
62
+ responseMetadata: observable,
63
+ page: observable,
64
+ itemsPerPage: observable,
65
+ errorMessage: observable,
66
+ selectedProductTypes: observable,
67
+ expandedRows: observable,
68
+ _currentFetchToken: false,
69
+ _abortController: false,
70
+ setSearchQuery: action,
71
+ setFieldSearchResultStates: action,
72
+ setResponseMetadata: action,
73
+ setPage: action,
74
+ setItemsPerPage: action,
75
+ setErrorMessage: action,
76
+ toggleProductType: action,
77
+ clearAllFilters: action,
78
+ toggleExpandRow: action,
79
+ clearExpandedRows: action,
80
+ fieldSearchRequest: computed,
81
+ tableRows: computed,
82
+ totalItems: computed,
83
+ totalFieldMatches: computed,
84
+ lakehouseCount: computed,
85
+ legacyCount: computed,
86
+ hasActiveFilters: computed,
87
+ isLoading: computed,
88
+ hasFailed: computed,
89
+ executeSearch: flow,
90
+ changePageAndFetch: flow,
91
+ changeItemsPerPageAndFetch: flow,
92
+ toggleProductTypeAndFetch: flow,
93
+ clearAllFiltersAndFetch: flow,
94
+ });
95
+ }
96
+
97
+ setSearchQuery(query: string | undefined): void {
98
+ this.searchQuery = query;
99
+ this.page = 1;
100
+ }
101
+
102
+ setFieldSearchResultStates(results: FieldSearchResultState[]): void {
103
+ this.fieldSearchResultStates = results;
104
+ }
105
+
106
+ setResponseMetadata(
107
+ value: GroupedFieldSearchResponseMetadata | undefined,
108
+ ): void {
109
+ this.responseMetadata = value;
110
+ }
111
+
112
+ setPage(value: number): void {
113
+ this.page = value;
114
+ }
115
+
116
+ setItemsPerPage(value: number): void {
117
+ this.itemsPerPage = value;
118
+ this.page = 1;
119
+ }
120
+
121
+ setErrorMessage(value: string | undefined): void {
122
+ this.errorMessage = value;
123
+ }
124
+
125
+ toggleProductType(productType: DataProductTypeFilter): void {
126
+ const wasSelected = this.selectedProductTypes.has(productType);
127
+ if (wasSelected) {
128
+ this.selectedProductTypes.delete(productType);
129
+ } else {
130
+ this.selectedProductTypes.add(productType);
131
+ }
132
+ this.page = 1;
133
+ LegendMarketplaceTelemetryHelper.logEvent_ApplySearchFilter(
134
+ this.marketplaceBaseStore.applicationStore.telemetryService,
135
+ 'dataProductType',
136
+ productType,
137
+ wasSelected ? 'deselect' : 'select',
138
+ this.searchQuery,
139
+ );
140
+ }
141
+
142
+ clearAllFilters(): void {
143
+ this.selectedProductTypes.clear();
144
+ this.page = 1;
145
+ LegendMarketplaceTelemetryHelper.logEvent_ClearSearchFilters(
146
+ this.marketplaceBaseStore.applicationStore.telemetryService,
147
+ this.searchQuery,
148
+ );
149
+ }
150
+
151
+ toggleExpandRow(rowId: string): void {
152
+ if (this.expandedRows.has(rowId)) {
153
+ this.expandedRows.delete(rowId);
154
+ } else {
155
+ this.expandedRows.add(rowId);
156
+ }
157
+ }
158
+
159
+ clearExpandedRows(): void {
160
+ this.expandedRows.clear();
161
+ }
162
+
163
+ isRowExpanded(rowId: string): boolean {
164
+ return this.expandedRows.has(rowId);
165
+ }
166
+
167
+ get fieldSearchRequest(): FieldSearchRequest | undefined {
168
+ if (!isNonEmptyString(this.searchQuery)) {
169
+ return undefined;
170
+ }
171
+ return {
172
+ query: this.searchQuery,
173
+ searchType: FieldSearchType.HYBRID,
174
+ pageSize: this.itemsPerPage,
175
+ pageNumber: this.page,
176
+ ...(this.selectedProductTypes.size > 0
177
+ ? { dataProductTypes: Array.from(this.selectedProductTypes) }
178
+ : {}),
179
+ };
180
+ }
181
+
182
+ get tableRows(): FieldSearchResultState[] {
183
+ return this.fieldSearchResultStates;
184
+ }
185
+
186
+ get totalItems(): number {
187
+ return this.responseMetadata?.total_count ?? 0;
188
+ }
189
+
190
+ get totalFieldMatches(): number {
191
+ return this.responseMetadata?.total_field_matches ?? 0;
192
+ }
193
+
194
+ get lakehouseCount(): number {
195
+ return this.responseMetadata?.lakehouse_count ?? 0;
196
+ }
197
+
198
+ get legacyCount(): number {
199
+ return this.responseMetadata?.legacy_count ?? 0;
200
+ }
201
+
202
+ get hasActiveFilters(): boolean {
203
+ return this.selectedProductTypes.size > 0;
204
+ }
205
+
206
+ get isLoading(): boolean {
207
+ return (
208
+ isNonEmptyString(this.searchQuery) &&
209
+ (this.loadState.isInInitialState || this.loadState.isInProgress)
210
+ );
211
+ }
212
+
213
+ get hasFailed(): boolean {
214
+ return this.loadState.hasFailed;
215
+ }
216
+
217
+ *executeSearch(): GeneratorFn<void> {
218
+ yield* this.fetchFieldSearchResultsInternal();
219
+ }
220
+
221
+ *changePageAndFetch(page: number): GeneratorFn<void> {
222
+ this.setPage(page);
223
+ yield* this.fetchFieldSearchResultsInternal();
224
+ }
225
+
226
+ *changeItemsPerPageAndFetch(itemsPerPage: number): GeneratorFn<void> {
227
+ this.setItemsPerPage(itemsPerPage);
228
+ yield* this.fetchFieldSearchResultsInternal();
229
+ }
230
+
231
+ *toggleProductTypeAndFetch(
232
+ productType: DataProductTypeFilter,
233
+ ): GeneratorFn<void> {
234
+ this.toggleProductType(productType);
235
+ yield* this.fetchFieldSearchResultsInternal();
236
+ }
237
+
238
+ *clearAllFiltersAndFetch(): GeneratorFn<void> {
239
+ this.clearAllFilters();
240
+ yield* this.fetchFieldSearchResultsInternal();
241
+ }
242
+
243
+ private *fetchFieldSearchResultsInternal(): GeneratorFn<void> {
244
+ const request = this.fieldSearchRequest;
245
+ const fetchToken = ++this._currentFetchToken;
246
+
247
+ if (!request) {
248
+ this.setFieldSearchResultStates([]);
249
+ this.setResponseMetadata(undefined);
250
+ this.setErrorMessage(undefined);
251
+ this.clearExpandedRows();
252
+ this.loadState.complete();
253
+ return;
254
+ }
255
+
256
+ this._abortController?.abort();
257
+ this._abortController = new AbortController();
258
+ const { signal } = this._abortController;
259
+
260
+ this.loadState.inProgress();
261
+ this.setErrorMessage(undefined);
262
+ this.clearExpandedRows();
263
+
264
+ try {
265
+ const rawResponse =
266
+ (yield this.marketplaceBaseStore.marketplaceServerClient.fieldSearch(
267
+ this.marketplaceBaseStore.envState.lakehouseEnvironment,
268
+ request,
269
+ signal,
270
+ )) as PlainObject<GroupedFieldSearchResponse>;
271
+
272
+ if (fetchToken !== this._currentFetchToken) {
273
+ return;
274
+ }
275
+
276
+ const response =
277
+ GroupedFieldSearchResponse.serialization.fromJson(rawResponse);
278
+ const results = response.results.map(
279
+ (entry) => new FieldSearchResultState(entry),
280
+ );
281
+
282
+ this.setFieldSearchResultStates(results);
283
+ this.setResponseMetadata(response.metadata);
284
+ this.loadState.complete();
285
+ } catch (error: unknown) {
286
+ if (fetchToken !== this._currentFetchToken) {
287
+ return;
288
+ }
289
+
290
+ assertErrorThrown(error);
291
+ this.marketplaceBaseStore.applicationStore.logService.error(
292
+ LogEvent.create(LEGEND_MARKETPLACE_APP_EVENT.FIELD_SEARCH_FAILURE),
293
+ error,
294
+ );
295
+ this.marketplaceBaseStore.applicationStore.notificationService.notifyError(
296
+ `Error fetching field search results: ${error.message}`,
297
+ );
298
+ this.setFieldSearchResultStates([]);
299
+ this.setResponseMetadata(undefined);
300
+ this.setErrorMessage(error.message);
301
+ this.loadState.fail();
302
+ }
303
+ }
304
+
305
+ dispose(): void {
306
+ this._abortController?.abort();
307
+ this._abortController = undefined;
308
+ }
309
+ }
@@ -55,7 +55,6 @@ import {
55
55
  V1_DataProductArtifact,
56
56
  V1_dataProductModelSchema,
57
57
  V1_entitlementsDataProductDetailsResponseToDataProductDetails,
58
- V1_ModelAccessPointGroup,
59
58
  V1_PureGraphManager,
60
59
  V1_SdlcDeploymentDataProductOrigin,
61
60
  V1_TerminalModelSchema,
@@ -393,26 +392,22 @@ export class LegendMarketplaceProductViewerStore {
393
392
  }
394
393
  : undefined,
395
394
  // TODO: improve with class opening
396
- openQuery: projectGAV
397
- ? (): void => {
398
- const modelAPG = v1DataProduct.accessPointGroups.find(
399
- (apg) => apg instanceof V1_ModelAccessPointGroup,
400
- );
401
- if (modelAPG) {
402
- this.marketplaceBaseStore.applicationStore.navigationService.navigator.visitAddress(
403
- EXTERNAL_APPLICATION_NAVIGATION__generateDataProductModelQueryUrl(
404
- this.marketplaceBaseStore.applicationStore.config
405
- .queryApplicationUrl,
406
- projectGAV.groupId,
407
- projectGAV.artifactId,
408
- projectGAV.versionId,
409
- v1DataProduct.path,
410
- modelAPG.id,
411
- ),
412
- );
413
- }
414
- }
415
- : undefined,
395
+ openQuery: (gav, type, id) => {
396
+ if (id) {
397
+ this.marketplaceBaseStore.applicationStore.navigationService.navigator.visitAddress(
398
+ EXTERNAL_APPLICATION_NAVIGATION__generateDataProductModelQueryUrl(
399
+ this.marketplaceBaseStore.applicationStore.config
400
+ .queryApplicationUrl,
401
+ gav.groupId,
402
+ gav.artifactId,
403
+ gav.versionId,
404
+ type,
405
+ v1DataProduct.path,
406
+ id,
407
+ ),
408
+ );
409
+ }
410
+ },
416
411
  },
417
412
  this.marketplaceBaseStore.registryServerClient,
418
413
  );
@@ -616,20 +611,18 @@ export class LegendMarketplaceProductViewerStore {
616
611
  ),
617
612
  );
618
613
  },
619
- openQuery: (): void => {
620
- const modelAPG = v1DataProduct.accessPointGroups.find(
621
- (apg) => apg instanceof V1_ModelAccessPointGroup,
622
- );
623
- if (modelAPG) {
614
+ openQuery: (_gav, type, id): void => {
615
+ if (id) {
624
616
  this.marketplaceBaseStore.applicationStore.navigationService.navigator.visitAddress(
625
617
  EXTERNAL_APPLICATION_NAVIGATION__generateDataProductModelQueryUrl(
626
618
  this.marketplaceBaseStore.applicationStore.config
627
619
  .queryApplicationUrl,
628
- projectData.groupId,
629
- projectData.artifactId,
630
- projectData.versionId,
620
+ _gav.groupId,
621
+ _gav.artifactId,
622
+ _gav.versionId,
623
+ type,
631
624
  v1DataProduct.path,
632
- modelAPG.id,
625
+ id,
633
626
  ),
634
627
  );
635
628
  }
@@ -0,0 +1,122 @@
1
+ /**
2
+ * Copyright (c) 2026-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 {
18
+ DataProductSearchResultDetailsType,
19
+ type GroupedFieldSearchDataProduct,
20
+ type GroupedFieldSearchResultEntry,
21
+ } from '@finos/legend-server-marketplace';
22
+ import { DataProductTypeFilter } from '../LegendMarketplaceSearchResultsStore.js';
23
+ import { generateGAVCoordinates } from '@finos/legend-storage';
24
+ import {
25
+ generateLakehouseDataProductPath,
26
+ generateLegacyDataProductPath,
27
+ } from '../../../__lib__/LegendMarketplaceNavigation.js';
28
+
29
+ const PRODUCT_TYPE_FILTER_MAP: Record<
30
+ DataProductSearchResultDetailsType,
31
+ DataProductTypeFilter
32
+ > = {
33
+ [DataProductSearchResultDetailsType.LEGACY]: DataProductTypeFilter.LEGACY,
34
+ [DataProductSearchResultDetailsType.LAKEHOUSE]:
35
+ DataProductTypeFilter.LAKEHOUSE,
36
+ [DataProductSearchResultDetailsType.ERROR]: DataProductTypeFilter.LEGACY,
37
+ };
38
+
39
+ const getDataProductName = (path: string): string =>
40
+ path.split('::').at(-1) ?? path;
41
+
42
+ const getOwningDataProductPath = (
43
+ dataProduct: GroupedFieldSearchDataProduct,
44
+ ): string => {
45
+ if (
46
+ dataProduct.productType === DataProductSearchResultDetailsType.LEGACY &&
47
+ dataProduct.groupId
48
+ ) {
49
+ return generateLegacyDataProductPath(
50
+ generateGAVCoordinates(
51
+ dataProduct.groupId,
52
+ dataProduct.artifactId ?? '',
53
+ dataProduct.versionId ?? '',
54
+ ),
55
+ dataProduct.path,
56
+ );
57
+ }
58
+ if (
59
+ dataProduct.productType === DataProductSearchResultDetailsType.LAKEHOUSE &&
60
+ dataProduct.dataProductId &&
61
+ dataProduct.deploymentId !== undefined
62
+ ) {
63
+ return generateLakehouseDataProductPath(
64
+ dataProduct.dataProductId,
65
+ dataProduct.deploymentId,
66
+ );
67
+ }
68
+ return '';
69
+ };
70
+
71
+ export class FieldSearchDataProductEntry {
72
+ readonly name: string;
73
+ readonly datasetName: string | undefined;
74
+ readonly modelPath: string | undefined;
75
+ readonly path: string;
76
+ readonly entityPath: string;
77
+ readonly dataProductId: string | undefined;
78
+ readonly deploymentId: number | undefined;
79
+ readonly groupId: string | undefined;
80
+ readonly artifactId: string | undefined;
81
+ readonly versionId: string | undefined;
82
+ readonly productType: DataProductTypeFilter | undefined;
83
+
84
+ constructor(dataProduct: GroupedFieldSearchDataProduct) {
85
+ const productType = PRODUCT_TYPE_FILTER_MAP[dataProduct.productType];
86
+ const dataProductName = getDataProductName(dataProduct.path);
87
+
88
+ this.name = dataProductName;
89
+ this.datasetName = dataProduct.datasetName;
90
+ this.modelPath = dataProduct.modelPath;
91
+ this.path = getOwningDataProductPath(dataProduct);
92
+ this.entityPath = dataProduct.path;
93
+ this.dataProductId = dataProduct.dataProductId ?? dataProductName;
94
+ this.deploymentId = dataProduct.deploymentId;
95
+ this.groupId = dataProduct.groupId;
96
+ this.artifactId = dataProduct.artifactId;
97
+ this.versionId = dataProduct.versionId;
98
+ this.productType = productType;
99
+ }
100
+ }
101
+
102
+ export class FieldSearchResultState {
103
+ readonly id: string;
104
+ readonly fieldName: string;
105
+ readonly fieldType: string;
106
+ readonly fieldDescription: string;
107
+ readonly dataProducts: FieldSearchDataProductEntry[];
108
+
109
+ constructor(result: GroupedFieldSearchResultEntry) {
110
+ this.fieldName = result.fieldName;
111
+ this.fieldType = result.fieldType ?? 'Unknown';
112
+ this.fieldDescription = result.fieldDescription ?? '-';
113
+ this.id = JSON.stringify([
114
+ this.fieldName,
115
+ this.fieldType,
116
+ this.fieldDescription,
117
+ ]);
118
+ this.dataProducts = result.dataProducts.map(
119
+ (dp) => new FieldSearchDataProductEntry(dp),
120
+ );
121
+ }
122
+ }
package/tsconfig.json CHANGED
@@ -71,12 +71,14 @@
71
71
  "./src/stores/cart/CartStore.ts",
72
72
  "./src/stores/dataAPIs/LegendMarketplaceDataAPIsStore.ts",
73
73
  "./src/stores/lakehouse/LakehouseDataProductService.ts",
74
+ "./src/stores/lakehouse/LegendMarketplaceFieldSearchResultsStore.ts",
74
75
  "./src/stores/lakehouse/LegendMarketplaceProductViewerStore.ts",
75
76
  "./src/stores/lakehouse/LegendMarketplaceSearchResultsStore.ts",
76
77
  "./src/stores/lakehouse/admin/LakehouseAdminStore.ts",
77
78
  "./src/stores/lakehouse/dataProducts/ProductCardState.ts",
78
79
  "./src/stores/lakehouse/entitlements/EntitlementsDashboardState.ts",
79
80
  "./src/stores/lakehouse/entitlements/LakehouseEntitlementsStore.ts",
81
+ "./src/stores/lakehouse/fieldSearch/FieldSearchResultState.ts",
80
82
  "./src/stores/orders/OrderHelpers.ts",
81
83
  "./src/stores/orders/OrderStore.ts",
82
84
  "./src/stores/subscriptions/SubscriptionStore.ts",
@@ -87,6 +89,7 @@
87
89
  "./src/application/providers/LakehouseAdminStoreProvider.tsx",
88
90
  "./src/application/providers/LakehouseEntitlementsStoreProvider.tsx",
89
91
  "./src/application/providers/LegendMarketplaceDataAPIsStoreProvider.tsx",
92
+ "./src/application/providers/LegendMarketplaceFieldSearchResultsStoreProvider.tsx",
90
93
  "./src/application/providers/LegendMarketplaceFrameworkProvider.tsx",
91
94
  "./src/application/providers/LegendMarketplaceProductViewerStoreProvider.tsx",
92
95
  "./src/application/providers/LegendMarketplaceSearchResultsStoreProvider.tsx",
@@ -99,6 +102,7 @@
99
102
  "./src/components/ComingSoon/ComingSoonDisplay.tsx",
100
103
  "./src/components/DataAPIsFiltersPanel/DataAPIsFiltersPanel.tsx",
101
104
  "./src/components/Feedback/FeedbackWidget.tsx",
105
+ "./src/components/FieldSearchFiltersPanel/FieldSearchFiltersPanel.tsx",
102
106
  "./src/components/Header/CartBadge.tsx",
103
107
  "./src/components/Header/LegendMarketplaceAppInfo.tsx",
104
108
  "./src/components/Header/LegendMarketplaceHeader.tsx",
@@ -110,6 +114,7 @@
110
114
  "./src/components/LegendServiceCard/LegendServiceCard.tsx",
111
115
  "./src/components/LegendServiceCard/LegendServiceGrid.tsx",
112
116
  "./src/components/LegendServiceCard/LegendServiceListRow.tsx",
117
+ "./src/components/MarketplaceCard/FieldSearchResultListItem.tsx",
113
118
  "./src/components/MarketplaceCard/LegendMarketplaceCard.tsx",
114
119
  "./src/components/MarketplaceCard/LegendMarketplaceListItem.tsx",
115
120
  "./src/components/MarketplaceSearchFiltersPanel/MarketplaceSearchFiltersPanel.tsx",
@@ -140,6 +145,7 @@
140
145
  "./src/pages/Lakehouse/entitlements/LakehouseDataContract.tsx",
141
146
  "./src/pages/Lakehouse/entitlements/LakehouseEntitlements.tsx",
142
147
  "./src/pages/Lakehouse/entitlements/WorkflowDataAccessRequest.tsx",
148
+ "./src/pages/Lakehouse/searchResults/LegendMarketplaceFieldSearchResults.tsx",
143
149
  "./src/pages/Lakehouse/searchResults/LegendMarketplaceSearchResults.tsx",
144
150
  "./src/pages/Profile/LegendMarketplaceSubscriptions.tsx",
145
151
  "./src/pages/Profile/LegendMarketplaceYourOrders.tsx",