synapse-react-client 4.0.9 → 4.0.10

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 (543) hide show
  1. package/dist/SWC.index.d.ts +1 -0
  2. package/dist/SWC.index.d.ts.map +1 -1
  3. package/dist/SWC.index.js +2 -1
  4. package/dist/SWC.index.js.map +1 -1
  5. package/dist/aridhia-queries/aridhiaTokenExchange.js.map +1 -1
  6. package/dist/aridhia-queries/useGetAridhiaRequests.js.map +1 -1
  7. package/dist/assets/icons/TasksIcon.d.ts.map +1 -1
  8. package/dist/assets/icons/TasksIcon.js +6 -10
  9. package/dist/assets/icons/TasksIcon.js.map +1 -1
  10. package/dist/components/AccessRequirementAclEditor/AccessRequirementAclEditor.d.ts.map +1 -1
  11. package/dist/components/AccessRequirementAclEditor/AccessRequirementAclEditor.js +69 -63
  12. package/dist/components/AccessRequirementAclEditor/AccessRequirementAclEditor.js.map +1 -1
  13. package/dist/components/AccessRequirementList/AccessApprovalCheckMark.js.map +1 -1
  14. package/dist/components/AccessRequirementList/AccessRequirementList.js.map +1 -1
  15. package/dist/components/AccessRequirementList/AccessRequirementListUtils.js.map +1 -1
  16. package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/DataAccessRequestAccessorsEditor.js.map +1 -1
  17. package/dist/components/AccessRequirementList/RequirementItem/SelfSignAccessRequirementItem.js.map +1 -1
  18. package/dist/components/AccessRequirementRelatedProjectsList/AccessRequirementRelatedProjectsList.js.map +1 -1
  19. package/dist/components/AccessTokenPage/AccessTokenCard/AccessTokenCard.js.map +1 -1
  20. package/dist/components/AcknowledgementsPage/StudyAcknowledgements.js.map +1 -1
  21. package/dist/components/AclEditor/PermissionLevelMenu.js.map +1 -1
  22. package/dist/components/AclEditor/ResourceAccessAndUserGroupHeader.js.map +1 -1
  23. package/dist/components/AclEditor/useSortResourceAccessList.js.map +1 -1
  24. package/dist/components/AclEditor/useUpdateAcl.js.map +1 -1
  25. package/dist/components/Aridhia/AridhiaAccessStatus.js.map +1 -1
  26. package/dist/components/Authentication/AuthenticationMethodSelection.d.ts.map +1 -1
  27. package/dist/components/Authentication/AuthenticationMethodSelection.js +38 -37
  28. package/dist/components/Authentication/AuthenticationMethodSelection.js.map +1 -1
  29. package/dist/components/Authentication/Constants.d.ts +1 -0
  30. package/dist/components/Authentication/Constants.d.ts.map +1 -1
  31. package/dist/components/Authentication/Constants.js +2 -2
  32. package/dist/components/Authentication/Constants.js.map +1 -1
  33. package/dist/components/Authentication/LastLoginInfo.js.map +1 -1
  34. package/dist/components/Authentication/RecoveryCodeForm.js.map +1 -1
  35. package/dist/components/Authentication/RecoveryCodeGrid.js.map +1 -1
  36. package/dist/components/Authentication/RegenerateBackupCodesWarning.js.map +1 -1
  37. package/dist/components/Authentication/Reset2FAWarning.js.map +1 -1
  38. package/dist/components/Authentication/StandaloneLoginForm.js +1 -1
  39. package/dist/components/Authentication/TwoFactorBackupCodes.js.map +1 -1
  40. package/dist/components/Authentication/TwoFactorEnrollmentForm.d.ts.map +1 -1
  41. package/dist/components/Authentication/TwoFactorEnrollmentForm.js +2 -1
  42. package/dist/components/Authentication/TwoFactorEnrollmentForm.js.map +1 -1
  43. package/dist/components/BasePortalCard/ColorfulPortalCardWithChips/ColorfulPortalCardWithChips.js.map +1 -1
  44. package/dist/components/CardContainer/CardContainer.js.map +1 -1
  45. package/dist/components/CardDeck/CardDeck.Mobile.js.map +1 -1
  46. package/dist/components/CardDeck/TableQueryCardDeck.js.map +1 -1
  47. package/dist/components/CertificationQuiz/CertificationQuiz.js.map +1 -1
  48. package/dist/components/ChallengeDataDownload/ChallengeDataDownload.js.map +1 -1
  49. package/dist/components/ChallengeSubmission/ChallengeSubmission.js.map +1 -1
  50. package/dist/components/ChallengeSubmission/ChallengeSubmissionStepper.js.map +1 -1
  51. package/dist/components/ChallengeSubmission/EvaluationQueueCurrentRoundInfo.js.map +1 -1
  52. package/dist/components/ChallengeSubmission/EvaluationQueueList.js.map +1 -1
  53. package/dist/components/ChallengeSubmission/SubmissionDirectoryList.js.map +1 -1
  54. package/dist/components/ChallengeTeamWizard/ChallengeTeamWizard.js.map +1 -1
  55. package/dist/components/ChallengeTeamWizard/CreateChallengeTeam.js.map +1 -1
  56. package/dist/components/ChangePassword/ChangePassword.js.map +1 -1
  57. package/dist/components/ChangePassword/ChangePasswordWithToken.js.map +1 -1
  58. package/dist/components/ChangePassword/useChangePasswordFormState.js +1 -1
  59. package/dist/components/ChangePassword/useChangePasswordFormState.js.map +1 -1
  60. package/dist/components/CitationPopover/CitationPopoverContent.js.map +1 -1
  61. package/dist/components/ColumnFilter/ColumnFilter.js.map +1 -1
  62. package/dist/components/ComponentCollapse.js.map +1 -1
  63. package/dist/components/CookiesNotification/CookiesNotification.js.map +1 -1
  64. package/dist/components/CreateProjectModal/CreateProjectModal.js.map +1 -1
  65. package/dist/components/CreateTableViewWizard/CreateTableViewWizardUtils.js.map +1 -1
  66. package/dist/components/DataGrid/DataGrid.d.ts +0 -1
  67. package/dist/components/DataGrid/DataGrid.d.ts.map +1 -1
  68. package/dist/components/DataGrid/DataGrid.js +72 -72
  69. package/dist/components/DataGrid/DataGrid.js.map +1 -1
  70. package/dist/components/DataGrid/DataGridWebSocket.d.ts +4 -0
  71. package/dist/components/DataGrid/DataGridWebSocket.d.ts.map +1 -1
  72. package/dist/components/DataGrid/DataGridWebSocket.js +9 -8
  73. package/dist/components/DataGrid/DataGridWebSocket.js.map +1 -1
  74. package/dist/components/DataGrid/SynapseGrid.d.ts.map +1 -1
  75. package/dist/components/DataGrid/SynapseGrid.js +326 -268
  76. package/dist/components/DataGrid/SynapseGrid.js.map +1 -1
  77. package/dist/components/DataGrid/columns/AutocompleteColumn.d.ts +2 -0
  78. package/dist/components/DataGrid/columns/AutocompleteColumn.d.ts.map +1 -1
  79. package/dist/components/DataGrid/columns/AutocompleteColumn.js +113 -67
  80. package/dist/components/DataGrid/columns/AutocompleteColumn.js.map +1 -1
  81. package/dist/components/DataGrid/columns/AutocompleteMultipleEnumColumn.d.ts +2 -1
  82. package/dist/components/DataGrid/columns/AutocompleteMultipleEnumColumn.d.ts.map +1 -1
  83. package/dist/components/DataGrid/columns/AutocompleteMultipleEnumColumn.js +126 -122
  84. package/dist/components/DataGrid/columns/AutocompleteMultipleEnumColumn.js.map +1 -1
  85. package/dist/components/DataGrid/columns/useGridAutocompleteState.d.ts +58 -0
  86. package/dist/components/DataGrid/columns/useGridAutocompleteState.d.ts.map +1 -0
  87. package/dist/components/DataGrid/columns/useGridAutocompleteState.js +52 -0
  88. package/dist/components/DataGrid/columns/useGridAutocompleteState.js.map +1 -0
  89. package/dist/components/DataGrid/components/ValidationAlert.d.ts +5 -2
  90. package/dist/components/DataGrid/components/ValidationAlert.d.ts.map +1 -1
  91. package/dist/components/DataGrid/components/ValidationAlert.js +429 -24
  92. package/dist/components/DataGrid/components/ValidationAlert.js.map +1 -1
  93. package/dist/components/DataGrid/hooks/useColumnResizeHandles.js.map +1 -1
  94. package/dist/components/DataGrid/hooks/useGetSchemaForGrid.js.map +1 -1
  95. package/dist/components/DataGrid/hooks/useGridUndoRedo.js.map +1 -1
  96. package/dist/components/DataGrid/hooks/useStack.js.map +1 -1
  97. package/dist/components/DataGrid/useCRDTModelView.js.map +1 -1
  98. package/dist/components/DataGrid/useDataGridWebsocket.d.ts +7 -0
  99. package/dist/components/DataGrid/useDataGridWebsocket.d.ts.map +1 -1
  100. package/dist/components/DataGrid/useDataGridWebsocket.js +16 -2
  101. package/dist/components/DataGrid/useDataGridWebsocket.js.map +1 -1
  102. package/dist/components/DataGrid/useInitializeGridConnection.js.map +1 -1
  103. package/dist/components/DataGrid/useMergeGridWithRecordSet.js.map +1 -1
  104. package/dist/components/DataGrid/useMergeGridWithSource.js.map +1 -1
  105. package/dist/components/DataGrid/useMergeGridWithTable.js.map +1 -1
  106. package/dist/components/DataGrid/utils/DataGridUtils.js.map +1 -1
  107. package/dist/components/DataGrid/utils/applyModelChange.js.map +1 -1
  108. package/dist/components/DataGrid/utils/columnFactory.js.map +1 -1
  109. package/dist/components/DataGrid/utils/computeReplicaSelectionModel.js.map +1 -1
  110. package/dist/components/DataGrid/utils/extractColumnValidationMessages.js.map +1 -1
  111. package/dist/components/DataGrid/utils/getCellClassName.d.ts.map +1 -1
  112. package/dist/components/DataGrid/utils/getCellClassName.js +8 -8
  113. package/dist/components/DataGrid/utils/getCellClassName.js.map +1 -1
  114. package/dist/components/DataGrid/utils/json-rx/JsonRx.js.map +1 -1
  115. package/dist/components/DataGrid/utils/modelRowsToGrid.js.map +1 -1
  116. package/dist/components/DataGrid/utils/parseFreeTextUsingJsonSchemaType.js.map +1 -1
  117. package/dist/components/DataGrid/utils/splitPatch.js.map +1 -1
  118. package/dist/components/DateTimePicker/DateTimePicker.js.map +1 -1
  119. package/dist/components/DirectDownload/DirectDownload.js.map +1 -1
  120. package/dist/components/DirectDownloadButton.js.map +1 -1
  121. package/dist/components/DownloadCart/CreatePackageV2.js.map +1 -1
  122. package/dist/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.js.map +1 -1
  123. package/dist/components/DownloadCart/DownloadListActionsRequired.js.map +1 -1
  124. package/dist/components/DownloadCart/DownloadListTable.js.map +1 -1
  125. package/dist/components/DownloadCart/fileNameUtils.js.map +1 -1
  126. package/dist/components/DraggableDialog/DraggableDialog.js.map +1 -1
  127. package/dist/components/DynamicForm/DynamicFormModal.js.map +1 -1
  128. package/dist/components/Ecosystem/TableQueryEcosystem.js.map +1 -1
  129. package/dist/components/EntityAclEditor/EntityAclEditor.d.ts.map +1 -1
  130. package/dist/components/EntityAclEditor/EntityAclEditor.js +103 -103
  131. package/dist/components/EntityAclEditor/EntityAclEditor.js.map +1 -1
  132. package/dist/components/EntityAclEditor/useNotifyNewACLUsers.js.map +1 -1
  133. package/dist/components/EntityBadgeIcons/EntityBadgeIcons.js.map +1 -1
  134. package/dist/components/EntityCitation/EntityCitation.js.map +1 -1
  135. package/dist/components/EntityDownloadButton/EntityDownloadButton.js.map +1 -1
  136. package/dist/components/EntityDownloadConfirmation/EntityDownloadConfirmation.d.ts.map +1 -1
  137. package/dist/components/EntityDownloadConfirmation/EntityDownloadConfirmation.js +36 -30
  138. package/dist/components/EntityDownloadConfirmation/EntityDownloadConfirmation.js.map +1 -1
  139. package/dist/components/EntityFinder/EntityFinder.js.map +1 -1
  140. package/dist/components/EntityFinder/VersionSelectionType.js.map +1 -1
  141. package/dist/components/EntityFinder/details/configurations/EntityChildrenDetails.js.map +1 -1
  142. package/dist/components/EntityFinder/details/configurations/FavoritesDetails.js.map +1 -1
  143. package/dist/components/EntityFinder/details/configurations/ProjectListDetails.js.map +1 -1
  144. package/dist/components/EntityFinder/details/view/DetailsView.js.map +1 -1
  145. package/dist/components/EntityFinder/tree/EntityTree.js.map +1 -1
  146. package/dist/components/EntityFinder/tree/VirtualizedTree.js.map +1 -1
  147. package/dist/components/EntityFinder/useEntitySelection.js.map +1 -1
  148. package/dist/components/EntityForm/EntityForm.js.map +1 -1
  149. package/dist/components/EntityHeaderTable/EntityHeaderTable.js.map +1 -1
  150. package/dist/components/EntityHeaderTable/Filter.js.map +1 -1
  151. package/dist/components/EntityHeaderTable/useEntityHeaderTableState.js.map +1 -1
  152. package/dist/components/EntitySubjectsSelector/EntitySubjectsSelector.js.map +1 -1
  153. package/dist/components/EntityTreeTable/components/IdColumnHeader.js.map +1 -1
  154. package/dist/components/EntityTreeTable/hooks/useEntityTreeState.js.map +1 -1
  155. package/dist/components/EntityTreeTable/hooks/useTableColumns.js.map +1 -1
  156. package/dist/components/EntityTreeTable/hooks/useTableData.js.map +1 -1
  157. package/dist/components/EntityTreeTable/hooks/useTreeOperationsWithDirectFetch.js.map +1 -1
  158. package/dist/components/EntityUpload/EntityUpload.js.map +1 -1
  159. package/dist/components/ExperimentalMode/ExperimentalMode.js.map +1 -1
  160. package/dist/components/ExternalFileHandleLink/ExternalFileHandleLink.js.map +1 -1
  161. package/dist/components/FeaturedDataTabs/FacetPlotsCard.js.map +1 -1
  162. package/dist/components/FeaturedDataTabs/QueryPerFacetPlotsCard.js.map +1 -1
  163. package/dist/components/FeaturedDataTabs/SingleQueryFacetPlotsCards.js.map +1 -1
  164. package/dist/components/FeaturedResearch/FeaturedResearch.js.map +1 -1
  165. package/dist/components/FeaturedToolsList/FeaturedToolsList.js.map +1 -1
  166. package/dist/components/FilePreview/FileHandleContentRenderer.js.map +1 -1
  167. package/dist/components/FilePreview/HtmlPreview/HtmlPreview.js.map +1 -1
  168. package/dist/components/FilePreview/PreviewRendererType.js.map +1 -1
  169. package/dist/components/Forum/DiscussionReply.js.map +1 -1
  170. package/dist/components/Forum/DiscussionSearchResult.js.map +1 -1
  171. package/dist/components/Forum/ForumTable.js.map +1 -1
  172. package/dist/components/Forum/ForumThreadEditor.js.map +1 -1
  173. package/dist/components/FullTextSearch/FullTextSearchUtils.js.map +1 -1
  174. package/dist/components/GenericCard/GenericCard.d.ts.map +1 -1
  175. package/dist/components/GenericCard/GenericCard.js +12 -7
  176. package/dist/components/GenericCard/GenericCard.js.map +1 -1
  177. package/dist/components/GenericCard/Linkify.js.map +1 -1
  178. package/dist/components/GenericCard/SynapseCardLabel.js.map +1 -1
  179. package/dist/components/GenericCard/TableRowGenericCard.js +105 -105
  180. package/dist/components/GenericCard/TableRowGenericCard.js.map +1 -1
  181. package/dist/components/Goals/Goals.Mobile.js.map +1 -1
  182. package/dist/components/Goals/Goals.js.map +1 -1
  183. package/dist/components/GoalsV2/GoalsV2.Mobile.js.map +1 -1
  184. package/dist/components/GoalsV2/GoalsV2.js.map +1 -1
  185. package/dist/components/GoalsV3/GoalsV3.Mobile.js.map +1 -1
  186. package/dist/components/GoalsV3/GoalsV3.js.map +1 -1
  187. package/dist/components/GoogleMap/SynapseUserMarker.js.map +1 -1
  188. package/dist/components/HasAccess/AccessIcon.js.map +1 -1
  189. package/dist/components/HasAccess/useHasAccess.js.map +1 -1
  190. package/dist/components/HeaderCard/HeaderCardV2.js.map +1 -1
  191. package/dist/components/HeaderCard.d.ts +6 -1
  192. package/dist/components/HeaderCard.d.ts.map +1 -1
  193. package/dist/components/HeaderCard.js +107 -76
  194. package/dist/components/HeaderCard.js.map +1 -1
  195. package/dist/components/HexGrid/HexGrid.js.map +1 -1
  196. package/dist/components/IconList.js.map +1 -1
  197. package/dist/components/ImageCardGridWithLinks/ImageCardGridWithLinks.js.map +1 -1
  198. package/dist/components/ImageFromSynapseTable.js.map +1 -1
  199. package/dist/components/JSONArrayEditor/useParseCsv.js.map +1 -1
  200. package/dist/components/JsonSchemaForm/templates/ArrayFieldDescriptionTemplate.js.map +1 -1
  201. package/dist/components/JsonSchemaForm/templates/ArrayFieldItemTemplate.js.map +1 -1
  202. package/dist/components/JsonSchemaForm/templates/BaseInputTemplate.js.map +1 -1
  203. package/dist/components/JsonSchemaForm/templates/FieldTemplate.js.map +1 -1
  204. package/dist/components/JsonSchemaForm/templates/RJSFInputLabel.js.map +1 -1
  205. package/dist/components/Markdown/MarkdownGithub.js.map +1 -1
  206. package/dist/components/Markdown/MarkdownSynapse.js.map +1 -1
  207. package/dist/components/Markdown/MarkdownUtils.js.map +1 -1
  208. package/dist/components/Markdown/SynapseWikiContext.js.map +1 -1
  209. package/dist/components/Markdown/UserMentionModal.js.map +1 -1
  210. package/dist/components/Markdown/widget/MarkdownProvenanceGraph.js.map +1 -1
  211. package/dist/components/MissingQueryResultsWarning/MissingQueryResultsWarning.js.map +1 -1
  212. package/dist/components/ModalDownload/ModalDownload.js.map +1 -1
  213. package/dist/components/OAuthClientAclEditor/OAuthClientAclEditor.d.ts.map +1 -1
  214. package/dist/components/OAuthClientAclEditor/OAuthClientAclEditor.js +45 -39
  215. package/dist/components/OAuthClientAclEditor/OAuthClientAclEditor.js.map +1 -1
  216. package/dist/components/OAuthClientManagement/OAuthManagement.js.map +1 -1
  217. package/dist/components/PageProgress/PageProgress.js.map +1 -1
  218. package/dist/components/Plot/DotPlot.js.map +1 -1
  219. package/dist/components/Plot/Plot.js.map +1 -1
  220. package/dist/components/Plot/SynapsePlot.js.map +1 -1
  221. package/dist/components/Plot/ThemesPlot.js.map +1 -1
  222. package/dist/components/Plot/UpsetPlot.js.map +1 -1
  223. package/dist/components/PortalAclEditor/PortalAclEditor.d.ts.map +1 -1
  224. package/dist/components/PortalAclEditor/PortalAclEditor.js +43 -41
  225. package/dist/components/PortalAclEditor/PortalAclEditor.js.map +1 -1
  226. package/dist/components/PortalFeaturedPartners/PortalFeaturedPartners.js.map +1 -1
  227. package/dist/components/PortalList/CreatePortalModal.js.map +1 -1
  228. package/dist/components/ProgrammaticInstructionsModal/ProgrammaticInstructionsModal.js.map +1 -1
  229. package/dist/components/ProgrammaticTableDownload/ProgrammaticTableDownload.js.map +1 -1
  230. package/dist/components/Programs/Programs.Mobile.js.map +1 -1
  231. package/dist/components/Programs/Programs.js.map +1 -1
  232. package/dist/components/ProvenanceGraph/ProvenanceExternalIcon.js.map +1 -1
  233. package/dist/components/ProvenanceGraph/ProvenanceGraph.js.map +1 -1
  234. package/dist/components/ProvenanceGraph/ProvenanceGraphUtils.js.map +1 -1
  235. package/dist/components/ProvenanceGraph/ProvenanceUtils.js.map +1 -1
  236. package/dist/components/QueryCount/QueryCount.js.map +1 -1
  237. package/dist/components/QueryCountButton/QueryCountButton.js.map +1 -1
  238. package/dist/components/QueryVisualizationWrapper/QueryVisualizationWrapper.js.map +1 -1
  239. package/dist/components/QueryWrapper/QueryWrapper.js.map +1 -1
  240. package/dist/components/QueryWrapper/TableQueryUseQueryOptions.js.map +1 -1
  241. package/dist/components/QueryWrapper/TableRowSelectionState.js.map +1 -1
  242. package/dist/components/QueryWrapper/generateEncodedPathAndQueryForSelectedFacetURL.js.map +1 -1
  243. package/dist/components/QueryWrapper/useGetQueryMetadata.js.map +1 -1
  244. package/dist/components/QueryWrapperErrorBoundary.js.map +1 -1
  245. package/dist/components/QueryWrapperPlotNav/QueryWrapperPlotNav.js.map +1 -1
  246. package/dist/components/QueryWrapperPlotNav/UseRowSet.js.map +1 -1
  247. package/dist/components/RecentPublicationsGrid/RecentPublicationsGrid.js.map +1 -1
  248. package/dist/components/ReleaseCard/ReleaseCardUtils.js.map +1 -1
  249. package/dist/components/ResizableContainer/hooks/useResizable.js.map +1 -1
  250. package/dist/components/Resources/Resources.Mobile.js.map +1 -1
  251. package/dist/components/Resources/Resources.js.map +1 -1
  252. package/dist/components/RowDataTable/RowDataTableWithQuery.js.map +1 -1
  253. package/dist/components/SageResourcesPopover/SageResourcesPopover.js.map +1 -1
  254. package/dist/components/SchemaDrivenAnnotationEditor/AnnotationEditorUtils.js.map +1 -1
  255. package/dist/components/SetAccessRequirementCommonFields/SetAccessRequirementCommonFields.js.map +1 -1
  256. package/dist/components/SetManagedAccessRequirementFields/SetManagedAccessRequirementFields.js.map +1 -1
  257. package/dist/components/SmartLink/SmartButton.js.map +1 -1
  258. package/dist/components/SmartLink/SmartLink.js.map +1 -1
  259. package/dist/components/SourceAppImage.js.map +1 -1
  260. package/dist/components/StandaloneQueryWrapper/StandaloneQueryWrapper.js.map +1 -1
  261. package/dist/components/StatisticsPlot.js.map +1 -1
  262. package/dist/components/StorybookComponentWrapper.js.map +1 -1
  263. package/dist/components/SubsectionRowRenderer/SubsectionRowRenderer.js.map +1 -1
  264. package/dist/components/SustainabilityScorecard/SustainabilityScorecard.js.map +1 -1
  265. package/dist/components/SynapseChat/GridAgentChat.js.map +1 -1
  266. package/dist/components/SynapseChat/SynapseChatInteraction.js.map +1 -1
  267. package/dist/components/SynapseChat/SynapseChatMessage.js.map +1 -1
  268. package/dist/components/SynapseChat/extractMessageFromTraceEvent.js.map +1 -1
  269. package/dist/components/SynapseForm/StepsSideNav.js.map +1 -1
  270. package/dist/components/SynapseForm/SummaryTable.js.map +1 -1
  271. package/dist/components/SynapseForm/SynapseForm.js +4 -2
  272. package/dist/components/SynapseForm/SynapseForm.js.map +1 -1
  273. package/dist/components/SynapseForm/SynapseFormWrapper.js.map +1 -1
  274. package/dist/components/SynapseHomepageV2/SynapseByTheNumbersItem.js.map +1 -1
  275. package/dist/components/SynapseHomepageV2/SynapseFeatureItem.js.map +1 -1
  276. package/dist/components/SynapseHomepageV2/SynapseHomepageChatSearch.js.map +1 -1
  277. package/dist/components/SynapseHomepageV2/SynapseHomepageSearch.js.map +1 -1
  278. package/dist/components/SynapseHomepageV2/SynapseInActionItem.js.map +1 -1
  279. package/dist/components/SynapseHomepageV2/SynapsePlans.js.map +1 -1
  280. package/dist/components/SynapseHomepageV2/SynapseTrendingProjects.js.map +1 -1
  281. package/dist/components/SynapseNavDrawer/SynapseNavDrawer.d.ts +8 -7
  282. package/dist/components/SynapseNavDrawer/SynapseNavDrawer.d.ts.map +1 -1
  283. package/dist/components/SynapseNavDrawer/SynapseNavDrawer.js +173 -164
  284. package/dist/components/SynapseNavDrawer/SynapseNavDrawer.js.map +1 -1
  285. package/dist/components/SynapsePortalBanners/SynapsePortalBanners.js.map +1 -1
  286. package/dist/components/SynapseSearchPageResults/SearchFacetPanel/SearchFacetPanel.js.map +1 -1
  287. package/dist/components/SynapseSearchPageResults/SearchFacetPanel/SearchFacetPanelUtils.js.map +1 -1
  288. package/dist/components/SynapseSearchPageResults/SynapseSearchPageResults.js.map +1 -1
  289. package/dist/components/SynapseTable/EntityIDColumnCopyIcon.js.map +1 -1
  290. package/dist/components/SynapseTable/NoContentPlaceholderType.js.map +1 -1
  291. package/dist/components/SynapseTable/RowSelection/RowSelectionControls.js.map +1 -1
  292. package/dist/components/SynapseTable/SynapseTableCell/SynapseTableCell.js.map +1 -1
  293. package/dist/components/SynapseTable/SynapseTableRenderers.js.map +1 -1
  294. package/dist/components/SynapseTable/datasets/DatasetItemsEditor.js.map +1 -1
  295. package/dist/components/SynapseTable/table-top/ColumnSelection.js.map +1 -1
  296. package/dist/components/SynapseTable/table-top/DownloadOptions.js.map +1 -1
  297. package/dist/components/SynapseTable/usePrefetchTableData.js.map +1 -1
  298. package/dist/components/TableColumnSchemaEditor/ColumnModelForm.js.map +1 -1
  299. package/dist/components/TableColumnSchemaEditor/ColumnModelFormFields/DefaultValueField.js.map +1 -1
  300. package/dist/components/TableColumnSchemaEditor/ImportTableColumnsButton.js.map +1 -1
  301. package/dist/components/TableColumnSchemaEditor/TableColumnSchemaEditorUtils.d.ts +1 -1
  302. package/dist/components/TableColumnSchemaEditor/TableColumnSchemaEditorUtils.d.ts.map +1 -1
  303. package/dist/components/TableColumnSchemaEditor/TableColumnSchemaEditorUtils.js.map +1 -1
  304. package/dist/components/TableColumnSchemaEditor/TableColumnSchemaForm.js.map +1 -1
  305. package/dist/components/TableColumnSchemaEditor/TableColumnSchemaFormReducer.js.map +1 -1
  306. package/dist/components/TableColumnSchemaEditor/Validators/ColumnModelValidator.js.map +1 -1
  307. package/dist/components/TableColumnSchemaEditor/Validators/DatetimeSchema.js.map +1 -1
  308. package/dist/components/TanStackTable/ColumnHeader.d.ts +1 -0
  309. package/dist/components/TanStackTable/ColumnHeader.d.ts.map +1 -1
  310. package/dist/components/TanStackTable/ColumnHeader.js +8 -8
  311. package/dist/components/TanStackTable/ColumnHeader.js.map +1 -1
  312. package/dist/components/TanStackTable/ColumnHeaderEnumFilter.js.map +1 -1
  313. package/dist/components/TanStackTable/TableBody.js.map +1 -1
  314. package/dist/components/TeamSubjectsSelector/TeamSubjectsSelector.js.map +1 -1
  315. package/dist/components/TextField/TextField.js.map +1 -1
  316. package/dist/components/TimelinePlot/TimelinePhase.js.map +1 -1
  317. package/dist/components/TimelinePlot/TimelinePlot.js.map +1 -1
  318. package/dist/components/TimelinePlot/TimelinePlotSpeciesSelector.js.map +1 -1
  319. package/dist/components/UserCard/Avatar.js.map +1 -1
  320. package/dist/components/UserCardList/UserCardList.js.map +1 -1
  321. package/dist/components/UserCardList/UserCardListGroups/UserCardListGroups.Mobile.js.map +1 -1
  322. package/dist/components/UserCardList/UserCardListRotate.js.map +1 -1
  323. package/dist/components/UserOrTeamBadge/useUserOrTeam.js.map +1 -1
  324. package/dist/components/UserProfileLinks/UserProjects.js.map +1 -1
  325. package/dist/components/UserSearchBox/UserSearchBox.js.map +1 -1
  326. package/dist/components/Webhook/WebhookDashboard.js.map +1 -1
  327. package/dist/components/WikiMarkdownEditor/WikiMarkdownEditor.js.map +1 -1
  328. package/dist/components/WikiMarkdownEditorButton/WikiMarkdownEditorButton.js.map +1 -1
  329. package/dist/components/dataaccess/AccessApprovalsTable.js.map +1 -1
  330. package/dist/components/dataaccess/AccessRequestSubmissionTable.js.map +1 -1
  331. package/dist/components/dataaccess/SubmissionPage/SubmissionPage.js.map +1 -1
  332. package/dist/components/dataaccess/UseAccessRequirementTable.js.map +1 -1
  333. package/dist/components/dataaccess/UserAccessRequestHistory/UserAccessRequestHistoryTable.js.map +1 -1
  334. package/dist/components/doi/CreateOrUpdateDoiModal.js.map +1 -1
  335. package/dist/components/entity/page/CreatedByModifiedBy.js.map +1 -1
  336. package/dist/components/entity/page/action_menu/EntityActionMenu.js.map +1 -1
  337. package/dist/components/entity/page/title_bar/useDataCiteUsage.js.map +1 -1
  338. package/dist/components/entity/page/title_bar/useGetMentions.js.map +1 -1
  339. package/dist/components/error/ErrorPage.js.map +1 -1
  340. package/dist/components/favorites/FavoritesPage.js.map +1 -1
  341. package/dist/components/file/upload/BasicFileHandleUpload.js.map +1 -1
  342. package/dist/components/layout/SWCHeader.d.ts +9 -0
  343. package/dist/components/layout/SWCHeader.d.ts.map +1 -0
  344. package/dist/components/layout/SWCHeader.js +19 -0
  345. package/dist/components/layout/SWCHeader.js.map +1 -0
  346. package/dist/components/layout/SWCPageLayout.d.ts +9 -0
  347. package/dist/components/layout/SWCPageLayout.d.ts.map +1 -0
  348. package/dist/components/layout/SWCPageLayout.js +14 -0
  349. package/dist/components/layout/SWCPageLayout.js.map +1 -0
  350. package/dist/components/menu/ComplexMenu.js.map +1 -1
  351. package/dist/components/row_renderers/utils/ChipContainer.js.map +1 -1
  352. package/dist/components/styled/StyledPopover.js.map +1 -1
  353. package/dist/components/table/CsvPreview/CsvPreview.js +2 -1
  354. package/dist/components/table/CsvPreview/CsvPreview.js.map +1 -1
  355. package/dist/components/table/CsvPreview/CsvPreviewDialog.js.map +1 -1
  356. package/dist/components/trash/TrashCanList.js.map +1 -1
  357. package/dist/components/widgets/FileHandleLink.js.map +1 -1
  358. package/dist/components/widgets/RangeSlider/RangeSlider.js.map +1 -1
  359. package/dist/components/widgets/SynapseVideo.js.map +1 -1
  360. package/dist/components/widgets/facet-nav/FacetNavPanel.js.map +1 -1
  361. package/dist/components/widgets/facet-nav/PlotsContainer.js.map +1 -1
  362. package/dist/components/widgets/facet-nav/SelectionCriteriaPills.js.map +1 -1
  363. package/dist/components/widgets/facet-nav/useFacetPlots.js.map +1 -1
  364. package/dist/components/widgets/query-filter/CombinedRangeFacetFilter.js.map +1 -1
  365. package/dist/components/widgets/query-filter/EnumFacetFilter/EnumFacetFilter.js.map +1 -1
  366. package/dist/components/widgets/query-filter/FacetFilterControls.js.map +1 -1
  367. package/dist/components/widgets/query-filter/RangeFacetFilter.js.map +1 -1
  368. package/dist/components/widgets/query-filter/RangeFacetFilterUI.js.map +1 -1
  369. package/dist/features/curator/GridPage/components/GridPageTitle.d.ts.map +1 -1
  370. package/dist/features/curator/GridPage/components/GridPageTitle.js +23 -30
  371. package/dist/features/curator/GridPage/components/GridPageTitle.js.map +1 -1
  372. package/dist/features/curator/dashboard/CuratorDashboard.d.ts +2 -0
  373. package/dist/features/curator/dashboard/CuratorDashboard.d.ts.map +1 -0
  374. package/dist/features/curator/dashboard/CuratorDashboard.js +45 -0
  375. package/dist/features/curator/dashboard/CuratorDashboard.js.map +1 -0
  376. package/dist/features/curator/dashboard/components/CurationTaskCard.css +1 -0
  377. package/dist/features/curator/dashboard/components/CurationTaskCard.d.ts +9 -0
  378. package/dist/features/curator/dashboard/components/CurationTaskCard.d.ts.map +1 -0
  379. package/dist/features/curator/dashboard/components/CurationTaskCard.js +106 -0
  380. package/dist/features/curator/dashboard/components/CurationTaskCard.js.map +1 -0
  381. package/dist/features/curator/dashboard/components/CurationTaskCard.module.js +12 -0
  382. package/dist/features/curator/dashboard/components/CurationTaskCard.module.js.map +1 -0
  383. package/dist/features/curator/dashboard/components/CurationTaskCard.module.scss +52 -0
  384. package/dist/features/curator/dashboard/components/NextStepButton.css +1 -0
  385. package/dist/features/curator/dashboard/components/NextStepButton.d.ts +14 -0
  386. package/dist/features/curator/dashboard/components/NextStepButton.d.ts.map +1 -0
  387. package/dist/features/curator/dashboard/components/NextStepButton.js +35 -0
  388. package/dist/features/curator/dashboard/components/NextStepButton.js.map +1 -0
  389. package/dist/features/curator/dashboard/components/NextStepButton.module.js +11 -0
  390. package/dist/features/curator/dashboard/components/NextStepButton.module.js.map +1 -0
  391. package/dist/features/curator/dashboard/components/NextStepButton.module.scss +57 -0
  392. package/dist/features/curator/dashboard/components/UserOrTeamChip.css +1 -1
  393. package/dist/features/curator/dashboard/components/UserOrTeamChip.module.js +1 -1
  394. package/dist/features/curator/dashboard/components/UserOrTeamChip.module.js.map +1 -1
  395. package/dist/features/curator/dashboard/components/UserOrTeamChip.module.scss +5 -5
  396. package/dist/features/curator/dashboard/components/shared.css +1 -0
  397. package/dist/features/curator/dashboard/components/shared.module.js +5 -0
  398. package/dist/features/curator/dashboard/components/shared.module.js.map +1 -0
  399. package/dist/features/curator/dashboard/components/shared.module.scss +8 -0
  400. package/dist/features/entity/metadata-task/components/MetadataTaskTableActionCell.d.ts +0 -2
  401. package/dist/features/entity/metadata-task/components/MetadataTaskTableActionCell.d.ts.map +1 -1
  402. package/dist/features/entity/metadata-task/components/MetadataTaskTableActionCell.js +16 -34
  403. package/dist/features/entity/metadata-task/components/MetadataTaskTableActionCell.js.map +1 -1
  404. package/dist/features/entity/metadata-task/components/MetadataTasksTableAssigneeCell.js.map +1 -1
  405. package/dist/features/entity/metadata-task/hooks/useGetOrCreateGridSessionForSource.js.map +1 -1
  406. package/dist/features/entity/metadata-task/hooks/useGridSessionForCurationTask.js.map +1 -1
  407. package/dist/features/entity/metadata-task/hooks/useGridSessionForCurationTask_legacy.js.map +1 -1
  408. package/dist/features/entity/metadata-task/hooks/useMetadataTaskTable.js +1 -1
  409. package/dist/features/entity/metadata-task/hooks/useMetadataTaskTable.js.map +1 -1
  410. package/dist/features/entity/metadata-task/hooks/useOpenCuratorButton.d.ts +10 -0
  411. package/dist/features/entity/metadata-task/hooks/useOpenCuratorButton.d.ts.map +1 -0
  412. package/dist/features/entity/metadata-task/hooks/useOpenCuratorButton.js +37 -0
  413. package/dist/features/entity/metadata-task/hooks/useOpenCuratorButton.js.map +1 -0
  414. package/dist/features/entity/metadata-task/utils/constants.d.ts +5 -0
  415. package/dist/features/entity/metadata-task/utils/constants.d.ts.map +1 -0
  416. package/dist/features/entity/metadata-task/utils/constants.js +6 -0
  417. package/dist/features/entity/metadata-task/utils/constants.js.map +1 -0
  418. package/dist/mocks/challenge/mockChallenge.js.map +1 -1
  419. package/dist/mocks/entity/mockDataset.js.map +1 -1
  420. package/dist/mocks/entity/mockDatasetCollection.js.map +1 -1
  421. package/dist/mocks/entity/mockFileEntity.js.map +1 -1
  422. package/dist/mocks/entity/mockFileView.js.map +1 -1
  423. package/dist/mocks/entity/mockGeneratedEntityData.js.map +1 -1
  424. package/dist/mocks/entity/mockProject.js.map +1 -1
  425. package/dist/mocks/entity/mockProjectView.js.map +1 -1
  426. package/dist/mocks/entity/mockRootEntity.js.map +1 -1
  427. package/dist/mocks/entity/mockTableEntity.js.map +1 -1
  428. package/dist/mocks/mockWiki.js.map +1 -1
  429. package/dist/mocks/msw/handlers/asyncJobHandlers.js.map +1 -1
  430. package/dist/mocks/msw/handlers/challengeHandlers.js.map +1 -1
  431. package/dist/mocks/msw/handlers/changePasswordHandlers.js.map +1 -1
  432. package/dist/mocks/msw/handlers/discussionHandlers.js.map +1 -1
  433. package/dist/mocks/msw/handlers/entityHandlers.js.map +1 -1
  434. package/dist/mocks/msw/handlers/fileHandlers.js.map +1 -1
  435. package/dist/mocks/msw/handlers/gridHandlers.js.map +1 -1
  436. package/dist/mocks/msw/handlers/personalAccessTokenHandlers.js.map +1 -1
  437. package/dist/mocks/msw/handlers/subscriptionHandlers.js.map +1 -1
  438. package/dist/mocks/msw/handlers/teamHandlers.js.map +1 -1
  439. package/dist/mocks/msw/handlers/userProfileHandlers.js.map +1 -1
  440. package/dist/mocks/msw/handlers/wikiHandlers.js.map +1 -1
  441. package/dist/mocks/provenance/mockActivity.js.map +1 -1
  442. package/dist/mocks/query/mockReleaseCardsTableQueryResultBundle.js.map +1 -1
  443. package/dist/ror-client/index.js.map +1 -1
  444. package/dist/style/components/_cards.scss +4 -0
  445. package/dist/style/components/_data-grid-extra.css +1 -1
  446. package/dist/style/components/_data-grid-extra.scss +2 -0
  447. package/dist/style/main.css +1 -1
  448. package/dist/synapse-client/HttpClient.js.map +1 -1
  449. package/dist/synapse-client/SynapseClient.js.map +1 -1
  450. package/dist/synapse-queries/QueryMatching.test-utils.js.map +1 -1
  451. package/dist/synapse-queries/auth/useTwoFactorEnrollment.js.map +1 -1
  452. package/dist/synapse-queries/curation/task/useCurationTask.d.ts +1 -1
  453. package/dist/synapse-queries/curation/task/useCurationTask.d.ts.map +1 -1
  454. package/dist/synapse-queries/curation/task/useCurationTask.js +1 -1
  455. package/dist/synapse-queries/curation/task/useCurationTask.js.map +1 -1
  456. package/dist/synapse-queries/dataaccess/useRestrictionInformation.js.map +1 -1
  457. package/dist/synapse-queries/doi/useDOI.js.map +1 -1
  458. package/dist/synapse-queries/download/useDownloadList.js.map +1 -1
  459. package/dist/synapse-queries/entity/useEntity.js.map +1 -1
  460. package/dist/synapse-queries/entity/useEntityBundle.js.map +1 -1
  461. package/dist/synapse-queries/entity/useExportTableQueryToAnalysisPlatform.js.map +1 -1
  462. package/dist/synapse-queries/entity/useExportToTerra.js.map +1 -1
  463. package/dist/synapse-queries/entity/useGetQueryResultBundle.js.map +1 -1
  464. package/dist/synapse-queries/entity/useSchema.js.map +1 -1
  465. package/dist/synapse-queries/file/UploadToS3.js.map +1 -1
  466. package/dist/synapse-queries/file/useDirectUploadToS3.js.map +1 -1
  467. package/dist/synapse-queries/file/useFiles.js.map +1 -1
  468. package/dist/synapse-queries/forum/useReply.js.map +1 -1
  469. package/dist/synapse-queries/forum/useThread.js.map +1 -1
  470. package/dist/synapse-queries/grid/useEstablishWebsocketConnection.d.ts +2 -0
  471. package/dist/synapse-queries/grid/useEstablishWebsocketConnection.d.ts.map +1 -1
  472. package/dist/synapse-queries/grid/useEstablishWebsocketConnection.js.map +1 -1
  473. package/dist/synapse-queries/grid/useExportGrid.js.map +1 -1
  474. package/dist/synapse-queries/grid/useGridSession.js.map +1 -1
  475. package/dist/synapse-queries/grid/useImportCsvIntoGrid.js.map +1 -1
  476. package/dist/synapse-queries/subscription/useSubscription.js.map +1 -1
  477. package/dist/synapse-queries/table/useGetCsvPreview.js.map +1 -1
  478. package/dist/synapse-queries/table/useTableUpdateTransaction.js.map +1 -1
  479. package/dist/synapse-queries/team/useTeamMembers.js.map +1 -1
  480. package/dist/synapse-queries/user/useGetUserChallenges.js.map +1 -1
  481. package/dist/synapse-queries/user/useUserBundle.js.map +1 -1
  482. package/dist/synapse-queries/user/useUserGroupHeader.js.map +1 -1
  483. package/dist/testutils/ReactQueryMockUtils.js.map +1 -1
  484. package/dist/theme/ThemeProvider.js.map +1 -1
  485. package/dist/tsconfig.build.tsbuildinfo +1 -1
  486. package/dist/utils/AppUtils/session/SynapseSessionManager.js.map +1 -1
  487. package/dist/utils/AppUtils/session/useSessionManager.js.map +1 -1
  488. package/dist/utils/PermissionLevelToAccessType.js.map +1 -1
  489. package/dist/utils/challenge/evaluation/EvaluationUtils.js.map +1 -1
  490. package/dist/utils/context/SynapseContext.js.map +1 -1
  491. package/dist/utils/functions/AccessControlListUtils.d.ts +4 -0
  492. package/dist/utils/functions/AccessControlListUtils.d.ts.map +1 -1
  493. package/dist/utils/functions/AccessControlListUtils.js +12 -1
  494. package/dist/utils/functions/AccessControlListUtils.js.map +1 -1
  495. package/dist/utils/functions/GridApiUtils.js.map +1 -1
  496. package/dist/utils/functions/QueryFilterUtils.js.map +1 -1
  497. package/dist/utils/functions/RealmUtils.d.ts +4 -0
  498. package/dist/utils/functions/RealmUtils.d.ts.map +1 -1
  499. package/dist/utils/functions/RealmUtils.js +9 -3
  500. package/dist/utils/functions/RealmUtils.js.map +1 -1
  501. package/dist/utils/functions/SanitizeHtmlUtils.js.map +1 -1
  502. package/dist/utils/functions/SanitizeHtmlUtils.test-utils.js.map +1 -1
  503. package/dist/utils/functions/SqlFunctions.js.map +1 -1
  504. package/dist/utils/functions/StringUtils.js.map +1 -1
  505. package/dist/utils/functions/deepLinkingUtils.js.map +1 -1
  506. package/dist/utils/functions/getDataFromFromStorage.js.map +1 -1
  507. package/dist/utils/functions/getEndpoint.js.map +1 -1
  508. package/dist/utils/functions/getUserData.js.map +1 -1
  509. package/dist/utils/functions/queryUtils.js.map +1 -1
  510. package/dist/utils/functions/testDownloadSpeed.js.map +1 -1
  511. package/dist/utils/hooks/useConfirmItems.js.map +1 -1
  512. package/dist/utils/hooks/useCookiePreferences.js.map +1 -1
  513. package/dist/utils/hooks/useCreateShortUrl.js.map +1 -1
  514. package/dist/utils/hooks/useDetectSSOCode.js.map +1 -1
  515. package/dist/utils/hooks/useDirectDownloadHandler.js.map +1 -1
  516. package/dist/utils/hooks/useGetGoalData.js.map +1 -1
  517. package/dist/utils/hooks/useGetInfoFromIds.js.map +1 -1
  518. package/dist/utils/hooks/useImageUrlUtils.js.map +1 -1
  519. package/dist/utils/hooks/useImmutableTableQuery/useImmutableTableQuery.js.map +1 -1
  520. package/dist/utils/hooks/useImmutableTableQuery/useTableQueryReducer.js.map +1 -1
  521. package/dist/utils/hooks/useIsBot.js.map +1 -1
  522. package/dist/utils/hooks/useListState.js.map +1 -1
  523. package/dist/utils/hooks/useLogin.d.ts.map +1 -1
  524. package/dist/utils/hooks/useLogin.js +53 -52
  525. package/dist/utils/hooks/useLogin.js.map +1 -1
  526. package/dist/utils/hooks/useMutuallyExclusiveState.js.map +1 -1
  527. package/dist/utils/hooks/useOverlay.js.map +1 -1
  528. package/dist/utils/hooks/usePreFetchResource.js.map +1 -1
  529. package/dist/utils/hooks/useQuerySearchParam.js.map +1 -1
  530. package/dist/utils/hooks/useScrollFadeTransition.js.map +1 -1
  531. package/dist/utils/hooks/useSet.js.map +1 -1
  532. package/dist/utils/hooks/useSourceAppConfigs.js.map +1 -1
  533. package/dist/utils/hooks/useTableImageUrl.js.map +1 -1
  534. package/dist/utils/hooks/useUploadFileEntity/useCreatePathsAndGetParentId.js.map +1 -1
  535. package/dist/utils/hooks/useUploadFileEntity/useLinkFileEntityToURL.js.map +1 -1
  536. package/dist/utils/hooks/useUploadFileEntity/usePrepareFileEntityUpload.js.map +1 -1
  537. package/dist/utils/hooks/useUploadFileEntity/useTrackFileUploads.js.map +1 -1
  538. package/dist/utils/hooks/useUploadFileEntity/useUploadFileEntities.js.map +1 -1
  539. package/dist/utils/hooks/useUploadFileEntity/useUploadFiles.js.map +1 -1
  540. package/dist/utils/hooks/useUploadFileEntity/willUploadsExceedStorageLimit.js.map +1 -1
  541. package/dist/utils/html/TargetEnum.js.map +1 -1
  542. package/dist/utils/jsonschema/SchemaAnnotationUtils.js.map +1 -1
  543. package/package.json +4 -4
@@ -1 +1 @@
1
- {"version":3,"file":"useNotifyNewACLUsers.js","names":[],"sources":["../../../src/components/EntityAclEditor/useNotifyNewACLUsers.ts"],"sourcesContent":["import {\n useGetCurrentUserProfile,\n useGetUserGroupHeaders,\n useSendMessage,\n} from '@/synapse-queries'\nimport { useGetRealmPrincipals } from '@/synapse-queries/realm/useRealmPrincipals'\nimport {\n ResourceAccess,\n UserGroupHeader,\n} from '@sage-bionetworks/synapse-types'\nimport { useCallback } from 'react'\nimport { displayToast } from '../ToastMessage'\n\ntype UseNotifyNewACLUsersOptions = {\n subject: string\n body: string\n initialResourceAccessList: ResourceAccess[]\n newResourceAccessList: ResourceAccess[]\n}\n\nexport function shouldNotifyUserInNewResourceAccess(\n principalId: number,\n initialResourceAccessList: ResourceAccess[],\n userGroupHeader: UserGroupHeader,\n currentUserId: string,\n publicPrincipalIds: string[],\n): boolean {\n const isInInitialResourceAccess = initialResourceAccessList.some(\n initialResourceAccess => principalId === initialResourceAccess.principalId,\n )\n const isIndividual = userGroupHeader.isIndividual\n const isCurrentUser = String(principalId) === currentUserId\n const isPublic = publicPrincipalIds.includes(String(principalId))\n\n return (\n !isInInitialResourceAccess && // Is not in the initial list\n isIndividual && // Is an individual, not a team (SWC-1195)\n !isCurrentUser && // do not notify the current user (SWC-5576)\n !isPublic // never try to notify all/public users\n )\n}\n\nexport default function useNotifyNewACLUsers(\n options: UseNotifyNewACLUsersOptions,\n) {\n const { subject, body, initialResourceAccessList, newResourceAccessList } =\n options\n\n const { data } = useGetRealmPrincipals()\n const realmPrincipals = data || {}\n const {\n authenticatedUsers: authenticatedUsersId,\n publicGroup: publicGroupId,\n anonymousUser: anonymousUserId,\n } = realmPrincipals\n const publicPrincipalIds = [\n authenticatedUsersId,\n publicGroupId,\n anonymousUserId,\n ].filter((id): id is string => id !== undefined)\n\n const { data: currentUserProfile, isLoading: isLoadingCurrentUserProfile } =\n useGetCurrentUserProfile()\n const { data: userGroupHeaders, isLoading: isLoadingUserGroupHeaders } =\n useGetUserGroupHeaders(\n newResourceAccessList.map(ra => String(ra.principalId)),\n )\n const isLoading = isLoadingCurrentUserProfile || isLoadingUserGroupHeaders\n\n const { mutate: sendMessage, isPending } = useSendMessage({\n onError: error => {\n displayToast(`New users couldn't be notified: ${error.reason}`)\n },\n })\n\n const sendNotification = useCallback(() => {\n if (isLoading) {\n console.error(\n 'Attempted to send notification before user profile or user group headers were loaded. This should never happen.',\n )\n return\n }\n const usersToNotify = newResourceAccessList\n .filter(newResourceAccess => {\n const userGroupHeader = userGroupHeaders!.find(\n ugh => ugh.ownerId === String(newResourceAccess.principalId),\n )!\n return shouldNotifyUserInNewResourceAccess(\n newResourceAccess.principalId,\n initialResourceAccessList,\n userGroupHeader,\n currentUserProfile!.ownerId,\n publicPrincipalIds,\n )\n })\n .map(ra => String(ra.principalId))\n\n if (usersToNotify.length > 0) {\n sendMessage({\n subject,\n body,\n recipients: usersToNotify,\n })\n }\n }, [\n body,\n currentUserProfile,\n initialResourceAccessList,\n isLoading,\n newResourceAccessList,\n publicPrincipalIds,\n sendMessage,\n subject,\n userGroupHeaders,\n ])\n\n return {\n sendNotification,\n isPending,\n isLoading,\n }\n}\n"],"mappings":";;;;;;;;;AAoBA,SAAgB,EACd,GACA,GACA,GACA,GACA,GACS;CACT,IAAM,IAA4B,EAA0B,MAC1D,MAAyB,MAAgB,EAAsB,YAChE,EACK,IAAe,EAAgB,cAC/B,IAAgB,OAAO,EAAY,KAAK,GACxC,IAAW,EAAmB,SAAS,OAAO,EAAY,CAAC;AAEjE,QACE,CAAC,KACD,KACA,CAAC,KACD,CAAC;;AAIL,SAAwB,EACtB,GACA;CACA,IAAM,EAAE,YAAS,SAAM,8BAA2B,6BAChD,GAEI,EAAE,YAAS,GAAuB,EAElC,EACJ,oBAAoB,GACpB,aAAa,GACb,eAAe,MAJO,KAAQ,EAAE,EAM5B,IAAqB;EACzB;EACA;EACA;EACD,CAAC,QAAQ,MAAqB,MAAO,KAAA,EAAU,EAE1C,EAAE,MAAM,GAAoB,WAAW,MAC3C,GAA0B,EACtB,EAAE,MAAM,GAAkB,WAAW,MACzC,EACE,EAAsB,KAAI,MAAM,OAAO,EAAG,YAAY,CAAC,CACxD,EACG,IAAY,KAA+B,GAE3C,EAAE,QAAQ,GAAa,iBAAc,EAAe,EACxD,UAAS,MAAS;AAChB,IAAa,mCAAmC,EAAM,SAAS;IAElE,CAAC;AA2CF,QAAO;EACL,kBA1CuB,QAAkB;AACzC,OAAI,GAAW;AACb,YAAQ,MACN,kHACD;AACD;;GAEF,IAAM,IAAgB,EACnB,QAAO,MAAqB;IAC3B,IAAM,IAAkB,EAAkB,MACxC,MAAO,EAAI,YAAY,OAAO,EAAkB,YAAY,CAC7D;AACD,WAAO,EACL,EAAkB,aAClB,GACA,GACA,EAAoB,SACpB,EACD;KACD,CACD,KAAI,MAAM,OAAO,EAAG,YAAY,CAAC;AAEpC,GAAI,EAAc,SAAS,KACzB,EAAY;IACV;IACA;IACA,YAAY;IACb,CAAC;KAEH;GACD;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACD,CAAC;EAIA;EACA;EACD"}
1
+ {"version":3,"file":"useNotifyNewACLUsers.js","names":[],"sources":["../../../src/components/EntityAclEditor/useNotifyNewACLUsers.ts"],"sourcesContent":["import {\n useGetCurrentUserProfile,\n useGetUserGroupHeaders,\n useSendMessage,\n} from '@/synapse-queries'\nimport { useGetRealmPrincipals } from '@/synapse-queries/realm/useRealmPrincipals'\nimport {\n ResourceAccess,\n UserGroupHeader,\n} from '@sage-bionetworks/synapse-types'\nimport { useCallback } from 'react'\nimport { displayToast } from '../ToastMessage'\n\ntype UseNotifyNewACLUsersOptions = {\n subject: string\n body: string\n initialResourceAccessList: ResourceAccess[]\n newResourceAccessList: ResourceAccess[]\n}\n\nexport function shouldNotifyUserInNewResourceAccess(\n principalId: number,\n initialResourceAccessList: ResourceAccess[],\n userGroupHeader: UserGroupHeader,\n currentUserId: string,\n publicPrincipalIds: string[],\n): boolean {\n const isInInitialResourceAccess = initialResourceAccessList.some(\n initialResourceAccess => principalId === initialResourceAccess.principalId,\n )\n const isIndividual = userGroupHeader.isIndividual\n const isCurrentUser = String(principalId) === currentUserId\n const isPublic = publicPrincipalIds.includes(String(principalId))\n\n return (\n !isInInitialResourceAccess && // Is not in the initial list\n isIndividual && // Is an individual, not a team (SWC-1195)\n !isCurrentUser && // do not notify the current user (SWC-5576)\n !isPublic // never try to notify all/public users\n )\n}\n\nexport default function useNotifyNewACLUsers(\n options: UseNotifyNewACLUsersOptions,\n) {\n const { subject, body, initialResourceAccessList, newResourceAccessList } =\n options\n\n const { data } = useGetRealmPrincipals()\n const realmPrincipals = data || {}\n const {\n authenticatedUsers: authenticatedUsersId,\n publicGroup: publicGroupId,\n anonymousUser: anonymousUserId,\n } = realmPrincipals\n const publicPrincipalIds = [\n authenticatedUsersId,\n publicGroupId,\n anonymousUserId,\n ].filter((id): id is string => id !== undefined)\n\n const { data: currentUserProfile, isLoading: isLoadingCurrentUserProfile } =\n useGetCurrentUserProfile()\n const { data: userGroupHeaders, isLoading: isLoadingUserGroupHeaders } =\n useGetUserGroupHeaders(\n newResourceAccessList.map(ra => String(ra.principalId)),\n )\n const isLoading = isLoadingCurrentUserProfile || isLoadingUserGroupHeaders\n\n const { mutate: sendMessage, isPending } = useSendMessage({\n onError: error => {\n displayToast(`New users couldn't be notified: ${error.reason}`)\n },\n })\n\n const sendNotification = useCallback(() => {\n if (isLoading) {\n console.error(\n 'Attempted to send notification before user profile or user group headers were loaded. This should never happen.',\n )\n return\n }\n const usersToNotify = newResourceAccessList\n .filter(newResourceAccess => {\n const userGroupHeader = userGroupHeaders!.find(\n ugh => ugh.ownerId === String(newResourceAccess.principalId),\n )!\n return shouldNotifyUserInNewResourceAccess(\n newResourceAccess.principalId,\n initialResourceAccessList,\n userGroupHeader,\n currentUserProfile!.ownerId,\n publicPrincipalIds,\n )\n })\n .map(ra => String(ra.principalId))\n\n if (usersToNotify.length > 0) {\n sendMessage({\n subject,\n body,\n recipients: usersToNotify,\n })\n }\n }, [\n body,\n currentUserProfile,\n initialResourceAccessList,\n isLoading,\n newResourceAccessList,\n publicPrincipalIds,\n sendMessage,\n subject,\n userGroupHeaders,\n ])\n\n return {\n sendNotification,\n isPending,\n isLoading,\n }\n}\n"],"mappings":";;;;;;;;;AAoBA,SAAgB,EACd,GACA,GACA,GACA,GACA,GACS;CACT,IAAM,IAA4B,EAA0B,MAC1D,MAAyB,MAAgB,EAAsB,YAChE,EACK,IAAe,EAAgB,cAC/B,IAAgB,OAAO,EAAY,KAAK,GACxC,IAAW,EAAmB,SAAS,OAAO,EAAY,CAAC;AAEjE,QACE,CAAC,KACD,KACA,CAAC,KACD,CAAC;;AAIL,SAAwB,EACtB,GACA;CACA,IAAM,EAAE,YAAS,SAAM,8BAA2B,6BAChD,GAEI,EAAE,YAAS,GAAuB,EAElC,EACJ,oBAAoB,GACpB,aAAa,GACb,eAAe,MAJO,KAAQ,EAAE,EAM5B,IAAqB;EACzB;EACA;EACA;EACD,CAAC,QAAQ,MAAqB,MAAO,KAAA,EAAU,EAE1C,EAAE,MAAM,GAAoB,WAAW,MAC3C,GAA0B,EACtB,EAAE,MAAM,GAAkB,WAAW,MACzC,EACE,EAAsB,KAAI,MAAM,OAAO,EAAG,YAAY,CAAC,CACxD,EACG,IAAY,KAA+B,GAE3C,EAAE,QAAQ,GAAa,iBAAc,EAAe,EACxD,UAAS,MAAS;AAChB,IAAa,mCAAmC,EAAM,SAAS;IAElE,CAAC;AA2CF,QAAO;EACL,kBA1CuB,QAAkB;AACzC,OAAI,GAAW;AACb,YAAQ,MACN,kHACD;AACD;;GAEF,IAAM,IAAgB,EACnB,QAAO,MAAqB;IAC3B,IAAM,IAAkB,EAAkB,MACxC,MAAO,EAAI,YAAY,OAAO,EAAkB,YAAY,CAC7D;AACD,WAAO,EACL,EAAkB,aAClB,GACA,GACA,EAAoB,SACpB,EACD;KACD,CACD,KAAI,MAAM,OAAO,EAAG,YAAY,CAAC;AAEpC,GAAI,EAAc,SAAS,KACzB,EAAY;IACV;IACA;IACA,YAAY;IACb,CAAC;KAEH;GACD;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACD,CAGC;EACA;EACA;EACD"}
@@ -1 +1 @@
1
- {"version":3,"file":"EntityBadgeIcons.js","names":[],"sources":["../../../src/components/EntityBadgeIcons/EntityBadgeIcons.tsx"],"sourcesContent":["import {\n useDeleteEntity,\n useGetEntityBundle,\n useGetJson,\n useGetSchemaBinding,\n useGetValidationResults,\n} from '@/synapse-queries'\nimport { useGetRealmPrincipals } from '@/synapse-queries/realm/useRealmPrincipals'\nimport { isEntityPublic } from '@/utils/functions/AccessControlListUtils'\nimport {\n ChatBubbleTwoTone,\n CheckTwoTone,\n DescriptionTwoTone,\n LinkOffTwoTone,\n LocalOfferTwoTone,\n LockTwoTone,\n PublicTwoTone,\n} from '@mui/icons-material'\nimport { Tooltip } from '@mui/material'\nimport { EntityType } from '@sage-bionetworks/synapse-client'\nimport { ALL_ENTITY_BUNDLE_FIELDS } from '@sage-bionetworks/synapse-types'\nimport { isEmpty } from 'lodash-es'\nimport React, { useEffect, useState } from 'react'\nimport { useInView } from 'react-intersection-observer'\nimport { getDisplayedAnnotation } from '../entity/metadata/AnnotationsTable'\nimport { EntityModal } from '../entity/metadata/EntityModal'\nimport { HoverPopover } from '../styled/HoverPopover'\nimport WarningDialog from '../SynapseForm/WarningDialog'\n\nexport type EntityBadgeIconsProps = {\n entityId: string\n versionNumber?: number\n flexWrap?: // possible settings for flex-wrap\n | 'wrap'\n | 'nowrap'\n | '-moz-initial'\n | 'inherit'\n | 'initial'\n | 'revert'\n | 'unset'\n | 'wrap-reverse'\n justifyContent?: 'flex-start' | 'flex-end' | string\n /** Shows an icon indicating if the entity is 'public' or 'private'. Default true */\n showIsPublicPrivate?: boolean\n /** Shows an icon if the entity has sharing settings set on itself. Default true */\n showHasLocalSharingSettings?: boolean\n /** Shows an icon if the entity has annotations, or if it has a validation schema (in experimental mode only). Default true */\n showHasAnnotations?: boolean\n /** Shows an icon if the entity a wiki. Default true */\n showHasWiki?: boolean\n /** Shows an icon if the entity has been mentioned in discussion threads. Default true */\n showHasDiscussionThread?: boolean\n /* Shows an 'unlink' button if the entity is a link and the user has permission to delete it. Default true */\n showUnlink?: boolean\n /* Invoked after the entity is unlinked/deleted in case there is cleanup to do. Returns the entityId */\n onUnlink?: (entityId: string) => void\n onUnlinkError?: (error: unknown) => void\n /** Whether or not the badges (e.g. Annotations) can trigger opening a modal on click */\n canOpenModal: boolean\n}\n\n/**\n * Stateless component used to show icons that show an entity's status.\n * Adapted from https://github.com/Sage-Bionetworks/SynapseWebClient/blob/46b9b717636cda2421926d96365244bbb72a05b6/src/main/java/org/sagebionetworks/web/client/widget/entity/EntityBadge.java\n */\nexport const EntityBadgeIcons = (\n props: EntityBadgeIconsProps,\n): React.ReactNode => {\n const {\n entityId,\n versionNumber,\n flexWrap = 'nowrap',\n justifyContent = 'flex-start',\n showIsPublicPrivate = true,\n showHasLocalSharingSettings = true,\n showHasAnnotations = true,\n showHasWiki = true,\n showHasDiscussionThread = true,\n showUnlink = true,\n onUnlink = () => {\n /* noop */\n },\n onUnlinkError = () => {\n /* noop */\n },\n canOpenModal,\n } = props\n\n const { data } = useGetRealmPrincipals()\n const realmPrincipals = data || {}\n\n enum SchemaConformanceState {\n NO_SCHEMA = '', // or not in experimental mode\n VALID = 'Valid',\n INVALID = 'Invalid',\n ANNOTATIONS_MISSING = 'Missing',\n }\n\n const { ref, inView } = useInView()\n\n const { data: entityData } = useGetJson(entityId, versionNumber, true, {\n enabled: inView,\n })\n const annotations = entityData?.annotations\n const { data: bundle } = useGetEntityBundle(\n entityId,\n versionNumber,\n ALL_ENTITY_BUNDLE_FIELDS,\n {\n enabled: inView,\n },\n )\n const [showModal, setShowModal] = useState(false)\n const [showUnlinkConfirmModal, setShowUnlinkConfirmModal] = useState(false)\n const [schemaConformance, setSchemaConformance] = useState(\n SchemaConformanceState.NO_SCHEMA,\n )\n\n const { data: boundSchema } = useGetSchemaBinding(entityId, {\n enabled: inView,\n staleTime: 60 * 1000, // 60 seconds\n })\n\n const { data: schemaValidationResults } = useGetValidationResults(entityId, {\n enabled: inView && !!boundSchema,\n staleTime: 60 * 1000, // 60 seconds\n })\n\n const annotationsCount =\n annotations && !isEmpty(annotations) ? Object.keys(annotations).length : 0\n useEffect(() => {\n if (schemaValidationResults) {\n if (schemaValidationResults.isValid) {\n setSchemaConformance(SchemaConformanceState.VALID)\n } else if (annotationsCount) {\n // If annotations exist, then indicate that they are invalid\n setSchemaConformance(SchemaConformanceState.INVALID)\n } else {\n // If annotations are missing, it's still invalid, but should appear differently\n setSchemaConformance(SchemaConformanceState.ANNOTATIONS_MISSING)\n }\n }\n }, [\n schemaValidationResults,\n annotationsCount,\n annotations,\n SchemaConformanceState.VALID,\n SchemaConformanceState.INVALID,\n SchemaConformanceState.ANNOTATIONS_MISSING,\n ])\n\n const { mutate: unlinkEntity } = useDeleteEntity({\n onSuccess: (_, entityId) => {\n onUnlink(entityId)\n },\n onError: onUnlinkError,\n })\n\n /**\n * Convert the list of annotations to a string of <tr>...anno1</tr><tr>...anno2</tr>...\n * If there are no annotations, this is the empty string ('')\n */\n const annotationsTableRows = (\n <>\n {annotations\n ? Object.entries(annotations ?? []).map(([key, value]) => (\n <tr key={key}>\n <td>\n <b>{key}</b>\n </td>\n <td>\n {Array.isArray(value)\n ? value.map(getDisplayedAnnotation).join(', ')\n : getDisplayedAnnotation(value as string | number | boolean)}\n </td>\n </tr>\n ))\n : ''}\n </>\n )\n // We also show the schema name if there is one (and we're in experimental mode)\n const valiationSchemaTableRow = (\n <>\n {boundSchema ? (\n <tr>\n <td>\n <b>Validation Schema</b>\n </td>\n <td>{boundSchema.jsonSchemaVersionInfo.schemaName}</td>\n </tr>\n ) : (\n ''\n )}\n </>\n )\n const annotationsTitle = schemaValidationResults\n ? `${schemaConformance} Annotations`\n : ''\n const annotationsHtml = (\n <div className=\"EntityBadgeTooltip\">\n <table>\n <tbody>\n {annotationsTableRows ? annotationsTableRows : ''}\n {valiationSchemaTableRow}\n </tbody>\n </table>\n </div>\n )\n\n return (\n <div className=\"EntityBadge\" ref={ref} style={{ flexWrap, justifyContent }}>\n {bundle && (\n <>\n <div onClick={e => e.stopPropagation()}>\n <EntityModal\n entityId={entityId}\n show={showModal}\n showTabs={false}\n onClose={() => setShowModal(false)}\n initialTab={'ANNOTATIONS'}\n />\n </div>\n {showIsPublicPrivate &&\n bundle.benefactorAcl &&\n isEntityPublic(\n bundle.benefactorAcl.resourceAccess,\n realmPrincipals,\n ) ? (\n <Tooltip title=\"Public\" enterNextDelay={100} placement=\"right\">\n <PublicTwoTone\n aria-hidden={false}\n role=\"img\"\n className=\"EntityBadge__Badge\"\n data-testid={'is-public-icon'}\n />\n </Tooltip>\n ) : null}\n {showIsPublicPrivate &&\n bundle.benefactorAcl &&\n !isEntityPublic(\n bundle.benefactorAcl.resourceAccess,\n realmPrincipals,\n ) ? (\n <Tooltip title=\"Private\" enterNextDelay={100} placement=\"right\">\n <LockTwoTone\n aria-hidden={false}\n role=\"img\"\n className=\"EntityBadge__Badge\"\n data-testid={'is-private-icon'}\n />\n </Tooltip>\n ) : null}\n {showHasLocalSharingSettings &&\n bundle.benefactorAcl &&\n entityId === bundle.benefactorAcl.id ? (\n <Tooltip\n title=\"Sharing Settings have been set\"\n enterNextDelay={100}\n placement=\"right\"\n >\n <CheckTwoTone\n aria-hidden={false}\n role=\"img\"\n className=\"EntityBadge__Badge\"\n data-testid={'sharing-settings-icon'}\n />\n </Tooltip>\n ) : null}\n\n {showHasAnnotations &&\n !!(annotationsCount || schemaValidationResults) && (\n <HoverPopover\n title={annotationsTitle}\n popoverContent={annotationsHtml}\n placement=\"right\"\n maxWidth={500}\n actionButton={\n canOpenModal\n ? {\n content: 'Edit Annotations',\n onClick: () => setShowModal(true),\n closeOnClick: true,\n }\n : undefined\n }\n >\n <LocalOfferTwoTone\n aria-hidden={false}\n role={canOpenModal ? 'button' : 'img'}\n className={`EntityBadge__Badge ${schemaConformance}`}\n data-html={true}\n data-testid={'annotations-icon'}\n />\n </HoverPopover>\n )}\n {showHasWiki && bundle.rootWikiId && (\n <Tooltip title=\"Has a wiki\" enterNextDelay={100} placement=\"right\">\n <DescriptionTwoTone\n aria-hidden={false}\n role=\"img\"\n className=\"EntityBadge__Badge\"\n data-testid={'wiki-icon'}\n />\n </Tooltip>\n )}\n {showHasDiscussionThread &&\n !!bundle.threadCount &&\n !!(bundle.threadCount > 0) && (\n <Tooltip\n title=\"Has been mentioned in discussion\"\n enterNextDelay={100}\n placement=\"right\"\n >\n <ChatBubbleTwoTone\n aria-hidden={false}\n role=\"img\"\n className=\"EntityBadge__Badge\"\n data-testid={'discussion-icon'}\n />\n </Tooltip>\n )}\n {showUnlink &&\n bundle.entityType === EntityType.link &&\n bundle.permissions?.canDelete && (\n <>\n <WarningDialog\n open={showUnlinkConfirmModal}\n title=\"Confirm Unlink\"\n content={\n 'Are you sure you want to remove this link? The original object will not be changed.'\n }\n confirmButtonText=\"Unlink\"\n confirmButtonColor=\"error\"\n onConfirm={() => {\n unlinkEntity(entityId)\n setShowUnlinkConfirmModal(false)\n }}\n onCancel={() => {\n setShowUnlinkConfirmModal(false)\n }}\n />\n <Tooltip\n title=\"Remove this link\"\n enterNextDelay={100}\n placement=\"right\"\n >\n <LinkOffTwoTone\n aria-hidden={false}\n role=\"button\"\n onClick={() => setShowUnlinkConfirmModal(true)}\n className=\"EntityBadge__Badge Unlink\"\n data-testid={'unlink-icon'}\n />\n </Tooltip>\n </>\n )}\n </>\n )}\n </div>\n )\n}\n\nexport default EntityBadgeIcons\n"],"mappings":"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"}
1
+ {"version":3,"file":"EntityBadgeIcons.js","names":[],"sources":["../../../src/components/EntityBadgeIcons/EntityBadgeIcons.tsx"],"sourcesContent":["import {\n useDeleteEntity,\n useGetEntityBundle,\n useGetJson,\n useGetSchemaBinding,\n useGetValidationResults,\n} from '@/synapse-queries'\nimport { useGetRealmPrincipals } from '@/synapse-queries/realm/useRealmPrincipals'\nimport { isEntityPublic } from '@/utils/functions/AccessControlListUtils'\nimport {\n ChatBubbleTwoTone,\n CheckTwoTone,\n DescriptionTwoTone,\n LinkOffTwoTone,\n LocalOfferTwoTone,\n LockTwoTone,\n PublicTwoTone,\n} from '@mui/icons-material'\nimport { Tooltip } from '@mui/material'\nimport { EntityType } from '@sage-bionetworks/synapse-client'\nimport { ALL_ENTITY_BUNDLE_FIELDS } from '@sage-bionetworks/synapse-types'\nimport { isEmpty } from 'lodash-es'\nimport React, { useEffect, useState } from 'react'\nimport { useInView } from 'react-intersection-observer'\nimport { getDisplayedAnnotation } from '../entity/metadata/AnnotationsTable'\nimport { EntityModal } from '../entity/metadata/EntityModal'\nimport { HoverPopover } from '../styled/HoverPopover'\nimport WarningDialog from '../SynapseForm/WarningDialog'\n\nexport type EntityBadgeIconsProps = {\n entityId: string\n versionNumber?: number\n flexWrap?: // possible settings for flex-wrap\n | 'wrap'\n | 'nowrap'\n | '-moz-initial'\n | 'inherit'\n | 'initial'\n | 'revert'\n | 'unset'\n | 'wrap-reverse'\n justifyContent?: 'flex-start' | 'flex-end' | string\n /** Shows an icon indicating if the entity is 'public' or 'private'. Default true */\n showIsPublicPrivate?: boolean\n /** Shows an icon if the entity has sharing settings set on itself. Default true */\n showHasLocalSharingSettings?: boolean\n /** Shows an icon if the entity has annotations, or if it has a validation schema (in experimental mode only). Default true */\n showHasAnnotations?: boolean\n /** Shows an icon if the entity a wiki. Default true */\n showHasWiki?: boolean\n /** Shows an icon if the entity has been mentioned in discussion threads. Default true */\n showHasDiscussionThread?: boolean\n /* Shows an 'unlink' button if the entity is a link and the user has permission to delete it. Default true */\n showUnlink?: boolean\n /* Invoked after the entity is unlinked/deleted in case there is cleanup to do. Returns the entityId */\n onUnlink?: (entityId: string) => void\n onUnlinkError?: (error: unknown) => void\n /** Whether or not the badges (e.g. Annotations) can trigger opening a modal on click */\n canOpenModal: boolean\n}\n\n/**\n * Stateless component used to show icons that show an entity's status.\n * Adapted from https://github.com/Sage-Bionetworks/SynapseWebClient/blob/46b9b717636cda2421926d96365244bbb72a05b6/src/main/java/org/sagebionetworks/web/client/widget/entity/EntityBadge.java\n */\nexport const EntityBadgeIcons = (\n props: EntityBadgeIconsProps,\n): React.ReactNode => {\n const {\n entityId,\n versionNumber,\n flexWrap = 'nowrap',\n justifyContent = 'flex-start',\n showIsPublicPrivate = true,\n showHasLocalSharingSettings = true,\n showHasAnnotations = true,\n showHasWiki = true,\n showHasDiscussionThread = true,\n showUnlink = true,\n onUnlink = () => {\n /* noop */\n },\n onUnlinkError = () => {\n /* noop */\n },\n canOpenModal,\n } = props\n\n const { data } = useGetRealmPrincipals()\n const realmPrincipals = data || {}\n\n enum SchemaConformanceState {\n NO_SCHEMA = '', // or not in experimental mode\n VALID = 'Valid',\n INVALID = 'Invalid',\n ANNOTATIONS_MISSING = 'Missing',\n }\n\n const { ref, inView } = useInView()\n\n const { data: entityData } = useGetJson(entityId, versionNumber, true, {\n enabled: inView,\n })\n const annotations = entityData?.annotations\n const { data: bundle } = useGetEntityBundle(\n entityId,\n versionNumber,\n ALL_ENTITY_BUNDLE_FIELDS,\n {\n enabled: inView,\n },\n )\n const [showModal, setShowModal] = useState(false)\n const [showUnlinkConfirmModal, setShowUnlinkConfirmModal] = useState(false)\n const [schemaConformance, setSchemaConformance] = useState(\n SchemaConformanceState.NO_SCHEMA,\n )\n\n const { data: boundSchema } = useGetSchemaBinding(entityId, {\n enabled: inView,\n staleTime: 60 * 1000, // 60 seconds\n })\n\n const { data: schemaValidationResults } = useGetValidationResults(entityId, {\n enabled: inView && !!boundSchema,\n staleTime: 60 * 1000, // 60 seconds\n })\n\n const annotationsCount =\n annotations && !isEmpty(annotations) ? Object.keys(annotations).length : 0\n useEffect(() => {\n if (schemaValidationResults) {\n if (schemaValidationResults.isValid) {\n setSchemaConformance(SchemaConformanceState.VALID)\n } else if (annotationsCount) {\n // If annotations exist, then indicate that they are invalid\n setSchemaConformance(SchemaConformanceState.INVALID)\n } else {\n // If annotations are missing, it's still invalid, but should appear differently\n setSchemaConformance(SchemaConformanceState.ANNOTATIONS_MISSING)\n }\n }\n }, [\n schemaValidationResults,\n annotationsCount,\n annotations,\n SchemaConformanceState.VALID,\n SchemaConformanceState.INVALID,\n SchemaConformanceState.ANNOTATIONS_MISSING,\n ])\n\n const { mutate: unlinkEntity } = useDeleteEntity({\n onSuccess: (_, entityId) => {\n onUnlink(entityId)\n },\n onError: onUnlinkError,\n })\n\n /**\n * Convert the list of annotations to a string of <tr>...anno1</tr><tr>...anno2</tr>...\n * If there are no annotations, this is the empty string ('')\n */\n const annotationsTableRows = (\n <>\n {annotations\n ? Object.entries(annotations ?? []).map(([key, value]) => (\n <tr key={key}>\n <td>\n <b>{key}</b>\n </td>\n <td>\n {Array.isArray(value)\n ? value.map(getDisplayedAnnotation).join(', ')\n : getDisplayedAnnotation(value as string | number | boolean)}\n </td>\n </tr>\n ))\n : ''}\n </>\n )\n // We also show the schema name if there is one (and we're in experimental mode)\n const valiationSchemaTableRow = (\n <>\n {boundSchema ? (\n <tr>\n <td>\n <b>Validation Schema</b>\n </td>\n <td>{boundSchema.jsonSchemaVersionInfo.schemaName}</td>\n </tr>\n ) : (\n ''\n )}\n </>\n )\n const annotationsTitle = schemaValidationResults\n ? `${schemaConformance} Annotations`\n : ''\n const annotationsHtml = (\n <div className=\"EntityBadgeTooltip\">\n <table>\n <tbody>\n {annotationsTableRows ? annotationsTableRows : ''}\n {valiationSchemaTableRow}\n </tbody>\n </table>\n </div>\n )\n\n return (\n <div className=\"EntityBadge\" ref={ref} style={{ flexWrap, justifyContent }}>\n {bundle && (\n <>\n <div onClick={e => e.stopPropagation()}>\n <EntityModal\n entityId={entityId}\n show={showModal}\n showTabs={false}\n onClose={() => setShowModal(false)}\n initialTab={'ANNOTATIONS'}\n />\n </div>\n {showIsPublicPrivate &&\n bundle.benefactorAcl &&\n isEntityPublic(\n bundle.benefactorAcl.resourceAccess,\n realmPrincipals,\n ) ? (\n <Tooltip title=\"Public\" enterNextDelay={100} placement=\"right\">\n <PublicTwoTone\n aria-hidden={false}\n role=\"img\"\n className=\"EntityBadge__Badge\"\n data-testid={'is-public-icon'}\n />\n </Tooltip>\n ) : null}\n {showIsPublicPrivate &&\n bundle.benefactorAcl &&\n !isEntityPublic(\n bundle.benefactorAcl.resourceAccess,\n realmPrincipals,\n ) ? (\n <Tooltip title=\"Private\" enterNextDelay={100} placement=\"right\">\n <LockTwoTone\n aria-hidden={false}\n role=\"img\"\n className=\"EntityBadge__Badge\"\n data-testid={'is-private-icon'}\n />\n </Tooltip>\n ) : null}\n {showHasLocalSharingSettings &&\n bundle.benefactorAcl &&\n entityId === bundle.benefactorAcl.id ? (\n <Tooltip\n title=\"Sharing Settings have been set\"\n enterNextDelay={100}\n placement=\"right\"\n >\n <CheckTwoTone\n aria-hidden={false}\n role=\"img\"\n className=\"EntityBadge__Badge\"\n data-testid={'sharing-settings-icon'}\n />\n </Tooltip>\n ) : null}\n\n {showHasAnnotations &&\n !!(annotationsCount || schemaValidationResults) && (\n <HoverPopover\n title={annotationsTitle}\n popoverContent={annotationsHtml}\n placement=\"right\"\n maxWidth={500}\n actionButton={\n canOpenModal\n ? {\n content: 'Edit Annotations',\n onClick: () => setShowModal(true),\n closeOnClick: true,\n }\n : undefined\n }\n >\n <LocalOfferTwoTone\n aria-hidden={false}\n role={canOpenModal ? 'button' : 'img'}\n className={`EntityBadge__Badge ${schemaConformance}`}\n data-html={true}\n data-testid={'annotations-icon'}\n />\n </HoverPopover>\n )}\n {showHasWiki && bundle.rootWikiId && (\n <Tooltip title=\"Has a wiki\" enterNextDelay={100} placement=\"right\">\n <DescriptionTwoTone\n aria-hidden={false}\n role=\"img\"\n className=\"EntityBadge__Badge\"\n data-testid={'wiki-icon'}\n />\n </Tooltip>\n )}\n {showHasDiscussionThread &&\n !!bundle.threadCount &&\n !!(bundle.threadCount > 0) && (\n <Tooltip\n title=\"Has been mentioned in discussion\"\n enterNextDelay={100}\n placement=\"right\"\n >\n <ChatBubbleTwoTone\n aria-hidden={false}\n role=\"img\"\n className=\"EntityBadge__Badge\"\n data-testid={'discussion-icon'}\n />\n </Tooltip>\n )}\n {showUnlink &&\n bundle.entityType === EntityType.link &&\n bundle.permissions?.canDelete && (\n <>\n <WarningDialog\n open={showUnlinkConfirmModal}\n title=\"Confirm Unlink\"\n content={\n 'Are you sure you want to remove this link? The original object will not be changed.'\n }\n confirmButtonText=\"Unlink\"\n confirmButtonColor=\"error\"\n onConfirm={() => {\n unlinkEntity(entityId)\n setShowUnlinkConfirmModal(false)\n }}\n onCancel={() => {\n setShowUnlinkConfirmModal(false)\n }}\n />\n <Tooltip\n title=\"Remove this link\"\n enterNextDelay={100}\n placement=\"right\"\n >\n <LinkOffTwoTone\n aria-hidden={false}\n role=\"button\"\n onClick={() => setShowUnlinkConfirmModal(true)}\n className=\"EntityBadge__Badge Unlink\"\n data-testid={'unlink-icon'}\n />\n </Tooltip>\n </>\n )}\n </>\n )}\n </div>\n )\n}\n\nexport default EntityBadgeIcons\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"EntityCitation.js","names":[],"sources":["../../../src/components/EntityCitation/EntityCitation.tsx"],"sourcesContent":["import React from 'react'\nimport { ReactComponent as DoubleQuotes } from '@/assets/icons/DoubleQuotes.svg'\nimport { Button, Skeleton } from '@mui/material'\nimport { useGetDOIAssociation } from '@/synapse-queries/doi/useDOI'\nimport { useGetEntityBundle } from '@/synapse-queries/entity'\nimport { DoiObjectType } from '@sage-bionetworks/synapse-client'\nimport CitationPopoverContent from '../CitationPopover/CitationPopoverContent'\nimport { useRef, useState } from 'react'\nimport { useGetEntityDoiAssociation } from './EntityCitationUtils'\nimport DropdownSelect from '../DropdownSelect'\n\nexport type EntityCitationProps = {\n projectId: string\n entityId: string\n versionNumber?: number\n}\n\nconst EntityCitation = ({\n projectId,\n entityId,\n versionNumber,\n}: EntityCitationProps): React.ReactNode => {\n const { data: bundle, isLoading: isEntityLoading } = useGetEntityBundle(\n entityId,\n versionNumber,\n )\n const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null)\n const [selectedDoi, setSelectedDoi] = useState<string | undefined>(undefined)\n const [citationAnchorEl, setCitationAnchorEl] = useState<HTMLElement | null>(\n null,\n )\n const [selectedIndex, setSelectedIndex] = useState<number | undefined>(\n undefined,\n )\n const citationButtonRef = useRef<HTMLDivElement>(null)\n\n const open = Boolean(anchorEl)\n const id = open ? 'cite-as-popover' : undefined\n\n const entityDoiAssociation = useGetEntityDoiAssociation(\n entityId,\n versionNumber,\n projectId,\n bundle,\n )\n\n // Get DOI association for the project\n // Projects are not versioned\n const { data: projectDoiAssociation, isLoading: isProjectLoading } =\n useGetDOIAssociation(\n {\n id: projectId,\n version: undefined,\n type: DoiObjectType.ENTITY,\n },\n {\n enabled: !!projectId,\n },\n )\n\n // If both project and entity have DOIs, we show the dropdown variant\n const isProjectAndEntityDoi = projectDoiAssociation && entityDoiAssociation\n\n function getButtonText() {\n if (isProjectAndEntityDoi) {\n return 'Cite as...'\n } else if (entityDoiAssociation && !projectDoiAssociation) {\n return 'Cite page'\n } else if (!entityDoiAssociation && projectDoiAssociation) {\n return 'Cite project'\n }\n return ''\n }\n\n const buttonText = getButtonText()\n\n const handleButtonClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n if (entityDoiAssociation && !projectDoiAssociation) {\n setSelectedDoi(entityDoiAssociation.doiUri)\n setCitationAnchorEl(event.currentTarget)\n } else if (!entityDoiAssociation && projectDoiAssociation) {\n setSelectedDoi(projectDoiAssociation.doiUri)\n setCitationAnchorEl(event.currentTarget)\n } else {\n // If both project and entity doi exist, show dropdown\n setAnchorEl(event.currentTarget)\n }\n }\n\n const popover = (\n <CitationPopoverContent\n doi={selectedDoi}\n anchorEl={citationAnchorEl}\n open={!!citationAnchorEl && !!selectedDoi}\n id={id}\n onClose={() => {\n setCitationAnchorEl(null)\n setSelectedDoi(undefined)\n }}\n />\n )\n\n const options: string[] = ['Cite this Project', 'Cite only this page']\n\n if (!projectDoiAssociation && !entityDoiAssociation) {\n return null\n }\n\n if (isEntityLoading || isProjectLoading) {\n return (\n <Skeleton\n sx={{\n width: { xs: '100%', sm: '140px' },\n height: '45px',\n }}\n />\n )\n }\n\n return (\n <>\n {isProjectAndEntityDoi ? (\n <DropdownSelect\n disabled={isEntityLoading && isProjectLoading}\n options={options}\n anchorRef={citationButtonRef}\n sx={{\n width: { xs: '100%', sm: 'initial' },\n }}\n buttonText=\"Cite as...\"\n variant=\"outlined\"\n buttonGroupAriaLabel=\"Citation options\"\n selectedIndex={selectedIndex}\n setSelectedIndex={(index: number) => {\n setSelectedIndex(index)\n const selected =\n index === 0\n ? projectDoiAssociation?.doiUri\n : entityDoiAssociation?.doiUri\n if (selected) {\n setSelectedDoi(selected)\n setCitationAnchorEl(citationButtonRef.current)\n }\n }}\n />\n ) : (\n <Button\n onClick={handleButtonClick}\n disabled={isEntityLoading && isProjectLoading}\n sx={{\n width: { xs: '100%', sm: 'initial' },\n }}\n variant=\"outlined\"\n startIcon={<DoubleQuotes width={18} height={18} />}\n >\n {buttonText}\n </Button>\n )}\n {popover}\n </>\n )\n}\n\nexport default EntityCitation\n"],"mappings":";;;;;;;;;;;;AAiBA,IAAM,KAAkB,EACtB,cACA,aACA,uBAC0C;CAC1C,IAAM,EAAE,MAAM,GAAQ,WAAW,MAAoB,EACnD,GACA,EACD,EACK,CAAC,GAAU,KAAe,EAAmC,KAAK,EAClE,CAAC,GAAa,KAAkB,EAA6B,KAAA,EAAU,EACvE,CAAC,GAAkB,KAAuB,EAC9C,KACD,EACK,CAAC,GAAe,KAAoB,EACxC,KAAA,EACD,EACK,IAAoB,EAAuB,KAAK,EAGhD,IADe,IACH,oBAAoB,KAAA,GAEhC,IAAuB,EAC3B,GACA,GACA,GACA,EACD,EAIK,EAAE,MAAM,GAAuB,WAAW,MAC9C,EACE;EACE,IAAI;EACJ,SAAS,KAAA;EACT,MAAM,EAAc;EACrB,EACD,EACE,SAAS,CAAC,CAAC,GACZ,CACF,EAGG,IAAwB,KAAyB;CAEvD,SAAS,IAAgB;AAQvB,SAPI,IACK,eACE,KAAwB,CAAC,IAC3B,cACE,CAAC,KAAwB,IAC3B,iBAEF;;CAGT,IAAM,IAAa,GAAe;AA6ClC,QAfI,CAAC,KAAyB,CAAC,IACtB,OAGL,KAAmB,IAEnB,kBAAC,GAAD,EACE,IAAI;EACF,OAAO;GAAE,IAAI;GAAQ,IAAI;GAAS;EAClC,QAAQ;EACT,EACD,CAAA,GAKJ,kBAAA,GAAA,EAAA,UAAA,CACG,IACC,kBAAC,GAAD;EACE,UAAU,KAAmB;EACpB,SAtBS,CAAC,qBAAqB,sBAAsB;EAuB9D,WAAW;EACX,IAAI,EACF,OAAO;GAAE,IAAI;GAAQ,IAAI;GAAW,EACrC;EACD,YAAW;EACX,SAAQ;EACR,sBAAqB;EACN;EACf,mBAAmB,MAAkB;AACnC,KAAiB,EAAM;GACvB,IAAM,IACJ,MAAU,IACN,GAAuB,SACvB,GAAsB;AAC5B,GAAI,MACF,EAAe,EAAS,EACxB,EAAoB,EAAkB,QAAQ;;EAGlD,CAAA,GAEF,kBAAC,GAAD;EACE,UAvEmB,MAA+C;AACxE,GAAI,KAAwB,CAAC,KAC3B,EAAe,EAAqB,OAAO,EAC3C,EAAoB,EAAM,cAAc,IAC/B,CAAC,KAAwB,KAClC,EAAe,EAAsB,OAAO,EAC5C,EAAoB,EAAM,cAAc,IAGxC,EAAY,EAAM,cAAc;;EA+D5B,UAAU,KAAmB;EAC7B,IAAI,EACF,OAAO;GAAE,IAAI;GAAQ,IAAI;GAAW,EACrC;EACD,SAAQ;EACR,WAAW,kBAAC,GAAD;GAAc,OAAO;GAAI,QAAQ;GAAM,CAAA;YAEjD;EACM,CAAA,EAlEb,kBAAC,GAAD;EACE,KAAK;EACL,UAAU;EACV,MAAM,CAAC,CAAC,KAAoB,CAAC,CAAC;EAC1B;EACJ,eAAe;AAEb,GADA,EAAoB,KAAK,EACzB,EAAe,KAAA,EAAU;;EAE3B,CAAA,CA4DC,EAAA,CAAA"}
1
+ {"version":3,"file":"EntityCitation.js","names":[],"sources":["../../../src/components/EntityCitation/EntityCitation.tsx"],"sourcesContent":["import React from 'react'\nimport { ReactComponent as DoubleQuotes } from '@/assets/icons/DoubleQuotes.svg'\nimport { Button, Skeleton } from '@mui/material'\nimport { useGetDOIAssociation } from '@/synapse-queries/doi/useDOI'\nimport { useGetEntityBundle } from '@/synapse-queries/entity'\nimport { DoiObjectType } from '@sage-bionetworks/synapse-client'\nimport CitationPopoverContent from '../CitationPopover/CitationPopoverContent'\nimport { useRef, useState } from 'react'\nimport { useGetEntityDoiAssociation } from './EntityCitationUtils'\nimport DropdownSelect from '../DropdownSelect'\n\nexport type EntityCitationProps = {\n projectId: string\n entityId: string\n versionNumber?: number\n}\n\nconst EntityCitation = ({\n projectId,\n entityId,\n versionNumber,\n}: EntityCitationProps): React.ReactNode => {\n const { data: bundle, isLoading: isEntityLoading } = useGetEntityBundle(\n entityId,\n versionNumber,\n )\n const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null)\n const [selectedDoi, setSelectedDoi] = useState<string | undefined>(undefined)\n const [citationAnchorEl, setCitationAnchorEl] = useState<HTMLElement | null>(\n null,\n )\n const [selectedIndex, setSelectedIndex] = useState<number | undefined>(\n undefined,\n )\n const citationButtonRef = useRef<HTMLDivElement>(null)\n\n const open = Boolean(anchorEl)\n const id = open ? 'cite-as-popover' : undefined\n\n const entityDoiAssociation = useGetEntityDoiAssociation(\n entityId,\n versionNumber,\n projectId,\n bundle,\n )\n\n // Get DOI association for the project\n // Projects are not versioned\n const { data: projectDoiAssociation, isLoading: isProjectLoading } =\n useGetDOIAssociation(\n {\n id: projectId,\n version: undefined,\n type: DoiObjectType.ENTITY,\n },\n {\n enabled: !!projectId,\n },\n )\n\n // If both project and entity have DOIs, we show the dropdown variant\n const isProjectAndEntityDoi = projectDoiAssociation && entityDoiAssociation\n\n function getButtonText() {\n if (isProjectAndEntityDoi) {\n return 'Cite as...'\n } else if (entityDoiAssociation && !projectDoiAssociation) {\n return 'Cite page'\n } else if (!entityDoiAssociation && projectDoiAssociation) {\n return 'Cite project'\n }\n return ''\n }\n\n const buttonText = getButtonText()\n\n const handleButtonClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n if (entityDoiAssociation && !projectDoiAssociation) {\n setSelectedDoi(entityDoiAssociation.doiUri)\n setCitationAnchorEl(event.currentTarget)\n } else if (!entityDoiAssociation && projectDoiAssociation) {\n setSelectedDoi(projectDoiAssociation.doiUri)\n setCitationAnchorEl(event.currentTarget)\n } else {\n // If both project and entity doi exist, show dropdown\n setAnchorEl(event.currentTarget)\n }\n }\n\n const popover = (\n <CitationPopoverContent\n doi={selectedDoi}\n anchorEl={citationAnchorEl}\n open={!!citationAnchorEl && !!selectedDoi}\n id={id}\n onClose={() => {\n setCitationAnchorEl(null)\n setSelectedDoi(undefined)\n }}\n />\n )\n\n const options: string[] = ['Cite this Project', 'Cite only this page']\n\n if (!projectDoiAssociation && !entityDoiAssociation) {\n return null\n }\n\n if (isEntityLoading || isProjectLoading) {\n return (\n <Skeleton\n sx={{\n width: { xs: '100%', sm: '140px' },\n height: '45px',\n }}\n />\n )\n }\n\n return (\n <>\n {isProjectAndEntityDoi ? (\n <DropdownSelect\n disabled={isEntityLoading && isProjectLoading}\n options={options}\n anchorRef={citationButtonRef}\n sx={{\n width: { xs: '100%', sm: 'initial' },\n }}\n buttonText=\"Cite as...\"\n variant=\"outlined\"\n buttonGroupAriaLabel=\"Citation options\"\n selectedIndex={selectedIndex}\n setSelectedIndex={(index: number) => {\n setSelectedIndex(index)\n const selected =\n index === 0\n ? projectDoiAssociation?.doiUri\n : entityDoiAssociation?.doiUri\n if (selected) {\n setSelectedDoi(selected)\n setCitationAnchorEl(citationButtonRef.current)\n }\n }}\n />\n ) : (\n <Button\n onClick={handleButtonClick}\n disabled={isEntityLoading && isProjectLoading}\n sx={{\n width: { xs: '100%', sm: 'initial' },\n }}\n variant=\"outlined\"\n startIcon={<DoubleQuotes width={18} height={18} />}\n >\n {buttonText}\n </Button>\n )}\n {popover}\n </>\n )\n}\n\nexport default EntityCitation\n"],"mappings":";;;;;;;;;;;;AAiBA,IAAM,KAAkB,EACtB,cACA,aACA,uBAC0C;CAC1C,IAAM,EAAE,MAAM,GAAQ,WAAW,MAAoB,EACnD,GACA,EACD,EACK,CAAC,GAAU,KAAe,EAAmC,KAAK,EAClE,CAAC,GAAa,KAAkB,EAA6B,KAAA,EAAU,EACvE,CAAC,GAAkB,KAAuB,EAC9C,KACD,EACK,CAAC,GAAe,KAAoB,EACxC,KAAA,EACD,EACK,IAAoB,EAAuB,KAAK,EAGhD,IADe,IACH,oBAAoB,KAAA,GAEhC,IAAuB,EAC3B,GACA,GACA,GACA,EACD,EAIK,EAAE,MAAM,GAAuB,WAAW,MAC9C,EACE;EACE,IAAI;EACJ,SAAS,KAAA;EACT,MAAM,EAAc;EACrB,EACD,EACE,SAAS,CAAC,CAAC,GACZ,CACF,EAGG,IAAwB,KAAyB;CAEvD,SAAS,IAAgB;AAQvB,SAPI,IACK,eACE,KAAwB,CAAC,IAC3B,cACE,CAAC,KAAwB,IAC3B,iBAEF;;CAGT,IAAM,IAAa,GAAe;AA6ClC,QAfI,CAAC,KAAyB,CAAC,IACtB,OAGL,KAAmB,IAEnB,kBAAC,GAAD,EACE,IAAI;EACF,OAAO;GAAE,IAAI;GAAQ,IAAI;GAAS;EAClC,QAAQ;EACT,EACD,CAAA,GAKJ,kBAAA,GAAA,EAAA,UAAA,CACG,IACC,kBAAC,GAAD;EACE,UAAU,KAAmB;EACpB,UAtBU,qBAAqB,sBAsB/B;EACT,WAAW;EACX,IAAI,EACF,OAAO;GAAE,IAAI;GAAQ,IAAI;GAAW,EACrC;EACD,YAAW;EACX,SAAQ;EACR,sBAAqB;EACN;EACf,mBAAmB,MAAkB;AACnC,KAAiB,EAAM;GACvB,IAAM,IACJ,MAAU,IACN,GAAuB,SACvB,GAAsB;AAC5B,GAAI,MACF,EAAe,EAAS,EACxB,EAAoB,EAAkB,QAAQ;;EAGlD,CAAA,GAEF,kBAAC,GAAD;EACE,UAvEmB,MAA+C;AACxE,GAAI,KAAwB,CAAC,KAC3B,EAAe,EAAqB,OAAO,EAC3C,EAAoB,EAAM,cAAc,IAC/B,CAAC,KAAwB,KAClC,EAAe,EAAsB,OAAO,EAC5C,EAAoB,EAAM,cAAc,IAGxC,EAAY,EAAM,cAAc;;EA+D5B,UAAU,KAAmB;EAC7B,IAAI,EACF,OAAO;GAAE,IAAI;GAAQ,IAAI;GAAW,EACrC;EACD,SAAQ;EACR,WAAW,kBAAC,GAAD;GAAc,OAAO;GAAI,QAAQ;GAAM,CAAA;YAEjD;EACM,CAAA,EAEV,gBApEH,EAAC,GAAD;EACE,KAAK;EACL,UAAU;EACV,MAAM,CAAC,CAAC,KAAoB,CAAC,CAAC;EAC1B;EACJ,eAAe;AAEb,GADA,EAAoB,KAAK,EACzB,EAAe,KAAA,EAAU;;EAE3B,CA2DC,CACA,EAAA,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"EntityDownloadButton.js","names":[],"sources":["../../../src/components/EntityDownloadButton/EntityDownloadButton.tsx"],"sourcesContent":["import { useGetEntity, useGetVersions } from '@/synapse-queries'\nimport {\n useAddFileToDownloadList,\n useGetAddToDownloadListStats,\n} from '@/synapse-queries/index'\nimport { useSynapseContext } from '@/utils'\nimport {\n entityTypeToFriendlyName,\n hasFilesInView,\n isContainerType,\n isDataset,\n isEntityView,\n isVersionableEntity,\n} from '@/utils/functions/EntityTypeUtils'\nimport { useDirectDownloadHandler } from '@/utils/hooks/useDirectDownloadHandler'\nimport { isFileEntity } from '@/utils/types/IsType'\nimport { DownloadOutlined as DownloadIcon } from '@mui/icons-material'\nimport { EntityType } from '@sage-bionetworks/synapse-client'\nimport {\n FileHandleAssociateType,\n QueryBundleRequest,\n} from '@sage-bionetworks/synapse-types'\nimport { RefObject, useState } from 'react'\nimport { createPortal } from 'react-dom'\nimport { displayFilesWereAddedToDownloadListSuccess } from '../download_list/DownloadConfirmationUtils'\nimport { EntityDownloadConfirmation } from '../EntityDownloadConfirmation'\nimport { DropdownMenu, DropdownMenuItem } from '../menu/DropdownMenu'\nimport { ModalDownload } from '../ModalDownload/ModalDownload'\nimport { ProgrammaticInstructionsModal } from '../ProgrammaticInstructionsModal/ProgrammaticInstructionsModal'\nimport { displayToast } from '../ToastMessage/index'\n\n// WIP\n// Per Nick Grosenbacher: For this to be reusable, I think we would also need to accept versionNumber as a prop. Where we would have the following behavior:\n// - If the version number is present, use it\n// - If the version number is null, do not use it,\n// - If the version number is undefined, then we would try to do the 'smart' thing-- get the latest version for datasets, otherwise don't use it.\n\n// Have to keep these consts outside of getProgrammaticAccessCode because\n// they are being called in ProgrammaticTableDownload.tsx\n// Python client import and login instructions\nexport const PYTHON_CLIENT_IMPORT_AND_LOGIN = `import synapseclient\nsyn = synapseclient.Synapse()\nsyn.login(authToken=\"YOUR_TOKEN_HERE\")`\n\n// R client import and login instructions\nexport const R_CLIENT_IMPORT_AND_LOGIN = `library(synapser)\nsynLogin(authToken=\"YOUR_TOKEN_HERE\")`\n\ntype ProgrammaticAccessCode = {\n cliCode: string | undefined\n rCode: string | undefined\n pythonCode: string | undefined\n}\n\n// Generate programmatic access code snippet content based on entity type\nfunction getProgrammaticAccessCode(\n type: EntityType,\n entityId: string,\n version: number | undefined,\n): ProgrammaticAccessCode {\n const id =\n type === EntityType.dataset && version ? `${entityId}.${version}` : entityId\n switch (type) {\n case EntityType.file:\n case EntityType.folder:\n case EntityType.project:\n case EntityType.link:\n return {\n cliCode: `synapse get -r ${entityId}`,\n rCode: `${R_CLIENT_IMPORT_AND_LOGIN} \\n\n# Download file\nsynGet('${entityId}')`,\n pythonCode: `${PYTHON_CLIENT_IMPORT_AND_LOGIN} \\n\n# Download file\nsyn.get('${entityId}')`,\n }\n case EntityType.dockerrepo:\n return {\n cliCode: `docker login -u <synapse username> -p <synapse password> docker.synapse.org \\n\ndocker pull docker.synapse.org/${entityId}/myrepo`,\n rCode: undefined,\n pythonCode: undefined,\n }\n case EntityType.dataset:\n case EntityType.entityview:\n case EntityType.datasetcollection:\n case EntityType.table:\n case EntityType.materializedview:\n case EntityType.submissionview:\n case EntityType.virtualtable:\n case EntityType.recordset:\n return {\n cliCode: `synapse get -q \"SELECT * FROM ${id}\"`,\n rCode: `${R_CLIENT_IMPORT_AND_LOGIN} \\n\nquery <- synTableQuery(\"SELECT * FROM ${id}\")\nread.table(query$filepath, sep=\",\")`,\n pythonCode: `${PYTHON_CLIENT_IMPORT_AND_LOGIN} \\n\nquery = syn.tableQuery(\"SELECT * FROM ${id}\")\nquery.asDataFrame()`,\n }\n default:\n throw new Error(`Unhandled EntityType: ${type}`)\n }\n}\n\nenum DownloadAction {\n downloadFile,\n addToCart,\n programmaticAccess,\n programmaticAccessDocker,\n exportTable,\n}\n\n// Function that creates menu items for download actions\nfunction getMenuItemForAction(\n entityId: string,\n entityName: string,\n entityType: EntityType,\n downloadAction: DownloadAction,\n setShowProgrammaticAccess: (show: boolean) => void,\n setShowExportMetadata: (show: boolean) => void,\n addFileToDownloadList: (params: {\n entityId: string\n entityVersionNumber: number | undefined\n }) => void,\n setShowDownloadConfirmation: (show: boolean) => void,\n versionNumber?: number,\n addToCartDisabled?: boolean,\n onDownloadFile?: () => void,\n isAuthenticated?: boolean,\n): DropdownMenuItem {\n switch (downloadAction) {\n case DownloadAction.downloadFile:\n return {\n text: 'Download File',\n onClick: () => {\n if (onDownloadFile) onDownloadFile()\n },\n tooltipText: isAuthenticated\n ? 'Download this file directly'\n : 'Sign in to download this file',\n disabled: !isAuthenticated,\n }\n case DownloadAction.addToCart:\n return {\n text: 'Add to Download List',\n disabled: addToCartDisabled,\n tooltipText: getAddToCartTooltip(entityType, !!addToCartDisabled),\n onClick: () => {\n if (\n entityType === EntityType.file ||\n entityType === EntityType.recordset\n ) {\n addFileToDownloadList({\n entityId,\n entityVersionNumber: versionNumber,\n })\n } else {\n setShowDownloadConfirmation(true)\n }\n },\n }\n case DownloadAction.programmaticAccess:\n return {\n text: 'Programmatic Access',\n onClick: () => {\n setShowProgrammaticAccess(true)\n },\n tooltipText: 'View programmatic access options',\n }\n case DownloadAction.programmaticAccessDocker:\n return {\n text: 'Programmatic Access (Docker)',\n onClick: () => {\n setShowProgrammaticAccess(true)\n },\n tooltipText: 'View programmatic options to pull Docker image',\n }\n case DownloadAction.exportTable:\n return {\n text: 'Export Table',\n onClick: () => {\n setShowExportMetadata(true)\n },\n tooltipText: 'Export table data',\n }\n }\n}\n\n/**\n * Determines the tooltip message based on the entity type and its \"add to cart\" status.\n */\nconst getAddToCartTooltip = (\n entityType: EntityType,\n isDisabled: boolean,\n): string => {\n if (!isDisabled) {\n return 'Add file(s) to your download list'\n }\n const entityFriendlyName = entityTypeToFriendlyName(entityType)\n return `This ${entityFriendlyName} has no accessible files`\n}\n\n// Function that returns DropdownMenuItem\nexport function getDownloadActionsForEntityType(\n type: EntityType,\n): DownloadAction[][] {\n switch (type) {\n case EntityType.file:\n case EntityType.recordset:\n return [\n [DownloadAction.downloadFile],\n [DownloadAction.addToCart, DownloadAction.programmaticAccess],\n ]\n case EntityType.project:\n case EntityType.folder:\n return [[DownloadAction.addToCart, DownloadAction.programmaticAccess]]\n case EntityType.dockerrepo:\n return [[DownloadAction.programmaticAccessDocker]]\n case EntityType.entityview:\n case EntityType.dataset:\n return [\n [\n DownloadAction.exportTable,\n DownloadAction.programmaticAccess,\n DownloadAction.addToCart,\n ],\n ]\n case EntityType.datasetcollection:\n case EntityType.table:\n case EntityType.materializedview:\n case EntityType.submissionview:\n case EntityType.virtualtable:\n return [[DownloadAction.exportTable, DownloadAction.programmaticAccess]]\n case EntityType.link:\n return [[DownloadAction.programmaticAccess]]\n default:\n // this will fail if a new EntityType is added and not handled\n throw new Error(`Unhandled EntityType: ${type}`)\n }\n}\n\n// get the appropriate version number for download based on entity type\n// for datasets: returns the most recent released version if any exist, undefined otherwise\n// for other entities: returns the current version number\nfunction useGetLatestVersionNumber(entityId: string, entityType: EntityType) {\n // get entity data\n const { data: entityData, isLoading: entityDataLoading } =\n useGetEntity(entityId) // No version = latest\n\n // for datasets, check if any versions exist and use the most recent one\n const mustGetVersion = entityType === EntityType.dataset\n const { data: versionsData, isLoading: versionsLoading } = useGetVersions(\n entityId,\n 0,\n 1,\n {\n enabled: mustGetVersion,\n },\n )\n\n let latestVersionNumber: number | undefined\n\n if (mustGetVersion) {\n // for datasets, check if any versions exist\n if (versionsData?.results && versionsData.results.length > 0) {\n // Use the most recent released version (first in the list, since versions are returned in descending order)\n latestVersionNumber = versionsData.results[0].versionNumber\n } else {\n // no versions exist, use undefined (will use current/draft version)\n latestVersionNumber = undefined\n }\n } else {\n // for non-datasets, use the entity's version number\n latestVersionNumber =\n entityData && isVersionableEntity(entityData)\n ? entityData.versionNumber\n : undefined\n }\n\n const isLoading = entityDataLoading || versionsLoading\n\n return { latestVersionNumber, isLoading }\n}\n\n// create default queryBundleRequest with appropriate SQL\nfunction getDefaultQueryBundleRequestForEntity(\n entityId: string,\n versionNumber: number | undefined,\n entityType: EntityType,\n): QueryBundleRequest {\n let sql: string\n\n if (entityType === EntityType.dataset) {\n // for datasets:\n // - if a version number exists (released version), use it: syn123.5\n // - if no version number (no released versions), use current/draft: syn123\n sql = versionNumber\n ? `SELECT * FROM ${entityId}.${versionNumber}`\n : `SELECT * FROM ${entityId}`\n } else {\n // For non-datasets, always use entity ID without version\n sql = `SELECT * FROM ${entityId}`\n }\n\n return {\n concreteType: 'org.sagebionetworks.repo.model.table.QueryBundleRequest',\n entityId: `${entityId}`,\n query: {\n sql: sql,\n },\n partMask: 0,\n }\n}\n\nexport function EntityDownloadButton(props: {\n entityId: string\n name: string\n entityType: EntityType\n downloadConfirmationContainer?: RefObject<HTMLElement | null>\n disabled?: boolean\n}) {\n // get the appropriate version number for the entity\n const { latestVersionNumber } = useGetLatestVersionNumber(\n props.entityId,\n props.entityType,\n )\n // create queryBundleRequest with appropriate SQL based on entity type and version\n const defaultQueryBundleRequest = getDefaultQueryBundleRequestForEntity(\n props.entityId,\n latestVersionNumber,\n props.entityType,\n )\n\n // Get context and download functionality\n const { downloadCartPageUrl, isAuthenticated } = useSynapseContext()\n const { mutate: addFileToDownloadList } = useAddFileToDownloadList({\n onSuccess: data => {\n if (data.numberOfFilesAdded > 0) {\n displayFilesWereAddedToDownloadListSuccess(downloadCartPageUrl)\n } else {\n displayToast('0 Files added to your Download List', 'info')\n }\n },\n onError: error => {\n displayToast(error.reason, 'danger')\n },\n })\n\n // state to manage programmatic access modal visibility\n const [showProgrammaticAccess, setShowProgrammaticAccess] =\n useState<boolean>(false)\n\n // state to manage download confirmation visibility and loading\n const [showDownloadConfirmation, setShowDownloadConfirmation] =\n useState<boolean>(false)\n const [downloadConfirmationLoading, setDownloadConfirmationLoading] =\n useState<boolean>(false)\n\n const handleCloseProgrammaticAccess = () => {\n setShowProgrammaticAccess(false)\n }\n\n const isFolderOrProject = isContainerType(props.entityType)\n\n const {\n data: folderOrProjectStats,\n isLoading: isLoadingFolderOrProjectStats,\n } = useGetAddToDownloadListStats(\n {\n concreteType:\n 'org.sagebionetworks.repo.model.download.AddToDownloadListStatsRequest',\n request: {\n parentId: props.entityId,\n concreteType:\n 'org.sagebionetworks.repo.model.download.AddToDownloadListRequest',\n recursive: true,\n },\n },\n {\n enabled: isFolderOrProject,\n },\n )\n\n const folderOrProjectHasNoFiles =\n isFolderOrProject &&\n (isLoadingFolderOrProjectStats || folderOrProjectStats?.fileCount === 0)\n\n const { data: entityData } = useGetEntity(props.entityId)\n\n const { downloadFile } = useDirectDownloadHandler()\n\n const fileHandleId =\n entityData && isFileEntity(entityData)\n ? entityData.dataFileHandleId\n : undefined\n\n const onDownloadFile = fileHandleId\n ? () => {\n void downloadFile({\n fileHandleId,\n associatedObjectId: props.entityId,\n associatedObjectType: FileHandleAssociateType.FileEntity,\n })\n }\n : undefined\n\n const entityViewHasNoFiles =\n entityData && isEntityView(entityData) && !hasFilesInView(entityData)\n\n const datasetHasNoFiles =\n entityData &&\n isDataset(entityData) &&\n (!entityData.items || entityData.items.length === 0)\n\n const addToCartDisabled =\n folderOrProjectHasNoFiles || entityViewHasNoFiles || datasetHasNoFiles\n\n // state to manage export metadata modal visibility\n const [showExportMetadata, setShowExportMetadata] = useState<boolean>(false)\n\n const handleCloseExportMetadata = () => {\n setShowExportMetadata(false)\n }\n\n // Create download menu items\n const downloadActions = getDownloadActionsForEntityType(props.entityType)\n const downloadMenuItems = downloadActions.map(actionGroup =>\n actionGroup.map(action =>\n getMenuItemForAction(\n props.entityId,\n props.name,\n props.entityType,\n action,\n setShowProgrammaticAccess,\n setShowExportMetadata,\n addFileToDownloadList,\n setShowDownloadConfirmation,\n latestVersionNumber,\n addToCartDisabled,\n onDownloadFile,\n isAuthenticated,\n ),\n ),\n )\n\n // Return programmatic access modal content\n const { cliCode, rCode, pythonCode } = getProgrammaticAccessCode(\n props.entityType,\n props.entityId,\n latestVersionNumber,\n )\n\n const downloadConfirmation = showDownloadConfirmation ? (\n <EntityDownloadConfirmation\n entityId={props.entityId}\n handleClose={() => setShowDownloadConfirmation(false)}\n onIsLoadingChange={setDownloadConfirmationLoading}\n />\n ) : null\n\n return (\n <>\n <DropdownMenu\n items={downloadMenuItems}\n dropdownButtonText=\"Download\"\n buttonTooltip=\"Download options for this entity\"\n buttonProps={{\n variant: 'outlined',\n startIcon: <DownloadIcon />,\n disabled: props.disabled || downloadConfirmationLoading,\n }}\n />\n {downloadConfirmation &&\n (props.downloadConfirmationContainer?.current\n ? createPortal(\n downloadConfirmation,\n props.downloadConfirmationContainer.current,\n )\n : downloadConfirmation)}\n <ProgrammaticInstructionsModal\n show={showProgrammaticAccess}\n title={`Programmatic Access: ${props.name}`}\n onClose={handleCloseProgrammaticAccess}\n pythonCode={pythonCode}\n rCode={rCode}\n cliCode={cliCode}\n helpUrl=\"https://help.synapse.org/docs/Synapse-Docker-Registry.2011037752.html#SynapseDockerRegistry-UsingDockerImagesStoredintheSynapseDockerRegistry\"\n />\n {showExportMetadata && (\n <ModalDownload\n queryBundleRequest={defaultQueryBundleRequest}\n onClose={handleCloseExportMetadata}\n />\n )}\n </>\n )\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"EntityDownloadButton.js","names":[],"sources":["../../../src/components/EntityDownloadButton/EntityDownloadButton.tsx"],"sourcesContent":["import { useGetEntity, useGetVersions } from '@/synapse-queries'\nimport {\n useAddFileToDownloadList,\n useGetAddToDownloadListStats,\n} from '@/synapse-queries/index'\nimport { useSynapseContext } from '@/utils'\nimport {\n entityTypeToFriendlyName,\n hasFilesInView,\n isContainerType,\n isDataset,\n isEntityView,\n isVersionableEntity,\n} from '@/utils/functions/EntityTypeUtils'\nimport { useDirectDownloadHandler } from '@/utils/hooks/useDirectDownloadHandler'\nimport { isFileEntity } from '@/utils/types/IsType'\nimport { DownloadOutlined as DownloadIcon } from '@mui/icons-material'\nimport { EntityType } from '@sage-bionetworks/synapse-client'\nimport {\n FileHandleAssociateType,\n QueryBundleRequest,\n} from '@sage-bionetworks/synapse-types'\nimport { RefObject, useState } from 'react'\nimport { createPortal } from 'react-dom'\nimport { displayFilesWereAddedToDownloadListSuccess } from '../download_list/DownloadConfirmationUtils'\nimport { EntityDownloadConfirmation } from '../EntityDownloadConfirmation'\nimport { DropdownMenu, DropdownMenuItem } from '../menu/DropdownMenu'\nimport { ModalDownload } from '../ModalDownload/ModalDownload'\nimport { ProgrammaticInstructionsModal } from '../ProgrammaticInstructionsModal/ProgrammaticInstructionsModal'\nimport { displayToast } from '../ToastMessage/index'\n\n// WIP\n// Per Nick Grosenbacher: For this to be reusable, I think we would also need to accept versionNumber as a prop. Where we would have the following behavior:\n// - If the version number is present, use it\n// - If the version number is null, do not use it,\n// - If the version number is undefined, then we would try to do the 'smart' thing-- get the latest version for datasets, otherwise don't use it.\n\n// Have to keep these consts outside of getProgrammaticAccessCode because\n// they are being called in ProgrammaticTableDownload.tsx\n// Python client import and login instructions\nexport const PYTHON_CLIENT_IMPORT_AND_LOGIN = `import synapseclient\nsyn = synapseclient.Synapse()\nsyn.login(authToken=\"YOUR_TOKEN_HERE\")`\n\n// R client import and login instructions\nexport const R_CLIENT_IMPORT_AND_LOGIN = `library(synapser)\nsynLogin(authToken=\"YOUR_TOKEN_HERE\")`\n\ntype ProgrammaticAccessCode = {\n cliCode: string | undefined\n rCode: string | undefined\n pythonCode: string | undefined\n}\n\n// Generate programmatic access code snippet content based on entity type\nfunction getProgrammaticAccessCode(\n type: EntityType,\n entityId: string,\n version: number | undefined,\n): ProgrammaticAccessCode {\n const id =\n type === EntityType.dataset && version ? `${entityId}.${version}` : entityId\n switch (type) {\n case EntityType.file:\n case EntityType.folder:\n case EntityType.project:\n case EntityType.link:\n return {\n cliCode: `synapse get -r ${entityId}`,\n rCode: `${R_CLIENT_IMPORT_AND_LOGIN} \\n\n# Download file\nsynGet('${entityId}')`,\n pythonCode: `${PYTHON_CLIENT_IMPORT_AND_LOGIN} \\n\n# Download file\nsyn.get('${entityId}')`,\n }\n case EntityType.dockerrepo:\n return {\n cliCode: `docker login -u <synapse username> -p <synapse password> docker.synapse.org \\n\ndocker pull docker.synapse.org/${entityId}/myrepo`,\n rCode: undefined,\n pythonCode: undefined,\n }\n case EntityType.dataset:\n case EntityType.entityview:\n case EntityType.datasetcollection:\n case EntityType.table:\n case EntityType.materializedview:\n case EntityType.submissionview:\n case EntityType.virtualtable:\n case EntityType.recordset:\n return {\n cliCode: `synapse get -q \"SELECT * FROM ${id}\"`,\n rCode: `${R_CLIENT_IMPORT_AND_LOGIN} \\n\nquery <- synTableQuery(\"SELECT * FROM ${id}\")\nread.table(query$filepath, sep=\",\")`,\n pythonCode: `${PYTHON_CLIENT_IMPORT_AND_LOGIN} \\n\nquery = syn.tableQuery(\"SELECT * FROM ${id}\")\nquery.asDataFrame()`,\n }\n default:\n throw new Error(`Unhandled EntityType: ${type}`)\n }\n}\n\nenum DownloadAction {\n downloadFile,\n addToCart,\n programmaticAccess,\n programmaticAccessDocker,\n exportTable,\n}\n\n// Function that creates menu items for download actions\nfunction getMenuItemForAction(\n entityId: string,\n entityName: string,\n entityType: EntityType,\n downloadAction: DownloadAction,\n setShowProgrammaticAccess: (show: boolean) => void,\n setShowExportMetadata: (show: boolean) => void,\n addFileToDownloadList: (params: {\n entityId: string\n entityVersionNumber: number | undefined\n }) => void,\n setShowDownloadConfirmation: (show: boolean) => void,\n versionNumber?: number,\n addToCartDisabled?: boolean,\n onDownloadFile?: () => void,\n isAuthenticated?: boolean,\n): DropdownMenuItem {\n switch (downloadAction) {\n case DownloadAction.downloadFile:\n return {\n text: 'Download File',\n onClick: () => {\n if (onDownloadFile) onDownloadFile()\n },\n tooltipText: isAuthenticated\n ? 'Download this file directly'\n : 'Sign in to download this file',\n disabled: !isAuthenticated,\n }\n case DownloadAction.addToCart:\n return {\n text: 'Add to Download List',\n disabled: addToCartDisabled,\n tooltipText: getAddToCartTooltip(entityType, !!addToCartDisabled),\n onClick: () => {\n if (\n entityType === EntityType.file ||\n entityType === EntityType.recordset\n ) {\n addFileToDownloadList({\n entityId,\n entityVersionNumber: versionNumber,\n })\n } else {\n setShowDownloadConfirmation(true)\n }\n },\n }\n case DownloadAction.programmaticAccess:\n return {\n text: 'Programmatic Access',\n onClick: () => {\n setShowProgrammaticAccess(true)\n },\n tooltipText: 'View programmatic access options',\n }\n case DownloadAction.programmaticAccessDocker:\n return {\n text: 'Programmatic Access (Docker)',\n onClick: () => {\n setShowProgrammaticAccess(true)\n },\n tooltipText: 'View programmatic options to pull Docker image',\n }\n case DownloadAction.exportTable:\n return {\n text: 'Export Table',\n onClick: () => {\n setShowExportMetadata(true)\n },\n tooltipText: 'Export table data',\n }\n }\n}\n\n/**\n * Determines the tooltip message based on the entity type and its \"add to cart\" status.\n */\nconst getAddToCartTooltip = (\n entityType: EntityType,\n isDisabled: boolean,\n): string => {\n if (!isDisabled) {\n return 'Add file(s) to your download list'\n }\n const entityFriendlyName = entityTypeToFriendlyName(entityType)\n return `This ${entityFriendlyName} has no accessible files`\n}\n\n// Function that returns DropdownMenuItem\nexport function getDownloadActionsForEntityType(\n type: EntityType,\n): DownloadAction[][] {\n switch (type) {\n case EntityType.file:\n case EntityType.recordset:\n return [\n [DownloadAction.downloadFile],\n [DownloadAction.addToCart, DownloadAction.programmaticAccess],\n ]\n case EntityType.project:\n case EntityType.folder:\n return [[DownloadAction.addToCart, DownloadAction.programmaticAccess]]\n case EntityType.dockerrepo:\n return [[DownloadAction.programmaticAccessDocker]]\n case EntityType.entityview:\n case EntityType.dataset:\n return [\n [\n DownloadAction.exportTable,\n DownloadAction.programmaticAccess,\n DownloadAction.addToCart,\n ],\n ]\n case EntityType.datasetcollection:\n case EntityType.table:\n case EntityType.materializedview:\n case EntityType.submissionview:\n case EntityType.virtualtable:\n return [[DownloadAction.exportTable, DownloadAction.programmaticAccess]]\n case EntityType.link:\n return [[DownloadAction.programmaticAccess]]\n default:\n // this will fail if a new EntityType is added and not handled\n throw new Error(`Unhandled EntityType: ${type}`)\n }\n}\n\n// get the appropriate version number for download based on entity type\n// for datasets: returns the most recent released version if any exist, undefined otherwise\n// for other entities: returns the current version number\nfunction useGetLatestVersionNumber(entityId: string, entityType: EntityType) {\n // get entity data\n const { data: entityData, isLoading: entityDataLoading } =\n useGetEntity(entityId) // No version = latest\n\n // for datasets, check if any versions exist and use the most recent one\n const mustGetVersion = entityType === EntityType.dataset\n const { data: versionsData, isLoading: versionsLoading } = useGetVersions(\n entityId,\n 0,\n 1,\n {\n enabled: mustGetVersion,\n },\n )\n\n let latestVersionNumber: number | undefined\n\n if (mustGetVersion) {\n // for datasets, check if any versions exist\n if (versionsData?.results && versionsData.results.length > 0) {\n // Use the most recent released version (first in the list, since versions are returned in descending order)\n latestVersionNumber = versionsData.results[0].versionNumber\n } else {\n // no versions exist, use undefined (will use current/draft version)\n latestVersionNumber = undefined\n }\n } else {\n // for non-datasets, use the entity's version number\n latestVersionNumber =\n entityData && isVersionableEntity(entityData)\n ? entityData.versionNumber\n : undefined\n }\n\n const isLoading = entityDataLoading || versionsLoading\n\n return { latestVersionNumber, isLoading }\n}\n\n// create default queryBundleRequest with appropriate SQL\nfunction getDefaultQueryBundleRequestForEntity(\n entityId: string,\n versionNumber: number | undefined,\n entityType: EntityType,\n): QueryBundleRequest {\n let sql: string\n\n if (entityType === EntityType.dataset) {\n // for datasets:\n // - if a version number exists (released version), use it: syn123.5\n // - if no version number (no released versions), use current/draft: syn123\n sql = versionNumber\n ? `SELECT * FROM ${entityId}.${versionNumber}`\n : `SELECT * FROM ${entityId}`\n } else {\n // For non-datasets, always use entity ID without version\n sql = `SELECT * FROM ${entityId}`\n }\n\n return {\n concreteType: 'org.sagebionetworks.repo.model.table.QueryBundleRequest',\n entityId: `${entityId}`,\n query: {\n sql: sql,\n },\n partMask: 0,\n }\n}\n\nexport function EntityDownloadButton(props: {\n entityId: string\n name: string\n entityType: EntityType\n downloadConfirmationContainer?: RefObject<HTMLElement | null>\n disabled?: boolean\n}) {\n // get the appropriate version number for the entity\n const { latestVersionNumber } = useGetLatestVersionNumber(\n props.entityId,\n props.entityType,\n )\n // create queryBundleRequest with appropriate SQL based on entity type and version\n const defaultQueryBundleRequest = getDefaultQueryBundleRequestForEntity(\n props.entityId,\n latestVersionNumber,\n props.entityType,\n )\n\n // Get context and download functionality\n const { downloadCartPageUrl, isAuthenticated } = useSynapseContext()\n const { mutate: addFileToDownloadList } = useAddFileToDownloadList({\n onSuccess: data => {\n if (data.numberOfFilesAdded > 0) {\n displayFilesWereAddedToDownloadListSuccess(downloadCartPageUrl)\n } else {\n displayToast('0 Files added to your Download List', 'info')\n }\n },\n onError: error => {\n displayToast(error.reason, 'danger')\n },\n })\n\n // state to manage programmatic access modal visibility\n const [showProgrammaticAccess, setShowProgrammaticAccess] =\n useState<boolean>(false)\n\n // state to manage download confirmation visibility and loading\n const [showDownloadConfirmation, setShowDownloadConfirmation] =\n useState<boolean>(false)\n const [downloadConfirmationLoading, setDownloadConfirmationLoading] =\n useState<boolean>(false)\n\n const handleCloseProgrammaticAccess = () => {\n setShowProgrammaticAccess(false)\n }\n\n const isFolderOrProject = isContainerType(props.entityType)\n\n const {\n data: folderOrProjectStats,\n isLoading: isLoadingFolderOrProjectStats,\n } = useGetAddToDownloadListStats(\n {\n concreteType:\n 'org.sagebionetworks.repo.model.download.AddToDownloadListStatsRequest',\n request: {\n parentId: props.entityId,\n concreteType:\n 'org.sagebionetworks.repo.model.download.AddToDownloadListRequest',\n recursive: true,\n },\n },\n {\n enabled: isFolderOrProject,\n },\n )\n\n const folderOrProjectHasNoFiles =\n isFolderOrProject &&\n (isLoadingFolderOrProjectStats || folderOrProjectStats?.fileCount === 0)\n\n const { data: entityData } = useGetEntity(props.entityId)\n\n const { downloadFile } = useDirectDownloadHandler()\n\n const fileHandleId =\n entityData && isFileEntity(entityData)\n ? entityData.dataFileHandleId\n : undefined\n\n const onDownloadFile = fileHandleId\n ? () => {\n void downloadFile({\n fileHandleId,\n associatedObjectId: props.entityId,\n associatedObjectType: FileHandleAssociateType.FileEntity,\n })\n }\n : undefined\n\n const entityViewHasNoFiles =\n entityData && isEntityView(entityData) && !hasFilesInView(entityData)\n\n const datasetHasNoFiles =\n entityData &&\n isDataset(entityData) &&\n (!entityData.items || entityData.items.length === 0)\n\n const addToCartDisabled =\n folderOrProjectHasNoFiles || entityViewHasNoFiles || datasetHasNoFiles\n\n // state to manage export metadata modal visibility\n const [showExportMetadata, setShowExportMetadata] = useState<boolean>(false)\n\n const handleCloseExportMetadata = () => {\n setShowExportMetadata(false)\n }\n\n // Create download menu items\n const downloadActions = getDownloadActionsForEntityType(props.entityType)\n const downloadMenuItems = downloadActions.map(actionGroup =>\n actionGroup.map(action =>\n getMenuItemForAction(\n props.entityId,\n props.name,\n props.entityType,\n action,\n setShowProgrammaticAccess,\n setShowExportMetadata,\n addFileToDownloadList,\n setShowDownloadConfirmation,\n latestVersionNumber,\n addToCartDisabled,\n onDownloadFile,\n isAuthenticated,\n ),\n ),\n )\n\n // Return programmatic access modal content\n const { cliCode, rCode, pythonCode } = getProgrammaticAccessCode(\n props.entityType,\n props.entityId,\n latestVersionNumber,\n )\n\n const downloadConfirmation = showDownloadConfirmation ? (\n <EntityDownloadConfirmation\n entityId={props.entityId}\n handleClose={() => setShowDownloadConfirmation(false)}\n onIsLoadingChange={setDownloadConfirmationLoading}\n />\n ) : null\n\n return (\n <>\n <DropdownMenu\n items={downloadMenuItems}\n dropdownButtonText=\"Download\"\n buttonTooltip=\"Download options for this entity\"\n buttonProps={{\n variant: 'outlined',\n startIcon: <DownloadIcon />,\n disabled: props.disabled || downloadConfirmationLoading,\n }}\n />\n {downloadConfirmation &&\n (props.downloadConfirmationContainer?.current\n ? createPortal(\n downloadConfirmation,\n props.downloadConfirmationContainer.current,\n )\n : downloadConfirmation)}\n <ProgrammaticInstructionsModal\n show={showProgrammaticAccess}\n title={`Programmatic Access: ${props.name}`}\n onClose={handleCloseProgrammaticAccess}\n pythonCode={pythonCode}\n rCode={rCode}\n cliCode={cliCode}\n helpUrl=\"https://help.synapse.org/docs/Synapse-Docker-Registry.2011037752.html#SynapseDockerRegistry-UsingDockerImagesStoredintheSynapseDockerRegistry\"\n />\n {showExportMetadata && (\n <ModalDownload\n queryBundleRequest={defaultQueryBundleRequest}\n onClose={handleCloseExportMetadata}\n />\n )}\n </>\n )\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"EntityDownloadConfirmation.d.ts","sourceRoot":"","sources":["../../../src/components/EntityDownloadConfirmation/EntityDownloadConfirmation.tsx"],"names":[],"mappings":"AAYA;;;;GAIG;AACH,MAAM,MAAM,+BAA+B,GAAG;IAC5C,QAAQ,EAAE,MAAM,CAAA;IAChB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,iBAAiB,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAA;IAC/C,WAAW,EAAE,MAAM,IAAI,CAAA;CACxB,CAAA;AAeD;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CAAC,EACzC,QAAQ,EACR,aAAa,EACb,WAAW,EACX,iBAAiB,GAClB,EAAE,+BAA+B,kDAsDjC;AAED,eAAe,0BAA0B,CAAA"}
1
+ {"version":3,"file":"EntityDownloadConfirmation.d.ts","sourceRoot":"","sources":["../../../src/components/EntityDownloadConfirmation/EntityDownloadConfirmation.tsx"],"names":[],"mappings":"AAcA;;;;GAIG;AACH,MAAM,MAAM,+BAA+B,GAAG;IAC5C,QAAQ,EAAE,MAAM,CAAA;IAChB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,iBAAiB,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAA;IAC/C,WAAW,EAAE,MAAM,IAAI,CAAA;CACxB,CAAA;AAeD;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CAAC,EACzC,QAAQ,EACR,aAAa,EACb,WAAW,EACX,iBAAiB,GAClB,EAAE,+BAA+B,kDAqEjC;AAED,eAAe,0BAA0B,CAAA"}
@@ -1,41 +1,47 @@
1
1
  import { convertToEntityType as e, isContainerType as t } from "../../utils/functions/EntityTypeUtils.js";
2
- import { useGetEntity as n } from "../../synapse-queries/entity/useEntity.js";
2
+ import { useSynapseContext as n } from "../../utils/context/SynapseContext.js";
3
+ import "../../utils/index.js";
4
+ import { useGetEntity as r } from "../../synapse-queries/entity/useEntity.js";
3
5
  import "../../synapse-queries/index.js";
4
- import r from "../download_list/AddToDownloadListConfirmationAlert/AddToDownloadListConfirmationAlert.js";
5
- import { useEffect as i, useMemo as a } from "react";
6
- import { jsx as o } from "react/jsx-runtime";
7
- import { EntityType as s } from "@sage-bionetworks/synapse-client";
6
+ import { DownloadConfirmationUI as i } from "../download_list/DownloadConfirmationUI.js";
7
+ import a from "../download_list/AddToDownloadListConfirmationAlert/AddToDownloadListConfirmationAlert.js";
8
+ import { useEffect as o, useMemo as s } from "react";
9
+ import { jsx as c } from "react/jsx-runtime";
10
+ import { EntityType as l } from "@sage-bionetworks/synapse-client";
8
11
  //#region src/components/EntityDownloadConfirmation/EntityDownloadConfirmation.tsx
9
- var c = [
10
- s.project,
11
- s.folder,
12
- s.dataset,
13
- s.datasetcollection
14
- ], l = [s.entityview], u = [s.dataset, s.datasetcollection];
15
- function d({ entityId: s, versionNumber: d, handleClose: f, onIsLoadingChange: p }) {
16
- let { data: m, isLoading: h } = n(s), g = m?.concreteType ? e(m.concreteType) : void 0;
17
- i(() => {
18
- p(h);
19
- }, [h, p]);
20
- let _ = a(() => g ? l.includes(g) ? {
12
+ var u = [
13
+ l.project,
14
+ l.folder,
15
+ l.dataset,
16
+ l.datasetcollection
17
+ ], d = [l.entityview], f = [l.dataset, l.datasetcollection];
18
+ function p({ entityId: l, versionNumber: p, handleClose: m, onIsLoadingChange: h }) {
19
+ let { isAuthenticated: g } = n(), { data: _, isLoading: v } = r(g ? l : void 0), y = _?.concreteType ? e(_.concreteType) : void 0;
20
+ o(() => {
21
+ h(v);
22
+ }, [v, h]);
23
+ let b = s(() => y ? d.includes(y) ? {
21
24
  concreteType: "org.sagebionetworks.repo.model.download.AddToDownloadListRequest",
22
- query: { sql: `select * from ${s}${d == null ? "" : `.${d}`}` }
23
- } : c.includes(g) ? {
25
+ query: { sql: `select * from ${l}${p == null ? "" : `.${p}`}` }
26
+ } : u.includes(y) ? {
24
27
  concreteType: "org.sagebionetworks.repo.model.download.AddToDownloadListRequest",
25
- parentId: s,
26
- useVersionNumber: u.includes(g),
27
- recursive: t(g)
28
+ parentId: l,
29
+ useVersionNumber: f.includes(y),
30
+ recursive: t(y)
28
31
  } : null : null, [
29
- g,
30
- s,
31
- d
32
+ y,
33
+ l,
34
+ p
32
35
  ]);
33
- return _ ? /* @__PURE__ */ o("div", { children: /* @__PURE__ */ o(r, {
34
- addToDownloadListRequest: _,
35
- onClose: f
36
- }) }) : null;
36
+ return b ? /* @__PURE__ */ c("div", { children: /* @__PURE__ */ c(a, {
37
+ addToDownloadListRequest: b,
38
+ onClose: m
39
+ }) }) : g ? null : /* @__PURE__ */ c("div", { children: /* @__PURE__ */ c(i, {
40
+ onAddToDownloadCart: () => {},
41
+ onCancel: m
42
+ }) });
37
43
  }
38
44
  //#endregion
39
- export { d as EntityDownloadConfirmation, d as default };
45
+ export { p as EntityDownloadConfirmation, p as default };
40
46
 
41
47
  //# sourceMappingURL=EntityDownloadConfirmation.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"EntityDownloadConfirmation.js","names":[],"sources":["../../../src/components/EntityDownloadConfirmation/EntityDownloadConfirmation.tsx"],"sourcesContent":["import AddToDownloadListConfirmationAlert from '@/components/download_list/AddToDownloadListConfirmationAlert/AddToDownloadListConfirmationAlert'\nimport {\n convertToEntityType,\n isContainerType,\n} from '@/utils/functions/EntityTypeUtils'\nimport {\n AddToDownloadListRequest,\n EntityType,\n} from '@sage-bionetworks/synapse-client'\nimport { useEffect, useMemo } from 'react'\nimport { useGetEntity } from '../../synapse-queries/'\n\n/**\n * Props for the EntityDownloadConfirmation component.\n *\n * @property entityId - The ID of the entity to be added to the download cart.\n */\nexport type EntityDownloadConfirmationProps = {\n entityId: string\n versionNumber?: number\n onIsLoadingChange: (isLoading: boolean) => void\n handleClose: () => void\n}\n\nconst typesToAddToDownloadListWithParentId: EntityType[] = [\n EntityType.project,\n EntityType.folder,\n EntityType.dataset,\n EntityType.datasetcollection,\n]\nconst typesToAddToDownloadListWithQuery: EntityType[] = [EntityType.entityview]\n/** Users expect the specific file version included in the dataset to be added to the cart */\nconst typesWhereFileVersionNumberShouldBeUsed: EntityType[] = [\n EntityType.dataset,\n EntityType.datasetcollection,\n]\n\n/**\n * A component that allows users to add an entity to the download cart. It displays a confirmation dialog that displays\n * statistics about the set of items that will be added to the download cart.\n *\n * @param props - The properties for the component.\n * @param props.entityId - The ID of the entity to be added to the download cart.\n *\n * @returns The rendered EntityDownloadConfirmation component.\n */\nexport function EntityDownloadConfirmation({\n entityId,\n versionNumber,\n handleClose,\n onIsLoadingChange,\n}: EntityDownloadConfirmationProps) {\n const { data: entity, isLoading: isLoadingEntity } = useGetEntity(entityId)\n const entityType = entity?.concreteType\n ? convertToEntityType(entity.concreteType)\n : undefined\n\n useEffect(() => {\n onIsLoadingChange(isLoadingEntity)\n }, [isLoadingEntity, onIsLoadingChange])\n\n const addToDownloadListRequest: AddToDownloadListRequest | null =\n useMemo(() => {\n if (!entityType) {\n return null\n }\n if (typesToAddToDownloadListWithQuery.includes(entityType)) {\n return {\n concreteType:\n 'org.sagebionetworks.repo.model.download.AddToDownloadListRequest',\n query: {\n sql: `select * from ${entityId}${\n versionNumber != undefined ? `.${versionNumber}` : ''\n }`,\n },\n }\n }\n if (typesToAddToDownloadListWithParentId.includes(entityType)) {\n const useVersionNumber =\n typesWhereFileVersionNumberShouldBeUsed.includes(entityType)\n return {\n concreteType:\n 'org.sagebionetworks.repo.model.download.AddToDownloadListRequest',\n // TODO: Specify version of dataset/dataset collection (PLFM-9311)\n parentId: entityId,\n useVersionNumber,\n recursive: isContainerType(entityType),\n }\n }\n\n return null\n }, [entityType, entityId, versionNumber])\n\n if (!addToDownloadListRequest) {\n return null\n }\n\n return (\n <div>\n <AddToDownloadListConfirmationAlert\n addToDownloadListRequest={addToDownloadListRequest}\n onClose={handleClose}\n />\n </div>\n )\n}\n\nexport default EntityDownloadConfirmation\n"],"mappings":";;;;;;;;AAwBA,IAAM,IAAqD;CACzD,EAAW;CACX,EAAW;CACX,EAAW;CACX,EAAW;CACZ,EACK,IAAkD,CAAC,EAAW,WAAW,EAEzE,IAAwD,CAC5D,EAAW,SACX,EAAW,kBACZ;AAWD,SAAgB,EAA2B,EACzC,aACA,kBACA,gBACA,wBACkC;CAClC,IAAM,EAAE,MAAM,GAAQ,WAAW,MAAoB,EAAa,EAAS,EACrE,IAAa,GAAQ,eACvB,EAAoB,EAAO,aAAa,GACxC,KAAA;AAEJ,SAAgB;AACd,IAAkB,EAAgB;IACjC,CAAC,GAAiB,EAAkB,CAAC;CAExC,IAAM,IACJ,QACO,IAGD,EAAkC,SAAS,EAAW,GACjD;EACL,cACE;EACF,OAAO,EACL,KAAK,iBAAiB,IACpB,KAAiB,OAAkC,KAAtB,IAAI,OAEpC;EACF,GAEC,EAAqC,SAAS,EAAW,GAGpD;EACL,cACE;EAEF,UAAU;EACV,kBANA,EAAwC,SAAS,EAAW;EAO5D,WAAW,EAAgB,EAAW;EACvC,GAGI,OA1BE,MA2BR;EAAC;EAAY;EAAU;EAAc,CAAC;AAM3C,QAJK,IAKH,kBAAC,OAAD,EAAA,UACE,kBAAC,GAAD;EAC4B;EAC1B,SAAS;EACT,CAAA,EACE,CAAA,GATC"}
1
+ {"version":3,"file":"EntityDownloadConfirmation.js","names":[],"sources":["../../../src/components/EntityDownloadConfirmation/EntityDownloadConfirmation.tsx"],"sourcesContent":["import AddToDownloadListConfirmationAlert from '@/components/download_list/AddToDownloadListConfirmationAlert/AddToDownloadListConfirmationAlert'\nimport DownloadConfirmationUI from '@/components/download_list/DownloadConfirmationUI'\nimport {\n convertToEntityType,\n isContainerType,\n} from '@/utils/functions/EntityTypeUtils'\nimport { useSynapseContext } from '@/utils'\nimport {\n AddToDownloadListRequest,\n EntityType,\n} from '@sage-bionetworks/synapse-client'\nimport { useEffect, useMemo } from 'react'\nimport { useGetEntity } from '../../synapse-queries/'\n\n/**\n * Props for the EntityDownloadConfirmation component.\n *\n * @property entityId - The ID of the entity to be added to the download cart.\n */\nexport type EntityDownloadConfirmationProps = {\n entityId: string\n versionNumber?: number\n onIsLoadingChange: (isLoading: boolean) => void\n handleClose: () => void\n}\n\nconst typesToAddToDownloadListWithParentId: EntityType[] = [\n EntityType.project,\n EntityType.folder,\n EntityType.dataset,\n EntityType.datasetcollection,\n]\nconst typesToAddToDownloadListWithQuery: EntityType[] = [EntityType.entityview]\n/** Users expect the specific file version included in the dataset to be added to the cart */\nconst typesWhereFileVersionNumberShouldBeUsed: EntityType[] = [\n EntityType.dataset,\n EntityType.datasetcollection,\n]\n\n/**\n * A component that allows users to add an entity to the download cart. It displays a confirmation dialog that displays\n * statistics about the set of items that will be added to the download cart.\n *\n * @param props - The properties for the component.\n * @param props.entityId - The ID of the entity to be added to the download cart.\n *\n * @returns The rendered EntityDownloadConfirmation component.\n */\nexport function EntityDownloadConfirmation({\n entityId,\n versionNumber,\n handleClose,\n onIsLoadingChange,\n}: EntityDownloadConfirmationProps) {\n const { isAuthenticated } = useSynapseContext()\n const { data: entity, isLoading: isLoadingEntity } = useGetEntity(\n isAuthenticated ? entityId : undefined,\n )\n const entityType = entity?.concreteType\n ? convertToEntityType(entity.concreteType)\n : undefined\n\n useEffect(() => {\n onIsLoadingChange(isLoadingEntity)\n }, [isLoadingEntity, onIsLoadingChange])\n\n const addToDownloadListRequest: AddToDownloadListRequest | null =\n useMemo(() => {\n if (!entityType) {\n return null\n }\n if (typesToAddToDownloadListWithQuery.includes(entityType)) {\n return {\n concreteType:\n 'org.sagebionetworks.repo.model.download.AddToDownloadListRequest',\n query: {\n sql: `select * from ${entityId}${\n versionNumber != undefined ? `.${versionNumber}` : ''\n }`,\n },\n }\n }\n if (typesToAddToDownloadListWithParentId.includes(entityType)) {\n const useVersionNumber =\n typesWhereFileVersionNumberShouldBeUsed.includes(entityType)\n return {\n concreteType:\n 'org.sagebionetworks.repo.model.download.AddToDownloadListRequest',\n // TODO: Specify version of dataset/dataset collection (PLFM-9311)\n parentId: entityId,\n useVersionNumber,\n recursive: isContainerType(entityType),\n }\n }\n\n return null\n }, [entityType, entityId, versionNumber])\n\n if (!addToDownloadListRequest) {\n if (!isAuthenticated) {\n return (\n <div>\n <DownloadConfirmationUI\n onAddToDownloadCart={() => {\n \t// Only displaying UI to prompt sign-in, so no-op is OK\n }}\n onCancel={handleClose}\n />\n </div>\n )\n }\n return null\n }\n\n return (\n <div>\n <AddToDownloadListConfirmationAlert\n addToDownloadListRequest={addToDownloadListRequest}\n onClose={handleClose}\n />\n </div>\n )\n}\n\nexport default EntityDownloadConfirmation\n"],"mappings":";;;;;;;;;;;AA0BA,IAAM,IAAqD;CACzD,EAAW;CACX,EAAW;CACX,EAAW;CACX,EAAW;CACZ,EACK,IAAkD,CAAC,EAAW,WAAW,EAEzE,IAAwD,CAC5D,EAAW,SACX,EAAW,kBACZ;AAWD,SAAgB,EAA2B,EACzC,aACA,kBACA,gBACA,wBACkC;CAClC,IAAM,EAAE,uBAAoB,GAAmB,EACzC,EAAE,MAAM,GAAQ,WAAW,MAAoB,EACnD,IAAkB,IAAW,KAAA,EAC9B,EACK,IAAa,GAAQ,eACvB,EAAoB,EAAO,aAAa,GACxC,KAAA;AAEJ,SAAgB;AACd,IAAkB,EAAgB;IACjC,CAAC,GAAiB,EAAkB,CAAC;CAExC,IAAM,IACJ,QACO,IAGD,EAAkC,SAAS,EAAW,GACjD;EACL,cACE;EACF,OAAO,EACL,KAAK,iBAAiB,IACpB,KAAiB,OAAkC,KAAtB,IAAI,OAEpC;EACF,GAEC,EAAqC,SAAS,EAAW,GAGpD;EACL,cACE;EAEF,UAAU;EACV,kBANA,EAAwC,SAAS,EAMjD;EACA,WAAW,EAAgB,EAAW;EACvC,GAGI,OA1BE,MA2BR;EAAC;EAAY;EAAU;EAAc,CAAC;AAkB3C,QAhBK,IAiBH,kBAAC,OAAD,EAAA,UACE,kBAAC,GAAD;EAC4B;EAC1B,SAAS;EACT,CAAA,EACE,CAAA,GArBD,IAYE,OAVH,kBAAC,OAAD,EAAA,UACE,kBAAC,GAAD;EACE,2BAA2B;EAG3B,UAAU;EACV,CAAA,EACE,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"EntityFinder.js","names":[],"sources":["../../../src/components/EntityFinder/EntityFinder.tsx"],"sourcesContent":["import SynapseClient from '@/synapse-client'\nimport { useSynapseContext } from '@/utils/context/SynapseContext'\nimport { getEntityTypeFromHeader } from '@/utils/functions/EntityTypeUtils'\nimport { parseSynId } from '@/utils/functions/RegularExpressions'\nimport ClearIcon from '@mui/icons-material/Clear'\nimport SearchIcon from '@mui/icons-material/Search'\nimport {\n Box,\n Chip,\n IconButton,\n InputAdornment,\n Stack,\n Tab,\n Tabs,\n TextField,\n} from '@mui/material'\nimport { EntityType } from '@sage-bionetworks/synapse-client'\nimport { KeyValue, Reference } from '@sage-bionetworks/synapse-types'\nimport { Map } from 'immutable'\nimport React, { useCallback, useEffect, useMemo, useState } from 'react'\nimport { useErrorHandler } from 'react-error-boundary'\nimport { ReflexContainer, ReflexElement, ReflexSplitter } from 'react-reflex'\nimport 'react-reflex/styles.css'\nimport { SynapseErrorBoundary } from '../error/ErrorBanner'\nimport { BreadcrumbItem, Breadcrumbs, BreadcrumbsProps } from './Breadcrumbs'\nimport {\n EntityDetailsList,\n EntityDetailsListDataConfiguration,\n EntityDetailsListDataConfigurationType,\n EntityDetailsListProps,\n} from './details/EntityDetailsList'\nimport { EntityFinderHeader } from './EntityFinderHeader'\nimport { EntityTree, EntityTreeContainer, FinderScope } from './tree/EntityTree'\nimport { EntityTreeNodeType } from './tree/VirtualizedTree'\nimport { useEntitySelection } from './useEntitySelection'\nimport { VersionSelectionType } from './VersionSelectionType'\n\nconst DEFAULT_SELECTABLE_TYPES = Object.values(EntityType)\nconst TABLE_DEFAULT_VISIBLE_TYPES = Object.values(EntityType)\nconst TREE_DEFAULT_VISIBLE_TYPES = [EntityType.project, EntityType.folder]\n\nconst searchForOnlyTypesBooleanQuery = (\n entityTypes: EntityType[],\n): KeyValue[] => {\n // Boolean query terms will be combined with AND, and there's no way to OR.\n // So we will negate searching for all omitted types.\n const allTypes = Object.values(EntityType)\n const typesToOmit = allTypes.filter(type => !entityTypes.includes(type))\n return typesToOmit.map(type => ({\n key: 'node_type',\n value: type.toString(),\n not: true,\n }))\n}\n\nexport type EntityFinderProps = {\n /** Whether it is possible to select multiple entities */\n selectMultiple: boolean\n /** Callback invoked when the selection changes */\n onSelectedChange: (selected: Reference[]) => void\n /** The initial appearance of the entity finder. Possible values include \"Current Project\", \"All Projects\", \"Projects Created By Me\", \"My Favorites\" */\n initialScope: FinderScope\n /** The SynID of the 'Current Project'. If this is not a defined, then the scope cannot be \"Current Project\" */\n projectId?: string\n /** The SynID of the entity that should open by default. If this is a Syn ID, then it must be in the project specified in `projectId` */\n initialContainer: string | 'root' | null\n /** Determines if versions are selectable, and if so, how they should be shown. Default is \"TRACKED\" */\n versionSelection?: VersionSelectionType\n /** The entity types to show in the details view (right pane). Any types specified in `selectableTypes` will automatically be included. */\n visibleTypesInList?: EntityType[]\n /** The entity types that may be selected. Types in `visibleTypesInList` that are not in `selectableTypes` will appear as disabled options. Only the types in `selectableTypes` will appear in search */\n selectableTypes?: EntityType[]\n /** The types to show in the tree used to navigate. If `treeOnly` is true, any types specified in `selectableTypes` will automatically be included. */\n visibleTypesInTree?: EntityType[]\n /** Whether to show only the tree. If `true`, the tree will be used to make selections */\n treeOnly?: boolean\n /** If provided, the initial selection will be set to this list of references. The selection will be reset to this value if this object changes, so it should be memoized. */\n initialSelected?: Reference[]\n}\n\nenum EntityFinderTab {\n BROWSE,\n SELECTED,\n}\n\nexport function EntityFinder({\n initialScope,\n projectId,\n initialContainer = null,\n selectMultiple,\n onSelectedChange,\n versionSelection = VersionSelectionType.TRACKED,\n selectableTypes = DEFAULT_SELECTABLE_TYPES,\n visibleTypesInList = TABLE_DEFAULT_VISIBLE_TYPES,\n visibleTypesInTree = TREE_DEFAULT_VISIBLE_TYPES,\n treeOnly = false,\n initialSelected,\n}: EntityFinderProps): React.ReactNode {\n const { accessToken } = useSynapseContext()\n const [currentTab, setCurrentTab] = React.useState(EntityFinderTab.BROWSE)\n\n const [searchActive, setSearchActive] = useState(false)\n // The raw value of the search input box:\n const [searchInput, setSearchInput] = useState<string>('')\n // The \"parsed\" search terms, which are only calculated when Enter is pressed:\n const [searchTerms, setSearchTerms] = useState<string[]>()\n const [breadcrumbsProps, setBreadcrumbsProps] = useState<BreadcrumbsProps>({\n items: [],\n })\n const [searchByIdResults, setSearchByIdResults] = useState<\n EntityFinderHeader[]\n >([])\n const [configFromTreeView, setConfigFromTreeView] =\n useState<EntityDetailsListDataConfiguration>({\n type: EntityDetailsListDataConfigurationType.PROMPT,\n })\n\n // If a type is selectable, it should be visible in the tree/list (depending on treeOnly)\n const selectableAndVisibleTypesInTree = useMemo(\n () => [...visibleTypesInTree, ...selectableTypes],\n [visibleTypesInTree, selectableTypes],\n )\n const selectableAndVisibleTypesInList = useMemo(\n () => [...visibleTypesInList, ...selectableTypes],\n [visibleTypesInList, selectableTypes],\n )\n\n // For dual-pane, this state variable indicates which container is selected in the tree view and should be shown in the table view\n const [currentContainer, setCurrentContainer] =\n useState<EntityTreeContainer>(initialContainer)\n\n const handleError = useErrorHandler()\n\n const setBreadcrumbs = useCallback(\n (items: BreadcrumbItem[]) => {\n setBreadcrumbsProps({\n items,\n })\n },\n [setBreadcrumbsProps],\n )\n\n const { selectedEntities, toggleSelection, setSelection, setInitialVersion } =\n useEntitySelection(selectMultiple)\n\n useEffect(() => {\n if (initialSelected) {\n let map = Map<string, Reference>()\n map = map.withMutations(mutableMap => {\n initialSelected.forEach(reference => {\n mutableMap.set(reference.targetId, reference)\n })\n })\n\n setSelection(map)\n }\n }, [initialSelected, setSelection])\n\n // A snapshot of the selectedEntities used to populate the selection list, allowing deselection of entities without removing them from the list.\n const [selectedEntitiesSnapshot, setSelectedEntitiesSnapshot] =\n useState(selectedEntities)\n\n const isIdSelected = useCallback(\n (entity: EntityFinderHeader) => {\n return selectedEntities.has(entity.id)\n },\n [selectedEntities],\n )\n\n const isSelectable = useCallback(\n (entity: EntityFinderHeader) => {\n const type = getEntityTypeFromHeader(entity)\n return selectableTypes.includes(type)\n },\n [selectableTypes],\n )\n\n useEffect(() => {\n // When it changes, convert the map of selected items to a list of references and invoke the callback\n onSelectedChange(Array.from(selectedEntities.values()))\n }, [selectedEntities, onSelectedChange])\n\n useEffect(() => {\n if (searchTerms?.length === 1) {\n const searchTermReference = parseSynId(searchTerms[0])\n if (searchTermReference) {\n SynapseClient.getEntityHeaders([searchTermReference], accessToken)\n .then(response => {\n setSearchByIdResults(response.results)\n })\n .catch(e => handleError(e))\n }\n } else {\n setSearchByIdResults([])\n }\n }, [accessToken, searchTerms, handleError])\n\n const handleTabChange = (\n _event: React.SyntheticEvent,\n newValue: EntityFinderTab,\n ) => {\n setSelectedEntitiesSnapshot(selectedEntities)\n setCurrentTab(newValue)\n }\n\n const mainPanelClass = searchActive\n ? 'MainPanelSearch'\n : treeOnly\n ? 'MainPanelSinglePane'\n : 'MainPanelDualPane'\n\n const entityDetailsListProps: EntityDetailsListProps = {\n configuration: configFromTreeView,\n versionSelection: versionSelection,\n selected: selectedEntities,\n isIdSelected: isIdSelected,\n isSelectable: isSelectable,\n visibleTypes: selectableAndVisibleTypesInList,\n selectableTypes: selectableTypes,\n selectColumnType: selectMultiple ? 'checkbox' : 'none',\n toggleSelection: toggleSelection,\n setInitialVersion: setInitialVersion,\n enableSelectAll: selectMultiple,\n setCurrentContainer: setCurrentContainer,\n }\n\n return (\n <SynapseErrorBoundary>\n <div className=\"EntityFinder\">\n <Box\n sx={{\n display: 'flex',\n justifyContent: 'space-between',\n mb: 2.5,\n rowGap: 2,\n columnGap: 4,\n flexWrap: { xs: 'wrap', md: 'nowrap' },\n }}\n >\n <Tabs\n value={currentTab}\n onChange={handleTabChange}\n sx={{ flex: 'none' }}\n >\n <Tab value={EntityFinderTab.BROWSE} label={'Browse'}></Tab>\n <Tab\n value={EntityFinderTab.SELECTED}\n label={\n <Stack\n direction={'row'}\n sx={{\n gap: 0.5,\n alignItems: 'center',\n }}\n >\n <span>Selected</span>\n <Chip\n size={'small'}\n label={selectedEntities.size.toLocaleString()}\n sx={{\n backgroundColor: 'tertiary.500',\n color: 'grey.900',\n height: '21px',\n }}\n ></Chip>\n </Stack>\n }\n ></Tab>\n </Tabs>\n <TextField\n size={'small'}\n placeholder=\"Search by name, wiki content, or SynID\"\n value={searchInput}\n onChange={event => {\n setSearchInput(event.target.value)\n }}\n onKeyDown={(event: any) => {\n if (event.key === 'Enter') {\n const trimmedInput = event.target.value.trim()\n setSearchActive(!!trimmedInput)\n if (trimmedInput) {\n setSearchTerms(trimmedInput.split(/\\s+/))\n setCurrentTab(EntityFinderTab.BROWSE)\n }\n }\n }}\n sx={{\n maxWidth: { xs: '100%', md: '350px' },\n flex: '1 1 350px',\n }}\n slotProps={{\n input: {\n startAdornment: (\n <InputAdornment position=\"start\">\n <SearchIcon />\n </InputAdornment>\n ),\n endAdornment: searchTerms ? (\n <InputAdornment position=\"end\">\n <IconButton\n size={'small'}\n onClick={() => {\n setSearchInput('')\n setSearchTerms(undefined)\n setSearchActive(false)\n }}\n aria-label=\"Clear Search\"\n disabled={!searchInput && !searchActive}\n >\n <ClearIcon />\n </IconButton>\n </InputAdornment>\n ) : undefined,\n },\n }}\n />\n </Box>\n <div\n role={'tabpanel'}\n className={`EntityFinder__MainPanel ${mainPanelClass}`}\n style={{\n display: currentTab === EntityFinderTab.BROWSE ? 'block' : 'none',\n }}\n >\n {/* We have a separate Details component for search in order to preserve state in the other component between searches */}\n {searchActive && (\n <EntityDetailsList\n configuration={\n searchByIdResults && searchByIdResults.length > 0\n ? {\n type: EntityDetailsListDataConfigurationType.HEADER_LIST,\n headerList: searchByIdResults,\n }\n : {\n type: EntityDetailsListDataConfigurationType.ENTITY_SEARCH,\n query: {\n queryTerm: searchTerms,\n booleanQuery:\n searchForOnlyTypesBooleanQuery(selectableTypes),\n },\n }\n }\n versionSelection={versionSelection}\n selectColumnType={selectMultiple ? 'checkbox' : 'none'}\n selected={selectedEntities}\n isIdSelected={isIdSelected}\n isSelectable={isSelectable}\n visibleTypes={selectableTypes}\n selectableTypes={selectableTypes}\n toggleSelection={toggleSelection}\n setInitialVersion={setInitialVersion}\n enableSelectAll={selectMultiple}\n // Intentionally do not pass \"setCurrentContainer\" -- search does not use the tree so it has nothing to update\n setCurrentContainer={undefined}\n />\n )}\n {\n <div style={searchActive ? { display: 'none' } : {}}>\n {treeOnly ? (\n <div>\n <SynapseErrorBoundary>\n <EntityTree\n toggleSelection={toggleSelection}\n showDropdown={true}\n visibleTypes={selectableAndVisibleTypesInTree}\n initialScope={initialScope}\n selectedEntities={selectedEntities}\n projectId={projectId}\n initialContainer={initialContainer}\n currentContainer={currentContainer}\n setCurrentContainer={setCurrentContainer}\n showScopeAsRootNode={false}\n treeNodeType={EntityTreeNodeType.SINGLE_PANE}\n selectableTypes={selectableTypes}\n />\n </SynapseErrorBoundary>\n </div>\n ) : (\n <div className=\"EntityFinderReflexContainer\">\n <ReflexContainer orientation=\"vertical\" windowResizeAware>\n <ReflexElement\n className=\"TreeViewReflexElement\"\n flex={0.24}\n >\n <SynapseErrorBoundary>\n <EntityTree\n selectedEntities={selectedEntities}\n setDetailsViewConfiguration={setConfigFromTreeView}\n showDropdown={true}\n visibleTypes={visibleTypesInTree}\n initialScope={initialScope}\n projectId={projectId}\n initialContainer={initialContainer}\n currentContainer={currentContainer}\n setCurrentContainer={setCurrentContainer}\n treeNodeType={EntityTreeNodeType.DUAL_PANE}\n setBreadcrumbItems={setBreadcrumbs}\n selectableTypes={visibleTypesInTree}\n />\n </SynapseErrorBoundary>\n </ReflexElement>\n <ReflexSplitter></ReflexSplitter>\n <ReflexElement className=\"DetailsViewReflexElement\">\n <SynapseErrorBoundary>\n <EntityDetailsList {...entityDetailsListProps} />\n <Breadcrumbs {...breadcrumbsProps} />\n </SynapseErrorBoundary>\n </ReflexElement>\n </ReflexContainer>\n </div>\n )}\n </div>\n }\n </div>\n <div\n role={'tabpanel'}\n className={'MainPanelSelected'}\n style={{\n display: currentTab === EntityFinderTab.SELECTED ? 'block' : 'none',\n }}\n >\n <EntityDetailsList\n {...entityDetailsListProps}\n configuration={{\n type: EntityDetailsListDataConfigurationType.REFERENCE_LIST,\n referenceList: Array.from(selectedEntitiesSnapshot.values()),\n }}\n />\n </div>\n </div>\n </SynapseErrorBoundary>\n )\n}\n\nexport default EntityFinder\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAqCA,IAAM,KAA2B,OAAO,OAAO,EAAW,EACpD,IAA8B,OAAO,OAAO,EAAW,EACvD,KAA6B,CAAC,EAAW,SAAS,EAAW,OAAO,EAEpE,MACJ,MAIiB,OAAO,OAAO,EAAW,CACb,QAAO,MAAQ,CAAC,EAAY,SAAS,EAAK,CAAC,CACrD,KAAI,OAAS;CAC9B,KAAK;CACL,OAAO,EAAK,UAAU;CACtB,KAAK;CACN,EAAE,EA4BA,IAAL,yBAAA,GAAA;QACE,EAAA,EAAA,SAAA,KAAA,UACA,EAAA,EAAA,WAAA,KAAA;EAFG,KAAA,EAAA,CAGJ;AAED,SAAgB,EAAa,EAC3B,iBACA,cACA,sBAAmB,MACnB,mBACA,qBACA,sBAAmB,GAAqB,SACxC,qBAAkB,IAClB,wBAAqB,GACrB,wBAAqB,IACrB,cAAW,IACX,sBACqC;CACrC,IAAM,EAAE,mBAAgB,IAAmB,EACrC,CAAC,GAAY,KAAiB,GAAM,SAAS,EAAgB,OAAO,EAEpE,CAAC,GAAc,KAAmB,EAAS,GAAM,EAEjD,CAAC,GAAa,KAAkB,EAAiB,GAAG,EAEpD,CAAC,GAAa,KAAkB,GAAoB,EACpD,CAAC,IAAkB,KAAuB,EAA2B,EACzE,OAAO,EAAE,EACV,CAAC,EACI,CAAC,GAAmB,KAAwB,EAEhD,EAAE,CAAC,EACC,CAAC,IAAoB,MACzB,EAA6C,EAC3C,MAAM,EAAuC,QAC9C,CAAC,EAGE,KAAkC,QAChC,CAAC,GAAG,GAAoB,GAAG,EAAgB,EACjD,CAAC,GAAoB,EAAgB,CACtC,EACK,KAAkC,QAChC,CAAC,GAAG,GAAoB,GAAG,EAAgB,EACjD,CAAC,GAAoB,EAAgB,CACtC,EAGK,CAAC,GAAkB,KACvB,EAA8B,EAAiB,EAE3C,IAAc,IAAiB,EAE/B,KAAiB,GACpB,MAA4B;AAC3B,IAAoB,EAClB,UACD,CAAC;IAEJ,CAAC,EAAoB,CACtB,EAEK,EAAE,qBAAkB,oBAAiB,iBAAc,yBACvD,GAAmB,EAAe;AAEpC,SAAgB;AACd,MAAI,GAAiB;GACnB,IAAI,IAAM,IAAwB;AAOlC,GANA,IAAM,EAAI,eAAc,MAAc;AACpC,MAAgB,SAAQ,MAAa;AACnC,OAAW,IAAI,EAAU,UAAU,EAAU;MAC7C;KACF,EAEF,EAAa,EAAI;;IAElB,CAAC,GAAiB,EAAa,CAAC;CAGnC,IAAM,CAAC,GAA0B,MAC/B,EAAS,EAAiB,EAEtB,IAAe,GAClB,MACQ,EAAiB,IAAI,EAAO,GAAG,EAExC,CAAC,EAAiB,CACnB,EAEK,IAAe,GAClB,MAA+B;EAC9B,IAAM,IAAO,EAAwB,EAAO;AAC5C,SAAO,EAAgB,SAAS,EAAK;IAEvC,CAAC,EAAgB,CAClB;AAOD,CALA,QAAgB;AAEd,IAAiB,MAAM,KAAK,EAAiB,QAAQ,CAAC,CAAC;IACtD,CAAC,GAAkB,EAAiB,CAAC,EAExC,QAAgB;AACd,MAAI,GAAa,WAAW,GAAG;GAC7B,IAAM,IAAsB,EAAW,EAAY,GAAG;AACtD,GAAI,KACF,EAAc,iBAAiB,CAAC,EAAoB,EAAE,EAAY,CAC/D,MAAK,MAAY;AAChB,MAAqB,EAAS,QAAQ;KACtC,CACD,OAAM,MAAK,EAAY,EAAE,CAAC;QAG/B,GAAqB,EAAE,CAAC;IAEzB;EAAC;EAAa;EAAa;EAAY,CAAC;CAE3C,IAAM,MACJ,GACA,MACG;AAEH,EADA,GAA4B,EAAiB,EAC7C,EAAc,EAAS;IAGnB,KAAiB,IACnB,oBACA,IACA,wBACA,qBAEE,IAAiD;EACrD,eAAe;EACG;EAClB,UAAU;EACI;EACA;EACd,cAAc;EACG;EACjB,kBAAkB,IAAiB,aAAa;EAC/B;EACE;EACnB,iBAAiB;EACI;EACtB;AAED,QACE,kBAAC,GAAD,EAAA,UACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,IAAD;IACE,IAAI;KACF,SAAS;KACT,gBAAgB;KAChB,IAAI;KACJ,QAAQ;KACR,WAAW;KACX,UAAU;MAAE,IAAI;MAAQ,IAAI;MAAU;KACvC;cARH,CAUE,kBAAC,IAAD;KACE,OAAO;KACP,UAAU;KACV,IAAI,EAAE,MAAM,QAAQ;eAHtB,CAKE,kBAAC,GAAD;MAAK,OAAO,EAAgB;MAAQ,OAAO;MAAgB,CAAA,EAC3D,kBAAC,GAAD;MACE,OAAO,EAAgB;MACvB,OACE,kBAAC,IAAD;OACE,WAAW;OACX,IAAI;QACF,KAAK;QACL,YAAY;QACb;iBALH,CAOE,kBAAC,QAAD,EAAA,UAAM,YAAe,CAAA,EACrB,kBAAC,IAAD;QACE,MAAM;QACN,OAAO,EAAiB,KAAK,gBAAgB;QAC7C,IAAI;SACF,iBAAiB;SACjB,OAAO;SACP,QAAQ;SACT;QACK,CAAA,CACF;;MAEL,CAAA,CACF;QACP,kBAAC,IAAD;KACE,MAAM;KACN,aAAY;KACZ,OAAO;KACP,WAAU,MAAS;AACjB,QAAe,EAAM,OAAO,MAAM;;KAEpC,YAAY,MAAe;AACzB,UAAI,EAAM,QAAQ,SAAS;OACzB,IAAM,IAAe,EAAM,OAAO,MAAM,MAAM;AAE9C,OADA,EAAgB,CAAC,CAAC,EAAa,EAC3B,MACF,EAAe,EAAa,MAAM,MAAM,CAAC,EACzC,EAAc,EAAgB,OAAO;;;KAI3C,IAAI;MACF,UAAU;OAAE,IAAI;OAAQ,IAAI;OAAS;MACrC,MAAM;MACP;KACD,WAAW,EACT,OAAO;MACL,gBACE,kBAAC,GAAD;OAAgB,UAAS;iBACvB,kBAAC,IAAD,EAAc,CAAA;OACC,CAAA;MAEnB,cAAc,IACZ,kBAAC,GAAD;OAAgB,UAAS;iBACvB,kBAAC,GAAD;QACE,MAAM;QACN,eAAe;AAGb,SAFA,EAAe,GAAG,EAClB,EAAe,KAAA,EAAU,EACzB,EAAgB,GAAM;;QAExB,cAAW;QACX,UAAU,CAAC,KAAe,CAAC;kBAE3B,kBAAC,IAAD,EAAa,CAAA;QACF,CAAA;OACE,CAAA,GACf,KAAA;MACL,EACF;KACD,CAAA,CACE;;GACN,kBAAC,OAAD;IACE,MAAM;IACN,WAAW,2BAA2B;IACtC,OAAO,EACL,SAAS,MAAe,EAAgB,SAAS,UAAU,QAC5D;cALH,CAQG,KACC,kBAAC,GAAD;KACE,eACE,KAAqB,EAAkB,SAAS,IAC5C;MACE,MAAM,EAAuC;MAC7C,YAAY;MACb,GACD;MACE,MAAM,EAAuC;MAC7C,OAAO;OACL,WAAW;OACX,cACE,GAA+B,EAAgB;OAClD;MACF;KAEW;KAClB,kBAAkB,IAAiB,aAAa;KAChD,UAAU;KACI;KACA;KACd,cAAc;KACG;KACA;KACE;KACnB,iBAAiB;KAEjB,qBAAqB,KAAA;KACrB,CAAA,EAGF,kBAAC,OAAD;KAAK,OAAO,IAAe,EAAE,SAAS,QAAQ,GAAG,EAAE;eAChD,IACC,kBAAC,OAAD,EAAA,UACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;MACmB;MACjB,cAAc;MACd,cAAc;MACA;MACI;MACP;MACO;MACA;MACG;MACrB,qBAAqB;MACrB,cAAc,EAAmB;MAChB;MACjB,CAAA,EACmB,CAAA,EACnB,CAAA,GAEN,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,IAAD;OAAiB,aAAY;OAAW,mBAAA;iBAAxC;QACE,kBAAC,GAAD;SACE,WAAU;SACV,MAAM;mBAEN,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;UACoB;UAClB,6BAA6B;UAC7B,cAAc;UACd,cAAc;UACA;UACH;UACO;UACA;UACG;UACrB,cAAc,EAAmB;UACjC,oBAAoB;UACpB,iBAAiB;UACjB,CAAA,EACmB,CAAA;SACT,CAAA;QAChB,kBAAC,IAAD,EAAiC,CAAA;QACjC,kBAAC,GAAD;SAAe,WAAU;mBACvB,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAmB,GAAI,GAA0B,CAAA,EACjD,kBAAC,IAAD,EAAa,GAAI,IAAoB,CAAA,CAChB,EAAA,CAAA;SACT,CAAA;QACA;;MACd,CAAA;KAEJ,CAAA,CAEJ;;GACN,kBAAC,OAAD;IACE,MAAM;IACN,WAAW;IACX,OAAO,EACL,SAAS,MAAe,EAAgB,WAAW,UAAU,QAC9D;cAED,kBAAC,GAAD;KACE,GAAI;KACJ,eAAe;MACb,MAAM,EAAuC;MAC7C,eAAe,MAAM,KAAK,EAAyB,QAAQ,CAAC;MAC7D;KACD,CAAA;IACE,CAAA;GACF;KACe,CAAA"}
1
+ {"version":3,"file":"EntityFinder.js","names":[],"sources":["../../../src/components/EntityFinder/EntityFinder.tsx"],"sourcesContent":["import SynapseClient from '@/synapse-client'\nimport { useSynapseContext } from '@/utils/context/SynapseContext'\nimport { getEntityTypeFromHeader } from '@/utils/functions/EntityTypeUtils'\nimport { parseSynId } from '@/utils/functions/RegularExpressions'\nimport ClearIcon from '@mui/icons-material/Clear'\nimport SearchIcon from '@mui/icons-material/Search'\nimport {\n Box,\n Chip,\n IconButton,\n InputAdornment,\n Stack,\n Tab,\n Tabs,\n TextField,\n} from '@mui/material'\nimport { EntityType } from '@sage-bionetworks/synapse-client'\nimport { KeyValue, Reference } from '@sage-bionetworks/synapse-types'\nimport { Map } from 'immutable'\nimport React, { useCallback, useEffect, useMemo, useState } from 'react'\nimport { useErrorHandler } from 'react-error-boundary'\nimport { ReflexContainer, ReflexElement, ReflexSplitter } from 'react-reflex'\nimport 'react-reflex/styles.css'\nimport { SynapseErrorBoundary } from '../error/ErrorBanner'\nimport { BreadcrumbItem, Breadcrumbs, BreadcrumbsProps } from './Breadcrumbs'\nimport {\n EntityDetailsList,\n EntityDetailsListDataConfiguration,\n EntityDetailsListDataConfigurationType,\n EntityDetailsListProps,\n} from './details/EntityDetailsList'\nimport { EntityFinderHeader } from './EntityFinderHeader'\nimport { EntityTree, EntityTreeContainer, FinderScope } from './tree/EntityTree'\nimport { EntityTreeNodeType } from './tree/VirtualizedTree'\nimport { useEntitySelection } from './useEntitySelection'\nimport { VersionSelectionType } from './VersionSelectionType'\n\nconst DEFAULT_SELECTABLE_TYPES = Object.values(EntityType)\nconst TABLE_DEFAULT_VISIBLE_TYPES = Object.values(EntityType)\nconst TREE_DEFAULT_VISIBLE_TYPES = [EntityType.project, EntityType.folder]\n\nconst searchForOnlyTypesBooleanQuery = (\n entityTypes: EntityType[],\n): KeyValue[] => {\n // Boolean query terms will be combined with AND, and there's no way to OR.\n // So we will negate searching for all omitted types.\n const allTypes = Object.values(EntityType)\n const typesToOmit = allTypes.filter(type => !entityTypes.includes(type))\n return typesToOmit.map(type => ({\n key: 'node_type',\n value: type.toString(),\n not: true,\n }))\n}\n\nexport type EntityFinderProps = {\n /** Whether it is possible to select multiple entities */\n selectMultiple: boolean\n /** Callback invoked when the selection changes */\n onSelectedChange: (selected: Reference[]) => void\n /** The initial appearance of the entity finder. Possible values include \"Current Project\", \"All Projects\", \"Projects Created By Me\", \"My Favorites\" */\n initialScope: FinderScope\n /** The SynID of the 'Current Project'. If this is not a defined, then the scope cannot be \"Current Project\" */\n projectId?: string\n /** The SynID of the entity that should open by default. If this is a Syn ID, then it must be in the project specified in `projectId` */\n initialContainer: string | 'root' | null\n /** Determines if versions are selectable, and if so, how they should be shown. Default is \"TRACKED\" */\n versionSelection?: VersionSelectionType\n /** The entity types to show in the details view (right pane). Any types specified in `selectableTypes` will automatically be included. */\n visibleTypesInList?: EntityType[]\n /** The entity types that may be selected. Types in `visibleTypesInList` that are not in `selectableTypes` will appear as disabled options. Only the types in `selectableTypes` will appear in search */\n selectableTypes?: EntityType[]\n /** The types to show in the tree used to navigate. If `treeOnly` is true, any types specified in `selectableTypes` will automatically be included. */\n visibleTypesInTree?: EntityType[]\n /** Whether to show only the tree. If `true`, the tree will be used to make selections */\n treeOnly?: boolean\n /** If provided, the initial selection will be set to this list of references. The selection will be reset to this value if this object changes, so it should be memoized. */\n initialSelected?: Reference[]\n}\n\nenum EntityFinderTab {\n BROWSE,\n SELECTED,\n}\n\nexport function EntityFinder({\n initialScope,\n projectId,\n initialContainer = null,\n selectMultiple,\n onSelectedChange,\n versionSelection = VersionSelectionType.TRACKED,\n selectableTypes = DEFAULT_SELECTABLE_TYPES,\n visibleTypesInList = TABLE_DEFAULT_VISIBLE_TYPES,\n visibleTypesInTree = TREE_DEFAULT_VISIBLE_TYPES,\n treeOnly = false,\n initialSelected,\n}: EntityFinderProps): React.ReactNode {\n const { accessToken } = useSynapseContext()\n const [currentTab, setCurrentTab] = React.useState(EntityFinderTab.BROWSE)\n\n const [searchActive, setSearchActive] = useState(false)\n // The raw value of the search input box:\n const [searchInput, setSearchInput] = useState<string>('')\n // The \"parsed\" search terms, which are only calculated when Enter is pressed:\n const [searchTerms, setSearchTerms] = useState<string[]>()\n const [breadcrumbsProps, setBreadcrumbsProps] = useState<BreadcrumbsProps>({\n items: [],\n })\n const [searchByIdResults, setSearchByIdResults] = useState<\n EntityFinderHeader[]\n >([])\n const [configFromTreeView, setConfigFromTreeView] =\n useState<EntityDetailsListDataConfiguration>({\n type: EntityDetailsListDataConfigurationType.PROMPT,\n })\n\n // If a type is selectable, it should be visible in the tree/list (depending on treeOnly)\n const selectableAndVisibleTypesInTree = useMemo(\n () => [...visibleTypesInTree, ...selectableTypes],\n [visibleTypesInTree, selectableTypes],\n )\n const selectableAndVisibleTypesInList = useMemo(\n () => [...visibleTypesInList, ...selectableTypes],\n [visibleTypesInList, selectableTypes],\n )\n\n // For dual-pane, this state variable indicates which container is selected in the tree view and should be shown in the table view\n const [currentContainer, setCurrentContainer] =\n useState<EntityTreeContainer>(initialContainer)\n\n const handleError = useErrorHandler()\n\n const setBreadcrumbs = useCallback(\n (items: BreadcrumbItem[]) => {\n setBreadcrumbsProps({\n items,\n })\n },\n [setBreadcrumbsProps],\n )\n\n const { selectedEntities, toggleSelection, setSelection, setInitialVersion } =\n useEntitySelection(selectMultiple)\n\n useEffect(() => {\n if (initialSelected) {\n let map = Map<string, Reference>()\n map = map.withMutations(mutableMap => {\n initialSelected.forEach(reference => {\n mutableMap.set(reference.targetId, reference)\n })\n })\n\n setSelection(map)\n }\n }, [initialSelected, setSelection])\n\n // A snapshot of the selectedEntities used to populate the selection list, allowing deselection of entities without removing them from the list.\n const [selectedEntitiesSnapshot, setSelectedEntitiesSnapshot] =\n useState(selectedEntities)\n\n const isIdSelected = useCallback(\n (entity: EntityFinderHeader) => {\n return selectedEntities.has(entity.id)\n },\n [selectedEntities],\n )\n\n const isSelectable = useCallback(\n (entity: EntityFinderHeader) => {\n const type = getEntityTypeFromHeader(entity)\n return selectableTypes.includes(type)\n },\n [selectableTypes],\n )\n\n useEffect(() => {\n // When it changes, convert the map of selected items to a list of references and invoke the callback\n onSelectedChange(Array.from(selectedEntities.values()))\n }, [selectedEntities, onSelectedChange])\n\n useEffect(() => {\n if (searchTerms?.length === 1) {\n const searchTermReference = parseSynId(searchTerms[0])\n if (searchTermReference) {\n SynapseClient.getEntityHeaders([searchTermReference], accessToken)\n .then(response => {\n setSearchByIdResults(response.results)\n })\n .catch(e => handleError(e))\n }\n } else {\n setSearchByIdResults([])\n }\n }, [accessToken, searchTerms, handleError])\n\n const handleTabChange = (\n _event: React.SyntheticEvent,\n newValue: EntityFinderTab,\n ) => {\n setSelectedEntitiesSnapshot(selectedEntities)\n setCurrentTab(newValue)\n }\n\n const mainPanelClass = searchActive\n ? 'MainPanelSearch'\n : treeOnly\n ? 'MainPanelSinglePane'\n : 'MainPanelDualPane'\n\n const entityDetailsListProps: EntityDetailsListProps = {\n configuration: configFromTreeView,\n versionSelection: versionSelection,\n selected: selectedEntities,\n isIdSelected: isIdSelected,\n isSelectable: isSelectable,\n visibleTypes: selectableAndVisibleTypesInList,\n selectableTypes: selectableTypes,\n selectColumnType: selectMultiple ? 'checkbox' : 'none',\n toggleSelection: toggleSelection,\n setInitialVersion: setInitialVersion,\n enableSelectAll: selectMultiple,\n setCurrentContainer: setCurrentContainer,\n }\n\n return (\n <SynapseErrorBoundary>\n <div className=\"EntityFinder\">\n <Box\n sx={{\n display: 'flex',\n justifyContent: 'space-between',\n mb: 2.5,\n rowGap: 2,\n columnGap: 4,\n flexWrap: { xs: 'wrap', md: 'nowrap' },\n }}\n >\n <Tabs\n value={currentTab}\n onChange={handleTabChange}\n sx={{ flex: 'none' }}\n >\n <Tab value={EntityFinderTab.BROWSE} label={'Browse'}></Tab>\n <Tab\n value={EntityFinderTab.SELECTED}\n label={\n <Stack\n direction={'row'}\n sx={{\n gap: 0.5,\n alignItems: 'center',\n }}\n >\n <span>Selected</span>\n <Chip\n size={'small'}\n label={selectedEntities.size.toLocaleString()}\n sx={{\n backgroundColor: 'tertiary.500',\n color: 'grey.900',\n height: '21px',\n }}\n ></Chip>\n </Stack>\n }\n ></Tab>\n </Tabs>\n <TextField\n size={'small'}\n placeholder=\"Search by name, wiki content, or SynID\"\n value={searchInput}\n onChange={event => {\n setSearchInput(event.target.value)\n }}\n onKeyDown={(event: any) => {\n if (event.key === 'Enter') {\n const trimmedInput = event.target.value.trim()\n setSearchActive(!!trimmedInput)\n if (trimmedInput) {\n setSearchTerms(trimmedInput.split(/\\s+/))\n setCurrentTab(EntityFinderTab.BROWSE)\n }\n }\n }}\n sx={{\n maxWidth: { xs: '100%', md: '350px' },\n flex: '1 1 350px',\n }}\n slotProps={{\n input: {\n startAdornment: (\n <InputAdornment position=\"start\">\n <SearchIcon />\n </InputAdornment>\n ),\n endAdornment: searchTerms ? (\n <InputAdornment position=\"end\">\n <IconButton\n size={'small'}\n onClick={() => {\n setSearchInput('')\n setSearchTerms(undefined)\n setSearchActive(false)\n }}\n aria-label=\"Clear Search\"\n disabled={!searchInput && !searchActive}\n >\n <ClearIcon />\n </IconButton>\n </InputAdornment>\n ) : undefined,\n },\n }}\n />\n </Box>\n <div\n role={'tabpanel'}\n className={`EntityFinder__MainPanel ${mainPanelClass}`}\n style={{\n display: currentTab === EntityFinderTab.BROWSE ? 'block' : 'none',\n }}\n >\n {/* We have a separate Details component for search in order to preserve state in the other component between searches */}\n {searchActive && (\n <EntityDetailsList\n configuration={\n searchByIdResults && searchByIdResults.length > 0\n ? {\n type: EntityDetailsListDataConfigurationType.HEADER_LIST,\n headerList: searchByIdResults,\n }\n : {\n type: EntityDetailsListDataConfigurationType.ENTITY_SEARCH,\n query: {\n queryTerm: searchTerms,\n booleanQuery:\n searchForOnlyTypesBooleanQuery(selectableTypes),\n },\n }\n }\n versionSelection={versionSelection}\n selectColumnType={selectMultiple ? 'checkbox' : 'none'}\n selected={selectedEntities}\n isIdSelected={isIdSelected}\n isSelectable={isSelectable}\n visibleTypes={selectableTypes}\n selectableTypes={selectableTypes}\n toggleSelection={toggleSelection}\n setInitialVersion={setInitialVersion}\n enableSelectAll={selectMultiple}\n // Intentionally do not pass \"setCurrentContainer\" -- search does not use the tree so it has nothing to update\n setCurrentContainer={undefined}\n />\n )}\n {\n <div style={searchActive ? { display: 'none' } : {}}>\n {treeOnly ? (\n <div>\n <SynapseErrorBoundary>\n <EntityTree\n toggleSelection={toggleSelection}\n showDropdown={true}\n visibleTypes={selectableAndVisibleTypesInTree}\n initialScope={initialScope}\n selectedEntities={selectedEntities}\n projectId={projectId}\n initialContainer={initialContainer}\n currentContainer={currentContainer}\n setCurrentContainer={setCurrentContainer}\n showScopeAsRootNode={false}\n treeNodeType={EntityTreeNodeType.SINGLE_PANE}\n selectableTypes={selectableTypes}\n />\n </SynapseErrorBoundary>\n </div>\n ) : (\n <div className=\"EntityFinderReflexContainer\">\n <ReflexContainer orientation=\"vertical\" windowResizeAware>\n <ReflexElement\n className=\"TreeViewReflexElement\"\n flex={0.24}\n >\n <SynapseErrorBoundary>\n <EntityTree\n selectedEntities={selectedEntities}\n setDetailsViewConfiguration={setConfigFromTreeView}\n showDropdown={true}\n visibleTypes={visibleTypesInTree}\n initialScope={initialScope}\n projectId={projectId}\n initialContainer={initialContainer}\n currentContainer={currentContainer}\n setCurrentContainer={setCurrentContainer}\n treeNodeType={EntityTreeNodeType.DUAL_PANE}\n setBreadcrumbItems={setBreadcrumbs}\n selectableTypes={visibleTypesInTree}\n />\n </SynapseErrorBoundary>\n </ReflexElement>\n <ReflexSplitter></ReflexSplitter>\n <ReflexElement className=\"DetailsViewReflexElement\">\n <SynapseErrorBoundary>\n <EntityDetailsList {...entityDetailsListProps} />\n <Breadcrumbs {...breadcrumbsProps} />\n </SynapseErrorBoundary>\n </ReflexElement>\n </ReflexContainer>\n </div>\n )}\n </div>\n }\n </div>\n <div\n role={'tabpanel'}\n className={'MainPanelSelected'}\n style={{\n display: currentTab === EntityFinderTab.SELECTED ? 'block' : 'none',\n }}\n >\n <EntityDetailsList\n {...entityDetailsListProps}\n configuration={{\n type: EntityDetailsListDataConfigurationType.REFERENCE_LIST,\n referenceList: Array.from(selectedEntitiesSnapshot.values()),\n }}\n />\n </div>\n </div>\n </SynapseErrorBoundary>\n )\n}\n\nexport default EntityFinder\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"VersionSelectionType.js","names":[],"sources":["../../../src/components/EntityFinder/VersionSelectionType.ts"],"sourcesContent":["/**\n * Documents the possible EntityFinder version selection configurations\n */\nexport enum VersionSelectionType {\n /** Versions cannot be selected. In dual-pane mode, the version column will not be shown. */\n DISALLOWED = 'DISALLOWED',\n /** A numbered version must be selected. The current version of tables will not be shown. */\n REQUIRED = 'REQUIRED',\n /**\n * Versions can be selected, including \"Always Latest\" version for any versionable entity type.\n * This should be selected if updates to the entity will not be \"tracked\" by the use case,\n * i.e. the widget will update when the entity is updated.\n */\n TRACKED = 'TRACKED',\n /**\n * Versions can be selected. Tables and views will allow selection of the \"Current\"/\"Draft\" version.\n * This should be selected if updates to the entity will not be \"tracked\" by the use case.\n */\n UNTRACKED = 'UNTRACKED',\n}\n"],"mappings":";AAGA,IAAY,IAAL,yBAAA,GAAA;QAEL,EAAA,aAAA,cAEA,EAAA,WAAA,YAMA,EAAA,UAAA,WAKA,EAAA,YAAA;KACD"}
1
+ {"version":3,"file":"VersionSelectionType.js","names":[],"sources":["../../../src/components/EntityFinder/VersionSelectionType.ts"],"sourcesContent":["/**\n * Documents the possible EntityFinder version selection configurations\n */\nexport enum VersionSelectionType {\n /** Versions cannot be selected. In dual-pane mode, the version column will not be shown. */\n DISALLOWED = 'DISALLOWED',\n /** A numbered version must be selected. The current version of tables will not be shown. */\n REQUIRED = 'REQUIRED',\n /**\n * Versions can be selected, including \"Always Latest\" version for any versionable entity type.\n * This should be selected if updates to the entity will not be \"tracked\" by the use case,\n * i.e. the widget will update when the entity is updated.\n */\n TRACKED = 'TRACKED',\n /**\n * Versions can be selected. Tables and views will allow selection of the \"Current\"/\"Draft\" version.\n * This should be selected if updates to the entity will not be \"tracked\" by the use case.\n */\n UNTRACKED = 'UNTRACKED',\n}\n"],"mappings":";AAGA,IAAY,IAAL,yBAAA,GAAA;QAEL,EAAA,aAAa,cAEb,EAAA,WAAW,YAMX,EAAA,UAAU,WAKV,EAAA,YAAY;KACb"}
@@ -1 +1 @@
1
- {"version":3,"file":"EntityChildrenDetails.js","names":[],"sources":["../../../../../src/components/EntityFinder/details/configurations/EntityChildrenDetails.tsx"],"sourcesContent":["import { useGetEntityChildrenInfinite } from '@/synapse-queries/entity/useGetEntityChildren'\nimport useGetIsAllSelectedFromInfiniteList from '@/utils/hooks/useGetIsAllSelectedInfiniteList'\nimport { Direction, SortBy } from '@sage-bionetworks/synapse-types'\nimport { SortingState } from '@tanstack/react-table'\nimport { useState } from 'react'\nimport { EntityDetailsListSharedProps } from '../EntityDetailsList'\nimport { DetailsView, DetailsViewColumn } from '../view/DetailsView'\n\ntype EntityChildrenDetailsProps = EntityDetailsListSharedProps & {\n parentContainerId: string\n}\n\nconst sortableColumns = [\n DetailsViewColumn.NAME,\n DetailsViewColumn.CREATED_ON,\n DetailsViewColumn.MODIFIED_ON,\n]\n\n/**\n * Translates TanStack table's SortBy state to the SortBy used in the Synapse getEntityChildren API\n */\nfunction convertColumnToSortBy(column: DetailsViewColumn): SortBy | undefined {\n switch (column) {\n case DetailsViewColumn.NAME:\n return SortBy.NAME\n case DetailsViewColumn.CREATED_ON:\n return SortBy.CREATED_ON\n case DetailsViewColumn.MODIFIED_ON:\n return SortBy.MODIFIED_ON\n }\n\n return undefined\n}\n\nexport function EntityChildrenDetails({\n parentContainerId,\n ...sharedProps\n}: EntityChildrenDetailsProps) {\n const [sortingState, setSortingState] = useState<SortingState>([\n {\n id: DetailsViewColumn.NAME,\n desc: false,\n },\n ])\n\n const getChildrenInfiniteRequestObject = {\n parentId: parentContainerId,\n includeTotalChildCount: true,\n includeTypes: sharedProps.visibleTypes,\n sortBy: sortingState[0]\n ? convertColumnToSortBy(sortingState[0].id as DetailsViewColumn)\n : undefined,\n sortDirection: sortingState[0]\n ? sortingState[0].desc\n ? Direction.DESC\n : Direction.ASC\n : undefined,\n }\n const { data, isLoading, isFetchingNextPage, hasNextPage, fetchNextPage } =\n useGetEntityChildrenInfinite(getChildrenInfiniteRequestObject, {\n throwOnError: true,\n })\n const entities = data?.pages.flatMap(page => page.page) ?? []\n const totalEntities = data?.pages[0].totalChildCount\n\n const selectAllCheckboxState = useGetIsAllSelectedFromInfiniteList(\n entities,\n sharedProps.selected.size,\n sharedProps.isIdSelected,\n sharedProps.isSelectable,\n hasNextPage,\n fetchNextPage,\n isFetchingNextPage,\n )\n\n return (\n <DetailsView\n entities={entities}\n isLoading={isLoading}\n hasNextPage={hasNextPage}\n fetchNextPage={fetchNextPage}\n isFetchingNextPage={isFetchingNextPage}\n enableSorting={true}\n enableMultiSort={false}\n sortableColumns={sortableColumns}\n sorting={sortingState}\n onSortingChange={setSortingState}\n selectAllIsChecked={selectAllCheckboxState}\n getChildrenInfiniteRequestObject={getChildrenInfiniteRequestObject}\n totalEntities={totalEntities}\n {...sharedProps}\n />\n )\n}\n"],"mappings":";;;;;;;AAYA,IAAM,IAAkB;CACtB,EAAkB;CAClB,EAAkB;CAClB,EAAkB;CACnB;AAKD,SAAS,EAAsB,GAA+C;AAC5E,SAAQ,GAAR;EACE,KAAK,EAAkB,KACrB,QAAO,EAAO;EAChB,KAAK,EAAkB,WACrB,QAAO,EAAO;EAChB,KAAK,EAAkB,YACrB,QAAO,EAAO;;;AAMpB,SAAgB,EAAsB,EACpC,sBACA,GAAG,KAC0B;CAC7B,IAAM,CAAC,GAAc,KAAmB,EAAuB,CAC7D;EACE,IAAI,EAAkB;EACtB,MAAM;EACP,CACF,CAAC,EAEI,IAAmC;EACvC,UAAU;EACV,wBAAwB;EACxB,cAAc,EAAY;EAC1B,QAAQ,EAAa,KACjB,EAAsB,EAAa,GAAG,GAAwB,GAC9D,KAAA;EACJ,eAAe,EAAa,KACxB,EAAa,GAAG,OACd,EAAU,OACV,EAAU,MACZ,KAAA;EACL,EACK,EAAE,SAAM,cAAW,uBAAoB,gBAAa,qBACxD,EAA6B,GAAkC,EAC7D,cAAc,IACf,CAAC,EACE,IAAW,GAAM,MAAM,SAAQ,MAAQ,EAAK,KAAK,IAAI,EAAE,EACvD,IAAgB,GAAM,MAAM,GAAG;AAYrC,QACE,kBAAC,GAAD;EACY;EACC;EACE;EACE;EACK;EACpB,eAAe;EACf,iBAAiB;EACA;EACjB,SAAS;EACT,iBAAiB;EACjB,oBAtB2B,EAC7B,GACA,EAAY,SAAS,MACrB,EAAY,cACZ,EAAY,cACZ,GACA,GACA,EACD;EAeqC;EACnB;EACf,GAAI;EACJ,CAAA"}
1
+ {"version":3,"file":"EntityChildrenDetails.js","names":[],"sources":["../../../../../src/components/EntityFinder/details/configurations/EntityChildrenDetails.tsx"],"sourcesContent":["import { useGetEntityChildrenInfinite } from '@/synapse-queries/entity/useGetEntityChildren'\nimport useGetIsAllSelectedFromInfiniteList from '@/utils/hooks/useGetIsAllSelectedInfiniteList'\nimport { Direction, SortBy } from '@sage-bionetworks/synapse-types'\nimport { SortingState } from '@tanstack/react-table'\nimport { useState } from 'react'\nimport { EntityDetailsListSharedProps } from '../EntityDetailsList'\nimport { DetailsView, DetailsViewColumn } from '../view/DetailsView'\n\ntype EntityChildrenDetailsProps = EntityDetailsListSharedProps & {\n parentContainerId: string\n}\n\nconst sortableColumns = [\n DetailsViewColumn.NAME,\n DetailsViewColumn.CREATED_ON,\n DetailsViewColumn.MODIFIED_ON,\n]\n\n/**\n * Translates TanStack table's SortBy state to the SortBy used in the Synapse getEntityChildren API\n */\nfunction convertColumnToSortBy(column: DetailsViewColumn): SortBy | undefined {\n switch (column) {\n case DetailsViewColumn.NAME:\n return SortBy.NAME\n case DetailsViewColumn.CREATED_ON:\n return SortBy.CREATED_ON\n case DetailsViewColumn.MODIFIED_ON:\n return SortBy.MODIFIED_ON\n }\n\n return undefined\n}\n\nexport function EntityChildrenDetails({\n parentContainerId,\n ...sharedProps\n}: EntityChildrenDetailsProps) {\n const [sortingState, setSortingState] = useState<SortingState>([\n {\n id: DetailsViewColumn.NAME,\n desc: false,\n },\n ])\n\n const getChildrenInfiniteRequestObject = {\n parentId: parentContainerId,\n includeTotalChildCount: true,\n includeTypes: sharedProps.visibleTypes,\n sortBy: sortingState[0]\n ? convertColumnToSortBy(sortingState[0].id as DetailsViewColumn)\n : undefined,\n sortDirection: sortingState[0]\n ? sortingState[0].desc\n ? Direction.DESC\n : Direction.ASC\n : undefined,\n }\n const { data, isLoading, isFetchingNextPage, hasNextPage, fetchNextPage } =\n useGetEntityChildrenInfinite(getChildrenInfiniteRequestObject, {\n throwOnError: true,\n })\n const entities = data?.pages.flatMap(page => page.page) ?? []\n const totalEntities = data?.pages[0].totalChildCount\n\n const selectAllCheckboxState = useGetIsAllSelectedFromInfiniteList(\n entities,\n sharedProps.selected.size,\n sharedProps.isIdSelected,\n sharedProps.isSelectable,\n hasNextPage,\n fetchNextPage,\n isFetchingNextPage,\n )\n\n return (\n <DetailsView\n entities={entities}\n isLoading={isLoading}\n hasNextPage={hasNextPage}\n fetchNextPage={fetchNextPage}\n isFetchingNextPage={isFetchingNextPage}\n enableSorting={true}\n enableMultiSort={false}\n sortableColumns={sortableColumns}\n sorting={sortingState}\n onSortingChange={setSortingState}\n selectAllIsChecked={selectAllCheckboxState}\n getChildrenInfiniteRequestObject={getChildrenInfiniteRequestObject}\n totalEntities={totalEntities}\n {...sharedProps}\n />\n )\n}\n"],"mappings":";;;;;;;AAYA,IAAM,IAAkB;CACtB,EAAkB;CAClB,EAAkB;CAClB,EAAkB;CACnB;AAKD,SAAS,EAAsB,GAA+C;AAC5E,SAAQ,GAAR;EACE,KAAK,EAAkB,KACrB,QAAO,EAAO;EAChB,KAAK,EAAkB,WACrB,QAAO,EAAO;EAChB,KAAK,EAAkB,YACrB,QAAO,EAAO;;;AAMpB,SAAgB,EAAsB,EACpC,sBACA,GAAG,KAC0B;CAC7B,IAAM,CAAC,GAAc,KAAmB,EAAuB,CAC7D;EACE,IAAI,EAAkB;EACtB,MAAM;EACP,CACF,CAAC,EAEI,IAAmC;EACvC,UAAU;EACV,wBAAwB;EACxB,cAAc,EAAY;EAC1B,QAAQ,EAAa,KACjB,EAAsB,EAAa,GAAG,GAAwB,GAC9D,KAAA;EACJ,eAAe,EAAa,KACxB,EAAa,GAAG,OACd,EAAU,OACV,EAAU,MACZ,KAAA;EACL,EACK,EAAE,SAAM,cAAW,uBAAoB,gBAAa,qBACxD,EAA6B,GAAkC,EAC7D,cAAc,IACf,CAAC,EACE,IAAW,GAAM,MAAM,SAAQ,MAAQ,EAAK,KAAK,IAAI,EAAE,EACvD,IAAgB,GAAM,MAAM,GAAG;AAYrC,QACE,kBAAC,GAAD;EACY;EACC;EACE;EACE;EACK;EACpB,eAAe;EACf,iBAAiB;EACA;EACjB,SAAS;EACT,iBAAiB;EACjB,oBAtB2B,EAC7B,GACA,EAAY,SAAS,MACrB,EAAY,cACZ,EAAY,cACZ,GACA,GACA,EAesB;EACc;EACnB;EACf,GAAI;EACJ,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"FavoritesDetails.js","names":[],"sources":["../../../../../src/components/EntityFinder/details/configurations/FavoritesDetails.tsx"],"sourcesContent":["import { useGetFavoritesInfinite } from '@/synapse-queries/user/useFavorites'\nimport useGetIsAllSelectedFromInfiniteList from '@/utils/hooks/useGetIsAllSelectedInfiniteList'\nimport { EntityDetailsListSharedProps } from '../EntityDetailsList'\nimport { DetailsView } from '../view/DetailsView'\n\ntype FavoritesDetailsProps = EntityDetailsListSharedProps\n\nexport function FavoritesDetails({ ...sharedProps }: FavoritesDetailsProps) {\n const { data, isLoading, hasNextPage, fetchNextPage, isFetchingNextPage } =\n useGetFavoritesInfinite('NAME', 'ASC', { throwOnError: true })\n\n const entities = data?.pages.flatMap(page => page.results) ?? []\n\n const selectAllCheckboxState = useGetIsAllSelectedFromInfiniteList(\n entities,\n sharedProps.selected.size,\n sharedProps.isIdSelected,\n sharedProps.isSelectable,\n hasNextPage,\n fetchNextPage,\n isFetchingNextPage,\n )\n\n return (\n <DetailsView\n entities={entities}\n isLoading={isLoading}\n hasNextPage={hasNextPage}\n fetchNextPage={fetchNextPage}\n isFetchingNextPage={isFetchingNextPage}\n selectAllIsChecked={selectAllCheckboxState}\n {...sharedProps}\n />\n )\n}\n"],"mappings":";;;;;AAOA,SAAgB,EAAiB,EAAE,GAAG,KAAsC;CAC1E,IAAM,EAAE,SAAM,cAAW,gBAAa,kBAAe,0BACnD,EAAwB,QAAQ,OAAO,EAAE,cAAc,IAAM,CAAC,EAE1D,IAAW,GAAM,MAAM,SAAQ,MAAQ,EAAK,QAAQ,IAAI,EAAE;AAYhE,QACE,kBAAC,GAAD;EACY;EACC;EACE;EACE;EACK;EACpB,oBAjB2B,EAC7B,GACA,EAAY,SAAS,MACrB,EAAY,cACZ,EAAY,cACZ,GACA,GACA,EACD;EAUG,GAAI;EACJ,CAAA"}
1
+ {"version":3,"file":"FavoritesDetails.js","names":[],"sources":["../../../../../src/components/EntityFinder/details/configurations/FavoritesDetails.tsx"],"sourcesContent":["import { useGetFavoritesInfinite } from '@/synapse-queries/user/useFavorites'\nimport useGetIsAllSelectedFromInfiniteList from '@/utils/hooks/useGetIsAllSelectedInfiniteList'\nimport { EntityDetailsListSharedProps } from '../EntityDetailsList'\nimport { DetailsView } from '../view/DetailsView'\n\ntype FavoritesDetailsProps = EntityDetailsListSharedProps\n\nexport function FavoritesDetails({ ...sharedProps }: FavoritesDetailsProps) {\n const { data, isLoading, hasNextPage, fetchNextPage, isFetchingNextPage } =\n useGetFavoritesInfinite('NAME', 'ASC', { throwOnError: true })\n\n const entities = data?.pages.flatMap(page => page.results) ?? []\n\n const selectAllCheckboxState = useGetIsAllSelectedFromInfiniteList(\n entities,\n sharedProps.selected.size,\n sharedProps.isIdSelected,\n sharedProps.isSelectable,\n hasNextPage,\n fetchNextPage,\n isFetchingNextPage,\n )\n\n return (\n <DetailsView\n entities={entities}\n isLoading={isLoading}\n hasNextPage={hasNextPage}\n fetchNextPage={fetchNextPage}\n isFetchingNextPage={isFetchingNextPage}\n selectAllIsChecked={selectAllCheckboxState}\n {...sharedProps}\n />\n )\n}\n"],"mappings":";;;;;AAOA,SAAgB,EAAiB,EAAE,GAAG,KAAsC;CAC1E,IAAM,EAAE,SAAM,cAAW,gBAAa,kBAAe,0BACnD,EAAwB,QAAQ,OAAO,EAAE,cAAc,IAAM,CAAC,EAE1D,IAAW,GAAM,MAAM,SAAQ,MAAQ,EAAK,QAAQ,IAAI,EAAE;AAYhE,QACE,kBAAC,GAAD;EACY;EACC;EACE;EACE;EACK;EACpB,oBAjB2B,EAC7B,GACA,EAAY,SAAS,MACrB,EAAY,cACZ,EAAY,cACZ,GACA,GACA,EAUsB;EACpB,GAAI;EACJ,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"ProjectListDetails.js","names":[],"sources":["../../../../../src/components/EntityFinder/details/configurations/ProjectListDetails.tsx"],"sourcesContent":["import { useGetProjectsInfinite } from '@/synapse-queries/user/useProjects'\nimport useGetIsAllSelectedFromInfiniteList from '@/utils/hooks/useGetIsAllSelectedInfiniteList'\nimport {\n GetProjectsParameters,\n ProjectHeader,\n} from '@sage-bionetworks/synapse-types'\nimport { EntityHeaderFromProjectHeader } from '../../EntityFinderHeader'\nimport { EntityDetailsListSharedProps } from '../EntityDetailsList'\nimport { DetailsView } from '../view/DetailsView'\n\ntype ProjectListDetailsProps = EntityDetailsListSharedProps & {\n projectsParams: GetProjectsParameters\n}\n\nexport function toEntityHeader(\n projectHeader: ProjectHeader,\n): EntityHeaderFromProjectHeader {\n return {\n ...projectHeader,\n type: 'org.sagebionetworks.repo.model.Project',\n }\n}\n\nexport function ProjectListDetails({\n projectsParams,\n ...sharedProps\n}: ProjectListDetailsProps) {\n const { data, isLoading, isFetchingNextPage, hasNextPage, fetchNextPage } =\n useGetProjectsInfinite(projectsParams, { throwOnError: true })\n\n const projects =\n data?.pages.flatMap(page => page.results).map(toEntityHeader) ?? []\n\n const selectAllCheckboxState = useGetIsAllSelectedFromInfiniteList(\n projects,\n sharedProps.selected.size,\n sharedProps.isIdSelected,\n sharedProps.isSelectable,\n hasNextPage,\n fetchNextPage,\n isFetchingNextPage,\n )\n\n return (\n <DetailsView\n entities={projects}\n isLoading={isLoading}\n hasNextPage={hasNextPage}\n fetchNextPage={fetchNextPage}\n isFetchingNextPage={isFetchingNextPage}\n selectAllIsChecked={selectAllCheckboxState}\n {...sharedProps}\n />\n )\n}\n"],"mappings":";;;;;AAcA,SAAgB,EACd,GAC+B;AAC/B,QAAO;EACL,GAAG;EACH,MAAM;EACP;;AAGH,SAAgB,EAAmB,EACjC,mBACA,GAAG,KACuB;CAC1B,IAAM,EAAE,SAAM,cAAW,uBAAoB,gBAAa,qBACxD,EAAuB,GAAgB,EAAE,cAAc,IAAM,CAAC,EAE1D,IACJ,GAAM,MAAM,SAAQ,MAAQ,EAAK,QAAQ,CAAC,IAAI,EAAe,IAAI,EAAE;AAYrE,QACE,kBAAC,GAAD;EACE,UAAU;EACC;EACE;EACE;EACK;EACpB,oBAjB2B,EAC7B,GACA,EAAY,SAAS,MACrB,EAAY,cACZ,EAAY,cACZ,GACA,GACA,EACD;EAUG,GAAI;EACJ,CAAA"}
1
+ {"version":3,"file":"ProjectListDetails.js","names":[],"sources":["../../../../../src/components/EntityFinder/details/configurations/ProjectListDetails.tsx"],"sourcesContent":["import { useGetProjectsInfinite } from '@/synapse-queries/user/useProjects'\nimport useGetIsAllSelectedFromInfiniteList from '@/utils/hooks/useGetIsAllSelectedInfiniteList'\nimport {\n GetProjectsParameters,\n ProjectHeader,\n} from '@sage-bionetworks/synapse-types'\nimport { EntityHeaderFromProjectHeader } from '../../EntityFinderHeader'\nimport { EntityDetailsListSharedProps } from '../EntityDetailsList'\nimport { DetailsView } from '../view/DetailsView'\n\ntype ProjectListDetailsProps = EntityDetailsListSharedProps & {\n projectsParams: GetProjectsParameters\n}\n\nexport function toEntityHeader(\n projectHeader: ProjectHeader,\n): EntityHeaderFromProjectHeader {\n return {\n ...projectHeader,\n type: 'org.sagebionetworks.repo.model.Project',\n }\n}\n\nexport function ProjectListDetails({\n projectsParams,\n ...sharedProps\n}: ProjectListDetailsProps) {\n const { data, isLoading, isFetchingNextPage, hasNextPage, fetchNextPage } =\n useGetProjectsInfinite(projectsParams, { throwOnError: true })\n\n const projects =\n data?.pages.flatMap(page => page.results).map(toEntityHeader) ?? []\n\n const selectAllCheckboxState = useGetIsAllSelectedFromInfiniteList(\n projects,\n sharedProps.selected.size,\n sharedProps.isIdSelected,\n sharedProps.isSelectable,\n hasNextPage,\n fetchNextPage,\n isFetchingNextPage,\n )\n\n return (\n <DetailsView\n entities={projects}\n isLoading={isLoading}\n hasNextPage={hasNextPage}\n fetchNextPage={fetchNextPage}\n isFetchingNextPage={isFetchingNextPage}\n selectAllIsChecked={selectAllCheckboxState}\n {...sharedProps}\n />\n )\n}\n"],"mappings":";;;;;AAcA,SAAgB,EACd,GAC+B;AAC/B,QAAO;EACL,GAAG;EACH,MAAM;EACP;;AAGH,SAAgB,EAAmB,EACjC,mBACA,GAAG,KACuB;CAC1B,IAAM,EAAE,SAAM,cAAW,uBAAoB,gBAAa,qBACxD,EAAuB,GAAgB,EAAE,cAAc,IAAM,CAAC,EAE1D,IACJ,GAAM,MAAM,SAAQ,MAAQ,EAAK,QAAQ,CAAC,IAAI,EAAe,IAAI,EAAE;AAYrE,QACE,kBAAC,GAAD;EACE,UAAU;EACC;EACE;EACE;EACK;EACpB,oBAjB2B,EAC7B,GACA,EAAY,SAAS,MACrB,EAAY,cACZ,EAAY,cACZ,GACA,GACA,EAUsB;EACpB,GAAI;EACJ,CAAA"}