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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCookiePreferences.js","names":[],"sources":["../../../src/utils/hooks/useCookiePreferences.ts"],"sourcesContent":["import { useCallback, useEffect, useRef } from 'react'\nimport { atom, useAtom } from 'jotai'\nimport UniversalCookies from 'universal-cookie'\n\nexport type CookiePreference = {\n functionalAllowed: boolean\n analyticsAllowed: boolean\n}\n\nexport const allowAll: CookiePreference = {\n functionalAllowed: true,\n analyticsAllowed: true,\n}\nexport const allowNone: CookiePreference = {\n functionalAllowed: false,\n analyticsAllowed: false,\n}\n\nexport const COOKIES_AGREEMENT_COOKIE_KEY =\n 'org.sagebionetworks.security.cookies.portal.preference'\n\n/**\n * Read the current cookie preferences from the browser cookie jar.\n * This must only be called in a browser environment (not during SSR).\n */\nexport const getCurrentCookiePreferences = (): CookiePreference => {\n const cookies = new UniversalCookies()\n const prefs = cookies.get(COOKIES_AGREEMENT_COOKIE_KEY, {\n doNotParse: true,\n }) as string | undefined\n let cookiePreference = allowNone\n try {\n if (prefs != undefined) {\n cookiePreference = JSON.parse(prefs) as CookiePreference\n }\n } catch (err) {\n console.error(\n `Failed to parse CookiePreference from value, falling back to allow none. value=${prefs}`,\n )\n }\n return cookiePreference\n}\n\n// Initialize with allowNone so the atom is SSR-safe. The actual cookie value\n// is synced on the client via useEffect inside useCookiePreferences.\nconst cookiePreferencesAtom = atom<CookiePreference>(allowNone)\n\nexport const useCookiePreferences = (): [\n CookiePreference,\n (pref: CookiePreference) => void,\n] => {\n const [cookiePreferences, setCookiePreferencesAtomValue] = useAtom(\n cookiePreferencesAtom,\n )\n\n // On first client mount, sync the atom with the actual cookie value.\n const hasSyncedRef = useRef(false)\n useEffect(() => {\n if (!hasSyncedRef.current) {\n hasSyncedRef.current = true\n const current = getCurrentCookiePreferences()\n setCookiePreferencesAtomValue(current)\n }\n }, [setCookiePreferencesAtomValue])\n\n const setCookiePreferences = useCallback(\n (prefs: CookiePreference) => {\n if (!prefs.functionalAllowed) {\n localStorage.clear()\n sessionStorage.clear()\n }\n\n const current = new Date()\n const nextYear = new Date()\n nextYear.setFullYear(current.getFullYear() + 1)\n const hostname = window.location.hostname.toLowerCase()\n const cookies = new UniversalCookies()\n cookies.set(COOKIES_AGREEMENT_COOKIE_KEY, prefs, {\n path: '/',\n expires: nextYear,\n domain: hostname.endsWith('.synapse.org') ? 'synapse.org' : undefined,\n })\n\n setCookiePreferencesAtomValue(prefs)\n },\n [setCookiePreferencesAtomValue],\n )\n return [cookiePreferences, setCookiePreferences]\n}\n"],"mappings":";;;;AASA,IAAa,IAA6B;CACxC,mBAAmB;CACnB,kBAAkB;CACnB,EACY,IAA8B;CACzC,mBAAmB;CACnB,kBAAkB;CACnB,EAEY,IACX,0DAMW,UAAsD;CAEjE,IAAM,
|
|
1
|
+
{"version":3,"file":"useCookiePreferences.js","names":[],"sources":["../../../src/utils/hooks/useCookiePreferences.ts"],"sourcesContent":["import { useCallback, useEffect, useRef } from 'react'\nimport { atom, useAtom } from 'jotai'\nimport UniversalCookies from 'universal-cookie'\n\nexport type CookiePreference = {\n functionalAllowed: boolean\n analyticsAllowed: boolean\n}\n\nexport const allowAll: CookiePreference = {\n functionalAllowed: true,\n analyticsAllowed: true,\n}\nexport const allowNone: CookiePreference = {\n functionalAllowed: false,\n analyticsAllowed: false,\n}\n\nexport const COOKIES_AGREEMENT_COOKIE_KEY =\n 'org.sagebionetworks.security.cookies.portal.preference'\n\n/**\n * Read the current cookie preferences from the browser cookie jar.\n * This must only be called in a browser environment (not during SSR).\n */\nexport const getCurrentCookiePreferences = (): CookiePreference => {\n const cookies = new UniversalCookies()\n const prefs = cookies.get(COOKIES_AGREEMENT_COOKIE_KEY, {\n doNotParse: true,\n }) as string | undefined\n let cookiePreference = allowNone\n try {\n if (prefs != undefined) {\n cookiePreference = JSON.parse(prefs) as CookiePreference\n }\n } catch (err) {\n console.error(\n `Failed to parse CookiePreference from value, falling back to allow none. value=${prefs}`,\n )\n }\n return cookiePreference\n}\n\n// Initialize with allowNone so the atom is SSR-safe. The actual cookie value\n// is synced on the client via useEffect inside useCookiePreferences.\nconst cookiePreferencesAtom = atom<CookiePreference>(allowNone)\n\nexport const useCookiePreferences = (): [\n CookiePreference,\n (pref: CookiePreference) => void,\n] => {\n const [cookiePreferences, setCookiePreferencesAtomValue] = useAtom(\n cookiePreferencesAtom,\n )\n\n // On first client mount, sync the atom with the actual cookie value.\n const hasSyncedRef = useRef(false)\n useEffect(() => {\n if (!hasSyncedRef.current) {\n hasSyncedRef.current = true\n const current = getCurrentCookiePreferences()\n setCookiePreferencesAtomValue(current)\n }\n }, [setCookiePreferencesAtomValue])\n\n const setCookiePreferences = useCallback(\n (prefs: CookiePreference) => {\n if (!prefs.functionalAllowed) {\n localStorage.clear()\n sessionStorage.clear()\n }\n\n const current = new Date()\n const nextYear = new Date()\n nextYear.setFullYear(current.getFullYear() + 1)\n const hostname = window.location.hostname.toLowerCase()\n const cookies = new UniversalCookies()\n cookies.set(COOKIES_AGREEMENT_COOKIE_KEY, prefs, {\n path: '/',\n expires: nextYear,\n domain: hostname.endsWith('.synapse.org') ? 'synapse.org' : undefined,\n })\n\n setCookiePreferencesAtomValue(prefs)\n },\n [setCookiePreferencesAtomValue],\n )\n return [cookiePreferences, setCookiePreferences]\n}\n"],"mappings":";;;;AASA,IAAa,IAA6B;CACxC,mBAAmB;CACnB,kBAAkB;CACnB,EACY,IAA8B;CACzC,mBAAmB;CACnB,kBAAkB;CACnB,EAEY,IACX,0DAMW,UAAsD;CAEjE,IAAM,IAAQ,IADM,GACN,CAAQ,IAAI,GAA8B,EACtD,YAAY,IACb,CAAC,EACE,IAAmB;AACvB,KAAI;AACF,EAAI,KAAS,SACX,IAAmB,KAAK,MAAM,EAAM;SAE1B;AACZ,UAAQ,MACN,kFAAkF,IACnF;;AAEH,QAAO;GAKH,IAAwB,EAAuB,EAAU,EAElD,UAGR;CACH,IAAM,CAAC,GAAmB,KAAiC,EACzD,EACD,EAGK,IAAe,EAAO,GAAM;AA+BlC,QA9BA,QAAgB;AACd,EAAK,EAAa,YAChB,EAAa,UAAU,IAEvB,EADgB,GACc,CAAQ;IAEvC,CAAC,EAA8B,CAAC,EAwB5B,CAAC,GAtBqB,GAC1B,MAA4B;AAC3B,EAAK,EAAM,sBACT,aAAa,OAAO,EACpB,eAAe,OAAO;EAGxB,IAAM,oBAAU,IAAI,MAAM,EACpB,oBAAW,IAAI,MAAM;AAC3B,IAAS,YAAY,EAAQ,aAAa,GAAG,EAAE;EAC/C,IAAM,IAAW,OAAO,SAAS,SAAS,aAAa;AAQvD,EANA,IADoB,GACpB,CAAQ,IAAI,GAA8B,GAAO;GAC/C,MAAM;GACN,SAAS;GACT,QAAQ,EAAS,SAAS,eAAe,GAAG,gBAAgB,KAAA;GAC7D,CAAC,EAEF,EAA8B,EAAM;IAEtC,CAAC,EAA8B,CAEN,CAAqB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCreateShortUrl.js","names":[],"sources":["../../../src/utils/hooks/useCreateShortUrl.tsx"],"sourcesContent":["import { useMutation, useQueryClient } from '@tanstack/react-query'\n\ninterface UseCreateShortUrlOptions {\n shortIoPublicApiKey?: string\n domain: string\n onSuccess?: (shortUrl: string) => void\n onError?: (error: Error) => void\n}\n\nexport function useCreateShortUrl({\n shortIoPublicApiKey,\n domain,\n onSuccess,\n onError,\n}: UseCreateShortUrlOptions) {\n const queryClient = useQueryClient()\n const currentUrl = typeof window !== 'undefined' ? window.location.href : ''\n // Create a unique cache key based on the current URL to store the short URL\n const cacheKey = ['shortUrl', currentUrl]\n\n // Check if we have a cached short URL\n // This prevents regenerating the same short URL multiple times\n const cachedUrl = queryClient.getQueryData<string>(cacheKey)\n\n return useMutation({\n mutationFn: async () => {\n if (cachedUrl) {\n return cachedUrl\n }\n\n if (!shortIoPublicApiKey) {\n return window.location.href\n } else {\n const response = await fetch('https://api.short.io/links/public', {\n method: 'POST',\n headers: {\n Authorization: shortIoPublicApiKey,\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n },\n body: JSON.stringify({\n originalURL: window.location.href,\n domain: domain,\n }),\n })\n if (!response.ok) {\n const responseText = await response.text()\n throw new Error(responseText)\n }\n const jsonResponse = await response.json()\n const shortUrl = jsonResponse.shortURL\n // Store the short URL in the React Query cache so we can reuse it\n queryClient.setQueryData(cacheKey, shortUrl)\n return shortUrl\n }\n },\n onSuccess,\n onError,\n })\n}\n"],"mappings":";;AASA,SAAgB,EAAkB,EAChC,wBACA,WACA,cACA,cAC2B;CAC3B,IAAM,IAAc,GAAgB,EAG9B,IAAW,CAAC,YAFC,OAAO,SAAW,MAAc,OAAO,SAAS,OAAO,GAEjC,EAInC,IAAY,EAAY,aAAqB,EAAS;AAE5D,QAAO,EAAY;EACjB,YAAY,YAAY;AACtB,OAAI,EACF,QAAO;AAGT,OAAK,GAEE;IACL,IAAM,IAAW,MAAM,MAAM,qCAAqC;KAChE,QAAQ;KACR,SAAS;MACP,eAAe;MACf,gBAAgB;MAChB,QAAQ;MACT;KACD,MAAM,KAAK,UAAU;MACnB,aAAa,OAAO,SAAS;MACrB;MACT,CAAC;KACH,CAAC;AACF,QAAI,CAAC,EAAS,IAAI;KAChB,IAAM,IAAe,MAAM,EAAS,MAAM;AAC1C,WAAU,MAAM,EAAa;;IAG/B,IAAM,
|
|
1
|
+
{"version":3,"file":"useCreateShortUrl.js","names":[],"sources":["../../../src/utils/hooks/useCreateShortUrl.tsx"],"sourcesContent":["import { useMutation, useQueryClient } from '@tanstack/react-query'\n\ninterface UseCreateShortUrlOptions {\n shortIoPublicApiKey?: string\n domain: string\n onSuccess?: (shortUrl: string) => void\n onError?: (error: Error) => void\n}\n\nexport function useCreateShortUrl({\n shortIoPublicApiKey,\n domain,\n onSuccess,\n onError,\n}: UseCreateShortUrlOptions) {\n const queryClient = useQueryClient()\n const currentUrl = typeof window !== 'undefined' ? window.location.href : ''\n // Create a unique cache key based on the current URL to store the short URL\n const cacheKey = ['shortUrl', currentUrl]\n\n // Check if we have a cached short URL\n // This prevents regenerating the same short URL multiple times\n const cachedUrl = queryClient.getQueryData<string>(cacheKey)\n\n return useMutation({\n mutationFn: async () => {\n if (cachedUrl) {\n return cachedUrl\n }\n\n if (!shortIoPublicApiKey) {\n return window.location.href\n } else {\n const response = await fetch('https://api.short.io/links/public', {\n method: 'POST',\n headers: {\n Authorization: shortIoPublicApiKey,\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n },\n body: JSON.stringify({\n originalURL: window.location.href,\n domain: domain,\n }),\n })\n if (!response.ok) {\n const responseText = await response.text()\n throw new Error(responseText)\n }\n const jsonResponse = await response.json()\n const shortUrl = jsonResponse.shortURL\n // Store the short URL in the React Query cache so we can reuse it\n queryClient.setQueryData(cacheKey, shortUrl)\n return shortUrl\n }\n },\n onSuccess,\n onError,\n })\n}\n"],"mappings":";;AASA,SAAgB,EAAkB,EAChC,wBACA,WACA,cACA,cAC2B;CAC3B,IAAM,IAAc,GAAgB,EAG9B,IAAW,CAAC,YAFC,OAAO,SAAW,MAAc,OAAO,SAAS,OAAO,GAEjC,EAInC,IAAY,EAAY,aAAqB,EAAS;AAE5D,QAAO,EAAY;EACjB,YAAY,YAAY;AACtB,OAAI,EACF,QAAO;AAGT,OAAK,GAEE;IACL,IAAM,IAAW,MAAM,MAAM,qCAAqC;KAChE,QAAQ;KACR,SAAS;MACP,eAAe;MACf,gBAAgB;MAChB,QAAQ;MACT;KACD,MAAM,KAAK,UAAU;MACnB,aAAa,OAAO,SAAS;MACrB;MACT,CAAC;KACH,CAAC;AACF,QAAI,CAAC,EAAS,IAAI;KAChB,IAAM,IAAe,MAAM,EAAS,MAAM;AAC1C,WAAU,MAAM,EAAa;;IAG/B,IAAM,KAAW,MADU,EAAS,MAAM,EACZ;AAG9B,WADA,EAAY,aAAa,GAAU,EAAS,EACrC;SAtBP,QAAO,OAAO,SAAS;;EAyB3B;EACA;EACD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDetectSSOCode.js","names":[],"sources":["../../../src/utils/hooks/useDetectSSOCode.ts"],"sourcesContent":["import {\n bindOAuthProviderToAccount,\n getRootURL,\n oAuthRegisterAccountStep2,\n oAuthSessionRequest,\n setAccessTokenCookie,\n} from '@/synapse-client'\nimport { OAuth2State } from '@/utils/types'\nimport { TwoFactorAuthErrorResponse } from '@sage-bionetworks/synapse-client/generated/models/TwoFactorAuthErrorResponse'\nimport { SynapseClientError } from '@sage-bionetworks/synapse-client/util/SynapseClientError'\nimport { LoginResponse } from '@sage-bionetworks/synapse-types'\nimport { useEffect, useMemo, useState } from 'react'\nimport { BackendDestinationEnum } from '../functions'\nimport { CSRF_TOKEN_STORAGE_KEY, OAUTH2_PROVIDERS } from '../SynapseConstants'\nimport { useOneSageURL } from './useOneSageURL'\n\nfunction safeLocalStorageGetItem(key: string): string | null {\n try {\n return localStorage.getItem(key)\n } catch (err) {\n console.warn(`Unable to read from localStorage: ${key}`, err)\n return null\n }\n}\n\nfunction safeLocalStorageRemoveItem(key: string): void {\n try {\n localStorage.removeItem(key)\n } catch (err) {\n console.warn(`Unable to remove from localStorage: ${key}`, err)\n }\n}\n\nexport type UseDetectSSOCodeReturnType = {\n /* true iff SSO login has occurred and the completion of the OAuth flow in Synapse is pending */\n isLoading: boolean\n}\n\nexport type UseDetectSSOCodeOptions = {\n onSignInComplete?: () => void\n registerAccountUrl?: string\n onError?: (err: unknown) => void\n onTwoFactorAuthRequired?: (resp: TwoFactorAuthErrorResponse) => void\n onTwoFactorAuthResetTokenPresent?: (\n resp: TwoFactorAuthErrorResponse,\n encodedTwoFaResetToken: string,\n ) => void\n isInitializingSession: boolean\n isAuthenticated: boolean\n}\n\n/*\n * During SSO login, the authorization provider (Google, ORCiD, ArcusBio Okta, ...) will send the user back to the portal with an authorization code,\n * which can be exchanged for a Synapse user session. This function should be called whenever the root App is initialized\n * (to look for this code parameter and complete the round-trip). If state is included, then we assume that this is being\n * used for account creation, where we pass the username through the process.\n */\nexport default function useDetectSSOCode(\n opts: UseDetectSSOCodeOptions = {\n isInitializingSession: true,\n isAuthenticated: false,\n },\n): UseDetectSSOCodeReturnType {\n const defaultRegisterAccountURL = useOneSageURL('/register1')\n\n const {\n onSignInComplete,\n registerAccountUrl = defaultRegisterAccountURL.toString(),\n onError,\n onTwoFactorAuthRequired,\n onTwoFactorAuthResetTokenPresent,\n isInitializingSession,\n isAuthenticated,\n } = opts\n const redirectURL = getRootURL()\n // 'code' handling (from SSO) should be preformed on the root page, and then redirect to original route.\n // Use 'http://localhost/' as a placeholder during SSR (no browser URL available).\n // Since there is no 'code' or 'provider' in this placeholder URL, the rest of the hook is a no-op.\n const fullUrl: URL = new URL(\n typeof window !== 'undefined' ? window.location.href : 'http://localhost/',\n )\n // in test environment the searchParams isn't defined\n const { searchParams } = fullUrl\n const code = searchParams?.get('code')\n const provider = searchParams?.get('provider')\n\n // If the URL contains a client_id and redirect_uri, then we are acting as an identity provider for an external OAuth client\n const isHandlingSynapseOAuthSignIn = Boolean(\n searchParams?.get('client_id') && searchParams?.get('redirect_uri'),\n )\n\n // If the Synapse user signed in with an external IdP, we may have passed data in the 'state' param\n // Parse it (if appropriate)\n const state: OAuth2State | null = useMemo(() => {\n // If we are acting as an OIDC identity provider, then we should not parse the state param -- it was sent to us, and we should return it untouched\n if (!isHandlingSynapseOAuthSignIn) {\n const encodedState = searchParams?.get('state')\n try {\n return encodedState\n ? (JSON.parse(decodeURIComponent(encodedState)) as OAuth2State)\n : null\n } catch (e) {\n console.error(\n 'Error parsing state param:\\n',\n e,\n '\\nEncoded value:\\n',\n encodedState,\n )\n }\n }\n return null\n }, [isHandlingSynapseOAuthSignIn, searchParams])\n\n const [isLoading, setIsLoading] = useState(!!(code && provider))\n\n useEffect(() => {\n if (!isInitializingSession) {\n if (code && provider) {\n if (!isHandlingSynapseOAuthSignIn) {\n const storedCsrfToken = safeLocalStorageGetItem(\n CSRF_TOKEN_STORAGE_KEY,\n )\n\n const expectedCsrfToken = state?.csrfToken ?? null\n const tokensMatch =\n typeof expectedCsrfToken === 'string' &&\n typeof storedCsrfToken === 'string' &&\n expectedCsrfToken === storedCsrfToken\n\n if (!tokensMatch) {\n safeLocalStorageRemoveItem(CSRF_TOKEN_STORAGE_KEY)\n console.error(\n 'Invalid or missing OAuth CSRF token detected. Aborting OAuth flow.',\n )\n if (onError) {\n onError('Invalid OAuth state. Please try signing in again.')\n }\n setIsLoading(false)\n return\n }\n\n safeLocalStorageRemoveItem(CSRF_TOKEN_STORAGE_KEY)\n }\n\n const redirectUrl = `${redirectURL}?provider=${provider}`\n\n //If user is already logged in, and the provider is ORCID, then try to bind this OAuth provider to the account.\n if (OAUTH2_PROVIDERS.ORCID == provider && isAuthenticated) {\n // now bind this to the user account\n const onFailure = (err: SynapseClientError) => {\n console.error('Error binding ORCiD to account: ', err)\n if (onError) {\n onError(err.reason)\n }\n }\n bindOAuthProviderToAccount(\n provider,\n code,\n redirectUrl,\n BackendDestinationEnum.REPO_ENDPOINT,\n )\n .then(onSignInComplete)\n .catch(onFailure)\n .finally(() => setIsLoading(false))\n } else if (\n OAUTH2_PROVIDERS.GOOGLE == provider ||\n OAUTH2_PROVIDERS.ORCID == provider ||\n OAUTH2_PROVIDERS.ARCUS == provider ||\n OAUTH2_PROVIDERS.SAGE_BIONETWORKS == provider\n ) {\n const onSuccess = (\n response: LoginResponse | TwoFactorAuthErrorResponse | null,\n ) => {\n if (response) {\n if ('accessToken' in response) {\n setAccessTokenCookie(response.accessToken).then(\n onSignInComplete,\n )\n } else {\n // The app will redirect or open a modal to handle a standard 2FA sign in\n if (onTwoFactorAuthRequired) {\n onTwoFactorAuthRequired(response)\n }\n if (\n // The user logged in with OAuth while attempting to disable 2FA using an emailed signed token\n state &&\n state.twoFaResetToken &&\n onTwoFactorAuthResetTokenPresent\n ) {\n // Let the app handle redirecting to the 2FA reset page\n onTwoFactorAuthResetTokenPresent(\n response,\n state.twoFaResetToken,\n )\n }\n }\n }\n }\n const onFailure = (err: SynapseClientError) => {\n if (err.status === 404) {\n // Synapse account not found, send to registration page\n window.location.replace(registerAccountUrl)\n }\n console.error('Error with account login: ', err)\n if (onError) {\n onError(err.reason)\n }\n }\n\n if (\n (OAUTH2_PROVIDERS.GOOGLE == provider ||\n OAUTH2_PROVIDERS.ARCUS == provider ||\n OAUTH2_PROVIDERS.SAGE_BIONETWORKS == provider) &&\n state?.registrationUsername\n ) {\n oAuthRegisterAccountStep2(\n state.registrationUsername,\n provider,\n code,\n redirectUrl,\n BackendDestinationEnum.REPO_ENDPOINT,\n )\n .then(onSuccess)\n .catch(onFailure)\n .finally(() => setIsLoading(false))\n } else {\n oAuthSessionRequest(\n provider,\n code,\n redirectUrl,\n BackendDestinationEnum.REPO_ENDPOINT,\n )\n .then(onSuccess)\n .catch(onFailure)\n .finally(() => setIsLoading(false))\n }\n } else {\n console.warn('Unknown SSO Provider: ', provider)\n setIsLoading(false)\n }\n }\n }\n // Intentionally only monitoring initialization of the session -- only running on mount after the session detection has completed since this uses URL params that come from a redirect\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [isInitializingSession])\n\n return { isLoading }\n}\n"],"mappings":";;;;;;;;AAgBA,SAAS,EAAwB,GAA4B;AAC3D,KAAI;AACF,SAAO,aAAa,QAAQ,EAAI;UACzB,GAAK;AAEZ,SADA,QAAQ,KAAK,qCAAqC,KAAO,EAAI,EACtD;;;AAIX,SAAS,EAA2B,GAAmB;AACrD,KAAI;AACF,eAAa,WAAW,EAAI;UACrB,GAAK;AACZ,UAAQ,KAAK,uCAAuC,KAAO,EAAI;;;AA4BnE,SAAwB,EACtB,IAAgC;CAC9B,uBAAuB;CACvB,iBAAiB;CAClB,EAC2B;CAC5B,IAAM,IAA4B,EAAc,aAAa,EAEvD,EACJ,qBACA,wBAAqB,EAA0B,UAAU,EACzD,YACA,4BACA,qCACA,0BACA,uBACE,GACE,IAAc,GAAY,EAQ1B,EAAE,oBAJa,IAAI,IACvB,OAAO,SAAW,MAAc,OAAO,SAAS,OAAO,oBACxD,EAGK,IAAO,GAAc,IAAI,OAAO,EAChC,IAAW,GAAc,IAAI,WAAW,EAGxC,IAA+B,GACnC,GAAc,IAAI,YAAY,IAAI,GAAc,IAAI,eAAe,GAK/D,IAA4B,QAAc;AAE9C,MAAI,CAAC,GAA8B;GACjC,IAAM,IAAe,GAAc,IAAI,QAAQ;AAC/C,OAAI;AACF,WAAO,IACF,KAAK,MAAM,mBAAmB,EAAa,CAAC,GAC7C;YACG,GAAG;AACV,YAAQ,MACN,gCACA,GACA,sBACA,EACD;;;AAGL,SAAO;IACN,CAAC,GAA8B,EAAa,CAAC,EAE1C,CAAC,GAAW,KAAgB,EAAS,CAAC,EAAE,KAAQ,GAAU;AAqIhE,QAnIA,QAAgB;AACd,MAAI,CAAC,KACC,KAAQ,GAAU;AACpB,OAAI,CAAC,GAA8B;IACjC,IAAM,IAAkB,EACtB,EACD,EAEK,IAAoB,GAAO,aAAa;AAM9C,QAAI,EAJF,OAAO,KAAsB,YAC7B,OAAO,KAAoB,YAC3B,MAAsB,IAEN;AAQhB,KAPA,EAA2B,EAAuB,EAClD,QAAQ,MACN,qEACD,EACG,KACF,EAAQ,oDAAoD,EAE9D,EAAa,GAAM;AACnB;;AAGF,MAA2B,EAAuB;;GAGpD,IAAM,IAAc,GAAG,EAAY,YAAY;AAG/C,OAAI,EAAiB,SAAS,KAAY,EAQxC,GACE,GACA,GACA,GACA,EAAuB,cACxB,CACE,KAAK,EAAiB,CACtB,OAbgB,MAA4B;AAE7C,IADA,QAAQ,MAAM,oCAAoC,EAAI,EAClD,KACF,EAAQ,EAAI,OAAO;KAUJ,CAChB,cAAc,EAAa,GAAM,CAAC;YAErC,EAAiB,UAAU,KAC3B,EAAiB,SAAS,KAC1B,EAAiB,SAAS,KAC1B,EAAiB,oBAAoB,GACrC;IACA,IAAM,KACJ,MACG;AACH,KAAI,MACE,iBAAiB,IACnB,EAAqB,EAAS,YAAY,CAAC,KACzC,EACD,IAGG,KACF,EAAwB,EAAS,EAIjC,KACA,EAAM,mBACN,KAGA,EACE,GACA,EAAM,gBACP;OAKH,KAAa,MAA4B;AAM7C,KALI,EAAI,WAAW,OAEjB,OAAO,SAAS,QAAQ,EAAmB,EAE7C,QAAQ,MAAM,8BAA8B,EAAI,EAC5C,KACF,EAAQ,EAAI,OAAO;;AAIvB,KACG,EAAiB,UAAU,KAC1B,EAAiB,SAAS,KAC1B,EAAiB,oBAAoB,MACvC,GAAO,uBAEP,EACE,EAAM,sBACN,GACA,GACA,GACA,EAAuB,cACxB,CACE,KAAK,EAAU,CACf,MAAM,EAAU,CAChB,cAAc,EAAa,GAAM,CAAC,GAErC,EACE,GACA,GACA,GACA,EAAuB,cACxB,CACE,KAAK,EAAU,CACf,MAAM,EAAU,CAChB,cAAc,EAAa,GAAM,CAAC;SAIvC,CADA,QAAQ,KAAK,0BAA0B,EAAS,EAChD,EAAa,GAAM;;IAMxB,CAAC,EAAsB,CAAC,EAEpB,EAAE,cAAW"}
|
|
1
|
+
{"version":3,"file":"useDetectSSOCode.js","names":[],"sources":["../../../src/utils/hooks/useDetectSSOCode.ts"],"sourcesContent":["import {\n bindOAuthProviderToAccount,\n getRootURL,\n oAuthRegisterAccountStep2,\n oAuthSessionRequest,\n setAccessTokenCookie,\n} from '@/synapse-client'\nimport { OAuth2State } from '@/utils/types'\nimport { TwoFactorAuthErrorResponse } from '@sage-bionetworks/synapse-client/generated/models/TwoFactorAuthErrorResponse'\nimport { SynapseClientError } from '@sage-bionetworks/synapse-client/util/SynapseClientError'\nimport { LoginResponse } from '@sage-bionetworks/synapse-types'\nimport { useEffect, useMemo, useState } from 'react'\nimport { BackendDestinationEnum } from '../functions'\nimport { CSRF_TOKEN_STORAGE_KEY, OAUTH2_PROVIDERS } from '../SynapseConstants'\nimport { useOneSageURL } from './useOneSageURL'\n\nfunction safeLocalStorageGetItem(key: string): string | null {\n try {\n return localStorage.getItem(key)\n } catch (err) {\n console.warn(`Unable to read from localStorage: ${key}`, err)\n return null\n }\n}\n\nfunction safeLocalStorageRemoveItem(key: string): void {\n try {\n localStorage.removeItem(key)\n } catch (err) {\n console.warn(`Unable to remove from localStorage: ${key}`, err)\n }\n}\n\nexport type UseDetectSSOCodeReturnType = {\n /* true iff SSO login has occurred and the completion of the OAuth flow in Synapse is pending */\n isLoading: boolean\n}\n\nexport type UseDetectSSOCodeOptions = {\n onSignInComplete?: () => void\n registerAccountUrl?: string\n onError?: (err: unknown) => void\n onTwoFactorAuthRequired?: (resp: TwoFactorAuthErrorResponse) => void\n onTwoFactorAuthResetTokenPresent?: (\n resp: TwoFactorAuthErrorResponse,\n encodedTwoFaResetToken: string,\n ) => void\n isInitializingSession: boolean\n isAuthenticated: boolean\n}\n\n/*\n * During SSO login, the authorization provider (Google, ORCiD, ArcusBio Okta, ...) will send the user back to the portal with an authorization code,\n * which can be exchanged for a Synapse user session. This function should be called whenever the root App is initialized\n * (to look for this code parameter and complete the round-trip). If state is included, then we assume that this is being\n * used for account creation, where we pass the username through the process.\n */\nexport default function useDetectSSOCode(\n opts: UseDetectSSOCodeOptions = {\n isInitializingSession: true,\n isAuthenticated: false,\n },\n): UseDetectSSOCodeReturnType {\n const defaultRegisterAccountURL = useOneSageURL('/register1')\n\n const {\n onSignInComplete,\n registerAccountUrl = defaultRegisterAccountURL.toString(),\n onError,\n onTwoFactorAuthRequired,\n onTwoFactorAuthResetTokenPresent,\n isInitializingSession,\n isAuthenticated,\n } = opts\n const redirectURL = getRootURL()\n // 'code' handling (from SSO) should be preformed on the root page, and then redirect to original route.\n // Use 'http://localhost/' as a placeholder during SSR (no browser URL available).\n // Since there is no 'code' or 'provider' in this placeholder URL, the rest of the hook is a no-op.\n const fullUrl: URL = new URL(\n typeof window !== 'undefined' ? window.location.href : 'http://localhost/',\n )\n // in test environment the searchParams isn't defined\n const { searchParams } = fullUrl\n const code = searchParams?.get('code')\n const provider = searchParams?.get('provider')\n\n // If the URL contains a client_id and redirect_uri, then we are acting as an identity provider for an external OAuth client\n const isHandlingSynapseOAuthSignIn = Boolean(\n searchParams?.get('client_id') && searchParams?.get('redirect_uri'),\n )\n\n // If the Synapse user signed in with an external IdP, we may have passed data in the 'state' param\n // Parse it (if appropriate)\n const state: OAuth2State | null = useMemo(() => {\n // If we are acting as an OIDC identity provider, then we should not parse the state param -- it was sent to us, and we should return it untouched\n if (!isHandlingSynapseOAuthSignIn) {\n const encodedState = searchParams?.get('state')\n try {\n return encodedState\n ? (JSON.parse(decodeURIComponent(encodedState)) as OAuth2State)\n : null\n } catch (e) {\n console.error(\n 'Error parsing state param:\\n',\n e,\n '\\nEncoded value:\\n',\n encodedState,\n )\n }\n }\n return null\n }, [isHandlingSynapseOAuthSignIn, searchParams])\n\n const [isLoading, setIsLoading] = useState(!!(code && provider))\n\n useEffect(() => {\n if (!isInitializingSession) {\n if (code && provider) {\n if (!isHandlingSynapseOAuthSignIn) {\n const storedCsrfToken = safeLocalStorageGetItem(\n CSRF_TOKEN_STORAGE_KEY,\n )\n\n const expectedCsrfToken = state?.csrfToken ?? null\n const tokensMatch =\n typeof expectedCsrfToken === 'string' &&\n typeof storedCsrfToken === 'string' &&\n expectedCsrfToken === storedCsrfToken\n\n if (!tokensMatch) {\n safeLocalStorageRemoveItem(CSRF_TOKEN_STORAGE_KEY)\n console.error(\n 'Invalid or missing OAuth CSRF token detected. Aborting OAuth flow.',\n )\n if (onError) {\n onError('Invalid OAuth state. Please try signing in again.')\n }\n setIsLoading(false)\n return\n }\n\n safeLocalStorageRemoveItem(CSRF_TOKEN_STORAGE_KEY)\n }\n\n const redirectUrl = `${redirectURL}?provider=${provider}`\n\n //If user is already logged in, and the provider is ORCID, then try to bind this OAuth provider to the account.\n if (OAUTH2_PROVIDERS.ORCID == provider && isAuthenticated) {\n // now bind this to the user account\n const onFailure = (err: SynapseClientError) => {\n console.error('Error binding ORCiD to account: ', err)\n if (onError) {\n onError(err.reason)\n }\n }\n bindOAuthProviderToAccount(\n provider,\n code,\n redirectUrl,\n BackendDestinationEnum.REPO_ENDPOINT,\n )\n .then(onSignInComplete)\n .catch(onFailure)\n .finally(() => setIsLoading(false))\n } else if (\n OAUTH2_PROVIDERS.GOOGLE == provider ||\n OAUTH2_PROVIDERS.ORCID == provider ||\n OAUTH2_PROVIDERS.ARCUS == provider ||\n OAUTH2_PROVIDERS.SAGE_BIONETWORKS == provider\n ) {\n const onSuccess = (\n response: LoginResponse | TwoFactorAuthErrorResponse | null,\n ) => {\n if (response) {\n if ('accessToken' in response) {\n setAccessTokenCookie(response.accessToken).then(\n onSignInComplete,\n )\n } else {\n // The app will redirect or open a modal to handle a standard 2FA sign in\n if (onTwoFactorAuthRequired) {\n onTwoFactorAuthRequired(response)\n }\n if (\n // The user logged in with OAuth while attempting to disable 2FA using an emailed signed token\n state &&\n state.twoFaResetToken &&\n onTwoFactorAuthResetTokenPresent\n ) {\n // Let the app handle redirecting to the 2FA reset page\n onTwoFactorAuthResetTokenPresent(\n response,\n state.twoFaResetToken,\n )\n }\n }\n }\n }\n const onFailure = (err: SynapseClientError) => {\n if (err.status === 404) {\n // Synapse account not found, send to registration page\n window.location.replace(registerAccountUrl)\n }\n console.error('Error with account login: ', err)\n if (onError) {\n onError(err.reason)\n }\n }\n\n if (\n (OAUTH2_PROVIDERS.GOOGLE == provider ||\n OAUTH2_PROVIDERS.ARCUS == provider ||\n OAUTH2_PROVIDERS.SAGE_BIONETWORKS == provider) &&\n state?.registrationUsername\n ) {\n oAuthRegisterAccountStep2(\n state.registrationUsername,\n provider,\n code,\n redirectUrl,\n BackendDestinationEnum.REPO_ENDPOINT,\n )\n .then(onSuccess)\n .catch(onFailure)\n .finally(() => setIsLoading(false))\n } else {\n oAuthSessionRequest(\n provider,\n code,\n redirectUrl,\n BackendDestinationEnum.REPO_ENDPOINT,\n )\n .then(onSuccess)\n .catch(onFailure)\n .finally(() => setIsLoading(false))\n }\n } else {\n console.warn('Unknown SSO Provider: ', provider)\n setIsLoading(false)\n }\n }\n }\n // Intentionally only monitoring initialization of the session -- only running on mount after the session detection has completed since this uses URL params that come from a redirect\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [isInitializingSession])\n\n return { isLoading }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDirectDownloadHandler.js","names":[],"sources":["../../../src/utils/hooks/useDirectDownloadHandler.tsx"],"sourcesContent":["import { getFiles } from '@/synapse-client'\nimport { useSynapseContext } from '@/utils/context/SynapseContext'\nimport {\n BatchFileRequest,\n FileHandleAssociateType,\n FileHandleAssociation,\n} from '@sage-bionetworks/synapse-types'\nimport UAParser from 'ua-parser-js'\n\ntype DirectDownloadHandlerProps = {\n fileHandleId: string\n associatedObjectId: string\n associatedObjectType: FileHandleAssociateType\n}\n\n/**\n * Returns a 'downloadFile' function that fetches a presigned URL for a file\n * handle and opens it in the browser to trigger a direct download.\n *\n * To bypass Safari's popup blocker, this function must be invoked\n * within a user-triggered event handler (ex, inside an onClick callback).\n */\nexport function useDirectDownloadHandler() {\n const { accessToken } = useSynapseContext()\n\n const downloadFile = async ({\n fileHandleId,\n associatedObjectId,\n associatedObjectType,\n }: DirectDownloadHandlerProps) => {\n // SWC-5907: opening in the file must be strictly done in the same click event process (Safari only).\n // https://stackoverflow.com/questions/6628949/window-open-popup-getting-blocked-during-click-event\n const parser = new UAParser()\n const isSafari = parser.getBrowser().name == 'Safari'\n let safariDownloadWindow: Window | null = null\n\n if (isSafari) {\n safariDownloadWindow = window.open(\n '',\n 'Safari Download',\n 'toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=yes,popup,width=600,height=200',\n )\n safariDownloadWindow!.document.body.innerHTML =\n 'Downloading file on Safari...'\n }\n\n try {\n const fileHandleAssociation: FileHandleAssociation = {\n fileHandleId,\n associateObjectId: associatedObjectId,\n associateObjectType: associatedObjectType,\n }\n\n const batchFileRequest: BatchFileRequest = {\n includeFileHandles: true,\n includePreSignedURLs: true,\n includePreviewPreSignedURLs: false,\n requestedFiles: [fileHandleAssociation],\n }\n\n const response = await getFiles(batchFileRequest, accessToken)\n const preSignedURL = response.requestedFiles[0].preSignedURL!\n\n if (!preSignedURL) {\n safariDownloadWindow?.close()\n console.log('Failed to get file download link')\n } else {\n if (isSafari && safariDownloadWindow) {\n safariDownloadWindow.location = preSignedURL\n setTimeout(() => {\n if (safariDownloadWindow) {\n safariDownloadWindow.close()\n }\n }, 10000)\n } else {\n window.open(preSignedURL)\n }\n }\n } catch (e) {\n safariDownloadWindow?.close()\n console.log('Failed to get file download link: ', e)\n }\n }\n return { downloadFile }\n}\n"],"mappings":";;;;;AAsBA,SAAgB,IAA2B;CACzC,IAAM,EAAE,mBAAgB,GAAmB;AA4D3C,QAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"useDirectDownloadHandler.js","names":[],"sources":["../../../src/utils/hooks/useDirectDownloadHandler.tsx"],"sourcesContent":["import { getFiles } from '@/synapse-client'\nimport { useSynapseContext } from '@/utils/context/SynapseContext'\nimport {\n BatchFileRequest,\n FileHandleAssociateType,\n FileHandleAssociation,\n} from '@sage-bionetworks/synapse-types'\nimport UAParser from 'ua-parser-js'\n\ntype DirectDownloadHandlerProps = {\n fileHandleId: string\n associatedObjectId: string\n associatedObjectType: FileHandleAssociateType\n}\n\n/**\n * Returns a 'downloadFile' function that fetches a presigned URL for a file\n * handle and opens it in the browser to trigger a direct download.\n *\n * To bypass Safari's popup blocker, this function must be invoked\n * within a user-triggered event handler (ex, inside an onClick callback).\n */\nexport function useDirectDownloadHandler() {\n const { accessToken } = useSynapseContext()\n\n const downloadFile = async ({\n fileHandleId,\n associatedObjectId,\n associatedObjectType,\n }: DirectDownloadHandlerProps) => {\n // SWC-5907: opening in the file must be strictly done in the same click event process (Safari only).\n // https://stackoverflow.com/questions/6628949/window-open-popup-getting-blocked-during-click-event\n const parser = new UAParser()\n const isSafari = parser.getBrowser().name == 'Safari'\n let safariDownloadWindow: Window | null = null\n\n if (isSafari) {\n safariDownloadWindow = window.open(\n '',\n 'Safari Download',\n 'toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=yes,popup,width=600,height=200',\n )\n safariDownloadWindow!.document.body.innerHTML =\n 'Downloading file on Safari...'\n }\n\n try {\n const fileHandleAssociation: FileHandleAssociation = {\n fileHandleId,\n associateObjectId: associatedObjectId,\n associateObjectType: associatedObjectType,\n }\n\n const batchFileRequest: BatchFileRequest = {\n includeFileHandles: true,\n includePreSignedURLs: true,\n includePreviewPreSignedURLs: false,\n requestedFiles: [fileHandleAssociation],\n }\n\n const response = await getFiles(batchFileRequest, accessToken)\n const preSignedURL = response.requestedFiles[0].preSignedURL!\n\n if (!preSignedURL) {\n safariDownloadWindow?.close()\n console.log('Failed to get file download link')\n } else {\n if (isSafari && safariDownloadWindow) {\n safariDownloadWindow.location = preSignedURL\n setTimeout(() => {\n if (safariDownloadWindow) {\n safariDownloadWindow.close()\n }\n }, 10000)\n } else {\n window.open(preSignedURL)\n }\n }\n } catch (e) {\n safariDownloadWindow?.close()\n console.log('Failed to get file download link: ', e)\n }\n }\n return { downloadFile }\n}\n"],"mappings":";;;;;AAsBA,SAAgB,IAA2B;CACzC,IAAM,EAAE,mBAAgB,GAAmB;AA4D3C,QAAO,EAAE,qBA1DmB,EAC1B,iBACA,uBACA,8BACgC;EAIhC,IAAM,IAAW,IADE,GACF,CAAO,YAAY,CAAC,QAAQ,UACzC,IAAsC;AAE1C,EAAI,MACF,IAAuB,OAAO,KAC5B,IACA,mBACA,qHACD,EACD,EAAsB,SAAS,KAAK,YAClC;AAGJ,MAAI;GAeF,IAAM,KAAe,MADE,EAAS;IAN9B,oBAAoB;IACpB,sBAAsB;IACtB,6BAA6B;IAC7B,gBAAgB,CAAC;KATjB;KACA,mBAAmB;KACnB,qBAAqB;KAOJ,CAAsB;IAGT,EAAkB,EAAY,EAChC,eAAe,GAAG;AAEhD,GAAK,IAIC,KAAY,KACd,EAAqB,WAAW,GAChC,iBAAiB;AACf,IAAI,KACF,EAAqB,OAAO;MAE7B,IAAM,IAET,OAAO,KAAK,EAAa,IAX3B,GAAsB,OAAO,EAC7B,QAAQ,IAAI,mCAAmC;WAa1C,GAAG;AAEV,GADA,GAAsB,OAAO,EAC7B,QAAQ,IAAI,sCAAsC,EAAE;;IAGjC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useGetGoalData.js","names":[],"sources":["../../../src/utils/hooks/useGetGoalData.ts"],"sourcesContent":["import { getFiles } from '@/synapse-client/SynapseClient'\nimport { useSynapseContext } from '@/utils/context/SynapseContext'\nimport { getFieldIndex } from '@/utils/functions/queryUtils'\nimport { SynapseClientError } from '@sage-bionetworks/synapse-client/util/SynapseClientError'\nimport {\n BatchFileRequest,\n FileHandleAssociateType,\n FileHandleAssociation,\n QueryResultBundle,\n} from '@sage-bionetworks/synapse-types'\nimport { useEffect, useState } from 'react'\n\nexport default function useGetGoalData(\n entityId: string,\n queryResultBundle: QueryResultBundle | undefined,\n) {\n const [assets, setAssets] = useState<string[] | undefined>()\n const [error, setError] = useState<string | SynapseClientError | undefined>()\n const { accessToken } = useSynapseContext()\n\n enum ExpectedColumns {\n TABLEID = 'TableId',\n COUNT_SQL = 'CountSql',\n TITLE = 'Title',\n SUMMARY = 'Summary',\n LINK = 'Link',\n ASSET = 'Asset',\n }\n\n useEffect(() => {\n const getData = async () => {\n try {\n const assetColumnIndex = getFieldIndex(\n ExpectedColumns.ASSET,\n queryResultBundle,\n )\n const fileHandle =\n (queryResultBundle?.queryResult!.queryResults.rows.map(\n row => row.values[assetColumnIndex],\n ) ?? []) as string[]\n const assetFileHandleIds = fileHandle.filter(\n v => v != null && v !== undefined,\n )\n if (assetFileHandleIds.length === 0) {\n setAssets(undefined)\n setError(undefined)\n return\n }\n const fileHandleAssociationList: FileHandleAssociation[] =\n assetFileHandleIds.map(fileId => {\n return {\n associateObjectId: entityId,\n associateObjectType: FileHandleAssociateType.TableEntity,\n fileHandleId: fileId,\n }\n })\n const batchFileRequest: BatchFileRequest = {\n includeFileHandles: false,\n includePreSignedURLs: true,\n includePreviewPreSignedURLs: false,\n requestedFiles: fileHandleAssociationList,\n }\n const files = await getFiles(batchFileRequest, accessToken)\n setError(undefined)\n const outFiles = files.requestedFiles\n .filter(row => row.preSignedURL !== undefined)\n .map(row => row.preSignedURL!)\n setAssets(outFiles)\n } catch (e) {\n setError(e)\n setAssets(undefined)\n }\n }\n getData()\n }, [entityId, queryResultBundle, accessToken])\n\n return { assets, error }\n}\n"],"mappings":";;;;;;AAYA,SAAwB,EACtB,GACA,GACA;CACA,IAAM,CAAC,GAAQ,KAAa,GAAgC,EACtD,CAAC,GAAO,KAAY,GAAmD,EACvE,EAAE,mBAAgB,GAAmB,EAEtC,IAAL,yBAAA,GAAA;SACE,EAAA,
|
|
1
|
+
{"version":3,"file":"useGetGoalData.js","names":[],"sources":["../../../src/utils/hooks/useGetGoalData.ts"],"sourcesContent":["import { getFiles } from '@/synapse-client/SynapseClient'\nimport { useSynapseContext } from '@/utils/context/SynapseContext'\nimport { getFieldIndex } from '@/utils/functions/queryUtils'\nimport { SynapseClientError } from '@sage-bionetworks/synapse-client/util/SynapseClientError'\nimport {\n BatchFileRequest,\n FileHandleAssociateType,\n FileHandleAssociation,\n QueryResultBundle,\n} from '@sage-bionetworks/synapse-types'\nimport { useEffect, useState } from 'react'\n\nexport default function useGetGoalData(\n entityId: string,\n queryResultBundle: QueryResultBundle | undefined,\n) {\n const [assets, setAssets] = useState<string[] | undefined>()\n const [error, setError] = useState<string | SynapseClientError | undefined>()\n const { accessToken } = useSynapseContext()\n\n enum ExpectedColumns {\n TABLEID = 'TableId',\n COUNT_SQL = 'CountSql',\n TITLE = 'Title',\n SUMMARY = 'Summary',\n LINK = 'Link',\n ASSET = 'Asset',\n }\n\n useEffect(() => {\n const getData = async () => {\n try {\n const assetColumnIndex = getFieldIndex(\n ExpectedColumns.ASSET,\n queryResultBundle,\n )\n const fileHandle =\n (queryResultBundle?.queryResult!.queryResults.rows.map(\n row => row.values[assetColumnIndex],\n ) ?? []) as string[]\n const assetFileHandleIds = fileHandle.filter(\n v => v != null && v !== undefined,\n )\n if (assetFileHandleIds.length === 0) {\n setAssets(undefined)\n setError(undefined)\n return\n }\n const fileHandleAssociationList: FileHandleAssociation[] =\n assetFileHandleIds.map(fileId => {\n return {\n associateObjectId: entityId,\n associateObjectType: FileHandleAssociateType.TableEntity,\n fileHandleId: fileId,\n }\n })\n const batchFileRequest: BatchFileRequest = {\n includeFileHandles: false,\n includePreSignedURLs: true,\n includePreviewPreSignedURLs: false,\n requestedFiles: fileHandleAssociationList,\n }\n const files = await getFiles(batchFileRequest, accessToken)\n setError(undefined)\n const outFiles = files.requestedFiles\n .filter(row => row.preSignedURL !== undefined)\n .map(row => row.preSignedURL!)\n setAssets(outFiles)\n } catch (e) {\n setError(e)\n setAssets(undefined)\n }\n }\n getData()\n }, [entityId, queryResultBundle, accessToken])\n\n return { assets, error }\n}\n"],"mappings":";;;;;;AAYA,SAAwB,EACtB,GACA,GACA;CACA,IAAM,CAAC,GAAQ,KAAa,GAAgC,EACtD,CAAC,GAAO,KAAY,GAAmD,EACvE,EAAE,mBAAgB,GAAmB,EAEtC,IAAL,yBAAA,GAAA;SACE,EAAA,UAAU,WACV,EAAA,YAAY,YACZ,EAAA,QAAQ,SACR,EAAA,UAAU,WACV,EAAA,OAAO,QACP,EAAA,QAAQ;MACT;AAiDD,QA/CA,QAAgB;AA4Cd,eA3C4B;AAC1B,OAAI;IACF,IAAM,IAAmB,EACvB,EAAgB,OAChB,EACD,EAKK,KAHH,GAAmB,YAAa,aAAa,KAAK,KACjD,MAAO,EAAI,OAAO,GACnB,IAAI,EAAE,EAC6B,QACpC,MAAK,KAAK,QAAQ,MAAM,KAAA,EACzB;AACD,QAAI,EAAmB,WAAW,GAAG;AAEnC,KADA,EAAU,KAAA,EAAU,EACpB,EAAS,KAAA,EAAU;AACnB;;IAgBF,IAAM,IAAQ,MAAM,EAAS;KAL3B,oBAAoB;KACpB,sBAAsB;KACtB,6BAA6B;KAC7B,gBAXA,EAAmB,KAAI,OACd;MACL,mBAAmB;MACnB,qBAAqB,EAAwB;MAC7C,cAAc;MACf,EAMa;KAEW,EAAkB,EAAY;AAK3D,IAJA,EAAS,KAAA,EAAU,EAInB,EAHiB,EAAM,eACpB,QAAO,MAAO,EAAI,iBAAiB,KAAA,EAAU,CAC7C,KAAI,MAAO,EAAI,aACR,CAAS;YACZ,GAAG;AAEV,IADA,EAAS,EAAE,EACX,EAAU,KAAA,EAAU;;MAGf;IACR;EAAC;EAAU;EAAmB;EAAY,CAAC,EAEvC;EAAE;EAAQ;EAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useGetInfoFromIds.js","names":[],"sources":["../../../src/utils/hooks/useGetInfoFromIds.ts"],"sourcesContent":["import {\n getEntityHeaders,\n getEvaluations,\n getGroupHeadersBatch,\n} from '@/synapse-client'\nimport {\n EntityHeader,\n Evaluation,\n Reference,\n ReferenceList,\n UserGroupHeader,\n} from '@sage-bionetworks/synapse-types'\nimport { chunk, uniq, without } from 'lodash-es'\nimport { useEffect, useState } from 'react'\nimport useDeepCompareEffect from 'use-deep-compare-effect'\nimport { useSynapseContext } from '../context/SynapseContext'\nimport { SynapseConstants } from '../index'\n\nexport type UseGetInfoFromIdsProps<\n T extends EntityHeader | UserGroupHeader | Evaluation,\n THookType = T extends EntityHeader\n ? 'ENTITY_HEADER'\n : T extends UserGroupHeader\n ? 'USER_PROFILE'\n : T extends Evaluation\n ? 'EVALUATION_QUEUE'\n : never,\n> = {\n ids: string[]\n type: THookType\n}\n\ntype LookupRequestType = string | Reference\n\nconst UserGroupHeaderTemplate: UserGroupHeader = {\n ownerId: '', // A foreign key to the ID of the 'principal' object for the user\n firstName: 'Unknown', // This person's given name (forename)\n lastName: 'Unknown', // This person's family name (surname)\n userName: 'Unknown', // A name chosen by the user that uniquely identifies them\n isIndividual: false,\n}\n\nconst entityHeaderTemplate: EntityHeader = {\n name: 'Unknown', //\tThe name of the entity\n id: 'unknown', //\tThe id of the entity\n type: 'org.sagebionetworks.repo.model.FileEntity', //\tThe type of the entity\n versionNumber: 0, //\tThe version number of the entity\n versionLabel: 'placeholder', //\tThe user defined version label of the entity\n benefactorId: 0, //\tThe ID of the entity that this Entity's ACL is inherited from.\n createdOn: 'null', //\tThe date this entity was created.\n modifiedOn: 'null', //\tThe date this entity was last modified.\n createdBy: 'null', //\tThe ID of the user that created this entity.\n modifiedBy: 'null', //\tThe ID of the user that last modified this entity.\n isLatestVersion: true, // If this version is the latest version of the entity\n}\n\nconst evaluationTemplate: Evaluation = {\n id: 'unknown', // The unique immutable ID for this Evaluation.\n etag: 'Unknown', // Synapse employs an Optimistic Concurrency Control (OCC) scheme to handle concurrent updates. The eTag changes every time an Evaluation is updated; it is used to detect when a client's copy of an Evaluation is out-of-date.\n name: 'Unknown', // The name of this Evaluation\n description: 'Unknown', // A text description of this Evaluation.\n ownerId: 'null', // The ID of the Synapse user who created this Evaluation.\n createdOn: 'null', //\tThe date on which Evaluation was created.\n contentSource: 'Unknown', // The Synapse ID of the Entity to which this Evaluation belongs, e.g. a reference to a Synapse project.\n submissionInstructionsMessage: 'Unknown', // Message to display to users detailing acceptable formatting for Submissions to this Evaluation.\n submissionReceiptMessage: 'Unknown', // Message to display to users upon successful submission to this Evaluation.\n}\n\nconst getEntityHeaderItems = async (\n lookupList: ReferenceList,\n accessToken: string | undefined,\n): Promise<EntityHeader[]> => {\n const newData = await getEntityHeaders(lookupList, accessToken)\n const notFound = lookupList.filter(\n item => newData.results.map(item => item.id).indexOf(item.targetId) === -1,\n )\n const notFoundPlaceholders = notFound.map(item => ({\n ...entityHeaderTemplate,\n id: item.targetId,\n name: `${item.targetId}`,\n }))\n\n return [...newData.results, ...notFoundPlaceholders]\n}\n\nconst getUserGroupHeaderItems = async (\n lookupList: string[],\n accessToken: string | undefined,\n): Promise<UserGroupHeader[]> => {\n const newData = (await getGroupHeadersBatch(lookupList, accessToken)).children\n const notFound = lookupList.filter(\n item => newData.map(item => item.ownerId).indexOf(item) === -1,\n )\n const notFoundPlaceholders = notFound.map(item => ({\n ...UserGroupHeaderTemplate,\n ownerId: item,\n name: `Unknown User (${item})`,\n }))\n\n return [...newData, ...notFoundPlaceholders]\n}\n\nconst getEvaluationItems = async (\n lookupList: string[],\n accessToken: string | undefined,\n): Promise<Evaluation[]> => {\n const newData = await getEvaluations(\n { evaluationIds: lookupList },\n accessToken,\n )\n const notFound = lookupList.filter(\n item => newData.results.map(item => item.id).indexOf(item) === -1,\n )\n const notFoundPlaceholders = notFound.map(item => ({\n ...evaluationTemplate,\n id: item,\n name: item,\n }))\n\n return [...newData.results, ...notFoundPlaceholders]\n}\n\n/**\n * React hook to get user profiles or entities or evaluation queues. Utilizes a custom cache in sessionStorage.\n *\n * For fetching just one entity or usergroup, see useGetEntity/useGetUserGroupHeader hooks powered by react-query\n * @returns\n */\nexport default function useGetInfoFromIds<\n T extends EntityHeader | UserGroupHeader | Evaluation,\n>(props: UseGetInfoFromIdsProps<T>): T[] {\n const { ids, type } = props\n const { accessToken } = useSynapseContext()\n\n const [data, setData] = useState<Array<T>>([])\n\n const idKey = (type === 'USER_PROFILE' ? 'ownerId' : 'id') as keyof T\n\n const getStorageKey = (type: UseGetInfoFromIdsProps<T>['type']) => {\n switch (type) {\n case 'USER_PROFILE':\n return SynapseConstants.USER_PROFILE_STORAGE_KEY\n case 'ENTITY_HEADER':\n return SynapseConstants.ENTITY_HEADER_STORAGE_KEY\n case 'EVALUATION_QUEUE':\n return SynapseConstants.EVALUATIONS_STORAGE_KEY\n default:\n return ''\n }\n }\n const storageKey: string = getStorageKey(type)\n\n // look at current list of data, see if incoming ids has new data,\n // if so grab those ids\n const curList = data.map(el => el[idKey]) as string[]\n const incomingList = ids.filter(el => el !== SynapseConstants.VALUE_NOT_SET)\n const newValues = uniq(without(incomingList, ...curList))\n\n useEffect(() => {\n const saveToSessionStorage = (data: T[]) => {\n if (!data.length) {\n return\n }\n //get what's there\n const dataInStorage = sessionStorage.getItem(storageKey)\n try {\n const dataInStorageAsObjectArr: T[] = dataInStorage\n ? JSON.parse(dataInStorage)\n : []\n //get an array of ids for items already in storage\n const ids = dataInStorageAsObjectArr.map(item => item[idKey])\n //push all the new data if ids are new\n for (const dataObject of data) {\n if (!ids.includes(dataObject[idKey])) {\n dataInStorageAsObjectArr.push(dataObject)\n }\n }\n sessionStorage.setItem(\n storageKey,\n JSON.stringify(dataInStorageAsObjectArr),\n )\n } catch (e) {\n sessionStorage.setItem(storageKey, JSON.stringify(data))\n }\n }\n saveToSessionStorage(data)\n }, [data, idKey, storageKey])\n\n // Alina TODO: check if the items are already in Local Storage before making server call.\n\n // Michael TODO: There's a bug where the data held in useGetInfoFromIds will be stale if the user token changes,\n // this can be solved by using the useCompare hook on the token to track when it changes\n useDeepCompareEffect(() => {\n let isCancelled = false\n const getData = async () => {\n if (newValues.length > 0) {\n try {\n const newIds = Array.from<string>(newValues)\n const newReferences: LookupRequestType[] =\n type === 'ENTITY_HEADER'\n ? newIds.map(el => ({ targetId: el }))\n : newIds\n const newReferencesChunks = chunk(newReferences, 45)\n const totalData: T[] = []\n for (const newReferences of newReferencesChunks) {\n let newData: T[] = []\n switch (type) {\n case 'USER_PROFILE':\n newData = (await getUserGroupHeaderItems(\n newReferences as string[],\n accessToken,\n )) as T[]\n break\n case 'ENTITY_HEADER':\n newData = (await getEntityHeaderItems(\n newReferences as ReferenceList,\n accessToken,\n )) as T[]\n break\n case 'EVALUATION_QUEUE':\n newData = (await getEvaluationItems(\n newReferences as string[],\n accessToken,\n )) as T[]\n break\n }\n totalData.push(...newData)\n }\n if (!isCancelled) {\n setData(oldData => oldData.concat(...totalData))\n }\n } catch (error) {\n console.error('Error on data retrieval', error)\n }\n }\n }\n getData()\n return () => {\n isCancelled = true\n }\n }, [accessToken, type, newValues])\n return data\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useGetInfoFromIds.js","names":[],"sources":["../../../src/utils/hooks/useGetInfoFromIds.ts"],"sourcesContent":["import {\n getEntityHeaders,\n getEvaluations,\n getGroupHeadersBatch,\n} from '@/synapse-client'\nimport {\n EntityHeader,\n Evaluation,\n Reference,\n ReferenceList,\n UserGroupHeader,\n} from '@sage-bionetworks/synapse-types'\nimport { chunk, uniq, without } from 'lodash-es'\nimport { useEffect, useState } from 'react'\nimport useDeepCompareEffect from 'use-deep-compare-effect'\nimport { useSynapseContext } from '../context/SynapseContext'\nimport { SynapseConstants } from '../index'\n\nexport type UseGetInfoFromIdsProps<\n T extends EntityHeader | UserGroupHeader | Evaluation,\n THookType = T extends EntityHeader\n ? 'ENTITY_HEADER'\n : T extends UserGroupHeader\n ? 'USER_PROFILE'\n : T extends Evaluation\n ? 'EVALUATION_QUEUE'\n : never,\n> = {\n ids: string[]\n type: THookType\n}\n\ntype LookupRequestType = string | Reference\n\nconst UserGroupHeaderTemplate: UserGroupHeader = {\n ownerId: '', // A foreign key to the ID of the 'principal' object for the user\n firstName: 'Unknown', // This person's given name (forename)\n lastName: 'Unknown', // This person's family name (surname)\n userName: 'Unknown', // A name chosen by the user that uniquely identifies them\n isIndividual: false,\n}\n\nconst entityHeaderTemplate: EntityHeader = {\n name: 'Unknown', //\tThe name of the entity\n id: 'unknown', //\tThe id of the entity\n type: 'org.sagebionetworks.repo.model.FileEntity', //\tThe type of the entity\n versionNumber: 0, //\tThe version number of the entity\n versionLabel: 'placeholder', //\tThe user defined version label of the entity\n benefactorId: 0, //\tThe ID of the entity that this Entity's ACL is inherited from.\n createdOn: 'null', //\tThe date this entity was created.\n modifiedOn: 'null', //\tThe date this entity was last modified.\n createdBy: 'null', //\tThe ID of the user that created this entity.\n modifiedBy: 'null', //\tThe ID of the user that last modified this entity.\n isLatestVersion: true, // If this version is the latest version of the entity\n}\n\nconst evaluationTemplate: Evaluation = {\n id: 'unknown', // The unique immutable ID for this Evaluation.\n etag: 'Unknown', // Synapse employs an Optimistic Concurrency Control (OCC) scheme to handle concurrent updates. The eTag changes every time an Evaluation is updated; it is used to detect when a client's copy of an Evaluation is out-of-date.\n name: 'Unknown', // The name of this Evaluation\n description: 'Unknown', // A text description of this Evaluation.\n ownerId: 'null', // The ID of the Synapse user who created this Evaluation.\n createdOn: 'null', //\tThe date on which Evaluation was created.\n contentSource: 'Unknown', // The Synapse ID of the Entity to which this Evaluation belongs, e.g. a reference to a Synapse project.\n submissionInstructionsMessage: 'Unknown', // Message to display to users detailing acceptable formatting for Submissions to this Evaluation.\n submissionReceiptMessage: 'Unknown', // Message to display to users upon successful submission to this Evaluation.\n}\n\nconst getEntityHeaderItems = async (\n lookupList: ReferenceList,\n accessToken: string | undefined,\n): Promise<EntityHeader[]> => {\n const newData = await getEntityHeaders(lookupList, accessToken)\n const notFound = lookupList.filter(\n item => newData.results.map(item => item.id).indexOf(item.targetId) === -1,\n )\n const notFoundPlaceholders = notFound.map(item => ({\n ...entityHeaderTemplate,\n id: item.targetId,\n name: `${item.targetId}`,\n }))\n\n return [...newData.results, ...notFoundPlaceholders]\n}\n\nconst getUserGroupHeaderItems = async (\n lookupList: string[],\n accessToken: string | undefined,\n): Promise<UserGroupHeader[]> => {\n const newData = (await getGroupHeadersBatch(lookupList, accessToken)).children\n const notFound = lookupList.filter(\n item => newData.map(item => item.ownerId).indexOf(item) === -1,\n )\n const notFoundPlaceholders = notFound.map(item => ({\n ...UserGroupHeaderTemplate,\n ownerId: item,\n name: `Unknown User (${item})`,\n }))\n\n return [...newData, ...notFoundPlaceholders]\n}\n\nconst getEvaluationItems = async (\n lookupList: string[],\n accessToken: string | undefined,\n): Promise<Evaluation[]> => {\n const newData = await getEvaluations(\n { evaluationIds: lookupList },\n accessToken,\n )\n const notFound = lookupList.filter(\n item => newData.results.map(item => item.id).indexOf(item) === -1,\n )\n const notFoundPlaceholders = notFound.map(item => ({\n ...evaluationTemplate,\n id: item,\n name: item,\n }))\n\n return [...newData.results, ...notFoundPlaceholders]\n}\n\n/**\n * React hook to get user profiles or entities or evaluation queues. Utilizes a custom cache in sessionStorage.\n *\n * For fetching just one entity or usergroup, see useGetEntity/useGetUserGroupHeader hooks powered by react-query\n * @returns\n */\nexport default function useGetInfoFromIds<\n T extends EntityHeader | UserGroupHeader | Evaluation,\n>(props: UseGetInfoFromIdsProps<T>): T[] {\n const { ids, type } = props\n const { accessToken } = useSynapseContext()\n\n const [data, setData] = useState<Array<T>>([])\n\n const idKey = (type === 'USER_PROFILE' ? 'ownerId' : 'id') as keyof T\n\n const getStorageKey = (type: UseGetInfoFromIdsProps<T>['type']) => {\n switch (type) {\n case 'USER_PROFILE':\n return SynapseConstants.USER_PROFILE_STORAGE_KEY\n case 'ENTITY_HEADER':\n return SynapseConstants.ENTITY_HEADER_STORAGE_KEY\n case 'EVALUATION_QUEUE':\n return SynapseConstants.EVALUATIONS_STORAGE_KEY\n default:\n return ''\n }\n }\n const storageKey: string = getStorageKey(type)\n\n // look at current list of data, see if incoming ids has new data,\n // if so grab those ids\n const curList = data.map(el => el[idKey]) as string[]\n const incomingList = ids.filter(el => el !== SynapseConstants.VALUE_NOT_SET)\n const newValues = uniq(without(incomingList, ...curList))\n\n useEffect(() => {\n const saveToSessionStorage = (data: T[]) => {\n if (!data.length) {\n return\n }\n //get what's there\n const dataInStorage = sessionStorage.getItem(storageKey)\n try {\n const dataInStorageAsObjectArr: T[] = dataInStorage\n ? JSON.parse(dataInStorage)\n : []\n //get an array of ids for items already in storage\n const ids = dataInStorageAsObjectArr.map(item => item[idKey])\n //push all the new data if ids are new\n for (const dataObject of data) {\n if (!ids.includes(dataObject[idKey])) {\n dataInStorageAsObjectArr.push(dataObject)\n }\n }\n sessionStorage.setItem(\n storageKey,\n JSON.stringify(dataInStorageAsObjectArr),\n )\n } catch (e) {\n sessionStorage.setItem(storageKey, JSON.stringify(data))\n }\n }\n saveToSessionStorage(data)\n }, [data, idKey, storageKey])\n\n // Alina TODO: check if the items are already in Local Storage before making server call.\n\n // Michael TODO: There's a bug where the data held in useGetInfoFromIds will be stale if the user token changes,\n // this can be solved by using the useCompare hook on the token to track when it changes\n useDeepCompareEffect(() => {\n let isCancelled = false\n const getData = async () => {\n if (newValues.length > 0) {\n try {\n const newIds = Array.from<string>(newValues)\n const newReferences: LookupRequestType[] =\n type === 'ENTITY_HEADER'\n ? newIds.map(el => ({ targetId: el }))\n : newIds\n const newReferencesChunks = chunk(newReferences, 45)\n const totalData: T[] = []\n for (const newReferences of newReferencesChunks) {\n let newData: T[] = []\n switch (type) {\n case 'USER_PROFILE':\n newData = (await getUserGroupHeaderItems(\n newReferences as string[],\n accessToken,\n )) as T[]\n break\n case 'ENTITY_HEADER':\n newData = (await getEntityHeaderItems(\n newReferences as ReferenceList,\n accessToken,\n )) as T[]\n break\n case 'EVALUATION_QUEUE':\n newData = (await getEvaluationItems(\n newReferences as string[],\n accessToken,\n )) as T[]\n break\n }\n totalData.push(...newData)\n }\n if (!isCancelled) {\n setData(oldData => oldData.concat(...totalData))\n }\n } catch (error) {\n console.error('Error on data retrieval', error)\n }\n }\n }\n getData()\n return () => {\n isCancelled = true\n }\n }, [accessToken, type, newValues])\n return data\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useImageUrlUtils.js","names":[],"sources":["../../../src/utils/hooks/useImageUrlUtils.ts"],"sourcesContent":["import { useGetStablePresignedUrl } from '@/synapse-queries'\nimport {\n FileHandleAssociateType,\n FileHandleAssociation,\n} from '@sage-bionetworks/synapse-types'\n\nexport const useImageUrl = (fileId: string, entityId: string) => {\n const fha: FileHandleAssociation = {\n associateObjectId: entityId,\n associateObjectType: FileHandleAssociateType.TableEntity,\n fileHandleId: fileId || '',\n }\n const stablePresignedUrl = useGetStablePresignedUrl(fha, false, {\n enabled: !!fileId,\n })\n const dataUrl = stablePresignedUrl?.dataUrl\n\n return dataUrl\n}\n"],"mappings":";;;;AAMA,IAAa,KAAe,GAAgB,MAMf,
|
|
1
|
+
{"version":3,"file":"useImageUrlUtils.js","names":[],"sources":["../../../src/utils/hooks/useImageUrlUtils.ts"],"sourcesContent":["import { useGetStablePresignedUrl } from '@/synapse-queries'\nimport {\n FileHandleAssociateType,\n FileHandleAssociation,\n} from '@sage-bionetworks/synapse-types'\n\nexport const useImageUrl = (fileId: string, entityId: string) => {\n const fha: FileHandleAssociation = {\n associateObjectId: entityId,\n associateObjectType: FileHandleAssociateType.TableEntity,\n fileHandleId: fileId || '',\n }\n const stablePresignedUrl = useGetStablePresignedUrl(fha, false, {\n enabled: !!fileId,\n })\n const dataUrl = stablePresignedUrl?.dataUrl\n\n return dataUrl\n}\n"],"mappings":";;;;AAMA,IAAa,KAAe,GAAgB,MAMf,EAAyB;CAJlD,mBAAmB;CACnB,qBAAqB,EAAwB;CAC7C,cAAc,KAAU;CAE0B,EAAK,IAAO,EAC9D,SAAS,CAAC,CAAC,GACZ,CACe,EAAoB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useImmutableTableQuery.js","names":[],"sources":["../../../../src/utils/hooks/useImmutableTableQuery/useImmutableTableQuery.ts"],"sourcesContent":["import { UniqueFacetIdentifier } from '@/utils/types/UniqueFacetIdentifier'\nimport {\n QueryBundleRequest,\n QueryFilter,\n} from '@sage-bionetworks/synapse-types'\nimport { cloneDeep, isEqual } from 'lodash-es'\nimport * as React from 'react'\nimport { useCallback, useEffect, useMemo } from 'react'\nimport { ReadonlyDeep } from 'type-fest'\nimport useDeepCompareEffect from 'use-deep-compare-effect'\nimport * as DeepLinkingUtils from '../../functions/deepLinkingUtils'\nimport { removeEmptyQueryParams } from '../../functions/queryUtils'\nimport { parseEntityIdAndVersionFromSqlStatement } from '../../functions/SqlFunctions'\nimport { DEFAULT_PAGE_SIZE } from '../../SynapseConstants'\nimport {\n QueryChangeCommitOptions,\n useTableQueryReducer,\n} from './useTableQueryReducer'\n\nexport type ImmutableTableQueryResult = {\n /** The ID of the table parsed from the SQL query */\n entityId?: string\n /** The version number of the table parsed from the SQL query */\n versionNumber?: number\n /** The current query request, which is passed on to the server for results */\n currentQueryRequest: ReadonlyDeep<QueryBundleRequest>\n /** The next (uncommitted) query request. This will become the current query request when commitChanges is called, or the configured debounced timer elapses. */\n nextQueryRequest: ReadonlyDeep<QueryBundleRequest>\n /** Resets the debounce timer to delay committing changes in `nextQueryRequest` */\n resetDebounceTimer: () => void\n /** Update the currentQueryRequest to be the nextQueryRequest */\n commitChanges: () => void\n getInitQueryRequest: () => QueryBundleRequest\n getCurrentQueryRequest: () => QueryBundleRequest\n setQuery: (\n queryRequest: React.SetStateAction<QueryBundleRequest>,\n commitOptions?: QueryChangeCommitOptions,\n ) => void\n pageSize: number\n /** The current page of results. The first page is `1` */\n currentPage: number\n setPageSize: (pageSize: number) => void\n /** pageNumber is 1-indexed */\n goToPage: (pageNumber: number) => void\n /** Resets the query to the initial state, clearing all user-specified filters */\n resetQuery: () => void\n addValueToSelectedFacet: (\n facet: UniqueFacetIdentifier,\n value: string,\n commitOptions?: QueryChangeCommitOptions,\n ) => void\n /** Removes a particular selected facet from the query */\n removeSelectedFacet: (\n facet: UniqueFacetIdentifier | UniqueFacetIdentifier[],\n ) => void\n /** Removes a particular value from a selected facet. If the value is the last value in the FacetColumnRequest, the selected facet will be removed. */\n removeValueFromSelectedFacet: (\n facet: UniqueFacetIdentifier,\n value: string,\n commitOptions?: QueryChangeCommitOptions,\n ) => void\n setRangeFacetValue: (\n facet: UniqueFacetIdentifier,\n min?: string,\n max?: string,\n commitOptions?: QueryChangeCommitOptions,\n ) => void\n /** Removes a particular QueryFilter from the query */\n removeQueryFilter: (filter: QueryFilter) => void\n /** Removes a particular value from a QueryFilter. If the value is the last value in the filter, the filter will be removed. */\n removeValueFromQueryFilter: (filter: QueryFilter, value: string) => void\n /** If `requireConfirmationOnChange` is true, this will become true when a function that triggers a query change is invoked. */\n isConfirmingChange: boolean\n /** If `isConfirmingChange` is true, invoke this function to complete the query change */\n onConfirmChange: () => void\n /** If `isConfirmingChange` is true, invoke this function to cancel the query change */\n onCancelChange: () => void\n\n /**\n * TODO: This hook could handle all potential query transformations, such as\n * - addFacetFilter, removeFacetFilter, clearFacetFilters\n * - addAdditionalFilter, remove..., clear...\n *\n * This could be preferable to allowing any QueryContext subscriber to arbitrarily update the query with `setQuery`\n * because we could uniformly handle all complex stateful logic in this hook\n */\n}\n\nexport type UseImmutableTableQueryOptions = {\n /** The initial table query request object */\n initQueryRequest: QueryBundleRequest\n /** Whether the URL should update when the query is modified. */\n shouldDeepLink?: boolean\n /** Unique index for the component on the page so URL updates do not conflict between table query components */\n componentIndex?: number\n /** Callback invoked when the query is modified */\n onQueryChange?: (newQueryJson: string) => void\n /** Whether to require explicit user confirmation before changing the query. */\n requireConfirmationOnChange?: boolean\n}\n\n// When changing the query with the debounce option, the amount of time to wait for additional debounced changes before updating the query\nexport const DEBOUNCE_DELAY_MS = 750\n\n/**\n * Utility to synchronize the URL with the current query request. Synchronization only occurs if `shouldDeepLink` is true.\n * @param shouldDeepLink whether the query should be synchronized with the URL\n * @param componentIndex the index of the component to synchronize with the URL - essential if multiple components to synchronize are on the page\n * @param setQuery - callback used to update the current query\n * @param initQueryRequest - the initial query request passed via props\n * @param currentQueryRequest - the query request that is currently used\n */\nfunction useSynchronizeQueryWithUrl(\n shouldDeepLink: boolean,\n componentIndex: number,\n setQuery: (\n queryRequest: React.SetStateAction<QueryBundleRequest>,\n commitOptions?: QueryChangeCommitOptions,\n ) => void,\n initQueryRequest: QueryBundleRequest,\n currentQueryRequest: QueryBundleRequest,\n) {\n /**\n * Inspect the URL on mount to see if we have a particular query request that we must show.\n */\n useEffect(() => {\n // Only run this effect if deep linking is enabled\n if (shouldDeepLink) {\n DeepLinkingUtils.getQueryRequestFromLink(\n componentIndex,\n initQueryRequest.query,\n ).then(queryRequestFromLink => {\n if (queryRequestFromLink && queryRequestFromLink.query) {\n setQuery(prevState => ({\n ...prevState,\n ...queryRequestFromLink,\n query: {\n ...prevState.query,\n ...queryRequestFromLink.query,\n },\n }))\n }\n })\n }\n // should only run on mount, or if the component index changes\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [componentIndex])\n\n // If `shouldDeepLink` is true, synchronize the URL\n useEffect(() => {\n if (shouldDeepLink) {\n if (isEqual(initQueryRequest, currentQueryRequest)) {\n void DeepLinkingUtils.updateUrlWithNewSearchParam(\n 'qw',\n componentIndex,\n null,\n null,\n ).catch(error => {\n console.error('Failed to update URL with search param:', error)\n })\n } else {\n void DeepLinkingUtils.updateUrlWithNewSearchParam(\n 'qw',\n componentIndex,\n currentQueryRequest.query,\n initQueryRequest.query,\n ).catch(error => {\n console.error('Failed to update URL with search param:', error)\n })\n }\n }\n // Clean up the URL param when this component unmounts or deep linking is disabled\n return () => {\n if (shouldDeepLink) {\n DeepLinkingUtils.updateUrlWithNewSearchParam(\n 'qw',\n componentIndex,\n null,\n initQueryRequest.query,\n )\n }\n }\n }, [componentIndex, currentQueryRequest, initQueryRequest, shouldDeepLink])\n}\n\n/**\n * Custom hook that maintains and manages the state of a Synapse Table query.\n * @param options\n * @returns\n */\nexport default function useImmutableTableQuery(\n options: UseImmutableTableQueryOptions,\n): ImmutableTableQueryResult {\n const {\n initQueryRequest: initQueryRequestFromProps,\n componentIndex = 0,\n shouldDeepLink = false,\n onQueryChange,\n requireConfirmationOnChange = false,\n } = options\n\n const initQueryRequest = useMemo(() => {\n const request = cloneDeep(initQueryRequestFromProps)\n request.query = removeEmptyQueryParams(request.query)\n return request\n }, [initQueryRequestFromProps])\n\n const {\n currentQueryRequest,\n nextQueryRequest,\n isConfirmingChange,\n dispatch,\n } = useTableQueryReducer(\n initQueryRequest,\n requireConfirmationOnChange,\n onQueryChange,\n )\n\n const onConfirmChange = useCallback(() => {\n dispatch({ type: 'confirmChanges' })\n }, [dispatch])\n\n /**\n * Pass down a deep clone (so no side effects on the child's part) of the\n * current query request\n *\n * @returns\n * @memberof QueryWrapper\n */\n const getCurrentQueryRequest = useCallback(() => {\n return cloneDeep(currentQueryRequest)\n }, [currentQueryRequest])\n\n /**\n * Pass down a deep clone (so no side effects on the child's part) of the\n * first query request made\n *\n * @returns\n * @memberof QueryWrapper\n */\n const getInitQueryRequest = useCallback((): QueryBundleRequest => {\n return cloneDeep(initQueryRequest)\n }, [initQueryRequest])\n\n /**\n * Execute the given query request, updating all the data in the QueryContext to match the new query\n * @param {*} queryRequest Query request as specified by\n * https://rest-docs.synapse.org/rest/org/sagebionetworks/repo/model/table/Query.html\n */\n const setQuery: ImmutableTableQueryResult['setQuery'] = useCallback(\n (\n queryRequest: React.SetStateAction<QueryBundleRequest>,\n commitOptions?: QueryChangeCommitOptions,\n ): void => {\n dispatch({\n type: 'setQuery',\n queryOrUpdater: queryRequest,\n commitOptions,\n })\n },\n [dispatch],\n )\n\n useSynchronizeQueryWithUrl(\n shouldDeepLink,\n componentIndex,\n setQuery,\n initQueryRequest,\n currentQueryRequest,\n )\n\n const onCancelChange = useCallback(() => {\n dispatch({ type: 'cancelChanges' })\n }, [dispatch])\n\n const { entityId, versionNumber } = useMemo(\n () =>\n parseEntityIdAndVersionFromSqlStatement(currentQueryRequest.query.sql),\n [currentQueryRequest.query.sql],\n )\n\n const pageSize = currentQueryRequest.query.limit ?? DEFAULT_PAGE_SIZE\n const currentPage = Math.ceil(\n ((currentQueryRequest.query.offset ?? 0) + Number(pageSize)) / pageSize,\n )\n\n const setPageSize = useCallback(\n (pageSize: number) => {\n dispatch({ type: 'setPageSize', pageSize })\n },\n [dispatch],\n )\n\n const goToPage = useCallback(\n (pageNumber: number) => {\n dispatch({ type: 'goToPage', pageNumber })\n },\n [dispatch],\n )\n\n const resetQuery = useCallback(() => {\n dispatch({\n type: 'resetQuery',\n })\n }, [dispatch])\n\n /* If the initial query changes, then reset the query to match the new prop */\n useDeepCompareEffect(() => {\n if (currentQueryRequest != initQueryRequest) {\n resetQuery()\n }\n }, [initQueryRequest])\n\n const addValueToSelectedFacet = useCallback(\n (\n facet: UniqueFacetIdentifier,\n value: string,\n commitOptions?: QueryChangeCommitOptions,\n ) => {\n dispatch({\n type: 'addValueToSelectedFacet',\n facet: facet,\n value: value,\n commitOptions: commitOptions,\n })\n },\n [dispatch],\n )\n\n const setRangeFacetValue = useCallback(\n (\n facet: UniqueFacetIdentifier,\n min?: string,\n max?: string,\n commitOptions?: QueryChangeCommitOptions,\n ) => {\n dispatch({\n type: 'setRangeFacetValue',\n facet,\n min,\n max,\n commitOptions,\n })\n },\n [dispatch],\n )\n\n const removeSelectedFacet = useCallback(\n (facetsToRemove: UniqueFacetIdentifier | UniqueFacetIdentifier[]) => {\n dispatch({\n type: 'removeSelectedFacet',\n facetsToRemove: facetsToRemove,\n })\n },\n [dispatch],\n )\n\n const removeValueFromSelectedFacet = useCallback(\n (\n facet: UniqueFacetIdentifier,\n value: string,\n commitOptions?: QueryChangeCommitOptions,\n ) => {\n dispatch({\n type: 'removeValueFromSelectedFacet',\n facet,\n value,\n commitOptions,\n })\n },\n [dispatch],\n )\n\n const removeQueryFilter = useCallback(\n (queryFilter: QueryFilter) => {\n dispatch({\n type: 'removeQueryFilter',\n queryFilter,\n })\n },\n [dispatch],\n )\n\n const removeValueFromQueryFilter = useCallback(\n (queryFilter: QueryFilter, value: string) => {\n dispatch({\n type: 'removeValueFromQueryFilter',\n queryFilter,\n value,\n })\n },\n [dispatch],\n )\n const commitChanges = useCallback(() => {\n dispatch({ type: 'commitChanges' })\n }, [dispatch])\n\n const resetDebounceTimer = useCallback(() => {\n dispatch({ type: 'resetDebounce' })\n }, [dispatch])\n\n return {\n entityId,\n commitChanges,\n resetDebounceTimer,\n currentQueryRequest,\n nextQueryRequest,\n versionNumber,\n getInitQueryRequest,\n getCurrentQueryRequest,\n setQuery,\n pageSize,\n currentPage,\n setPageSize,\n goToPage,\n resetQuery,\n removeSelectedFacet,\n removeValueFromSelectedFacet,\n removeQueryFilter,\n removeValueFromQueryFilter,\n isConfirmingChange,\n onConfirmChange,\n onCancelChange,\n addValueToSelectedFacet,\n setRangeFacetValue,\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useImmutableTableQuery.js","names":[],"sources":["../../../../src/utils/hooks/useImmutableTableQuery/useImmutableTableQuery.ts"],"sourcesContent":["import { UniqueFacetIdentifier } from '@/utils/types/UniqueFacetIdentifier'\nimport {\n QueryBundleRequest,\n QueryFilter,\n} from '@sage-bionetworks/synapse-types'\nimport { cloneDeep, isEqual } from 'lodash-es'\nimport * as React from 'react'\nimport { useCallback, useEffect, useMemo } from 'react'\nimport { ReadonlyDeep } from 'type-fest'\nimport useDeepCompareEffect from 'use-deep-compare-effect'\nimport * as DeepLinkingUtils from '../../functions/deepLinkingUtils'\nimport { removeEmptyQueryParams } from '../../functions/queryUtils'\nimport { parseEntityIdAndVersionFromSqlStatement } from '../../functions/SqlFunctions'\nimport { DEFAULT_PAGE_SIZE } from '../../SynapseConstants'\nimport {\n QueryChangeCommitOptions,\n useTableQueryReducer,\n} from './useTableQueryReducer'\n\nexport type ImmutableTableQueryResult = {\n /** The ID of the table parsed from the SQL query */\n entityId?: string\n /** The version number of the table parsed from the SQL query */\n versionNumber?: number\n /** The current query request, which is passed on to the server for results */\n currentQueryRequest: ReadonlyDeep<QueryBundleRequest>\n /** The next (uncommitted) query request. This will become the current query request when commitChanges is called, or the configured debounced timer elapses. */\n nextQueryRequest: ReadonlyDeep<QueryBundleRequest>\n /** Resets the debounce timer to delay committing changes in `nextQueryRequest` */\n resetDebounceTimer: () => void\n /** Update the currentQueryRequest to be the nextQueryRequest */\n commitChanges: () => void\n getInitQueryRequest: () => QueryBundleRequest\n getCurrentQueryRequest: () => QueryBundleRequest\n setQuery: (\n queryRequest: React.SetStateAction<QueryBundleRequest>,\n commitOptions?: QueryChangeCommitOptions,\n ) => void\n pageSize: number\n /** The current page of results. The first page is `1` */\n currentPage: number\n setPageSize: (pageSize: number) => void\n /** pageNumber is 1-indexed */\n goToPage: (pageNumber: number) => void\n /** Resets the query to the initial state, clearing all user-specified filters */\n resetQuery: () => void\n addValueToSelectedFacet: (\n facet: UniqueFacetIdentifier,\n value: string,\n commitOptions?: QueryChangeCommitOptions,\n ) => void\n /** Removes a particular selected facet from the query */\n removeSelectedFacet: (\n facet: UniqueFacetIdentifier | UniqueFacetIdentifier[],\n ) => void\n /** Removes a particular value from a selected facet. If the value is the last value in the FacetColumnRequest, the selected facet will be removed. */\n removeValueFromSelectedFacet: (\n facet: UniqueFacetIdentifier,\n value: string,\n commitOptions?: QueryChangeCommitOptions,\n ) => void\n setRangeFacetValue: (\n facet: UniqueFacetIdentifier,\n min?: string,\n max?: string,\n commitOptions?: QueryChangeCommitOptions,\n ) => void\n /** Removes a particular QueryFilter from the query */\n removeQueryFilter: (filter: QueryFilter) => void\n /** Removes a particular value from a QueryFilter. If the value is the last value in the filter, the filter will be removed. */\n removeValueFromQueryFilter: (filter: QueryFilter, value: string) => void\n /** If `requireConfirmationOnChange` is true, this will become true when a function that triggers a query change is invoked. */\n isConfirmingChange: boolean\n /** If `isConfirmingChange` is true, invoke this function to complete the query change */\n onConfirmChange: () => void\n /** If `isConfirmingChange` is true, invoke this function to cancel the query change */\n onCancelChange: () => void\n\n /**\n * TODO: This hook could handle all potential query transformations, such as\n * - addFacetFilter, removeFacetFilter, clearFacetFilters\n * - addAdditionalFilter, remove..., clear...\n *\n * This could be preferable to allowing any QueryContext subscriber to arbitrarily update the query with `setQuery`\n * because we could uniformly handle all complex stateful logic in this hook\n */\n}\n\nexport type UseImmutableTableQueryOptions = {\n /** The initial table query request object */\n initQueryRequest: QueryBundleRequest\n /** Whether the URL should update when the query is modified. */\n shouldDeepLink?: boolean\n /** Unique index for the component on the page so URL updates do not conflict between table query components */\n componentIndex?: number\n /** Callback invoked when the query is modified */\n onQueryChange?: (newQueryJson: string) => void\n /** Whether to require explicit user confirmation before changing the query. */\n requireConfirmationOnChange?: boolean\n}\n\n// When changing the query with the debounce option, the amount of time to wait for additional debounced changes before updating the query\nexport const DEBOUNCE_DELAY_MS = 750\n\n/**\n * Utility to synchronize the URL with the current query request. Synchronization only occurs if `shouldDeepLink` is true.\n * @param shouldDeepLink whether the query should be synchronized with the URL\n * @param componentIndex the index of the component to synchronize with the URL - essential if multiple components to synchronize are on the page\n * @param setQuery - callback used to update the current query\n * @param initQueryRequest - the initial query request passed via props\n * @param currentQueryRequest - the query request that is currently used\n */\nfunction useSynchronizeQueryWithUrl(\n shouldDeepLink: boolean,\n componentIndex: number,\n setQuery: (\n queryRequest: React.SetStateAction<QueryBundleRequest>,\n commitOptions?: QueryChangeCommitOptions,\n ) => void,\n initQueryRequest: QueryBundleRequest,\n currentQueryRequest: QueryBundleRequest,\n) {\n /**\n * Inspect the URL on mount to see if we have a particular query request that we must show.\n */\n useEffect(() => {\n // Only run this effect if deep linking is enabled\n if (shouldDeepLink) {\n DeepLinkingUtils.getQueryRequestFromLink(\n componentIndex,\n initQueryRequest.query,\n ).then(queryRequestFromLink => {\n if (queryRequestFromLink && queryRequestFromLink.query) {\n setQuery(prevState => ({\n ...prevState,\n ...queryRequestFromLink,\n query: {\n ...prevState.query,\n ...queryRequestFromLink.query,\n },\n }))\n }\n })\n }\n // should only run on mount, or if the component index changes\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [componentIndex])\n\n // If `shouldDeepLink` is true, synchronize the URL\n useEffect(() => {\n if (shouldDeepLink) {\n if (isEqual(initQueryRequest, currentQueryRequest)) {\n void DeepLinkingUtils.updateUrlWithNewSearchParam(\n 'qw',\n componentIndex,\n null,\n null,\n ).catch(error => {\n console.error('Failed to update URL with search param:', error)\n })\n } else {\n void DeepLinkingUtils.updateUrlWithNewSearchParam(\n 'qw',\n componentIndex,\n currentQueryRequest.query,\n initQueryRequest.query,\n ).catch(error => {\n console.error('Failed to update URL with search param:', error)\n })\n }\n }\n // Clean up the URL param when this component unmounts or deep linking is disabled\n return () => {\n if (shouldDeepLink) {\n DeepLinkingUtils.updateUrlWithNewSearchParam(\n 'qw',\n componentIndex,\n null,\n initQueryRequest.query,\n )\n }\n }\n }, [componentIndex, currentQueryRequest, initQueryRequest, shouldDeepLink])\n}\n\n/**\n * Custom hook that maintains and manages the state of a Synapse Table query.\n * @param options\n * @returns\n */\nexport default function useImmutableTableQuery(\n options: UseImmutableTableQueryOptions,\n): ImmutableTableQueryResult {\n const {\n initQueryRequest: initQueryRequestFromProps,\n componentIndex = 0,\n shouldDeepLink = false,\n onQueryChange,\n requireConfirmationOnChange = false,\n } = options\n\n const initQueryRequest = useMemo(() => {\n const request = cloneDeep(initQueryRequestFromProps)\n request.query = removeEmptyQueryParams(request.query)\n return request\n }, [initQueryRequestFromProps])\n\n const {\n currentQueryRequest,\n nextQueryRequest,\n isConfirmingChange,\n dispatch,\n } = useTableQueryReducer(\n initQueryRequest,\n requireConfirmationOnChange,\n onQueryChange,\n )\n\n const onConfirmChange = useCallback(() => {\n dispatch({ type: 'confirmChanges' })\n }, [dispatch])\n\n /**\n * Pass down a deep clone (so no side effects on the child's part) of the\n * current query request\n *\n * @returns\n * @memberof QueryWrapper\n */\n const getCurrentQueryRequest = useCallback(() => {\n return cloneDeep(currentQueryRequest)\n }, [currentQueryRequest])\n\n /**\n * Pass down a deep clone (so no side effects on the child's part) of the\n * first query request made\n *\n * @returns\n * @memberof QueryWrapper\n */\n const getInitQueryRequest = useCallback((): QueryBundleRequest => {\n return cloneDeep(initQueryRequest)\n }, [initQueryRequest])\n\n /**\n * Execute the given query request, updating all the data in the QueryContext to match the new query\n * @param {*} queryRequest Query request as specified by\n * https://rest-docs.synapse.org/rest/org/sagebionetworks/repo/model/table/Query.html\n */\n const setQuery: ImmutableTableQueryResult['setQuery'] = useCallback(\n (\n queryRequest: React.SetStateAction<QueryBundleRequest>,\n commitOptions?: QueryChangeCommitOptions,\n ): void => {\n dispatch({\n type: 'setQuery',\n queryOrUpdater: queryRequest,\n commitOptions,\n })\n },\n [dispatch],\n )\n\n useSynchronizeQueryWithUrl(\n shouldDeepLink,\n componentIndex,\n setQuery,\n initQueryRequest,\n currentQueryRequest,\n )\n\n const onCancelChange = useCallback(() => {\n dispatch({ type: 'cancelChanges' })\n }, [dispatch])\n\n const { entityId, versionNumber } = useMemo(\n () =>\n parseEntityIdAndVersionFromSqlStatement(currentQueryRequest.query.sql),\n [currentQueryRequest.query.sql],\n )\n\n const pageSize = currentQueryRequest.query.limit ?? DEFAULT_PAGE_SIZE\n const currentPage = Math.ceil(\n ((currentQueryRequest.query.offset ?? 0) + Number(pageSize)) / pageSize,\n )\n\n const setPageSize = useCallback(\n (pageSize: number) => {\n dispatch({ type: 'setPageSize', pageSize })\n },\n [dispatch],\n )\n\n const goToPage = useCallback(\n (pageNumber: number) => {\n dispatch({ type: 'goToPage', pageNumber })\n },\n [dispatch],\n )\n\n const resetQuery = useCallback(() => {\n dispatch({\n type: 'resetQuery',\n })\n }, [dispatch])\n\n /* If the initial query changes, then reset the query to match the new prop */\n useDeepCompareEffect(() => {\n if (currentQueryRequest != initQueryRequest) {\n resetQuery()\n }\n }, [initQueryRequest])\n\n const addValueToSelectedFacet = useCallback(\n (\n facet: UniqueFacetIdentifier,\n value: string,\n commitOptions?: QueryChangeCommitOptions,\n ) => {\n dispatch({\n type: 'addValueToSelectedFacet',\n facet: facet,\n value: value,\n commitOptions: commitOptions,\n })\n },\n [dispatch],\n )\n\n const setRangeFacetValue = useCallback(\n (\n facet: UniqueFacetIdentifier,\n min?: string,\n max?: string,\n commitOptions?: QueryChangeCommitOptions,\n ) => {\n dispatch({\n type: 'setRangeFacetValue',\n facet,\n min,\n max,\n commitOptions,\n })\n },\n [dispatch],\n )\n\n const removeSelectedFacet = useCallback(\n (facetsToRemove: UniqueFacetIdentifier | UniqueFacetIdentifier[]) => {\n dispatch({\n type: 'removeSelectedFacet',\n facetsToRemove: facetsToRemove,\n })\n },\n [dispatch],\n )\n\n const removeValueFromSelectedFacet = useCallback(\n (\n facet: UniqueFacetIdentifier,\n value: string,\n commitOptions?: QueryChangeCommitOptions,\n ) => {\n dispatch({\n type: 'removeValueFromSelectedFacet',\n facet,\n value,\n commitOptions,\n })\n },\n [dispatch],\n )\n\n const removeQueryFilter = useCallback(\n (queryFilter: QueryFilter) => {\n dispatch({\n type: 'removeQueryFilter',\n queryFilter,\n })\n },\n [dispatch],\n )\n\n const removeValueFromQueryFilter = useCallback(\n (queryFilter: QueryFilter, value: string) => {\n dispatch({\n type: 'removeValueFromQueryFilter',\n queryFilter,\n value,\n })\n },\n [dispatch],\n )\n const commitChanges = useCallback(() => {\n dispatch({ type: 'commitChanges' })\n }, [dispatch])\n\n const resetDebounceTimer = useCallback(() => {\n dispatch({ type: 'resetDebounce' })\n }, [dispatch])\n\n return {\n entityId,\n commitChanges,\n resetDebounceTimer,\n currentQueryRequest,\n nextQueryRequest,\n versionNumber,\n getInitQueryRequest,\n getCurrentQueryRequest,\n setQuery,\n pageSize,\n currentPage,\n setPageSize,\n goToPage,\n resetQuery,\n removeSelectedFacet,\n removeValueFromSelectedFacet,\n removeQueryFilter,\n removeValueFromQueryFilter,\n isConfirmingChange,\n onConfirmChange,\n onCancelChange,\n addValueToSelectedFacet,\n setRangeFacetValue,\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useTableQueryReducer.js","names":[],"sources":["../../../../src/utils/hooks/useImmutableTableQuery/useTableQueryReducer.ts"],"sourcesContent":["import { UniqueFacetIdentifier } from '@/utils/types'\nimport { useDebouncedEffect } from '@react-hookz/web'\nimport {\n QueryBundleRequest,\n QueryFilter,\n} from '@sage-bionetworks/synapse-types'\nimport { cloneDeep, isEqual } from 'lodash-es'\nimport * as React from 'react'\nimport { useMemo, useReducer, useState } from 'react'\nimport {\n queryRequestsHaveSameTotalResults,\n removeEmptyQueryParams,\n} from '../../functions/queryUtils'\nimport {\n addValueToSelectedFacet,\n getQueryFromSetStateAction,\n goToPage,\n removeQueryFilter,\n removeSelectedFacet,\n removeValueFromQueryFilter,\n removeValueFromSelectedFacet,\n setPageSize,\n setRangeFacetValue,\n} from './TableQueryReducerActions'\nimport { DEBOUNCE_DELAY_MS } from './useImmutableTableQuery'\n\nexport type QueryChangeCommitOptions =\n | {\n // This and future changes including debounce will not be committed until the debounceDelay has elapsed\n debounce: true\n }\n | {\n // The change will not be committed until the commit function is invoked.\n noCommit: true\n }\n\nexport type TableQueryReducerState = {\n currentQueryRequest: QueryBundleRequest\n nextQueryRequest: QueryBundleRequest\n isConfirmingChange: boolean\n}\n\nexport type TableQueryReducerAction = {\n commitOptions?: QueryChangeCommitOptions\n} & (\n | {\n type: 'setQuery'\n queryOrUpdater: React.SetStateAction<QueryBundleRequest>\n }\n | {\n type: 'addValueToSelectedFacet'\n facet: UniqueFacetIdentifier\n value: string\n }\n | {\n type: 'removeSelectedFacet'\n facetsToRemove: UniqueFacetIdentifier | UniqueFacetIdentifier[]\n }\n | {\n type: 'setRangeFacetValue'\n facet: UniqueFacetIdentifier\n min?: string\n max?: string\n }\n | {\n type: 'removeValueFromSelectedFacet'\n facet: UniqueFacetIdentifier\n value: string\n }\n | {\n type: 'setPageSize'\n pageSize: number\n }\n | {\n type: 'goToPage'\n pageNumber: number\n }\n | {\n type: 'resetQuery'\n }\n | {\n type: 'removeQueryFilter'\n queryFilter: QueryFilter\n }\n | {\n type: 'removeValueFromQueryFilter'\n queryFilter: QueryFilter\n value: string\n }\n | {\n type: 'resetUncommittedChanges'\n }\n | { type: 'commitChanges' }\n | { type: 'confirmChanges' }\n | { type: 'cancelChanges' }\n | { type: 'resetDebounce' }\n)\n\n/**\n * Utility hook that internally uses a reducer to manage the state of a table query.\n * @param initQueryRequest\n * @param requireConfirmationOnChange\n * @param onQueryChange\n */\nexport function useTableQueryReducer(\n initQueryRequest: QueryBundleRequest,\n requireConfirmationOnChange: boolean,\n onQueryChange?: (queryJsonString: string) => void,\n) {\n // Increment to reset the debounce counter.\n const [resetDebounceCounter, setResetDebounceCounter] = useState(0)\n const [commitAfterDebounce, setCommitAfterDebounce] = useState(false)\n\n // Note: we must use a reducer because we're tracking interrelated state variables. Attempts to separate these will\n // likely result in bugs such as dropped state changes when React performs a batch update.\n const [state, dispatch] = useReducer(\n (\n prevState: TableQueryReducerState,\n action: TableQueryReducerAction,\n ): TableQueryReducerState => {\n let updatedNextQueryRequest = prevState.nextQueryRequest\n switch (action.type) {\n case 'resetDebounce': {\n setResetDebounceCounter(v => v + 1)\n // Do not update state\n return prevState\n }\n case 'setQuery': {\n updatedNextQueryRequest = getQueryFromSetStateAction(\n action,\n prevState.nextQueryRequest,\n )\n break\n }\n case 'addValueToSelectedFacet': {\n updatedNextQueryRequest = addValueToSelectedFacet(\n action,\n prevState.nextQueryRequest,\n )\n break\n }\n case 'removeSelectedFacet': {\n updatedNextQueryRequest = removeSelectedFacet(\n action,\n prevState.nextQueryRequest,\n )\n break\n }\n case 'setRangeFacetValue': {\n updatedNextQueryRequest = setRangeFacetValue(\n action,\n prevState.nextQueryRequest,\n )\n break\n }\n case 'removeValueFromSelectedFacet': {\n updatedNextQueryRequest = removeValueFromSelectedFacet(\n action,\n prevState.nextQueryRequest,\n )\n break\n }\n case 'removeQueryFilter': {\n updatedNextQueryRequest = removeQueryFilter(\n action,\n prevState.nextQueryRequest,\n )\n break\n }\n case 'removeValueFromQueryFilter': {\n updatedNextQueryRequest = removeValueFromQueryFilter(\n action,\n prevState.nextQueryRequest,\n )\n break\n }\n case 'setPageSize': {\n updatedNextQueryRequest = setPageSize(\n action,\n prevState.nextQueryRequest,\n )\n break\n }\n case 'goToPage': {\n updatedNextQueryRequest = goToPage(action, prevState.nextQueryRequest)\n break\n }\n case 'resetQuery': {\n updatedNextQueryRequest = initQueryRequest\n break\n }\n case 'cancelChanges':\n case 'resetUncommittedChanges': {\n updatedNextQueryRequest = prevState.currentQueryRequest\n break\n }\n case 'confirmChanges':\n case 'commitChanges': {\n updatedNextQueryRequest = cloneDeep(prevState.nextQueryRequest)\n // commit the changes\n break\n }\n }\n\n updatedNextQueryRequest.query = removeEmptyQueryParams(\n updatedNextQueryRequest.query,\n )\n\n const isConfirmingChange =\n requireConfirmationOnChange &&\n !queryRequestsHaveSameTotalResults(\n prevState.currentQueryRequest.query,\n updatedNextQueryRequest.query,\n )\n\n if (\n // No commit cases:\n // If `noCommit` is explicitly specified in the commit options\n (action.commitOptions && 'noCommit' in action.commitOptions) ||\n // Or if the user is in the 'confirm' state (modal is shown) AND\n // the action is not the 'confirmChanges' or 'cancelChanges' action.\n (isConfirmingChange &&\n action.type !== 'confirmChanges' &&\n action.type !== 'cancelChanges')\n ) {\n return {\n currentQueryRequest: prevState.currentQueryRequest,\n nextQueryRequest: updatedNextQueryRequest,\n isConfirmingChange: isConfirmingChange,\n }\n } else if (action.commitOptions && 'debounce' in action.commitOptions) {\n // If debouncing, update the state flag. An effect will commit the changes after the debounce delay.\n setCommitAfterDebounce(true)\n return {\n currentQueryRequest: prevState.currentQueryRequest,\n nextQueryRequest: updatedNextQueryRequest,\n isConfirmingChange: isConfirmingChange,\n }\n } else {\n // Commit case: clear the debounce flag and update state\n setCommitAfterDebounce(false)\n if (\n onQueryChange &&\n !isEqual(prevState.currentQueryRequest, updatedNextQueryRequest)\n ) {\n const queryJsonString = JSON.stringify(updatedNextQueryRequest.query)\n onQueryChange(queryJsonString)\n }\n return {\n currentQueryRequest: updatedNextQueryRequest,\n nextQueryRequest: updatedNextQueryRequest,\n isConfirmingChange: false,\n }\n }\n },\n {\n currentQueryRequest: initQueryRequest,\n nextQueryRequest: initQueryRequest,\n isConfirmingChange: false,\n },\n )\n\n useDebouncedEffect(\n () => {\n if (commitAfterDebounce) {\n dispatch({ type: 'commitChanges' })\n setCommitAfterDebounce(false)\n }\n },\n // nextQueryRequest MUST be included in the dependencies to ensure the debounce resets when it changes\n [\n state.nextQueryRequest,\n commitAfterDebounce,\n setCommitAfterDebounce,\n resetDebounceCounter,\n ],\n DEBOUNCE_DELAY_MS,\n )\n\n return useMemo(\n () => ({\n currentQueryRequest: state.currentQueryRequest,\n nextQueryRequest: state.nextQueryRequest,\n isConfirmingChange: state.isConfirmingChange,\n dispatch,\n }),\n [\n state.currentQueryRequest,\n state.isConfirmingChange,\n state.nextQueryRequest,\n ],\n )\n}\n"],"mappings":";;;;;;;AAwGA,SAAgB,EACd,GACA,GACA,GACA;CAEA,IAAM,CAAC,GAAsB,KAA2B,EAAS,EAAE,EAC7D,CAAC,GAAqB,KAA0B,EAAS,GAAM,EAI/D,CAAC,GAAO,KAAY,GAEtB,GACA,MAC2B;EAC3B,IAAI,IAA0B,EAAU;AACxC,UAAQ,EAAO,MAAf;GACE,KAAK,gBAGH,QAFA,GAAwB,MAAK,IAAI,EAAE,EAE5B;GAET,KAAK;AACH,QAA0B,EACxB,GACA,EAAU,iBACX;AACD;GAEF,KAAK;AACH,QAA0B,EACxB,GACA,EAAU,iBACX;AACD;GAEF,KAAK;AACH,QAA0B,EACxB,GACA,EAAU,iBACX;AACD;GAEF,KAAK;AACH,QAA0B,EACxB,GACA,EAAU,iBACX;AACD;GAEF,KAAK;AACH,QAA0B,EACxB,GACA,EAAU,iBACX;AACD;GAEF,KAAK;AACH,QAA0B,EACxB,GACA,EAAU,iBACX;AACD;GAEF,KAAK;AACH,QAA0B,EACxB,GACA,EAAU,iBACX;AACD;GAEF,KAAK;AACH,QAA0B,EACxB,GACA,EAAU,iBACX;AACD;GAEF,KAAK;AACH,QAA0B,EAAS,GAAQ,EAAU,iBAAiB;AACtE;GAEF,KAAK;AACH,QAA0B;AAC1B;GAEF,KAAK;GACL,KAAK;AACH,QAA0B,EAAU;AACpC;GAEF,KAAK;GACL,KAAK;AACH,QAA0B,EAAU,EAAU,iBAAiB;AAE/D;;AAIJ,IAAwB,QAAQ,EAC9B,EAAwB,MACzB;EAED,IAAM,IACJ,KACA,CAAC,EACC,EAAU,oBAAoB,OAC9B,EAAwB,MACzB;AAmCD,SA9BC,EAAO,iBAAiB,cAAc,EAAO,iBAG7C,KACC,EAAO,SAAS,oBAChB,EAAO,SAAS,kBAEX;GACL,qBAAqB,EAAU;GAC/B,kBAAkB;GACE;GACrB,GACQ,EAAO,iBAAiB,cAAc,EAAO,iBAEtD,EAAuB,GAAK,EACrB;GACL,qBAAqB,EAAU;GAC/B,kBAAkB;GACE;GACrB,KAGD,EAAuB,GAAM,EAE3B,KACA,CAAC,EAAQ,EAAU,qBAAqB,EAAwB,IAGhE,EADwB,KAAK,UAAU,EAAwB,MAAM,CACvC,EAEzB;GACL,qBAAqB;GACrB,kBAAkB;GAClB,oBAAoB;GACrB;IAGL;EACE,qBAAqB;EACrB,kBAAkB;EAClB,oBAAoB;EACrB,CACF;AAmBD,QAjBA,QACQ;AACJ,EAAI,MACF,EAAS,EAAE,MAAM,iBAAiB,CAAC,EACnC,EAAuB,GAAM;IAIjC;EACE,EAAM;EACN;EACA;EACA;EACD,EAAA,IAEF,EAEM,SACE;EACL,qBAAqB,EAAM;EAC3B,kBAAkB,EAAM;EACxB,oBAAoB,EAAM;EAC1B;EACD,GACD;EACE,EAAM;EACN,EAAM;EACN,EAAM;EACP,CACF"}
|
|
1
|
+
{"version":3,"file":"useTableQueryReducer.js","names":[],"sources":["../../../../src/utils/hooks/useImmutableTableQuery/useTableQueryReducer.ts"],"sourcesContent":["import { UniqueFacetIdentifier } from '@/utils/types'\nimport { useDebouncedEffect } from '@react-hookz/web'\nimport {\n QueryBundleRequest,\n QueryFilter,\n} from '@sage-bionetworks/synapse-types'\nimport { cloneDeep, isEqual } from 'lodash-es'\nimport * as React from 'react'\nimport { useMemo, useReducer, useState } from 'react'\nimport {\n queryRequestsHaveSameTotalResults,\n removeEmptyQueryParams,\n} from '../../functions/queryUtils'\nimport {\n addValueToSelectedFacet,\n getQueryFromSetStateAction,\n goToPage,\n removeQueryFilter,\n removeSelectedFacet,\n removeValueFromQueryFilter,\n removeValueFromSelectedFacet,\n setPageSize,\n setRangeFacetValue,\n} from './TableQueryReducerActions'\nimport { DEBOUNCE_DELAY_MS } from './useImmutableTableQuery'\n\nexport type QueryChangeCommitOptions =\n | {\n // This and future changes including debounce will not be committed until the debounceDelay has elapsed\n debounce: true\n }\n | {\n // The change will not be committed until the commit function is invoked.\n noCommit: true\n }\n\nexport type TableQueryReducerState = {\n currentQueryRequest: QueryBundleRequest\n nextQueryRequest: QueryBundleRequest\n isConfirmingChange: boolean\n}\n\nexport type TableQueryReducerAction = {\n commitOptions?: QueryChangeCommitOptions\n} & (\n | {\n type: 'setQuery'\n queryOrUpdater: React.SetStateAction<QueryBundleRequest>\n }\n | {\n type: 'addValueToSelectedFacet'\n facet: UniqueFacetIdentifier\n value: string\n }\n | {\n type: 'removeSelectedFacet'\n facetsToRemove: UniqueFacetIdentifier | UniqueFacetIdentifier[]\n }\n | {\n type: 'setRangeFacetValue'\n facet: UniqueFacetIdentifier\n min?: string\n max?: string\n }\n | {\n type: 'removeValueFromSelectedFacet'\n facet: UniqueFacetIdentifier\n value: string\n }\n | {\n type: 'setPageSize'\n pageSize: number\n }\n | {\n type: 'goToPage'\n pageNumber: number\n }\n | {\n type: 'resetQuery'\n }\n | {\n type: 'removeQueryFilter'\n queryFilter: QueryFilter\n }\n | {\n type: 'removeValueFromQueryFilter'\n queryFilter: QueryFilter\n value: string\n }\n | {\n type: 'resetUncommittedChanges'\n }\n | { type: 'commitChanges' }\n | { type: 'confirmChanges' }\n | { type: 'cancelChanges' }\n | { type: 'resetDebounce' }\n)\n\n/**\n * Utility hook that internally uses a reducer to manage the state of a table query.\n * @param initQueryRequest\n * @param requireConfirmationOnChange\n * @param onQueryChange\n */\nexport function useTableQueryReducer(\n initQueryRequest: QueryBundleRequest,\n requireConfirmationOnChange: boolean,\n onQueryChange?: (queryJsonString: string) => void,\n) {\n // Increment to reset the debounce counter.\n const [resetDebounceCounter, setResetDebounceCounter] = useState(0)\n const [commitAfterDebounce, setCommitAfterDebounce] = useState(false)\n\n // Note: we must use a reducer because we're tracking interrelated state variables. Attempts to separate these will\n // likely result in bugs such as dropped state changes when React performs a batch update.\n const [state, dispatch] = useReducer(\n (\n prevState: TableQueryReducerState,\n action: TableQueryReducerAction,\n ): TableQueryReducerState => {\n let updatedNextQueryRequest = prevState.nextQueryRequest\n switch (action.type) {\n case 'resetDebounce': {\n setResetDebounceCounter(v => v + 1)\n // Do not update state\n return prevState\n }\n case 'setQuery': {\n updatedNextQueryRequest = getQueryFromSetStateAction(\n action,\n prevState.nextQueryRequest,\n )\n break\n }\n case 'addValueToSelectedFacet': {\n updatedNextQueryRequest = addValueToSelectedFacet(\n action,\n prevState.nextQueryRequest,\n )\n break\n }\n case 'removeSelectedFacet': {\n updatedNextQueryRequest = removeSelectedFacet(\n action,\n prevState.nextQueryRequest,\n )\n break\n }\n case 'setRangeFacetValue': {\n updatedNextQueryRequest = setRangeFacetValue(\n action,\n prevState.nextQueryRequest,\n )\n break\n }\n case 'removeValueFromSelectedFacet': {\n updatedNextQueryRequest = removeValueFromSelectedFacet(\n action,\n prevState.nextQueryRequest,\n )\n break\n }\n case 'removeQueryFilter': {\n updatedNextQueryRequest = removeQueryFilter(\n action,\n prevState.nextQueryRequest,\n )\n break\n }\n case 'removeValueFromQueryFilter': {\n updatedNextQueryRequest = removeValueFromQueryFilter(\n action,\n prevState.nextQueryRequest,\n )\n break\n }\n case 'setPageSize': {\n updatedNextQueryRequest = setPageSize(\n action,\n prevState.nextQueryRequest,\n )\n break\n }\n case 'goToPage': {\n updatedNextQueryRequest = goToPage(action, prevState.nextQueryRequest)\n break\n }\n case 'resetQuery': {\n updatedNextQueryRequest = initQueryRequest\n break\n }\n case 'cancelChanges':\n case 'resetUncommittedChanges': {\n updatedNextQueryRequest = prevState.currentQueryRequest\n break\n }\n case 'confirmChanges':\n case 'commitChanges': {\n updatedNextQueryRequest = cloneDeep(prevState.nextQueryRequest)\n // commit the changes\n break\n }\n }\n\n updatedNextQueryRequest.query = removeEmptyQueryParams(\n updatedNextQueryRequest.query,\n )\n\n const isConfirmingChange =\n requireConfirmationOnChange &&\n !queryRequestsHaveSameTotalResults(\n prevState.currentQueryRequest.query,\n updatedNextQueryRequest.query,\n )\n\n if (\n // No commit cases:\n // If `noCommit` is explicitly specified in the commit options\n (action.commitOptions && 'noCommit' in action.commitOptions) ||\n // Or if the user is in the 'confirm' state (modal is shown) AND\n // the action is not the 'confirmChanges' or 'cancelChanges' action.\n (isConfirmingChange &&\n action.type !== 'confirmChanges' &&\n action.type !== 'cancelChanges')\n ) {\n return {\n currentQueryRequest: prevState.currentQueryRequest,\n nextQueryRequest: updatedNextQueryRequest,\n isConfirmingChange: isConfirmingChange,\n }\n } else if (action.commitOptions && 'debounce' in action.commitOptions) {\n // If debouncing, update the state flag. An effect will commit the changes after the debounce delay.\n setCommitAfterDebounce(true)\n return {\n currentQueryRequest: prevState.currentQueryRequest,\n nextQueryRequest: updatedNextQueryRequest,\n isConfirmingChange: isConfirmingChange,\n }\n } else {\n // Commit case: clear the debounce flag and update state\n setCommitAfterDebounce(false)\n if (\n onQueryChange &&\n !isEqual(prevState.currentQueryRequest, updatedNextQueryRequest)\n ) {\n const queryJsonString = JSON.stringify(updatedNextQueryRequest.query)\n onQueryChange(queryJsonString)\n }\n return {\n currentQueryRequest: updatedNextQueryRequest,\n nextQueryRequest: updatedNextQueryRequest,\n isConfirmingChange: false,\n }\n }\n },\n {\n currentQueryRequest: initQueryRequest,\n nextQueryRequest: initQueryRequest,\n isConfirmingChange: false,\n },\n )\n\n useDebouncedEffect(\n () => {\n if (commitAfterDebounce) {\n dispatch({ type: 'commitChanges' })\n setCommitAfterDebounce(false)\n }\n },\n // nextQueryRequest MUST be included in the dependencies to ensure the debounce resets when it changes\n [\n state.nextQueryRequest,\n commitAfterDebounce,\n setCommitAfterDebounce,\n resetDebounceCounter,\n ],\n DEBOUNCE_DELAY_MS,\n )\n\n return useMemo(\n () => ({\n currentQueryRequest: state.currentQueryRequest,\n nextQueryRequest: state.nextQueryRequest,\n isConfirmingChange: state.isConfirmingChange,\n dispatch,\n }),\n [\n state.currentQueryRequest,\n state.isConfirmingChange,\n state.nextQueryRequest,\n ],\n )\n}\n"],"mappings":";;;;;;;AAwGA,SAAgB,EACd,GACA,GACA,GACA;CAEA,IAAM,CAAC,GAAsB,KAA2B,EAAS,EAAE,EAC7D,CAAC,GAAqB,KAA0B,EAAS,GAAM,EAI/D,CAAC,GAAO,KAAY,GAEtB,GACA,MAC2B;EAC3B,IAAI,IAA0B,EAAU;AACxC,UAAQ,EAAO,MAAf;GACE,KAAK,gBAGH,QAFA,GAAwB,MAAK,IAAI,EAAE,EAE5B;GAET,KAAK;AACH,QAA0B,EACxB,GACA,EAAU,iBACX;AACD;GAEF,KAAK;AACH,QAA0B,EACxB,GACA,EAAU,iBACX;AACD;GAEF,KAAK;AACH,QAA0B,EACxB,GACA,EAAU,iBACX;AACD;GAEF,KAAK;AACH,QAA0B,EACxB,GACA,EAAU,iBACX;AACD;GAEF,KAAK;AACH,QAA0B,EACxB,GACA,EAAU,iBACX;AACD;GAEF,KAAK;AACH,QAA0B,EACxB,GACA,EAAU,iBACX;AACD;GAEF,KAAK;AACH,QAA0B,EACxB,GACA,EAAU,iBACX;AACD;GAEF,KAAK;AACH,QAA0B,EACxB,GACA,EAAU,iBACX;AACD;GAEF,KAAK;AACH,QAA0B,EAAS,GAAQ,EAAU,iBAAiB;AACtE;GAEF,KAAK;AACH,QAA0B;AAC1B;GAEF,KAAK;GACL,KAAK;AACH,QAA0B,EAAU;AACpC;GAEF,KAAK;GACL,KAAK;AACH,QAA0B,EAAU,EAAU,iBAAiB;AAE/D;;AAIJ,IAAwB,QAAQ,EAC9B,EAAwB,MACzB;EAED,IAAM,IACJ,KACA,CAAC,EACC,EAAU,oBAAoB,OAC9B,EAAwB,MACzB;AAmCD,SA9BC,EAAO,iBAAiB,cAAc,EAAO,iBAG7C,KACC,EAAO,SAAS,oBAChB,EAAO,SAAS,kBAEX;GACL,qBAAqB,EAAU;GAC/B,kBAAkB;GACE;GACrB,GACQ,EAAO,iBAAiB,cAAc,EAAO,iBAEtD,EAAuB,GAAK,EACrB;GACL,qBAAqB,EAAU;GAC/B,kBAAkB;GACE;GACrB,KAGD,EAAuB,GAAM,EAE3B,KACA,CAAC,EAAQ,EAAU,qBAAqB,EAAwB,IAGhE,EADwB,KAAK,UAAU,EAAwB,MACjD,CAAgB,EAEzB;GACL,qBAAqB;GACrB,kBAAkB;GAClB,oBAAoB;GACrB;IAGL;EACE,qBAAqB;EACrB,kBAAkB;EAClB,oBAAoB;EACrB,CACF;AAmBD,QAjBA,QACQ;AACJ,EAAI,MACF,EAAS,EAAE,MAAM,iBAAiB,CAAC,EACnC,EAAuB,GAAM;IAIjC;EACE,EAAM;EACN;EACA;EACA;EACD,EAAA,IAEF,EAEM,SACE;EACL,qBAAqB,EAAM;EAC3B,kBAAkB,EAAM;EACxB,oBAAoB,EAAM;EAC1B;EACD,GACD;EACE,EAAM;EACN,EAAM;EACN,EAAM;EACP,CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useIsBot.js","names":[],"sources":["../../../src/utils/hooks/useIsBot.ts"],"sourcesContent":["import { useMemo } from 'react'\n\n/**\n * Hook that detects if the current user agent is likely a bot/crawler.\n * This is useful for automatically fetching all content for search engine indexing.\n *\n * @returns true if the user agent appears to be a bot, false otherwise\n */\nexport function useIsBot(): boolean {\n return useMemo(() => {\n if (typeof navigator === 'undefined' || !navigator.userAgent) {\n return false\n }\n\n const userAgent = navigator.userAgent.toLowerCase()\n\n // Common bot/crawler patterns\n const botPatterns = [\n 'bot',\n 'crawler',\n 'spider',\n 'crawling',\n 'google',\n 'bing',\n 'yahoo',\n 'baidu',\n 'yandex',\n 'duckduckbot',\n 'slurp',\n 'teoma',\n 'ia_archiver',\n 'bingpreview',\n 'facebookexternalhit',\n 'twitterbot',\n 'rogerbot',\n 'linkedinbot',\n 'embedly',\n 'quora link preview',\n 'showyoubot',\n 'outbrain',\n 'pinterest',\n 'slackbot',\n 'vkshare',\n 'w3c_validator',\n 'redditbot',\n 'applebot',\n 'whatsapp',\n 'flipboard',\n 'tumblr',\n 'bitlybot',\n 'skypeuripreview',\n 'nuzzel',\n 'discordbot',\n 'qwantify',\n 'pinterestbot',\n 'bitrix',\n ]\n\n return botPatterns.some(pattern => userAgent.includes(pattern))\n }, [])\n}\n"],"mappings":";;AAQA,SAAgB,IAAoB;AAClC,QAAO,QAAc;AACnB,MAAI,OAAO,YAAc,OAAe,CAAC,UAAU,UACjD,QAAO;EAGT,IAAM,IAAY,UAAU,UAAU,aAAa;AA4CnD,
|
|
1
|
+
{"version":3,"file":"useIsBot.js","names":[],"sources":["../../../src/utils/hooks/useIsBot.ts"],"sourcesContent":["import { useMemo } from 'react'\n\n/**\n * Hook that detects if the current user agent is likely a bot/crawler.\n * This is useful for automatically fetching all content for search engine indexing.\n *\n * @returns true if the user agent appears to be a bot, false otherwise\n */\nexport function useIsBot(): boolean {\n return useMemo(() => {\n if (typeof navigator === 'undefined' || !navigator.userAgent) {\n return false\n }\n\n const userAgent = navigator.userAgent.toLowerCase()\n\n // Common bot/crawler patterns\n const botPatterns = [\n 'bot',\n 'crawler',\n 'spider',\n 'crawling',\n 'google',\n 'bing',\n 'yahoo',\n 'baidu',\n 'yandex',\n 'duckduckbot',\n 'slurp',\n 'teoma',\n 'ia_archiver',\n 'bingpreview',\n 'facebookexternalhit',\n 'twitterbot',\n 'rogerbot',\n 'linkedinbot',\n 'embedly',\n 'quora link preview',\n 'showyoubot',\n 'outbrain',\n 'pinterest',\n 'slackbot',\n 'vkshare',\n 'w3c_validator',\n 'redditbot',\n 'applebot',\n 'whatsapp',\n 'flipboard',\n 'tumblr',\n 'bitlybot',\n 'skypeuripreview',\n 'nuzzel',\n 'discordbot',\n 'qwantify',\n 'pinterestbot',\n 'bitrix',\n ]\n\n return botPatterns.some(pattern => userAgent.includes(pattern))\n }, [])\n}\n"],"mappings":";;AAQA,SAAgB,IAAoB;AAClC,QAAO,QAAc;AACnB,MAAI,OAAO,YAAc,OAAe,CAAC,UAAU,UACjD,QAAO;EAGT,IAAM,IAAY,UAAU,UAAU,aAAa;AA4CnD,UAAO,wYAAA,EAAY,MAAK,MAAW,EAAU,SAAS,EAAQ,CAAC;IAC9D,EAAE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useListState.js","names":[],"sources":["../../../src/utils/hooks/useListState.ts"],"sourcesContent":["import { Dispatch, SetStateAction, useState } from 'react'\n\nexport interface ListStateReturn<T> {\n // initial state of the list\n list: T[]\n // generates a function to update a specific index of the list\n handleListChange: (index: number) => (changedValue: T) => void\n // generates a function to remove a index from the list\n handleListRemove: (index: number) => () => void\n // generates a function to append to the end of the list\n appendToList: (...newItem: T[]) => void\n //changes the entire list state\n setList: Dispatch<SetStateAction<T[]>>\n}\n/**\n * This is used when a component's state uses a List<T> and has child components\n * that are responsible for creating, updating, deleting the objects within the List.\n *\n *\n * This should be used in conjunction with list.map() to generate child elements.\n *\n * The handle*() functions will generate a callback function for\n * the child to use to perform an item change, or removal on the list.\n *\n * Generally, appending items to the list will be handled by the parent\n * so appendToList() is just a regular function instead of a function generator\n * For Example:\n *\n * ```\n * export const ParentComponent: React.FunctionComponent<ParentComponentProps> = ({\n * prop1,\n * prop2,\n * }) => {\n * const {list: myList,\n * handleListChange: handleMyListChange,\n * handleListRemove: handleMyListPush,\n * appendToList: handleMyListRemove} = useListState<string>(['asdf','qwerty'])\n *\n * return (\n * <div>\n * myList.map((item, index) => {\n return <ChildComponent\n value={item}\n onChange={handleMyListChange(index)}\n onRemove={handleMyListRemove(index)}\n />\n })\n <button onClick={(event) => {appendToList(\"some new value\")} }> >Add Child</button>\n * </div>\n * )\n *\n * }\n * ```\n *\n *\n * @param initialState The initial value of the array\n * @returns an ListStateReturn object containing the useState value and additonal change/remove/push hnndlers. Use object destructuring\n */\nexport const useListState = <T>(initialState: T[]): ListStateReturn<T> => {\n const [list, setList] = useState<T[]>(initialState)\n\n const handleListChange =\n (index: number) =>\n (changedValue: T): void => {\n const modifiedList = [...list]\n modifiedList[index] = changedValue\n setList(modifiedList)\n }\n\n const handleListRemove = (index: number) => (): void => {\n const modifiedList = list.filter((value, arr_index) => index !== arr_index)\n setList(modifiedList)\n }\n\n const appendToList = (...newItem: T[]): void => {\n const modifiedList = [...list]\n modifiedList.push(...newItem)\n setList(modifiedList)\n }\n return { list, handleListChange, handleListRemove, appendToList, setList }\n}\n"],"mappings":";;AA0DA,IAAa,KAAmB,MAA0C;CACxE,IAAM,CAAC,GAAM,KAAW,EAAc,EAAa;AAoBnD,QAAO;EAAE;EAAM,mBAjBZ,OACA,MAA0B;GACzB,IAAM,IAAe,CAAC,GAAG,EAAK;AAE9B,GADA,EAAa,KAAS,GACtB,EAAQ,EAAa;;EAaQ,mBAVP,YAA8B;AAEtD,KADqB,EAAK,QAAQ,GAAO,MAAc,MAAU,
|
|
1
|
+
{"version":3,"file":"useListState.js","names":[],"sources":["../../../src/utils/hooks/useListState.ts"],"sourcesContent":["import { Dispatch, SetStateAction, useState } from 'react'\n\nexport interface ListStateReturn<T> {\n // initial state of the list\n list: T[]\n // generates a function to update a specific index of the list\n handleListChange: (index: number) => (changedValue: T) => void\n // generates a function to remove a index from the list\n handleListRemove: (index: number) => () => void\n // generates a function to append to the end of the list\n appendToList: (...newItem: T[]) => void\n //changes the entire list state\n setList: Dispatch<SetStateAction<T[]>>\n}\n/**\n * This is used when a component's state uses a List<T> and has child components\n * that are responsible for creating, updating, deleting the objects within the List.\n *\n *\n * This should be used in conjunction with list.map() to generate child elements.\n *\n * The handle*() functions will generate a callback function for\n * the child to use to perform an item change, or removal on the list.\n *\n * Generally, appending items to the list will be handled by the parent\n * so appendToList() is just a regular function instead of a function generator\n * For Example:\n *\n * ```\n * export const ParentComponent: React.FunctionComponent<ParentComponentProps> = ({\n * prop1,\n * prop2,\n * }) => {\n * const {list: myList,\n * handleListChange: handleMyListChange,\n * handleListRemove: handleMyListPush,\n * appendToList: handleMyListRemove} = useListState<string>(['asdf','qwerty'])\n *\n * return (\n * <div>\n * myList.map((item, index) => {\n return <ChildComponent\n value={item}\n onChange={handleMyListChange(index)}\n onRemove={handleMyListRemove(index)}\n />\n })\n <button onClick={(event) => {appendToList(\"some new value\")} }> >Add Child</button>\n * </div>\n * )\n *\n * }\n * ```\n *\n *\n * @param initialState The initial value of the array\n * @returns an ListStateReturn object containing the useState value and additonal change/remove/push hnndlers. Use object destructuring\n */\nexport const useListState = <T>(initialState: T[]): ListStateReturn<T> => {\n const [list, setList] = useState<T[]>(initialState)\n\n const handleListChange =\n (index: number) =>\n (changedValue: T): void => {\n const modifiedList = [...list]\n modifiedList[index] = changedValue\n setList(modifiedList)\n }\n\n const handleListRemove = (index: number) => (): void => {\n const modifiedList = list.filter((value, arr_index) => index !== arr_index)\n setList(modifiedList)\n }\n\n const appendToList = (...newItem: T[]): void => {\n const modifiedList = [...list]\n modifiedList.push(...newItem)\n setList(modifiedList)\n }\n return { list, handleListChange, handleListRemove, appendToList, setList }\n}\n"],"mappings":";;AA0DA,IAAa,KAAmB,MAA0C;CACxE,IAAM,CAAC,GAAM,KAAW,EAAc,EAAa;AAoBnD,QAAO;EAAE;EAAM,mBAjBZ,OACA,MAA0B;GACzB,IAAM,IAAe,CAAC,GAAG,EAAK;AAE9B,GADA,EAAa,KAAS,GACtB,EAAQ,EAAa;;EAaQ,mBAVP,YAA8B;AAEtD,KADqB,EAAK,QAAQ,GAAO,MAAc,MAAU,EACzD,CAAa;;EAQ4B,eAL7B,GAAG,MAAuB;GAC9C,IAAM,IAAe,CAAC,GAAG,EAAK;AAE9B,GADA,EAAa,KAAK,GAAG,EAAQ,EAC7B,EAAQ,EAAa;;EAE0C;EAAS"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useLogin.d.ts","sourceRoot":"","sources":["../../../src/utils/hooks/useLogin.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,0BAA0B,EAC3B,MAAM,8EAA8E,CAAA;AAErF,OAAO,EAIL,oBAAoB,EAErB,MAAM,iCAAiC,CAAA;AAGxC,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAuB,MAAM,OAAO,CAAA;AAGrE,OAAO,EAAE,sBAAsB,EAAE,MAAM,iDAAiD,CAAA;
|
|
1
|
+
{"version":3,"file":"useLogin.d.ts","sourceRoot":"","sources":["../../../src/utils/hooks/useLogin.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,0BAA0B,EAC3B,MAAM,8EAA8E,CAAA;AAErF,OAAO,EAIL,oBAAoB,EAErB,MAAM,iCAAiC,CAAA;AAGxC,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAuB,MAAM,OAAO,CAAA;AAGrE,OAAO,EAAE,sBAAsB,EAAE,MAAM,iDAAiD,CAAA;AAGxF,MAAM,MAAM,eAAe,GAAG;IAC5B,eAAe,CAAC,EAAE,MAAM,IAAI,CAAA;IAC5B,kBAAkB,CAAC,EAAE,0BAA0B,CAAA;IAE/C,uBAAuB,CAAC,EAAE,CACxB,UAAU,EAAE,IAAI,CAAC,0BAA0B,EAAE,YAAY,GAAG,QAAQ,CAAC,KAClE,IAAI,CAAA;CACV,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EACA,oBAAoB,GACpB,mBAAmB,GACnB,sBAAsB,GACtB,WAAW,CAAA;IACf,YAAY,EAAE,QAAQ,CAAC,cAAc,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;IAC9D,yBAAyB,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAA;IACvE,qBAAqB,EAAE,CACrB,IAAI,EAAE,MAAM,EAEZ,OAAO,CAAC,EAAE,oBAAoB,KAC3B,IAAI,CAAA;IAET,uBAAuB,EAAE,CAAC,kBAAkB,EAAE,MAAM,KAAK,IAAI,CAAA;IAC7D,2BAA2B,EAAE,OAAO,CAAA;IACpC,2BAA2B,EAAE,OAAO,CAAA;IACpC,YAAY,EAAE,MAAM,GAAG,SAAS,CAAA;IAChC,cAAc,EAAE,OAAO,CAAA;CACxB,CAAA;AAUD;;GAEG;AACH,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,IAAI,EAAE,eAAe,GAAG,cAAc,CA0PtE"}
|
|
@@ -1,100 +1,101 @@
|
|
|
1
1
|
import { AUTHENTICATION_RECEIPT_LOCALSTORAGE_KEY as e } from "../SynapseConstants.js";
|
|
2
2
|
import t from "../../synapse-client/index.js";
|
|
3
3
|
import { useOneSageURL as n } from "./useOneSageURL.js";
|
|
4
|
-
import {
|
|
4
|
+
import { TOTP_CLOCK_SKEW_ERROR_APPENDAGE as r } from "../../components/Authentication/Constants.js";
|
|
5
|
+
import { useResetTwoFactorAuth as i } from "../../synapse-queries/auth/useTwoFactorEnrollment.js";
|
|
5
6
|
import "../../synapse-queries/index.js";
|
|
6
|
-
import { useEffect as
|
|
7
|
-
import { noop as
|
|
8
|
-
import { ErrorResponseCode as
|
|
9
|
-
import { instanceOfTwoFactorAuthErrorResponse as
|
|
10
|
-
import { useMutation as
|
|
7
|
+
import { useEffect as a, useState as o } from "react";
|
|
8
|
+
import { noop as s } from "lodash-es";
|
|
9
|
+
import { ErrorResponseCode as c } from "@sage-bionetworks/synapse-types";
|
|
10
|
+
import { instanceOfTwoFactorAuthErrorResponse as l } from "@sage-bionetworks/synapse-client/generated/models/TwoFactorAuthErrorResponse";
|
|
11
|
+
import { useMutation as u } from "@tanstack/react-query";
|
|
11
12
|
//#region src/utils/hooks/useLogin.ts
|
|
12
|
-
var
|
|
13
|
+
var d = [
|
|
13
14
|
"VERIFICATION_CODE",
|
|
14
15
|
"RECOVERY_CODE",
|
|
15
16
|
"LOGGED_IN",
|
|
16
17
|
"DISABLE_2FA_PROMPT"
|
|
17
18
|
];
|
|
18
|
-
function
|
|
19
|
-
let { sessionCallback:
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}, [
|
|
19
|
+
function f(f) {
|
|
20
|
+
let { sessionCallback: p = s, twoFaErrorResponse: m, onTwoFactorAuthRequired: h = s } = f, [g, _] = o("CHOOSE_AUTH_METHOD"), [v, y] = o(), [b, x] = o(), S = n("/changePassword");
|
|
21
|
+
a(() => {
|
|
22
|
+
m && x(m);
|
|
23
|
+
}, [m]), a(() => {
|
|
23
24
|
let { searchParams: e } = new URL(window.location.href);
|
|
24
25
|
if (e) {
|
|
25
26
|
let t = e.get("userId"), n = e.get("twoFaToken");
|
|
26
|
-
t && n && (
|
|
27
|
-
errorCode:
|
|
27
|
+
t && n && (x({
|
|
28
|
+
errorCode: c.TWO_FA_REQUIRED,
|
|
28
29
|
reason: "",
|
|
29
30
|
userId: parseInt(t, 10),
|
|
30
31
|
twoFaToken: n,
|
|
31
32
|
concreteType: "org.sagebionetworks.repo.model.auth.TwoFactorAuthErrorResponse"
|
|
32
|
-
}),
|
|
33
|
+
}), d.includes(g) || _("VERIFICATION_CODE"));
|
|
33
34
|
}
|
|
34
|
-
}, [
|
|
35
|
-
|
|
36
|
-
}, [
|
|
37
|
-
|
|
38
|
-
}, [
|
|
39
|
-
|
|
40
|
-
}, [
|
|
41
|
-
async function
|
|
42
|
-
await t.setAccessTokenCookie(n.accessToken), localStorage.setItem(e, n.authenticationReceipt ?? ""),
|
|
35
|
+
}, [g]), a(() => {
|
|
36
|
+
b && (x(b), d.includes(g) || _("VERIFICATION_CODE"));
|
|
37
|
+
}, [b]), a(() => {
|
|
38
|
+
b && h(b);
|
|
39
|
+
}, [h, b]), a(() => {
|
|
40
|
+
y(void 0);
|
|
41
|
+
}, [g]);
|
|
42
|
+
async function C(n) {
|
|
43
|
+
await t.setAccessTokenCookie(n.accessToken), localStorage.setItem(e, n.authenticationReceipt ?? ""), _("LOGGED_IN"), p && p();
|
|
43
44
|
}
|
|
44
|
-
let { mutate:
|
|
45
|
+
let { mutate: w, isPending: T } = u({
|
|
45
46
|
mutationFn: ({ username: e, password: n, authenticationReceipt: r }) => t.login(e, n, r),
|
|
46
47
|
onError: (e) => {
|
|
47
|
-
|
|
48
|
+
y(e.reason);
|
|
48
49
|
let { errorResponse: t } = e;
|
|
49
|
-
t && "errorCode" in t && t.errorCode ==
|
|
50
|
+
t && "errorCode" in t && t.errorCode == c.PASSWORD_RESET_VIA_EMAIL_REQUIRED && window.location.assign(S.toString());
|
|
50
51
|
},
|
|
51
52
|
onSuccess: async (e) => {
|
|
52
|
-
e && (
|
|
53
|
+
e && (l(e) ? (_("VERIFICATION_CODE"), x(e)) : await C(e));
|
|
53
54
|
}
|
|
54
|
-
}), { mutate:
|
|
55
|
+
}), { mutate: E, isPending: D } = u({
|
|
55
56
|
mutationFn: t.loginWith2fa,
|
|
56
57
|
onError: (e) => {
|
|
57
|
-
|
|
58
|
+
y(e.reason), e.reason.includes("The provided code is invalid") ? y(`${e.reason} ${r}`) : (e.reason.includes("The provided twoFaToken is invalid") || e.reason.includes("Token has expired")) && (console.warn(e), y("Something went wrong. Refresh the page and try again."), window.location.href.includes("twoFaToken") && window.history.replaceState({}, document.title, window.location.href.replaceAll(/(twoFaToken|userId)=[^&]*&?/g, "")));
|
|
58
59
|
},
|
|
59
|
-
onSuccess:
|
|
60
|
-
}), { mutate:
|
|
61
|
-
|
|
62
|
-
} }),
|
|
63
|
-
|
|
60
|
+
onSuccess: C
|
|
61
|
+
}), { mutate: O, isSuccess: k, isPending: A } = i({ onError: (e) => {
|
|
62
|
+
y(e.reason);
|
|
63
|
+
} }), j = (t, n) => {
|
|
64
|
+
y(void 0), w({
|
|
64
65
|
username: t,
|
|
65
66
|
password: n,
|
|
66
67
|
authenticationReceipt: localStorage.getItem(e)
|
|
67
68
|
});
|
|
68
69
|
};
|
|
69
|
-
function
|
|
70
|
-
return e == null ? (
|
|
70
|
+
function M(e) {
|
|
71
|
+
return e == null ? (y("You did not first log in with your password or a third-party identity provider."), !1) : !0;
|
|
71
72
|
}
|
|
72
73
|
return {
|
|
73
|
-
step:
|
|
74
|
-
onStepChange:
|
|
75
|
-
submitUsernameAndPassword:
|
|
76
|
-
submitOneTimePassword: (e, t =
|
|
77
|
-
|
|
78
|
-
userId:
|
|
79
|
-
twoFaToken:
|
|
74
|
+
step: g,
|
|
75
|
+
onStepChange: _,
|
|
76
|
+
submitUsernameAndPassword: j,
|
|
77
|
+
submitOneTimePassword: (e, t = g === "RECOVERY_CODE" ? "RECOVERY_CODE" : "TOTP") => {
|
|
78
|
+
y(void 0), M(b) && E({
|
|
79
|
+
userId: b.userId,
|
|
80
|
+
twoFaToken: b.twoFaToken,
|
|
80
81
|
otpCode: e,
|
|
81
82
|
otpType: t
|
|
82
83
|
});
|
|
83
84
|
},
|
|
84
|
-
errorMessage:
|
|
85
|
-
loginIsPending:
|
|
85
|
+
errorMessage: v,
|
|
86
|
+
loginIsPending: T || D,
|
|
86
87
|
beginTwoFactorAuthReset: (e) => {
|
|
87
|
-
|
|
88
|
-
userId:
|
|
89
|
-
twoFaToken:
|
|
88
|
+
y(void 0), M(b) && O({
|
|
89
|
+
userId: b.userId,
|
|
90
|
+
twoFaToken: b.twoFaToken,
|
|
90
91
|
twoFaResetEndpoint: e
|
|
91
92
|
});
|
|
92
93
|
},
|
|
93
|
-
twoFactorAuthResetIsPending:
|
|
94
|
-
twoFactorAuthResetIsSuccess:
|
|
94
|
+
twoFactorAuthResetIsPending: A,
|
|
95
|
+
twoFactorAuthResetIsSuccess: k
|
|
95
96
|
};
|
|
96
97
|
}
|
|
97
98
|
//#endregion
|
|
98
|
-
export {
|
|
99
|
+
export { f as default };
|
|
99
100
|
|
|
100
101
|
//# sourceMappingURL=useLogin.js.map
|