@gen3/frontend 0.10.89 → 0.10.91

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 (171) hide show
  1. package/dist/cjs/index.js +694 -174
  2. package/dist/cjs/index.js.map +1 -1
  3. package/dist/dts/components/Profile/CredentialsTable.d.ts.map +1 -1
  4. package/dist/dts/components/Profile/CredentialsTable.js +2 -1
  5. package/dist/dts/components/Profile/CredentialsTable.js.map +1 -1
  6. package/dist/dts/components/Providers/Gen3Provider.d.ts.map +1 -1
  7. package/dist/dts/components/Providers/Gen3Provider.js +6 -8
  8. package/dist/dts/components/Providers/Gen3Provider.js.map +1 -1
  9. package/dist/dts/components/Providers/ResourceMonitor.d.ts.map +1 -1
  10. package/dist/dts/components/Providers/ResourceMonitor.js +0 -1
  11. package/dist/dts/components/Providers/ResourceMonitor.js.map +1 -1
  12. package/dist/dts/features/Analysis/AnalysisCardCompact.stories.d.ts +6 -6
  13. package/dist/dts/features/Authz/Gen3Authz.js +2 -2
  14. package/dist/dts/features/Authz/Gen3Authz.js.map +1 -1
  15. package/dist/dts/features/Authz/Policies/PoliciesTable.d.ts.map +1 -1
  16. package/dist/dts/features/Authz/Policies/PoliciesTable.js +3 -3
  17. package/dist/dts/features/Authz/Policies/PoliciesTable.js.map +1 -1
  18. package/dist/dts/features/Authz/Resources/ResourcesTable.d.ts.map +1 -1
  19. package/dist/dts/features/Authz/Resources/ResourcesTable.js +2 -2
  20. package/dist/dts/features/Authz/Resources/ResourcesTable.js.map +1 -1
  21. package/dist/dts/features/Authz/Roles/RolesTable.js +1 -1
  22. package/dist/dts/features/Authz/Roles/RolesTable.js.map +1 -1
  23. package/dist/dts/features/Authz/Users/NewUserPanel.js +1 -1
  24. package/dist/dts/features/Authz/Users/NewUserPanel.js.map +1 -1
  25. package/dist/dts/features/Authz/Users/UserTable.js +1 -1
  26. package/dist/dts/features/Authz/Users/UserTable.js.map +1 -1
  27. package/dist/dts/features/Authz/index.d.ts +2 -2
  28. package/dist/dts/features/Authz/index.d.ts.map +1 -1
  29. package/dist/dts/features/Authz/index.js +2 -2
  30. package/dist/dts/features/Authz/index.js.map +1 -1
  31. package/dist/dts/features/CohortBuilder/CohortBuilder.js +1 -1
  32. package/dist/dts/features/CohortBuilder/CohortBuilder.js.map +1 -1
  33. package/dist/dts/features/CohortDiscovery/CohortDiscovery.js +2 -2
  34. package/dist/dts/features/CohortDiscovery/CohortDiscovery.js.map +1 -1
  35. package/dist/dts/features/DataLibrary/DataLibraryLists.d.ts.map +1 -1
  36. package/dist/dts/features/DataLibrary/DataLibraryLists.js +32 -19
  37. package/dist/dts/features/DataLibrary/DataLibraryLists.js.map +1 -1
  38. package/dist/dts/features/DataLibrary/DatalistAccordionItem.d.ts +3 -4
  39. package/dist/dts/features/DataLibrary/DatalistAccordionItem.d.ts.map +1 -1
  40. package/dist/dts/features/DataLibrary/DatalistAccordionItem.js +11 -9
  41. package/dist/dts/features/DataLibrary/DatalistAccordionItem.js.map +1 -1
  42. package/dist/dts/features/DataLibrary/DatasetAccordionControl.d.ts.map +1 -1
  43. package/dist/dts/features/DataLibrary/DatasetAccordionControl.js +1 -1
  44. package/dist/dts/features/DataLibrary/DatasetAccordionControl.js.map +1 -1
  45. package/dist/dts/features/DataLibrary/QueryDetails.d.ts.map +1 -1
  46. package/dist/dts/features/DataLibrary/QueryDetails.js +6 -2
  47. package/dist/dts/features/DataLibrary/QueryDetails.js.map +1 -1
  48. package/dist/dts/features/DataLibrary/SearchAndActions.d.ts +4 -2
  49. package/dist/dts/features/DataLibrary/SearchAndActions.d.ts.map +1 -1
  50. package/dist/dts/features/DataLibrary/SearchAndActions.js +4 -3
  51. package/dist/dts/features/DataLibrary/SearchAndActions.js.map +1 -1
  52. package/dist/dts/features/DataLibrary/selection/exportActions.d.ts +1 -1
  53. package/dist/dts/features/DataLibrary/selection/exportActions.d.ts.map +1 -1
  54. package/dist/dts/features/DataLibrary/selection/exportActions.js +1 -1
  55. package/dist/dts/features/DataLibrary/selection/exportActions.js.map +1 -1
  56. package/dist/dts/features/DataLibrary/selection/registeredActions.d.ts +1 -4
  57. package/dist/dts/features/DataLibrary/selection/registeredActions.d.ts.map +1 -1
  58. package/dist/dts/features/DataLibrary/selection/registeredActions.js.map +1 -1
  59. package/dist/dts/features/DataLibrary/selection/selection.d.ts +3 -3
  60. package/dist/dts/features/DataLibrary/selection/selection.d.ts.map +1 -1
  61. package/dist/dts/features/DataLibrary/selection/selection.js +2 -2
  62. package/dist/dts/features/DataLibrary/selection/selection.js.map +1 -1
  63. package/dist/dts/features/DataLibrary/selection/types.d.ts +4 -2
  64. package/dist/dts/features/DataLibrary/selection/types.d.ts.map +1 -1
  65. package/dist/dts/features/DataLibrary/selection/utils.js +3 -3
  66. package/dist/dts/features/DataLibrary/selection/utils.js.map +1 -1
  67. package/dist/dts/features/DataLibrary/tables/DatasetContentsTable.d.ts.map +1 -1
  68. package/dist/dts/features/DataLibrary/tables/DatasetContentsTable.js +2 -2
  69. package/dist/dts/features/DataLibrary/tables/DatasetContentsTable.js.map +1 -1
  70. package/dist/dts/features/DataLibrary/types.d.ts +1 -0
  71. package/dist/dts/features/DataLibrary/types.d.ts.map +1 -1
  72. package/dist/dts/features/DataLibrary/types.js.map +1 -1
  73. package/dist/dts/features/Discovery/ActionBar/ActionBar.d.ts +5 -4
  74. package/dist/dts/features/Discovery/ActionBar/ActionBar.d.ts.map +1 -1
  75. package/dist/dts/features/Discovery/ActionBar/ActionBar.js +16 -10
  76. package/dist/dts/features/Discovery/ActionBar/ActionBar.js.map +1 -1
  77. package/dist/dts/features/Discovery/ActionBar/AddToDataLibrary.d.ts +1 -1
  78. package/dist/dts/features/Discovery/ActionBar/AddToDataLibrary.d.ts.map +1 -1
  79. package/dist/dts/features/Discovery/ActionBar/AddToDataLibrary.js +86 -44
  80. package/dist/dts/features/Discovery/ActionBar/AddToDataLibrary.js.map +1 -1
  81. package/dist/dts/features/Discovery/ActionBar/AddToDataLibrary.stories.d.ts +1 -1
  82. package/dist/dts/features/Discovery/ActionBar/DataLibraryActionButton.d.ts +1 -1
  83. package/dist/dts/features/Discovery/ActionBar/DataLibraryActionButton.js +3 -3
  84. package/dist/dts/features/Discovery/ActionBar/DownloadAsZipButton.d.ts +2 -2
  85. package/dist/dts/features/Discovery/ActionBar/DownloadAsZipButton.d.ts.map +1 -1
  86. package/dist/dts/features/Discovery/ActionBar/DownloadAsZipButton.js +2 -2
  87. package/dist/dts/features/Discovery/ActionBar/DownloadAsZipButton.js.map +1 -1
  88. package/dist/dts/features/Discovery/ActionBar/DownloadManifestButton.d.ts +2 -2
  89. package/dist/dts/features/Discovery/ActionBar/DownloadManifestButton.d.ts.map +1 -1
  90. package/dist/dts/features/Discovery/ActionBar/DownloadManifestButton.js +58 -9
  91. package/dist/dts/features/Discovery/ActionBar/DownloadManifestButton.js.map +1 -1
  92. package/dist/dts/features/Discovery/ActionBar/types.d.ts +10 -2
  93. package/dist/dts/features/Discovery/ActionBar/types.d.ts.map +1 -1
  94. package/dist/dts/features/Discovery/DataLoaders/IndexedMetadata/DataLoader.d.ts.map +1 -1
  95. package/dist/dts/features/Discovery/DataLoaders/IndexedMetadata/DataLoader.js +3 -1
  96. package/dist/dts/features/Discovery/DataLoaders/IndexedMetadata/DataLoader.js.map +1 -1
  97. package/dist/dts/features/Discovery/DataLoaders/MDSAllLocal/DataLoader.d.ts.map +1 -1
  98. package/dist/dts/features/Discovery/DataLoaders/MDSAllLocal/DataLoader.js +6 -2
  99. package/dist/dts/features/Discovery/DataLoaders/MDSAllLocal/DataLoader.js.map +1 -1
  100. package/dist/dts/features/Discovery/DataLoaders/utils.d.ts +2 -2
  101. package/dist/dts/features/Discovery/DataLoaders/utils.d.ts.map +1 -1
  102. package/dist/dts/features/Discovery/DataLoaders/utils.js +87 -41
  103. package/dist/dts/features/Discovery/DataLoaders/utils.js.map +1 -1
  104. package/dist/dts/features/Discovery/DiscoveryIndexPanel.d.ts +13 -0
  105. package/dist/dts/features/Discovery/DiscoveryIndexPanel.d.ts.map +1 -1
  106. package/dist/dts/features/Discovery/DiscoveryIndexPanel.js +38 -14
  107. package/dist/dts/features/Discovery/DiscoveryIndexPanel.js.map +1 -1
  108. package/dist/dts/features/Discovery/DiscoveryTable.d.ts +2 -1
  109. package/dist/dts/features/Discovery/DiscoveryTable.d.ts.map +1 -1
  110. package/dist/dts/features/Discovery/DiscoveryTable.js +18 -6
  111. package/dist/dts/features/Discovery/DiscoveryTable.js.map +1 -1
  112. package/dist/dts/features/Discovery/StudyPage/DownloadLinksPanel.d.ts.map +1 -1
  113. package/dist/dts/features/Discovery/StudyPage/DownloadLinksPanel.js +2 -1
  114. package/dist/dts/features/Discovery/StudyPage/DownloadLinksPanel.js.map +1 -1
  115. package/dist/dts/features/Discovery/TableRenderers/CellRendererFactory.js +2 -2
  116. package/dist/dts/features/Discovery/TableRenderers/CellRendererFactory.js.map +1 -1
  117. package/dist/dts/features/Discovery/TableRenderers/CellRenderers.d.ts +2 -1
  118. package/dist/dts/features/Discovery/TableRenderers/CellRenderers.d.ts.map +1 -1
  119. package/dist/dts/features/Discovery/TableRenderers/CellRenderers.js +1 -1
  120. package/dist/dts/features/Discovery/TableRenderers/CellRenderers.js.map +1 -1
  121. package/dist/dts/features/Discovery/TableRenderers/DataAccessCellRenderers.d.ts +2 -1
  122. package/dist/dts/features/Discovery/TableRenderers/DataAccessCellRenderers.d.ts.map +1 -1
  123. package/dist/dts/features/Discovery/TableRenderers/DataAccessCellRenderers.js +30 -11
  124. package/dist/dts/features/Discovery/TableRenderers/DataAccessCellRenderers.js.map +1 -1
  125. package/dist/dts/features/Discovery/TableRenderers/types.d.ts +2 -1
  126. package/dist/dts/features/Discovery/TableRenderers/types.d.ts.map +1 -1
  127. package/dist/dts/features/Discovery/constants.d.ts +2 -0
  128. package/dist/dts/features/Discovery/constants.d.ts.map +1 -0
  129. package/dist/dts/features/Discovery/constants.js +2 -0
  130. package/dist/dts/features/Discovery/constants.js.map +1 -0
  131. package/dist/dts/features/Discovery/index.d.ts +2 -1
  132. package/dist/dts/features/Discovery/index.d.ts.map +1 -1
  133. package/dist/dts/features/Discovery/index.js +2 -1
  134. package/dist/dts/features/Discovery/index.js.map +1 -1
  135. package/dist/dts/features/Discovery/types.d.ts +12 -15
  136. package/dist/dts/features/Discovery/types.d.ts.map +1 -1
  137. package/dist/dts/features/Discovery/types.js +2 -1
  138. package/dist/dts/features/Discovery/types.js.map +1 -1
  139. package/dist/dts/features/Discovery/utils.d.ts +8 -2
  140. package/dist/dts/features/Discovery/utils.d.ts.map +1 -1
  141. package/dist/dts/features/Discovery/utils.js +37 -4
  142. package/dist/dts/features/Discovery/utils.js.map +1 -1
  143. package/dist/dts/features/Navigation/TopBar/TopBar.d.ts.map +1 -1
  144. package/dist/dts/features/Navigation/TopBar/TopBar.js +1 -1
  145. package/dist/dts/features/Navigation/TopBar/TopBar.js.map +1 -1
  146. package/dist/dts/features/Workspace/admin/WorkspaceEditorContext.js +1 -1
  147. package/dist/dts/features/Workspace/admin/WorkspaceEditorContext.js.map +1 -1
  148. package/dist/dts/lib/content/filesystem.js +1 -1
  149. package/dist/dts/lib/content/filesystem.js.map +1 -1
  150. package/dist/dts/lib/session/session.d.ts.map +1 -1
  151. package/dist/dts/lib/session/session.js +2 -1
  152. package/dist/dts/lib/session/session.js.map +1 -1
  153. package/dist/dts/pages/Explorer/data.d.ts.map +1 -1
  154. package/dist/dts/pages/Explorer/data.js +2 -2
  155. package/dist/dts/pages/Explorer/data.js.map +1 -1
  156. package/dist/dts/utils/authMapping.d.ts +2 -2
  157. package/dist/dts/utils/authMapping.d.ts.map +1 -1
  158. package/dist/dts/utils/authMapping.js.map +1 -1
  159. package/dist/esm/index.js +698 -179
  160. package/dist/esm/index.js.map +1 -1
  161. package/dist/index.d.ts +33 -16
  162. package/dist/tsconfig.tsbuildinfo +1 -1
  163. package/package.json +3 -3
  164. package/dist/dts/features/Authz/Provider.d.ts +0 -44
  165. package/dist/dts/features/Authz/Provider.d.ts.map +0 -1
  166. package/dist/dts/features/Authz/Provider.js +0 -55
  167. package/dist/dts/features/Authz/Provider.js.map +0 -1
  168. package/dist/dts/features/Discovery/utils/processDataAccess.d.ts +0 -3
  169. package/dist/dts/features/Discovery/utils/processDataAccess.d.ts.map +0 -1
  170. package/dist/dts/features/Discovery/utils/processDataAccess.js +0 -73
  171. package/dist/dts/features/Discovery/utils/processDataAccess.js.map +0 -1
package/dist/cjs/index.js CHANGED
@@ -682,7 +682,6 @@ const workspaceShutdownAlertLimit = 30000; // 5 minutes: 5 * 60 * 1000 TODO Figu
682
682
  const dispatch = core.useCoreDispatch();
683
683
  React.useEffect(()=>{
684
684
  if (isWorkspaceStatusError) {
685
- console.error('Workspace model error: ', workspaceStatusError.toString());
686
685
  dispatch(core.setActiveWorkspaceStatus(core.WorkspaceStatus.StatusError));
687
686
  setPollingInterval(0); // stop polling
688
687
  setPaymentPollingInterval(0);
@@ -885,6 +884,7 @@ const UPDATE_SESSION_LIMIT = MinutesToMilliseconds(5);
885
884
  */ const SessionProvider = ({ children, updateSessionTime = 5, inactiveTimeLimit = 20, workspaceInactivityTimeLimit = 0, logoutInactiveUsers = true, monitorWorkspace = true })=>{
886
885
  const router$1 = router.useRouter();
887
886
  const coreDispatch = core.useCoreDispatch();
887
+ core.useGetCSRFQuery();
888
888
  useWorkspaceResourceMonitor(monitorWorkspace); // monitor workspaces if any are running or configured
889
889
  const [getUserDetails] = core.useLazyFetchUserDetailsQuery(); // Fetch user details
890
890
  const userStatus = core.useCoreSelector((state)=>core.selectUserAuthStatus(state));
@@ -3747,6 +3747,23 @@ const NavPageLayout = ({ headerProps, footerProps, mainProps, headerData, childr
3747
3747
 
3748
3748
  var classes = {"tableRow":"DiscoveryTable-module_tableRow__yFUJZ"};
3749
3749
 
3750
+ const isSearchKV = (obj)=>{
3751
+ return obj && obj.key && obj.value;
3752
+ };
3753
+ const isSearchKVArray = (obj)=>{
3754
+ return obj && Array.isArray(obj) && obj.every(isSearchKV);
3755
+ };
3756
+ const accessibleFieldName = '__accessible';
3757
+ var AccessLevel = /*#__PURE__*/ function(AccessLevel) {
3758
+ AccessLevel[AccessLevel["ACCESSIBLE"] = 1] = "ACCESSIBLE";
3759
+ AccessLevel[AccessLevel["UNACCESSIBLE"] = 2] = "UNACCESSIBLE";
3760
+ AccessLevel[AccessLevel["WAITING"] = 3] = "WAITING";
3761
+ AccessLevel[AccessLevel["NOT_AVAILABLE"] = 4] = "NOT_AVAILABLE";
3762
+ AccessLevel[AccessLevel["OTHER"] = 5] = "OTHER";
3763
+ AccessLevel[AccessLevel["MIXED"] = 6] = "MIXED";
3764
+ return AccessLevel;
3765
+ }({});
3766
+
3750
3767
  const jsonPathAccessor$1 = (path)=>(row)=>{
3751
3768
  // TODO: add logging if path is not found
3752
3769
  return jsonpathPlus.JSONPath({
@@ -3755,7 +3772,14 @@ const jsonPathAccessor$1 = (path)=>(row)=>{
3755
3772
  });
3756
3773
  };
3757
3774
  const getTagInfo = (tagData, tagsConfig)=>{
3758
- const categoryConfig = tagsConfig.tagCategories.find((category)=>category.name === tagData.category);
3775
+ if (tagData.category === undefined) {
3776
+ return {
3777
+ color: 'darkgray',
3778
+ display: tagsConfig?.showUnknownTags ?? false,
3779
+ label: tagData.name
3780
+ };
3781
+ }
3782
+ const categoryConfig = tagsConfig?.tagCategories.find((category)=>category.name === tagData.category);
3759
3783
  if (categoryConfig === undefined) return {
3760
3784
  color: 'gray',
3761
3785
  display: tagsConfig?.showUnknownTags ?? false,
@@ -3772,6 +3796,29 @@ const getManualSortingAndPagination = (config)=>{
3772
3796
  const sortingAndPagination = config?.features?.dataLoader?.sortingAndPagination ?? defaultFeature;
3773
3797
  return sortingAndPagination === 'server';
3774
3798
  };
3799
+ /**
3800
+ * Converts a numeric value to its equivalent AccessLevel enum value
3801
+ * @param value - The numeric value to convert (1-6)
3802
+ * @returns The corresponding AccessLevel enum value or undefined if not found
3803
+ */ const getAccessLevelFromNumber = (value)=>{
3804
+ if (value === undefined) return undefined;
3805
+ switch(value){
3806
+ case AccessLevel.ACCESSIBLE:
3807
+ return AccessLevel.ACCESSIBLE;
3808
+ case AccessLevel.UNACCESSIBLE:
3809
+ return AccessLevel.UNACCESSIBLE;
3810
+ case AccessLevel.WAITING:
3811
+ return AccessLevel.WAITING;
3812
+ case AccessLevel.NOT_AVAILABLE:
3813
+ return AccessLevel.NOT_AVAILABLE;
3814
+ case AccessLevel.OTHER:
3815
+ return AccessLevel.OTHER;
3816
+ case AccessLevel.MIXED:
3817
+ return AccessLevel.MIXED;
3818
+ default:
3819
+ return undefined;
3820
+ }
3821
+ };
3775
3822
 
3776
3823
  const defaultCellRenderer = (value, params)=>{
3777
3824
  if (value === undefined || value === null || lodash.toString(value) === '') {
@@ -3782,11 +3829,8 @@ const defaultCellRenderer = (value, params)=>{
3782
3829
  ]
3783
3830
  });
3784
3831
  }
3785
- return /*#__PURE__*/ jsxRuntime.jsxs(core$1.Text, {
3786
- children: [
3787
- lodash.toString(value),
3788
- "dfdsfdsf"
3789
- ]
3832
+ return /*#__PURE__*/ jsxRuntime.jsx(core$1.Text, {
3833
+ children: lodash.toString(value)
3790
3834
  });
3791
3835
  };
3792
3836
  class DiscoveryCellRendererFactory {
@@ -3931,45 +3975,94 @@ const DiscoveryProvider = ({ children, discoveryIndexConfig })=>{
3931
3975
  });
3932
3976
  };
3933
3977
 
3934
- const isSearchKV = (obj)=>{
3935
- return obj && obj.key && obj.value;
3936
- };
3937
- const isSearchKVArray = (obj)=>{
3938
- return obj && Array.isArray(obj) && obj.every(isSearchKV);
3978
+ const buildTooltip = (mainMessage, secondaryMessage)=>{
3979
+ return /*#__PURE__*/ jsxRuntime.jsxs("div", {
3980
+ className: "flex flex-col",
3981
+ children: [
3982
+ /*#__PURE__*/ jsxRuntime.jsxs(core$1.Text, {
3983
+ size: "sm",
3984
+ children: [
3985
+ " ",
3986
+ mainMessage,
3987
+ " "
3988
+ ]
3989
+ }),
3990
+ secondaryMessage ? /*#__PURE__*/ jsxRuntime.jsxs("div", {
3991
+ className: "flex flex-col items-start my-1",
3992
+ children: [
3993
+ /*#__PURE__*/ jsxRuntime.jsx(core$1.Divider, {}),
3994
+ /*#__PURE__*/ jsxRuntime.jsx(core$1.Text, {
3995
+ size: "xs",
3996
+ children: secondaryMessage
3997
+ })
3998
+ ]
3999
+ }) : null
4000
+ ]
4001
+ });
3939
4002
  };
3940
- const accessibleFieldName = '__accessible';
3941
- var AccessLevel = /*#__PURE__*/ function(AccessLevel) {
3942
- AccessLevel[AccessLevel["ACCESSIBLE"] = 1] = "ACCESSIBLE";
3943
- AccessLevel[AccessLevel["UNACCESSIBLE"] = 2] = "UNACCESSIBLE";
3944
- AccessLevel[AccessLevel["PENDING"] = 3] = "PENDING";
3945
- AccessLevel[AccessLevel["NOT_AVAILABLE"] = 4] = "NOT_AVAILABLE";
3946
- AccessLevel[AccessLevel["OTHER"] = 5] = "OTHER";
3947
- return AccessLevel;
3948
- }({});
3949
-
3950
- const DataAccessCellRenderer = ({ value })=>{
3951
- if (value === AccessLevel.PENDING) {
3952
- return /*#__PURE__*/ jsxRuntime.jsx(lu.LuClock, {
3953
- color: "yellow",
3954
- children: "Your access to this study is pending."
4003
+ const DataAccessCellRenderer = ({ cell, row }, params)=>{
4004
+ const authzField = params?.authzField || 'authz';
4005
+ let value = cell?.getValue();
4006
+ const authorization = row?.original?.[authzField] || undefined;
4007
+ if (lodash.isArray(value)) value = value[0];
4008
+ const accessLevel = getAccessLevelFromNumber(value);
4009
+ if (!accessLevel) {
4010
+ return /*#__PURE__*/ jsxRuntime.jsx(core$1.Tooltip, {
4011
+ label: buildTooltip('Unable to determine access level'),
4012
+ children: /*#__PURE__*/ jsxRuntime.jsx(lu.LuCircleSlash, {
4013
+ className: "text-utility-error"
4014
+ })
3955
4015
  });
3956
4016
  }
3957
- if (value === AccessLevel.NOT_AVAILABLE) {
3958
- return /*#__PURE__*/ jsxRuntime.jsx(lu.LuCircleSlash, {
3959
- color: "red",
3960
- children: "Cannot determine access to this study. Please contact the study owner."
4017
+ if (accessLevel === AccessLevel.WAITING) {
4018
+ return /*#__PURE__*/ jsxRuntime.jsx(core$1.Tooltip, {
4019
+ label: buildTooltip('Data are not yet available'),
4020
+ children: /*#__PURE__*/ jsxRuntime.jsx(lu.LuClock, {
4021
+ className: "text-utility-warning"
4022
+ })
3961
4023
  });
3962
4024
  }
3963
- if (value === AccessLevel.ACCESSIBLE) {
3964
- return /*#__PURE__*/ jsxRuntime.jsx(lu.LuUnlock, {
3965
- color: "green",
3966
- children: "You have access to this study."
4025
+ if (accessLevel === AccessLevel.MIXED) {
4026
+ return /*#__PURE__*/ jsxRuntime.jsx(core$1.Tooltip, {
4027
+ label: buildTooltip('You have mixed acccess'),
4028
+ children: /*#__PURE__*/ jsxRuntime.jsxs(core$1.Group, {
4029
+ children: [
4030
+ /*#__PURE__*/ jsxRuntime.jsx(lu.LuLock, {
4031
+ className: "text-utility-warning"
4032
+ }),
4033
+ /*#__PURE__*/ jsxRuntime.jsx(lu.LuUnlock, {
4034
+ className: "text-utility-warning"
4035
+ })
4036
+ ]
4037
+ })
3967
4038
  });
3968
4039
  }
3969
- if (value === AccessLevel.UNACCESSIBLE) {
3970
- return /*#__PURE__*/ jsxRuntime.jsx(lu.LuLock, {
3971
- color: "red",
3972
- children: "You do not have access to this study."
4040
+ if (accessLevel === AccessLevel.NOT_AVAILABLE) {
4041
+ return /*#__PURE__*/ jsxRuntime.jsx(core$1.Tooltip, {
4042
+ label: buildTooltip('No data is shared'),
4043
+ children: /*#__PURE__*/ jsxRuntime.jsx(lu.LuCircleSlash, {
4044
+ className: "text-utility-error"
4045
+ })
4046
+ });
4047
+ }
4048
+ if (accessLevel === AccessLevel.ACCESSIBLE) {
4049
+ return /*#__PURE__*/ jsxRuntime.jsx(core$1.Tooltip, {
4050
+ label: buildTooltip('You have access to this study', `read access to ${authorization}`),
4051
+ children: /*#__PURE__*/ jsxRuntime.jsx("div", {
4052
+ children: /*#__PURE__*/ jsxRuntime.jsx(lu.LuUnlock, {
4053
+ className: "text-utility-success"
4054
+ })
4055
+ })
4056
+ });
4057
+ }
4058
+ if (accessLevel === AccessLevel.UNACCESSIBLE) {
4059
+ return /*#__PURE__*/ jsxRuntime.jsx(core$1.Tooltip, {
4060
+ label: buildTooltip('You currently do not have access to this study', `you need read access to ${authorization}`),
4061
+ children: /*#__PURE__*/ jsxRuntime.jsx("div", {
4062
+ children: /*#__PURE__*/ jsxRuntime.jsx(lu.LuLock, {
4063
+ className: "text-utility-error"
4064
+ })
4065
+ })
3973
4066
  });
3974
4067
  }
3975
4068
  return /*#__PURE__*/ jsxRuntime.jsx(React.Fragment, {});
@@ -4147,13 +4240,10 @@ const RenderLinkWithURL = ({ value, cell }, params)=>{
4147
4240
  onClick: (ev)=>ev.stopPropagation(),
4148
4241
  target: "_blank",
4149
4242
  rel: "noreferrer",
4150
- children: /*#__PURE__*/ jsxRuntime.jsxs(core$1.Text, {
4243
+ children: /*#__PURE__*/ jsxRuntime.jsx(core$1.Text, {
4151
4244
  c: "utility.0",
4152
4245
  tt: ttValue,
4153
- children: [
4154
- content,
4155
- " fgh"
4156
- ]
4246
+ children: content
4157
4247
  })
4158
4248
  });
4159
4249
  };
@@ -4827,14 +4917,20 @@ const DownloadLinksPanel = ({ studyData, downloadLinks, downloadLinkFields = {
4827
4917
  }
4828
4918
  const id = entry[downloadLinkFields.idField];
4829
4919
  return /*#__PURE__*/ jsxRuntime.jsxs(core$1.Group, {
4920
+ justify: "space-between",
4830
4921
  gap: "md",
4831
4922
  children: [
4832
4923
  /*#__PURE__*/ jsxRuntime.jsx(core$1.Text, {
4833
4924
  children: entry['titleField'] || ''
4834
4925
  }),
4835
4926
  /*#__PURE__*/ jsxRuntime.jsx(core$1.Button, {
4927
+ component: "a",
4928
+ href: `${core.GEN3_FENCE_API}/data/${id}?expires_in=900&redirect`,
4929
+ target: "_blank",
4930
+ rel: "noreferrer",
4931
+ type: "text",
4836
4932
  leftSection: /*#__PURE__*/ jsxRuntime.jsx(fi.FiDownload, {}),
4837
- disabled: !id,
4933
+ "data-disabled": !id,
4838
4934
  children: "Download File"
4839
4935
  })
4840
4936
  ]
@@ -5013,14 +5109,16 @@ const TableIcons = {
5013
5109
  })
5014
5110
  };
5015
5111
 
5016
- const extractCellValue = (func)=>({ cell })=>func({
5112
+ const extractCellValue = (func)=>({ cell, row })=>func({
5017
5113
  value: cell.getValue(),
5018
- cell
5114
+ cell,
5115
+ row
5019
5116
  });
5020
- const DiscoveryTable = ({ data, hits, dataRequestStatus, setSorting, setPagination, pagination, sorting })=>{
5117
+ const DiscoveryTable = ({ data, hits, dataRequestStatus, setSorting, setPagination, setSelection, pagination, sorting })=>{
5021
5118
  const { discoveryConfig: config, setStudyDetails } = useDiscoveryContext();
5022
5119
  const { isLoading, isError, isFetching } = dataRequestStatus;
5023
5120
  const manualSortingAndPagination = getManualSortingAndPagination(config);
5121
+ const [rowSelection, setRowSelection] = React.useState({}); //ts type available
5024
5122
  const cols = useDeepCompare.useDeepCompareMemo(()=>{
5025
5123
  const studyColumns = config.studyColumns ?? [];
5026
5124
  return studyColumns.map((columnDef, idx)=>{
@@ -5060,6 +5158,7 @@ const DiscoveryTable = ({ data, hits, dataRequestStatus, setSorting, setPaginati
5060
5158
  enableColumnActions: false,
5061
5159
  enableStickyHeader: true,
5062
5160
  enableStickyFooter: true,
5161
+ getRowId: (originalRow)=>config?.minimalFieldMapping?.uid && config.minimalFieldMapping.uid in originalRow ? originalRow[config.minimalFieldMapping.uid] : originalRow?.id ?? undefined,
5063
5162
  // TODO: keep this to explore later
5064
5163
  // mantineTableContainerProps: ({ table }) => {
5065
5164
  // return {
@@ -5069,7 +5168,9 @@ const DiscoveryTable = ({ data, hits, dataRequestStatus, setSorting, setPaginati
5069
5168
  // };
5070
5169
  // },
5071
5170
  renderDetailPanel: config.studyPreviewField ? DiscoveryTableRowRenderer(config.studyPreviewField) : undefined,
5171
+ onRowSelectionChange: setRowSelection,
5072
5172
  state: {
5173
+ rowSelection,
5073
5174
  isLoading,
5074
5175
  ...manualSortingAndPagination ? {
5075
5176
  pagination,
@@ -5116,6 +5217,13 @@ const DiscoveryTable = ({ data, hits, dataRequestStatus, setSorting, setPaginati
5116
5217
  }
5117
5218
  }
5118
5219
  });
5220
+ useDeepCompare.useDeepCompareEffect(()=>{
5221
+ //fetch data based on row selection state or something
5222
+ setSelection(rowSelection ? Object.keys(rowSelection) : []);
5223
+ }, [
5224
+ rowSelection,
5225
+ setSelection
5226
+ ]);
5119
5227
  return /*#__PURE__*/ jsxRuntime.jsxs(React.Fragment, {
5120
5228
  children: [
5121
5229
  /*#__PURE__*/ jsxRuntime.jsx(StudyDetails, {}),
@@ -5411,10 +5519,10 @@ const AdvancedSearchPanel = (props)=>{
5411
5519
  });
5412
5520
  };
5413
5521
 
5414
- const DataLibraryActionButton = /*#__PURE__*/ React.forwardRef(({ label = undefined, icon = undefined, disabled = false, toolTip = undefined, onClick = ()=>null, active = false, showIcon = true, loginRequired = false, ...buttonProps }, ref)=>{
5522
+ const DataLibraryActionButton = /*#__PURE__*/ React.forwardRef(({ label = undefined, icon = undefined, disabled = false, tooltip = undefined, onClick = ()=>null, active = false, showIcon = true, loginRequired = false, ...buttonProps }, ref)=>{
5415
5523
  // TODO Test what idp was used to login and restrict actions to that idp or all or none
5416
5524
  const requiresLogin = !core.useIsUserLoggedIn() && loginRequired;
5417
- const buttonUcon = active ? /*#__PURE__*/ jsxRuntime.jsx(core$1.Loader, {
5525
+ const buttonIcon = active ? /*#__PURE__*/ jsxRuntime.jsx(core$1.Loader, {
5418
5526
  size: "sm",
5419
5527
  className: "p-1"
5420
5528
  }) : /*#__PURE__*/ jsxRuntime.jsx(fi.FiDownload, {
@@ -5422,13 +5530,13 @@ const DataLibraryActionButton = /*#__PURE__*/ React.forwardRef(({ label = undefi
5422
5530
  size: 16
5423
5531
  });
5424
5532
  return /*#__PURE__*/ jsxRuntime.jsx(core$1.Tooltip, {
5425
- disabled: !toolTip,
5426
- label: toolTip,
5533
+ disabled: !tooltip,
5534
+ label: tooltip,
5427
5535
  children: /*#__PURE__*/ jsxRuntime.jsx(core$1.Button, {
5428
5536
  ref: ref,
5429
5537
  onClick: onClick,
5430
5538
  disabled: disabled || requiresLogin,
5431
- leftSection: showIcon ? buttonUcon : undefined,
5539
+ leftSection: showIcon ? buttonIcon : undefined,
5432
5540
  ...buttonProps,
5433
5541
  children: label
5434
5542
  })
@@ -5436,21 +5544,297 @@ const DataLibraryActionButton = /*#__PURE__*/ React.forwardRef(({ label = undefi
5436
5544
  });
5437
5545
  DataLibraryActionButton.displayName = 'DataLibraryActionButton';
5438
5546
 
5439
- const ActionBar = ({ config })=>{
5440
- const { buttons } = config;
5547
+ const MANIFEST_FILENAME = 'manifest.json';
5548
+ /**
5549
+ * Determines the disabled state and the reason for disabling based on authentication status,
5550
+ * selection count, and requirement for login.
5551
+ *
5552
+ * @param {boolean} isAuthenticated - Indicates whether the user is authenticated.
5553
+ * @param {number} numSelected - The number of items selected for the operation.
5554
+ * @param {boolean} requiresLogin - Specifies whether login is required to perform the operation.
5555
+ * @returns {Object} An object containing the following properties:
5556
+ * - {boolean} disabled - True if the action should be disabled, false otherwise.
5557
+ * - {string} [disabledReason] - The reason why the action is disabled (if applicable).
5558
+ */ const getDisabledState = (isAuthenticated, numSelected, requiresLogin)=>{
5559
+ const LOGIN_REQUIRED_MSG = 'You must be logged in to download a manifest';
5560
+ const NO_SELECTION_MSG = 'You must select at least one study to download a manifest';
5561
+ if (requiresLogin && !isAuthenticated) {
5562
+ return {
5563
+ disabled: true,
5564
+ disabledReason: LOGIN_REQUIRED_MSG
5565
+ };
5566
+ }
5567
+ if (numSelected === 0) {
5568
+ return {
5569
+ disabled: true,
5570
+ disabledReason: NO_SELECTION_MSG
5571
+ };
5572
+ }
5573
+ return {
5574
+ disabled: false
5575
+ }; // Default enabled state.
5576
+ };
5577
+ const handleDownloadManifestClick = ({ exportDataFields, selectedResources })=>{
5578
+ const { dataObjectField } = exportDataFields;
5579
+ if (dataObjectField === undefined) {
5580
+ notifications.notifications.show({
5581
+ title: 'Error notification',
5582
+ message: 'Missing required configuration field `config.features.export.manifestFieldName'
5583
+ });
5584
+ return;
5585
+ }
5586
+ // combine manifests from all selected studies
5587
+ const manifest = [];
5588
+ selectedResources.forEach((study)=>{
5589
+ if (study[dataObjectField]) {
5590
+ const studyDataObject = study[dataObjectField];
5591
+ if ('commons_url' in study && !core.GEN3_DOMAIN?.includes(study.commons_url)) {
5592
+ // PlanX addition to allow hostname based DRS in manifest download clients
5593
+ // like FUSE
5594
+ manifest.push(...studyDataObject.map((x)=>({
5595
+ ...x,
5596
+ commons_url: 'commons_url' in x ? x.commons_url : study.commons_url
5597
+ })));
5598
+ } else {
5599
+ manifest.push(...studyDataObject);
5600
+ }
5601
+ }
5602
+ });
5603
+ // download the manifest
5604
+ if (manifest.length === 0) {
5605
+ notifications.notifications.show({
5606
+ title: 'Export warning',
5607
+ message: 'None of the selected studies have any data objects. Please select a different study or select a different data object field.'
5608
+ });
5609
+ return;
5610
+ }
5611
+ const blob = new Blob([
5612
+ JSON.stringify(manifest, null, 2)
5613
+ ], {
5614
+ type: 'text/json'
5615
+ });
5616
+ FileSaver.saveAs(blob, MANIFEST_FILENAME);
5617
+ };
5618
+ const DownloadManifestButton = ({ buttonConfig, selectedResources, exportDataFields })=>{
5619
+ const { isAuthenticated } = useIsAuthenticated();
5620
+ const { disabled, disabledReason } = getDisabledState(isAuthenticated, selectedResources.length, buttonConfig?.requiresLogin ?? false);
5621
+ return /*#__PURE__*/ jsxRuntime.jsx(DataLibraryActionButton, {
5622
+ "data-testid": "download-manifest-button",
5623
+ label: buttonConfig?.label ?? 'Download Manifest',
5624
+ icon: /*#__PURE__*/ jsxRuntime.jsx(fi.FiDownload, {}),
5625
+ disabled: disabled,
5626
+ tooltip: disabledReason ?? buttonConfig?.tooltip ?? 'Download Manifest of selected studies',
5627
+ onClick: ()=>{
5628
+ handleDownloadManifestClick({
5629
+ selectedResources: selectedResources,
5630
+ exportDataFields: exportDataFields
5631
+ });
5632
+ }
5633
+ });
5634
+ };
5635
+
5636
+ const extractIdToLabel = (data)=>!data ? {} : Object.keys(data).reduce((acc, id)=>{
5637
+ acc[id] = data[id].name;
5638
+ return acc;
5639
+ }, {});
5640
+ const createTooltipLabel = (error, isLoggedIn, requiresLogin, numSelected, currentListName)=>{
5641
+ if (error) return 'Error saving to data library. Please try again later';
5642
+ if (!isLoggedIn && requiresLogin) return 'Please log in to save to data library';
5643
+ if (numSelected === 0) return 'Please select at least one study to save to data library';
5644
+ if (!currentListName) return 'Please select or create a list';
5645
+ return 'Add selections to list';
5646
+ };
5647
+ const AddToDataLibrary = ({ buttonConfig, selectedResources, exportDataFields, classNames = {} })=>{
5648
+ const [selectItems, setSelectItems] = React.useState({});
5649
+ const [currentList, setCurrentList] = React.useState(null);
5650
+ const [error, setError] = React.useState(null);
5651
+ const [currentListName, setCurrentListName] = React.useState('');
5652
+ const combobox = core$1.useCombobox({
5653
+ onDropdownClose: ()=>combobox.resetSelectedOption()
5654
+ });
5655
+ const userStatus = core.useCoreSelector((state)=>core.selectUserAuthStatus(state));
5656
+ const isLoggedIn = core.isAuthenticated(userStatus);
5657
+ const isDisabled = error !== null || selectedResources.length === 0 || !currentListName || buttonConfig?.requiresLogin && !isLoggedIn;
5658
+ const tooltipLabel = createTooltipLabel(error, isLoggedIn, buttonConfig.requiresLogin, selectedResources.length, currentListName);
5659
+ const classNamesDefaults = {
5660
+ root: 'w-1/2'
5661
+ };
5662
+ const mergedClassnames = mergeDefaultTailwindClassnames(classNamesDefaults, classNames);
5663
+ const { dataLibrary, updateListInDataLibrary, addListToDataLibrary, isLoading, error: dataLibraryError } = core.useDataLibrary();
5664
+ const saveToList = (listname, listId = undefined)=>{
5665
+ if (selectedResources.length === 0) return;
5666
+ const items = core.buildListItemsGroupedByDataset(core.extractFileDatasetsInRecords(selectedResources, exportDataFields));
5667
+ if (listId) {
5668
+ if (Object.keys(items).length === 0) {
5669
+ notifications.notifications.show({
5670
+ id: 'update-datalibrary-no-items-to-update-notification',
5671
+ position: 'top-center',
5672
+ withCloseButton: true,
5673
+ autoClose: 5000,
5674
+ title: 'Save to list',
5675
+ message: `No data objects selected to save to list ${listname}.`,
5676
+ loading: false
5677
+ });
5678
+ return;
5679
+ }
5680
+ updateListInDataLibrary({
5681
+ id: listId,
5682
+ name: listname,
5683
+ items: {
5684
+ ...dataLibrary[listId].items,
5685
+ ...items
5686
+ }
5687
+ });
5688
+ notifications.notifications.show({
5689
+ id: 'update-datalibrary-list-notification',
5690
+ position: 'top-center',
5691
+ withCloseButton: true,
5692
+ autoClose: 5000,
5693
+ title: 'Save to list',
5694
+ message: `${Object.values(items)} saved to list ${listname} successfully.`,
5695
+ loading: isLoading
5696
+ });
5697
+ } else {
5698
+ addListToDataLibrary(items, listname);
5699
+ notifications.notifications.show({
5700
+ id: 'update-datalibrary-list-notification',
5701
+ position: 'top-center',
5702
+ withCloseButton: true,
5703
+ autoClose: 5000,
5704
+ title: 'Save to list',
5705
+ message: `${Object.values(items)} saved to list ${listname} successfully.`,
5706
+ loading: isLoading
5707
+ });
5708
+ }
5709
+ };
5710
+ const exactOptionMatch = Object.values(selectItems).some((listName)=>listName === currentListName);
5711
+ const filteredOptions = exactOptionMatch ? selectItems : Object.entries(selectItems).reduce((acc, [listId, listName])=>{
5712
+ if (listName.toLowerCase().includes(currentListName.toLowerCase().trim())) {
5713
+ acc[listId] = listName;
5714
+ }
5715
+ return acc;
5716
+ }, {});
5717
+ const options = React.useMemo(()=>Object.entries(filteredOptions).map(([listId, listName])=>/*#__PURE__*/ jsxRuntime.jsx(core$1.Combobox.Option, {
5718
+ value: listId,
5719
+ children: listName
5720
+ }, listId)), [
5721
+ filteredOptions
5722
+ ]);
5723
+ React.useEffect(()=>{
5724
+ if (options.length === 0) setCurrentList(null);
5725
+ }, [
5726
+ options
5727
+ ]);
5728
+ useDeepCompare.useDeepCompareEffect(()=>{
5729
+ if (dataLibrary && !dataLibraryError) {
5730
+ const listItems = extractIdToLabel(dataLibrary);
5731
+ setSelectItems(listItems);
5732
+ }
5733
+ setError(dataLibraryError);
5734
+ if (dataLibraryError) {
5735
+ notifications.notifications.show({
5736
+ id: 'update-datalibrary-error-notification',
5737
+ position: 'top-center',
5738
+ withCloseButton: true,
5739
+ autoClose: 5000,
5740
+ title: 'Error',
5741
+ message: `Error saving to data library. Please try again later.`,
5742
+ loading: false
5743
+ });
5744
+ }
5745
+ }, [
5746
+ dataLibrary,
5747
+ dataLibraryError
5748
+ ]);
5749
+ return /*#__PURE__*/ jsxRuntime.jsxs(core$1.Group, {
5750
+ "data-testid": "add-to-data-library",
5751
+ wrap: "nowrap",
5752
+ classNames: {
5753
+ root: mergedClassnames.root
5754
+ },
5755
+ children: [
5756
+ /*#__PURE__*/ jsxRuntime.jsxs(core$1.Combobox, {
5757
+ onOptionSubmit: (selectedValue)=>{
5758
+ setCurrentList(selectedValue);
5759
+ setCurrentListName(selectItems[selectedValue]);
5760
+ combobox.closeDropdown();
5761
+ },
5762
+ store: combobox,
5763
+ withinPortal: false,
5764
+ children: [
5765
+ /*#__PURE__*/ jsxRuntime.jsx(core$1.Combobox.Target, {
5766
+ children: /*#__PURE__*/ jsxRuntime.jsx(core$1.TextInput, {
5767
+ placeholder: "Select/Search/Create List",
5768
+ value: currentListName ?? '',
5769
+ className: 'w-full',
5770
+ onChange: (event)=>{
5771
+ setCurrentListName(event.currentTarget.value);
5772
+ combobox.openDropdown();
5773
+ combobox.updateSelectedOptionIndex();
5774
+ },
5775
+ onClick: ()=>combobox.openDropdown(),
5776
+ onFocus: ()=>combobox.openDropdown(),
5777
+ onBlur: ()=>combobox.closeDropdown()
5778
+ })
5779
+ }),
5780
+ /*#__PURE__*/ jsxRuntime.jsx(core$1.Combobox.Dropdown, {
5781
+ children: /*#__PURE__*/ jsxRuntime.jsx(core$1.Combobox.Options, {
5782
+ children: /*#__PURE__*/ jsxRuntime.jsx(core$1.ScrollArea.Autosize, {
5783
+ mah: 200,
5784
+ type: "scroll",
5785
+ children: options.length === 0 ? /*#__PURE__*/ jsxRuntime.jsx(core$1.Combobox.Empty, {
5786
+ children: "Click button to create new list"
5787
+ }) : options
5788
+ })
5789
+ })
5790
+ })
5791
+ ]
5792
+ }),
5793
+ /*#__PURE__*/ jsxRuntime.jsx(core$1.Tooltip, {
5794
+ label: tooltipLabel,
5795
+ children: /*#__PURE__*/ jsxRuntime.jsx(core$1.Button, {
5796
+ classNames: {
5797
+ root: 'w-1/3'
5798
+ },
5799
+ loading: isLoading,
5800
+ disabled: isDisabled,
5801
+ onClick: ()=>{
5802
+ if (currentList) {
5803
+ saveToList(selectItems[currentList], currentList);
5804
+ } else {
5805
+ saveToList(currentListName, undefined);
5806
+ }
5807
+ },
5808
+ children: options.length === 0 && currentListName.length > 0 ? 'Save to New List' : buttonConfig?.label ?? 'Save to List'
5809
+ })
5810
+ })
5811
+ ]
5812
+ });
5813
+ };
5814
+
5815
+ const createActionButton = ({ buttonConfig, selectedResources, exportDataFields })=>{
5816
+ return ({
5817
+ manifest: /*#__PURE__*/ jsxRuntime.jsx(DownloadManifestButton, {
5818
+ buttonConfig: buttonConfig,
5819
+ selectedResources: selectedResources,
5820
+ exportDataFields: exportDataFields
5821
+ }, buttonConfig.type),
5822
+ addToDataLibrary: /*#__PURE__*/ jsxRuntime.jsx(AddToDataLibrary, {
5823
+ buttonConfig: buttonConfig,
5824
+ selectedResources: selectedResources,
5825
+ exportDataFields: exportDataFields
5826
+ }, buttonConfig.type)
5827
+ })[buttonConfig.type];
5828
+ };
5829
+ const ActionBar = ({ buttons, selectedResources, exportDataFields, verifyExternalLogins })=>{
5441
5830
  return /*#__PURE__*/ jsxRuntime.jsx("div", {
5442
5831
  className: "flex items-center justify-end py-1 px-2 mb-1 w-full gap-x-1.5 ",
5443
- children: buttons?.map((button, index)=>{
5444
- return /*#__PURE__*/ jsxRuntime.jsx(DataLibraryActionButton, {
5445
- label: button.label,
5446
- icon: /*#__PURE__*/ jsxRuntime.jsx(fi.FiDownload, {}),
5447
- toolTip: button.tooltip,
5448
- loginRequired: config?.loginRequireForAllButtons ?? true,
5449
- onClick: ()=>{
5450
- console.log('Download $[button.label]');
5451
- }
5452
- }, `action-button-${index}`);
5453
- // }
5832
+ children: buttons?.map((button)=>{
5833
+ return createActionButton({
5834
+ buttonConfig: button,
5835
+ selectedResources,
5836
+ exportDataFields
5837
+ });
5454
5838
  })
5455
5839
  });
5456
5840
  };
@@ -5704,26 +6088,41 @@ const userHasMethodForServiceOnResource = (method, service, resourcePath, userAu
5704
6088
  return actions !== undefined && actions.some((x)=>(x.service === service || x.service === '*') && (x.method === method || x.method === '*'));
5705
6089
  };
5706
6090
 
6091
+ const METADATA_ITEM_AUTHORIZATION_FIELD = '__accessible';
6092
+
5707
6093
  /**
5708
- * Check for non-numeric items in an array and convert them to numbers.
5709
- * Handles strings, numbers, and nested arrays.
5710
- * It will silently convert any non-numeric items to 0 so as not to break the sum.
5711
- * @param fields - array of fields to check
5712
- */ const checkForNonNumericItems = (fields)=>fields.map((item)=>{
5713
- if (typeof item === 'number') {
5714
- return item;
5715
- }
5716
- // parse any string representation of an integer
5717
- if (typeof item === 'string') {
5718
- return parseInt(item, 10) || 0;
5719
- }
5720
- // if it's an array, recurse and sum the result
5721
- if (Array.isArray(item)) {
5722
- return sum(checkForNonNumericItems(item));
5723
- }
5724
- // if it's not a number, return 0 so as not to break the sum
5725
- return 0;
5726
- });
6094
+ * Parses a single value into a number
6095
+ * @param item - Value to convert
6096
+ * @returns Numeric representation of the value
6097
+ */ const parseNumericValue = (item)=>{
6098
+ const DEFAULT_VALUE = 0;
6099
+ // Handle undefined values
6100
+ if (item === undefined) {
6101
+ return DEFAULT_VALUE;
6102
+ }
6103
+ // Numbers can be used directly
6104
+ if (typeof item === 'number' && !Number.isNaN(item)) {
6105
+ return item;
6106
+ }
6107
+ // Parse string representations of numbers
6108
+ if (typeof item === 'string') {
6109
+ const parsedValue = parseInt(item, 10);
6110
+ return Number.isNaN(parsedValue) ? DEFAULT_VALUE : parsedValue;
6111
+ }
6112
+ // Recursively handle arrays by summing their numeric values
6113
+ if (Array.isArray(item)) {
6114
+ return convertToNumbers(item).reduce((acc, val)=>acc + val, 0);
6115
+ }
6116
+ // Return default for any other types
6117
+ return DEFAULT_VALUE;
6118
+ };
6119
+ /**
6120
+ * Converts various types of values to numbers
6121
+ * @param fields - Array of values to convert
6122
+ * @returns Array of numbers, with non-numeric values converted to 0
6123
+ */ const convertToNumbers = (fields)=>{
6124
+ return fields.map(parseNumericValue);
6125
+ };
5727
6126
  /**
5728
6127
  * Process a summary statistic using the provided data and summary config
5729
6128
  * @param {JSONObject }data
@@ -5740,7 +6139,7 @@ const userHasMethodForServiceOnResource = (method, service, resourcePath, userAu
5740
6139
  case 'sum':
5741
6140
  {
5742
6141
  // parse any string representation of an integer
5743
- fields = checkForNonNumericItems(fields);
6142
+ fields = convertToNumbers(fields);
5744
6143
  return sum(fields).toLocaleString();
5745
6144
  }
5746
6145
  case 'count':
@@ -5766,21 +6165,45 @@ const processAllSummaries = (data, summaries)=>{
5766
6165
  ];
5767
6166
  }, []);
5768
6167
  };
5769
- const processAuthorizations = (data, config, authMapping)=>{
6168
+ const processAuthorizations = (data, config, userAuthMapping)=>{
6169
+ const { enabled } = config.features.authorization;
6170
+ if (!enabled) {
6171
+ return data;
6172
+ }
6173
+ if (!userAuthMapping) {
6174
+ throw new Error('Arborist must be enabled for the Discovery page to work if authorization is enabled in the Discovery page. Set `useArboristUI: true` in the portal config.');
6175
+ }
6176
+ const hostnameWithSubdomain = window.location.hostname; // TODO: replace this with useRouter
6177
+ // mark studies as accessible or inaccessible to user
5770
6178
  const { authzField, dataAvailabilityField } = config.minimalFieldMapping;
5771
- const { supportedValues } = config.features.authorization;
5772
- return data.map((study)=>{
5773
- if (typeof study[authzField] !== 'string') return study;
5774
- const studyAuthz = study[authzField];
5775
- let accessible;
5776
- if (supportedValues?.pending?.enabled && dataAvailabilityField && study[dataAvailabilityField] === 'pending') {
5777
- accessible = AccessLevel.PENDING;
5778
- } else if (supportedValues?.notAvailable?.enabled && !study[authzField]) {
6179
+ const { supportedValues, isMesh } = config.features.authorization;
6180
+ const studiesWithAccessibleField = data.map((study)=>{
6181
+ let accessible = AccessLevel.NOT_AVAILABLE;
6182
+ if (supportedValues?.unaccessible?.enabled && dataAvailabilityField && study[dataAvailabilityField] === 'unaccessible') {
6183
+ accessible = AccessLevel.UNACCESSIBLE;
6184
+ } else if (supportedValues?.notAvailable?.enabled && dataAvailabilityField && study[dataAvailabilityField] === 'not_available') {
5779
6185
  accessible = AccessLevel.NOT_AVAILABLE;
6186
+ } else if (supportedValues?.waiting?.enabled && !study[authzField]) {
6187
+ accessible = AccessLevel.WAITING;
5780
6188
  } else {
5781
- const isAuthorized = userHasMethodForServiceOnResource('read', '*', studyAuthz, authMapping) || userHasMethodForServiceOnResource('read', 'peregrine', studyAuthz, authMapping) || userHasMethodForServiceOnResource('read', 'guppy', studyAuthz, authMapping) || userHasMethodForServiceOnResource('read-storage', 'fence', studyAuthz, authMapping);
6189
+ let authMapping = {};
6190
+ if (isMesh) {
6191
+ let commonsURL = study.commons_url; // TODO: configure this value
6192
+ if (commonsURL && commonsURL.startsWith('http')) {
6193
+ commonsURL = new URL(commonsURL).hostname;
6194
+ }
6195
+ authMapping = userAuthMapping[commonsURL || hostnameWithSubdomain] || {};
6196
+ } else {
6197
+ authMapping = Object.values(userAuthMapping)[0];
6198
+ }
6199
+ // TODO: This needs to be configurable GFF-294
6200
+ const isAuthorized = userHasMethodForServiceOnResource('read', '*', study[authzField], authMapping) || userHasMethodForServiceOnResource('read', 'peregrine', study[authzField], authMapping) || userHasMethodForServiceOnResource('read', 'guppy', study[authzField], authMapping) || userHasMethodForServiceOnResource('read-storage', 'fence', study[authzField], authMapping);
5782
6201
  if (supportedValues?.accessible?.enabled && isAuthorized) {
5783
- accessible = AccessLevel.ACCESSIBLE;
6202
+ if (supportedValues?.mixed?.enabled && dataAvailabilityField && study[dataAvailabilityField] === 'mixed_availability') {
6203
+ accessible = AccessLevel.MIXED;
6204
+ } else {
6205
+ accessible = AccessLevel.ACCESSIBLE;
6206
+ }
5784
6207
  } else if (supportedValues?.unaccessible?.enabled && !isAuthorized) {
5785
6208
  accessible = AccessLevel.UNACCESSIBLE;
5786
6209
  } else {
@@ -5789,9 +6212,10 @@ const processAuthorizations = (data, config, authMapping)=>{
5789
6212
  }
5790
6213
  return {
5791
6214
  ...study,
5792
- __accessible: accessible
6215
+ [METADATA_ITEM_AUTHORIZATION_FIELD]: accessible
5793
6216
  };
5794
6217
  });
6218
+ return studiesWithAccessibleField;
5795
6219
  };
5796
6220
  const processChartData = (data, pathsToProcess)=>{
5797
6221
  // Initialize results object
@@ -5898,7 +6322,9 @@ const useGetMDSData = ({ guidType = 'unregistered_discovery_metadata', maxStudie
5898
6322
  ] : acc;
5899
6323
  }, []);
5900
6324
  if (discoveryConfig?.features?.authorization.enabled) {
5901
- setMDSData(processAuthorizations(studyData, discoveryConfig, authMapping));
6325
+ setMDSData(processAuthorizations(studyData, discoveryConfig, {
6326
+ default: authMapping
6327
+ }));
5902
6328
  } else setMDSData(studyData);
5903
6329
  }
5904
6330
  }, [
@@ -5937,7 +6363,9 @@ const useGetAggMDSData = ({ guidType = 'unregistered_discovery_metadata', maxStu
5937
6363
  React.useEffect(()=>{
5938
6364
  if (data && isSuccess) {
5939
6365
  if (discoveryConfig?.features?.authorization.enabled) {
5940
- setMDSData(processAuthorizations(data.data, discoveryConfig, authMapping));
6366
+ setMDSData(processAuthorizations(data.data, discoveryConfig, {
6367
+ default: authMapping
6368
+ }));
5941
6369
  } else setMDSData(data.data);
5942
6370
  }
5943
6371
  }, [
@@ -6718,7 +7146,9 @@ const useGetIndexedMDSData = ({ guidType = 'unregistered_discovery_metadata', ma
6718
7146
  if (data && isSuccess) {
6719
7147
  const studyData = data.data;
6720
7148
  if (discoveryConfig?.features?.authorization.enabled) {
6721
- setMDSData(processAuthorizations(studyData, discoveryConfig, authMapping));
7149
+ setMDSData(processAuthorizations(studyData, discoveryConfig, {
7150
+ default: authMapping
7151
+ }));
6722
7152
  } else setMDSData(studyData);
6723
7153
  } else setMDSData([]);
6724
7154
  }, [
@@ -6780,7 +7210,20 @@ const registerDefaultDiscoveryDataLoaders = ()=>{
6780
7210
  };
6781
7211
  registerDefaultDiscoveryDataLoaders();
6782
7212
 
6783
- const DiscoveryIndexPanel = ({ discoveryConfig, indexSelector })=>{
7213
+ /**
7214
+ * DiscoveryIndexPanel is a React functional component that renders a discovery panel interface.
7215
+ * It includes features such as search, sorting, filtering, charts, export functionality, and a discovery table.
7216
+ * The component uses hooks for handling state, API data loading, and interface interactions.
7217
+ *
7218
+ * @param {Object} props - The properties object passed to the component.
7219
+ * @param {Object} props.discoveryConfig - Configuration object for setting up the discovery panel.
7220
+ * @param {Object} props.discoveryConfig.features - Defines enabled features (e.g., search, charts, export).
7221
+ * @param {Object} props.discoveryConfig.minimalFieldMapping - Field mapping configuration, such as `uid`.
7222
+ * @param {JSX.Element} props.indexSelector - React component for selecting an index in the discovery panel.
7223
+ *
7224
+ * @return {JSX.Element} A fully featured discovery interface including search functionality, a table, charts, filters, and more.
7225
+ */ const DiscoveryIndexPanel = ({ discoveryConfig, indexSelector })=>{
7226
+ console.log(discoveryConfig);
6784
7227
  const dataHook = React.useMemo(()=>getDiscoveryDataLoader(discoveryConfig?.features?.dataLoader?.dataFetchFunction) ?? useLoadAllMDSData, [
6785
7228
  discoveryConfig?.features?.dataLoader?.dataFetchFunction
6786
7229
  ]);
@@ -6790,6 +7233,7 @@ const DiscoveryIndexPanel = ({ discoveryConfig, indexSelector })=>{
6790
7233
  });
6791
7234
  const parentDivRef = React.useRef(null);
6792
7235
  const [searchBarTerm, setSearchBarTerm] = React.useState([]);
7236
+ const [selections, setSelections] = React.useState([]); // table selections
6793
7237
  const [advancedSearchTerms, setAdvancedSearchTerms] = React.useState({
6794
7238
  operation: SearchCombination.and,
6795
7239
  filters: {}
@@ -6815,6 +7259,15 @@ const DiscoveryIndexPanel = ({ discoveryConfig, indexSelector })=>{
6815
7259
  searchTerms: searchParam,
6816
7260
  discoveryConfig
6817
7261
  });
7262
+ const selectedRecords = React.useMemo(()=>{
7263
+ const uidField = discoveryConfig?.minimalFieldMapping?.uid ?? 'guid';
7264
+ const filterSelectedMembers = (data)=>data.filter((member)=>uidField in member && selections.includes(member[uidField]));
7265
+ return filterSelectedMembers(data);
7266
+ }, [
7267
+ data,
7268
+ discoveryConfig?.minimalFieldMapping?.uid,
7269
+ selections
7270
+ ]);
6818
7271
  const [sorting, setSorting] = React.useState([]);
6819
7272
  const [showAdvancedSearch, { toggle: toggleAdvancedSearch }] = hooks.useDisclosure(false);
6820
7273
  if (dataRequestStatus.isLoading) {
@@ -6888,8 +7341,11 @@ const DiscoveryIndexPanel = ({ discoveryConfig, indexSelector })=>{
6888
7341
  color: "accent",
6889
7342
  children: "Filters"
6890
7343
  }) : false,
6891
- discoveryConfig?.features?.exportToDataLibrary?.enabled ? /*#__PURE__*/ jsxRuntime.jsx(ActionBar, {
6892
- config: discoveryConfig.features.exportToDataLibrary
7344
+ discoveryConfig?.features?.exportFromDiscovery?.enabled ? /*#__PURE__*/ jsxRuntime.jsx(ActionBar, {
7345
+ buttons: discoveryConfig.features.exportFromDiscovery.buttons,
7346
+ exportDataFields: discoveryConfig.features.exportFromDiscovery.exportDataFields,
7347
+ selectedResources: selectedRecords,
7348
+ verifyExternalLogins: discoveryConfig.features.exportFromDiscovery.verifyExternalLogins
6893
7349
  }) : null
6894
7350
  ]
6895
7351
  }),
@@ -6910,6 +7366,7 @@ const DiscoveryIndexPanel = ({ discoveryConfig, indexSelector })=>{
6910
7366
  dataRequestStatus: dataRequestStatus,
6911
7367
  setPagination: setPagination,
6912
7368
  setSorting: setSorting,
7369
+ setSelection: setSelections,
6913
7370
  pagination: pagination,
6914
7371
  sorting: sorting
6915
7372
  })
@@ -11012,7 +11469,7 @@ const TabsLayoutToComponentProp = (tabsLayout)=>{
11012
11469
  }
11013
11470
  };
11014
11471
  const CohortBuilder = ({ explorerConfig, sharedFiltersMap = null, tabsLayout = 'left' })=>{
11015
- const { isFetching } = core.useGetCSRFQuery();
11472
+ core.useGetCSRFQuery();
11016
11473
  const dispatch = core.useCoreDispatch();
11017
11474
  dispatch(core.setSharedFilters(sharedFiltersMap ?? {}));
11018
11475
  return /*#__PURE__*/ jsxRuntime.jsx("div", {
@@ -12322,7 +12779,7 @@ class FilesystemContent {
12322
12779
  try {
12323
12780
  return await JSON.parse(fs.readFileSync(path.join(this.rootPath, filepath)).toString('utf8'));
12324
12781
  } catch (err) {
12325
- throw new Error(`Cannot process ${filepath} `);
12782
+ throw new Error(`Cannot process ${path.join(this.rootPath, filepath)} `);
12326
12783
  }
12327
12784
  }
12328
12785
  async getAll(filepath, filter) {
@@ -12839,8 +13296,8 @@ const IndexPanel = ({ dataConfig, tabs, tabTitle })=>{
12839
13296
 
12840
13297
  const persistor = reduxPersist.persistStore(AppStore);
12841
13298
  const CohortDiscovery = (config)=>{
12842
- const { isLoading } = core.useGetCSRFQuery(); // need for Guppy
12843
- if (isLoading) {
13299
+ const { isFetching } = core.useGetCSRFQuery(); // needed for Guppy
13300
+ if (isFetching) {
12844
13301
  return /*#__PURE__*/ jsxRuntime.jsx(core$1.Center, {
12845
13302
  maw: 400,
12846
13303
  h: 100,
@@ -15174,24 +15631,25 @@ const createMantineTheme = (fonts, colors)=>{
15174
15631
  Pagination: core$1.Pagination.extend({
15175
15632
  defaultProps: {
15176
15633
  getControlProps: (control)=>{
15634
+ //Add 508 localization to Pagination, not needed if using react table
15177
15635
  if (control === 'first') {
15178
15636
  return {
15179
- "aria-label": "First"
15637
+ 'aria-label': 'First'
15180
15638
  };
15181
15639
  }
15182
15640
  if (control === 'last') {
15183
15641
  return {
15184
- "aria-label": "Last"
15642
+ 'aria-label': 'Last'
15185
15643
  };
15186
15644
  }
15187
15645
  if (control === 'next') {
15188
15646
  return {
15189
- "aria-label": "Next"
15647
+ 'aria-label': 'Next'
15190
15648
  };
15191
15649
  }
15192
15650
  if (control === 'previous') {
15193
15651
  return {
15194
- "aria-label": "Previous"
15652
+ 'aria-label': 'Previous'
15195
15653
  };
15196
15654
  }
15197
15655
  return {};
@@ -15606,7 +16064,7 @@ const GetSharedFieldMapping = async (cohortBuilderConfiguration)=>{
15606
16064
  // create shared filter from Gen3 graphql mapping
15607
16065
  const indices = cohortBuilderConfiguration?.explorerConfig.map((tab)=>tab.guppyConfig.dataType);
15608
16066
  try {
15609
- const data = await core.fetchJSONDataFromURL(`${core.GEN3_GUPPY_API}/graphql`, true, 'POST', {
16067
+ const data = await core.fetchJSONDataFromURL(`${core.GEN3_GUPPY_API}/graphql`, true, core.HttpMethod.POST, {
15610
16068
  query: `{ _mapping { ${indices.join(' ')} }}`,
15611
16069
  variables: {}
15612
16070
  });
@@ -16080,7 +16538,7 @@ const getStatus = (expiration, now)=>{
16080
16538
  * with the ability to delete a given credential using useRemoveCredentialMutation() hook
16081
16539
  * @returns {JSX.Element} The JSX element representing the credentials table.
16082
16540
  */ const CredentialsTable = ()=>{
16083
- const { data: csrfToken } = core.useGetCSRFQuery();
16541
+ const { data: csrfToken, isFetching: isCSRFFetching } = core.useGetCSRFQuery();
16084
16542
  const { data: credentials } = core.useGetCredentialsQuery();
16085
16543
  const [removeCredential] = core.useRemoveCredentialMutation();
16086
16544
  const columns = React.useMemo(()=>{
@@ -16142,7 +16600,10 @@ const getStatus = (expiration, now)=>{
16142
16600
  mantineSearchTextInputProps: {
16143
16601
  placeholder: 'Search API Keys'
16144
16602
  },
16145
- icons: TableIcons
16603
+ icons: TableIcons,
16604
+ state: {
16605
+ isLoading: isCSRFFetching
16606
+ }
16146
16607
  });
16147
16608
  return /*#__PURE__*/ jsxRuntime.jsx(mantineReactTable.MantineReactTable, {
16148
16609
  table: table
@@ -16752,7 +17213,7 @@ const AuthzContext = /*#__PURE__*/ React.createContext({
16752
17213
  },
16753
17214
  dispatch: ()=>null
16754
17215
  });
16755
- const AuthzProvider = ({ children, authz = {
17216
+ const AuthzAdminProvider = ({ children, authz = {
16756
17217
  users: [],
16757
17218
  groups: [],
16758
17219
  roles: [],
@@ -17332,7 +17793,7 @@ const Gen3Authz = ({ authz })=>{
17332
17793
  /*#__PURE__*/ jsxRuntime.jsx("h1", {
17333
17794
  children: "Gen3 Authz"
17334
17795
  }),
17335
- /*#__PURE__*/ jsxRuntime.jsx(AuthzProvider, {
17796
+ /*#__PURE__*/ jsxRuntime.jsx(AuthzAdminProvider, {
17336
17797
  authz: authz,
17337
17798
  children: /*#__PURE__*/ jsxRuntime.jsxs(core$1.Tabs, {
17338
17799
  orientation: "vertical",
@@ -18616,12 +19077,12 @@ const getDataLibraryItem = (dataLibrary, listId, dataId, fileId)=>{
18616
19077
  };
18617
19078
  } else {
18618
19079
  if (!fileId) return undefined;
18619
- if (!(fileId in datasetOrCohort.items)) return undefined;
18620
- if (core.isFileItem(datasetOrCohort.items[fileId])) {
19080
+ if (!(fileId in datasetOrCohort.members)) return undefined;
19081
+ if (core.isFileItem(datasetOrCohort.members[fileId])) {
18621
19082
  return {
18622
19083
  datasetName: name,
18623
19084
  datasetId: dataId,
18624
- ...datasetOrCohort.items[fileId]
19085
+ ...datasetOrCohort.members[fileId]
18625
19086
  };
18626
19087
  }
18627
19088
  return undefined;
@@ -18828,7 +19289,7 @@ const getNumberOfSelectedItemsInList = (selections, listId)=>{
18828
19289
  };
18829
19290
  const isListInSelection = (listId, selections)=>listId in selections;
18830
19291
 
18831
- const SearchAndActions = ({ createList, gatherData, size = 'sm' })=>{
19292
+ const SearchAndActions = ({ createList, gatherData, size = 'sm', enableCreateNewList = false, enableDownloadManifest = false })=>{
18832
19293
  const { selections, clearSelections } = useDataLibrarySelection();
18833
19294
  const retrieveDisabled = Object.keys(selections).length === 0;
18834
19295
  const iconSize = IconSize[size] || IconSize['sm'];
@@ -18868,6 +19329,38 @@ const SearchAndActions = ({ createList, gatherData, size = 'sm' })=>{
18868
19329
  height: iconSize
18869
19330
  })
18870
19331
  })
19332
+ }),
19333
+ enableCreateNewList && /*#__PURE__*/ jsxRuntime.jsx(core$1.Tooltip, {
19334
+ label: "Create a new empty list",
19335
+ children: /*#__PURE__*/ jsxRuntime.jsx(core$1.Button, {
19336
+ hidden: true,
19337
+ size: "compact-md",
19338
+ variant: "outline",
19339
+ onClick: ()=>createList({}),
19340
+ "aria-label": "create a new list",
19341
+ classNames: {
19342
+ root: 'bg-base-max hover:bg-base-light'
19343
+ },
19344
+ children: /*#__PURE__*/ jsxRuntime.jsx(md.MdAdd, {
19345
+ size: "1.5em"
19346
+ })
19347
+ })
19348
+ }),
19349
+ enableCreateNewList && /*#__PURE__*/ jsxRuntime.jsx(core$1.Tooltip, {
19350
+ label: "Download Manifest of selected items",
19351
+ children: /*#__PURE__*/ jsxRuntime.jsx(core$1.Button, {
19352
+ size: "compact-md",
19353
+ variant: "outline",
19354
+ "aria-label": "Download Manifest of Selected Items",
19355
+ classNames: {
19356
+ root: 'bg-base-max hover:bg-base-light'
19357
+ },
19358
+ children: /*#__PURE__*/ jsxRuntime.jsx(react.Icon, {
19359
+ icon: "gen3:download-alt",
19360
+ height: 24,
19361
+ width: 24
19362
+ })
19363
+ })
18871
19364
  })
18872
19365
  ]
18873
19366
  })
@@ -19275,7 +19768,7 @@ const sendExistingPFBToURL = async (validatedSelections, params, done = ()=>null
19275
19768
  withCloseButton: true,
19276
19769
  autoClose: 5000,
19277
19770
  title: 'Action Error',
19278
- message: error.status in HTTPUserFriendlyErrorMessages ? HTTPUserFriendlyErrorMessages[error.status] : 'An error has occured to prevent exporting PFB',
19771
+ message: error.status in HTTPUserFriendlyErrorMessages ? HTTPUserFriendlyErrorMessages[error.status] : 'An error has occurred to prevent exporting PFB',
19279
19772
  color: 'red',
19280
19773
  loading: false
19281
19774
  });
@@ -19544,7 +20037,7 @@ const SelectedItemsModal = (props)=>{
19544
20037
  * it iterates through the dataset items and sets the keys of file items
19545
20038
  * to true in the returned object.
19546
20039
  *
19547
- * @param {RegisteredDataListEntry | CohortItem} dataSetOrCohort - The dataset or cohort item to process.
20040
+ * @param {DataLibraryDataset | CohortItem} dataSetOrCohort - The dataset or cohort item to process.
19548
20041
  * @returns {SelectedMembers} An object representing the selected members.
19549
20042
  */ const getDatasetMembers = (dataSetOrCohort)=>{
19550
20043
  if (core.isCohortItem(dataSetOrCohort)) {
@@ -19552,7 +20045,7 @@ const SelectedItemsModal = (props)=>{
19552
20045
  [dataSetOrCohort.id]: true
19553
20046
  };
19554
20047
  }
19555
- return Object.entries(dataSetOrCohort.items).reduce((acc, [key, item])=>{
20048
+ return Object.entries(dataSetOrCohort.members).reduce((acc, [key, item])=>{
19556
20049
  if (core.isFileItem(item)) acc[key] = true;
19557
20050
  return acc;
19558
20051
  }, {});
@@ -19752,7 +20245,7 @@ const DatasetAccordionControl = ({ listName, numberOfItems, updatedTime, created
19752
20245
  ]
19753
20246
  }),
19754
20247
  /*#__PURE__*/ jsxRuntime.jsx(core$1.Tooltip, {
19755
- label: `Delete ${listName}. Will not delete dataset`,
20248
+ label: `Delete list ${listName}. Will not delete the actual dataset`,
19756
20249
  children: /*#__PURE__*/ jsxRuntime.jsx(core$1.ActionIcon, {
19757
20250
  color: "accent.4",
19758
20251
  variant: "transparent",
@@ -19969,12 +20462,18 @@ const LabeledText = ({ label, text })=>{
19969
20462
  ]
19970
20463
  });
19971
20464
  };
19972
- const QueryDetails = ({ name, schemaVersion, index, data, id })=>{
20465
+ const QueryDetails = ({ name, schemaVersion, data, id })=>{
19973
20466
  if (!data) {
19974
20467
  return /*#__PURE__*/ jsxRuntime.jsx(ErrorCard, {
19975
20468
  message: "No cohort query"
19976
20469
  });
19977
20470
  }
20471
+ const index = core.extractIndexFromDataLibraryCohort(data);
20472
+ if (!index) {
20473
+ return /*#__PURE__*/ jsxRuntime.jsx(ErrorCard, {
20474
+ message: "Not able to extract index from cohort query"
20475
+ });
20476
+ }
19978
20477
  return /*#__PURE__*/ jsxRuntime.jsxs("div", {
19979
20478
  className: "flex flex-col",
19980
20479
  children: [
@@ -20139,11 +20638,12 @@ const DataSetContentsTable = ({ listId, data, removeList, size = 'sm' })=>{
20139
20638
  } : {}
20140
20639
  };
20141
20640
  },
20142
- renderRowActions: ({ row })=>/*#__PURE__*/ jsxRuntime.jsx(core$1.Tooltip, {
20143
- label: row.original.isCohort ? 'Remove cohort from list' : 'Remove dataset from list',
20641
+ renderRowActions: ({ row })=>{
20642
+ return /*#__PURE__*/ jsxRuntime.jsx(core$1.Tooltip, {
20643
+ label: row.original.isCohort === 'True' ? 'Remove cohort from list' : 'Remove dataset from list',
20144
20644
  children: /*#__PURE__*/ jsxRuntime.jsxs(core$1.Button, {
20145
20645
  variant: "transparent",
20146
- "aria-label": `remove ${row.original.isCohort ? 'cohort' : 'dataset'} ${row.original.name} from list`,
20646
+ "aria-label": `remove ${row.original.isCohort === 'True' ? 'cohort' : 'dataset'} ${row.original.name} from list`,
20147
20647
  onClick: ()=>{
20148
20648
  removeList(row.id);
20149
20649
  },
@@ -20154,7 +20654,8 @@ const DataSetContentsTable = ({ listId, data, removeList, size = 'sm' })=>{
20154
20654
  row.original.itemType
20155
20655
  ]
20156
20656
  })
20157
- }),
20657
+ });
20658
+ },
20158
20659
  mantineDetailPanelProps: {
20159
20660
  style: {
20160
20661
  padding: '0px',
@@ -20200,11 +20701,9 @@ const DataSetContentsTable = ({ listId, data, removeList, size = 'sm' })=>{
20200
20701
  *
20201
20702
  * @param {Object} dataListAccordionItemParams - Parameters for the DataListAccordionItem.
20202
20703
  * @param {Object} dataListAccordionItemParams.dataList - The data list to be displayed in the accordion item.
20203
- * @param {Function} dataListAccordionItemParams.updateListInDataLibrary - Function to update the list in the data library.
20204
- * @param {Function} dataListAccordionItemParams.deleteListFromDataLibrary - Function to delete the list from the data library.
20205
20704
  *
20206
20705
  * @return {JSX.Element} A rendered accordion item component with controls for data list updates and deletions.
20207
- */ const DatalistAccordionItem = ({ dataList, updateListInDataLibrary, deleteListFromDataLibrary, size = 'sm' })=>{
20706
+ */ const DatalistAccordionItem = ({ dataList, updateListInDataLibrary, deleteListFromDataLibrary, isUpdating, size = 'sm' })=>{
20208
20707
  const [selectedState, setSelectedState] = React.useState('unchecked');
20209
20708
  const { id: listId, name: listName } = dataList;
20210
20709
  const numberOfItemsInList = React.useMemo(()=>{
@@ -20214,10 +20713,13 @@ const DataSetContentsTable = ({ listId, data, removeList, size = 'sm' })=>{
20214
20713
  ]);
20215
20714
  const { selections, updateSelections, removeListMember, removeList } = useDataLibrarySelection();
20216
20715
  const updateList = async (update)=>{
20217
- await updateListInDataLibrary(listId, {
20218
- ...dataList,
20716
+ await updateListInDataLibrary({
20717
+ ...{
20718
+ name: listName,
20719
+ items: dataList.items
20720
+ },
20219
20721
  ...update,
20220
- updatedTime: core.getTimestamp()
20722
+ id: listId
20221
20723
  });
20222
20724
  };
20223
20725
  const tableRowData = React.useMemo(()=>Object.entries(dataList.items).reduce((acc, [datasetId, dataItem])=>{
@@ -20235,7 +20737,7 @@ const DataSetContentsTable = ({ listId, data, removeList, size = 'sm' })=>{
20235
20737
  });
20236
20738
  } else {
20237
20739
  // handle RegisteredDataListEntry
20238
- Object.entries(dataItem.items).forEach(([itemId, item])=>{
20740
+ Object.entries(dataItem.members).forEach(([itemId, item])=>{
20239
20741
  if (core.isFileItem(item)) {
20240
20742
  files.push({
20241
20743
  ...item,
@@ -20287,10 +20789,10 @@ const DataSetContentsTable = ({ listId, data, removeList, size = 'sm' })=>{
20287
20789
  const removeItemFromList = async (itemId)=>{
20288
20790
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
20289
20791
  const { [itemId]: _removedKey, ...newObject } = dataList.items;
20290
- await updateListInDataLibrary(listId, {
20291
- ...dataList,
20292
- items: newObject,
20293
- updatedTime: core.getTimestamp()
20792
+ await updateListInDataLibrary({
20793
+ id: listId,
20794
+ name: dataList.name,
20795
+ items: newObject
20294
20796
  });
20295
20797
  // update selections
20296
20798
  removeListMember(listId, itemId);
@@ -20306,12 +20808,16 @@ const DataSetContentsTable = ({ listId, data, removeList, size = 'sm' })=>{
20306
20808
  return /*#__PURE__*/ jsxRuntime.jsxs(core$1.Accordion.Item, {
20307
20809
  value: listName,
20308
20810
  className: "group",
20811
+ pos: "relative",
20309
20812
  children: [
20813
+ /*#__PURE__*/ jsxRuntime.jsx(core$1.LoadingOverlay, {
20814
+ visible: isUpdating === listId
20815
+ }),
20310
20816
  /*#__PURE__*/ jsxRuntime.jsx(DatasetAccordionControl, {
20311
20817
  listName: listName,
20312
20818
  numberOfItems: numberOfItemsInList,
20313
- updatedTime: dataList.updatedTime,
20314
- createdTime: dataList.createdTime,
20819
+ updatedTime: dataList.updated_time,
20820
+ createdTime: dataList.created_time,
20315
20821
  updateHandler: updateList,
20316
20822
  deleteListHandler: ()=>deleteListFromDataLibrary(listId),
20317
20823
  selectListHandler: handleSelectList,
@@ -20330,34 +20836,41 @@ const DataSetContentsTable = ({ listId, data, removeList, size = 'sm' })=>{
20330
20836
  }, listName);
20331
20837
  };
20332
20838
 
20333
- const DataLibraryLists = ({ useAPI, actions, size })=>{
20334
- const { dataLibrary, isError, isLoading, error: dataLibraryError, addListToDataLibrary, updateListInDataLibrary, deleteListFromDataLibrary } = core.useDataLibrary(useAPI);
20839
+ const DataLibraryLists = ({ requiresLogin = true, actions, size })=>{
20840
+ const { dataLibrary, isLoading, isUpdating, error: dataLibraryError, addListToDataLibrary, updateListInDataLibrary, deleteListFromDataLibrary } = core.useDataLibrary();
20841
+ const { isAuthenticated } = useIsAuthenticated();
20335
20842
  const [selectedItemsOpen, { open, close }] = hooks.useDisclosure(false);
20336
20843
  const { gatherSelectedItems } = useDataLibrarySelection();
20337
20844
  const gatherData = ()=>{
20338
20845
  gatherSelectedItems(dataLibrary);
20339
20846
  open();
20340
20847
  };
20341
- if (isError) {
20342
- let message = 'There was a error getting the library';
20343
- if (dataLibraryError && 'data' in dataLibraryError && dataLibraryError?.status in HTTPUserFriendlyErrorMessages) {
20344
- message = HTTPUserFriendlyErrorMessages[dataLibraryError?.status];
20345
- }
20346
- return /*#__PURE__*/ jsxRuntime.jsx("div", {
20347
- className: "flex flex-col w-full ml-2",
20348
- children: /*#__PURE__*/ jsxRuntime.jsx(core$1.Center, {
20349
- children: /*#__PURE__*/ jsxRuntime.jsx(ErrorCard, {
20350
- message: message
20848
+ if (dataLibraryError?.isError) {
20849
+ if (dataLibraryError?.status === 401) {
20850
+ let message = 'You are not authorized to access the library.';
20851
+ if (requiresLogin) {
20852
+ if (!isAuthenticated) message = 'Data Library requires login. Please log in to continue.';
20853
+ else message = 'You are not authorized to access the library. Please contact your site administrator.';
20854
+ }
20855
+ return /*#__PURE__*/ jsxRuntime.jsx("div", {
20856
+ className: "flex flex-col w-full ml-2",
20857
+ children: /*#__PURE__*/ jsxRuntime.jsx(core$1.Center, {
20858
+ children: /*#__PURE__*/ jsxRuntime.jsx(ErrorCard, {
20859
+ message: message
20860
+ })
20351
20861
  })
20352
- })
20862
+ });
20863
+ } else notifications.notifications.show({
20864
+ position: 'top-center',
20865
+ color: 'red',
20866
+ title: 'Data Library Error',
20867
+ message: dataLibraryError?.message,
20868
+ autoClose: 2000
20353
20869
  });
20354
20870
  }
20355
20871
  return /*#__PURE__*/ jsxRuntime.jsxs("div", {
20356
20872
  className: "flex flex-col w-full ml-2",
20357
20873
  children: [
20358
- /*#__PURE__*/ jsxRuntime.jsx(core$1.LoadingOverlay, {
20359
- visible: isLoading
20360
- }),
20361
20874
  /*#__PURE__*/ jsxRuntime.jsx(SelectedItemsModal, {
20362
20875
  opened: selectedItemsOpen,
20363
20876
  onClose: close,
@@ -20368,23 +20881,29 @@ const DataLibraryLists = ({ useAPI, actions, size })=>{
20368
20881
  createList: addListToDataLibrary,
20369
20882
  gatherData: gatherData
20370
20883
  }),
20371
- /*#__PURE__*/ jsxRuntime.jsx("div", {
20884
+ /*#__PURE__*/ jsxRuntime.jsxs("div", {
20372
20885
  className: "flex items-center",
20373
- children: /*#__PURE__*/ jsxRuntime.jsx(core$1.Accordion, {
20374
- chevronPosition: "left",
20375
- classNames: {
20376
- root: 'w-full',
20377
- control: 'data-active:bg-secondary-lightest'
20378
- },
20379
- children: dataLibrary && Object.values(dataLibrary).map((datalist)=>{
20380
- return /*#__PURE__*/ jsxRuntime.jsx(DatalistAccordionItem, {
20381
- dataList: datalist,
20382
- size: size,
20383
- updateListInDataLibrary: updateListInDataLibrary,
20384
- deleteListFromDataLibrary: deleteListFromDataLibrary
20385
- }, datalist.id);
20886
+ children: [
20887
+ /*#__PURE__*/ jsxRuntime.jsx(core$1.LoadingOverlay, {
20888
+ visible: isLoading
20889
+ }),
20890
+ /*#__PURE__*/ jsxRuntime.jsx(core$1.Accordion, {
20891
+ chevronPosition: "left",
20892
+ classNames: {
20893
+ root: 'w-full',
20894
+ control: 'data-active:bg-secondary-lightest'
20895
+ },
20896
+ children: dataLibrary && Object.values(dataLibrary).map((datalist)=>{
20897
+ return /*#__PURE__*/ jsxRuntime.jsx(DatalistAccordionItem, {
20898
+ dataList: datalist,
20899
+ size: size,
20900
+ isUpdating: isUpdating,
20901
+ updateListInDataLibrary: updateListInDataLibrary,
20902
+ deleteListFromDataLibrary: deleteListFromDataLibrary
20903
+ }, datalist.id);
20904
+ })
20386
20905
  })
20387
- })
20906
+ ]
20388
20907
  })
20389
20908
  ]
20390
20909
  });
@@ -21046,6 +21565,7 @@ async function credentialsLogout(req, res) {
21046
21565
  }
21047
21566
 
21048
21567
  exports.AISearchPageGetServerSideProps = AISearchPageGetServerSideProps;
21568
+ exports.ActionBar = ActionBar;
21049
21569
  exports.ActionButton = ActionButton;
21050
21570
  exports.AdminAuthZPageGetServerSideProps = AdminAuthZPageGetServerSideProps;
21051
21571
  exports.AiSearch = AiSearch;