synapse-react-client 4.0.9 → 4.0.11
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.
- package/dist/SWC.index.d.ts +1 -0
- package/dist/SWC.index.d.ts.map +1 -1
- package/dist/SWC.index.js +2 -1
- package/dist/SWC.index.js.map +1 -1
- package/dist/aridhia-queries/aridhiaTokenExchange.js.map +1 -1
- package/dist/aridhia-queries/useGetAridhiaRequests.js.map +1 -1
- package/dist/assets/icons/CloudWarning.d.ts +5 -0
- package/dist/assets/icons/CloudWarning.d.ts.map +1 -0
- package/dist/assets/icons/CloudWarning.js +47 -0
- package/dist/assets/icons/CloudWarning.js.map +1 -0
- package/dist/assets/icons/TasksIcon.d.ts.map +1 -1
- package/dist/assets/icons/TasksIcon.js +6 -10
- package/dist/assets/icons/TasksIcon.js.map +1 -1
- package/dist/components/AccessRequirementAclEditor/AccessRequirementAclEditor.d.ts.map +1 -1
- package/dist/components/AccessRequirementAclEditor/AccessRequirementAclEditor.js +69 -63
- package/dist/components/AccessRequirementAclEditor/AccessRequirementAclEditor.js.map +1 -1
- package/dist/components/AccessRequirementList/AccessApprovalCheckMark.js.map +1 -1
- package/dist/components/AccessRequirementList/AccessRequirementList.js.map +1 -1
- package/dist/components/AccessRequirementList/AccessRequirementListUtils.js.map +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/DataAccessRequestAccessorsEditor.js.map +1 -1
- package/dist/components/AccessRequirementList/RequirementItem/SelfSignAccessRequirementItem.js.map +1 -1
- package/dist/components/AccessRequirementRelatedProjectsList/AccessRequirementRelatedProjectsList.js.map +1 -1
- package/dist/components/AccessTokenPage/AccessTokenCard/AccessTokenCard.js.map +1 -1
- package/dist/components/AcknowledgementsPage/StudyAcknowledgements.js.map +1 -1
- package/dist/components/AclEditor/PermissionLevelMenu.js.map +1 -1
- package/dist/components/AclEditor/ResourceAccessAndUserGroupHeader.js.map +1 -1
- package/dist/components/AclEditor/useSortResourceAccessList.js.map +1 -1
- package/dist/components/AclEditor/useUpdateAcl.js.map +1 -1
- package/dist/components/Aridhia/AridhiaAccessStatus.js.map +1 -1
- package/dist/components/Authentication/AuthenticationMethodSelection.d.ts.map +1 -1
- package/dist/components/Authentication/AuthenticationMethodSelection.js +38 -37
- package/dist/components/Authentication/AuthenticationMethodSelection.js.map +1 -1
- package/dist/components/Authentication/Constants.d.ts +1 -0
- package/dist/components/Authentication/Constants.d.ts.map +1 -1
- package/dist/components/Authentication/Constants.js +2 -2
- package/dist/components/Authentication/Constants.js.map +1 -1
- package/dist/components/Authentication/LastLoginInfo.js.map +1 -1
- package/dist/components/Authentication/RecoveryCodeForm.js.map +1 -1
- package/dist/components/Authentication/RecoveryCodeGrid.js.map +1 -1
- package/dist/components/Authentication/RegenerateBackupCodesWarning.js.map +1 -1
- package/dist/components/Authentication/Reset2FAWarning.js.map +1 -1
- package/dist/components/Authentication/StandaloneLoginForm.js +1 -1
- package/dist/components/Authentication/TwoFactorBackupCodes.js.map +1 -1
- package/dist/components/Authentication/TwoFactorEnrollmentForm.d.ts.map +1 -1
- package/dist/components/Authentication/TwoFactorEnrollmentForm.js +2 -1
- package/dist/components/Authentication/TwoFactorEnrollmentForm.js.map +1 -1
- package/dist/components/BasePortalCard/ColorfulPortalCardWithChips/ColorfulPortalCardWithChips.js.map +1 -1
- package/dist/components/CardContainer/CardContainer.js.map +1 -1
- package/dist/components/CardDeck/CardDeck.Mobile.js.map +1 -1
- package/dist/components/CardDeck/TableQueryCardDeck.js.map +1 -1
- package/dist/components/CertificationQuiz/CertificationQuiz.js.map +1 -1
- package/dist/components/ChallengeDataDownload/ChallengeDataDownload.js.map +1 -1
- package/dist/components/ChallengeSubmission/ChallengeSubmission.js.map +1 -1
- package/dist/components/ChallengeSubmission/ChallengeSubmissionStepper.js.map +1 -1
- package/dist/components/ChallengeSubmission/EvaluationQueueCurrentRoundInfo.js.map +1 -1
- package/dist/components/ChallengeSubmission/EvaluationQueueList.js.map +1 -1
- package/dist/components/ChallengeSubmission/SubmissionDirectoryList.d.ts.map +1 -1
- package/dist/components/ChallengeSubmission/SubmissionDirectoryList.js +143 -140
- package/dist/components/ChallengeSubmission/SubmissionDirectoryList.js.map +1 -1
- package/dist/components/ChallengeTeamWizard/ChallengeTeamWizard.js.map +1 -1
- package/dist/components/ChallengeTeamWizard/CreateChallengeTeam.js.map +1 -1
- package/dist/components/ChangePassword/ChangePassword.js.map +1 -1
- package/dist/components/ChangePassword/ChangePasswordWithToken.js.map +1 -1
- package/dist/components/ChangePassword/useChangePasswordFormState.js +1 -1
- package/dist/components/ChangePassword/useChangePasswordFormState.js.map +1 -1
- package/dist/components/CitationPopover/CitationPopoverContent.js.map +1 -1
- package/dist/components/ColumnFilter/ColumnFilter.js.map +1 -1
- package/dist/components/ComponentCollapse.js.map +1 -1
- package/dist/components/CookiesNotification/CookiesNotification.js.map +1 -1
- package/dist/components/CreateProjectModal/CreateProjectModal.js.map +1 -1
- package/dist/components/CreateTableViewWizard/CreateTableViewWizardUtils.js.map +1 -1
- package/dist/components/DataGrid/DataGrid.d.ts +0 -1
- package/dist/components/DataGrid/DataGrid.d.ts.map +1 -1
- package/dist/components/DataGrid/DataGrid.js +72 -72
- package/dist/components/DataGrid/DataGrid.js.map +1 -1
- package/dist/components/DataGrid/DataGridWebSocket.d.ts +4 -0
- package/dist/components/DataGrid/DataGridWebSocket.d.ts.map +1 -1
- package/dist/components/DataGrid/DataGridWebSocket.js +9 -8
- package/dist/components/DataGrid/DataGridWebSocket.js.map +1 -1
- package/dist/components/DataGrid/SynapseGrid.d.ts.map +1 -1
- package/dist/components/DataGrid/SynapseGrid.js +326 -268
- package/dist/components/DataGrid/SynapseGrid.js.map +1 -1
- package/dist/components/DataGrid/columns/AutocompleteColumn.d.ts +2 -0
- package/dist/components/DataGrid/columns/AutocompleteColumn.d.ts.map +1 -1
- package/dist/components/DataGrid/columns/AutocompleteColumn.js +124 -67
- package/dist/components/DataGrid/columns/AutocompleteColumn.js.map +1 -1
- package/dist/components/DataGrid/columns/AutocompleteMultipleEnumColumn.d.ts +2 -1
- package/dist/components/DataGrid/columns/AutocompleteMultipleEnumColumn.d.ts.map +1 -1
- package/dist/components/DataGrid/columns/AutocompleteMultipleEnumColumn.js +126 -122
- package/dist/components/DataGrid/columns/AutocompleteMultipleEnumColumn.js.map +1 -1
- package/dist/components/DataGrid/columns/useGridAutocompleteState.d.ts +58 -0
- package/dist/components/DataGrid/columns/useGridAutocompleteState.d.ts.map +1 -0
- package/dist/components/DataGrid/columns/useGridAutocompleteState.js +52 -0
- package/dist/components/DataGrid/columns/useGridAutocompleteState.js.map +1 -0
- package/dist/components/DataGrid/components/ValidationAlert.d.ts +5 -2
- package/dist/components/DataGrid/components/ValidationAlert.d.ts.map +1 -1
- package/dist/components/DataGrid/components/ValidationAlert.js +429 -24
- package/dist/components/DataGrid/components/ValidationAlert.js.map +1 -1
- package/dist/components/DataGrid/hooks/useColumnResizeHandles.js.map +1 -1
- package/dist/components/DataGrid/hooks/useGetSchemaForGrid.js.map +1 -1
- package/dist/components/DataGrid/hooks/useGridUndoRedo.js.map +1 -1
- package/dist/components/DataGrid/hooks/useStack.js.map +1 -1
- package/dist/components/DataGrid/useCRDTModelView.js.map +1 -1
- package/dist/components/DataGrid/useDataGridWebsocket.d.ts +7 -0
- package/dist/components/DataGrid/useDataGridWebsocket.d.ts.map +1 -1
- package/dist/components/DataGrid/useDataGridWebsocket.js +16 -2
- package/dist/components/DataGrid/useDataGridWebsocket.js.map +1 -1
- package/dist/components/DataGrid/useInitializeGridConnection.js.map +1 -1
- package/dist/components/DataGrid/useMergeGridWithRecordSet.js.map +1 -1
- package/dist/components/DataGrid/useMergeGridWithSource.js.map +1 -1
- package/dist/components/DataGrid/useMergeGridWithTable.js.map +1 -1
- package/dist/components/DataGrid/utils/DataGridUtils.js.map +1 -1
- package/dist/components/DataGrid/utils/applyModelChange.d.ts +1 -1
- package/dist/components/DataGrid/utils/applyModelChange.d.ts.map +1 -1
- package/dist/components/DataGrid/utils/applyModelChange.js +27 -24
- package/dist/components/DataGrid/utils/applyModelChange.js.map +1 -1
- package/dist/components/DataGrid/utils/columnFactory.d.ts +8 -0
- package/dist/components/DataGrid/utils/columnFactory.d.ts.map +1 -1
- package/dist/components/DataGrid/utils/columnFactory.js +47 -44
- package/dist/components/DataGrid/utils/columnFactory.js.map +1 -1
- package/dist/components/DataGrid/utils/computeReplicaSelectionModel.js.map +1 -1
- package/dist/components/DataGrid/utils/extractColumnValidationMessages.js.map +1 -1
- package/dist/components/DataGrid/utils/getCellClassName.d.ts.map +1 -1
- package/dist/components/DataGrid/utils/getCellClassName.js +8 -8
- package/dist/components/DataGrid/utils/getCellClassName.js.map +1 -1
- package/dist/components/DataGrid/utils/getEmptyValue.d.ts +2 -0
- package/dist/components/DataGrid/utils/getEmptyValue.d.ts.map +1 -0
- package/dist/components/DataGrid/utils/getEmptyValue.js +8 -0
- package/dist/components/DataGrid/utils/getEmptyValue.js.map +1 -0
- package/dist/components/DataGrid/utils/json-rx/JsonRx.js.map +1 -1
- package/dist/components/DataGrid/utils/modelColsToGrid.d.ts.map +1 -1
- package/dist/components/DataGrid/utils/modelColsToGrid.js +2 -1
- package/dist/components/DataGrid/utils/modelColsToGrid.js.map +1 -1
- package/dist/components/DataGrid/utils/modelRowsToGrid.js.map +1 -1
- package/dist/components/DataGrid/utils/parseFreeTextUsingJsonSchemaType.js.map +1 -1
- package/dist/components/DataGrid/utils/schemaAwarePasteValue.d.ts +32 -0
- package/dist/components/DataGrid/utils/schemaAwarePasteValue.d.ts.map +1 -0
- package/dist/components/DataGrid/utils/schemaAwarePasteValue.js +22 -0
- package/dist/components/DataGrid/utils/schemaAwarePasteValue.js.map +1 -0
- package/dist/components/DataGrid/utils/splitPatch.js.map +1 -1
- package/dist/components/DateTimePicker/DateTimePicker.js.map +1 -1
- package/dist/components/DirectDownload/DirectDownload.js.map +1 -1
- package/dist/components/DirectDownloadButton.js.map +1 -1
- package/dist/components/DownloadCart/CreatePackageV2.js.map +1 -1
- package/dist/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.css +1 -0
- package/dist/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.d.ts.map +1 -1
- package/dist/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.js +199 -132
- package/dist/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.js.map +1 -1
- package/dist/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.module.js +22 -0
- package/dist/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.module.js.map +1 -0
- package/dist/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.module.scss +170 -0
- package/dist/components/DownloadCart/DownloadListActionsRequired.js.map +1 -1
- package/dist/components/DownloadCart/DownloadListTable.js.map +1 -1
- package/dist/components/DownloadCart/fileNameUtils.js.map +1 -1
- package/dist/components/DraggableDialog/DraggableDialog.js.map +1 -1
- package/dist/components/DynamicForm/DynamicFormModal.js.map +1 -1
- package/dist/components/Ecosystem/TableQueryEcosystem.js.map +1 -1
- package/dist/components/EntityAclEditor/EntityAclEditor.d.ts.map +1 -1
- package/dist/components/EntityAclEditor/EntityAclEditor.js +103 -103
- package/dist/components/EntityAclEditor/EntityAclEditor.js.map +1 -1
- package/dist/components/EntityAclEditor/useNotifyNewACLUsers.js.map +1 -1
- package/dist/components/EntityBadgeIcons/EntityBadgeIcons.js.map +1 -1
- package/dist/components/EntityCitation/EntityCitation.js.map +1 -1
- package/dist/components/EntityDownloadButton/EntityDownloadButton.d.ts.map +1 -1
- package/dist/components/EntityDownloadButton/EntityDownloadButton.js +1 -0
- package/dist/components/EntityDownloadButton/EntityDownloadButton.js.map +1 -1
- package/dist/components/EntityDownloadConfirmation/EntityDownloadConfirmation.d.ts.map +1 -1
- package/dist/components/EntityDownloadConfirmation/EntityDownloadConfirmation.js +36 -30
- package/dist/components/EntityDownloadConfirmation/EntityDownloadConfirmation.js.map +1 -1
- package/dist/components/EntityFinder/EntityFinder.js.map +1 -1
- package/dist/components/EntityFinder/VersionSelectionType.js.map +1 -1
- package/dist/components/EntityFinder/details/configurations/EntityChildrenDetails.js.map +1 -1
- package/dist/components/EntityFinder/details/configurations/FavoritesDetails.js.map +1 -1
- package/dist/components/EntityFinder/details/configurations/ProjectListDetails.js.map +1 -1
- package/dist/components/EntityFinder/details/view/DetailsView.js.map +1 -1
- package/dist/components/EntityFinder/tree/EntityTree.js.map +1 -1
- package/dist/components/EntityFinder/tree/VirtualizedTree.js.map +1 -1
- package/dist/components/EntityFinder/useEntitySelection.js.map +1 -1
- package/dist/components/EntityForm/EntityForm.js.map +1 -1
- package/dist/components/EntityHeaderTable/EntityHeaderTable.js.map +1 -1
- package/dist/components/EntityHeaderTable/Filter.js.map +1 -1
- package/dist/components/EntityHeaderTable/useEntityHeaderTableState.js.map +1 -1
- package/dist/components/EntitySubjectsSelector/EntitySubjectsSelector.js.map +1 -1
- package/dist/components/EntityTreeTable/components/IdColumnHeader.js.map +1 -1
- package/dist/components/EntityTreeTable/hooks/useEntityTreeState.js.map +1 -1
- package/dist/components/EntityTreeTable/hooks/useTableColumns.js.map +1 -1
- package/dist/components/EntityTreeTable/hooks/useTableData.js.map +1 -1
- package/dist/components/EntityTreeTable/hooks/useTreeOperationsWithDirectFetch.js.map +1 -1
- package/dist/components/EntityUpload/EntityUpload.js.map +1 -1
- package/dist/components/EntityViewScopeEditor/EntityViewMaskEditor.d.ts.map +1 -1
- package/dist/components/EntityViewScopeEditor/EntityViewMaskEditor.js +15 -14
- package/dist/components/EntityViewScopeEditor/EntityViewMaskEditor.js.map +1 -1
- package/dist/components/ExperimentalMode/ExperimentalMode.js.map +1 -1
- package/dist/components/ExternalFileHandleLink/ExternalFileHandleLink.js.map +1 -1
- package/dist/components/FeaturedDataTabs/FacetPlotsCard.js.map +1 -1
- package/dist/components/FeaturedDataTabs/QueryPerFacetPlotsCard.js.map +1 -1
- package/dist/components/FeaturedDataTabs/SingleQueryFacetPlotsCards.js.map +1 -1
- package/dist/components/FeaturedResearch/FeaturedResearch.js.map +1 -1
- package/dist/components/FeaturedToolsList/FeaturedToolsList.js.map +1 -1
- package/dist/components/FilePreview/FileHandleContentRenderer.js.map +1 -1
- package/dist/components/FilePreview/HtmlPreview/HtmlPreview.js.map +1 -1
- package/dist/components/FilePreview/PreviewRendererType.js.map +1 -1
- package/dist/components/Forum/DiscussionReply.d.ts +1 -0
- package/dist/components/Forum/DiscussionReply.d.ts.map +1 -1
- package/dist/components/Forum/DiscussionReply.js +19 -19
- package/dist/components/Forum/DiscussionReply.js.map +1 -1
- package/dist/components/Forum/DiscussionSearchResult.js.map +1 -1
- package/dist/components/Forum/DiscussionThread.d.ts +1 -0
- package/dist/components/Forum/DiscussionThread.d.ts.map +1 -1
- package/dist/components/Forum/DiscussionThread.js +73 -72
- package/dist/components/Forum/DiscussionThread.js.map +1 -1
- package/dist/components/Forum/ForumTable.js.map +1 -1
- package/dist/components/Forum/ForumThreadEditor.js.map +1 -1
- package/dist/components/FullTextSearch/FullTextSearchUtils.js.map +1 -1
- package/dist/components/GenericCard/BioregistryRules.d.ts.map +1 -1
- package/dist/components/GenericCard/BioregistryRules.js +7 -3
- package/dist/components/GenericCard/BioregistryRules.js.map +1 -1
- package/dist/components/GenericCard/GenericCard.d.ts.map +1 -1
- package/dist/components/GenericCard/GenericCard.js +12 -7
- package/dist/components/GenericCard/GenericCard.js.map +1 -1
- package/dist/components/GenericCard/Linkify.js.map +1 -1
- package/dist/components/GenericCard/SynapseCardLabel.js.map +1 -1
- package/dist/components/GenericCard/TableRowGenericCard.js +105 -105
- package/dist/components/GenericCard/TableRowGenericCard.js.map +1 -1
- package/dist/components/Goals/Goals.Mobile.js.map +1 -1
- package/dist/components/Goals/Goals.js.map +1 -1
- package/dist/components/GoalsV2/GoalsV2.Mobile.js.map +1 -1
- package/dist/components/GoalsV2/GoalsV2.js.map +1 -1
- package/dist/components/GoalsV3/GoalsV3.Mobile.js.map +1 -1
- package/dist/components/GoalsV3/GoalsV3.js.map +1 -1
- package/dist/components/GoogleMap/SynapseUserMarker.js.map +1 -1
- package/dist/components/HasAccess/AccessIcon.js.map +1 -1
- package/dist/components/HasAccess/useHasAccess.js.map +1 -1
- package/dist/components/HeaderCard/HeaderCardV2.js.map +1 -1
- package/dist/components/HeaderCard.d.ts +6 -1
- package/dist/components/HeaderCard.d.ts.map +1 -1
- package/dist/components/HeaderCard.js +107 -76
- package/dist/components/HeaderCard.js.map +1 -1
- package/dist/components/HexGrid/HexGrid.js.map +1 -1
- package/dist/components/IconList.js.map +1 -1
- package/dist/components/IconSvg/IconSvg.d.ts.map +1 -1
- package/dist/components/IconSvg/IconSvg.js +2 -1
- package/dist/components/IconSvg/IconSvg.js.map +1 -1
- package/dist/components/ImageCardGridWithLinks/ImageCardGridWithLinks.js.map +1 -1
- package/dist/components/ImageFromSynapseTable.js.map +1 -1
- package/dist/components/JSONArrayEditor/useParseCsv.js.map +1 -1
- package/dist/components/JsonSchemaForm/templates/ArrayFieldDescriptionTemplate.js.map +1 -1
- package/dist/components/JsonSchemaForm/templates/ArrayFieldItemTemplate.js.map +1 -1
- package/dist/components/JsonSchemaForm/templates/BaseInputTemplate.js.map +1 -1
- package/dist/components/JsonSchemaForm/templates/FieldTemplate.js.map +1 -1
- package/dist/components/JsonSchemaForm/templates/RJSFInputLabel.js.map +1 -1
- package/dist/components/Markdown/MarkdownGithub.js.map +1 -1
- package/dist/components/Markdown/MarkdownSynapse.js.map +1 -1
- package/dist/components/Markdown/MarkdownUtils.js.map +1 -1
- package/dist/components/Markdown/SynapseWikiContext.js.map +1 -1
- package/dist/components/Markdown/UserMentionModal.js.map +1 -1
- package/dist/components/Markdown/widget/MarkdownProvenanceGraph.js.map +1 -1
- package/dist/components/MissingQueryResultsWarning/MissingQueryResultsWarning.js.map +1 -1
- package/dist/components/ModalDownload/ModalDownload.js.map +1 -1
- package/dist/components/OAuthClientAclEditor/OAuthClientAclEditor.d.ts.map +1 -1
- package/dist/components/OAuthClientAclEditor/OAuthClientAclEditor.js +45 -39
- package/dist/components/OAuthClientAclEditor/OAuthClientAclEditor.js.map +1 -1
- package/dist/components/OAuthClientManagement/OAuthManagement.js.map +1 -1
- package/dist/components/PageProgress/PageProgress.js.map +1 -1
- package/dist/components/Plot/DotPlot.js.map +1 -1
- package/dist/components/Plot/Plot.js.map +1 -1
- package/dist/components/Plot/SynapsePlot.js.map +1 -1
- package/dist/components/Plot/ThemesPlot.js.map +1 -1
- package/dist/components/Plot/UpsetPlot.js.map +1 -1
- package/dist/components/PortalAclEditor/PortalAclEditor.d.ts.map +1 -1
- package/dist/components/PortalAclEditor/PortalAclEditor.js +43 -41
- package/dist/components/PortalAclEditor/PortalAclEditor.js.map +1 -1
- package/dist/components/PortalFeaturedPartners/PortalFeaturedPartners.js.map +1 -1
- package/dist/components/PortalList/CreatePortalModal.js.map +1 -1
- package/dist/components/ProgrammaticInstructionsModal/ProgrammaticInstructionsModal.js.map +1 -1
- package/dist/components/ProgrammaticTableDownload/ProgrammaticTableDownload.js.map +1 -1
- package/dist/components/Programs/Programs.Mobile.js.map +1 -1
- package/dist/components/Programs/Programs.js.map +1 -1
- package/dist/components/ProvenanceGraph/ProvenanceExternalIcon.js.map +1 -1
- package/dist/components/ProvenanceGraph/ProvenanceGraph.js.map +1 -1
- package/dist/components/ProvenanceGraph/ProvenanceGraphUtils.js.map +1 -1
- package/dist/components/ProvenanceGraph/ProvenanceUtils.js.map +1 -1
- package/dist/components/QueryCount/QueryCount.js.map +1 -1
- package/dist/components/QueryCountButton/QueryCountButton.js.map +1 -1
- package/dist/components/QueryVisualizationWrapper/QueryVisualizationWrapper.js.map +1 -1
- package/dist/components/QueryWrapper/QueryWrapper.js.map +1 -1
- package/dist/components/QueryWrapper/TableQueryUseQueryOptions.js.map +1 -1
- package/dist/components/QueryWrapper/TableRowSelectionState.js.map +1 -1
- package/dist/components/QueryWrapper/generateEncodedPathAndQueryForSelectedFacetURL.js.map +1 -1
- package/dist/components/QueryWrapper/useGetQueryMetadata.js.map +1 -1
- package/dist/components/QueryWrapperErrorBoundary.js.map +1 -1
- package/dist/components/QueryWrapperPlotNav/QueryWrapperPlotNav.js.map +1 -1
- package/dist/components/QueryWrapperPlotNav/UseRowSet.js.map +1 -1
- package/dist/components/RecentPublicationsGrid/RecentPublicationsGrid.js.map +1 -1
- package/dist/components/ReleaseCard/ReleaseCardUtils.js.map +1 -1
- package/dist/components/ResizableContainer/hooks/useResizable.js.map +1 -1
- package/dist/components/Resources/Resources.Mobile.js.map +1 -1
- package/dist/components/Resources/Resources.js.map +1 -1
- package/dist/components/RowDataTable/RowDataTableWithQuery.js.map +1 -1
- package/dist/components/SageResourcesPopover/SageResourcesPopover.js.map +1 -1
- package/dist/components/SchemaDrivenAnnotationEditor/AnnotationEditorUtils.js.map +1 -1
- package/dist/components/SetAccessRequirementCommonFields/SetAccessRequirementCommonFields.js.map +1 -1
- package/dist/components/SetManagedAccessRequirementFields/SetManagedAccessRequirementFields.js.map +1 -1
- package/dist/components/SmartLink/SmartButton.js.map +1 -1
- package/dist/components/SmartLink/SmartLink.js.map +1 -1
- package/dist/components/SourceAppImage.js.map +1 -1
- package/dist/components/StandaloneQueryWrapper/StandaloneQueryWrapper.js.map +1 -1
- package/dist/components/StatisticsPlot.js.map +1 -1
- package/dist/components/StorybookComponentWrapper.js.map +1 -1
- package/dist/components/SubsectionRowRenderer/SubsectionRowRenderer.js.map +1 -1
- package/dist/components/SustainabilityScorecard/SustainabilityScorecard.js.map +1 -1
- package/dist/components/SynapseChat/GridAgentChat.js.map +1 -1
- package/dist/components/SynapseChat/SynapseChatInteraction.js.map +1 -1
- package/dist/components/SynapseChat/SynapseChatMessage.js.map +1 -1
- package/dist/components/SynapseChat/extractMessageFromTraceEvent.js.map +1 -1
- package/dist/components/SynapseForm/StepsSideNav.js.map +1 -1
- package/dist/components/SynapseForm/SummaryTable.js.map +1 -1
- package/dist/components/SynapseForm/SynapseForm.js +4 -2
- package/dist/components/SynapseForm/SynapseForm.js.map +1 -1
- package/dist/components/SynapseForm/SynapseFormWrapper.js.map +1 -1
- package/dist/components/SynapseHomepageV2/SynapseByTheNumbersItem.js.map +1 -1
- package/dist/components/SynapseHomepageV2/SynapseFeatureItem.js.map +1 -1
- package/dist/components/SynapseHomepageV2/SynapseHomepageChatSearch.js.map +1 -1
- package/dist/components/SynapseHomepageV2/SynapseHomepageSearch.js.map +1 -1
- package/dist/components/SynapseHomepageV2/SynapseInActionItem.js.map +1 -1
- package/dist/components/SynapseHomepageV2/SynapsePlans.js.map +1 -1
- package/dist/components/SynapseHomepageV2/SynapseTrendingProjects.js.map +1 -1
- package/dist/components/SynapseNavDrawer/SynapseNavDrawer.d.ts +8 -7
- package/dist/components/SynapseNavDrawer/SynapseNavDrawer.d.ts.map +1 -1
- package/dist/components/SynapseNavDrawer/SynapseNavDrawer.js +173 -164
- package/dist/components/SynapseNavDrawer/SynapseNavDrawer.js.map +1 -1
- package/dist/components/SynapsePortalBanners/SynapsePortalBanners.js.map +1 -1
- package/dist/components/SynapseSearchPageResults/SearchFacetPanel/SearchFacetPanel.js.map +1 -1
- package/dist/components/SynapseSearchPageResults/SearchFacetPanel/SearchFacetPanelUtils.js.map +1 -1
- package/dist/components/SynapseSearchPageResults/SynapseSearchPageResults.js.map +1 -1
- package/dist/components/SynapseTable/EntityIDColumnCopyIcon.js.map +1 -1
- package/dist/components/SynapseTable/NoContentPlaceholderType.js.map +1 -1
- package/dist/components/SynapseTable/RowSelection/RowSelectionControls.js.map +1 -1
- package/dist/components/SynapseTable/SynapseTableCell/SynapseTableCell.js.map +1 -1
- package/dist/components/SynapseTable/SynapseTableRenderers.js.map +1 -1
- package/dist/components/SynapseTable/datasets/DatasetItemsEditor.js.map +1 -1
- package/dist/components/SynapseTable/table-top/ColumnSelection.js.map +1 -1
- package/dist/components/SynapseTable/table-top/DownloadOptions.js.map +1 -1
- package/dist/components/SynapseTable/usePrefetchTableData.js.map +1 -1
- package/dist/components/TableColumnSchemaEditor/ColumnModelForm.js.map +1 -1
- package/dist/components/TableColumnSchemaEditor/ColumnModelFormFields/DefaultValueField.js.map +1 -1
- package/dist/components/TableColumnSchemaEditor/ImportTableColumnsButton.js.map +1 -1
- package/dist/components/TableColumnSchemaEditor/TableColumnSchemaEditorUtils.d.ts +1 -1
- package/dist/components/TableColumnSchemaEditor/TableColumnSchemaEditorUtils.d.ts.map +1 -1
- package/dist/components/TableColumnSchemaEditor/TableColumnSchemaEditorUtils.js.map +1 -1
- package/dist/components/TableColumnSchemaEditor/TableColumnSchemaForm.js.map +1 -1
- package/dist/components/TableColumnSchemaEditor/TableColumnSchemaFormReducer.js.map +1 -1
- package/dist/components/TableColumnSchemaEditor/Validators/ColumnModelValidator.js.map +1 -1
- package/dist/components/TableColumnSchemaEditor/Validators/DatetimeSchema.js.map +1 -1
- package/dist/components/TanStackTable/ColumnHeader.d.ts +1 -0
- package/dist/components/TanStackTable/ColumnHeader.d.ts.map +1 -1
- package/dist/components/TanStackTable/ColumnHeader.js +8 -8
- package/dist/components/TanStackTable/ColumnHeader.js.map +1 -1
- package/dist/components/TanStackTable/ColumnHeaderEnumFilter.js.map +1 -1
- package/dist/components/TanStackTable/TableBody.js.map +1 -1
- package/dist/components/TeamSubjectsSelector/TeamSubjectsSelector.js.map +1 -1
- package/dist/components/TextField/TextField.js.map +1 -1
- package/dist/components/TimelinePlot/TimelinePhase.js.map +1 -1
- package/dist/components/TimelinePlot/TimelinePlot.js.map +1 -1
- package/dist/components/TimelinePlot/TimelinePlotSpeciesSelector.js.map +1 -1
- package/dist/components/UserCard/Avatar.js.map +1 -1
- package/dist/components/UserCardList/UserCardList.js.map +1 -1
- package/dist/components/UserCardList/UserCardListGroups/UserCardListGroups.Mobile.js.map +1 -1
- package/dist/components/UserCardList/UserCardListRotate.js.map +1 -1
- package/dist/components/UserOrTeamBadge/useUserOrTeam.js.map +1 -1
- package/dist/components/UserProfileLinks/UserProjects.js.map +1 -1
- package/dist/components/UserSearchBox/UserSearchBox.js.map +1 -1
- package/dist/components/Webhook/WebhookDashboard.js.map +1 -1
- package/dist/components/WikiMarkdownEditor/WikiMarkdownEditor.js.map +1 -1
- package/dist/components/WikiMarkdownEditorButton/WikiMarkdownEditorButton.js.map +1 -1
- package/dist/components/dataaccess/AccessApprovalsTable.js.map +1 -1
- package/dist/components/dataaccess/AccessRequestSubmissionTable.js.map +1 -1
- package/dist/components/dataaccess/SubmissionPage/SubmissionPage.d.ts.map +1 -1
- package/dist/components/dataaccess/SubmissionPage/SubmissionPage.js +157 -148
- package/dist/components/dataaccess/SubmissionPage/SubmissionPage.js.map +1 -1
- package/dist/components/dataaccess/UseAccessRequirementTable.js.map +1 -1
- package/dist/components/dataaccess/UserAccessRequestHistory/UserAccessRequestHistoryTable.js.map +1 -1
- package/dist/components/doi/CreateOrUpdateDoiModal.d.ts.map +1 -1
- package/dist/components/doi/CreateOrUpdateDoiModal.js +20 -19
- package/dist/components/doi/CreateOrUpdateDoiModal.js.map +1 -1
- package/dist/components/entity/page/CreatedByModifiedBy.js.map +1 -1
- package/dist/components/entity/page/action_menu/EntityActionMenu.js.map +1 -1
- package/dist/components/entity/page/title_bar/useDataCiteUsage.js.map +1 -1
- package/dist/components/entity/page/title_bar/useGetMentions.js.map +1 -1
- package/dist/components/error/ErrorPage.js.map +1 -1
- package/dist/components/favorites/FavoritesPage.js.map +1 -1
- package/dist/components/file/upload/BasicFileHandleUpload.js.map +1 -1
- package/dist/components/layout/SWCHeader.d.ts +9 -0
- package/dist/components/layout/SWCHeader.d.ts.map +1 -0
- package/dist/components/layout/SWCHeader.js +19 -0
- package/dist/components/layout/SWCHeader.js.map +1 -0
- package/dist/components/layout/SWCPageLayout.d.ts +9 -0
- package/dist/components/layout/SWCPageLayout.d.ts.map +1 -0
- package/dist/components/layout/SWCPageLayout.js +14 -0
- package/dist/components/layout/SWCPageLayout.js.map +1 -0
- package/dist/components/menu/ComplexMenu.js.map +1 -1
- package/dist/components/row_renderers/utils/ChipContainer.js.map +1 -1
- package/dist/components/styled/StyledPopover.js.map +1 -1
- package/dist/components/table/CsvPreview/CsvPreview.js +2 -1
- package/dist/components/table/CsvPreview/CsvPreview.js.map +1 -1
- package/dist/components/table/CsvPreview/CsvPreviewDialog.js.map +1 -1
- package/dist/components/trash/TrashCanList.js.map +1 -1
- package/dist/components/widgets/FileHandleLink.js.map +1 -1
- package/dist/components/widgets/RangeSlider/RangeSlider.js.map +1 -1
- package/dist/components/widgets/SynapseVideo.js.map +1 -1
- package/dist/components/widgets/facet-nav/FacetNavPanel.js.map +1 -1
- package/dist/components/widgets/facet-nav/PlotsContainer.js.map +1 -1
- package/dist/components/widgets/facet-nav/SelectionCriteriaPills.js.map +1 -1
- package/dist/components/widgets/facet-nav/useFacetPlots.js.map +1 -1
- package/dist/components/widgets/query-filter/CombinedRangeFacetFilter.js.map +1 -1
- package/dist/components/widgets/query-filter/EnumFacetFilter/EnumFacetFilter.js.map +1 -1
- package/dist/components/widgets/query-filter/FacetFilterControls.js.map +1 -1
- package/dist/components/widgets/query-filter/RangeFacetFilter.js.map +1 -1
- package/dist/components/widgets/query-filter/RangeFacetFilterUI.js.map +1 -1
- package/dist/features/curator/GridPage/components/GridPageTitle.d.ts.map +1 -1
- package/dist/features/curator/GridPage/components/GridPageTitle.js +23 -30
- package/dist/features/curator/GridPage/components/GridPageTitle.js.map +1 -1
- package/dist/features/curator/dashboard/CuratorDashboard.d.ts +2 -0
- package/dist/features/curator/dashboard/CuratorDashboard.d.ts.map +1 -0
- package/dist/features/curator/dashboard/CuratorDashboard.js +45 -0
- package/dist/features/curator/dashboard/CuratorDashboard.js.map +1 -0
- package/dist/features/curator/dashboard/components/CurationTaskCard.css +1 -0
- package/dist/features/curator/dashboard/components/CurationTaskCard.d.ts +9 -0
- package/dist/features/curator/dashboard/components/CurationTaskCard.d.ts.map +1 -0
- package/dist/features/curator/dashboard/components/CurationTaskCard.js +106 -0
- package/dist/features/curator/dashboard/components/CurationTaskCard.js.map +1 -0
- package/dist/features/curator/dashboard/components/CurationTaskCard.module.js +12 -0
- package/dist/features/curator/dashboard/components/CurationTaskCard.module.js.map +1 -0
- package/dist/features/curator/dashboard/components/CurationTaskCard.module.scss +52 -0
- package/dist/features/curator/dashboard/components/NextStepButton.css +1 -0
- package/dist/features/curator/dashboard/components/NextStepButton.d.ts +14 -0
- package/dist/features/curator/dashboard/components/NextStepButton.d.ts.map +1 -0
- package/dist/features/curator/dashboard/components/NextStepButton.js +35 -0
- package/dist/features/curator/dashboard/components/NextStepButton.js.map +1 -0
- package/dist/features/curator/dashboard/components/NextStepButton.module.js +11 -0
- package/dist/features/curator/dashboard/components/NextStepButton.module.js.map +1 -0
- package/dist/features/curator/dashboard/components/NextStepButton.module.scss +57 -0
- package/dist/features/curator/dashboard/components/UserOrTeamChip.css +1 -1
- package/dist/features/curator/dashboard/components/UserOrTeamChip.module.js +1 -1
- package/dist/features/curator/dashboard/components/UserOrTeamChip.module.js.map +1 -1
- package/dist/features/curator/dashboard/components/UserOrTeamChip.module.scss +5 -5
- package/dist/features/curator/dashboard/components/shared.css +1 -0
- package/dist/features/curator/dashboard/components/shared.module.js +5 -0
- package/dist/features/curator/dashboard/components/shared.module.js.map +1 -0
- package/dist/features/curator/dashboard/components/shared.module.scss +8 -0
- package/dist/features/entity/metadata-task/components/MetadataTaskTableActionCell.d.ts +0 -2
- package/dist/features/entity/metadata-task/components/MetadataTaskTableActionCell.d.ts.map +1 -1
- package/dist/features/entity/metadata-task/components/MetadataTaskTableActionCell.js +16 -34
- package/dist/features/entity/metadata-task/components/MetadataTaskTableActionCell.js.map +1 -1
- package/dist/features/entity/metadata-task/components/MetadataTasksTableAssigneeCell.d.ts.map +1 -1
- package/dist/features/entity/metadata-task/components/MetadataTasksTableAssigneeCell.js +1 -1
- package/dist/features/entity/metadata-task/components/MetadataTasksTableAssigneeCell.js.map +1 -1
- package/dist/features/entity/metadata-task/hooks/useGetOrCreateGridSessionForSource.js.map +1 -1
- package/dist/features/entity/metadata-task/hooks/useGridSessionForCurationTask.js.map +1 -1
- package/dist/features/entity/metadata-task/hooks/useGridSessionForCurationTask_legacy.js.map +1 -1
- package/dist/features/entity/metadata-task/hooks/useMetadataTaskTable.js +1 -1
- package/dist/features/entity/metadata-task/hooks/useMetadataTaskTable.js.map +1 -1
- package/dist/features/entity/metadata-task/hooks/useOpenCuratorButton.d.ts +10 -0
- package/dist/features/entity/metadata-task/hooks/useOpenCuratorButton.d.ts.map +1 -0
- package/dist/features/entity/metadata-task/hooks/useOpenCuratorButton.js +37 -0
- package/dist/features/entity/metadata-task/hooks/useOpenCuratorButton.js.map +1 -0
- package/dist/features/entity/metadata-task/utils/constants.d.ts +5 -0
- package/dist/features/entity/metadata-task/utils/constants.d.ts.map +1 -0
- package/dist/features/entity/metadata-task/utils/constants.js +6 -0
- package/dist/features/entity/metadata-task/utils/constants.js.map +1 -0
- package/dist/mocks/challenge/mockChallenge.js.map +1 -1
- package/dist/mocks/entity/mockDataset.js.map +1 -1
- package/dist/mocks/entity/mockDatasetCollection.js.map +1 -1
- package/dist/mocks/entity/mockFileEntity.js.map +1 -1
- package/dist/mocks/entity/mockFileView.js.map +1 -1
- package/dist/mocks/entity/mockGeneratedEntityData.js.map +1 -1
- package/dist/mocks/entity/mockProject.js.map +1 -1
- package/dist/mocks/entity/mockProjectView.js.map +1 -1
- package/dist/mocks/entity/mockRootEntity.js.map +1 -1
- package/dist/mocks/entity/mockTableEntity.js.map +1 -1
- package/dist/mocks/mockWiki.js.map +1 -1
- package/dist/mocks/msw/handlers/asyncJobHandlers.js.map +1 -1
- package/dist/mocks/msw/handlers/challengeHandlers.js.map +1 -1
- package/dist/mocks/msw/handlers/changePasswordHandlers.js.map +1 -1
- package/dist/mocks/msw/handlers/discussionHandlers.js.map +1 -1
- package/dist/mocks/msw/handlers/entityHandlers.js.map +1 -1
- package/dist/mocks/msw/handlers/fileHandlers.js.map +1 -1
- package/dist/mocks/msw/handlers/gridHandlers.js.map +1 -1
- package/dist/mocks/msw/handlers/personalAccessTokenHandlers.js.map +1 -1
- package/dist/mocks/msw/handlers/subscriptionHandlers.js.map +1 -1
- package/dist/mocks/msw/handlers/teamHandlers.js.map +1 -1
- package/dist/mocks/msw/handlers/userProfileHandlers.js.map +1 -1
- package/dist/mocks/msw/handlers/wikiHandlers.js.map +1 -1
- package/dist/mocks/provenance/mockActivity.js.map +1 -1
- package/dist/mocks/query/mockReleaseCardsTableQueryResultBundle.js.map +1 -1
- package/dist/ror-client/index.js.map +1 -1
- package/dist/style/components/_cards.scss +4 -0
- package/dist/style/components/_data-grid-extra.css +1 -1
- package/dist/style/components/_data-grid-extra.scss +2 -0
- package/dist/style/main.css +1 -1
- package/dist/synapse-client/HttpClient.js.map +1 -1
- package/dist/synapse-client/SynapseClient.js.map +1 -1
- package/dist/synapse-queries/KeyFactory.d.ts +1 -0
- package/dist/synapse-queries/KeyFactory.d.ts.map +1 -1
- package/dist/synapse-queries/KeyFactory.js +3 -0
- package/dist/synapse-queries/KeyFactory.js.map +1 -1
- package/dist/synapse-queries/QueryMatching.test-utils.js.map +1 -1
- package/dist/synapse-queries/auth/useTwoFactorEnrollment.js.map +1 -1
- package/dist/synapse-queries/curation/task/useCurationTask.d.ts +1 -1
- package/dist/synapse-queries/curation/task/useCurationTask.d.ts.map +1 -1
- package/dist/synapse-queries/curation/task/useCurationTask.js +1 -1
- package/dist/synapse-queries/curation/task/useCurationTask.js.map +1 -1
- package/dist/synapse-queries/dataaccess/useRestrictionInformation.js.map +1 -1
- package/dist/synapse-queries/doi/useDOI.js.map +1 -1
- package/dist/synapse-queries/download/useDownloadList.js.map +1 -1
- package/dist/synapse-queries/entity/useEntity.js.map +1 -1
- package/dist/synapse-queries/entity/useEntityBundle.js.map +1 -1
- package/dist/synapse-queries/entity/useExportTableQueryToAnalysisPlatform.js.map +1 -1
- package/dist/synapse-queries/entity/useExportToTerra.js.map +1 -1
- package/dist/synapse-queries/entity/useGetQueryResultBundle.js.map +1 -1
- package/dist/synapse-queries/entity/useSchema.js.map +1 -1
- package/dist/synapse-queries/file/UploadToS3.js.map +1 -1
- package/dist/synapse-queries/file/useDirectUploadToS3.js.map +1 -1
- package/dist/synapse-queries/file/useFiles.js.map +1 -1
- package/dist/synapse-queries/forum/useReply.js.map +1 -1
- package/dist/synapse-queries/forum/useThread.d.ts +1 -0
- package/dist/synapse-queries/forum/useThread.d.ts.map +1 -1
- package/dist/synapse-queries/forum/useThread.js +19 -12
- package/dist/synapse-queries/forum/useThread.js.map +1 -1
- package/dist/synapse-queries/grid/useEstablishWebsocketConnection.d.ts +2 -0
- package/dist/synapse-queries/grid/useEstablishWebsocketConnection.d.ts.map +1 -1
- package/dist/synapse-queries/grid/useEstablishWebsocketConnection.js.map +1 -1
- package/dist/synapse-queries/grid/useExportGrid.js.map +1 -1
- package/dist/synapse-queries/grid/useGridSession.js.map +1 -1
- package/dist/synapse-queries/grid/useImportCsvIntoGrid.js.map +1 -1
- package/dist/synapse-queries/subscription/useSubscription.js.map +1 -1
- package/dist/synapse-queries/table/useGetCsvPreview.js.map +1 -1
- package/dist/synapse-queries/table/useTableUpdateTransaction.js.map +1 -1
- package/dist/synapse-queries/team/useTeamMembers.js.map +1 -1
- package/dist/synapse-queries/user/useGetUserChallenges.js.map +1 -1
- package/dist/synapse-queries/user/useUserBundle.js.map +1 -1
- package/dist/synapse-queries/user/useUserGroupHeader.js.map +1 -1
- package/dist/testutils/ReactQueryMockUtils.js.map +1 -1
- package/dist/theme/ThemeProvider.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/utils/APIConstants.d.ts +1 -0
- package/dist/utils/APIConstants.d.ts.map +1 -1
- package/dist/utils/APIConstants.js +2 -2
- package/dist/utils/APIConstants.js.map +1 -1
- package/dist/utils/AppUtils/session/ApplicationSessionManager.d.ts.map +1 -1
- package/dist/utils/AppUtils/session/ApplicationSessionManager.js +7 -4
- package/dist/utils/AppUtils/session/ApplicationSessionManager.js.map +1 -1
- package/dist/utils/AppUtils/session/SynapseSessionManager.js.map +1 -1
- package/dist/utils/AppUtils/session/useSessionManager.js.map +1 -1
- package/dist/utils/PermissionLevelToAccessType.js.map +1 -1
- package/dist/utils/challenge/evaluation/EvaluationUtils.js.map +1 -1
- package/dist/utils/context/SynapseContext.js.map +1 -1
- package/dist/utils/functions/AccessControlListUtils.d.ts +4 -0
- package/dist/utils/functions/AccessControlListUtils.d.ts.map +1 -1
- package/dist/utils/functions/AccessControlListUtils.js +12 -1
- package/dist/utils/functions/AccessControlListUtils.js.map +1 -1
- package/dist/utils/functions/EntityTypeUtils.d.ts.map +1 -1
- package/dist/utils/functions/EntityTypeUtils.js +15 -4
- package/dist/utils/functions/EntityTypeUtils.js.map +1 -1
- package/dist/utils/functions/GridApiUtils.js.map +1 -1
- package/dist/utils/functions/QueryFilterUtils.js.map +1 -1
- package/dist/utils/functions/RealmUtils.d.ts +4 -0
- package/dist/utils/functions/RealmUtils.d.ts.map +1 -1
- package/dist/utils/functions/RealmUtils.js +9 -3
- package/dist/utils/functions/RealmUtils.js.map +1 -1
- package/dist/utils/functions/SanitizeHtmlUtils.js.map +1 -1
- package/dist/utils/functions/SanitizeHtmlUtils.test-utils.js.map +1 -1
- package/dist/utils/functions/SqlFunctions.js.map +1 -1
- package/dist/utils/functions/StringUtils.js.map +1 -1
- package/dist/utils/functions/deepLinkingUtils.js.map +1 -1
- package/dist/utils/functions/getDataFromFromStorage.js.map +1 -1
- package/dist/utils/functions/getEndpoint.js.map +1 -1
- package/dist/utils/functions/getUserData.js.map +1 -1
- package/dist/utils/functions/queryUtils.js.map +1 -1
- package/dist/utils/functions/testDownloadSpeed.js.map +1 -1
- package/dist/utils/hooks/useConfirmItems.js.map +1 -1
- package/dist/utils/hooks/useCookiePreferences.js.map +1 -1
- package/dist/utils/hooks/useCreateShortUrl.js.map +1 -1
- package/dist/utils/hooks/useDetectSSOCode.js.map +1 -1
- package/dist/utils/hooks/useDirectDownloadHandler.js.map +1 -1
- package/dist/utils/hooks/useGetGoalData.js.map +1 -1
- package/dist/utils/hooks/useGetInfoFromIds.js.map +1 -1
- package/dist/utils/hooks/useImageUrlUtils.js.map +1 -1
- package/dist/utils/hooks/useImmutableTableQuery/useImmutableTableQuery.js.map +1 -1
- package/dist/utils/hooks/useImmutableTableQuery/useTableQueryReducer.js.map +1 -1
- package/dist/utils/hooks/useIsBot.js.map +1 -1
- package/dist/utils/hooks/useListState.js.map +1 -1
- package/dist/utils/hooks/useLogin.d.ts.map +1 -1
- package/dist/utils/hooks/useLogin.js +53 -52
- package/dist/utils/hooks/useLogin.js.map +1 -1
- package/dist/utils/hooks/useMutuallyExclusiveState.js.map +1 -1
- package/dist/utils/hooks/useOverlay.js.map +1 -1
- package/dist/utils/hooks/usePreFetchResource.js.map +1 -1
- package/dist/utils/hooks/useQuerySearchParam.js.map +1 -1
- package/dist/utils/hooks/useScrollFadeTransition.js.map +1 -1
- package/dist/utils/hooks/useSet.js.map +1 -1
- package/dist/utils/hooks/useSourceAppConfigs.js.map +1 -1
- package/dist/utils/hooks/useTableImageUrl.js.map +1 -1
- package/dist/utils/hooks/useUploadFileEntity/useCreatePathsAndGetParentId.js.map +1 -1
- package/dist/utils/hooks/useUploadFileEntity/useLinkFileEntityToURL.js.map +1 -1
- package/dist/utils/hooks/useUploadFileEntity/usePrepareFileEntityUpload.js.map +1 -1
- package/dist/utils/hooks/useUploadFileEntity/useTrackFileUploads.js.map +1 -1
- package/dist/utils/hooks/useUploadFileEntity/useUploadFileEntities.js.map +1 -1
- package/dist/utils/hooks/useUploadFileEntity/useUploadFiles.js.map +1 -1
- package/dist/utils/hooks/useUploadFileEntity/willUploadsExceedStorageLimit.js.map +1 -1
- package/dist/utils/html/TargetEnum.js.map +1 -1
- package/dist/utils/jsonschema/SchemaAnnotationUtils.js.map +1 -1
- package/package.json +5 -5
package/dist/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DownloadIneligibleForPackagingFilesFromListButton.js","names":[],"sources":["../../../src/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.tsx"],"sourcesContent":["import { useSynapseContext } from '@/utils'\nimport { implementsExternalFileHandleInterface } from '@/utils/types/IsType'\nimport { calculateFriendlyFileSize } from '@/utils/functions/calculateFriendlyFileSize'\nimport { Button, LinearProgress, Typography } from '@mui/material'\nimport { Download } from '@mui/icons-material'\nimport { SynapseClientError } from '@sage-bionetworks/synapse-client/util/SynapseClientError'\nimport {\n BatchFileRequest,\n BatchFileResult,\n ExternalFileHandle,\n FileEntity,\n FileHandleAssociation,\n FileHandleAssociateType,\n} from '@sage-bionetworks/synapse-types'\nimport { useCallback, useRef, useState } from 'react'\nimport { useQueryClient } from '@tanstack/react-query'\nimport { displayToast } from '../ToastMessage/ToastMessage'\nimport {\n useGetAvailableFilesToDownloadInfinite,\n useGetDownloadListStatistics,\n useRemoveFilesFromDownloadList,\n} from '@/synapse-queries/download/useDownloadList'\nimport { getFiles } from '@/synapse-client/SynapseClient'\nimport { useGetEntityQueryOptions } from '@/synapse-queries/entity/useEntity'\nimport { DialogBase } from '../DialogBase'\nimport { deduplicateFileName, getFileName } from './fileNameUtils'\n\n// showDirectoryPicker is not yet available on the Window interface.\ninterface FileSystemAccessWindow extends Window {\n showDirectoryPicker(options?: {\n mode?: 'read' | 'readwrite'\n startIn?:\n | 'desktop'\n | 'documents'\n | 'downloads'\n | 'music'\n | 'pictures'\n | 'videos'\n }): Promise<FileSystemDirectoryHandle>\n}\n\n/**\n * Type guard to check if File System Access API is available\n */\nfunction supportsFileSystemAccess(\n window: Window,\n): window is FileSystemAccessWindow {\n return 'showDirectoryPicker' in window\n}\n\nconst FILE_BATCH_SIZE = 50 // Maximum batch size for fetching presigned URLs\n\nexport type DownloadIneligibleForPackagingFilesFromListButtonProps = {\n buttonText?: string\n variant?: 'text' | 'outlined' | 'contained'\n}\n\n/**\n * Button component that downloads files from the user's download list that are ineligible for packaging.\n * Uses the infinite query hook to fetch all pages of download list items,\n * batches requests to get presigned URLs, and triggers browser downloads.\n */\nexport function DownloadIneligibleForPackagingFilesFromListButton(\n props: DownloadIneligibleForPackagingFilesFromListButtonProps,\n) {\n const { buttonText = 'Start Multi-file Download', variant = 'contained' } =\n props\n const { accessToken, isAuthenticated } = useSynapseContext()\n const queryClient = useQueryClient()\n const getEntityQueryOptions = useGetEntityQueryOptions<FileEntity>()\n const [isDownloading, setIsDownloading] = useState(false)\n const isDownloadingRef = useRef(false)\n const isCancelledRef = useRef(false)\n const [downloadProgress, setDownloadProgress] = useState<{\n currentFile: string\n fileIndex: number\n totalFiles: number\n bytesDownloaded: number\n totalBytes: number\n } | null>(null)\n\n const { data, status, hasNextPage, fetchNextPage, error } =\n useGetAvailableFilesToDownloadInfinite()\n\n const { mutateAsync: removeFilesFromDownloadList } =\n useRemoveFilesFromDownloadList()\n\n const { refetch: refetchDownloadListStatistics } =\n useGetDownloadListStatistics()\n\n /**\n * Downloads all files from the download list.\n */\n const downloadAllFiles = useCallback(\n async (downloadListItems: typeof data) => {\n // Prevent re-entry if already downloading\n if (isDownloadingRef.current) {\n return\n }\n\n if (!downloadListItems || !isAuthenticated) {\n setIsDownloading(false)\n return\n }\n\n try {\n isDownloadingRef.current = true\n isCancelledRef.current = false\n const allItems = downloadListItems.pages.flatMap(page => page.page)\n\n // Filter to only include files that are NOT eligible for packaging\n const nonPackageableFiles = allItems.filter(\n item => !item.isEligibleForPackaging,\n )\n\n if (nonPackageableFiles.length === 0) {\n displayToast('No non-packageable files available to download', 'info')\n setIsDownloading(false)\n isDownloadingRef.current = false\n return\n }\n\n // Determine if File System Access API is available\n const useFileSystemAccess = supportsFileSystemAccess(window)\n\n // Prompt user to select a directory for downloads BEFORE async operations\n // (must be called during user gesture to avoid SecurityError)\n let directoryHandle: FileSystemDirectoryHandle | undefined\n\n if (useFileSystemAccess) {\n // TypeScript narrowing: we know window has showDirectoryPicker at this point\n const fileSystemWindow = window as unknown as FileSystemAccessWindow\n\n try {\n directoryHandle = await fileSystemWindow.showDirectoryPicker({\n mode: 'readwrite',\n })\n } catch (error) {\n // User cancelled directory picker\n console.error('Failed to select directory:', error)\n displayToast(\n 'Directory selection is required to directly download files from the website.',\n 'warning',\n )\n setIsDownloading(false)\n isDownloadingRef.current = false\n return\n }\n } else {\n // Show info message for browsers without File System Access API\n displayToast(\n 'Your browser will download files individually to your default downloads folder. Each file may trigger a separate download prompt.',\n 'info',\n )\n }\n\n // Initialize progress tracking\n setDownloadProgress({\n currentFile: '',\n fileIndex: 0,\n totalFiles: nonPackageableFiles.length,\n bytesDownloaded: 0,\n totalBytes: 0,\n })\n\n // Fetch entities to get dataFileHandleId for each file\n // Use React Query's ensureQueryData to leverage cache and built-in retry logic (handles 429s with exponential backoff)\n // Map key combines entity ID and version to handle multiple versions of the same entity\n const entityIdToFileHandleId = new Map<string, string>()\n\n // Fetch all entities in parallel - React Query handles concurrency and retries\n const entityPromises = nonPackageableFiles.map(async item => {\n if (isCancelledRef.current) {\n return\n }\n\n try {\n const entity = await queryClient.ensureQueryData(\n getEntityQueryOptions(\n item.fileEntityId,\n item.versionNumber?.toString(),\n ),\n )\n // Use composite key: entityId-version (or entityId if no version)\n const mapKey = `${entity.id!}-${item.versionNumber ?? 'latest'}`\n entityIdToFileHandleId.set(mapKey, entity.dataFileHandleId)\n } catch (error) {\n console.error(`Failed to fetch entity ${item.fileEntityId}:`, error)\n // Continue even if one entity fails\n }\n })\n\n await Promise.all(entityPromises)\n\n // Convert download list items to file handle associations using the fetched dataFileHandleIds\n const fileHandleAssociations: FileHandleAssociation[] =\n nonPackageableFiles\n .filter(item => {\n const mapKey = `${item.fileEntityId}-${\n item.versionNumber ?? 'latest'\n }`\n return entityIdToFileHandleId.has(mapKey)\n })\n .map(item => {\n const mapKey = `${item.fileEntityId}-${\n item.versionNumber ?? 'latest'\n }`\n return {\n fileHandleId: entityIdToFileHandleId.get(mapKey)!,\n associateObjectId: item.fileEntityId,\n associateObjectType: FileHandleAssociateType.FileEntity,\n }\n })\n\n if (fileHandleAssociations.length === 0) {\n displayToast(\n 'Failed to fetch file information for download',\n 'danger',\n )\n setIsDownloading(false)\n isDownloadingRef.current = false\n return\n }\n\n // Split into batches to avoid overwhelming the API\n const batches: FileHandleAssociation[][] = []\n for (\n let i = 0;\n i < fileHandleAssociations.length;\n i += FILE_BATCH_SIZE\n ) {\n batches.push(fileHandleAssociations.slice(i, i + FILE_BATCH_SIZE))\n }\n\n let downloadedCount = 0\n let failedCount = 0\n const successfullyDownloadedItems: typeof nonPackageableFiles = []\n\n // Track used filenames to prevent collisions\n const usedFilenames = new Map<string, number>()\n\n /**\n * Helper function to download file using traditional anchor tag method\n * @returns boolean indicating if the download was successful\n */\n const downloadFileTraditional = async (\n downloadUrl: string,\n fileName: string,\n ): Promise<boolean> => {\n try {\n const response = await fetch(downloadUrl)\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`)\n }\n\n const blob = await response.blob()\n const blobUrl = URL.createObjectURL(blob)\n const anchor = document.createElement('a')\n anchor.href = blobUrl\n anchor.download = fileName\n anchor.style.display = 'none'\n document.body.appendChild(anchor)\n anchor.click()\n document.body.removeChild(anchor)\n\n // Clean up blob URL after a delay to ensure download initiation\n setTimeout(() => URL.revokeObjectURL(blobUrl), 1000)\n\n return true\n } catch (error) {\n console.error(`Failed to download file ${fileName}:`, error)\n // Fallback to window.open method\n try {\n window.open(downloadUrl, '_blank', 'noopener,noreferrer')\n return true\n } catch (fallbackError) {\n console.error(`Fallback window.open also failed:`, fallbackError)\n return false\n }\n }\n }\n\n /**\n * Helper function to process a single file download\n * @returns boolean indicating if download is successful\n */\n const processFileDownload = async (\n fileResult: BatchFileResult['requestedFiles'][0],\n originalItem: (typeof nonPackageableFiles)[0] | undefined,\n ): Promise<boolean> => {\n try {\n let downloadUrl: string | undefined\n\n // Check if this is an external file handle\n if (\n fileResult.fileHandle &&\n implementsExternalFileHandleInterface(fileResult.fileHandle)\n ) {\n // For external file handles, use the externalURL\n downloadUrl = (fileResult.fileHandle as ExternalFileHandle)\n .externalURL\n } else if (fileResult.preSignedURL) {\n // For other file types, use the presigned URL\n downloadUrl = fileResult.preSignedURL\n }\n\n if (!downloadUrl) {\n return false\n }\n\n // Get filename from file result or create a default name\n const baseFileName = getFileName(fileResult, originalItem)\n\n // Handle filename collisions by adding a counter suffix\n const fileName = deduplicateFileName(baseFileName, usedFilenames)\n\n // Update progress with current file info\n const currentFileIndex = downloadedCount + 1\n setDownloadProgress(prev =>\n prev\n ? {\n ...prev,\n currentFile: fileName,\n fileIndex: currentFileIndex,\n bytesDownloaded: 0,\n totalBytes: 0,\n }\n : null,\n )\n\n // Use traditional download method for unsupported browsers\n if (!useFileSystemAccess) {\n const success = await downloadFileTraditional(\n downloadUrl,\n fileName,\n )\n if (success) {\n downloadedCount = currentFileIndex\n if (originalItem) {\n successfullyDownloadedItems.push(originalItem)\n }\n }\n return success\n }\n\n // Use File System Access API for supported browsers\n if (!directoryHandle) {\n return false\n }\n\n try {\n // Fetch the file\n const response = await fetch(downloadUrl)\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`)\n }\n\n // Get total file size from headers\n const contentLength = response.headers.get('content-length')\n const totalBytes = contentLength ? parseInt(contentLength, 10) : 0\n\n // Update progress with file size\n setDownloadProgress(prev =>\n prev\n ? {\n ...prev,\n bytesDownloaded: 0,\n totalBytes,\n }\n : null,\n )\n\n // Create file handle in selected directory\n const fileHandle = await directoryHandle.getFileHandle(fileName, {\n create: true,\n })\n const writableStream = await fileHandle.createWritable()\n\n // Stream the response body to the file with progress tracking\n if (response.body) {\n const reader = response.body.getReader()\n let bytesReceived = 0\n\n try {\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n\n bytesReceived += value.length\n await writableStream.write(value)\n\n // Update progress\n setDownloadProgress(prev =>\n prev\n ? {\n ...prev,\n bytesDownloaded: bytesReceived,\n }\n : null,\n )\n }\n } catch (streamError) {\n await writableStream.abort()\n throw streamError\n } finally {\n await writableStream.close()\n }\n } else {\n // Fallback if streaming not supported\n try {\n const blob = await response.blob()\n await writableStream.write(blob)\n } finally {\n await writableStream.close()\n }\n }\n\n downloadedCount = currentFileIndex\n\n // Track successfully downloaded item for batch removal\n if (originalItem) {\n successfullyDownloadedItems.push(originalItem)\n }\n return true\n } catch (fetchError) {\n console.error(\n `Failed to fetch/write file ${fileResult.fileHandleId}:`,\n fetchError,\n )\n // Fallback to window.open if File System Access API fails\n try {\n downloadFileTraditional(downloadUrl, fileName)\n downloadedCount = currentFileIndex\n if (originalItem) {\n successfullyDownloadedItems.push(originalItem)\n }\n return true\n } catch (fallbackError) {\n console.error(\n `Fallback downloadFileTraditional also failed for ${fileResult.fileHandleId}:`,\n fallbackError,\n )\n return false\n }\n }\n } catch (error) {\n console.error(\n `Failed to download file ${fileResult.fileHandleId}:`,\n error,\n )\n return false\n }\n }\n\n /**\n * Fallback function to fetch files individually when batch fails\n */\n const fetchIndividually = async (\n batch: FileHandleAssociation[],\n ): Promise<void> => {\n console.info(\n `Attempting to fetch ${batch.length} files individually after batch failure`,\n )\n\n for (const fileHandleAssociation of batch) {\n // Check if user cancelled the operation\n if (isCancelledRef.current) {\n console.info('Individual file fetch cancelled by user')\n break\n }\n\n const singleBatch = [fileHandleAssociation]\n try {\n const batchRequest: BatchFileRequest = {\n requestedFiles: singleBatch,\n includeFileHandles: true,\n includePreSignedURLs: true,\n includePreviewPreSignedURLs: false,\n }\n\n const batchResult = await getFiles(batchRequest, accessToken)\n\n if (batchResult.requestedFiles.length > 0) {\n const fileResult = batchResult.requestedFiles[0]\n const originalItem = nonPackageableFiles.find(\n item =>\n item.fileEntityId ===\n fileHandleAssociation.associateObjectId,\n )\n\n const success = await processFileDownload(\n fileResult,\n originalItem,\n )\n if (!success) {\n failedCount++\n }\n } else {\n failedCount++\n }\n } catch (error) {\n console.error(\n `Failed to fetch individual file ${fileHandleAssociation.fileHandleId}:`,\n error,\n )\n failedCount++\n }\n }\n }\n\n // Process each batch\n for (const batch of batches) {\n // Check if user cancelled the operation\n if (isCancelledRef.current) {\n console.info('Download cancelled by user')\n break\n }\n\n // Try to fetch the entire batch (getFiles has built-in retry logic)\n let batchResult: BatchFileResult | null = null\n try {\n const batchRequest: BatchFileRequest = {\n requestedFiles: batch,\n includeFileHandles: true,\n includePreSignedURLs: true,\n includePreviewPreSignedURLs: false,\n }\n batchResult = await getFiles(batchRequest, accessToken)\n } catch (error) {\n console.error('Failed to fetch batch:', error)\n }\n\n if (batchResult) {\n // Batch fetch succeeded, process all files\n for (let i = 0; i < batchResult.requestedFiles.length; i++) {\n // Check if user cancelled the operation\n if (isCancelledRef.current) {\n console.info(\n 'Download cancelled by user during batch processing',\n )\n break\n }\n\n const fileResult = batchResult.requestedFiles[i]\n const originalItem = nonPackageableFiles.find(\n item => item.fileEntityId === batch[i].associateObjectId,\n )\n\n const success = await processFileDownload(\n fileResult,\n originalItem,\n )\n if (!success) {\n failedCount++\n }\n }\n } else {\n // Batch fetch failed after retries, try fetching files individually\n await fetchIndividually(batch)\n }\n }\n\n // Remove all successfully downloaded files from the download list in one batch\n if (successfullyDownloadedItems.length > 0) {\n await removeFilesFromDownloadList({\n batchToRemove: successfullyDownloadedItems.map(\n (item: (typeof nonPackageableFiles)[0]) => ({\n fileEntityId: item.fileEntityId,\n versionNumber: item.versionNumber,\n }),\n ),\n })\n // Refetch statistics after removing files\n await refetchDownloadListStatistics()\n // Scroll to top of page to show updated statistics\n window.scrollTo({ top: 0, behavior: 'smooth' })\n }\n\n // Show completion message\n if (isCancelledRef.current) {\n displayToast(\n `Download cancelled. ${downloadedCount} file${\n downloadedCount !== 1 ? 's were' : ' was'\n } downloaded before cancellation.`,\n 'info',\n )\n } else if (downloadedCount > 0) {\n displayToast(\n `Download started for ${downloadedCount} file${\n downloadedCount !== 1 ? 's' : ''\n }${\n failedCount > 0\n ? `. ${failedCount} file${failedCount !== 1 ? 's' : ''} failed.`\n : '.'\n }`,\n failedCount > 0 ? 'warning' : 'success',\n )\n } else {\n displayToast('No files could be downloaded', 'warning')\n }\n } catch (error) {\n console.error('Error downloading files:', error)\n const message =\n (error as SynapseClientError | undefined)?.reason ??\n (error instanceof Error ? error.message : undefined) ??\n 'An error occurred while downloading files'\n displayToast(message, 'danger')\n } finally {\n setDownloadProgress(null)\n setIsDownloading(false)\n isDownloadingRef.current = false\n }\n },\n [\n accessToken,\n isAuthenticated,\n queryClient,\n getEntityQueryOptions,\n removeFilesFromDownloadList,\n refetchDownloadListStatistics,\n ],\n )\n\n const handleClick = useCallback(async () => {\n if (isDownloading) {\n return\n }\n setIsDownloading(true)\n\n // Fetch all remaining pages imperatively, then download\n try {\n let stillHasNextPage = hasNextPage\n let latestData = data\n while (stillHasNextPage && fetchNextPage) {\n const result = await fetchNextPage()\n stillHasNextPage = result.hasNextPage\n if (result.data) {\n latestData = result.data\n }\n }\n\n // All pages loaded, now download\n if (status === 'success' && latestData) {\n void downloadAllFiles(latestData)\n } else {\n // Failed to load data\n setIsDownloading(false)\n isDownloadingRef.current = false\n displayToast(\n 'Failed to load download list. Please try again.',\n 'danger',\n )\n }\n } catch (error) {\n console.error('Error downloading files:', error)\n setIsDownloading(false)\n isDownloadingRef.current = false\n const message =\n (error as SynapseClientError | undefined)?.reason ??\n (error instanceof Error ? error.message : undefined) ??\n 'An error occurred while preparing files for download'\n displayToast(message, 'danger')\n }\n }, [\n isDownloading,\n hasNextPage,\n fetchNextPage,\n status,\n data,\n downloadAllFiles,\n ])\n\n const handleCancel = useCallback(() => {\n isCancelledRef.current = true\n setDownloadProgress(null)\n setIsDownloading(false)\n isDownloadingRef.current = false\n }, [])\n\n if (error) {\n return null\n }\n\n return (\n <>\n <DialogBase\n open={!!downloadProgress}\n title=\"Downloading Files\"\n hasCloseButton={false}\n onCancel={handleCancel}\n maxWidth=\"sm\"\n content={\n downloadProgress ? (\n <>\n <Typography\n variant=\"body2\"\n color=\"text.secondary\"\n gutterBottom\n id=\"download-progress-description\"\n >\n File {downloadProgress.fileIndex} of{' '}\n {downloadProgress.totalFiles}\n </Typography>\n <Typography variant=\"body2\" noWrap gutterBottom>\n {downloadProgress.currentFile}\n </Typography>\n {downloadProgress.totalBytes > 0 && (\n <>\n <LinearProgress\n variant=\"determinate\"\n value={\n (downloadProgress.bytesDownloaded /\n downloadProgress.totalBytes) *\n 100\n }\n sx={{ my: 2 }}\n aria-label=\"Download progress\"\n />\n <Typography\n variant=\"body2\"\n color=\"text.secondary\"\n aria-live=\"polite\"\n aria-atomic=\"true\"\n >\n {calculateFriendlyFileSize(\n downloadProgress.bytesDownloaded,\n )}{' '}\n of {calculateFriendlyFileSize(downloadProgress.totalBytes)}\n </Typography>\n </>\n )}\n {downloadProgress.totalBytes === 0 && (\n <LinearProgress sx={{ my: 2 }} aria-label=\"Download progress\" />\n )}\n </>\n ) : null\n }\n actions={\n <Button variant=\"outlined\" color=\"error\" onClick={handleCancel}>\n Cancel\n </Button>\n }\n DialogProps={{\n 'aria-describedby': 'download-progress-description',\n disableEscapeKeyDown: false,\n }}\n />\n <Button\n variant={variant}\n onClick={() => {\n void handleClick()\n }}\n loading={isDownloading}\n startIcon={<Download />}\n >\n {buttonText}\n </Button>\n </>\n )\n}\n\nexport default DownloadIneligibleForPackagingFilesFromListButton\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DownloadIneligibleForPackagingFilesFromListButton.js","names":[],"sources":["../../../src/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.tsx"],"sourcesContent":["import { useSynapseContext } from '@/utils'\nimport { implementsExternalFileHandleInterface } from '@/utils/types/IsType'\nimport { calculateFriendlyFileSize } from '@/utils/functions/calculateFriendlyFileSize'\nimport {\n Box,\n Button,\n IconButton,\n LinearProgress,\n Paper,\n Typography,\n} from '@mui/material'\nimport { Close, Download } from '@mui/icons-material'\nimport CloudWarning from '@/assets/icons/CloudWarning'\nimport { SynapseClientError } from '@sage-bionetworks/synapse-client/util/SynapseClientError'\nimport dayjs from 'dayjs'\nimport duration from 'dayjs/plugin/duration'\nimport relativeTime from 'dayjs/plugin/relativeTime'\nimport {\n BatchFileRequest,\n BatchFileResult,\n ExternalFileHandle,\n FileEntity,\n FileHandleAssociation,\n FileHandleAssociateType,\n} from '@sage-bionetworks/synapse-types'\nimport { useCallback, useEffect, useRef, useState } from 'react'\nimport { useQueryClient } from '@tanstack/react-query'\nimport { displayToast } from '../ToastMessage/ToastMessage'\nimport {\n useGetAvailableFilesToDownloadInfinite,\n useGetDownloadListStatistics,\n useRemoveFilesFromDownloadList,\n} from '@/synapse-queries/download/useDownloadList'\nimport { getFiles } from '@/synapse-client/SynapseClient'\nimport { useGetEntityQueryOptions } from '@/synapse-queries/entity/useEntity'\n\nimport { deduplicateFileName, getFileName } from './fileNameUtils'\nimport styles from './DownloadIneligibleForPackagingFilesFromListButton.module.scss'\n\n// showDirectoryPicker is not yet available on the Window interface.\ninterface FileSystemAccessWindow extends Window {\n showDirectoryPicker(options?: {\n mode?: 'read' | 'readwrite'\n startIn?:\n | 'desktop'\n | 'documents'\n | 'downloads'\n | 'music'\n | 'pictures'\n | 'videos'\n }): Promise<FileSystemDirectoryHandle>\n}\n\n/**\n * Type guard to check if File System Access API is available\n */\nfunction supportsFileSystemAccess(\n window: Window,\n): window is FileSystemAccessWindow {\n return 'showDirectoryPicker' in window\n}\n\nconst FILE_BATCH_SIZE = 50 // Maximum batch size for fetching presigned URLs\nconst ETA_DELAY_MS = 3000 // Wait this long before showing ETA\n\ndayjs.extend(duration)\ndayjs.extend(relativeTime)\n\nexport type DownloadIneligibleForPackagingFilesFromListButtonProps = {\n buttonText?: string\n variant?: 'text' | 'outlined' | 'contained'\n}\n\n/**\n * Button component that downloads files from the user's download list that are ineligible for packaging.\n * Uses the infinite query hook to fetch all pages of download list items,\n * batches requests to get presigned URLs, and triggers browser downloads.\n */\nexport function DownloadIneligibleForPackagingFilesFromListButton(\n props: DownloadIneligibleForPackagingFilesFromListButtonProps,\n) {\n const { buttonText = 'Start Multi-file Download', variant = 'contained' } =\n props\n const { accessToken, isAuthenticated } = useSynapseContext()\n const queryClient = useQueryClient()\n const getEntityQueryOptions = useGetEntityQueryOptions<FileEntity>()\n const [isDownloading, setIsDownloading] = useState(false)\n const isDownloadingRef = useRef(false)\n const [showExternalFileWarning, setShowExternalFileWarning] = useState(false)\n const isCancelledRef = useRef(false)\n const abortControllerRef = useRef<AbortController | null>(null)\n const [downloadProgress, setDownloadProgress] = useState<{\n currentFile: string\n fileIndex: number\n totalFiles: number\n bytesDownloaded: number\n totalBytes: number\n estimatedSecondsRemaining: number | null\n } | null>(null)\n const fileDownloadStartRef = useRef<number | null>(null)\n\n // Accessibility: tracks the last announced file index and progress bucket so\n // the aria-live region only updates on meaningful changes (not every chunk).\n const [announceText, setAnnounceText] = useState('')\n const lastAnnouncedFileIndexRef = useRef<number>(-1)\n const lastAnnouncedPercentBucketRef = useRef<number>(-1)\n\n useEffect(() => {\n if (!downloadProgress) {\n lastAnnouncedFileIndexRef.current = -1\n lastAnnouncedPercentBucketRef.current = -1\n setAnnounceText('')\n return\n }\n\n const { fileIndex, totalFiles, currentFile, bytesDownloaded, totalBytes } =\n downloadProgress\n\n // Announce when a new file starts downloading\n if (fileIndex !== lastAnnouncedFileIndexRef.current) {\n lastAnnouncedFileIndexRef.current = fileIndex\n lastAnnouncedPercentBucketRef.current = -1\n setAnnounceText(\n `Downloading file ${fileIndex} of ${totalFiles}: ${currentFile}`,\n )\n return\n }\n\n // Announce at each 25% milestone (25, 50, 75, 100) once per file\n if (totalBytes > 0) {\n const percent = Math.floor((bytesDownloaded / totalBytes) * 100)\n const bucket = Math.floor(percent / 25) * 25\n if (bucket > 0 && bucket !== lastAnnouncedPercentBucketRef.current) {\n lastAnnouncedPercentBucketRef.current = bucket\n setAnnounceText(`${bucket}% of ${currentFile} downloaded`)\n }\n }\n }, [downloadProgress])\n\n const { data, status, hasNextPage, fetchNextPage, error } =\n useGetAvailableFilesToDownloadInfinite()\n\n const { mutateAsync: removeFilesFromDownloadList } =\n useRemoveFilesFromDownloadList()\n\n const { refetch: refetchDownloadListStatistics } =\n useGetDownloadListStatistics()\n\n /**\n * Downloads all files from the download list.\n */\n const downloadAllFiles = useCallback(\n async (downloadListItems: typeof data) => {\n // Prevent re-entry if already downloading\n if (isDownloadingRef.current) {\n return\n }\n\n if (!downloadListItems || !isAuthenticated) {\n setIsDownloading(false)\n return\n }\n\n try {\n isDownloadingRef.current = true\n isCancelledRef.current = false\n setShowExternalFileWarning(false)\n const allItems = downloadListItems.pages.flatMap(page => page.page)\n\n // Filter to only include files that are NOT eligible for packaging\n const nonPackageableFiles = allItems.filter(\n item => !item.isEligibleForPackaging,\n )\n\n if (nonPackageableFiles.length === 0) {\n displayToast('No non-packageable files available to download', 'info')\n setIsDownloading(false)\n isDownloadingRef.current = false\n return\n }\n\n // Determine if File System Access API is available\n const useFileSystemAccess = supportsFileSystemAccess(window)\n\n // Prompt user to select a directory for downloads BEFORE async operations\n // (must be called during user gesture to avoid SecurityError)\n let directoryHandle: FileSystemDirectoryHandle | undefined\n\n if (useFileSystemAccess) {\n // TypeScript narrowing: we know window has showDirectoryPicker at this point\n const fileSystemWindow = window as unknown as FileSystemAccessWindow\n\n try {\n directoryHandle = await fileSystemWindow.showDirectoryPicker({\n mode: 'readwrite',\n })\n } catch (error) {\n // User cancelled directory picker\n console.error('Failed to select directory:', error)\n displayToast(\n 'Directory selection is required to directly download files from the website.',\n 'warning',\n )\n setIsDownloading(false)\n isDownloadingRef.current = false\n return\n }\n } else {\n // Show info message for browsers without File System Access API\n displayToast(\n 'Your browser will download files individually to your default downloads folder. Each file may trigger a separate download prompt.',\n 'info',\n )\n }\n\n // Initialize progress tracking\n fileDownloadStartRef.current = null\n setDownloadProgress({\n currentFile: '',\n fileIndex: 0,\n totalFiles: nonPackageableFiles.length,\n bytesDownloaded: 0,\n totalBytes: 0,\n estimatedSecondsRemaining: null,\n })\n\n // Fetch entities to get dataFileHandleId for each file\n // Use React Query's ensureQueryData to leverage cache and built-in retry logic (handles 429s with exponential backoff)\n // Map key combines entity ID and version to handle multiple versions of the same entity\n const entityIdToFileHandleId = new Map<string, string>()\n\n // Fetch all entities in parallel - React Query handles concurrency and retries\n const entityPromises = nonPackageableFiles.map(async item => {\n if (isCancelledRef.current) {\n return\n }\n\n try {\n const entity = await queryClient.ensureQueryData(\n getEntityQueryOptions(\n item.fileEntityId,\n item.versionNumber?.toString(),\n ),\n )\n // Use composite key: entityId-version (or entityId if no version)\n const mapKey = `${entity.id!}-${item.versionNumber ?? 'latest'}`\n entityIdToFileHandleId.set(mapKey, entity.dataFileHandleId)\n } catch (error) {\n console.error(`Failed to fetch entity ${item.fileEntityId}:`, error)\n // Continue even if one entity fails\n }\n })\n\n await Promise.all(entityPromises)\n\n // Convert download list items to file handle associations using the fetched dataFileHandleIds\n const fileHandleAssociations: FileHandleAssociation[] =\n nonPackageableFiles\n .filter(item => {\n const mapKey = `${item.fileEntityId}-${\n item.versionNumber ?? 'latest'\n }`\n return entityIdToFileHandleId.has(mapKey)\n })\n .map(item => {\n const mapKey = `${item.fileEntityId}-${\n item.versionNumber ?? 'latest'\n }`\n return {\n fileHandleId: entityIdToFileHandleId.get(mapKey)!,\n associateObjectId: item.fileEntityId,\n associateObjectType: FileHandleAssociateType.FileEntity,\n }\n })\n\n if (fileHandleAssociations.length === 0) {\n displayToast(\n 'Failed to fetch file information for download',\n 'danger',\n )\n setIsDownloading(false)\n isDownloadingRef.current = false\n return\n }\n\n // Split into batches to avoid overwhelming the API\n const batches: FileHandleAssociation[][] = []\n for (\n let i = 0;\n i < fileHandleAssociations.length;\n i += FILE_BATCH_SIZE\n ) {\n batches.push(fileHandleAssociations.slice(i, i + FILE_BATCH_SIZE))\n }\n\n let downloadedCount = 0\n let failedCount = 0\n const successfullyDownloadedItems: typeof nonPackageableFiles = []\n\n // Track used filenames to prevent collisions\n const usedFilenames = new Map<string, number>()\n\n /**\n * Helper function to download file using traditional anchor tag method\n * @returns boolean indicating if the download was successful\n */\n const downloadFileTraditional = async (\n downloadUrl: string,\n fileName: string,\n ): Promise<boolean> => {\n try {\n const response = await fetch(downloadUrl)\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`)\n }\n\n const blob = await response.blob()\n const blobUrl = URL.createObjectURL(blob)\n const anchor = document.createElement('a')\n anchor.href = blobUrl\n anchor.download = fileName\n anchor.style.display = 'none'\n document.body.appendChild(anchor)\n anchor.click()\n document.body.removeChild(anchor)\n\n // Clean up blob URL after a delay to ensure download initiation\n setTimeout(() => URL.revokeObjectURL(blobUrl), 1000)\n\n return true\n } catch (error) {\n console.error(`Failed to download file ${fileName}:`, error)\n // Fallback to window.open method\n try {\n window.open(downloadUrl, '_blank', 'noopener,noreferrer')\n return true\n } catch (fallbackError) {\n console.error(`Fallback window.open also failed:`, fallbackError)\n return false\n }\n }\n }\n\n /**\n * Helper function to process a single file download\n * @returns boolean indicating if download is successful\n */\n const processFileDownload = async (\n fileResult: BatchFileResult['requestedFiles'][0],\n originalItem: (typeof nonPackageableFiles)[0] | undefined,\n ): Promise<boolean> => {\n try {\n let downloadUrl: string | undefined\n\n // Check if this is an external file handle\n if (\n fileResult.fileHandle &&\n implementsExternalFileHandleInterface(fileResult.fileHandle)\n ) {\n // For external file handles, use the externalURL\n downloadUrl = (fileResult.fileHandle as ExternalFileHandle)\n .externalURL\n setShowExternalFileWarning(true)\n } else if (fileResult.preSignedURL) {\n // For other file types, use the presigned URL\n downloadUrl = fileResult.preSignedURL\n }\n\n if (!downloadUrl) {\n return false\n }\n\n // Get filename from file result or create a default name\n const baseFileName = getFileName(fileResult, originalItem)\n\n // Handle filename collisions by adding a counter suffix\n const fileName = deduplicateFileName(baseFileName, usedFilenames)\n\n // Update progress with current file info\n const currentFileIndex = downloadedCount + 1\n fileDownloadStartRef.current = null\n setDownloadProgress(prev =>\n prev\n ? {\n ...prev,\n currentFile: fileName,\n fileIndex: currentFileIndex,\n bytesDownloaded: 0,\n totalBytes: 0,\n estimatedSecondsRemaining: null,\n }\n : null,\n )\n\n // Use traditional download method for unsupported browsers\n if (!useFileSystemAccess) {\n const success = await downloadFileTraditional(\n downloadUrl,\n fileName,\n )\n if (success) {\n downloadedCount = currentFileIndex\n if (originalItem) {\n successfullyDownloadedItems.push(originalItem)\n }\n }\n return success\n }\n\n // Use File System Access API for supported browsers\n if (!directoryHandle) {\n return false\n }\n\n try {\n // Fetch the file\n abortControllerRef.current = new AbortController()\n const response = await fetch(downloadUrl, {\n signal: abortControllerRef.current.signal,\n })\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`)\n }\n\n // Get total file size from headers\n const contentLength = response.headers.get('content-length')\n const totalBytes = contentLength ? parseInt(contentLength, 10) : 0\n\n // Update progress with file size\n setDownloadProgress(prev =>\n prev\n ? {\n ...prev,\n bytesDownloaded: 0,\n totalBytes,\n }\n : null,\n )\n\n // Create file handle in selected directory\n const fileHandle = await directoryHandle.getFileHandle(fileName, {\n create: true,\n })\n const writableStream = await fileHandle.createWritable()\n\n // Stream the response body to the file with progress tracking\n if (response.body) {\n const reader = response.body.getReader()\n let bytesReceived = 0\n let streamAborted = false\n\n try {\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n\n bytesReceived += value.length\n await writableStream.write(value)\n\n // Check for cancellation on every chunk\n if (isCancelledRef.current) {\n streamAborted = true\n reader.cancel()\n await writableStream.abort()\n break\n }\n\n if (fileDownloadStartRef.current === null) {\n fileDownloadStartRef.current = Date.now()\n }\n const elapsedMs = Date.now() - fileDownloadStartRef.current\n let estimatedSecondsRemaining: number | null = null\n if (\n elapsedMs > ETA_DELAY_MS &&\n bytesReceived > 0 &&\n totalBytes > 0\n ) {\n const rate = bytesReceived / elapsedMs\n estimatedSecondsRemaining = Math.max(\n 0,\n (totalBytes - bytesReceived) / rate / 1000,\n )\n }\n\n // Update progress\n setDownloadProgress(prev =>\n prev\n ? {\n ...prev,\n bytesDownloaded: bytesReceived,\n ...(elapsedMs > ETA_DELAY_MS && {\n estimatedSecondsRemaining,\n }),\n }\n : null,\n )\n }\n } catch (streamError) {\n if (!streamAborted) {\n await writableStream.abort()\n streamAborted = true\n }\n throw streamError\n } finally {\n if (!streamAborted) {\n await writableStream.close()\n }\n }\n\n // If cancelled mid-stream, return false without falling through to success path\n if (isCancelledRef.current) {\n return false\n }\n } else {\n // Fallback if streaming not supported\n try {\n const blob = await response.blob()\n await writableStream.write(blob)\n } finally {\n await writableStream.close()\n }\n }\n\n downloadedCount = currentFileIndex\n\n // Track successfully downloaded item for batch removal\n if (originalItem) {\n successfullyDownloadedItems.push(originalItem)\n }\n return true\n } catch (fetchError) {\n // If the fetch was aborted due to cancellation, do not fall back\n if (\n isCancelledRef.current ||\n (fetchError instanceof DOMException &&\n fetchError.name === 'AbortError')\n ) {\n return false\n }\n console.error(\n `Failed to fetch/write file ${fileResult.fileHandleId}:`,\n fetchError,\n )\n // Fallback to window.open if File System Access API fails\n try {\n downloadFileTraditional(downloadUrl, fileName)\n downloadedCount = currentFileIndex\n if (originalItem) {\n successfullyDownloadedItems.push(originalItem)\n }\n return true\n } catch (fallbackError) {\n console.error(\n `Fallback downloadFileTraditional also failed for ${fileResult.fileHandleId}:`,\n fallbackError,\n )\n return false\n }\n }\n } catch (error) {\n console.error(\n `Failed to download file ${fileResult.fileHandleId}:`,\n error,\n )\n return false\n }\n }\n\n /**\n * Fallback function to fetch files individually when batch fails\n */\n const fetchIndividually = async (\n batch: FileHandleAssociation[],\n ): Promise<void> => {\n console.info(\n `Attempting to fetch ${batch.length} files individually after batch failure`,\n )\n\n for (const fileHandleAssociation of batch) {\n // Check if user cancelled the operation\n if (isCancelledRef.current) {\n console.info('Individual file fetch cancelled by user')\n break\n }\n\n const singleBatch = [fileHandleAssociation]\n try {\n const batchRequest: BatchFileRequest = {\n requestedFiles: singleBatch,\n includeFileHandles: true,\n includePreSignedURLs: true,\n includePreviewPreSignedURLs: false,\n }\n\n const batchResult = await getFiles(batchRequest, accessToken)\n\n if (batchResult.requestedFiles.length > 0) {\n const fileResult = batchResult.requestedFiles[0]\n const originalItem = nonPackageableFiles.find(\n item =>\n item.fileEntityId ===\n fileHandleAssociation.associateObjectId,\n )\n\n const success = await processFileDownload(\n fileResult,\n originalItem,\n )\n if (!success) {\n failedCount++\n }\n } else {\n failedCount++\n }\n } catch (error) {\n console.error(\n `Failed to fetch individual file ${fileHandleAssociation.fileHandleId}:`,\n error,\n )\n failedCount++\n }\n }\n }\n\n // Process each batch\n for (const batch of batches) {\n // Check if user cancelled the operation\n if (isCancelledRef.current) {\n console.info('Download cancelled by user')\n break\n }\n\n // Try to fetch the entire batch (getFiles has built-in retry logic)\n let batchResult: BatchFileResult | null = null\n try {\n const batchRequest: BatchFileRequest = {\n requestedFiles: batch,\n includeFileHandles: true,\n includePreSignedURLs: true,\n includePreviewPreSignedURLs: false,\n }\n batchResult = await getFiles(batchRequest, accessToken)\n } catch (error) {\n console.error('Failed to fetch batch:', error)\n }\n\n if (batchResult) {\n // Batch fetch succeeded, process all files\n for (let i = 0; i < batchResult.requestedFiles.length; i++) {\n // Check if user cancelled the operation\n if (isCancelledRef.current) {\n console.info(\n 'Download cancelled by user during batch processing',\n )\n break\n }\n\n const fileResult = batchResult.requestedFiles[i]\n const originalItem = nonPackageableFiles.find(\n item => item.fileEntityId === batch[i].associateObjectId,\n )\n\n const success = await processFileDownload(\n fileResult,\n originalItem,\n )\n if (!success) {\n failedCount++\n }\n }\n } else {\n // Batch fetch failed after retries, try fetching files individually\n await fetchIndividually(batch)\n }\n }\n\n // Remove all successfully downloaded files from the download list in one batch\n if (successfullyDownloadedItems.length > 0) {\n await removeFilesFromDownloadList({\n batchToRemove: successfullyDownloadedItems.map(\n (item: (typeof nonPackageableFiles)[0]) => ({\n fileEntityId: item.fileEntityId,\n versionNumber: item.versionNumber,\n }),\n ),\n })\n // Refetch statistics after removing files\n await refetchDownloadListStatistics()\n // Scroll to top of page to show updated statistics\n window.scrollTo({ top: 0, behavior: 'smooth' })\n }\n\n // Show completion message\n if (isCancelledRef.current) {\n displayToast(\n `Download cancelled. ${downloadedCount} file${\n downloadedCount !== 1 ? 's were' : ' was'\n } downloaded before cancellation.`,\n 'info',\n )\n } else if (downloadedCount > 0) {\n displayToast(\n `Download started for ${downloadedCount} file${\n downloadedCount !== 1 ? 's' : ''\n }${\n failedCount > 0\n ? `. ${failedCount} file${failedCount !== 1 ? 's' : ''} failed.`\n : '.'\n }`,\n failedCount > 0 ? 'warning' : 'success',\n )\n } else {\n displayToast('No files could be downloaded', 'warning')\n }\n } catch (error) {\n console.error('Error downloading files:', error)\n const message =\n (error as SynapseClientError | undefined)?.reason ??\n (error instanceof Error ? error.message : undefined) ??\n 'An error occurred while downloading files'\n displayToast(message, 'danger')\n } finally {\n setDownloadProgress(null)\n setIsDownloading(false)\n isDownloadingRef.current = false\n }\n },\n [\n accessToken,\n isAuthenticated,\n queryClient,\n getEntityQueryOptions,\n removeFilesFromDownloadList,\n refetchDownloadListStatistics,\n ],\n )\n\n const handleClick = useCallback(async () => {\n if (isDownloading) {\n return\n }\n setIsDownloading(true)\n\n // Fetch all remaining pages imperatively, then download\n try {\n let stillHasNextPage = hasNextPage\n let latestData = data\n while (stillHasNextPage && fetchNextPage) {\n const result = await fetchNextPage()\n stillHasNextPage = result.hasNextPage\n if (result.data) {\n latestData = result.data\n }\n }\n\n // All pages loaded, now download\n if (status === 'success' && latestData) {\n void downloadAllFiles(latestData)\n } else {\n // Failed to load data\n setIsDownloading(false)\n isDownloadingRef.current = false\n displayToast(\n 'Failed to load download list. Please try again.',\n 'danger',\n )\n }\n } catch (error) {\n console.error('Error downloading files:', error)\n setIsDownloading(false)\n isDownloadingRef.current = false\n const message =\n (error as SynapseClientError | undefined)?.reason ??\n (error instanceof Error ? error.message : undefined) ??\n 'An error occurred while preparing files for download'\n displayToast(message, 'danger')\n }\n }, [\n isDownloading,\n hasNextPage,\n fetchNextPage,\n status,\n data,\n downloadAllFiles,\n ])\n\n const handleCancel = useCallback(() => {\n isCancelledRef.current = true\n abortControllerRef.current?.abort()\n setDownloadProgress(null)\n setIsDownloading(false)\n isDownloadingRef.current = false\n }, [])\n\n if (error) {\n return null\n }\n\n return (\n <>\n {/* Visually-hidden live region — announces file start and progress milestones to screen readers */}\n <span\n role=\"status\"\n aria-live=\"polite\"\n aria-atomic=\"true\"\n className={styles.visuallyHidden}\n >\n {announceText}\n </span>\n {!!downloadProgress && showExternalFileWarning && (\n <Paper\n elevation={8}\n className={styles.externalWarningPanel}\n sx={{ zIndex: theme => theme.zIndex.modal }}\n role=\"region\"\n aria-label=\"External file warning\"\n >\n <CloudWarning className={styles.warningIcon} />\n <Box className={styles.warningTextContainer}>\n <Typography className={styles.warningTitleText}>\n Some of your files are hosted externally.\n </Typography>\n <Typography className={styles.progressFileNameText}>\n Downloads may be slower than expected\n </Typography>\n </Box>\n <IconButton\n onClick={() => setShowExternalFileWarning(false)}\n size=\"small\"\n className={styles.warningCloseButton}\n aria-label=\"Dismiss external file warning\"\n >\n <Close />\n </IconButton>\n </Paper>\n )}\n {!!downloadProgress && (\n <Paper\n elevation={8}\n className={styles.progressPanel}\n sx={{ zIndex: theme => theme.zIndex.modal }}\n role=\"region\"\n aria-label=\"Download progress\"\n >\n <Typography className={styles.progressTitleText}>\n Downloading file {downloadProgress.fileIndex} of{' '}\n {downloadProgress.totalFiles}\n </Typography>\n <Typography className={styles.progressFileNameText}>\n {downloadProgress.currentFile}\n </Typography>\n <Box className={styles.progressFooter}>\n <Box className={styles.progressBarContainer}>\n <Box className={styles.progressStats}>\n <Typography className={styles.progressStatsText}>\n {downloadProgress.totalBytes > 0\n ? `${Math.round(\n (downloadProgress.bytesDownloaded /\n downloadProgress.totalBytes) *\n 100,\n )}% ( ${calculateFriendlyFileSize(\n downloadProgress.bytesDownloaded,\n 0,\n )} / ${calculateFriendlyFileSize(\n downloadProgress.totalBytes,\n )} )`\n : ''}\n </Typography>\n <Typography className={styles.progressStatsText}>\n {downloadProgress.estimatedSecondsRemaining !== null\n ? `About ${dayjs\n .duration({\n seconds: downloadProgress.estimatedSecondsRemaining,\n })\n .humanize()} remaining`\n : ''}\n </Typography>\n </Box>\n <LinearProgress\n variant={\n downloadProgress.totalBytes > 0\n ? 'determinate'\n : 'indeterminate'\n }\n value={\n downloadProgress.totalBytes > 0\n ? (downloadProgress.bytesDownloaded /\n downloadProgress.totalBytes) *\n 100\n : undefined\n }\n aria-label=\"Download progress\"\n className={styles.progressBar}\n />\n </Box>\n <Box className={styles.cancelButtonContainer}>\n <Button\n variant=\"outlined\"\n onClick={handleCancel}\n className={styles.cancelButton}\n >\n Cancel\n </Button>\n </Box>\n </Box>\n </Paper>\n )}\n <Button\n variant={variant}\n onClick={() => {\n void handleClick()\n }}\n loading={isDownloading}\n startIcon={<Download />}\n >\n {buttonText}\n </Button>\n </>\n )\n}\n\nexport default DownloadIneligibleForPackagingFilesFromListButton\n"],"mappings":"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"}
|
package/dist/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.module.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import './DownloadIneligibleForPackagingFilesFromListButton.css';var e = {
|
|
2
|
+
visuallyHidden: "_visuallyHidden_58da9_1",
|
|
3
|
+
externalWarningPanel: "_externalWarningPanel_58da9_12",
|
|
4
|
+
warningIcon: "_warningIcon_58da9_29",
|
|
5
|
+
warningTextContainer: "_warningTextContainer_58da9_36",
|
|
6
|
+
warningTitleText: "_warningTitleText_58da9_40",
|
|
7
|
+
warningCloseButton: "_warningCloseButton_58da9_47",
|
|
8
|
+
progressPanel: "_progressPanel_58da9_56",
|
|
9
|
+
progressTitleText: "_progressTitleText_58da9_73",
|
|
10
|
+
progressFileNameText: "_progressFileNameText_58da9_79",
|
|
11
|
+
progressFooter: "_progressFooter_58da9_90",
|
|
12
|
+
progressBarContainer: "_progressBarContainer_58da9_98",
|
|
13
|
+
progressStats: "_progressStats_58da9_105",
|
|
14
|
+
progressStatsText: "_progressStatsText_58da9_110",
|
|
15
|
+
progressBar: "_progressBar_58da9_98",
|
|
16
|
+
cancelButtonContainer: "_cancelButtonContainer_58da9_119",
|
|
17
|
+
cancelButton: "_cancelButton_58da9_119"
|
|
18
|
+
};
|
|
19
|
+
//#endregion
|
|
20
|
+
export { e as default };
|
|
21
|
+
|
|
22
|
+
//# sourceMappingURL=DownloadIneligibleForPackagingFilesFromListButton.module.js.map
|
package/dist/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.module.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DownloadIneligibleForPackagingFilesFromListButton.module.js","names":[],"sources":["../../../src/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.module.scss"],"sourcesContent":["// Hides an element visually while keeping it accessible to screen readers.\n.visuallyHidden {\n border: 0;\n clip: rect(0 0 0 0);\n height: 1px;\n margin: -1px;\n overflow: hidden;\n padding: 0;\n position: absolute;\n width: 1px;\n}\n\n$progress-panel-bottom: 20px;\n$progress-panel-height: 150px;\n\n.externalWarningPanel {\n position: fixed;\n bottom: calc(\n #{$progress-panel-height} + 10px\n ); // positioned above the progress panel\n right: 20px;\n width: 500px;\n padding: 16px;\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: 12px;\n box-sizing: border-box;\n\n // Use &#{&} to increase specificity and override MUI Paper's default styles\n &#{&} {\n border-radius: 0;\n background-color: #223549;\n }\n}\n\n.warningIcon {\n flex-shrink: 0;\n\n // Use &#{&} to increase specificity and override MUI SvgIcon's default styles\n &#{&} {\n font-size: 40px;\n }\n}\n\n.warningTextContainer {\n flex: 1;\n}\n\n.warningTitleText {\n // Use &#{&} to increase specificity and override MUI Typography's default styles\n &#{&} {\n color: white;\n font-size: 14px;\n line-height: 1.4;\n font-weight: 700;\n }\n}\n\n.warningCloseButton {\n // Use &#{&} to increase specificity and override MUI IconButton's default styles\n &#{&} {\n color: white;\n align-self: flex-start;\n flex-shrink: 0;\n\n &:hover {\n color: #889baf;\n }\n }\n}\n\n.progressPanel {\n position: fixed;\n bottom: $progress-panel-bottom;\n right: 20px;\n width: 500px;\n height: $progress-panel-height;\n padding: 16px;\n display: flex;\n flex-direction: column;\n gap: 4px;\n box-sizing: border-box;\n\n // Use &#{&} to increase specificity and override MUI Paper's default styles\n &#{&} {\n border-radius: 0;\n background-color: #223549;\n }\n}\n\n.progressTitleText {\n // Use &#{&} to increase specificity and override MUI Typography's default styles\n &#{&} {\n color: white;\n font-size: 14px;\n line-height: 1.4;\n }\n}\n\n.progressFileNameText {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n\n // Use &#{&} to increase specificity and override MUI Typography's default styles\n &#{&} {\n color: #889baf;\n font-size: 13px;\n line-height: 1.4;\n }\n}\n\n.progressFooter {\n display: flex;\n flex: 1;\n gap: 8px;\n align-items: center;\n margin-top: auto;\n}\n\n.progressBarContainer {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.progressStats {\n display: flex;\n justify-content: space-between;\n}\n\n.progressStatsText {\n // Use &#{&} to increase specificity and override MUI Typography's default styles\n &#{&} {\n color: #889baf;\n font-size: 12px;\n }\n}\n\n.progressBar {\n :global(.MuiLinearProgress-bar) {\n background-color: #469285;\n }\n}\n\n.cancelButtonContainer {\n width: 80px;\n display: flex;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.cancelButton {\n // Use &#{&} to increase specificity and override MUI Button's default styles\n &#{&} {\n color: white;\n border-color: white;\n min-width: 0;\n padding: 10px 16px;\n font-size: 0.75rem;\n line-height: 1;\n\n &:hover {\n border-color: #889baf;\n color: #889baf;\n }\n }\n}\n"],"mappings":""}
|
package/dist/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.module.scss
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
// Hides an element visually while keeping it accessible to screen readers.
|
|
2
|
+
.visuallyHidden {
|
|
3
|
+
border: 0;
|
|
4
|
+
clip: rect(0 0 0 0);
|
|
5
|
+
height: 1px;
|
|
6
|
+
margin: -1px;
|
|
7
|
+
overflow: hidden;
|
|
8
|
+
padding: 0;
|
|
9
|
+
position: absolute;
|
|
10
|
+
width: 1px;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
$progress-panel-bottom: 20px;
|
|
14
|
+
$progress-panel-height: 150px;
|
|
15
|
+
|
|
16
|
+
.externalWarningPanel {
|
|
17
|
+
position: fixed;
|
|
18
|
+
bottom: calc(
|
|
19
|
+
#{$progress-panel-height} + 10px
|
|
20
|
+
); // positioned above the progress panel
|
|
21
|
+
right: 20px;
|
|
22
|
+
width: 500px;
|
|
23
|
+
padding: 16px;
|
|
24
|
+
display: flex;
|
|
25
|
+
flex-direction: row;
|
|
26
|
+
align-items: center;
|
|
27
|
+
gap: 12px;
|
|
28
|
+
box-sizing: border-box;
|
|
29
|
+
|
|
30
|
+
// Use &#{&} to increase specificity and override MUI Paper's default styles
|
|
31
|
+
&#{&} {
|
|
32
|
+
border-radius: 0;
|
|
33
|
+
background-color: #223549;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.warningIcon {
|
|
38
|
+
flex-shrink: 0;
|
|
39
|
+
|
|
40
|
+
// Use &#{&} to increase specificity and override MUI SvgIcon's default styles
|
|
41
|
+
&#{&} {
|
|
42
|
+
font-size: 40px;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.warningTextContainer {
|
|
47
|
+
flex: 1;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.warningTitleText {
|
|
51
|
+
// Use &#{&} to increase specificity and override MUI Typography's default styles
|
|
52
|
+
&#{&} {
|
|
53
|
+
color: white;
|
|
54
|
+
font-size: 14px;
|
|
55
|
+
line-height: 1.4;
|
|
56
|
+
font-weight: 700;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.warningCloseButton {
|
|
61
|
+
// Use &#{&} to increase specificity and override MUI IconButton's default styles
|
|
62
|
+
&#{&} {
|
|
63
|
+
color: white;
|
|
64
|
+
align-self: flex-start;
|
|
65
|
+
flex-shrink: 0;
|
|
66
|
+
|
|
67
|
+
&:hover {
|
|
68
|
+
color: #889baf;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.progressPanel {
|
|
74
|
+
position: fixed;
|
|
75
|
+
bottom: $progress-panel-bottom;
|
|
76
|
+
right: 20px;
|
|
77
|
+
width: 500px;
|
|
78
|
+
height: $progress-panel-height;
|
|
79
|
+
padding: 16px;
|
|
80
|
+
display: flex;
|
|
81
|
+
flex-direction: column;
|
|
82
|
+
gap: 4px;
|
|
83
|
+
box-sizing: border-box;
|
|
84
|
+
|
|
85
|
+
// Use &#{&} to increase specificity and override MUI Paper's default styles
|
|
86
|
+
&#{&} {
|
|
87
|
+
border-radius: 0;
|
|
88
|
+
background-color: #223549;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.progressTitleText {
|
|
93
|
+
// Use &#{&} to increase specificity and override MUI Typography's default styles
|
|
94
|
+
&#{&} {
|
|
95
|
+
color: white;
|
|
96
|
+
font-size: 14px;
|
|
97
|
+
line-height: 1.4;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.progressFileNameText {
|
|
102
|
+
overflow: hidden;
|
|
103
|
+
text-overflow: ellipsis;
|
|
104
|
+
white-space: nowrap;
|
|
105
|
+
|
|
106
|
+
// Use &#{&} to increase specificity and override MUI Typography's default styles
|
|
107
|
+
&#{&} {
|
|
108
|
+
color: #889baf;
|
|
109
|
+
font-size: 13px;
|
|
110
|
+
line-height: 1.4;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.progressFooter {
|
|
115
|
+
display: flex;
|
|
116
|
+
flex: 1;
|
|
117
|
+
gap: 8px;
|
|
118
|
+
align-items: center;
|
|
119
|
+
margin-top: auto;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.progressBarContainer {
|
|
123
|
+
flex: 1;
|
|
124
|
+
display: flex;
|
|
125
|
+
flex-direction: column;
|
|
126
|
+
gap: 4px;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.progressStats {
|
|
130
|
+
display: flex;
|
|
131
|
+
justify-content: space-between;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.progressStatsText {
|
|
135
|
+
// Use &#{&} to increase specificity and override MUI Typography's default styles
|
|
136
|
+
&#{&} {
|
|
137
|
+
color: #889baf;
|
|
138
|
+
font-size: 12px;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.progressBar {
|
|
143
|
+
:global(.MuiLinearProgress-bar) {
|
|
144
|
+
background-color: #469285;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.cancelButtonContainer {
|
|
149
|
+
width: 80px;
|
|
150
|
+
display: flex;
|
|
151
|
+
justify-content: center;
|
|
152
|
+
flex-shrink: 0;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.cancelButton {
|
|
156
|
+
// Use &#{&} to increase specificity and override MUI Button's default styles
|
|
157
|
+
&#{&} {
|
|
158
|
+
color: white;
|
|
159
|
+
border-color: white;
|
|
160
|
+
min-width: 0;
|
|
161
|
+
padding: 10px 16px;
|
|
162
|
+
font-size: 0.75rem;
|
|
163
|
+
line-height: 1;
|
|
164
|
+
|
|
165
|
+
&:hover {
|
|
166
|
+
border-color: #889baf;
|
|
167
|
+
color: #889baf;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DownloadListActionsRequired.js","names":[],"sources":["../../../src/components/DownloadCart/DownloadListActionsRequired.tsx"],"sourcesContent":["import { useGetAllDownloadListActionsRequired } from '@/synapse-queries'\nimport useTrackTransientListItems from '@/utils/hooks/useTrackTransientListItems'\nimport { Box } from '@mui/material'\nimport { times } from 'lodash-es'\nimport { LoadingActionRequiredCard } from './ActionRequiredCard/ActionRequiredCard'\nimport { ActionRequiredListItem } from './ActionRequiredListItem'\n\nexport type DownloadListActionsRequiredProps = {\n /** Invoked when a user clicks \"View Sharing Settings\" for a set of files that require the Download permission*/\n onViewSharingSettingsClicked?: (benefactorId: string) => void\n}\n\nexport function DownloadListActionsRequired(\n props: DownloadListActionsRequiredProps,\n) {\n const { onViewSharingSettingsClicked } = props\n\n // This component will track all completed actions, based on which actions are omitted from the ActionsRequiredResponse as the user performs required tasks\n // For accurate tracking, we must make sure we have all data. So we will fetch all pages instead of one page at a time.\n const { data: currentActionsRequired, isLoading } =\n useGetAllDownloadListActionsRequired({\n throwOnError: true,\n })\n\n // PORTALS-2950 - Keep a record of actions that disappear from the server response - i.e. the 'completed' actions\n const allCompleteAndIncompleteActions = useTrackTransientListItems(\n currentActionsRequired,\n )\n\n return (\n <>\n <Box\n sx={{\n display: 'flex',\n flexDirection: 'column',\n gap: 3,\n pt: 5,\n }}\n >\n {allCompleteAndIncompleteActions.map((item, index) => {\n if (item) {\n return (\n <ActionRequiredListItem\n key={index}\n action={item.action}\n count={item.count}\n onViewSharingSettingsClicked={onViewSharingSettingsClicked}\n />\n )\n } else return false\n })}\n {isLoading && times(3).map(k => <LoadingActionRequiredCard key={k} />)}\n </Box>\n </>\n )\n}\n"],"mappings":";;;;;;;;;AAYA,SAAgB,EACd,GACA;CACA,IAAM,EAAE,oCAAiC,GAInC,EAAE,MAAM,GAAwB,iBACpC,EAAqC,EACnC,cAAc,IACf,CAAC;AAOJ,QACE,kBAAA,GAAA,EAAA,UACE,kBAAC,GAAD;EACE,IAAI;GACF,SAAS;GACT,eAAe;GACf,KAAK;GACL,IAAI;GACL;YANH,CANoC,EACtC,
|
|
1
|
+
{"version":3,"file":"DownloadListActionsRequired.js","names":[],"sources":["../../../src/components/DownloadCart/DownloadListActionsRequired.tsx"],"sourcesContent":["import { useGetAllDownloadListActionsRequired } from '@/synapse-queries'\nimport useTrackTransientListItems from '@/utils/hooks/useTrackTransientListItems'\nimport { Box } from '@mui/material'\nimport { times } from 'lodash-es'\nimport { LoadingActionRequiredCard } from './ActionRequiredCard/ActionRequiredCard'\nimport { ActionRequiredListItem } from './ActionRequiredListItem'\n\nexport type DownloadListActionsRequiredProps = {\n /** Invoked when a user clicks \"View Sharing Settings\" for a set of files that require the Download permission*/\n onViewSharingSettingsClicked?: (benefactorId: string) => void\n}\n\nexport function DownloadListActionsRequired(\n props: DownloadListActionsRequiredProps,\n) {\n const { onViewSharingSettingsClicked } = props\n\n // This component will track all completed actions, based on which actions are omitted from the ActionsRequiredResponse as the user performs required tasks\n // For accurate tracking, we must make sure we have all data. So we will fetch all pages instead of one page at a time.\n const { data: currentActionsRequired, isLoading } =\n useGetAllDownloadListActionsRequired({\n throwOnError: true,\n })\n\n // PORTALS-2950 - Keep a record of actions that disappear from the server response - i.e. the 'completed' actions\n const allCompleteAndIncompleteActions = useTrackTransientListItems(\n currentActionsRequired,\n )\n\n return (\n <>\n <Box\n sx={{\n display: 'flex',\n flexDirection: 'column',\n gap: 3,\n pt: 5,\n }}\n >\n {allCompleteAndIncompleteActions.map((item, index) => {\n if (item) {\n return (\n <ActionRequiredListItem\n key={index}\n action={item.action}\n count={item.count}\n onViewSharingSettingsClicked={onViewSharingSettingsClicked}\n />\n )\n } else return false\n })}\n {isLoading && times(3).map(k => <LoadingActionRequiredCard key={k} />)}\n </Box>\n </>\n )\n}\n"],"mappings":";;;;;;;;;AAYA,SAAgB,EACd,GACA;CACA,IAAM,EAAE,oCAAiC,GAInC,EAAE,MAAM,GAAwB,iBACpC,EAAqC,EACnC,cAAc,IACf,CAAC;AAOJ,QACE,kBAAA,GAAA,EAAA,UACE,kBAAC,GAAD;EACE,IAAI;GACF,SAAS;GACT,eAAe;GACf,KAAK;GACL,IAAI;GACL;YANH,CANoC,EACtC,EAaK,CAAgC,KAAK,GAAM,MACtC,IAEA,kBAAC,GAAD;GAEE,QAAQ,EAAK;GACb,OAAO,EAAK;GACkB;GAC9B,EAJK,EAIL,GAEQ,GACd,EACD,KAAa,EAAM,EAAE,CAAC,KAAI,MAAK,kBAAC,GAAD,EAAqC,EAAL,EAAK,CAAC,CAClE;KACL,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DownloadListTable.js","names":[],"sources":["../../../src/components/DownloadCart/DownloadListTable.tsx"],"sourcesContent":["import {\n useGetAvailableFilesToDownloadInfinite,\n useRemoveFilesFromDownloadList,\n} from '@/synapse-queries'\nimport { calculateFriendlyFileSize } from '@/utils/functions/calculateFriendlyFileSize'\nimport { formatDate } from '@/utils/functions/DateFormatter'\nimport { PRODUCTION_ENDPOINT_CONFIG } from '@/utils/functions/getEndpoint'\nimport { Box, Button, Tooltip, Typography } from '@mui/material'\nimport {\n AvailableFilter,\n DownloadListItem,\n DownloadListItemResult,\n Sort,\n SortField,\n} from '@sage-bionetworks/synapse-types'\nimport {\n CellContext,\n createColumnHelper,\n getCoreRowModel,\n Row,\n SortingState,\n useReactTable,\n} from '@tanstack/react-table'\nimport dayjs from 'dayjs'\nimport { useCallback, useEffect, useMemo, useState } from 'react'\nimport { useErrorHandler } from 'react-error-boundary'\nimport FileEntityDirectDownload from '../DirectDownload/FileEntityDirectDownload'\nimport IconSvg from '../IconSvg/IconSvg'\nimport { InteractiveCopyIdsIcon } from '../InteractiveCopyIdsIcon'\nimport { BlockingLoader, SynapseSpinner } from '../LoadingScreen/LoadingScreen'\nimport { SkeletonTable } from '../Skeleton'\nimport { TOOLTIP_DELAY_SHOW } from '../SynapseTable/SynapseTableConstants'\nimport ColumnHeader from '../TanStackTable/ColumnHeader'\nimport StyledTanStackTable from '../TanStackTable/StyledTanStackTable'\nimport { displayToast } from '../ToastMessage'\nimport DirectProgrammaticDownload from './DirectProgrammaticDownload'\nimport { copyStringToClipboard } from '@/utils/functions/StringUtils'\n\nexport const TESTING_TRASH_BTN_CLASS = 'TESTING_TRASH_BTN_CLASS'\n\nfunction notifyRemovedFromDownloadList(\n notificationTitle: string,\n fileName: string,\n) {\n displayToast(`${fileName} has been removed from your list.`, 'success', {\n title: notificationTitle,\n })\n}\n\nfunction RemoveFromDownloadListButton(props: {\n ctx: CellContext<DownloadListItemResult, any>\n}) {\n const { ctx } = props\n const { mutateAsync: removeFileFromDownloadList, isPending } =\n useRemoveFilesFromDownloadList({\n onSuccess: () =>\n displayToast(\n `${ctx.row.original.fileName} has been removed from your list.`,\n 'success',\n {\n title: 'File Removed',\n },\n ),\n })\n\n return (\n <Tooltip\n title=\"Remove from Download List\"\n placement=\"left\"\n enterNextDelay={TOOLTIP_DELAY_SHOW}\n >\n <span className=\"removeItem\">\n <button\n className={TESTING_TRASH_BTN_CLASS}\n onClick={() => {\n void removeFileFromDownloadList({\n batchToRemove: [\n {\n fileEntityId: ctx.row.original.fileEntityId,\n versionNumber: ctx.row.original.versionNumber,\n },\n ],\n })\n }}\n >\n {isPending ? <SynapseSpinner /> : <IconSvg icon=\"removeCircle\" />}\n </button>\n </span>\n </Tooltip>\n )\n}\n\nconst columnHelper = createColumnHelper<DownloadListItemResult>()\nconst getColumns = (args: {\n removeItem: (item: DownloadListItem, fileName: string, title: string) => void\n onCopySynIds: () => void\n}) => {\n const { onCopySynIds, removeItem } = args\n return [\n columnHelper.accessor('isEligibleForPackaging', {\n header: () => <></>,\n cell: ctx => (\n <div>\n {!ctx.getValue() && (\n <Tooltip\n title={\n <>\n This file can’t be packaged as a ZIP because it is {'>'}\n 100MB, or it is an external link, or it is not stored on\n Synapse native storage.\n <br />\n Try clicking the “download” icon at the end of the row, or\n download programmatically.\n </>\n }\n enterNextDelay={TOOLTIP_DELAY_SHOW}\n placement=\"right\"\n >\n <span className=\"ineligibileIcon\">\n <IconSvg wrap={false} icon=\"unpackagableFile\" />\n </span>\n </Tooltip>\n )}\n </div>\n ),\n enableResizing: false,\n enableColumnFilter: false,\n size: 50,\n }),\n columnHelper.accessor('fileName', {\n header: props => <ColumnHeader {...props} title={'Name'} />,\n cell: ctx => (\n <a\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n href={`${PRODUCTION_ENDPOINT_CONFIG.PORTAL}Synapse:${ctx.row.original.fileEntityId}.${ctx.row.original.versionNumber}`}\n >\n {ctx.getValue()}\n </a>\n ),\n enableColumnFilter: false,\n size: 360,\n }),\n columnHelper.accessor('fileSizeBytes', {\n header: props => <ColumnHeader {...props} title={'Size'} />,\n cell: ctx =>\n ctx.getValue() != null && ctx.getValue() > 0 ? (\n calculateFriendlyFileSize(ctx.getValue())\n ) : (\n <Typography variant=\"smallText1\" sx={{ color: 'grey.600' }}>\n Unknown\n </Typography>\n ),\n enableColumnFilter: false,\n size: 117,\n }),\n columnHelper.accessor('fileEntityId', {\n header: props => (\n <ColumnHeader\n {...props}\n title={'SynID'}\n additionalButtons={\n <InteractiveCopyIdsIcon size={'small'} onCopy={onCopySynIds} />\n }\n />\n ),\n cell: ctx => `${ctx.getValue()}.${ctx.row.original.versionNumber}`,\n enableColumnFilter: false,\n size: 143,\n }),\n columnHelper.accessor('addedOn', {\n header: props => <ColumnHeader {...props} title={'Added On'} />,\n cell: ctx => formatDate(dayjs(ctx.getValue())),\n enableColumnFilter: false,\n size: 150,\n }),\n columnHelper.accessor('projectName', {\n header: props => <ColumnHeader {...props} title={'Project'} />,\n enableColumnFilter: false,\n size: 170,\n }),\n columnHelper.display({\n id: 'actions',\n header: props => <ColumnHeader {...props} title={'Actions'} />,\n cell: ctx => (\n <div className=\"actionsContainer\">\n <span className=\"downloadItem\">\n <FileEntityDirectDownload\n entityId={ctx.row.original.fileEntityId}\n entityVersionNumber={ctx.row.original.versionNumber}\n displayFileName={false}\n onClickCallback={(isExternalLink: boolean) => {\n // SWC-5944: remove the item from the download list, unless it's an external link.\n if (!isExternalLink) {\n removeItem(\n {\n fileEntityId: ctx.row.original.fileEntityId,\n versionNumber: ctx.row.original.versionNumber,\n },\n ctx.row.original.fileName,\n 'File Downloaded',\n )\n }\n }}\n />\n </span>\n <span className=\"programmaticAccessItem\">\n <DirectProgrammaticDownload\n entityId={ctx.row.original.fileEntityId}\n version={ctx.row.original.versionNumber}\n />\n </span>\n <RemoveFromDownloadListButton ctx={ctx} />\n </div>\n ),\n enableResizing: false,\n enableColumnFilter: false,\n size: 140,\n meta: {\n textAlign: 'center',\n },\n }),\n ]\n}\n\nfunction getSortApiRequestFromTableSortState(\n sortingState: SortingState,\n): Sort | undefined {\n if (sortingState.length === 0) {\n return undefined\n }\n const sort = sortingState[0]\n let field: SortField = 'addedOn'\n\n if (sort.id === 'fileName') {\n field = 'fileName'\n } else if (sort.id === 'fileSizeBytes') {\n field = 'fileSize'\n } else if (sort.id === 'fileEntityId') {\n field = 'synId'\n } else if (sort.id === 'projectName') {\n field = 'projectName'\n } else if (sort.id === 'addedOn') {\n field = 'addedOn'\n } else if (sort.id === 'createdBy') {\n field = 'createdBy'\n } else if (sort.id === 'createdOn') {\n field = 'createdOn'\n }\n\n return {\n field,\n direction: sort.desc ? 'DESC' : 'ASC',\n }\n}\n\nexport default function DownloadListTable({\n filter,\n}: {\n filter?: AvailableFilter\n}) {\n const handleError = useErrorHandler()\n\n const [copyingAllSynapseIDs, setCopyingAllSynapseIDs] =\n useState<boolean>(false)\n const [tableSortState, setTableSortState] = useState<SortingState>([\n {\n desc: true,\n id: 'addedOn',\n },\n ])\n\n const {\n data,\n status,\n isFetchingNextPage,\n isLoading,\n hasNextPage,\n fetchNextPage,\n isError,\n error: newError,\n } = useGetAvailableFilesToDownloadInfinite(\n getSortApiRequestFromTableSortState(tableSortState),\n filter,\n )\n\n useEffect(() => {\n if (isError && newError) {\n handleError(newError)\n }\n }, [isError, newError, handleError])\n\n const { mutateAsync: removeFileFromDownloadList } =\n useRemoveFilesFromDownloadList()\n\n const removeItem = useCallback(\n async (\n item: DownloadListItem,\n fileName: string,\n notificationTitle: string,\n ) => {\n await removeFileFromDownloadList({ batchToRemove: [item] })\n notifyRemovedFromDownloadList(notificationTitle, fileName)\n },\n [removeFileFromDownloadList],\n )\n\n const allRows = useMemo(\n () => data?.pages.flatMap(page => page.page) ?? [],\n [data?.pages],\n )\n\n const columns = useMemo(\n () =>\n getColumns({\n removeItem: (...args) => {\n void removeItem(...args)\n },\n onCopySynIds: () => {\n // trigger loading all pages of the download list table, and then copy all IDs to the clipboard\n setCopyingAllSynapseIDs(true)\n },\n }),\n [removeItem],\n )\n\n const table = useReactTable<DownloadListItemResult>({\n data: allRows,\n columns: columns,\n getCoreRowModel: getCoreRowModel(),\n manualSorting: true,\n onSortingChange: setTableSortState,\n state: {\n columnPinning: {\n right: ['actions'],\n },\n sorting: tableSortState,\n },\n columnResizeMode: 'onChange',\n meta: {\n getRowClassNames(row: Row<DownloadListItemResult>) {\n if (!row.original.isEligibleForPackaging) {\n return 'ineligibleForPackaging'\n }\n return ''\n },\n },\n })\n\n useEffect(() => {\n const copyAllSynapseIDs = () => {\n const synIDs = allRows\n .map((item: DownloadListItemResult) => {\n return `${item.fileEntityId}.${item.versionNumber}`\n })\n .join('\\n')\n copyStringToClipboard(synIDs).then(() => {\n displayToast('Successfully copied to clipboard')\n })\n setCopyingAllSynapseIDs(false)\n }\n\n if (\n status === 'success' &&\n !isFetchingNextPage &&\n hasNextPage &&\n fetchNextPage &&\n copyingAllSynapseIDs\n ) {\n void fetchNextPage()\n } else if (!hasNextPage && copyingAllSynapseIDs) {\n // We have all the data in allRows. Put it together and copy to the clipboard\n copyAllSynapseIDs()\n }\n }, [\n status,\n isFetchingNextPage,\n hasNextPage,\n fetchNextPage,\n copyingAllSynapseIDs,\n allRows,\n ])\n\n return (\n <div>\n <BlockingLoader show={copyingAllSynapseIDs} />\n {allRows.length > 0 && (\n <div className=\"DownloadListTableV2\">\n {/* TODO: This table can be very large, so it should be refactored to use row virtualization or discrete pagination */}\n <StyledTanStackTable table={table} fullWidth={false} />\n {hasNextPage && (\n <Box sx={{ display: 'flex', justifyContent: 'right' }}>\n <Button\n variant={'contained'}\n sx={{ my: 2, ml: 'auto' }}\n onClick={() => {\n void fetchNextPage()\n }}\n disabled={isFetchingNextPage}\n startIcon={isFetchingNextPage ? <SynapseSpinner /> : undefined}\n >\n {isFetchingNextPage ? 'Loading...' : 'Show More'}\n </Button>\n </Box>\n )}\n </div>\n )}\n {allRows.length === 0 && !isLoading && (\n <Typography variant=\"body1Italic\">\n You have no matching files in your download list.\n </Typography>\n )}\n {isLoading && <SkeletonTable numCols={5} numRows={3} />}\n </div>\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DownloadListTable.js","names":[],"sources":["../../../src/components/DownloadCart/DownloadListTable.tsx"],"sourcesContent":["import {\n useGetAvailableFilesToDownloadInfinite,\n useRemoveFilesFromDownloadList,\n} from '@/synapse-queries'\nimport { calculateFriendlyFileSize } from '@/utils/functions/calculateFriendlyFileSize'\nimport { formatDate } from '@/utils/functions/DateFormatter'\nimport { PRODUCTION_ENDPOINT_CONFIG } from '@/utils/functions/getEndpoint'\nimport { Box, Button, Tooltip, Typography } from '@mui/material'\nimport {\n AvailableFilter,\n DownloadListItem,\n DownloadListItemResult,\n Sort,\n SortField,\n} from '@sage-bionetworks/synapse-types'\nimport {\n CellContext,\n createColumnHelper,\n getCoreRowModel,\n Row,\n SortingState,\n useReactTable,\n} from '@tanstack/react-table'\nimport dayjs from 'dayjs'\nimport { useCallback, useEffect, useMemo, useState } from 'react'\nimport { useErrorHandler } from 'react-error-boundary'\nimport FileEntityDirectDownload from '../DirectDownload/FileEntityDirectDownload'\nimport IconSvg from '../IconSvg/IconSvg'\nimport { InteractiveCopyIdsIcon } from '../InteractiveCopyIdsIcon'\nimport { BlockingLoader, SynapseSpinner } from '../LoadingScreen/LoadingScreen'\nimport { SkeletonTable } from '../Skeleton'\nimport { TOOLTIP_DELAY_SHOW } from '../SynapseTable/SynapseTableConstants'\nimport ColumnHeader from '../TanStackTable/ColumnHeader'\nimport StyledTanStackTable from '../TanStackTable/StyledTanStackTable'\nimport { displayToast } from '../ToastMessage'\nimport DirectProgrammaticDownload from './DirectProgrammaticDownload'\nimport { copyStringToClipboard } from '@/utils/functions/StringUtils'\n\nexport const TESTING_TRASH_BTN_CLASS = 'TESTING_TRASH_BTN_CLASS'\n\nfunction notifyRemovedFromDownloadList(\n notificationTitle: string,\n fileName: string,\n) {\n displayToast(`${fileName} has been removed from your list.`, 'success', {\n title: notificationTitle,\n })\n}\n\nfunction RemoveFromDownloadListButton(props: {\n ctx: CellContext<DownloadListItemResult, any>\n}) {\n const { ctx } = props\n const { mutateAsync: removeFileFromDownloadList, isPending } =\n useRemoveFilesFromDownloadList({\n onSuccess: () =>\n displayToast(\n `${ctx.row.original.fileName} has been removed from your list.`,\n 'success',\n {\n title: 'File Removed',\n },\n ),\n })\n\n return (\n <Tooltip\n title=\"Remove from Download List\"\n placement=\"left\"\n enterNextDelay={TOOLTIP_DELAY_SHOW}\n >\n <span className=\"removeItem\">\n <button\n className={TESTING_TRASH_BTN_CLASS}\n onClick={() => {\n void removeFileFromDownloadList({\n batchToRemove: [\n {\n fileEntityId: ctx.row.original.fileEntityId,\n versionNumber: ctx.row.original.versionNumber,\n },\n ],\n })\n }}\n >\n {isPending ? <SynapseSpinner /> : <IconSvg icon=\"removeCircle\" />}\n </button>\n </span>\n </Tooltip>\n )\n}\n\nconst columnHelper = createColumnHelper<DownloadListItemResult>()\nconst getColumns = (args: {\n removeItem: (item: DownloadListItem, fileName: string, title: string) => void\n onCopySynIds: () => void\n}) => {\n const { onCopySynIds, removeItem } = args\n return [\n columnHelper.accessor('isEligibleForPackaging', {\n header: () => <></>,\n cell: ctx => (\n <div>\n {!ctx.getValue() && (\n <Tooltip\n title={\n <>\n This file can’t be packaged as a ZIP because it is {'>'}\n 100MB, or it is an external link, or it is not stored on\n Synapse native storage.\n <br />\n Try clicking the “download” icon at the end of the row, or\n download programmatically.\n </>\n }\n enterNextDelay={TOOLTIP_DELAY_SHOW}\n placement=\"right\"\n >\n <span className=\"ineligibileIcon\">\n <IconSvg wrap={false} icon=\"unpackagableFile\" />\n </span>\n </Tooltip>\n )}\n </div>\n ),\n enableResizing: false,\n enableColumnFilter: false,\n size: 50,\n }),\n columnHelper.accessor('fileName', {\n header: props => <ColumnHeader {...props} title={'Name'} />,\n cell: ctx => (\n <a\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n href={`${PRODUCTION_ENDPOINT_CONFIG.PORTAL}Synapse:${ctx.row.original.fileEntityId}.${ctx.row.original.versionNumber}`}\n >\n {ctx.getValue()}\n </a>\n ),\n enableColumnFilter: false,\n size: 360,\n }),\n columnHelper.accessor('fileSizeBytes', {\n header: props => <ColumnHeader {...props} title={'Size'} />,\n cell: ctx =>\n ctx.getValue() != null && ctx.getValue() > 0 ? (\n calculateFriendlyFileSize(ctx.getValue())\n ) : (\n <Typography variant=\"smallText1\" sx={{ color: 'grey.600' }}>\n Unknown\n </Typography>\n ),\n enableColumnFilter: false,\n size: 117,\n }),\n columnHelper.accessor('fileEntityId', {\n header: props => (\n <ColumnHeader\n {...props}\n title={'SynID'}\n additionalButtons={\n <InteractiveCopyIdsIcon size={'small'} onCopy={onCopySynIds} />\n }\n />\n ),\n cell: ctx => `${ctx.getValue()}.${ctx.row.original.versionNumber}`,\n enableColumnFilter: false,\n size: 143,\n }),\n columnHelper.accessor('addedOn', {\n header: props => <ColumnHeader {...props} title={'Added On'} />,\n cell: ctx => formatDate(dayjs(ctx.getValue())),\n enableColumnFilter: false,\n size: 150,\n }),\n columnHelper.accessor('projectName', {\n header: props => <ColumnHeader {...props} title={'Project'} />,\n enableColumnFilter: false,\n size: 170,\n }),\n columnHelper.display({\n id: 'actions',\n header: props => <ColumnHeader {...props} title={'Actions'} />,\n cell: ctx => (\n <div className=\"actionsContainer\">\n <span className=\"downloadItem\">\n <FileEntityDirectDownload\n entityId={ctx.row.original.fileEntityId}\n entityVersionNumber={ctx.row.original.versionNumber}\n displayFileName={false}\n onClickCallback={(isExternalLink: boolean) => {\n // SWC-5944: remove the item from the download list, unless it's an external link.\n if (!isExternalLink) {\n removeItem(\n {\n fileEntityId: ctx.row.original.fileEntityId,\n versionNumber: ctx.row.original.versionNumber,\n },\n ctx.row.original.fileName,\n 'File Downloaded',\n )\n }\n }}\n />\n </span>\n <span className=\"programmaticAccessItem\">\n <DirectProgrammaticDownload\n entityId={ctx.row.original.fileEntityId}\n version={ctx.row.original.versionNumber}\n />\n </span>\n <RemoveFromDownloadListButton ctx={ctx} />\n </div>\n ),\n enableResizing: false,\n enableColumnFilter: false,\n size: 140,\n meta: {\n textAlign: 'center',\n },\n }),\n ]\n}\n\nfunction getSortApiRequestFromTableSortState(\n sortingState: SortingState,\n): Sort | undefined {\n if (sortingState.length === 0) {\n return undefined\n }\n const sort = sortingState[0]\n let field: SortField = 'addedOn'\n\n if (sort.id === 'fileName') {\n field = 'fileName'\n } else if (sort.id === 'fileSizeBytes') {\n field = 'fileSize'\n } else if (sort.id === 'fileEntityId') {\n field = 'synId'\n } else if (sort.id === 'projectName') {\n field = 'projectName'\n } else if (sort.id === 'addedOn') {\n field = 'addedOn'\n } else if (sort.id === 'createdBy') {\n field = 'createdBy'\n } else if (sort.id === 'createdOn') {\n field = 'createdOn'\n }\n\n return {\n field,\n direction: sort.desc ? 'DESC' : 'ASC',\n }\n}\n\nexport default function DownloadListTable({\n filter,\n}: {\n filter?: AvailableFilter\n}) {\n const handleError = useErrorHandler()\n\n const [copyingAllSynapseIDs, setCopyingAllSynapseIDs] =\n useState<boolean>(false)\n const [tableSortState, setTableSortState] = useState<SortingState>([\n {\n desc: true,\n id: 'addedOn',\n },\n ])\n\n const {\n data,\n status,\n isFetchingNextPage,\n isLoading,\n hasNextPage,\n fetchNextPage,\n isError,\n error: newError,\n } = useGetAvailableFilesToDownloadInfinite(\n getSortApiRequestFromTableSortState(tableSortState),\n filter,\n )\n\n useEffect(() => {\n if (isError && newError) {\n handleError(newError)\n }\n }, [isError, newError, handleError])\n\n const { mutateAsync: removeFileFromDownloadList } =\n useRemoveFilesFromDownloadList()\n\n const removeItem = useCallback(\n async (\n item: DownloadListItem,\n fileName: string,\n notificationTitle: string,\n ) => {\n await removeFileFromDownloadList({ batchToRemove: [item] })\n notifyRemovedFromDownloadList(notificationTitle, fileName)\n },\n [removeFileFromDownloadList],\n )\n\n const allRows = useMemo(\n () => data?.pages.flatMap(page => page.page) ?? [],\n [data?.pages],\n )\n\n const columns = useMemo(\n () =>\n getColumns({\n removeItem: (...args) => {\n void removeItem(...args)\n },\n onCopySynIds: () => {\n // trigger loading all pages of the download list table, and then copy all IDs to the clipboard\n setCopyingAllSynapseIDs(true)\n },\n }),\n [removeItem],\n )\n\n const table = useReactTable<DownloadListItemResult>({\n data: allRows,\n columns: columns,\n getCoreRowModel: getCoreRowModel(),\n manualSorting: true,\n onSortingChange: setTableSortState,\n state: {\n columnPinning: {\n right: ['actions'],\n },\n sorting: tableSortState,\n },\n columnResizeMode: 'onChange',\n meta: {\n getRowClassNames(row: Row<DownloadListItemResult>) {\n if (!row.original.isEligibleForPackaging) {\n return 'ineligibleForPackaging'\n }\n return ''\n },\n },\n })\n\n useEffect(() => {\n const copyAllSynapseIDs = () => {\n const synIDs = allRows\n .map((item: DownloadListItemResult) => {\n return `${item.fileEntityId}.${item.versionNumber}`\n })\n .join('\\n')\n copyStringToClipboard(synIDs).then(() => {\n displayToast('Successfully copied to clipboard')\n })\n setCopyingAllSynapseIDs(false)\n }\n\n if (\n status === 'success' &&\n !isFetchingNextPage &&\n hasNextPage &&\n fetchNextPage &&\n copyingAllSynapseIDs\n ) {\n void fetchNextPage()\n } else if (!hasNextPage && copyingAllSynapseIDs) {\n // We have all the data in allRows. Put it together and copy to the clipboard\n copyAllSynapseIDs()\n }\n }, [\n status,\n isFetchingNextPage,\n hasNextPage,\n fetchNextPage,\n copyingAllSynapseIDs,\n allRows,\n ])\n\n return (\n <div>\n <BlockingLoader show={copyingAllSynapseIDs} />\n {allRows.length > 0 && (\n <div className=\"DownloadListTableV2\">\n {/* TODO: This table can be very large, so it should be refactored to use row virtualization or discrete pagination */}\n <StyledTanStackTable table={table} fullWidth={false} />\n {hasNextPage && (\n <Box sx={{ display: 'flex', justifyContent: 'right' }}>\n <Button\n variant={'contained'}\n sx={{ my: 2, ml: 'auto' }}\n onClick={() => {\n void fetchNextPage()\n }}\n disabled={isFetchingNextPage}\n startIcon={isFetchingNextPage ? <SynapseSpinner /> : undefined}\n >\n {isFetchingNextPage ? 'Loading...' : 'Show More'}\n </Button>\n </Box>\n )}\n </div>\n )}\n {allRows.length === 0 && !isLoading && (\n <Typography variant=\"body1Italic\">\n You have no matching files in your download list.\n </Typography>\n )}\n {isLoading && <SkeletonTable numCols={5} numRows={3} />}\n </div>\n )\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fileNameUtils.js","names":[],"sources":["../../../src/components/DownloadCart/fileNameUtils.ts"],"sourcesContent":["import {\n FileResult,\n DownloadListItemResult,\n} from '@sage-bionetworks/synapse-types'\n\n/**\n * Gets a filename from a file result, falling back to the original item's filename\n * or a default generated name if neither is available.\n *\n * @param fileResult - The file result containing file handle information\n * @param originalItem - The original download list item result\n * @param fallbackFileHandleId - The file handle ID to use for the default name\n * @returns The resolved filename\n */\nexport function getFileName(\n fileResult: FileResult,\n originalItem?: DownloadListItemResult,\n): string {\n return (\n fileResult.fileHandle?.fileName ||\n originalItem?.fileName ||\n `file-${fileResult.fileHandleId}`\n )\n}\n\n/**\n * Handles filename collisions by appending a counter suffix to the filename.\n * If the filename has already been used, adds \" (N)\" before the extension.\n *\n * @param fileName - The original filename\n * @param usedFilenames - Map tracking filename usage counts\n * @returns The deduplicated filename\n */\nexport function deduplicateFileName(\n fileName: string,\n usedFilenames: Map<string, number>,\n): string {\n if (usedFilenames.has(fileName)) {\n const count = usedFilenames.get(fileName)! + 1\n usedFilenames.set(fileName, count)\n\n // Split filename into base and extension\n const lastDotIndex = fileName.lastIndexOf('.')\n if (lastDotIndex > 0) {\n const baseName = fileName.substring(0, lastDotIndex)\n const extension = fileName.substring(lastDotIndex)\n return `${baseName} (${count})${extension}`\n } else {\n return `${fileName} (${count})`\n }\n } else {\n usedFilenames.set(fileName, 0)\n return fileName\n }\n}\n"],"mappings":";AAcA,SAAgB,EACd,GACA,GACQ;AACR,QACE,EAAW,YAAY,YACvB,GAAc,YACd,QAAQ,EAAW;;AAYvB,SAAgB,EACd,GACA,GACQ;AACR,KAAI,EAAc,IAAI,EAAS,EAAE;EAC/B,IAAM,IAAQ,EAAc,IAAI,EAAS,GAAI;AAC7C,IAAc,IAAI,GAAU,EAAM;EAGlC,IAAM,IAAe,EAAS,YAAY,IAAI;AAM5C,SALE,IAAe,IAGV,GAFU,EAAS,UAAU,GAAG,
|
|
1
|
+
{"version":3,"file":"fileNameUtils.js","names":[],"sources":["../../../src/components/DownloadCart/fileNameUtils.ts"],"sourcesContent":["import {\n FileResult,\n DownloadListItemResult,\n} from '@sage-bionetworks/synapse-types'\n\n/**\n * Gets a filename from a file result, falling back to the original item's filename\n * or a default generated name if neither is available.\n *\n * @param fileResult - The file result containing file handle information\n * @param originalItem - The original download list item result\n * @param fallbackFileHandleId - The file handle ID to use for the default name\n * @returns The resolved filename\n */\nexport function getFileName(\n fileResult: FileResult,\n originalItem?: DownloadListItemResult,\n): string {\n return (\n fileResult.fileHandle?.fileName ||\n originalItem?.fileName ||\n `file-${fileResult.fileHandleId}`\n )\n}\n\n/**\n * Handles filename collisions by appending a counter suffix to the filename.\n * If the filename has already been used, adds \" (N)\" before the extension.\n *\n * @param fileName - The original filename\n * @param usedFilenames - Map tracking filename usage counts\n * @returns The deduplicated filename\n */\nexport function deduplicateFileName(\n fileName: string,\n usedFilenames: Map<string, number>,\n): string {\n if (usedFilenames.has(fileName)) {\n const count = usedFilenames.get(fileName)! + 1\n usedFilenames.set(fileName, count)\n\n // Split filename into base and extension\n const lastDotIndex = fileName.lastIndexOf('.')\n if (lastDotIndex > 0) {\n const baseName = fileName.substring(0, lastDotIndex)\n const extension = fileName.substring(lastDotIndex)\n return `${baseName} (${count})${extension}`\n } else {\n return `${fileName} (${count})`\n }\n } else {\n usedFilenames.set(fileName, 0)\n return fileName\n }\n}\n"],"mappings":";AAcA,SAAgB,EACd,GACA,GACQ;AACR,QACE,EAAW,YAAY,YACvB,GAAc,YACd,QAAQ,EAAW;;AAYvB,SAAgB,EACd,GACA,GACQ;AACR,KAAI,EAAc,IAAI,EAAS,EAAE;EAC/B,IAAM,IAAQ,EAAc,IAAI,EAAS,GAAI;AAC7C,IAAc,IAAI,GAAU,EAAM;EAGlC,IAAM,IAAe,EAAS,YAAY,IAAI;AAM5C,SALE,IAAe,IAGV,GAFU,EAAS,UAAU,GAAG,EAE7B,CAAS,IAAI,EAAM,GADX,EAAS,UAAU,EACL,KAEzB,GAAG,EAAS,IAAI,EAAM;OAI/B,QADA,EAAc,IAAI,GAAU,EAAE,EACvB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DraggableDialog.js","names":[],"sources":["../../../src/components/DraggableDialog/DraggableDialog.tsx"],"sourcesContent":["import Draggable, { DraggableBounds } from 'react-draggable'\nimport {\n Box,\n IconButton,\n Paper,\n Stack,\n Typography,\n Divider,\n useMediaQuery,\n useTheme,\n DialogContent,\n} from '@mui/material'\nimport CloseIcon from '@mui/icons-material/Close'\nimport { useRef, ReactNode, useEffect, useState } from 'react'\nimport { useResizable } from '../ResizableContainer/hooks/useResizable'\nimport { ResizableContainer } from '../ResizableContainer/ResizableContainer'\n\ntype DraggableDialogProps = {\n open?: boolean\n onClose?: () => void\n children: ReactNode\n title?: ReactNode\n}\n\nexport default function DraggableDialog({\n open = false,\n onClose,\n title,\n children,\n}: DraggableDialogProps) {\n const theme = useTheme()\n const isMobile = useMediaQuery(theme.breakpoints.down('sm'))\n const draggableRef = useRef<HTMLDivElement>(null)\n const [bounds, setBounds] = useState<DraggableBounds>()\n const [position, setPosition] = useState({ x: 100, y: 100 })\n const { width, height, handleResizeStart } = useResizable({\n initialWidth: 600,\n initialHeight: 500,\n minWidth: 300,\n minHeight: 200,\n maxWidth: 1200,\n maxHeight: 800,\n })\n\n useEffect(() => {\n // Calculate draggable bounds to keep dialog within viewport with margin\n function updateBounds() {\n const margin = 100\n const dialogWidth = width\n\n const newBounds = {\n left: -(dialogWidth - margin),\n top: 0,\n right: window.innerWidth - margin,\n bottom: window.innerHeight - margin,\n }\n\n setBounds(newBounds)\n\n // Clamp dialog position to new bounds to keep it visible after window resize\n setPosition(prevPosition => ({\n x: Math.max(newBounds.left, Math.min(prevPosition.x, newBounds.right)),\n y: Math.max(newBounds.top, Math.min(prevPosition.y, newBounds.bottom)),\n }))\n }\n updateBounds()\n window.addEventListener('resize', updateBounds)\n return () => window.removeEventListener('resize', updateBounds)\n }, [width, height])\n\n if (!open) {\n return null\n }\n\n const paperContent = (\n <Paper\n elevation={5}\n sx={{\n display: 'flex',\n flexDirection: 'column',\n height: isMobile ? '95vh' : `${height}px`,\n width: isMobile ? '95vw' : `${width}px`,\n ...(isMobile && {\n position: 'fixed',\n }),\n }}\n >\n <Stack\n direction=\"row\"\n alignItems=\"center\"\n gap=\"5px\"\n className=\"drag-handle\"\n sx={{\n padding: '20px',\n cursor: 'move',\n }}\n >\n <Typography variant=\"headline1\">{title}</Typography>\n <Box sx={{ flexGrow: 1 }} />\n <IconButton onClick={onClose}>\n <CloseIcon />\n </IconButton>\n </Stack>\n <Divider sx={{ mx: 2 }} />\n <DialogContent\n sx={{\n height: '100%',\n maxWidth: '100%',\n padding: '16px',\n }}\n >\n {children}\n </DialogContent>\n </Paper>\n )\n\n return (\n <Box\n sx={{\n position: 'fixed',\n zIndex: 1000,\n top: 0,\n left: 0,\n pointerEvents: isMobile ? 'auto' : 'none',\n }}\n >\n {isMobile ? (\n paperContent\n ) : (\n <Draggable\n position={position}\n onDrag={(e, data) => setPosition({ x: data.x, y: data.y })}\n nodeRef={draggableRef}\n bounds={bounds}\n handle=\".drag-handle\"\n >\n <Box ref={draggableRef} sx={{ pointerEvents: 'auto' }}>\n <ResizableContainer\n width={width}\n height={height}\n onResizeStart={handleResizeStart}\n >\n {paperContent}\n </ResizableContainer>\n </Box>\n </Draggable>\n )}\n </Box>\n )\n}\n"],"mappings":";;;;;;;;AAwBA,SAAwB,EAAgB,EACtC,UAAO,IACP,YACA,UACA,eACuB;CAEvB,IAAM,IAAW,EADH,
|
|
1
|
+
{"version":3,"file":"DraggableDialog.js","names":[],"sources":["../../../src/components/DraggableDialog/DraggableDialog.tsx"],"sourcesContent":["import Draggable, { DraggableBounds } from 'react-draggable'\nimport {\n Box,\n IconButton,\n Paper,\n Stack,\n Typography,\n Divider,\n useMediaQuery,\n useTheme,\n DialogContent,\n} from '@mui/material'\nimport CloseIcon from '@mui/icons-material/Close'\nimport { useRef, ReactNode, useEffect, useState } from 'react'\nimport { useResizable } from '../ResizableContainer/hooks/useResizable'\nimport { ResizableContainer } from '../ResizableContainer/ResizableContainer'\n\ntype DraggableDialogProps = {\n open?: boolean\n onClose?: () => void\n children: ReactNode\n title?: ReactNode\n}\n\nexport default function DraggableDialog({\n open = false,\n onClose,\n title,\n children,\n}: DraggableDialogProps) {\n const theme = useTheme()\n const isMobile = useMediaQuery(theme.breakpoints.down('sm'))\n const draggableRef = useRef<HTMLDivElement>(null)\n const [bounds, setBounds] = useState<DraggableBounds>()\n const [position, setPosition] = useState({ x: 100, y: 100 })\n const { width, height, handleResizeStart } = useResizable({\n initialWidth: 600,\n initialHeight: 500,\n minWidth: 300,\n minHeight: 200,\n maxWidth: 1200,\n maxHeight: 800,\n })\n\n useEffect(() => {\n // Calculate draggable bounds to keep dialog within viewport with margin\n function updateBounds() {\n const margin = 100\n const dialogWidth = width\n\n const newBounds = {\n left: -(dialogWidth - margin),\n top: 0,\n right: window.innerWidth - margin,\n bottom: window.innerHeight - margin,\n }\n\n setBounds(newBounds)\n\n // Clamp dialog position to new bounds to keep it visible after window resize\n setPosition(prevPosition => ({\n x: Math.max(newBounds.left, Math.min(prevPosition.x, newBounds.right)),\n y: Math.max(newBounds.top, Math.min(prevPosition.y, newBounds.bottom)),\n }))\n }\n updateBounds()\n window.addEventListener('resize', updateBounds)\n return () => window.removeEventListener('resize', updateBounds)\n }, [width, height])\n\n if (!open) {\n return null\n }\n\n const paperContent = (\n <Paper\n elevation={5}\n sx={{\n display: 'flex',\n flexDirection: 'column',\n height: isMobile ? '95vh' : `${height}px`,\n width: isMobile ? '95vw' : `${width}px`,\n ...(isMobile && {\n position: 'fixed',\n }),\n }}\n >\n <Stack\n direction=\"row\"\n alignItems=\"center\"\n gap=\"5px\"\n className=\"drag-handle\"\n sx={{\n padding: '20px',\n cursor: 'move',\n }}\n >\n <Typography variant=\"headline1\">{title}</Typography>\n <Box sx={{ flexGrow: 1 }} />\n <IconButton onClick={onClose}>\n <CloseIcon />\n </IconButton>\n </Stack>\n <Divider sx={{ mx: 2 }} />\n <DialogContent\n sx={{\n height: '100%',\n maxWidth: '100%',\n padding: '16px',\n }}\n >\n {children}\n </DialogContent>\n </Paper>\n )\n\n return (\n <Box\n sx={{\n position: 'fixed',\n zIndex: 1000,\n top: 0,\n left: 0,\n pointerEvents: isMobile ? 'auto' : 'none',\n }}\n >\n {isMobile ? (\n paperContent\n ) : (\n <Draggable\n position={position}\n onDrag={(e, data) => setPosition({ x: data.x, y: data.y })}\n nodeRef={draggableRef}\n bounds={bounds}\n handle=\".drag-handle\"\n >\n <Box ref={draggableRef} sx={{ pointerEvents: 'auto' }}>\n <ResizableContainer\n width={width}\n height={height}\n onResizeStart={handleResizeStart}\n >\n {paperContent}\n </ResizableContainer>\n </Box>\n </Draggable>\n )}\n </Box>\n )\n}\n"],"mappings":";;;;;;;;AAwBA,SAAwB,EAAgB,EACtC,UAAO,IACP,YACA,UACA,eACuB;CAEvB,IAAM,IAAW,EADH,GACiB,CAAM,YAAY,KAAK,KAAK,CAAC,EACtD,IAAe,EAAuB,KAAK,EAC3C,CAAC,GAAQ,KAAa,GAA2B,EACjD,CAAC,GAAU,KAAe,EAAS;EAAE,GAAG;EAAK,GAAG;EAAK,CAAC,EACtD,EAAE,UAAO,WAAQ,yBAAsB,EAAa;EACxD,cAAc;EACd,eAAe;EACf,UAAU;EACV,WAAW;EACX,UAAU;EACV,WAAW;EACZ,CAAC;AA4BF,KA1BA,QAAgB;EAEd,SAAS,IAAe;GACtB,IAGM,IAAY;IAChB,MAAM,EAAE,IAAc;IACtB,KAAK;IACL,OAAO,OAAO,aAAa;IAC3B,QAAQ,OAAO,cAAc;IAC9B;AAKD,GAHA,EAAU,EAAU,EAGpB,GAAY,OAAiB;IAC3B,GAAG,KAAK,IAAI,EAAU,MAAM,KAAK,IAAI,EAAa,GAAG,EAAU,MAAM,CAAC;IACtE,GAAG,KAAK,IAAI,EAAU,KAAK,KAAK,IAAI,EAAa,GAAG,EAAU,OAAO,CAAC;IACvE,EAAE;;AAIL,SAFA,GAAc,EACd,OAAO,iBAAiB,UAAU,EAAa,QAClC,OAAO,oBAAoB,UAAU,EAAa;IAC9D,CAAC,GAAO,EAAO,CAAC,EAEf,CAAC,EACH,QAAO;CAGT,IAAM,IACJ,kBAAC,GAAD;EACE,WAAW;EACX,IAAI;GACF,SAAS;GACT,eAAe;GACf,QAAQ,IAAW,SAAS,GAAG,EAAO;GACtC,OAAO,IAAW,SAAS,GAAG,EAAM;GACpC,GAAI,KAAY,EACd,UAAU,SACX;GACF;YAVH;GAYE,kBAAC,GAAD;IACE,WAAU;IACV,YAAW;IACX,KAAI;IACJ,WAAU;IACV,IAAI;KACF,SAAS;KACT,QAAQ;KACT;cARH;KAUE,kBAAC,GAAD;MAAY,SAAQ;gBAAa;MAAmB,CAAA;KACpD,kBAAC,GAAD,EAAK,IAAI,EAAE,UAAU,GAAG,EAAI,CAAA;KAC5B,kBAAC,GAAD;MAAY,SAAS;gBACnB,kBAAC,GAAD,EAAa,CAAA;MACF,CAAA;KACP;;GACR,kBAAC,GAAD,EAAS,IAAI,EAAE,IAAI,GAAG,EAAI,CAAA;GAC1B,kBAAC,GAAD;IACE,IAAI;KACF,QAAQ;KACR,UAAU;KACV,SAAS;KACV;IAEA;IACa,CAAA;GACV;;AAGV,QACE,kBAAC,GAAD;EACE,IAAI;GACF,UAAU;GACV,QAAQ;GACR,KAAK;GACL,MAAM;GACN,eAAe,IAAW,SAAS;GACpC;YAEA,IACC,IAEA,kBAAC,GAAD;GACY;GACV,SAAS,GAAG,MAAS,EAAY;IAAE,GAAG,EAAK;IAAG,GAAG,EAAK;IAAG,CAAC;GAC1D,SAAS;GACD;GACR,QAAO;aAEP,kBAAC,GAAD;IAAK,KAAK;IAAc,IAAI,EAAE,eAAe,QAAQ;cACnD,kBAAC,GAAD;KACS;KACC;KACR,eAAe;eAEd;KACkB,CAAA;IACjB,CAAA;GACI,CAAA;EAEV,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DynamicFormModal.js","names":[],"sources":["../../../src/components/DynamicForm/DynamicFormModal.tsx"],"sourcesContent":["import React from 'react'\nimport WideButton from '@/components/styled/WideButton'\nimport { Box } from '@mui/material'\nimport { useState } from 'react'\nimport ConfirmationDialog from '../ConfirmationDialog'\nimport DynamicForm, { DynamicFormProps } from './DynamicForm'\n\ntype ModalProps = {\n submitButtonText?: string\n}\n\nexport type DynamicFormModalProps = DynamicFormProps & ModalProps\n\nconst DynamicFormModal = ({\n schemaUrl,\n uiSchemaUrl,\n postUrl,\n submitButtonText,\n}: DynamicFormModalProps): React.ReactNode => {\n const [open, setOpen] = useState(false)\n\n const handleClickOpen = () => {\n setOpen(true)\n }\n\n const handleClose = () => {\n setOpen(false)\n }\n\n const form = (\n <DynamicForm\n schemaUrl={schemaUrl}\n uiSchemaUrl={uiSchemaUrl}\n postUrl={postUrl}\n onSubmit={() => {\n handleClose()\n }}\n />\n )\n\n return (\n <div className=\"browse-tools-page\">\n <Box sx={{ margin: '10px 0px 50px 0px' }}>\n <WideButton\n className=\"highlightSubmitToolButton\"\n variant=\"contained\"\n onClick={handleClickOpen}\n >\n {submitButtonText}\n </WideButton>\n <ConfirmationDialog\n open={open}\n title=\"\"\n content={form}\n onCancel={handleClose}\n onConfirm={() => {}}\n confirmButtonProps={{\n sx: { display: 'none' },\n }}\n cancelButtonProps={{\n children: 'cancel',\n }}\n />\n </Box>\n </div>\n )\n}\n\nexport default DynamicFormModal\n"],"mappings":";;;;;;;AAaA,IAAM,KAAoB,EACxB,cACA,gBACA,YACA,0BAC4C;CAC5C,IAAM,CAAC,GAAM,KAAW,EAAS,GAAM,EAEjC,UAAwB;AAC5B,IAAQ,GAAK;IAGT,UAAoB;AACxB,IAAQ,GAAM;;AAchB,QACE,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,GAAD;GAAK,IAAI,EAAE,QAAQ,qBAAqB;aAAxC,CACE,kBAAC,GAAD;IACE,WAAU;IACV,SAAQ;IACR,SAAS;cAER;IACU,CAAA,EACb,kBAAC,GAAD;IACQ;IACN,OAAM;IACN,SAvBN,kBAAC,GAAD;KACa;KACE;KACJ;KACT,gBAAgB;AACd,SAAa;;KAEf,
|
|
1
|
+
{"version":3,"file":"DynamicFormModal.js","names":[],"sources":["../../../src/components/DynamicForm/DynamicFormModal.tsx"],"sourcesContent":["import React from 'react'\nimport WideButton from '@/components/styled/WideButton'\nimport { Box } from '@mui/material'\nimport { useState } from 'react'\nimport ConfirmationDialog from '../ConfirmationDialog'\nimport DynamicForm, { DynamicFormProps } from './DynamicForm'\n\ntype ModalProps = {\n submitButtonText?: string\n}\n\nexport type DynamicFormModalProps = DynamicFormProps & ModalProps\n\nconst DynamicFormModal = ({\n schemaUrl,\n uiSchemaUrl,\n postUrl,\n submitButtonText,\n}: DynamicFormModalProps): React.ReactNode => {\n const [open, setOpen] = useState(false)\n\n const handleClickOpen = () => {\n setOpen(true)\n }\n\n const handleClose = () => {\n setOpen(false)\n }\n\n const form = (\n <DynamicForm\n schemaUrl={schemaUrl}\n uiSchemaUrl={uiSchemaUrl}\n postUrl={postUrl}\n onSubmit={() => {\n handleClose()\n }}\n />\n )\n\n return (\n <div className=\"browse-tools-page\">\n <Box sx={{ margin: '10px 0px 50px 0px' }}>\n <WideButton\n className=\"highlightSubmitToolButton\"\n variant=\"contained\"\n onClick={handleClickOpen}\n >\n {submitButtonText}\n </WideButton>\n <ConfirmationDialog\n open={open}\n title=\"\"\n content={form}\n onCancel={handleClose}\n onConfirm={() => {}}\n confirmButtonProps={{\n sx: { display: 'none' },\n }}\n cancelButtonProps={{\n children: 'cancel',\n }}\n />\n </Box>\n </div>\n )\n}\n\nexport default DynamicFormModal\n"],"mappings":";;;;;;;AAaA,IAAM,KAAoB,EACxB,cACA,gBACA,YACA,0BAC4C;CAC5C,IAAM,CAAC,GAAM,KAAW,EAAS,GAAM,EAEjC,UAAwB;AAC5B,IAAQ,GAAK;IAGT,UAAoB;AACxB,IAAQ,GAAM;;AAchB,QACE,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,GAAD;GAAK,IAAI,EAAE,QAAQ,qBAAqB;aAAxC,CACE,kBAAC,GAAD;IACE,WAAU;IACV,SAAQ;IACR,SAAS;cAER;IACU,CAAA,EACb,kBAAC,GAAD;IACQ;IACN,OAAM;IACN,SAvBN,kBAAC,GAAD;KACa;KACE;KACJ;KACT,gBAAgB;AACd,SAAa;;KAEf,CAgBa;IACT,UAAU;IACV,iBAAiB;IACjB,oBAAoB,EAClB,IAAI,EAAE,SAAS,QAAQ,EACxB;IACD,mBAAmB,EACjB,UAAU,UACX;IACD,CAAA,CACE;;EACF,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TableQueryEcosystem.js","names":[],"sources":["../../../src/components/Ecosystem/TableQueryEcosystem.tsx"],"sourcesContent":["import EcosystemCard from '@/components/Ecosystem/EcosystemCard'\nimport EcosystemSkeleton from '@/components/Ecosystem/EcosystemSkeleton'\nimport { Markdown } from '@/components/Markdown/MarkdownSynapse'\nimport { ImageFileHandle } from '@/components/widgets/ImageFileHandle'\nimport { useGetFullTableQueryResults } from '@/synapse-queries/entity/useGetQueryResultBundle'\nimport {\n getColumnIndex,\n parseEntityIdFromSqlStatement,\n} from '@/utils/functions/index'\nimport { BUNDLE_MASK_QUERY_RESULTS } from '@/utils/SynapseConstants'\nimport { Alert, Stack } from '@mui/material'\nimport {\n FileHandleAssociateType,\n Query,\n Row,\n SelectColumn,\n} from '@sage-bionetworks/synapse-types'\nimport uniq from 'lodash-es/uniq'\nimport { ReactNode } from 'react'\nimport EcosystemLayout from './EcosystemLayout'\n\n/* The column names expected to be found in the table */\nconst COLUMN_NAMES = {\n RESOURCE_CATEGORY: 'resourcecategory',\n RESOURCE_NAME: 'resourcename',\n RESOURCE_DESCRIPTION: 'resourcedescription',\n RESOURCE_URL: 'resourceurl',\n RESOURCE_ICON_IMAGE: 'resourceiconimage',\n}\n\ntype TableQueryEcosystemCardProps = {\n /** The row data to display*/\n row: Row\n /** The headers (select columns) of the table query result */\n headers: SelectColumn[]\n /** The entity ID of the table */\n tableEntityId: string\n}\n\n/**\n * Maps a table query result row to an EcosystemCard.\n */\nfunction TableQueryEcosystemCard(props: TableQueryEcosystemCardProps) {\n const { row, headers, tableEntityId } = props\n const resourceNameColumnIndex = getColumnIndex(\n COLUMN_NAMES.RESOURCE_NAME,\n headers,\n )!\n const resourceName = row.values[resourceNameColumnIndex]!\n\n const resourceUrlColumnIndex = getColumnIndex(\n COLUMN_NAMES.RESOURCE_URL,\n headers,\n )!\n const resourceUrl = row.values[resourceUrlColumnIndex]!\n\n const resourceDescriptionColumnIndex = getColumnIndex(\n COLUMN_NAMES.RESOURCE_DESCRIPTION,\n headers,\n )!\n const resourceDescriptionMarkdown =\n row.values[resourceDescriptionColumnIndex]!\n\n let iconElement: ReactNode = null\n\n const resourceIconImageColumnIndex = getColumnIndex(\n COLUMN_NAMES.RESOURCE_ICON_IMAGE,\n headers,\n )\n\n if (resourceIconImageColumnIndex) {\n const resourceIconFileHandleId = row.values[resourceIconImageColumnIndex]\n if (resourceIconFileHandleId) {\n iconElement = (\n <ImageFileHandle\n fileHandleAssociation={{\n fileHandleId: resourceIconFileHandleId,\n associateObjectId: tableEntityId,\n associateObjectType: FileHandleAssociateType.TableEntity,\n }}\n />\n )\n }\n }\n\n return (\n <EcosystemCard\n title={resourceName}\n titleUrl={resourceUrl}\n description={<Markdown markdown={resourceDescriptionMarkdown} />}\n image={iconElement}\n />\n )\n}\n\nexport type TableQueryEcosystemProps = {\n /** The Synapse table query to execute to populate the Ecosystem component */\n query: Query\n}\n\n/**\n * The Ecosystem component driven by the results of a Synapse table query.\n * @constructor\n */\nfunction TableQueryEcosystem(props: TableQueryEcosystemProps) {\n const { query } = props\n const tableEntityId = parseEntityIdFromSqlStatement(query.sql)\n const { data, isLoading, error } = useGetFullTableQueryResults({\n concreteType: 'org.sagebionetworks.repo.model.table.QueryBundleRequest',\n entityId: tableEntityId,\n query,\n partMask: BUNDLE_MASK_QUERY_RESULTS,\n })\n\n if (!data?.queryResult) {\n if (isLoading) {\n return <EcosystemSkeleton />\n }\n if (error) {\n return (\n <Alert color={'error'}>\n Error loading Ecosystem data: {error.message}\n </Alert>\n )\n }\n return null\n }\n\n const RESOURCE_CATEGORY_COLUMN_INDEX = getColumnIndex(\n COLUMN_NAMES.RESOURCE_CATEGORY,\n data.queryResult.queryResults.headers,\n )!\n\n // Get the distinct categories\n const categories: string[] = uniq(\n data.queryResult.queryResults.rows\n .map(row => row.values[RESOURCE_CATEGORY_COLUMN_INDEX])\n .filter((s): s is string => !!s), // Remove null values\n )\n\n // Create the content for each category and return it in the expected format for the Ecosystem component\n const config = categories.map(category => {\n const rowsForCategory = data.queryResult!.queryResults.rows.filter(\n row => row.values[RESOURCE_CATEGORY_COLUMN_INDEX] === category,\n )\n\n return {\n title: category,\n content: (\n <Stack>\n {rowsForCategory.map(row => (\n <TableQueryEcosystemCard\n key={row.values.join('-')}\n row={row}\n headers={data.queryResult!.queryResults.headers}\n tableEntityId={tableEntityId}\n />\n ))}\n </Stack>\n ),\n }\n })\n\n return <EcosystemLayout config={config} />\n}\n\nexport default TableQueryEcosystem\n"],"mappings":";;;;;;;;;;;;;;AAsBA,IAAM,IAAe;CACnB,mBAAmB;CACnB,eAAe;CACf,sBAAsB;CACtB,cAAc;CACd,qBAAqB;CACtB;AAcD,SAAS,EAAwB,GAAqC;CACpE,IAAM,EAAE,QAAK,YAAS,qBAAkB,GAClC,IAA0B,EAC9B,EAAa,eACb,EACD,EACK,IAAe,EAAI,OAAO,IAE1B,IAAyB,EAC7B,EAAa,cACb,EACD,EACK,IAAc,EAAI,OAAO,IAEzB,IAAiC,EACrC,EAAa,sBACb,EACD,EACK,IACJ,EAAI,OAAO,IAET,IAAyB,MAEvB,IAA+B,EACnC,EAAa,qBACb,EACD;AAED,KAAI,GAA8B;EAChC,IAAM,IAA2B,EAAI,OAAO;AAC5C,EAAI,MACF,IACE,kBAAC,GAAD,EACE,uBAAuB;GACrB,cAAc;GACd,mBAAmB;GACnB,qBAAqB,EAAwB;GAC9C,EACD,CAAA;;AAKR,QACE,kBAAC,GAAD;EACE,OAAO;EACP,UAAU;EACV,aAAa,kBAAC,GAAD,EAAU,UAAU,GAA+B,CAAA;EAChE,OAAO;EACP,CAAA;;AAaN,SAAS,EAAoB,GAAiC;CAC5D,IAAM,EAAE,aAAU,GACZ,IAAgB,EAA8B,EAAM,IAAI,EACxD,EAAE,SAAM,cAAW,aAAU,EAA4B;EAC7D,cAAc;EACd,UAAU;EACV;EACA,UAAA;EACD,CAAC;AAEF,KAAI,CAAC,GAAM,YAWT,QAVI,IACK,kBAAC,GAAD,EAAqB,CAAA,GAE1B,IAEA,kBAAC,GAAD;EAAO,OAAO;YAAd,CAAuB,kCACU,EAAM,QAC/B;MAGL;CAGT,IAAM,IAAiC,EACrC,EAAa,mBACb,EAAK,YAAY,aAAa,QAC/B;AAgCD,QAAO,kBAAC,GAAD,EAAyB,QA7BH,EAC3B,EAAK,YAAY,aAAa,KAC3B,KAAI,MAAO,EAAI,OAAO,GAAgC,CACtD,QAAQ,MAAmB,CAAC,CAAC,EAAE,
|
|
1
|
+
{"version":3,"file":"TableQueryEcosystem.js","names":[],"sources":["../../../src/components/Ecosystem/TableQueryEcosystem.tsx"],"sourcesContent":["import EcosystemCard from '@/components/Ecosystem/EcosystemCard'\nimport EcosystemSkeleton from '@/components/Ecosystem/EcosystemSkeleton'\nimport { Markdown } from '@/components/Markdown/MarkdownSynapse'\nimport { ImageFileHandle } from '@/components/widgets/ImageFileHandle'\nimport { useGetFullTableQueryResults } from '@/synapse-queries/entity/useGetQueryResultBundle'\nimport {\n getColumnIndex,\n parseEntityIdFromSqlStatement,\n} from '@/utils/functions/index'\nimport { BUNDLE_MASK_QUERY_RESULTS } from '@/utils/SynapseConstants'\nimport { Alert, Stack } from '@mui/material'\nimport {\n FileHandleAssociateType,\n Query,\n Row,\n SelectColumn,\n} from '@sage-bionetworks/synapse-types'\nimport uniq from 'lodash-es/uniq'\nimport { ReactNode } from 'react'\nimport EcosystemLayout from './EcosystemLayout'\n\n/* The column names expected to be found in the table */\nconst COLUMN_NAMES = {\n RESOURCE_CATEGORY: 'resourcecategory',\n RESOURCE_NAME: 'resourcename',\n RESOURCE_DESCRIPTION: 'resourcedescription',\n RESOURCE_URL: 'resourceurl',\n RESOURCE_ICON_IMAGE: 'resourceiconimage',\n}\n\ntype TableQueryEcosystemCardProps = {\n /** The row data to display*/\n row: Row\n /** The headers (select columns) of the table query result */\n headers: SelectColumn[]\n /** The entity ID of the table */\n tableEntityId: string\n}\n\n/**\n * Maps a table query result row to an EcosystemCard.\n */\nfunction TableQueryEcosystemCard(props: TableQueryEcosystemCardProps) {\n const { row, headers, tableEntityId } = props\n const resourceNameColumnIndex = getColumnIndex(\n COLUMN_NAMES.RESOURCE_NAME,\n headers,\n )!\n const resourceName = row.values[resourceNameColumnIndex]!\n\n const resourceUrlColumnIndex = getColumnIndex(\n COLUMN_NAMES.RESOURCE_URL,\n headers,\n )!\n const resourceUrl = row.values[resourceUrlColumnIndex]!\n\n const resourceDescriptionColumnIndex = getColumnIndex(\n COLUMN_NAMES.RESOURCE_DESCRIPTION,\n headers,\n )!\n const resourceDescriptionMarkdown =\n row.values[resourceDescriptionColumnIndex]!\n\n let iconElement: ReactNode = null\n\n const resourceIconImageColumnIndex = getColumnIndex(\n COLUMN_NAMES.RESOURCE_ICON_IMAGE,\n headers,\n )\n\n if (resourceIconImageColumnIndex) {\n const resourceIconFileHandleId = row.values[resourceIconImageColumnIndex]\n if (resourceIconFileHandleId) {\n iconElement = (\n <ImageFileHandle\n fileHandleAssociation={{\n fileHandleId: resourceIconFileHandleId,\n associateObjectId: tableEntityId,\n associateObjectType: FileHandleAssociateType.TableEntity,\n }}\n />\n )\n }\n }\n\n return (\n <EcosystemCard\n title={resourceName}\n titleUrl={resourceUrl}\n description={<Markdown markdown={resourceDescriptionMarkdown} />}\n image={iconElement}\n />\n )\n}\n\nexport type TableQueryEcosystemProps = {\n /** The Synapse table query to execute to populate the Ecosystem component */\n query: Query\n}\n\n/**\n * The Ecosystem component driven by the results of a Synapse table query.\n * @constructor\n */\nfunction TableQueryEcosystem(props: TableQueryEcosystemProps) {\n const { query } = props\n const tableEntityId = parseEntityIdFromSqlStatement(query.sql)\n const { data, isLoading, error } = useGetFullTableQueryResults({\n concreteType: 'org.sagebionetworks.repo.model.table.QueryBundleRequest',\n entityId: tableEntityId,\n query,\n partMask: BUNDLE_MASK_QUERY_RESULTS,\n })\n\n if (!data?.queryResult) {\n if (isLoading) {\n return <EcosystemSkeleton />\n }\n if (error) {\n return (\n <Alert color={'error'}>\n Error loading Ecosystem data: {error.message}\n </Alert>\n )\n }\n return null\n }\n\n const RESOURCE_CATEGORY_COLUMN_INDEX = getColumnIndex(\n COLUMN_NAMES.RESOURCE_CATEGORY,\n data.queryResult.queryResults.headers,\n )!\n\n // Get the distinct categories\n const categories: string[] = uniq(\n data.queryResult.queryResults.rows\n .map(row => row.values[RESOURCE_CATEGORY_COLUMN_INDEX])\n .filter((s): s is string => !!s), // Remove null values\n )\n\n // Create the content for each category and return it in the expected format for the Ecosystem component\n const config = categories.map(category => {\n const rowsForCategory = data.queryResult!.queryResults.rows.filter(\n row => row.values[RESOURCE_CATEGORY_COLUMN_INDEX] === category,\n )\n\n return {\n title: category,\n content: (\n <Stack>\n {rowsForCategory.map(row => (\n <TableQueryEcosystemCard\n key={row.values.join('-')}\n row={row}\n headers={data.queryResult!.queryResults.headers}\n tableEntityId={tableEntityId}\n />\n ))}\n </Stack>\n ),\n }\n })\n\n return <EcosystemLayout config={config} />\n}\n\nexport default TableQueryEcosystem\n"],"mappings":";;;;;;;;;;;;;;AAsBA,IAAM,IAAe;CACnB,mBAAmB;CACnB,eAAe;CACf,sBAAsB;CACtB,cAAc;CACd,qBAAqB;CACtB;AAcD,SAAS,EAAwB,GAAqC;CACpE,IAAM,EAAE,QAAK,YAAS,qBAAkB,GAClC,IAA0B,EAC9B,EAAa,eACb,EACD,EACK,IAAe,EAAI,OAAO,IAE1B,IAAyB,EAC7B,EAAa,cACb,EACD,EACK,IAAc,EAAI,OAAO,IAEzB,IAAiC,EACrC,EAAa,sBACb,EACD,EACK,IACJ,EAAI,OAAO,IAET,IAAyB,MAEvB,IAA+B,EACnC,EAAa,qBACb,EACD;AAED,KAAI,GAA8B;EAChC,IAAM,IAA2B,EAAI,OAAO;AAC5C,EAAI,MACF,IACE,kBAAC,GAAD,EACE,uBAAuB;GACrB,cAAc;GACd,mBAAmB;GACnB,qBAAqB,EAAwB;GAC9C,EACD,CAAA;;AAKR,QACE,kBAAC,GAAD;EACE,OAAO;EACP,UAAU;EACV,aAAa,kBAAC,GAAD,EAAU,UAAU,GAA+B,CAAA;EAChE,OAAO;EACP,CAAA;;AAaN,SAAS,EAAoB,GAAiC;CAC5D,IAAM,EAAE,aAAU,GACZ,IAAgB,EAA8B,EAAM,IAAI,EACxD,EAAE,SAAM,cAAW,aAAU,EAA4B;EAC7D,cAAc;EACd,UAAU;EACV;EACA,UAAA;EACD,CAAC;AAEF,KAAI,CAAC,GAAM,YAWT,QAVI,IACK,kBAAC,GAAD,EAAqB,CAAA,GAE1B,IAEA,kBAAC,GAAD;EAAO,OAAO;YAAd,CAAuB,kCACU,EAAM,QAC/B;MAGL;CAGT,IAAM,IAAiC,EACrC,EAAa,mBACb,EAAK,YAAY,aAAa,QAC/B;AAgCD,QAAO,kBAAC,GAAD,EAAyB,QA7BH,EAC3B,EAAK,YAAY,aAAa,KAC3B,KAAI,MAAO,EAAI,OAAO,GAAgC,CACtD,QAAQ,MAAmB,CAAC,CAAC,EAAE,CAIrB,CAAW,KAAI,OAKrB;EACL,OAAO;EACP,SACE,kBAAC,GAAD,EAAA,UAPoB,EAAK,YAAa,aAAa,KAAK,QAC1D,MAAO,EAAI,OAAO,OAAoC,EAOjD,CAAgB,KAAI,MACnB,kBAAC,GAAD;GAEO;GACL,SAAS,EAAK,YAAa,aAAa;GACzB;GACf,EAJK,EAAI,OAAO,KAAK,IAAI,CAIzB,CACF,EACI,CAAA;EAEX,EAG6B,EAAU,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EntityAclEditor.d.ts","sourceRoot":"","sources":["../../../src/components/EntityAclEditor/EntityAclEditor.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"EntityAclEditor.d.ts","sourceRoot":"","sources":["../../../src/components/EntityAclEditor/EntityAclEditor.tsx"],"names":[],"mappings":"AAyDA,MAAM,MAAM,oBAAoB,GAAG;IACjC,oIAAoI;IACpI,QAAQ,EAAE,MAAM,CAAA;IAChB,iEAAiE;IACjE,eAAe,EAAE,CAAC,cAAc,EAAE,OAAO,KAAK,IAAI,CAAA;IAClD,kDAAkD;IAClD,eAAe,EAAE,MAAM,IAAI,CAAA;IAC3B;;6BAEyB;IACzB,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,IAAI,EAAE,MAAM,IAAI,CAAA;CACjB,CAAA;AAoYD,QAAA,MAAM,2BAA2B,wHAahC,CAAA;AAED,eAAe,2BAA2B,CAAA"}
|