@finos/legend-application-marketplace 0.2.20 → 0.2.21

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 (71) hide show
  1. package/lib/application/LegendMarketplaceApplicationConfig.d.ts +6 -3
  2. package/lib/application/LegendMarketplaceApplicationConfig.d.ts.map +1 -1
  3. package/lib/application/LegendMarketplaceApplicationConfig.js +13 -4
  4. package/lib/application/LegendMarketplaceApplicationConfig.js.map +1 -1
  5. package/lib/components/Pagination/PaginationControls.d.ts.map +1 -1
  6. package/lib/components/Pagination/PaginationControls.js +2 -2
  7. package/lib/components/Pagination/PaginationControls.js.map +1 -1
  8. package/lib/components/ProviderCard/LegendMarketplaceOrderProfileCard.d.ts +23 -0
  9. package/lib/components/ProviderCard/LegendMarketplaceOrderProfileCard.d.ts.map +1 -0
  10. package/lib/components/ProviderCard/LegendMarketplaceOrderProfileCard.js +93 -0
  11. package/lib/components/ProviderCard/LegendMarketplaceOrderProfileCard.js.map +1 -0
  12. package/lib/components/ProviderCard/LegendMarketplaceTerminalCard.d.ts.map +1 -1
  13. package/lib/components/ProviderCard/LegendMarketplaceTerminalCard.js +5 -11
  14. package/lib/components/ProviderCard/LegendMarketplaceTerminalCard.js.map +1 -1
  15. package/lib/components/ProviderCard/OrderProfileDetailModal.d.ts +26 -0
  16. package/lib/components/ProviderCard/OrderProfileDetailModal.d.ts.map +1 -0
  17. package/lib/components/ProviderCard/OrderProfileDetailModal.js +36 -0
  18. package/lib/components/ProviderCard/OrderProfileDetailModal.js.map +1 -0
  19. package/lib/components/ProviderCard/OrderProfileMultiselectModal.d.ts +26 -0
  20. package/lib/components/ProviderCard/OrderProfileMultiselectModal.d.ts.map +1 -0
  21. package/lib/components/ProviderCard/OrderProfileMultiselectModal.js +31 -0
  22. package/lib/components/ProviderCard/OrderProfileMultiselectModal.js.map +1 -0
  23. package/lib/components/ProviderCard/orderProfileUtils.d.ts +71 -0
  24. package/lib/components/ProviderCard/orderProfileUtils.d.ts.map +1 -0
  25. package/lib/components/ProviderCard/orderProfileUtils.js +122 -0
  26. package/lib/components/ProviderCard/orderProfileUtils.js.map +1 -0
  27. package/lib/index.css +2 -2
  28. package/lib/index.css.map +1 -1
  29. package/lib/package.json +1 -1
  30. package/lib/pages/Lakehouse/entitlements/PermitDataAccessRequest.d.ts.map +1 -1
  31. package/lib/pages/Lakehouse/entitlements/PermitDataAccessRequest.js +3 -0
  32. package/lib/pages/Lakehouse/entitlements/PermitDataAccessRequest.js.map +1 -1
  33. package/lib/pages/TerminalsAddons/LegendMarketplaceTerminalsAddons.d.ts.map +1 -1
  34. package/lib/pages/TerminalsAddons/LegendMarketplaceTerminalsAddons.js +42 -9
  35. package/lib/pages/TerminalsAddons/LegendMarketplaceTerminalsAddons.js.map +1 -1
  36. package/lib/stores/LegendMarketPlaceVendorDataStore.d.ts +6 -2
  37. package/lib/stores/LegendMarketPlaceVendorDataStore.d.ts.map +1 -1
  38. package/lib/stores/LegendMarketPlaceVendorDataStore.js +25 -2
  39. package/lib/stores/LegendMarketPlaceVendorDataStore.js.map +1 -1
  40. package/lib/stores/LegendMarketplaceBaseStore.d.ts +1 -1
  41. package/lib/stores/LegendMarketplaceBaseStore.d.ts.map +1 -1
  42. package/lib/stores/LegendMarketplaceBaseStore.js +10 -5
  43. package/lib/stores/LegendMarketplaceBaseStore.js.map +1 -1
  44. package/lib/stores/ai/LegendMarketplaceAIChatStore.d.ts +10 -0
  45. package/lib/stores/ai/LegendMarketplaceAIChatStore.d.ts.map +1 -1
  46. package/lib/stores/ai/LegendMarketplaceAIChatStore.js +115 -50
  47. package/lib/stores/ai/LegendMarketplaceAIChatStore.js.map +1 -1
  48. package/lib/stores/cart/CartStore.d.ts +14 -2
  49. package/lib/stores/cart/CartStore.d.ts.map +1 -1
  50. package/lib/stores/cart/CartStore.js +68 -5
  51. package/lib/stores/cart/CartStore.js.map +1 -1
  52. package/lib/stores/lakehouse/entitlements/EntitlementsDashboardState.d.ts +2 -1
  53. package/lib/stores/lakehouse/entitlements/EntitlementsDashboardState.d.ts.map +1 -1
  54. package/lib/stores/lakehouse/entitlements/EntitlementsDashboardState.js +8 -3
  55. package/lib/stores/lakehouse/entitlements/EntitlementsDashboardState.js.map +1 -1
  56. package/package.json +10 -10
  57. package/src/application/LegendMarketplaceApplicationConfig.ts +19 -11
  58. package/src/components/Pagination/PaginationControls.tsx +19 -17
  59. package/src/components/ProviderCard/LegendMarketplaceOrderProfileCard.tsx +246 -0
  60. package/src/components/ProviderCard/LegendMarketplaceTerminalCard.tsx +9 -16
  61. package/src/components/ProviderCard/OrderProfileDetailModal.tsx +224 -0
  62. package/src/components/ProviderCard/OrderProfileMultiselectModal.tsx +142 -0
  63. package/src/components/ProviderCard/orderProfileUtils.ts +165 -0
  64. package/src/pages/Lakehouse/entitlements/PermitDataAccessRequest.tsx +3 -0
  65. package/src/pages/TerminalsAddons/LegendMarketplaceTerminalsAddons.tsx +170 -21
  66. package/src/stores/LegendMarketPlaceVendorDataStore.tsx +33 -1
  67. package/src/stores/LegendMarketplaceBaseStore.ts +13 -9
  68. package/src/stores/ai/LegendMarketplaceAIChatStore.ts +273 -69
  69. package/src/stores/cart/CartStore.ts +90 -4
  70. package/src/stores/lakehouse/entitlements/EntitlementsDashboardState.ts +10 -1
  71. package/tsconfig.json +4 -0
@@ -15,6 +15,7 @@
15
15
  */
16
16
 
17
17
  import { observer } from 'mobx-react-lite';
18
+ import { type JSX, useEffect, useCallback } from 'react';
18
19
  import { LegendMarketplaceSearchBar } from '../../components/SearchBar/LegendMarketplaceSearchBar.js';
19
20
  import {
20
21
  Button,
@@ -25,14 +26,17 @@ import {
25
26
  ListItem,
26
27
  CircularProgress,
27
28
  } from '@mui/material';
28
- import type { TerminalResult } from '@finos/legend-server-marketplace';
29
+ import type {
30
+ TerminalResult,
31
+ TraderProfile,
32
+ } from '@finos/legend-server-marketplace';
29
33
  import { LegendMarketplaceTerminalCard } from '../../components/ProviderCard/LegendMarketplaceTerminalCard.js';
34
+ import { LegendMarketplaceOrderProfileCard } from '../../components/ProviderCard/LegendMarketplaceOrderProfileCard.js';
30
35
  import {
31
36
  type LegendMarketPlaceVendorDataStore,
32
37
  VendorDataProviderType,
33
38
  } from '../../stores/LegendMarketPlaceVendorDataStore.js';
34
39
  import { LegendMarketplacePage } from '../LegendMarketplacePage.js';
35
- import { useEffect, useCallback } from 'react';
36
40
  import {
37
41
  useLegendMarketPlaceVendorDataStore,
38
42
  withLegendMarketplaceVendorDataStore,
@@ -52,6 +56,7 @@ export const RefinedVendorRadioSelector = observer(
52
56
  VendorDataProviderType.ALL,
53
57
  VendorDataProviderType.TERMINAL_LICENSE,
54
58
  VendorDataProviderType.ADD_ONS,
59
+ VendorDataProviderType.ORDER_PROFILE,
55
60
  ];
56
61
 
57
62
  const onRadioChange = useCallback(
@@ -91,24 +96,31 @@ export const RefinedVendorRadioSelector = observer(
91
96
  },
92
97
  );
93
98
 
94
- const SearchResultsRenderer = observer(
99
+ /**
100
+ * Shared section wrapper that renders the header (title, count badge, tooltip,
101
+ * "See All" button) plus any card content passed via the `renderCards` prop.
102
+ * Use this as the base for both terminal/add-on and order-profile sections so
103
+ * the header logic lives in exactly one place.
104
+ */
105
+ const SearchResultsSection = observer(
95
106
  (props: {
96
107
  vendorDataState: LegendMarketPlaceVendorDataStore;
97
- terminalResults: TerminalResult[];
98
108
  sectionTitle: VendorDataProviderType;
99
- totalCount?: number | undefined;
100
- seeAll?: boolean;
101
- tooltip?: string;
102
- }) => {
109
+ itemCount: number;
110
+ totalCount: number | undefined;
111
+ tooltip: string | undefined;
112
+ seeAll: boolean | undefined;
113
+ renderCards: () => JSX.Element;
114
+ }): JSX.Element => {
103
115
  const {
104
116
  vendorDataState,
105
- terminalResults,
106
117
  sectionTitle,
118
+ itemCount,
107
119
  totalCount,
108
- seeAll,
109
120
  tooltip,
121
+ seeAll,
122
+ renderCards,
110
123
  } = props;
111
-
112
124
  const showCount = vendorDataState.searchTerm.trim().length > 0;
113
125
 
114
126
  return (
@@ -118,7 +130,7 @@ const SearchResultsRenderer = observer(
118
130
  {sectionTitle}
119
131
  {showCount && (
120
132
  <span className="legend-marketplace-vendordata-main-sidebar__title__count">
121
- ({totalCount ?? terminalResults.length})
133
+ ({totalCount ?? itemCount})
122
134
  </span>
123
135
  )}
124
136
  </div>
@@ -141,19 +153,93 @@ const SearchResultsRenderer = observer(
141
153
  </button>
142
154
  )}
143
155
  </div>
144
- <div className="legend-marketplace-vendordata-main-search-results__card-group">
145
- {terminalResults.map((terminal) => (
146
- <LegendMarketplaceTerminalCard
147
- key={terminal.id}
148
- terminalResult={terminal}
149
- />
150
- ))}
151
- </div>
156
+ {renderCards()}
152
157
  </div>
153
158
  );
154
159
  },
155
160
  );
156
161
 
162
+ const SearchResultsRenderer = observer(
163
+ (props: {
164
+ vendorDataState: LegendMarketPlaceVendorDataStore;
165
+ terminalResults: TerminalResult[];
166
+ sectionTitle: VendorDataProviderType;
167
+ totalCount?: number;
168
+ seeAll?: boolean;
169
+ tooltip?: string;
170
+ }): JSX.Element => {
171
+ const {
172
+ vendorDataState,
173
+ terminalResults,
174
+ sectionTitle,
175
+ totalCount,
176
+ seeAll,
177
+ tooltip,
178
+ } = props;
179
+
180
+ return (
181
+ <SearchResultsSection
182
+ vendorDataState={vendorDataState}
183
+ sectionTitle={sectionTitle}
184
+ itemCount={terminalResults.length}
185
+ totalCount={totalCount}
186
+ seeAll={seeAll}
187
+ tooltip={tooltip}
188
+ renderCards={() => (
189
+ <div className="legend-marketplace-vendordata-main-search-results__card-group">
190
+ {terminalResults.map((terminal) => (
191
+ <LegendMarketplaceTerminalCard
192
+ key={terminal.id}
193
+ terminalResult={terminal}
194
+ />
195
+ ))}
196
+ </div>
197
+ )}
198
+ />
199
+ );
200
+ },
201
+ );
202
+
203
+ const OrderProfileSearchResultsRenderer = observer(
204
+ (props: {
205
+ vendorDataState: LegendMarketPlaceVendorDataStore;
206
+ traderProfiles: TraderProfile[];
207
+ totalCount?: number;
208
+ tooltip?: string;
209
+ seeAll?: boolean;
210
+ }): JSX.Element => {
211
+ const { vendorDataState, traderProfiles, totalCount, tooltip, seeAll } =
212
+ props;
213
+
214
+ return (
215
+ <SearchResultsSection
216
+ vendorDataState={vendorDataState}
217
+ sectionTitle={VendorDataProviderType.ORDER_PROFILE}
218
+ itemCount={traderProfiles.length}
219
+ totalCount={totalCount}
220
+ seeAll={seeAll}
221
+ tooltip={tooltip}
222
+ renderCards={() =>
223
+ traderProfiles.length === 0 ? (
224
+ <div className="legend-marketplace-vendordata-main__empty">
225
+ No Order Profiles available
226
+ </div>
227
+ ) : (
228
+ <div className="legend-marketplace-vendordata-main-search-results__card-group">
229
+ {traderProfiles.map((profile) => (
230
+ <LegendMarketplaceOrderProfileCard
231
+ key={profile.id}
232
+ traderProfile={profile}
233
+ />
234
+ ))}
235
+ </div>
236
+ )
237
+ }
238
+ />
239
+ );
240
+ },
241
+ );
242
+
157
243
  export const VendorDataMainContent = observer(
158
244
  (props: { marketPlaceVendorDataState: LegendMarketPlaceVendorDataStore }) => {
159
245
  const { marketPlaceVendorDataState } = props;
@@ -211,6 +297,17 @@ export const VendorDataMainContent = observer(
211
297
  seeAll={true}
212
298
  tooltip={addOnsInfoMessage}
213
299
  />
300
+ <hr />
301
+ <OrderProfileSearchResultsRenderer
302
+ vendorDataState={marketPlaceVendorDataState}
303
+ traderProfiles={
304
+ marketPlaceVendorDataState.traderProfileProviders
305
+ }
306
+ totalCount={
307
+ marketPlaceVendorDataState.totalTraderProfileItems
308
+ }
309
+ seeAll={true}
310
+ />
214
311
  </>
215
312
  )}
216
313
  {marketPlaceVendorDataState.providerDisplayState ===
@@ -234,11 +331,23 @@ export const VendorDataMainContent = observer(
234
331
  tooltip={addOnsInfoMessage}
235
332
  />
236
333
  )}
334
+ {marketPlaceVendorDataState.providerDisplayState ===
335
+ VendorDataProviderType.ORDER_PROFILE && (
336
+ <OrderProfileSearchResultsRenderer
337
+ vendorDataState={marketPlaceVendorDataState}
338
+ traderProfiles={
339
+ marketPlaceVendorDataState.traderProfileAllProviders
340
+ }
341
+ totalCount={marketPlaceVendorDataState.totalItems}
342
+ />
343
+ )}
237
344
  </div>
238
345
  {(marketPlaceVendorDataState.providerDisplayState ===
239
346
  VendorDataProviderType.TERMINAL_LICENSE ||
240
347
  marketPlaceVendorDataState.providerDisplayState ===
241
- VendorDataProviderType.ADD_ONS) && (
348
+ VendorDataProviderType.ADD_ONS ||
349
+ marketPlaceVendorDataState.providerDisplayState ===
350
+ VendorDataProviderType.ORDER_PROFILE) && (
242
351
  <PaginationControls
243
352
  totalItems={marketPlaceVendorDataState.totalItems}
244
353
  itemsPerPage={marketPlaceVendorDataState.itemsPerPage}
@@ -342,6 +451,46 @@ export const LegendMarketplaceVendorData = withLegendMarketplaceVendorDataStore(
342
451
  vendorDataState={marketPlaceVendorDataStore}
343
452
  />
344
453
  </div>
454
+ <div className="legend-marketplace-body__action-buttons">
455
+ {marketplaceStore.applicationStore.config.options
456
+ .generalInquiriesUrl && (
457
+ <Button
458
+ variant="outlined"
459
+ className="legend-marketplace-body__action-button"
460
+ onClick={() => {
461
+ const url =
462
+ marketplaceStore.applicationStore.config.options
463
+ .generalInquiriesUrl;
464
+ if (url) {
465
+ marketplaceStore.applicationStore.navigationService.navigator.visitAddress(
466
+ url,
467
+ );
468
+ }
469
+ }}
470
+ >
471
+ General Inquiries
472
+ </Button>
473
+ )}
474
+ {marketplaceStore.applicationStore.config.options
475
+ .requestInternalAppUrl && (
476
+ <Button
477
+ variant="outlined"
478
+ className="legend-marketplace-body__action-button"
479
+ onClick={() => {
480
+ const url =
481
+ marketplaceStore.applicationStore.config.options
482
+ .requestInternalAppUrl;
483
+ if (url) {
484
+ marketplaceStore.applicationStore.navigationService.navigator.visitAddress(
485
+ url,
486
+ );
487
+ }
488
+ }}
489
+ >
490
+ Request Internal Application
491
+ </Button>
492
+ )}
493
+ </div>
345
494
  </div>
346
495
  <VendorDataMainContent
347
496
  marketPlaceVendorDataState={marketPlaceVendorDataStore}
@@ -16,6 +16,7 @@
16
16
 
17
17
  import {
18
18
  TerminalResult,
19
+ TraderProfile,
19
20
  type Filter,
20
21
  type MarketplaceServerClient,
21
22
  type TerminalServicesResponse,
@@ -38,6 +39,7 @@ export enum VendorDataProviderType {
38
39
  ALL = 'All',
39
40
  TERMINAL_LICENSE = 'Terminal License',
40
41
  ADD_ONS = 'Add-Ons',
42
+ ORDER_PROFILE = 'Order Profile',
41
43
  }
42
44
 
43
45
  export class LegendMarketPlaceVendorDataStore {
@@ -51,12 +53,15 @@ export class LegendMarketPlaceVendorDataStore {
51
53
 
52
54
  terminalProviders: TerminalResult[] = [];
53
55
  addOnProviders: TerminalResult[] = [];
56
+ traderProfileProviders: TraderProfile[] = [];
54
57
  providers: TerminalResult[] = [];
58
+ traderProfileAllProviders: TraderProfile[] = [];
55
59
 
56
60
  page = 1;
57
61
  itemsPerPage = 24;
58
62
  totalTerminalItems = 0;
59
63
  totalAddOnItems = 0;
64
+ totalTraderProfileItems = 0;
60
65
  totalItems = 0;
61
66
 
62
67
  searchTerm = '';
@@ -73,11 +78,14 @@ export class LegendMarketPlaceVendorDataStore {
73
78
  selectedUser: observable,
74
79
  terminalProviders: observable,
75
80
  addOnProviders: observable,
81
+ traderProfileProviders: observable,
76
82
  providers: observable,
83
+ traderProfileAllProviders: observable,
77
84
  page: observable,
78
85
  itemsPerPage: observable,
79
86
  totalTerminalItems: observable,
80
87
  totalAddOnItems: observable,
88
+ totalTraderProfileItems: observable,
81
89
  totalItems: observable,
82
90
  searchTerm: observable,
83
91
  providerDisplayState: observable,
@@ -181,8 +189,13 @@ export class LegendMarketPlaceVendorDataStore {
181
189
  TerminalResult.serialization.fromJson(json),
182
190
  );
183
191
 
192
+ this.traderProfileProviders = (response.order_profile ?? []).map(
193
+ (json) => TraderProfile.serialization.fromJson(json),
194
+ );
195
+
184
196
  this.totalTerminalItems = response.vendor_profiles_total_count ?? 0;
185
197
  this.totalAddOnItems = response.service_pricing_total_count ?? 0;
198
+ this.totalTraderProfileItems = response.order_profile_total_count ?? 0;
186
199
  } else if (
187
200
  this.providerDisplayState === VendorDataProviderType.TERMINAL_LICENSE
188
201
  ) {
@@ -203,7 +216,7 @@ export class LegendMarketPlaceVendorDataStore {
203
216
  );
204
217
 
205
218
  this.totalItems = response.total_count ?? 0;
206
- } else {
219
+ } else if (this.providerDisplayState === VendorDataProviderType.ADD_ONS) {
207
220
  const params: FetchProductsParams = {
208
221
  kerberos: this.selectedUser.id,
209
222
  product_type: ProductType.SERVICE_PRICING,
@@ -220,6 +233,25 @@ export class LegendMarketPlaceVendorDataStore {
220
233
  TerminalResult.serialization.fromJson(json),
221
234
  );
222
235
 
236
+ this.totalItems = response.total_count ?? 0;
237
+ } else {
238
+ // ORDER_PROFILE
239
+ const params: FetchProductsParams = {
240
+ kerberos: this.selectedUser.id,
241
+ product_type: ProductType.ORDER_PROFILE,
242
+ preferred_products: false,
243
+ page_size: this.itemsPerPage,
244
+ search: this.searchTerm,
245
+ page_number: this.page,
246
+ };
247
+ const response = (yield this.marketplaceServerClient.fetchProducts(
248
+ params,
249
+ )) as TerminalServicesResponse;
250
+
251
+ this.traderProfileAllProviders = (response.order_profile ?? []).map(
252
+ (json) => TraderProfile.serialization.fromJson(json),
253
+ );
254
+
223
255
  this.totalItems = response.total_count ?? 0;
224
256
  }
225
257
 
@@ -94,7 +94,7 @@ export class LegendMarketplaceBaseStore {
94
94
  readonly remoteEngine: V1_RemoteEngine;
95
95
  readonly userSearchService: UserSearchService | undefined;
96
96
  readonly lakehouseWorkflowServerClient: LakehouseWorkflowServerClient;
97
- readonly permitWorkflowServerClient: PermitWorkflowServerClient;
97
+ readonly permitWorkflowServerClient: PermitWorkflowServerClient | undefined;
98
98
  readonly lakehouseDataProductService: LakehouseDataProductService;
99
99
  readonly cartStore: CartStore;
100
100
  readonly terminalAccessServerClient: TerminalAccessServerClient;
@@ -182,14 +182,18 @@ export class LegendMarketplaceBaseStore {
182
182
  );
183
183
 
184
184
  // permit + eTask workflow
185
- this.permitWorkflowServerClient = new PermitWorkflowServerClient({
186
- authBaseUrl: this.applicationStore.config.lakehouseServerUrl,
187
- workflowBaseUrl:
188
- this.applicationStore.config.lakehousePermitWorkflowServerUrl,
189
- });
190
- this.permitWorkflowServerClient.setTracerService(
191
- this.applicationStore.tracerService,
192
- );
185
+ if (this.applicationStore.config.lakehousePermitWorkflowServerUrl) {
186
+ this.permitWorkflowServerClient = new PermitWorkflowServerClient({
187
+ authBaseUrl: this.applicationStore.config.lakehouseServerUrl,
188
+ workflowBaseUrl:
189
+ this.applicationStore.config.lakehousePermitWorkflowServerUrl,
190
+ });
191
+ this.permitWorkflowServerClient.setTracerService(
192
+ this.applicationStore.tracerService,
193
+ );
194
+ } else {
195
+ this.permitWorkflowServerClient = undefined;
196
+ }
193
197
 
194
198
  // lakehouse ingest
195
199
  this.lakehouseIngestServerClient = new LakehouseIngestServerClient(