@finos/legend-application-marketplace 0.2.12 → 0.2.14

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 (39) hide show
  1. package/lib/components/MarketplaceCard/FieldSearchResultListItem.d.ts +1 -0
  2. package/lib/components/MarketplaceCard/FieldSearchResultListItem.d.ts.map +1 -1
  3. package/lib/components/MarketplaceCard/FieldSearchResultListItem.js +30 -12
  4. package/lib/components/MarketplaceCard/FieldSearchResultListItem.js.map +1 -1
  5. package/lib/index.css +2 -2
  6. package/lib/index.css.map +1 -1
  7. package/lib/package.json +1 -1
  8. package/lib/pages/Lakehouse/entitlements/EntitlementsClosedContractsDashboard.d.ts.map +1 -1
  9. package/lib/pages/Lakehouse/entitlements/EntitlementsClosedContractsDashboard.js +14 -3
  10. package/lib/pages/Lakehouse/entitlements/EntitlementsClosedContractsDashboard.js.map +1 -1
  11. package/lib/pages/Lakehouse/entitlements/EntitlementsPendingContractsDashboard.d.ts.map +1 -1
  12. package/lib/pages/Lakehouse/entitlements/EntitlementsPendingContractsDashboard.js +15 -3
  13. package/lib/pages/Lakehouse/entitlements/EntitlementsPendingContractsDashboard.js.map +1 -1
  14. package/lib/pages/Lakehouse/entitlements/EntitlementsPendingTasksDashboard.d.ts.map +1 -1
  15. package/lib/pages/Lakehouse/entitlements/EntitlementsPendingTasksDashboard.js +19 -4
  16. package/lib/pages/Lakehouse/entitlements/EntitlementsPendingTasksDashboard.js.map +1 -1
  17. package/lib/pages/Lakehouse/searchResults/LegendMarketplaceFieldSearchResults.d.ts.map +1 -1
  18. package/lib/pages/Lakehouse/searchResults/LegendMarketplaceFieldSearchResults.js +29 -23
  19. package/lib/pages/Lakehouse/searchResults/LegendMarketplaceFieldSearchResults.js.map +1 -1
  20. package/lib/pages/Lakehouse/searchResults/LegendMarketplaceSearchResults.d.ts.map +1 -1
  21. package/lib/pages/Lakehouse/searchResults/LegendMarketplaceSearchResults.js +8 -1
  22. package/lib/pages/Lakehouse/searchResults/LegendMarketplaceSearchResults.js.map +1 -1
  23. package/lib/stores/lakehouse/entitlements/EntitlementsDashboardState.d.ts +26 -1
  24. package/lib/stores/lakehouse/entitlements/EntitlementsDashboardState.d.ts.map +1 -1
  25. package/lib/stores/lakehouse/entitlements/EntitlementsDashboardState.js +233 -14
  26. package/lib/stores/lakehouse/entitlements/EntitlementsDashboardState.js.map +1 -1
  27. package/lib/stores/lakehouse/fieldSearch/FieldSearchResultState.d.ts +4 -0
  28. package/lib/stores/lakehouse/fieldSearch/FieldSearchResultState.d.ts.map +1 -1
  29. package/lib/stores/lakehouse/fieldSearch/FieldSearchResultState.js +44 -7
  30. package/lib/stores/lakehouse/fieldSearch/FieldSearchResultState.js.map +1 -1
  31. package/package.json +8 -8
  32. package/src/components/MarketplaceCard/FieldSearchResultListItem.tsx +110 -32
  33. package/src/pages/Lakehouse/entitlements/EntitlementsClosedContractsDashboard.tsx +22 -2
  34. package/src/pages/Lakehouse/entitlements/EntitlementsPendingContractsDashboard.tsx +28 -4
  35. package/src/pages/Lakehouse/entitlements/EntitlementsPendingTasksDashboard.tsx +45 -5
  36. package/src/pages/Lakehouse/searchResults/LegendMarketplaceFieldSearchResults.tsx +100 -25
  37. package/src/pages/Lakehouse/searchResults/LegendMarketplaceSearchResults.tsx +37 -0
  38. package/src/stores/lakehouse/entitlements/EntitlementsDashboardState.ts +371 -37
  39. package/src/stores/lakehouse/fieldSearch/FieldSearchResultState.ts +53 -4
@@ -55,6 +55,7 @@ import { observer } from 'mobx-react-lite';
55
55
  import type { LegendMarketplaceBaseStore } from '../../../stores/LegendMarketplaceBaseStore.js';
56
56
  import { startCase } from '@finos/legend-shared';
57
57
  import {
58
+ type ContractErrorLayer,
58
59
  UserRenderer,
59
60
  getOrganizationalScopeTypeName,
60
61
  getOrganizationalScopeTypeDetails,
@@ -289,6 +290,9 @@ export const EntitlementsPendingTasksDashboard = observer(
289
290
  >();
290
291
  const [selectedContractTargetUser, setSelectedContractTargetUser] =
291
292
  useState<string | undefined>();
293
+ const [contractErrors, setContractErrors] = useState<
294
+ ContractErrorLayer | undefined
295
+ >(undefined);
292
296
 
293
297
  const auth = useAuth();
294
298
 
@@ -309,7 +313,7 @@ export const EntitlementsPendingTasksDashboard = observer(
309
313
  event.api.setNodesSelected({ nodes: nodesToSelect, newValue: true });
310
314
  };
311
315
 
312
- const handleCellClicked = (
316
+ const handleCellClicked = async (
313
317
  event: DataGridCellClickedEvent<V1_ContractUserEventRecord, unknown>,
314
318
  ) => {
315
319
  if (event.colDef.colId !== 'selection') {
@@ -318,6 +322,14 @@ export const EntitlementsPendingTasksDashboard = observer(
318
322
  );
319
323
  setSelectedContract(contract);
320
324
  setSelectedContractTargetUser(event.data?.consumer);
325
+ setContractErrors(undefined);
326
+ if (contract !== undefined) {
327
+ const result = await dashboardState.getContractErrors(
328
+ contract.guid,
329
+ auth.user?.access_token,
330
+ );
331
+ setContractErrors(result);
332
+ }
321
333
  }
322
334
  };
323
335
 
@@ -737,7 +749,15 @@ export const EntitlementsPendingTasksDashboard = observer(
737
749
  rowHeight={45}
738
750
  rowSelection={rowSelection}
739
751
  onFirstDataRendered={handleFirstDataRendered}
740
- onCellClicked={handleCellClicked}
752
+ onCellClicked={(
753
+ event: DataGridCellClickedEvent<
754
+ V1_ContractUserEventRecord,
755
+ unknown
756
+ >,
757
+ ) =>
758
+ // eslint-disable-next-line no-void
759
+ void handleCellClicked(event)
760
+ }
741
761
  columnDefs={privilegeManagerColDefs}
742
762
  overlayNoRowsTemplate="You have no contracts to approve as a Privilege Manager"
743
763
  loading={loading}
@@ -772,7 +792,15 @@ export const EntitlementsPendingTasksDashboard = observer(
772
792
  rowHeight={45}
773
793
  rowSelection={rowSelection}
774
794
  onFirstDataRendered={handleFirstDataRendered}
775
- onCellClicked={handleCellClicked}
795
+ onCellClicked={(
796
+ event: DataGridCellClickedEvent<
797
+ V1_ContractUserEventRecord,
798
+ unknown
799
+ >,
800
+ ) =>
801
+ // eslint-disable-next-line no-void
802
+ void handleCellClicked(event)
803
+ }
776
804
  columnDefs={dataOwnerColDefs}
777
805
  overlayNoRowsTemplate="You have no contracts to approve as a Data Owner"
778
806
  loading={loading}
@@ -796,7 +824,15 @@ export const EntitlementsPendingTasksDashboard = observer(
796
824
  rowHeight={45}
797
825
  rowSelection={rowSelection}
798
826
  onFirstDataRendered={handleFirstDataRendered}
799
- onCellClicked={handleCellClicked}
827
+ onCellClicked={(
828
+ event: DataGridCellClickedEvent<
829
+ V1_ContractUserEventRecord,
830
+ unknown
831
+ >,
832
+ ) =>
833
+ // eslint-disable-next-line no-void
834
+ void handleCellClicked(event)
835
+ }
800
836
  columnDefs={otherTasksColDefs}
801
837
  loading={loading}
802
838
  overlayLoadingTemplate="Loading contracts"
@@ -822,7 +858,11 @@ export const EntitlementsPendingTasksDashboard = observer(
822
858
  {selectedContract !== undefined && (
823
859
  <DataAccessRequestViewer
824
860
  open={true}
825
- onClose={() => setSelectedContract(undefined)}
861
+ onClose={() => {
862
+ setSelectedContract(undefined);
863
+ setContractErrors(undefined);
864
+ }}
865
+ contractErrors={contractErrors}
826
866
  viewerState={
827
867
  new DataContractViewerState(
828
868
  selectedContract,
@@ -20,20 +20,22 @@ import { flowResult } from 'mobx';
20
20
  import { useCallback, useEffect, useRef } from 'react';
21
21
  import { useSyncStateAndSearchParam } from '@finos/legend-application';
22
22
  import { useSearchParams } from '@finos/legend-application/browser';
23
- import { isNonEmptyString } from '@finos/legend-shared';
23
+ import { isNonEmptyString, LogEvent } from '@finos/legend-shared';
24
24
  import {
25
25
  CubesLoadingIndicator,
26
26
  CubesLoadingIndicatorIcon,
27
27
  } from '@finos/legend-art';
28
- import { DATAPRODUCT_TYPE } from '@finos/legend-extension-dsl-data-product';
29
28
  import {
30
29
  LEGEND_MARKETPLACE_FIELD_SEARCH_RESULTS_QUERY_PARAM_TOKEN,
31
30
  generateLakehouseSearchResultsRoute,
31
+ EXTERNAL_APPLICATION_NAVIGATION__generateDataSpaceQueryEditorUrl,
32
32
  } from '../../../__lib__/LegendMarketplaceNavigation.js';
33
33
  import {
34
34
  LEGEND_MARKETPLACE_PAGE,
35
35
  LegendMarketplaceTelemetryHelper,
36
36
  } from '../../../__lib__/LegendMarketplaceTelemetryHelper.js';
37
+
38
+ import { LEGEND_MARKETPLACE_APP_EVENT } from '../../../__lib__/LegendMarketplaceAppEvent.js';
37
39
  import {
38
40
  useLegendMarketplaceFieldSearchResultsStore,
39
41
  withLegendMarketplaceFieldSearchResultsStore,
@@ -54,6 +56,9 @@ const FieldSearchResultsContent = observer(
54
56
  handleItemsPerPageChange: (itemsPerPage: number) => void;
55
57
  handleToggleExpandRow: (rowId: string) => void;
56
58
  handleOpenDataProduct: (dataProduct: FieldSearchDataProductEntry) => void;
59
+ handleOpenDatasetInQuery: (
60
+ dataProduct: FieldSearchDataProductEntry,
61
+ ) => void;
57
62
  }) => {
58
63
  const {
59
64
  fieldSearchResultsStore,
@@ -61,6 +66,7 @@ const FieldSearchResultsContent = observer(
61
66
  handleItemsPerPageChange,
62
67
  handleToggleExpandRow,
63
68
  handleOpenDataProduct,
69
+ handleOpenDatasetInQuery,
64
70
  } = props;
65
71
 
66
72
  if (fieldSearchResultsStore.isLoading) {
@@ -160,6 +166,9 @@ const FieldSearchResultsContent = observer(
160
166
  <Typography className="marketplace-lakehouse-field-search-results__list-header-cell">
161
167
  Data Products
162
168
  </Typography>
169
+ <Typography className="marketplace-lakehouse-field-search-results__list-header-cell">
170
+ Datasets
171
+ </Typography>
163
172
  </div>
164
173
  <div className="marketplace-lakehouse-field-search-results__list-body">
165
174
  {fieldSearchResultsStore.tableRows.map((row) => (
@@ -169,6 +178,7 @@ const FieldSearchResultsContent = observer(
169
178
  expanded={fieldSearchResultsStore.isRowExpanded(row.id)}
170
179
  onToggleExpanded={handleToggleExpandRow}
171
180
  onOpenDataProduct={handleOpenDataProduct}
181
+ onOpenDatasetInQuery={handleOpenDatasetInQuery}
172
182
  />
173
183
  ))}
174
184
  </div>
@@ -283,29 +293,45 @@ const LegendMarketplaceFieldSearchResultsPage = observer(() => {
283
293
  [applicationStore, fieldSearchResultsStore],
284
294
  );
285
295
 
286
- const handleOpenDataProduct = useCallback(
287
- (dataProduct: FieldSearchDataProductEntry) => {
288
- LegendMarketplaceTelemetryHelper.logEvent_ClickingDataProductCard(
289
- applicationStore.telemetryService,
290
- {
291
- origin:
292
- dataProduct.productType === DataProductTypeFilter.LEGACY
293
- ? {
294
- type: DATAPRODUCT_TYPE.SDLC,
295
- groupId: dataProduct.groupId,
296
- artifactId: dataProduct.artifactId,
297
- versionId: dataProduct.versionId,
298
- path: dataProduct.entityPath,
299
- }
300
- : {
301
- type: DATAPRODUCT_TYPE.ADHOC,
302
- },
303
- dataProductId: dataProduct.dataProductId,
304
- name: dataProduct.name,
305
- deploymentId: dataProduct.deploymentId,
306
- },
307
- LEGEND_MARKETPLACE_PAGE.SEARCH_RESULTS_PAGE,
308
- );
296
+ const openInLegendQuery = useCallback(
297
+ (
298
+ dataProduct: FieldSearchDataProductEntry,
299
+ modelPath: string | undefined,
300
+ ) => {
301
+ const isLegacyDataProduct =
302
+ dataProduct.productType === DataProductTypeFilter.LEGACY;
303
+ const canOpenLegacyQuery =
304
+ dataProduct.groupId &&
305
+ dataProduct.artifactId &&
306
+ dataProduct.versionId &&
307
+ dataProduct.executionContextKey;
308
+
309
+ if (isLegacyDataProduct && canOpenLegacyQuery) {
310
+ applicationStore.navigationService.navigator.visitAddress(
311
+ EXTERNAL_APPLICATION_NAVIGATION__generateDataSpaceQueryEditorUrl(
312
+ applicationStore.config.queryApplicationUrl,
313
+ dataProduct.groupId,
314
+ dataProduct.artifactId,
315
+ dataProduct.versionId,
316
+ dataProduct.entityPath,
317
+ dataProduct.executionContextKey,
318
+ undefined,
319
+ modelPath,
320
+ ),
321
+ );
322
+ return;
323
+ }
324
+
325
+ if (isLegacyDataProduct && !canOpenLegacyQuery) {
326
+ applicationStore.logService.warn(
327
+ LogEvent.create(
328
+ LEGEND_MARKETPLACE_APP_EVENT.CLICK_QUERY_DATA_PRODUCT,
329
+ ),
330
+ `Falling back to marketplace navigation for legacy data product ${dataProduct.entityPath} due to missing query context`,
331
+ );
332
+ }
333
+
334
+ // Fallback to marketplace data product page for adhoc/lakehouse products
309
335
  applicationStore.navigationService.navigator.visitAddress(
310
336
  applicationStore.navigationService.navigator.generateAddress(
311
337
  dataProduct.path,
@@ -315,6 +341,20 @@ const LegendMarketplaceFieldSearchResultsPage = observer(() => {
315
341
  [applicationStore],
316
342
  );
317
343
 
344
+ const handleOpenDataProduct = useCallback(
345
+ (dataProduct: FieldSearchDataProductEntry) => {
346
+ openInLegendQuery(dataProduct, undefined);
347
+ },
348
+ [openInLegendQuery],
349
+ );
350
+
351
+ const handleOpenDatasetInQuery = useCallback(
352
+ (dataProduct: FieldSearchDataProductEntry) => {
353
+ openInLegendQuery(dataProduct, dataProduct.modelPath);
354
+ },
355
+ [openInLegendQuery],
356
+ );
357
+
318
358
  const handleToggleExpandRow = useCallback(
319
359
  (rowId: string) => {
320
360
  fieldSearchResultsStore.toggleExpandRow(rowId);
@@ -322,6 +362,15 @@ const LegendMarketplaceFieldSearchResultsPage = observer(() => {
322
362
  [fieldSearchResultsStore],
323
363
  );
324
364
 
365
+ const handleOpenDataProductsTab = useCallback(() => {
366
+ applicationStore.navigationService.navigator.goToLocation(
367
+ generateLakehouseSearchResultsRoute(
368
+ fieldSearchResultsStore.searchQuery,
369
+ false,
370
+ ),
371
+ );
372
+ }, [applicationStore, fieldSearchResultsStore.searchQuery]);
373
+
325
374
  return (
326
375
  <LegendMarketplacePage className="marketplace-lakehouse-search-results marketplace-lakehouse-field-search-results">
327
376
  <div ref={pageRef} />
@@ -345,6 +394,31 @@ const LegendMarketplaceFieldSearchResultsPage = observer(() => {
345
394
  >
346
395
  {fieldSearchResultsStore.totalFieldMatches} Fields
347
396
  </Typography>
397
+ <div
398
+ className="legend-marketplace-search-results__search-type-tabs"
399
+ role="tablist"
400
+ aria-label="Search result type"
401
+ >
402
+ <button
403
+ type="button"
404
+ role="tab"
405
+ aria-selected={false}
406
+ tabIndex={-1}
407
+ className="legend-marketplace-search-results__search-type-tab"
408
+ onClick={handleOpenDataProductsTab}
409
+ >
410
+ Data Products
411
+ </button>
412
+ <button
413
+ type="button"
414
+ role="tab"
415
+ aria-selected={true}
416
+ tabIndex={0}
417
+ className="legend-marketplace-search-results__search-type-tab legend-marketplace-search-results__search-type-tab--active"
418
+ >
419
+ Data Fields
420
+ </button>
421
+ </div>
348
422
  </div>
349
423
  </div>
350
424
  <Container
@@ -366,6 +440,7 @@ const LegendMarketplaceFieldSearchResultsPage = observer(() => {
366
440
  handleItemsPerPageChange={handleItemsPerPageChange}
367
441
  handleToggleExpandRow={handleToggleExpandRow}
368
442
  handleOpenDataProduct={handleOpenDataProduct}
443
+ handleOpenDatasetInQuery={handleOpenDatasetInQuery}
369
444
  />
370
445
  </div>
371
446
  </div>
@@ -382,6 +382,43 @@ export const LegendMarketplaceSearchResults =
382
382
  ? `${searchResultsStore.filterSortProducts?.length ?? 0} Products`
383
383
  : `${searchResultsStore.totalItems} Products`}
384
384
  </Typography>
385
+ <div
386
+ className="legend-marketplace-search-results__search-type-tabs"
387
+ role="tablist"
388
+ aria-label="Search result type"
389
+ >
390
+ <button
391
+ type="button"
392
+ role="tab"
393
+ aria-selected={true}
394
+ tabIndex={0}
395
+ className="legend-marketplace-search-results__search-type-tab legend-marketplace-search-results__search-type-tab--active"
396
+ >
397
+ Data Products
398
+ </button>
399
+ <button
400
+ type="button"
401
+ role="tab"
402
+ aria-selected={false}
403
+ tabIndex={-1}
404
+ className="legend-marketplace-search-results__search-type-tab"
405
+ onClick={() => {
406
+ if (isNonEmptyString(searchResultsStore.searchQuery)) {
407
+ applicationStore.navigationService.navigator.goToLocation(
408
+ generateFieldSearchResultsRoute(
409
+ searchResultsStore.searchQuery,
410
+ ),
411
+ );
412
+ } else {
413
+ applicationStore.navigationService.navigator.goToLocation(
414
+ generateFieldSearchResultsRoute(undefined),
415
+ );
416
+ }
417
+ }}
418
+ >
419
+ Data Fields
420
+ </button>
421
+ </div>
385
422
  <div className="legend-marketplace-search-results__sort-bar__controls">
386
423
  <div className="legend-marketplace-search-results__view-toggle">
387
424
  <div