synapse-react-client 4.0.9 → 4.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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/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.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 +113 -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.js.map +1 -1
- 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/json-rx/JsonRx.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/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.js.map +1 -1
- 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.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/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.js.map +1 -1
- package/dist/components/Forum/DiscussionSearchResult.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/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/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.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.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.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/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.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/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/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 +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataAccessRequestAccessorsEditor.js","names":[],"sources":["../../../../src/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/DataAccessRequestAccessorsEditor.tsx"],"sourcesContent":["import { useGetCurrentUserProfile } from '@/synapse-queries'\nimport {\n Button,\n FormControlLabel,\n Radio,\n RadioGroup,\n Stack,\n Typography,\n} from '@mui/material'\nimport {\n AccessorChange,\n AccessType,\n TYPE_FILTER,\n UserGroupHeader,\n} from '@sage-bionetworks/synapse-types'\nimport { ReactNode } from 'react'\nimport IconSvg from '../../IconSvg/IconSvg'\nimport { UserBadge } from '../../UserCard/UserBadge'\nimport UserSearchBox from '../../UserSearchBox/UserSearchBox'\n\nexport type DataAccessRequestAccessorsEditorProps = {\n /* The current set of accessor changes for a data access request */\n accessorChanges: AccessorChange[]\n /* Invoked when the set of accessors is updated */\n onChange: (updater: (prevValue: AccessorChange[]) => AccessorChange[]) => void\n /* Whether this request is a renewal */\n isRenewal: boolean\n /* Text to show to inform the user about requirements accessors may need to meet */\n helpText: ReactNode\n}\n\n/**\n * Component that handles adding/removing/revoking accessors for a data access request.\n */\nexport default function DataAccessRequestAccessorsEditor(\n props: DataAccessRequestAccessorsEditorProps,\n) {\n const { accessorChanges, onChange, isRenewal, helpText } = props\n const { data: user } = useGetCurrentUserProfile()\n\n const onSelectUserCallback = (\n id: string | null,\n ugh: UserGroupHeader | null,\n ) => {\n if (ugh) {\n onChange(previousValue => {\n const currentAccessorIds = previousValue.map(ac => ac.userId)\n // if user is not already in the accessor list (prevent duplicates in accessor list)\n if (!currentAccessorIds.includes(ugh.ownerId)) {\n const selectedAccessor: AccessorChange = {\n userId: ugh.ownerId,\n type: AccessType.GAIN_ACCESS,\n }\n previousValue.push(selectedAccessor)\n }\n return previousValue\n })\n }\n }\n\n const onClearAccessor = (userId: string) => {\n onChange(previousValue => {\n return previousValue.filter(item => item.userId !== userId)\n })\n }\n\n // For renewal only\n const onAccessorAccessTypeChange = (\n accessType: AccessType,\n userId: string,\n ) => {\n onChange(previousValue => {\n const indexOfUser = previousValue.findIndex(\n item => item.userId === userId,\n )\n previousValue[indexOfUser].type = accessType\n return previousValue\n })\n }\n\n return (\n <>\n <Typography variant={'headline3'} sx={{ mt: 4, mb: 2 }}>\n Data Requesters\n </Typography>\n <Typography\n component={'div'}\n variant={'body1'}\n sx={{ mb: 1 }}\n className={'requester-label'}\n >\n {helpText}\n </Typography>\n <UserSearchBox\n inputId={'requesters'}\n typeFilter={TYPE_FILTER.USERS_ONLY}\n onChange={onSelectUserCallback}\n filterPredicate={userGroupHeader =>\n !accessorChanges\n .map(ac => ac.userId)\n .includes(userGroupHeader.ownerId)\n }\n value={null}\n />\n <Stack sx={{ my: 1, gap: 1 }}>\n {accessorChanges.map((ac, i) => {\n return (\n <div className={'list-items'} key={`accessor-${i}`}>\n <UserBadge\n userId={ac.userId}\n showAccountLevelIcon={true}\n disableLink={true}\n showFullName={true}\n />\n {\n // only display delete button if the user profile is not the current user and has not had access before\n user?.ownerId !== ac.userId &&\n ac.type === AccessType.GAIN_ACCESS && (\n <Button\n aria-label={`Remove user`}\n variant={'text'}\n sx={{\n ml: 1,\n px: 0,\n }}\n onClick={() => onClearAccessor(ac.userId)}\n >\n <IconSvg icon=\"clear\" />\n </Button>\n )\n }\n {\n // Renewal/Revoke data access, only display if isRenewal is true\n // TODO: It's possible to that the accessors list is in an illegal state with no way to recover -- see PLFM-7893\n isRenewal &&\n user?.ownerId !== ac.userId &&\n ac.type !== AccessType.GAIN_ACCESS && (\n <>\n <RadioGroup\n value={ac.type}\n onChange={(_event, value) =>\n onAccessorAccessTypeChange(\n value as AccessType,\n ac.userId,\n )\n }\n >\n <FormControlLabel\n control={<Radio />}\n label={'Renew'}\n value={AccessType.RENEW_ACCESS}\n />\n <FormControlLabel\n control={<Radio />}\n label={'Revoke'}\n value={AccessType.REVOKE_ACCESS}\n />\n </RadioGroup>\n </>\n )\n }\n </div>\n )\n })}\n </Stack>\n </>\n )\n}\n"],"mappings":";;;;;;;;;AAkCA,SAAwB,EACtB,GACA;CACA,IAAM,EAAE,oBAAiB,aAAU,cAAW,gBAAa,GACrD,EAAE,MAAM,MAAS,GAA0B,EAE3C,KACJ,GACA,MACG;AACH,EAAI,KACF,GAAS,MAAiB;AAGxB,OAAI,CAFuB,EAAc,KAAI,MAAM,EAAG,
|
|
1
|
+
{"version":3,"file":"DataAccessRequestAccessorsEditor.js","names":[],"sources":["../../../../src/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/DataAccessRequestAccessorsEditor.tsx"],"sourcesContent":["import { useGetCurrentUserProfile } from '@/synapse-queries'\nimport {\n Button,\n FormControlLabel,\n Radio,\n RadioGroup,\n Stack,\n Typography,\n} from '@mui/material'\nimport {\n AccessorChange,\n AccessType,\n TYPE_FILTER,\n UserGroupHeader,\n} from '@sage-bionetworks/synapse-types'\nimport { ReactNode } from 'react'\nimport IconSvg from '../../IconSvg/IconSvg'\nimport { UserBadge } from '../../UserCard/UserBadge'\nimport UserSearchBox from '../../UserSearchBox/UserSearchBox'\n\nexport type DataAccessRequestAccessorsEditorProps = {\n /* The current set of accessor changes for a data access request */\n accessorChanges: AccessorChange[]\n /* Invoked when the set of accessors is updated */\n onChange: (updater: (prevValue: AccessorChange[]) => AccessorChange[]) => void\n /* Whether this request is a renewal */\n isRenewal: boolean\n /* Text to show to inform the user about requirements accessors may need to meet */\n helpText: ReactNode\n}\n\n/**\n * Component that handles adding/removing/revoking accessors for a data access request.\n */\nexport default function DataAccessRequestAccessorsEditor(\n props: DataAccessRequestAccessorsEditorProps,\n) {\n const { accessorChanges, onChange, isRenewal, helpText } = props\n const { data: user } = useGetCurrentUserProfile()\n\n const onSelectUserCallback = (\n id: string | null,\n ugh: UserGroupHeader | null,\n ) => {\n if (ugh) {\n onChange(previousValue => {\n const currentAccessorIds = previousValue.map(ac => ac.userId)\n // if user is not already in the accessor list (prevent duplicates in accessor list)\n if (!currentAccessorIds.includes(ugh.ownerId)) {\n const selectedAccessor: AccessorChange = {\n userId: ugh.ownerId,\n type: AccessType.GAIN_ACCESS,\n }\n previousValue.push(selectedAccessor)\n }\n return previousValue\n })\n }\n }\n\n const onClearAccessor = (userId: string) => {\n onChange(previousValue => {\n return previousValue.filter(item => item.userId !== userId)\n })\n }\n\n // For renewal only\n const onAccessorAccessTypeChange = (\n accessType: AccessType,\n userId: string,\n ) => {\n onChange(previousValue => {\n const indexOfUser = previousValue.findIndex(\n item => item.userId === userId,\n )\n previousValue[indexOfUser].type = accessType\n return previousValue\n })\n }\n\n return (\n <>\n <Typography variant={'headline3'} sx={{ mt: 4, mb: 2 }}>\n Data Requesters\n </Typography>\n <Typography\n component={'div'}\n variant={'body1'}\n sx={{ mb: 1 }}\n className={'requester-label'}\n >\n {helpText}\n </Typography>\n <UserSearchBox\n inputId={'requesters'}\n typeFilter={TYPE_FILTER.USERS_ONLY}\n onChange={onSelectUserCallback}\n filterPredicate={userGroupHeader =>\n !accessorChanges\n .map(ac => ac.userId)\n .includes(userGroupHeader.ownerId)\n }\n value={null}\n />\n <Stack sx={{ my: 1, gap: 1 }}>\n {accessorChanges.map((ac, i) => {\n return (\n <div className={'list-items'} key={`accessor-${i}`}>\n <UserBadge\n userId={ac.userId}\n showAccountLevelIcon={true}\n disableLink={true}\n showFullName={true}\n />\n {\n // only display delete button if the user profile is not the current user and has not had access before\n user?.ownerId !== ac.userId &&\n ac.type === AccessType.GAIN_ACCESS && (\n <Button\n aria-label={`Remove user`}\n variant={'text'}\n sx={{\n ml: 1,\n px: 0,\n }}\n onClick={() => onClearAccessor(ac.userId)}\n >\n <IconSvg icon=\"clear\" />\n </Button>\n )\n }\n {\n // Renewal/Revoke data access, only display if isRenewal is true\n // TODO: It's possible to that the accessors list is in an illegal state with no way to recover -- see PLFM-7893\n isRenewal &&\n user?.ownerId !== ac.userId &&\n ac.type !== AccessType.GAIN_ACCESS && (\n <>\n <RadioGroup\n value={ac.type}\n onChange={(_event, value) =>\n onAccessorAccessTypeChange(\n value as AccessType,\n ac.userId,\n )\n }\n >\n <FormControlLabel\n control={<Radio />}\n label={'Renew'}\n value={AccessType.RENEW_ACCESS}\n />\n <FormControlLabel\n control={<Radio />}\n label={'Revoke'}\n value={AccessType.REVOKE_ACCESS}\n />\n </RadioGroup>\n </>\n )\n }\n </div>\n )\n })}\n </Stack>\n </>\n )\n}\n"],"mappings":";;;;;;;;;AAkCA,SAAwB,EACtB,GACA;CACA,IAAM,EAAE,oBAAiB,aAAU,cAAW,gBAAa,GACrD,EAAE,MAAM,MAAS,GAA0B,EAE3C,KACJ,GACA,MACG;AACH,EAAI,KACF,GAAS,MAAiB;AAGxB,OAAI,CAFuB,EAAc,KAAI,MAAM,EAAG,OAEjD,CAAmB,SAAS,EAAI,QAAQ,EAAE;IAC7C,IAAM,IAAmC;KACvC,QAAQ,EAAI;KACZ,MAAM,EAAW;KAClB;AACD,MAAc,KAAK,EAAiB;;AAEtC,UAAO;IACP;IAIA,KAAmB,MAAmB;AAC1C,KAAS,MACA,EAAc,QAAO,MAAQ,EAAK,WAAW,EAAO,CAC3D;IAIE,KACJ,GACA,MACG;AACH,KAAS,MAAiB;GACxB,IAAM,IAAc,EAAc,WAChC,MAAQ,EAAK,WAAW,EACzB;AAED,UADA,EAAc,GAAa,OAAO,GAC3B;IACP;;AAGJ,QACE,kBAAA,GAAA,EAAA,UAAA;EACE,kBAAC,GAAD;GAAY,SAAS;GAAa,IAAI;IAAE,IAAI;IAAG,IAAI;IAAG;aAAE;GAE3C,CAAA;EACb,kBAAC,GAAD;GACE,WAAW;GACX,SAAS;GACT,IAAI,EAAE,IAAI,GAAG;GACb,WAAW;aAEV;GACU,CAAA;EACb,kBAAC,GAAD;GACE,SAAS;GACT,YAAY,EAAY;GACxB,UAAU;GACV,kBAAiB,MACf,CAAC,EACE,KAAI,MAAM,EAAG,OAAO,CACpB,SAAS,EAAgB,QAAQ;GAEtC,OAAO;GACP,CAAA;EACF,kBAAC,GAAD;GAAO,IAAI;IAAE,IAAI;IAAG,KAAK;IAAG;aACzB,EAAgB,KAAK,GAAI,MAEtB,kBAAC,OAAD;IAAK,WAAW;cAAhB;KACE,kBAAC,GAAD;MACE,QAAQ,EAAG;MACX,sBAAsB;MACtB,aAAa;MACb,cAAc;MACd,CAAA;KAGA,GAAM,YAAY,EAAG,UACnB,EAAG,SAAS,EAAW,eACrB,kBAAC,GAAD;MACE,cAAY;MACZ,SAAS;MACT,IAAI;OACF,IAAI;OACJ,IAAI;OACL;MACD,eAAe,EAAgB,EAAG,OAAO;gBAEzC,kBAAC,GAAD,EAAS,MAAK,SAAU,CAAA;MACjB,CAAA;KAMb,KACE,GAAM,YAAY,EAAG,UACrB,EAAG,SAAS,EAAW,eACrB,kBAAA,GAAA,EAAA,UACE,kBAAC,GAAD;MACE,OAAO,EAAG;MACV,WAAW,GAAQ,MACjB,EACE,GACA,EAAG,OACJ;gBANL,CASE,kBAAC,GAAD;OACE,SAAS,kBAAC,GAAD,EAAS,CAAA;OAClB,OAAO;OACP,OAAO,EAAW;OAClB,CAAA,EACF,kBAAC,GAAD;OACE,SAAS,kBAAC,GAAD,EAAS,CAAA;OAClB,OAAO;OACP,OAAO,EAAW;OAClB,CAAA,CACS;SACZ,CAAA;KAGL;MAtD6B,YAAY,IAsDzC,CAER;GACI,CAAA;EACP,EAAA,CAAA"}
|
package/dist/components/AccessRequirementList/RequirementItem/SelfSignAccessRequirementItem.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SelfSignAccessRequirementItem.js","names":[],"sources":["../../../../src/components/AccessRequirementList/RequirementItem/SelfSignAccessRequirementItem.tsx"],"sourcesContent":["import {\n useCreateAccessApproval,\n useGetAccessRequirementStatus,\n useGetAccessRequirementWikiPageKey,\n useGetCurrentUserBundle,\n useGetCurrentUserProfile,\n} from '@/synapse-queries'\nimport { useSynapseContext } from '@/utils/context/SynapseContext'\nimport { isTermsOfUseAccessRequirement } from '@/utils/types/IsType'\nimport { Alert, Box, ButtonProps, Link, Typography } from '@mui/material'\nimport {\n ApprovalState,\n CreateAccessApprovalRequest,\n SelfSignAccessRequirement,\n TermsOfUseAccessRequirement,\n} from '@sage-bionetworks/synapse-types'\nimport { useState } from 'react'\nimport MarkdownSynapse from '../../Markdown/MarkdownSynapse'\nimport { RequirementItemStatus } from '../AccessApprovalCheckMark'\nimport RequirementItem from './RequirementItem'\n\nexport type SelfSignAccessRequirementItemProps = {\n accessRequirement: SelfSignAccessRequirement | TermsOfUseAccessRequirement\n onHide: () => void\n}\n\n/**\n * Renders a {@link RequirementItem} for an self-sign Access Requirement, including {@link SelfSignAccessRequirement} or\n * {@link TermsOfUseAccessRequirement}.\n *\n * For {@link ManagedACTAccessRequirement}s, see {@link RequestDataAccess}\n */\nexport default function SelfSignAccessRequirementItem(\n props: SelfSignAccessRequirementItemProps,\n) {\n const { accessRequirement, onHide } = props\n const { isAuthenticated } = useSynapseContext()\n const isTermsOfUse = isTermsOfUseAccessRequirement(accessRequirement)\n\n const { data: user } = useGetCurrentUserProfile()\n const { data: userBundle } = useGetCurrentUserBundle()\n\n const certificationRequirementNotMet =\n isAuthenticated &&\n userBundle &&\n !isTermsOfUse &&\n accessRequirement.isCertifiedUserRequired &&\n !userBundle.isCertified\n const verificationRequirementNotMet =\n isAuthenticated &&\n userBundle &&\n !isTermsOfUse &&\n accessRequirement.isValidatedProfileRequired &&\n !userBundle.isVerified\n\n const { data: accessRequirementStatus, isLoading: isLoadingStatus } =\n useGetAccessRequirementStatus(String(accessRequirement.id))\n\n const isApproved = accessRequirementStatus?.isApproved\n\n const { data: wikiPage } = useGetAccessRequirementWikiPageKey(\n accessRequirement.id.toString(),\n // TermsOfUse ARs may have the terms embedded in the AR or an associated Wiki.\n )\n\n const [showTerms, setShowTerms] = useState<boolean>(false)\n\n const {\n mutate: createAccessApproval,\n isPending: createAccessApprovalIsPending,\n error,\n } = useCreateAccessApproval({\n onError: err => {\n console.error('Error creating access approval: ', err)\n },\n })\n\n const onAcceptClicked = () => {\n const accessApprovalRequest: CreateAccessApprovalRequest = {\n requirementId: accessRequirement?.id,\n submitterId: user?.ownerId!,\n accessorId: user?.ownerId!,\n state: ApprovalState.APPROVED,\n }\n\n createAccessApproval(accessApprovalRequest)\n }\n\n let renderedTerms = <></>\n if (isTermsOfUse && accessRequirement.termsOfUse) {\n renderedTerms = <MarkdownSynapse markdown={accessRequirement.termsOfUse} />\n } else if (wikiPage) {\n renderedTerms = (\n <MarkdownSynapse\n wikiId={wikiPage?.wikiPageId}\n ownerId={wikiPage?.ownerObjectId}\n objectType={wikiPage?.ownerObjectType}\n />\n )\n }\n let actions: ButtonProps[] | undefined = undefined\n\n if (isAuthenticated && !isApproved) {\n let acceptButtonText = 'I Accept Terms of Use'\n let acceptButtonDisabled = false\n if (certificationRequirementNotMet || verificationRequirementNotMet) {\n acceptButtonDisabled = true\n acceptButtonText = `You must ${\n certificationRequirementNotMet ? 'be certified' : ''\n }${\n certificationRequirementNotMet && verificationRequirementNotMet\n ? ' and '\n : ''\n }${\n verificationRequirementNotMet ? 'have a validated user profile' : ''\n } to accept`\n }\n\n actions = [\n {\n variant: 'outlined',\n onClick: onAcceptClicked,\n children: acceptButtonText,\n disabled: createAccessApprovalIsPending || acceptButtonDisabled,\n },\n {\n variant: 'text',\n onClick: onHide,\n children: 'I do not accept',\n },\n ]\n }\n\n return (\n <RequirementItem\n data-testid=\"SelfSignAccessRequirementItem\"\n status={\n isLoadingStatus\n ? RequirementItemStatus.LOADING\n : isApproved\n ? RequirementItemStatus.COMPLETE\n : RequirementItemStatus.LOCKED\n }\n actions={actions}\n >\n {isApproved ? (\n <>\n <Typography variant={'body1'}>\n You have accepted the terms of use.{' '}\n <Link role=\"button\" onClick={() => setShowTerms(!showTerms)}>\n {showTerms ? 'Hide Terms' : 'View Terms'}\n </Link>\n </Typography>\n {showTerms && <Box sx={{ my: 1 }}>{renderedTerms}</Box>}\n </>\n ) : (\n renderedTerms\n )}\n {error && <Alert severity=\"error\">{error.reason}</Alert>}\n </RequirementItem>\n )\n}\n"],"mappings":";;;;;;;;;;;;;AAgCA,SAAwB,EACtB,GACA;CACA,IAAM,EAAE,sBAAmB,cAAW,GAChC,EAAE,uBAAoB,GAAmB,EACzC,IAAe,EAA8B,EAAkB,EAE/D,EAAE,MAAM,MAAS,GAA0B,EAC3C,EAAE,MAAM,MAAe,GAAyB,EAEhD,IACJ,KACA,KACA,CAAC,KACD,EAAkB,2BAClB,CAAC,EAAW,aACR,IACJ,KACA,KACA,CAAC,KACD,EAAkB,8BAClB,CAAC,EAAW,YAER,EAAE,MAAM,GAAyB,WAAW,MAChD,EAA8B,OAAO,EAAkB,GAAG,CAAC,EAEvD,IAAa,GAAyB,YAEtC,EAAE,MAAM,MAAa,EACzB,EAAkB,GAAG,UAAU,CAEhC,EAEK,CAAC,GAAW,KAAgB,EAAkB,GAAM,EAEpD,EACJ,QAAQ,GACR,WAAW,GACX,aACE,EAAwB,EAC1B,UAAS,MAAO;AACd,UAAQ,MAAM,oCAAoC,EAAI;IAEzD,CAAC,EAEI,UAAwB;AAQ5B,
|
|
1
|
+
{"version":3,"file":"SelfSignAccessRequirementItem.js","names":[],"sources":["../../../../src/components/AccessRequirementList/RequirementItem/SelfSignAccessRequirementItem.tsx"],"sourcesContent":["import {\n useCreateAccessApproval,\n useGetAccessRequirementStatus,\n useGetAccessRequirementWikiPageKey,\n useGetCurrentUserBundle,\n useGetCurrentUserProfile,\n} from '@/synapse-queries'\nimport { useSynapseContext } from '@/utils/context/SynapseContext'\nimport { isTermsOfUseAccessRequirement } from '@/utils/types/IsType'\nimport { Alert, Box, ButtonProps, Link, Typography } from '@mui/material'\nimport {\n ApprovalState,\n CreateAccessApprovalRequest,\n SelfSignAccessRequirement,\n TermsOfUseAccessRequirement,\n} from '@sage-bionetworks/synapse-types'\nimport { useState } from 'react'\nimport MarkdownSynapse from '../../Markdown/MarkdownSynapse'\nimport { RequirementItemStatus } from '../AccessApprovalCheckMark'\nimport RequirementItem from './RequirementItem'\n\nexport type SelfSignAccessRequirementItemProps = {\n accessRequirement: SelfSignAccessRequirement | TermsOfUseAccessRequirement\n onHide: () => void\n}\n\n/**\n * Renders a {@link RequirementItem} for an self-sign Access Requirement, including {@link SelfSignAccessRequirement} or\n * {@link TermsOfUseAccessRequirement}.\n *\n * For {@link ManagedACTAccessRequirement}s, see {@link RequestDataAccess}\n */\nexport default function SelfSignAccessRequirementItem(\n props: SelfSignAccessRequirementItemProps,\n) {\n const { accessRequirement, onHide } = props\n const { isAuthenticated } = useSynapseContext()\n const isTermsOfUse = isTermsOfUseAccessRequirement(accessRequirement)\n\n const { data: user } = useGetCurrentUserProfile()\n const { data: userBundle } = useGetCurrentUserBundle()\n\n const certificationRequirementNotMet =\n isAuthenticated &&\n userBundle &&\n !isTermsOfUse &&\n accessRequirement.isCertifiedUserRequired &&\n !userBundle.isCertified\n const verificationRequirementNotMet =\n isAuthenticated &&\n userBundle &&\n !isTermsOfUse &&\n accessRequirement.isValidatedProfileRequired &&\n !userBundle.isVerified\n\n const { data: accessRequirementStatus, isLoading: isLoadingStatus } =\n useGetAccessRequirementStatus(String(accessRequirement.id))\n\n const isApproved = accessRequirementStatus?.isApproved\n\n const { data: wikiPage } = useGetAccessRequirementWikiPageKey(\n accessRequirement.id.toString(),\n // TermsOfUse ARs may have the terms embedded in the AR or an associated Wiki.\n )\n\n const [showTerms, setShowTerms] = useState<boolean>(false)\n\n const {\n mutate: createAccessApproval,\n isPending: createAccessApprovalIsPending,\n error,\n } = useCreateAccessApproval({\n onError: err => {\n console.error('Error creating access approval: ', err)\n },\n })\n\n const onAcceptClicked = () => {\n const accessApprovalRequest: CreateAccessApprovalRequest = {\n requirementId: accessRequirement?.id,\n submitterId: user?.ownerId!,\n accessorId: user?.ownerId!,\n state: ApprovalState.APPROVED,\n }\n\n createAccessApproval(accessApprovalRequest)\n }\n\n let renderedTerms = <></>\n if (isTermsOfUse && accessRequirement.termsOfUse) {\n renderedTerms = <MarkdownSynapse markdown={accessRequirement.termsOfUse} />\n } else if (wikiPage) {\n renderedTerms = (\n <MarkdownSynapse\n wikiId={wikiPage?.wikiPageId}\n ownerId={wikiPage?.ownerObjectId}\n objectType={wikiPage?.ownerObjectType}\n />\n )\n }\n let actions: ButtonProps[] | undefined = undefined\n\n if (isAuthenticated && !isApproved) {\n let acceptButtonText = 'I Accept Terms of Use'\n let acceptButtonDisabled = false\n if (certificationRequirementNotMet || verificationRequirementNotMet) {\n acceptButtonDisabled = true\n acceptButtonText = `You must ${\n certificationRequirementNotMet ? 'be certified' : ''\n }${\n certificationRequirementNotMet && verificationRequirementNotMet\n ? ' and '\n : ''\n }${\n verificationRequirementNotMet ? 'have a validated user profile' : ''\n } to accept`\n }\n\n actions = [\n {\n variant: 'outlined',\n onClick: onAcceptClicked,\n children: acceptButtonText,\n disabled: createAccessApprovalIsPending || acceptButtonDisabled,\n },\n {\n variant: 'text',\n onClick: onHide,\n children: 'I do not accept',\n },\n ]\n }\n\n return (\n <RequirementItem\n data-testid=\"SelfSignAccessRequirementItem\"\n status={\n isLoadingStatus\n ? RequirementItemStatus.LOADING\n : isApproved\n ? RequirementItemStatus.COMPLETE\n : RequirementItemStatus.LOCKED\n }\n actions={actions}\n >\n {isApproved ? (\n <>\n <Typography variant={'body1'}>\n You have accepted the terms of use.{' '}\n <Link role=\"button\" onClick={() => setShowTerms(!showTerms)}>\n {showTerms ? 'Hide Terms' : 'View Terms'}\n </Link>\n </Typography>\n {showTerms && <Box sx={{ my: 1 }}>{renderedTerms}</Box>}\n </>\n ) : (\n renderedTerms\n )}\n {error && <Alert severity=\"error\">{error.reason}</Alert>}\n </RequirementItem>\n )\n}\n"],"mappings":";;;;;;;;;;;;;AAgCA,SAAwB,EACtB,GACA;CACA,IAAM,EAAE,sBAAmB,cAAW,GAChC,EAAE,uBAAoB,GAAmB,EACzC,IAAe,EAA8B,EAAkB,EAE/D,EAAE,MAAM,MAAS,GAA0B,EAC3C,EAAE,MAAM,MAAe,GAAyB,EAEhD,IACJ,KACA,KACA,CAAC,KACD,EAAkB,2BAClB,CAAC,EAAW,aACR,IACJ,KACA,KACA,CAAC,KACD,EAAkB,8BAClB,CAAC,EAAW,YAER,EAAE,MAAM,GAAyB,WAAW,MAChD,EAA8B,OAAO,EAAkB,GAAG,CAAC,EAEvD,IAAa,GAAyB,YAEtC,EAAE,MAAM,MAAa,EACzB,EAAkB,GAAG,UAAU,CAEhC,EAEK,CAAC,GAAW,KAAgB,EAAkB,GAAM,EAEpD,EACJ,QAAQ,GACR,WAAW,GACX,aACE,EAAwB,EAC1B,UAAS,MAAO;AACd,UAAQ,MAAM,oCAAoC,EAAI;IAEzD,CAAC,EAEI,UAAwB;AAQ5B,IAAqB;GANnB,eAAe,GAAmB;GAClC,aAAa,GAAM;GACnB,YAAY,GAAM;GAClB,OAAO,EAAc;GAGF,CAAsB;IAGzC,IAAgB,kBAAA,GAAA,EAAK,CAAA;AACzB,CAAI,KAAgB,EAAkB,aACpC,IAAgB,kBAAC,GAAD,EAAiB,UAAU,EAAkB,YAAc,CAAA,GAClE,MACT,IACE,kBAAC,GAAD;EACE,QAAQ,GAAU;EAClB,SAAS,GAAU;EACnB,YAAY,GAAU;EACtB,CAAA;CAGN,IAAI;AAEJ,KAAI,KAAmB,CAAC,GAAY;EAClC,IAAI,IAAmB,yBACnB,IAAuB;AAc3B,GAbI,KAAkC,OACpC,IAAuB,IACvB,IAAmB,YACjB,IAAiC,iBAAiB,KAElD,KAAkC,IAC9B,UACA,KAEJ,IAAgC,kCAAkC,GACnE,cAGH,IAAU,CACR;GACE,SAAS;GACT,SAAS;GACT,UAAU;GACV,UAAU,KAAiC;GAC5C,EACD;GACE,SAAS;GACT,SAAS;GACT,UAAU;GACX,CACF;;AAGH,QACE,kBAAC,GAAD;EACE,eAAY;EACZ,QACE,IACI,EAAsB,UACtB,IACA,EAAsB,WACtB,EAAsB;EAEnB;YATX,CAWG,IACC,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD;GAAY,SAAS;aAArB;IAA8B;IACQ;IACpC,kBAAC,GAAD;KAAM,MAAK;KAAS,eAAe,EAAa,CAAC,EAAU;eACxD,IAAY,eAAe;KACvB,CAAA;IACI;MACZ,KAAa,kBAAC,GAAD;GAAK,IAAI,EAAE,IAAI,GAAG;aAAG;GAAoB,CAAA,CACtD,EAAA,CAAA,GAEH,GAED,KAAS,kBAAC,GAAD;GAAO,UAAS;aAAS,EAAM;GAAe,CAAA,CACxC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AccessRequirementRelatedProjectsList.js","names":[],"sources":["../../../src/components/AccessRequirementRelatedProjectsList/AccessRequirementRelatedProjectsList.tsx"],"sourcesContent":["import React from 'react'\nimport { useSearchAccessRequirementsInfinite } from '@/synapse-queries'\nimport { Alert, List, ListItem, Typography } from '@mui/material'\nimport { AccessRequirementSearchRequest } from '@sage-bionetworks/synapse-types'\nimport pluralize from 'pluralize'\nimport { EntityLink } from '../EntityLink'\n\nexport type AccessRequirementRelatedProjectsListProps = {\n accessRequirementId: number\n}\n\nexport const AccessRequirementRelatedProjectsList = (\n props: AccessRequirementRelatedProjectsListProps,\n): React.ReactNode => {\n const searchRequest: Omit<AccessRequirementSearchRequest, 'nextPageToken'> = {\n ids: [props.accessRequirementId],\n }\n\n const { data, isError, error } =\n useSearchAccessRequirementsInfinite(searchRequest)\n const ar = data?.pages.flatMap(page => page.results)[0] ?? undefined\n\n const nRelatedProjects = ar?.relatedProjectIds.length || 0\n const relatedProjectsTitle = `${pluralize(\n 'project',\n nRelatedProjects,\n true,\n )}${nRelatedProjects > 0 ? ':' : ''}`\n\n return (\n <>\n {ar && (\n <>\n <Typography variant=\"body1\">{relatedProjectsTitle}</Typography>\n <List sx={{ listStyleType: 'disc', pl: 4 }}>\n {ar.relatedProjectIds.map(projectId => (\n <ListItem\n sx={{\n display: 'list-item',\n py: '4px',\n // remove extra margin added by type.less to p tags\n '.no-margin-y': { my: 0 },\n }}\n key={projectId}\n >\n <EntityLink\n entity={projectId}\n link={false}\n showIcon={false}\n className=\"no-margin-y\"\n />\n </ListItem>\n ))}\n </List>\n </>\n )}\n {isError && <Alert severity=\"error\">{error.message}</Alert>}\n </>\n )\n}\n"],"mappings":";;;;;;;;AAWA,IAAa,KACX,MACoB;CAKpB,IAAM,EAAE,SAAM,YAAS,aACrB,
|
|
1
|
+
{"version":3,"file":"AccessRequirementRelatedProjectsList.js","names":[],"sources":["../../../src/components/AccessRequirementRelatedProjectsList/AccessRequirementRelatedProjectsList.tsx"],"sourcesContent":["import React from 'react'\nimport { useSearchAccessRequirementsInfinite } from '@/synapse-queries'\nimport { Alert, List, ListItem, Typography } from '@mui/material'\nimport { AccessRequirementSearchRequest } from '@sage-bionetworks/synapse-types'\nimport pluralize from 'pluralize'\nimport { EntityLink } from '../EntityLink'\n\nexport type AccessRequirementRelatedProjectsListProps = {\n accessRequirementId: number\n}\n\nexport const AccessRequirementRelatedProjectsList = (\n props: AccessRequirementRelatedProjectsListProps,\n): React.ReactNode => {\n const searchRequest: Omit<AccessRequirementSearchRequest, 'nextPageToken'> = {\n ids: [props.accessRequirementId],\n }\n\n const { data, isError, error } =\n useSearchAccessRequirementsInfinite(searchRequest)\n const ar = data?.pages.flatMap(page => page.results)[0] ?? undefined\n\n const nRelatedProjects = ar?.relatedProjectIds.length || 0\n const relatedProjectsTitle = `${pluralize(\n 'project',\n nRelatedProjects,\n true,\n )}${nRelatedProjects > 0 ? ':' : ''}`\n\n return (\n <>\n {ar && (\n <>\n <Typography variant=\"body1\">{relatedProjectsTitle}</Typography>\n <List sx={{ listStyleType: 'disc', pl: 4 }}>\n {ar.relatedProjectIds.map(projectId => (\n <ListItem\n sx={{\n display: 'list-item',\n py: '4px',\n // remove extra margin added by type.less to p tags\n '.no-margin-y': { my: 0 },\n }}\n key={projectId}\n >\n <EntityLink\n entity={projectId}\n link={false}\n showIcon={false}\n className=\"no-margin-y\"\n />\n </ListItem>\n ))}\n </List>\n </>\n )}\n {isError && <Alert severity=\"error\">{error.message}</Alert>}\n </>\n )\n}\n"],"mappings":";;;;;;;;AAWA,IAAa,KACX,MACoB;CAKpB,IAAM,EAAE,SAAM,YAAS,aACrB,EAAoC,EAJpC,KAAK,CAAC,EAAM,oBAAoB,EAII,CAAc,EAC9C,IAAK,GAAM,MAAM,SAAQ,MAAQ,EAAK,QAAQ,CAAC,MAAM,KAAA,GAErD,IAAmB,GAAI,kBAAkB,UAAU,GACnD,IAAuB,GAAG,EAC9B,WACA,GACA,GACD,GAAG,IAAmB,IAAI,MAAM;AAEjC,QACE,kBAAA,GAAA,EAAA,UAAA,CACG,KACC,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD;EAAY,SAAQ;YAAS;EAAkC,CAAA,EAC/D,kBAAC,GAAD;EAAM,IAAI;GAAE,eAAe;GAAQ,IAAI;GAAG;YACvC,EAAG,kBAAkB,KAAI,MACxB,kBAAC,GAAD;GACE,IAAI;IACF,SAAS;IACT,IAAI;IAEJ,gBAAgB,EAAE,IAAI,GAAG;IAC1B;aAGD,kBAAC,GAAD;IACE,QAAQ;IACR,MAAM;IACN,UAAU;IACV,WAAU;IACV,CAAA;GACO,EARJ,EAQI,CACX;EACG,CAAA,CACN,EAAA,CAAA,EAEJ,KAAW,kBAAC,GAAD;EAAO,UAAS;YAAS,EAAM;EAAgB,CAAA,CAC1D,EAAA,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AccessTokenCard.js","names":[],"sources":["../../../../src/components/AccessTokenPage/AccessTokenCard/AccessTokenCard.tsx"],"sourcesContent":["import { useDeletePersonalAccessToken } from '@/synapse-queries/user/usePersonalAccessToken'\nimport DeleteTwoToneIcon from '@mui/icons-material/DeleteTwoTone'\nimport {\n Box,\n Card,\n IconButton,\n Stack,\n Tooltip,\n Typography,\n} from '@mui/material'\nimport {\n AccessTokenRecord,\n scopeDescriptions,\n} from '@sage-bionetworks/synapse-types'\nimport dayjs from 'dayjs'\nimport relativeTime from 'dayjs/plugin/relativeTime'\nimport { noop } from 'lodash-es'\nimport { useCallback, useState } from 'react'\nimport IconSvg from '../../IconSvg/IconSvg'\nimport WarningDialog from '../../SynapseForm/WarningDialog'\n\ndayjs.extend(relativeTime)\n\nexport type AccessTokenCardProps = {\n /** Record referring to an access token, not a token itself */\n accessToken: AccessTokenRecord\n onDelete?: () => void\n}\n\nexport const EXPIRED_PAT_WARNING =\n 'This token has expired. It no longer works and can only be deleted.'\n\nexport function AccessTokenCard(props: AccessTokenCardProps) {\n const { accessToken, onDelete = noop } = props\n const [showModal, setShowModal] = useState(false)\n\n const isExpired = accessToken.state === 'EXPIRED'\n\n const { mutate: deleteToken, isPending: deleteIsPending } =\n useDeletePersonalAccessToken({\n onSuccess: () => {\n onDelete()\n },\n throwOnError: true,\n })\n\n const onClickDeleteButton = useCallback(() => {\n if (isExpired) {\n // token no longer works, no need for warning/confirmation\n deleteToken(accessToken.id)\n } else {\n setShowModal(true)\n }\n }, [accessToken.id, deleteToken, isExpired])\n\n const warningDialog = (\n <WarningDialog\n title={'Confirm Deletion'}\n content={\n <>\n <Typography variant={'body1'}>\n If you delete this token, any applications using it will stop\n working. This action cannot be undone.\n </Typography>\n <Typography\n variant={'body1'}\n sx={{\n fontWeight: '700',\n }}\n >\n Are you sure you want to delete this token?\n </Typography>\n </>\n }\n confirmButtonText={'Delete Token'}\n onCancel={() => setShowModal(false)}\n onConfirm={() => {\n deleteToken(accessToken.id)\n setShowModal(false)\n }}\n confirmButtonColor=\"error\"\n open={showModal}\n />\n )\n return (\n <Card\n sx={{\n my: 2,\n height: '120px',\n width: '100%',\n p: 1.5,\n pl: 4,\n backgroundColor: isExpired ? '#fcf8e3' : 'inherit',\n }}\n >\n {warningDialog}\n <Box\n sx={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n height: '100%',\n }}\n >\n <Stack\n sx={{\n flexGrow: 1,\n gap: 1,\n justifyContent: 'space-between',\n }}\n >\n <Typography variant={'headline3'} sx={{ fontSize: '16px' }}>\n {accessToken.name}\n </Typography>\n <div>\n <span>Permissions: </span>\n {accessToken.scopes.map(scope => {\n const scopeDescriptionKey =\n scope as keyof typeof scopeDescriptions\n let scopeDescription = scopeDescriptions[scopeDescriptionKey]\n if (scopeDescription === undefined) {\n const titleCaseScope =\n scope.charAt(0).toUpperCase() + scope.slice(1)\n scopeDescription = {\n displayName: titleCaseScope,\n description: titleCaseScope,\n }\n }\n return (\n <Tooltip key={scope} title={scopeDescription.description}>\n <Typography\n component={'span'}\n variant={'smallText1'}\n sx={{ mx: 0.25, cursor: 'default', color: 'primary.main' }}\n >\n {scopeDescription.displayName}\n </Typography>\n </Tooltip>\n )\n })}\n </div>\n <div>\n <Typography component={'span'} variant={'smallText1'}>\n Last used {dayjs(accessToken.lastUsed).fromNow()}\n </Typography>\n <Typography\n component={'span'}\n variant={'smallText1'}\n sx={{\n color: 'grey.700',\n }}\n >\n {' | '}\n </Typography>\n <Typography component={'span'} variant={'smallText1'}>\n Created {dayjs(accessToken.createdOn).fromNow()}\n </Typography>\n </div>\n </Stack>\n <Box\n sx={{\n alignSelf: 'flex-start',\n display: 'flex',\n gap: 1,\n alignItems: 'center',\n }}\n >\n {isExpired && (\n <Tooltip title={EXPIRED_PAT_WARNING} placement={'top'}>\n <IconButton>\n <IconSvg\n icon=\"warning\"\n sx={{ color: 'warning.main', fontSize: 'inherit' }}\n wrap={false}\n />\n </IconButton>\n </Tooltip>\n )}\n <Tooltip title={'Delete Token'} placement={'top'}>\n <IconButton\n disabled={deleteIsPending}\n color=\"error\"\n onClick={onClickDeleteButton}\n >\n <DeleteTwoToneIcon />\n </IconButton>\n </Tooltip>\n </Box>\n </Box>\n </Card>\n )\n}\n"],"mappings":";;;;;;;;;;;;AAqBA,EAAM,OAAO,EAAa;AAQ1B,IAAa,IACX;AAEF,SAAgB,EAAgB,GAA6B;CAC3D,IAAM,EAAE,gBAAa,cAAW,MAAS,GACnC,CAAC,GAAW,KAAgB,EAAS,GAAM,EAE3C,IAAY,EAAY,UAAU,WAElC,EAAE,QAAQ,GAAa,WAAW,MACtC,EAA6B;EAC3B,iBAAiB;AACf,MAAU;;EAEZ,cAAc;EACf,CAAC,EAEE,IAAsB,QAAkB;AAC5C,EAAI,IAEF,EAAY,EAAY,GAAG,GAE3B,EAAa,GAAK;IAEnB;EAAC,EAAY;EAAI;EAAa;EAAU,CAAC;AA+B5C,QACE,kBAAC,GAAD;EACE,IAAI;GACF,IAAI;GACJ,QAAQ;GACR,OAAO;GACP,GAAG;GACH,IAAI;GACJ,iBAAiB,IAAY,YAAY;GAC1C;YARH,CA7BA,kBAAC,GAAD;GACE,OAAO;GACP,SACE,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD;IAAY,SAAS;cAAS;IAGjB,CAAA,EACb,kBAAC,GAAD;IACE,SAAS;IACT,IAAI,EACF,YAAY,OACb;cACF;IAEY,CAAA,CACZ,EAAA,CAAA;GAEL,mBAAmB;GACnB,gBAAgB,EAAa,GAAM;GACnC,iBAAiB;AAEf,IADA,EAAY,EAAY,GAAG,EAC3B,EAAa,GAAM;;GAErB,oBAAmB;GACnB,MAAM;GACN,
|
|
1
|
+
{"version":3,"file":"AccessTokenCard.js","names":[],"sources":["../../../../src/components/AccessTokenPage/AccessTokenCard/AccessTokenCard.tsx"],"sourcesContent":["import { useDeletePersonalAccessToken } from '@/synapse-queries/user/usePersonalAccessToken'\nimport DeleteTwoToneIcon from '@mui/icons-material/DeleteTwoTone'\nimport {\n Box,\n Card,\n IconButton,\n Stack,\n Tooltip,\n Typography,\n} from '@mui/material'\nimport {\n AccessTokenRecord,\n scopeDescriptions,\n} from '@sage-bionetworks/synapse-types'\nimport dayjs from 'dayjs'\nimport relativeTime from 'dayjs/plugin/relativeTime'\nimport { noop } from 'lodash-es'\nimport { useCallback, useState } from 'react'\nimport IconSvg from '../../IconSvg/IconSvg'\nimport WarningDialog from '../../SynapseForm/WarningDialog'\n\ndayjs.extend(relativeTime)\n\nexport type AccessTokenCardProps = {\n /** Record referring to an access token, not a token itself */\n accessToken: AccessTokenRecord\n onDelete?: () => void\n}\n\nexport const EXPIRED_PAT_WARNING =\n 'This token has expired. It no longer works and can only be deleted.'\n\nexport function AccessTokenCard(props: AccessTokenCardProps) {\n const { accessToken, onDelete = noop } = props\n const [showModal, setShowModal] = useState(false)\n\n const isExpired = accessToken.state === 'EXPIRED'\n\n const { mutate: deleteToken, isPending: deleteIsPending } =\n useDeletePersonalAccessToken({\n onSuccess: () => {\n onDelete()\n },\n throwOnError: true,\n })\n\n const onClickDeleteButton = useCallback(() => {\n if (isExpired) {\n // token no longer works, no need for warning/confirmation\n deleteToken(accessToken.id)\n } else {\n setShowModal(true)\n }\n }, [accessToken.id, deleteToken, isExpired])\n\n const warningDialog = (\n <WarningDialog\n title={'Confirm Deletion'}\n content={\n <>\n <Typography variant={'body1'}>\n If you delete this token, any applications using it will stop\n working. This action cannot be undone.\n </Typography>\n <Typography\n variant={'body1'}\n sx={{\n fontWeight: '700',\n }}\n >\n Are you sure you want to delete this token?\n </Typography>\n </>\n }\n confirmButtonText={'Delete Token'}\n onCancel={() => setShowModal(false)}\n onConfirm={() => {\n deleteToken(accessToken.id)\n setShowModal(false)\n }}\n confirmButtonColor=\"error\"\n open={showModal}\n />\n )\n return (\n <Card\n sx={{\n my: 2,\n height: '120px',\n width: '100%',\n p: 1.5,\n pl: 4,\n backgroundColor: isExpired ? '#fcf8e3' : 'inherit',\n }}\n >\n {warningDialog}\n <Box\n sx={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n height: '100%',\n }}\n >\n <Stack\n sx={{\n flexGrow: 1,\n gap: 1,\n justifyContent: 'space-between',\n }}\n >\n <Typography variant={'headline3'} sx={{ fontSize: '16px' }}>\n {accessToken.name}\n </Typography>\n <div>\n <span>Permissions: </span>\n {accessToken.scopes.map(scope => {\n const scopeDescriptionKey =\n scope as keyof typeof scopeDescriptions\n let scopeDescription = scopeDescriptions[scopeDescriptionKey]\n if (scopeDescription === undefined) {\n const titleCaseScope =\n scope.charAt(0).toUpperCase() + scope.slice(1)\n scopeDescription = {\n displayName: titleCaseScope,\n description: titleCaseScope,\n }\n }\n return (\n <Tooltip key={scope} title={scopeDescription.description}>\n <Typography\n component={'span'}\n variant={'smallText1'}\n sx={{ mx: 0.25, cursor: 'default', color: 'primary.main' }}\n >\n {scopeDescription.displayName}\n </Typography>\n </Tooltip>\n )\n })}\n </div>\n <div>\n <Typography component={'span'} variant={'smallText1'}>\n Last used {dayjs(accessToken.lastUsed).fromNow()}\n </Typography>\n <Typography\n component={'span'}\n variant={'smallText1'}\n sx={{\n color: 'grey.700',\n }}\n >\n {' | '}\n </Typography>\n <Typography component={'span'} variant={'smallText1'}>\n Created {dayjs(accessToken.createdOn).fromNow()}\n </Typography>\n </div>\n </Stack>\n <Box\n sx={{\n alignSelf: 'flex-start',\n display: 'flex',\n gap: 1,\n alignItems: 'center',\n }}\n >\n {isExpired && (\n <Tooltip title={EXPIRED_PAT_WARNING} placement={'top'}>\n <IconButton>\n <IconSvg\n icon=\"warning\"\n sx={{ color: 'warning.main', fontSize: 'inherit' }}\n wrap={false}\n />\n </IconButton>\n </Tooltip>\n )}\n <Tooltip title={'Delete Token'} placement={'top'}>\n <IconButton\n disabled={deleteIsPending}\n color=\"error\"\n onClick={onClickDeleteButton}\n >\n <DeleteTwoToneIcon />\n </IconButton>\n </Tooltip>\n </Box>\n </Box>\n </Card>\n )\n}\n"],"mappings":";;;;;;;;;;;;AAqBA,EAAM,OAAO,EAAa;AAQ1B,IAAa,IACX;AAEF,SAAgB,EAAgB,GAA6B;CAC3D,IAAM,EAAE,gBAAa,cAAW,MAAS,GACnC,CAAC,GAAW,KAAgB,EAAS,GAAM,EAE3C,IAAY,EAAY,UAAU,WAElC,EAAE,QAAQ,GAAa,WAAW,MACtC,EAA6B;EAC3B,iBAAiB;AACf,MAAU;;EAEZ,cAAc;EACf,CAAC,EAEE,IAAsB,QAAkB;AAC5C,EAAI,IAEF,EAAY,EAAY,GAAG,GAE3B,EAAa,GAAK;IAEnB;EAAC,EAAY;EAAI;EAAa;EAAU,CAAC;AA+B5C,QACE,kBAAC,GAAD;EACE,IAAI;GACF,IAAI;GACJ,QAAQ;GACR,OAAO;GACP,GAAG;GACH,IAAI;GACJ,iBAAiB,IAAY,YAAY;GAC1C;YARH,CA7BA,kBAAC,GAAD;GACE,OAAO;GACP,SACE,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD;IAAY,SAAS;cAAS;IAGjB,CAAA,EACb,kBAAC,GAAD;IACE,SAAS;IACT,IAAI,EACF,YAAY,OACb;cACF;IAEY,CAAA,CACZ,EAAA,CAAA;GAEL,mBAAmB;GACnB,gBAAgB,EAAa,GAAM;GACnC,iBAAiB;AAEf,IADA,EAAY,EAAY,GAAG,EAC3B,EAAa,GAAM;;GAErB,oBAAmB;GACnB,MAAM;GACN,CAaC,EACD,kBAAC,GAAD;GACE,IAAI;IACF,SAAS;IACT,YAAY;IACZ,gBAAgB;IAChB,QAAQ;IACT;aANH,CAQE,kBAAC,GAAD;IACE,IAAI;KACF,UAAU;KACV,KAAK;KACL,gBAAgB;KACjB;cALH;KAOE,kBAAC,GAAD;MAAY,SAAS;MAAa,IAAI,EAAE,UAAU,QAAQ;gBACvD,EAAY;MACF,CAAA;KACb,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,QAAD,EAAA,UAAM,iBAAoB,CAAA,EACzB,EAAY,OAAO,KAAI,MAAS;MAG/B,IAAI,IAAmB,EAAkB;AACzC,UAAI,MAAqB,KAAA,GAAW;OAClC,IAAM,IACJ,EAAM,OAAO,EAAE,CAAC,aAAa,GAAG,EAAM,MAAM,EAAE;AAChD,WAAmB;QACjB,aAAa;QACb,aAAa;QACd;;AAEH,aACE,kBAAC,GAAD;OAAqB,OAAO,EAAiB;iBAC3C,kBAAC,GAAD;QACE,WAAW;QACX,SAAS;QACT,IAAI;SAAE,IAAI;SAAM,QAAQ;SAAW,OAAO;SAAgB;kBAEzD,EAAiB;QACP,CAAA;OACL,EARI,EAQJ;OAEZ,CACE,EAAA,CAAA;KACN,kBAAC,OAAD,EAAA,UAAA;MACE,kBAAC,GAAD;OAAY,WAAW;OAAQ,SAAS;iBAAxC,CAAsD,cACzC,EAAM,EAAY,SAAS,CAAC,SAAS,CACrC;;MACb,kBAAC,GAAD;OACE,WAAW;OACX,SAAS;OACT,IAAI,EACF,OAAO,YACR;iBAEA;OACU,CAAA;MACb,kBAAC,GAAD;OAAY,WAAW;OAAQ,SAAS;iBAAxC,CAAsD,YAC3C,EAAM,EAAY,UAAU,CAAC,SAAS,CACpC;;MACT,EAAA,CAAA;KACA;OACR,kBAAC,GAAD;IACE,IAAI;KACF,WAAW;KACX,SAAS;KACT,KAAK;KACL,YAAY;KACb;cANH,CAQG,KACC,kBAAC,GAAD;KAAS,OAAA;KAA4B,WAAW;eAC9C,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;MACE,MAAK;MACL,IAAI;OAAE,OAAO;OAAgB,UAAU;OAAW;MAClD,MAAM;MACN,CAAA,EACS,CAAA;KACL,CAAA,EAEZ,kBAAC,GAAD;KAAS,OAAO;KAAgB,WAAW;eACzC,kBAAC,GAAD;MACE,UAAU;MACV,OAAM;MACN,SAAS;gBAET,kBAAC,GAAD,EAAqB,CAAA;MACV,CAAA;KACL,CAAA,CACN;MACF;KACD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StudyAcknowledgements.js","names":[],"sources":["../../../src/components/AcknowledgementsPage/StudyAcknowledgements.tsx"],"sourcesContent":["import { useGetQueryResultBundleWithAsyncStatus } from '@/synapse-queries'\nimport { parseEntityIdFromSqlStatement } from '@/utils/functions'\nimport { BUNDLE_MASK_QUERY_RESULTS } from '@/utils/SynapseConstants'\nimport { StudyAcknowledgement } from './StudyAcknowledgement'\nimport { AcknowledgementItem } from './AcknowledgementsPage'\n\nexport type StudyAcknowledgementsProps = {\n // First column should be the study name, second column should be the acknowledgement statement\n sql: string\n onSelectChange?: (item: AcknowledgementItem, checked: boolean) => void\n}\n\nexport function StudyAcknowledgements({\n sql,\n onSelectChange,\n}: StudyAcknowledgementsProps) {\n const entityId = parseEntityIdFromSqlStatement(sql)\n const { data } = useGetQueryResultBundleWithAsyncStatus({\n entityId: entityId,\n query: {\n sql,\n },\n partMask: BUNDLE_MASK_QUERY_RESULTS,\n concreteType: 'org.sagebionetworks.repo.model.table.QueryBundleRequest',\n })\n\n // get raw data. parse and then inject? or just inject without parsing?\n const rows = data?.responseBody?.queryResult?.queryResults?.rows\n return (\n <>\n {rows?.map((row, index) => {\n const studyName = row.values[0]\n const acknowledgementStatementWikiRef = row.values[1]\n if (!studyName || !acknowledgementStatementWikiRef) {\n return null\n }\n return (\n <StudyAcknowledgement\n key={index}\n studyName={studyName}\n acknowledgementStatementWikiRef={acknowledgementStatementWikiRef}\n onSelectChange={onSelectChange}\n />\n )\n })}\n </>\n )\n}\n"],"mappings":";;;;;;;;AAYA,SAAgB,EAAsB,EACpC,QACA,qBAC6B;CAE7B,IAAM,EAAE,YAAS,EAAuC;EAC5C,UAFK,EAA8B,
|
|
1
|
+
{"version":3,"file":"StudyAcknowledgements.js","names":[],"sources":["../../../src/components/AcknowledgementsPage/StudyAcknowledgements.tsx"],"sourcesContent":["import { useGetQueryResultBundleWithAsyncStatus } from '@/synapse-queries'\nimport { parseEntityIdFromSqlStatement } from '@/utils/functions'\nimport { BUNDLE_MASK_QUERY_RESULTS } from '@/utils/SynapseConstants'\nimport { StudyAcknowledgement } from './StudyAcknowledgement'\nimport { AcknowledgementItem } from './AcknowledgementsPage'\n\nexport type StudyAcknowledgementsProps = {\n // First column should be the study name, second column should be the acknowledgement statement\n sql: string\n onSelectChange?: (item: AcknowledgementItem, checked: boolean) => void\n}\n\nexport function StudyAcknowledgements({\n sql,\n onSelectChange,\n}: StudyAcknowledgementsProps) {\n const entityId = parseEntityIdFromSqlStatement(sql)\n const { data } = useGetQueryResultBundleWithAsyncStatus({\n entityId: entityId,\n query: {\n sql,\n },\n partMask: BUNDLE_MASK_QUERY_RESULTS,\n concreteType: 'org.sagebionetworks.repo.model.table.QueryBundleRequest',\n })\n\n // get raw data. parse and then inject? or just inject without parsing?\n const rows = data?.responseBody?.queryResult?.queryResults?.rows\n return (\n <>\n {rows?.map((row, index) => {\n const studyName = row.values[0]\n const acknowledgementStatementWikiRef = row.values[1]\n if (!studyName || !acknowledgementStatementWikiRef) {\n return null\n }\n return (\n <StudyAcknowledgement\n key={index}\n studyName={studyName}\n acknowledgementStatementWikiRef={acknowledgementStatementWikiRef}\n onSelectChange={onSelectChange}\n />\n )\n })}\n </>\n )\n}\n"],"mappings":";;;;;;;;AAYA,SAAgB,EAAsB,EACpC,QACA,qBAC6B;CAE7B,IAAM,EAAE,YAAS,EAAuC;EAC5C,UAFK,EAA8B,EAEnC;EACV,OAAO,EACL,QACD;EACD,UAAA;EACA,cAAc;EACf,CAAC,EAGI,IAAO,GAAM,cAAc,aAAa,cAAc;AAC5D,QACE,kBAAA,GAAA,EAAA,UACG,GAAM,KAAK,GAAK,MAAU;EACzB,IAAM,IAAY,EAAI,OAAO,IACvB,IAAkC,EAAI,OAAO;AAInD,SAHI,CAAC,KAAa,CAAC,IACV,OAGP,kBAAC,GAAD;GAEa;GACsB;GACjB;GAChB,EAJK,EAIL;GAEJ,EACD,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PermissionLevelMenu.js","names":[],"sources":["../../../src/components/AclEditor/PermissionLevelMenu.tsx"],"sourcesContent":["import {\n getAccessTypeFromPermissionLevel,\n getPermissionLevelFromAccessType,\n PermissionLevel,\n permissionLevelToLabel,\n} from '@/utils/PermissionLevelToAccessType'\nimport { MenuItem, TextField, Typography } from '@mui/material'\nimport { ACCESS_TYPE } from '@sage-bionetworks/synapse-types'\nimport React from 'react'\n\nexport type PermissionLevelMenuProps = {\n currentAccessType: ACCESS_TYPE[]\n availablePermissionLevels: PermissionLevel[]\n onChange: (accessTypes: ACCESS_TYPE[]) => void\n}\n\nconst CUSTOM_VALUE = 'CUSTOM'\nconst CUSTOM_TEXT = 'Custom'\n\nexport function PermissionLevelMenu(\n props: PermissionLevelMenuProps,\n): React.ReactNode {\n const { currentAccessType, availablePermissionLevels, onChange } = props\n\n const selectedPermissionLevel: PermissionLevel | null =\n getPermissionLevelFromAccessType(currentAccessType)\n\n const isCustomPermissionSelected = selectedPermissionLevel == null\n\n return (\n <TextField\n value={\n isCustomPermissionSelected ? CUSTOM_VALUE : selectedPermissionLevel\n }\n onChange={e => {\n const accessType = getAccessTypeFromPermissionLevel(\n e.target.value as PermissionLevel,\n )\n\n onChange(accessType || currentAccessType)\n }}\n fullWidth\n select\n size=\"small\"\n slotProps={{\n select: {\n renderValue: selected => {\n if (selected == CUSTOM_VALUE) {\n return CUSTOM_TEXT\n }\n return permissionLevelToLabel[selected as PermissionLevel]\n },\n },\n }}\n >\n {Object.values(availablePermissionLevels).map(permissionLevel => {\n return (\n <MenuItem key={permissionLevel} value={permissionLevel}>\n <Typography variant=\"smallText1\" noWrap>\n {permissionLevelToLabel[permissionLevel]}\n </Typography>\n </MenuItem>\n )\n })}\n {isCustomPermissionSelected && (\n <MenuItem value={CUSTOM_VALUE}>\n <Typography variant=\"smallText1\" noWrap>\n {CUSTOM_TEXT}\n </Typography>\n </MenuItem>\n )}\n </TextField>\n )\n}\n"],"mappings":";;;;;AAgBA,IAAM,IAAe,UACf,IAAc;AAEpB,SAAgB,EACd,GACiB;CACjB,IAAM,EAAE,sBAAmB,8BAA2B,gBAAa,GAE7D,IACJ,EAAiC,EAAkB,EAE/C,IAA6B,KAA2B;AAE9D,QACE,kBAAC,GAAD;EACE,OACE,IAA6B,IAAe;EAE9C,WAAU,MAAK;AAKb,KAJmB,EACjB,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"PermissionLevelMenu.js","names":[],"sources":["../../../src/components/AclEditor/PermissionLevelMenu.tsx"],"sourcesContent":["import {\n getAccessTypeFromPermissionLevel,\n getPermissionLevelFromAccessType,\n PermissionLevel,\n permissionLevelToLabel,\n} from '@/utils/PermissionLevelToAccessType'\nimport { MenuItem, TextField, Typography } from '@mui/material'\nimport { ACCESS_TYPE } from '@sage-bionetworks/synapse-types'\nimport React from 'react'\n\nexport type PermissionLevelMenuProps = {\n currentAccessType: ACCESS_TYPE[]\n availablePermissionLevels: PermissionLevel[]\n onChange: (accessTypes: ACCESS_TYPE[]) => void\n}\n\nconst CUSTOM_VALUE = 'CUSTOM'\nconst CUSTOM_TEXT = 'Custom'\n\nexport function PermissionLevelMenu(\n props: PermissionLevelMenuProps,\n): React.ReactNode {\n const { currentAccessType, availablePermissionLevels, onChange } = props\n\n const selectedPermissionLevel: PermissionLevel | null =\n getPermissionLevelFromAccessType(currentAccessType)\n\n const isCustomPermissionSelected = selectedPermissionLevel == null\n\n return (\n <TextField\n value={\n isCustomPermissionSelected ? CUSTOM_VALUE : selectedPermissionLevel\n }\n onChange={e => {\n const accessType = getAccessTypeFromPermissionLevel(\n e.target.value as PermissionLevel,\n )\n\n onChange(accessType || currentAccessType)\n }}\n fullWidth\n select\n size=\"small\"\n slotProps={{\n select: {\n renderValue: selected => {\n if (selected == CUSTOM_VALUE) {\n return CUSTOM_TEXT\n }\n return permissionLevelToLabel[selected as PermissionLevel]\n },\n },\n }}\n >\n {Object.values(availablePermissionLevels).map(permissionLevel => {\n return (\n <MenuItem key={permissionLevel} value={permissionLevel}>\n <Typography variant=\"smallText1\" noWrap>\n {permissionLevelToLabel[permissionLevel]}\n </Typography>\n </MenuItem>\n )\n })}\n {isCustomPermissionSelected && (\n <MenuItem value={CUSTOM_VALUE}>\n <Typography variant=\"smallText1\" noWrap>\n {CUSTOM_TEXT}\n </Typography>\n </MenuItem>\n )}\n </TextField>\n )\n}\n"],"mappings":";;;;;AAgBA,IAAM,IAAe,UACf,IAAc;AAEpB,SAAgB,EACd,GACiB;CACjB,IAAM,EAAE,sBAAmB,8BAA2B,gBAAa,GAE7D,IACJ,EAAiC,EAAkB,EAE/C,IAA6B,KAA2B;AAE9D,QACE,kBAAC,GAAD;EACE,OACE,IAA6B,IAAe;EAE9C,WAAU,MAAK;AAKb,KAJmB,EACjB,EAAE,OAAO,MAGF,IAAc,EAAkB;;EAE3C,WAAA;EACA,QAAA;EACA,MAAK;EACL,WAAW,EACT,QAAQ,EACN,cAAa,MACP,KAAY,IACP,IAEF,EAAuB,IAEjC,EACF;YAvBH,CAyBG,OAAO,OAAO,EAA0B,CAAC,KAAI,MAE1C,kBAAC,GAAD;GAAgC,OAAO;aACrC,kBAAC,GAAD;IAAY,SAAQ;IAAa,QAAA;cAC9B,EAAuB;IACb,CAAA;GACJ,EAJI,EAIJ,CAEb,EACD,KACC,kBAAC,GAAD;GAAU,OAAO;aACf,kBAAC,GAAD;IAAY,SAAQ;IAAa,QAAA;cAC9B;IACU,CAAA;GACJ,CAAA,CAEH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ResourceAccessAndUserGroupHeader.js","names":[],"sources":["../../../src/components/AclEditor/ResourceAccessAndUserGroupHeader.ts"],"sourcesContent":["import {\n ACCESS_TYPE,\n ResourceAccess,\n UserGroupHeader,\n} from '@sage-bionetworks/synapse-types'\n\n/**\n * Utility type to combine a ResourceAccess and the associated UserGroupHeader for that principalId.\n * This allows us to easily sort the ResourceAccess list by the name of the user or team.\n */\nexport type ResourceAccessAndUserGroupHeader = {\n resourceAccess: ResourceAccess\n userGroupHeader: UserGroupHeader\n}\n\n/**\n * Comparator for ResourceAccess list. Sorts by the following criteria:\n * 1. Users or teams with the CHANGE_PERMISSIONS permission should be at the top, sorted alphabetically by username\n * 2. The authenticated group (all users signed in to Synapse)\n * 3. The public group (all users signed in to Synapse, and 'anonymous')\n * 4. All other users or teams, sorted alphabetically by username\n */\nexport function compareResourceAccessAndUserGroupHeader(\n a: ResourceAccessAndUserGroupHeader,\n b: ResourceAccessAndUserGroupHeader,\n authenticatedPrincipalId?: string,\n publicPrincipalId?: string,\n): number {\n enum CompareResult {\n A_FIRST = -1,\n B_FIRST = 1,\n }\n\n const hasChangePermissionA = a.resourceAccess.accessType.includes(\n ACCESS_TYPE.CHANGE_PERMISSIONS,\n )\n const hasChangePermissionB = b.resourceAccess.accessType.includes(\n ACCESS_TYPE.CHANGE_PERMISSIONS,\n )\n\n if (hasChangePermissionA && !hasChangePermissionB)\n return CompareResult.A_FIRST\n if (!hasChangePermissionA && hasChangePermissionB)\n return CompareResult.B_FIRST\n\n // Both have CHANGE_PERMISSIONS or neither have it, proceed with other checks\n\n // AUTHENTICATED group always appears before PUBLIC group\n if (\n authenticatedPrincipalId &&\n String(a.resourceAccess.principalId) === authenticatedPrincipalId &&\n String(b.resourceAccess.principalId) !== authenticatedPrincipalId\n )\n return CompareResult.A_FIRST\n if (\n authenticatedPrincipalId &&\n String(a.resourceAccess.principalId) !== authenticatedPrincipalId &&\n String(b.resourceAccess.principalId) === authenticatedPrincipalId\n )\n return CompareResult.B_FIRST\n\n // PUBLIC group always appears before other users / teams\n if (\n publicPrincipalId &&\n String(a.resourceAccess.principalId) === publicPrincipalId &&\n String(b.resourceAccess.principalId) !== publicPrincipalId\n )\n return CompareResult.A_FIRST\n if (\n publicPrincipalId &&\n String(a.resourceAccess.principalId) !== publicPrincipalId &&\n String(b.resourceAccess.principalId) === publicPrincipalId\n )\n return CompareResult.B_FIRST\n\n // If none of the other cases apply, sort alphabetically by userName\n return a.userGroupHeader.userName.localeCompare(b.userGroupHeader.userName)\n}\n"],"mappings":";;AAsBA,SAAgB,EACd,GACA,GACA,GACA,GACQ;CACR,IAAK,IAAL,yBAAA,GAAA;SACE,EAAA,EAAA,
|
|
1
|
+
{"version":3,"file":"ResourceAccessAndUserGroupHeader.js","names":[],"sources":["../../../src/components/AclEditor/ResourceAccessAndUserGroupHeader.ts"],"sourcesContent":["import {\n ACCESS_TYPE,\n ResourceAccess,\n UserGroupHeader,\n} from '@sage-bionetworks/synapse-types'\n\n/**\n * Utility type to combine a ResourceAccess and the associated UserGroupHeader for that principalId.\n * This allows us to easily sort the ResourceAccess list by the name of the user or team.\n */\nexport type ResourceAccessAndUserGroupHeader = {\n resourceAccess: ResourceAccess\n userGroupHeader: UserGroupHeader\n}\n\n/**\n * Comparator for ResourceAccess list. Sorts by the following criteria:\n * 1. Users or teams with the CHANGE_PERMISSIONS permission should be at the top, sorted alphabetically by username\n * 2. The authenticated group (all users signed in to Synapse)\n * 3. The public group (all users signed in to Synapse, and 'anonymous')\n * 4. All other users or teams, sorted alphabetically by username\n */\nexport function compareResourceAccessAndUserGroupHeader(\n a: ResourceAccessAndUserGroupHeader,\n b: ResourceAccessAndUserGroupHeader,\n authenticatedPrincipalId?: string,\n publicPrincipalId?: string,\n): number {\n enum CompareResult {\n A_FIRST = -1,\n B_FIRST = 1,\n }\n\n const hasChangePermissionA = a.resourceAccess.accessType.includes(\n ACCESS_TYPE.CHANGE_PERMISSIONS,\n )\n const hasChangePermissionB = b.resourceAccess.accessType.includes(\n ACCESS_TYPE.CHANGE_PERMISSIONS,\n )\n\n if (hasChangePermissionA && !hasChangePermissionB)\n return CompareResult.A_FIRST\n if (!hasChangePermissionA && hasChangePermissionB)\n return CompareResult.B_FIRST\n\n // Both have CHANGE_PERMISSIONS or neither have it, proceed with other checks\n\n // AUTHENTICATED group always appears before PUBLIC group\n if (\n authenticatedPrincipalId &&\n String(a.resourceAccess.principalId) === authenticatedPrincipalId &&\n String(b.resourceAccess.principalId) !== authenticatedPrincipalId\n )\n return CompareResult.A_FIRST\n if (\n authenticatedPrincipalId &&\n String(a.resourceAccess.principalId) !== authenticatedPrincipalId &&\n String(b.resourceAccess.principalId) === authenticatedPrincipalId\n )\n return CompareResult.B_FIRST\n\n // PUBLIC group always appears before other users / teams\n if (\n publicPrincipalId &&\n String(a.resourceAccess.principalId) === publicPrincipalId &&\n String(b.resourceAccess.principalId) !== publicPrincipalId\n )\n return CompareResult.A_FIRST\n if (\n publicPrincipalId &&\n String(a.resourceAccess.principalId) !== publicPrincipalId &&\n String(b.resourceAccess.principalId) === publicPrincipalId\n )\n return CompareResult.B_FIRST\n\n // If none of the other cases apply, sort alphabetically by userName\n return a.userGroupHeader.userName.localeCompare(b.userGroupHeader.userName)\n}\n"],"mappings":";;AAsBA,SAAgB,EACd,GACA,GACA,GACA,GACQ;CACR,IAAK,IAAL,yBAAA,GAAA;SACE,EAAA,EAAA,UAAU,MAAC,WACX,EAAA,EAAA,UAAU,KAAA;MACX,EAEK,IAAuB,EAAE,eAAe,WAAW,SACvD,EAAY,mBACb,EACK,IAAuB,EAAE,eAAe,WAAW,SACvD,EAAY,mBACb;AAsCD,QApCI,KAAwB,CAAC,IACpB,EAAc,UACnB,CAAC,KAAwB,IACpB,EAAc,UAMrB,KACA,OAAO,EAAE,eAAe,YAAY,KAAK,KACzC,OAAO,EAAE,eAAe,YAAY,KAAK,IAElC,EAAc,UAErB,KACA,OAAO,EAAE,eAAe,YAAY,KAAK,KACzC,OAAO,EAAE,eAAe,YAAY,KAAK,IAElC,EAAc,UAIrB,KACA,OAAO,EAAE,eAAe,YAAY,KAAK,KACzC,OAAO,EAAE,eAAe,YAAY,KAAK,IAElC,EAAc,UAErB,KACA,OAAO,EAAE,eAAe,YAAY,KAAK,KACzC,OAAO,EAAE,eAAe,YAAY,KAAK,IAElC,EAAc,UAGhB,EAAE,gBAAgB,SAAS,cAAc,EAAE,gBAAgB,SAAS"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSortResourceAccessList.js","names":[],"sources":["../../../src/components/AclEditor/useSortResourceAccessList.ts"],"sourcesContent":["import { useGetUserGroupHeaders } from '@/synapse-queries'\nimport { useGetRealmPrincipals } from '@/synapse-queries/realm/useRealmPrincipals'\nimport { ResourceAccess } from '@sage-bionetworks/synapse-types'\nimport { useEffect, useMemo } from 'react'\nimport {\n compareResourceAccessAndUserGroupHeader,\n ResourceAccessAndUserGroupHeader,\n} from './ResourceAccessAndUserGroupHeader'\n\n/**\n * Custom hook to sort a list of ResourceAccess objects by the permissions and name of the user or team.\n * @param resourceAccessList\n */\nexport default function useSortResourceAccessList(\n resourceAccessList: ResourceAccess[],\n) {\n const { data } = useGetRealmPrincipals()\n const realmPrincipals = data || {}\n const {\n authenticatedUsers: authenticatedUsersId,\n publicGroup: publicGroupId,\n } = realmPrincipals\n const principalIdsOnResourceAccessList = useMemo(\n () => resourceAccessList.map(ra => ra.principalId),\n [resourceAccessList],\n )\n\n const {\n data: userGroupHeadersOnResourceAccessList,\n isLoading,\n error,\n } = useGetUserGroupHeaders(principalIdsOnResourceAccessList.map(String), {\n enabled: principalIdsOnResourceAccessList.length > 0,\n })\n\n useEffect(() => {\n if (error) {\n console.error('Error fetching user group headers: ', error)\n }\n }, [error])\n\n const sortedResourceAccessList = useMemo(() => {\n if (!userGroupHeadersOnResourceAccessList) {\n return null\n }\n\n const joinedWithUserGroupHeaders = resourceAccessList.map(\n (ral): ResourceAccessAndUserGroupHeader => ({\n resourceAccess: ral,\n userGroupHeader: userGroupHeadersOnResourceAccessList.find(\n ugh => String(ugh.ownerId) === String(ral.principalId),\n )!,\n }),\n )\n\n const allEntriesHaveUserGroupHeader = joinedWithUserGroupHeaders.every(\n obj => Boolean(obj.userGroupHeader),\n )\n\n if (!allEntriesHaveUserGroupHeader) {\n console.warn(\n 'Some ACL entries do not have a corresponding UserGroupHeader. The ResourceAccess list will not be sorted. Missing entries: ',\n joinedWithUserGroupHeaders.filter(obj => !obj.userGroupHeader),\n )\n return null\n }\n\n return joinedWithUserGroupHeaders\n .toSorted((a, b) =>\n compareResourceAccessAndUserGroupHeader(\n a,\n b,\n authenticatedUsersId,\n publicGroupId,\n ),\n )\n .map(obj => obj.resourceAccess)\n }, [\n resourceAccessList,\n userGroupHeadersOnResourceAccessList,\n authenticatedUsersId,\n publicGroupId,\n ])\n\n return {\n sortedResourceAccessList,\n isLoading,\n }\n}\n"],"mappings":";;;;;;AAaA,SAAwB,EACtB,GACA;CACA,IAAM,EAAE,YAAS,GAAuB,EAElC,EACJ,oBAAoB,GACpB,aAAa,MAHS,KAAQ,EAAE,EAK5B,IAAmC,QACjC,EAAmB,KAAI,MAAM,EAAG,YAAY,EAClD,CAAC,EAAmB,CACrB,EAEK,EACJ,MAAM,GACN,cACA,aACE,EAAuB,EAAiC,IAAI,OAAO,EAAE,EACvE,SAAS,EAAiC,SAAS,GACpD,CAAC;AAmDF,QAjDA,QAAgB;AACd,EAAI,KACF,QAAQ,MAAM,uCAAuC,EAAM;IAE5D,CAAC,EAAM,CAAC,EA6CJ;EACL,0BA5C+B,QAAc;AAC7C,OAAI,CAAC,EACH,QAAO;GAGT,IAAM,IAA6B,EAAmB,KACnD,OAA2C;IAC1C,gBAAgB;IAChB,iBAAiB,EAAqC,MACpD,MAAO,OAAO,EAAI,QAAQ,KAAK,OAAO,EAAI,YAAY,CACvD;IACF,EACF;AAcD,UAZsC,EAA2B,OAC/D,MAAO,EAAQ,EAAI,
|
|
1
|
+
{"version":3,"file":"useSortResourceAccessList.js","names":[],"sources":["../../../src/components/AclEditor/useSortResourceAccessList.ts"],"sourcesContent":["import { useGetUserGroupHeaders } from '@/synapse-queries'\nimport { useGetRealmPrincipals } from '@/synapse-queries/realm/useRealmPrincipals'\nimport { ResourceAccess } from '@sage-bionetworks/synapse-types'\nimport { useEffect, useMemo } from 'react'\nimport {\n compareResourceAccessAndUserGroupHeader,\n ResourceAccessAndUserGroupHeader,\n} from './ResourceAccessAndUserGroupHeader'\n\n/**\n * Custom hook to sort a list of ResourceAccess objects by the permissions and name of the user or team.\n * @param resourceAccessList\n */\nexport default function useSortResourceAccessList(\n resourceAccessList: ResourceAccess[],\n) {\n const { data } = useGetRealmPrincipals()\n const realmPrincipals = data || {}\n const {\n authenticatedUsers: authenticatedUsersId,\n publicGroup: publicGroupId,\n } = realmPrincipals\n const principalIdsOnResourceAccessList = useMemo(\n () => resourceAccessList.map(ra => ra.principalId),\n [resourceAccessList],\n )\n\n const {\n data: userGroupHeadersOnResourceAccessList,\n isLoading,\n error,\n } = useGetUserGroupHeaders(principalIdsOnResourceAccessList.map(String), {\n enabled: principalIdsOnResourceAccessList.length > 0,\n })\n\n useEffect(() => {\n if (error) {\n console.error('Error fetching user group headers: ', error)\n }\n }, [error])\n\n const sortedResourceAccessList = useMemo(() => {\n if (!userGroupHeadersOnResourceAccessList) {\n return null\n }\n\n const joinedWithUserGroupHeaders = resourceAccessList.map(\n (ral): ResourceAccessAndUserGroupHeader => ({\n resourceAccess: ral,\n userGroupHeader: userGroupHeadersOnResourceAccessList.find(\n ugh => String(ugh.ownerId) === String(ral.principalId),\n )!,\n }),\n )\n\n const allEntriesHaveUserGroupHeader = joinedWithUserGroupHeaders.every(\n obj => Boolean(obj.userGroupHeader),\n )\n\n if (!allEntriesHaveUserGroupHeader) {\n console.warn(\n 'Some ACL entries do not have a corresponding UserGroupHeader. The ResourceAccess list will not be sorted. Missing entries: ',\n joinedWithUserGroupHeaders.filter(obj => !obj.userGroupHeader),\n )\n return null\n }\n\n return joinedWithUserGroupHeaders\n .toSorted((a, b) =>\n compareResourceAccessAndUserGroupHeader(\n a,\n b,\n authenticatedUsersId,\n publicGroupId,\n ),\n )\n .map(obj => obj.resourceAccess)\n }, [\n resourceAccessList,\n userGroupHeadersOnResourceAccessList,\n authenticatedUsersId,\n publicGroupId,\n ])\n\n return {\n sortedResourceAccessList,\n isLoading,\n }\n}\n"],"mappings":";;;;;;AAaA,SAAwB,EACtB,GACA;CACA,IAAM,EAAE,YAAS,GAAuB,EAElC,EACJ,oBAAoB,GACpB,aAAa,MAHS,KAAQ,EAAE,EAK5B,IAAmC,QACjC,EAAmB,KAAI,MAAM,EAAG,YAAY,EAClD,CAAC,EAAmB,CACrB,EAEK,EACJ,MAAM,GACN,cACA,aACE,EAAuB,EAAiC,IAAI,OAAO,EAAE,EACvE,SAAS,EAAiC,SAAS,GACpD,CAAC;AAmDF,QAjDA,QAAgB;AACd,EAAI,KACF,QAAQ,MAAM,uCAAuC,EAAM;IAE5D,CAAC,EAAM,CAAC,EA6CJ;EACL,0BA5C+B,QAAc;AAC7C,OAAI,CAAC,EACH,QAAO;GAGT,IAAM,IAA6B,EAAmB,KACnD,OAA2C;IAC1C,gBAAgB;IAChB,iBAAiB,EAAqC,MACpD,MAAO,OAAO,EAAI,QAAQ,KAAK,OAAO,EAAI,YAAY,CACvD;IACF,EACF;AAcD,UAZsC,EAA2B,OAC/D,MAAO,EAAQ,EAAI,gBAGhB,GAQE,EACJ,UAAU,GAAG,MACZ,EACE,GACA,GACA,GACA,EACD,CACF,CACA,KAAI,MAAO,EAAI,eAAe,IAhB/B,QAAQ,KACN,+HACA,EAA2B,QAAO,MAAO,CAAC,EAAI,gBAAgB,CAC/D,EACM;KAaR;GACD;GACA;GACA;GACA;GACD,CAGC;EACA;EACD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useUpdateAcl.js","names":[],"sources":["../../../src/components/AclEditor/useUpdateAcl.ts"],"sourcesContent":["import { useGlobalIsEditingContext } from '@/utils/context/GlobalIsEditingContext'\nimport { ACCESS_TYPE, ResourceAccess } from '@sage-bionetworks/synapse-types'\nimport {\n Dispatch,\n SetStateAction,\n useCallback,\n useEffect,\n useState,\n} from 'react'\nimport { noop } from 'lodash-es'\nimport useSortResourceAccessList from './useSortResourceAccessList'\n\nexport const PRINCIPAL_ALREADY_ADDED_ERROR_MESSAGE =\n 'User or team already has permissions.'\n\nexport type UseUpdateAclOptions = {\n initialResourceAccessList?: ResourceAccess[]\n onChange?: (resourceAccessList: ResourceAccess[]) => void\n onError?: (e: string) => void\n}\n\ntype UseUpdateAclReturn = {\n /** The ResourceAccess list that is being updated. It will automatically be sorted unless the `add`, `update` or `remove` functions are called. */\n resourceAccessList: ResourceAccess[]\n /** Set the ResourceAccess list. Does not prevent re-sorting */\n setResourceAccessList: Dispatch<SetStateAction<ResourceAccess[]>>\n /** Adds a principal to the list with the provided accessTypes */\n addResourceAccessItem: (\n principalId: number,\n accessTypes: ACCESS_TYPE[],\n ) => void\n /** Updates the principal in the list with the provided accessTypes */\n updateResourceAccessItem: (\n principalId: number,\n accessType: ACCESS_TYPE[],\n ) => void\n /** Removes the principal from the list */\n removeResourceAccessItem: (principalId: number) => void\n /** Resets the dirty state of the form, which will immediately trigger sorting the resourceAccessList */\n resetDirtyState: () => void\n}\n\nconst EMPTY_ARRAY: ResourceAccess[] = []\n\nexport default function useUpdateAcl(\n options: UseUpdateAclOptions = {},\n): UseUpdateAclReturn {\n const {\n initialResourceAccessList = EMPTY_ARRAY,\n onChange = noop,\n onError = noop,\n } = options\n const [isDirty, setIsDirty] = useState(false)\n const { setIsEditing } = useGlobalIsEditingContext()\n\n // When the form is dirty, set the global editing state to true\n useEffect(() => {\n setIsEditing(isDirty)\n return () => {\n setIsEditing(false)\n }\n }, [isDirty, setIsEditing])\n\n const [resourceAccessList, setResourceAccessList] = useState<\n ResourceAccess[]\n >(initialResourceAccessList)\n const [hasSorted, setHasSorted] = useState(false)\n\n // While the form has not been edited, sort the resourceAccessList\n const { sortedResourceAccessList, isLoading: isLoadingSortedList } =\n useSortResourceAccessList(resourceAccessList)\n useEffect(() => {\n if (\n !isDirty &&\n !isLoadingSortedList &&\n !hasSorted &&\n sortedResourceAccessList != null\n ) {\n setResourceAccessList(sortedResourceAccessList)\n // `useSortResourceAccessList` will return a new array every time `resourceAccessList` changes, so we need to\n // track if we've already sorted to prevent an infinite loop\n setHasSorted(true)\n }\n }, [hasSorted, isDirty, isLoadingSortedList, sortedResourceAccessList])\n\n useEffect(() => {\n onChange(resourceAccessList)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [resourceAccessList])\n\n const addResourceAccessItem = useCallback(\n (principalId: number, accessTypes: ACCESS_TYPE[]) => {\n setIsDirty(true)\n if (principalId) {\n setResourceAccessList(resourceAccessList => {\n const alreadyReviewer = resourceAccessList.some(\n resourceAccess => resourceAccess.principalId === principalId,\n )\n if (alreadyReviewer) {\n onError(PRINCIPAL_ALREADY_ADDED_ERROR_MESSAGE)\n } else {\n const newResourceAccess: ResourceAccess = {\n principalId: principalId,\n accessType: accessTypes,\n }\n return [...resourceAccessList, newResourceAccess]\n }\n return resourceAccessList\n })\n }\n },\n [onError],\n )\n\n const updateResourceAccessItem = useCallback(\n (principalId: number, accessType: ACCESS_TYPE[]) => {\n setIsDirty(true)\n setResourceAccessList(resourceAccessList =>\n resourceAccessList.map(resourceAccess => {\n return resourceAccess.principalId === principalId\n ? { ...resourceAccess, accessType }\n : resourceAccess\n }),\n )\n },\n [],\n )\n\n const removeResourceAccessItem = useCallback((principalId: number) => {\n setIsDirty(true)\n setResourceAccessList(resourceAccessList =>\n resourceAccessList.filter(\n raListItem => raListItem.principalId !== principalId,\n ),\n )\n }, [])\n\n const resetDirtyState = useCallback(() => {\n setIsDirty(false)\n }, [])\n\n return {\n resourceAccessList,\n setResourceAccessList,\n addResourceAccessItem,\n updateResourceAccessItem,\n removeResourceAccessItem,\n resetDirtyState,\n }\n}\n"],"mappings":";;;;;AAYA,IAAa,IACX,yCA6BI,IAAgC,EAAE;AAExC,SAAwB,EACtB,IAA+B,EAAE,EACb;CACpB,IAAM,EACJ,+BAA4B,GAC5B,cAAW,GACX,aAAU,MACR,GACE,CAAC,GAAS,KAAc,EAAS,GAAM,EACvC,EAAE,oBAAiB,GAA2B;AAGpD,UACE,EAAa,EAAQ,QACR;AACX,IAAa,GAAM;KAEpB,CAAC,GAAS,EAAa,CAAC;CAE3B,IAAM,CAAC,GAAoB,KAAyB,EAElD,EAA0B,EACtB,CAAC,GAAW,KAAgB,EAAS,GAAM,EAG3C,EAAE,6BAA0B,WAAW,MAC3C,EAA0B,EAAmB;AAuE/C,QAtEA,QAAgB;AACd,EACE,CAAC,KACD,CAAC,KACD,CAAC,KACD,KAA4B,SAE5B,EAAsB,EAAyB,EAG/C,EAAa,GAAK;IAEnB;EAAC;EAAW;EAAS;EAAqB;EAAyB,CAAC,EAEvE,QAAgB;AACd,IAAS,EAAmB;IAE3B,CAAC,EAAmB,CAAC,EAqDjB;EACL;EACA;EACA,uBAtD4B,GAC3B,GAAqB,MAA+B;AAEnD,GADA,EAAW,GAAK,EACZ,KACF,GAAsB,MAAsB;AAI1C,QAHwB,EAAmB,MACzC,MAAkB,EAAe,gBAAgB,
|
|
1
|
+
{"version":3,"file":"useUpdateAcl.js","names":[],"sources":["../../../src/components/AclEditor/useUpdateAcl.ts"],"sourcesContent":["import { useGlobalIsEditingContext } from '@/utils/context/GlobalIsEditingContext'\nimport { ACCESS_TYPE, ResourceAccess } from '@sage-bionetworks/synapse-types'\nimport {\n Dispatch,\n SetStateAction,\n useCallback,\n useEffect,\n useState,\n} from 'react'\nimport { noop } from 'lodash-es'\nimport useSortResourceAccessList from './useSortResourceAccessList'\n\nexport const PRINCIPAL_ALREADY_ADDED_ERROR_MESSAGE =\n 'User or team already has permissions.'\n\nexport type UseUpdateAclOptions = {\n initialResourceAccessList?: ResourceAccess[]\n onChange?: (resourceAccessList: ResourceAccess[]) => void\n onError?: (e: string) => void\n}\n\ntype UseUpdateAclReturn = {\n /** The ResourceAccess list that is being updated. It will automatically be sorted unless the `add`, `update` or `remove` functions are called. */\n resourceAccessList: ResourceAccess[]\n /** Set the ResourceAccess list. Does not prevent re-sorting */\n setResourceAccessList: Dispatch<SetStateAction<ResourceAccess[]>>\n /** Adds a principal to the list with the provided accessTypes */\n addResourceAccessItem: (\n principalId: number,\n accessTypes: ACCESS_TYPE[],\n ) => void\n /** Updates the principal in the list with the provided accessTypes */\n updateResourceAccessItem: (\n principalId: number,\n accessType: ACCESS_TYPE[],\n ) => void\n /** Removes the principal from the list */\n removeResourceAccessItem: (principalId: number) => void\n /** Resets the dirty state of the form, which will immediately trigger sorting the resourceAccessList */\n resetDirtyState: () => void\n}\n\nconst EMPTY_ARRAY: ResourceAccess[] = []\n\nexport default function useUpdateAcl(\n options: UseUpdateAclOptions = {},\n): UseUpdateAclReturn {\n const {\n initialResourceAccessList = EMPTY_ARRAY,\n onChange = noop,\n onError = noop,\n } = options\n const [isDirty, setIsDirty] = useState(false)\n const { setIsEditing } = useGlobalIsEditingContext()\n\n // When the form is dirty, set the global editing state to true\n useEffect(() => {\n setIsEditing(isDirty)\n return () => {\n setIsEditing(false)\n }\n }, [isDirty, setIsEditing])\n\n const [resourceAccessList, setResourceAccessList] = useState<\n ResourceAccess[]\n >(initialResourceAccessList)\n const [hasSorted, setHasSorted] = useState(false)\n\n // While the form has not been edited, sort the resourceAccessList\n const { sortedResourceAccessList, isLoading: isLoadingSortedList } =\n useSortResourceAccessList(resourceAccessList)\n useEffect(() => {\n if (\n !isDirty &&\n !isLoadingSortedList &&\n !hasSorted &&\n sortedResourceAccessList != null\n ) {\n setResourceAccessList(sortedResourceAccessList)\n // `useSortResourceAccessList` will return a new array every time `resourceAccessList` changes, so we need to\n // track if we've already sorted to prevent an infinite loop\n setHasSorted(true)\n }\n }, [hasSorted, isDirty, isLoadingSortedList, sortedResourceAccessList])\n\n useEffect(() => {\n onChange(resourceAccessList)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [resourceAccessList])\n\n const addResourceAccessItem = useCallback(\n (principalId: number, accessTypes: ACCESS_TYPE[]) => {\n setIsDirty(true)\n if (principalId) {\n setResourceAccessList(resourceAccessList => {\n const alreadyReviewer = resourceAccessList.some(\n resourceAccess => resourceAccess.principalId === principalId,\n )\n if (alreadyReviewer) {\n onError(PRINCIPAL_ALREADY_ADDED_ERROR_MESSAGE)\n } else {\n const newResourceAccess: ResourceAccess = {\n principalId: principalId,\n accessType: accessTypes,\n }\n return [...resourceAccessList, newResourceAccess]\n }\n return resourceAccessList\n })\n }\n },\n [onError],\n )\n\n const updateResourceAccessItem = useCallback(\n (principalId: number, accessType: ACCESS_TYPE[]) => {\n setIsDirty(true)\n setResourceAccessList(resourceAccessList =>\n resourceAccessList.map(resourceAccess => {\n return resourceAccess.principalId === principalId\n ? { ...resourceAccess, accessType }\n : resourceAccess\n }),\n )\n },\n [],\n )\n\n const removeResourceAccessItem = useCallback((principalId: number) => {\n setIsDirty(true)\n setResourceAccessList(resourceAccessList =>\n resourceAccessList.filter(\n raListItem => raListItem.principalId !== principalId,\n ),\n )\n }, [])\n\n const resetDirtyState = useCallback(() => {\n setIsDirty(false)\n }, [])\n\n return {\n resourceAccessList,\n setResourceAccessList,\n addResourceAccessItem,\n updateResourceAccessItem,\n removeResourceAccessItem,\n resetDirtyState,\n }\n}\n"],"mappings":";;;;;AAYA,IAAa,IACX,yCA6BI,IAAgC,EAAE;AAExC,SAAwB,EACtB,IAA+B,EAAE,EACb;CACpB,IAAM,EACJ,+BAA4B,GAC5B,cAAW,GACX,aAAU,MACR,GACE,CAAC,GAAS,KAAc,EAAS,GAAM,EACvC,EAAE,oBAAiB,GAA2B;AAGpD,UACE,EAAa,EAAQ,QACR;AACX,IAAa,GAAM;KAEpB,CAAC,GAAS,EAAa,CAAC;CAE3B,IAAM,CAAC,GAAoB,KAAyB,EAElD,EAA0B,EACtB,CAAC,GAAW,KAAgB,EAAS,GAAM,EAG3C,EAAE,6BAA0B,WAAW,MAC3C,EAA0B,EAAmB;AAuE/C,QAtEA,QAAgB;AACd,EACE,CAAC,KACD,CAAC,KACD,CAAC,KACD,KAA4B,SAE5B,EAAsB,EAAyB,EAG/C,EAAa,GAAK;IAEnB;EAAC;EAAW;EAAS;EAAqB;EAAyB,CAAC,EAEvE,QAAgB;AACd,IAAS,EAAmB;IAE3B,CAAC,EAAmB,CAAC,EAqDjB;EACL;EACA;EACA,uBAtD4B,GAC3B,GAAqB,MAA+B;AAEnD,GADA,EAAW,GAAK,EACZ,KACF,GAAsB,MAAsB;AAI1C,QAHwB,EAAmB,MACzC,MAAkB,EAAe,gBAAgB,EAE/C,CACF,GAAQ,EAAsC;SACzC;KACL,IAAM,IAAoC;MAC3B;MACb,YAAY;MACb;AACD,YAAO,CAAC,GAAG,GAAoB,EAAkB;;AAEnD,WAAO;KACP;KAGN,CAAC,EAAQ,CAiCT;EACA,0BA/B+B,GAC9B,GAAqB,MAA8B;AAElD,GADA,EAAW,GAAK,EAChB,GAAsB,MACpB,EAAmB,KAAI,MACd,EAAe,gBAAgB,IAClC;IAAE,GAAG;IAAgB;IAAY,GACjC,EACJ,CACH;KAEH,EAAE,CAoBF;EACA,0BAlB+B,GAAa,MAAwB;AAEpE,GADA,EAAW,GAAK,EAChB,GAAsB,MACpB,EAAmB,QACjB,MAAc,EAAW,gBAAgB,EAC1C,CACF;KACA,EAAE,CAWH;EACA,iBAVsB,QAAkB;AACxC,KAAW,GAAM;KAChB,EAAE,CAQH;EACD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AridhiaAccessStatus.js","names":[],"sources":["../../../src/components/Aridhia/AridhiaAccessStatus.tsx"],"sourcesContent":["import { Button } from '@mui/material'\nimport { useGetAridhiaRequests } from '@/aridhia-queries'\nimport AccessIcon, { RestrictionUiType } from '../HasAccess/AccessIcon'\nimport { SRC_SIGN_IN_CLASS } from '@/utils/SynapseConstants'\nimport { useSynapseContext } from '@/utils'\nimport {\n getRestrictionUiTypeFromAridhiaRequest,\n findRequestForDataset,\n} from './aridhiaAccessStatusUtils'\n\nconst buttonSx = { p: '0px', minWidth: 'unset' }\n\nexport type AridhiaAccessStatusProps = {\n /**\n * dataset code\n */\n datasetCode: string\n url?: string\n}\n\n/**\n * Component that displays the Aridhia data access request status.\n * If the user is not authenticated with Aridhia, shows a sign-in button.\n * Otherwise, shows the access status based on the data access requests.\n */\nexport default function AridhiaAccessStatus(props: AridhiaAccessStatusProps) {\n const { datasetCode, url } = props\n const { isAuthenticated } = useSynapseContext()\n const { data: requestsResponse, isLoading } = useGetAridhiaRequests()\n\n if (!isAuthenticated) {\n return (\n <Button\n sx={buttonSx}\n className={SRC_SIGN_IN_CLASS}\n onClick={ev => {\n if (ev.isTrusted) {\n /*\n There is a tricky problem - \n The portals listens to click events for buttons with the class SRC_SIGN_IN_CLASS set, it listens to this event\n so that it can display the login modal.\n\n This button has an svg inside of it which is problematic because more often than not clicking this button will \n instead click that svg. The event listener in the portals will break as a result.\n\n Though the svg may get the actual click event, because of event bubbling this button will get its onClick called.\n Once onClick is called we can manually dispatch an event off of this button. This does pose a problem, we end up in a \n infinite loop because this button keeps dispatching click events, so we can use the isTrusted to recognize if onClick was\n triggered programmatically or by user click. Lastly, using { bubbles: true } ensures the event bubbles up to the document level.\n\n */\n const clickEvent = new MouseEvent('click', { bubbles: true })\n ev.currentTarget.dispatchEvent(clickEvent)\n }\n }}\n >\n <AccessIcon\n restrictionUiType={RestrictionUiType.AccessBlockedToAnonymous}\n />\n </Button>\n )\n }\n\n // Show loading state\n if (isLoading) {\n return <></>\n }\n\n // Check if there's a request for this dataset\n const entityRequest = findRequestForDataset(\n requestsResponse?.items ?? [],\n datasetCode,\n )\n\n const restrictionUiType =\n getRestrictionUiTypeFromAridhiaRequest(entityRequest)\n\n const icon = <AccessIcon restrictionUiType={restrictionUiType} />\n\n // If URL provided, wrap icon in link\n return url ? (\n <a href={url} target=\"_blank\" rel=\"noopener noreferrer\">\n {icon}\n </a>\n ) : (\n icon\n )\n}\n"],"mappings":";;;;;;;;;;AAUA,IAAM,IAAW;CAAE,GAAG;CAAO,UAAU;CAAS;AAehD,SAAwB,EAAoB,GAAiC;CAC3E,IAAM,EAAE,gBAAa,WAAQ,GACvB,EAAE,uBAAoB,GAAmB,EACzC,EAAE,MAAM,GAAkB,iBAAc,GAAuB;AAErE,KAAI,CAAC,EACH,QACE,kBAAC,GAAD;EACE,IAAI;EACJ,WAAW;EACX,UAAS,MAAM;AACb,OAAI,EAAG,WAAW;IAehB,IAAM,IAAa,IAAI,WAAW,SAAS,EAAE,SAAS,IAAM,CAAC;AAC7D,MAAG,cAAc,cAAc,EAAW;;;YAI9C,kBAAC,GAAD,EACE,mBAAmB,EAAkB,0BACrC,CAAA;EACK,CAAA;AAKb,KAAI,EACF,QAAO,kBAAA,GAAA,EAAK,CAAA;CAYd,IAAM,IAAO,kBAAC,GAAD,EAA+B,mBAF1C,EANoB,EACpB,GAAkB,SAAS,EAAE,EAC7B,
|
|
1
|
+
{"version":3,"file":"AridhiaAccessStatus.js","names":[],"sources":["../../../src/components/Aridhia/AridhiaAccessStatus.tsx"],"sourcesContent":["import { Button } from '@mui/material'\nimport { useGetAridhiaRequests } from '@/aridhia-queries'\nimport AccessIcon, { RestrictionUiType } from '../HasAccess/AccessIcon'\nimport { SRC_SIGN_IN_CLASS } from '@/utils/SynapseConstants'\nimport { useSynapseContext } from '@/utils'\nimport {\n getRestrictionUiTypeFromAridhiaRequest,\n findRequestForDataset,\n} from './aridhiaAccessStatusUtils'\n\nconst buttonSx = { p: '0px', minWidth: 'unset' }\n\nexport type AridhiaAccessStatusProps = {\n /**\n * dataset code\n */\n datasetCode: string\n url?: string\n}\n\n/**\n * Component that displays the Aridhia data access request status.\n * If the user is not authenticated with Aridhia, shows a sign-in button.\n * Otherwise, shows the access status based on the data access requests.\n */\nexport default function AridhiaAccessStatus(props: AridhiaAccessStatusProps) {\n const { datasetCode, url } = props\n const { isAuthenticated } = useSynapseContext()\n const { data: requestsResponse, isLoading } = useGetAridhiaRequests()\n\n if (!isAuthenticated) {\n return (\n <Button\n sx={buttonSx}\n className={SRC_SIGN_IN_CLASS}\n onClick={ev => {\n if (ev.isTrusted) {\n /*\n There is a tricky problem - \n The portals listens to click events for buttons with the class SRC_SIGN_IN_CLASS set, it listens to this event\n so that it can display the login modal.\n\n This button has an svg inside of it which is problematic because more often than not clicking this button will \n instead click that svg. The event listener in the portals will break as a result.\n\n Though the svg may get the actual click event, because of event bubbling this button will get its onClick called.\n Once onClick is called we can manually dispatch an event off of this button. This does pose a problem, we end up in a \n infinite loop because this button keeps dispatching click events, so we can use the isTrusted to recognize if onClick was\n triggered programmatically or by user click. Lastly, using { bubbles: true } ensures the event bubbles up to the document level.\n\n */\n const clickEvent = new MouseEvent('click', { bubbles: true })\n ev.currentTarget.dispatchEvent(clickEvent)\n }\n }}\n >\n <AccessIcon\n restrictionUiType={RestrictionUiType.AccessBlockedToAnonymous}\n />\n </Button>\n )\n }\n\n // Show loading state\n if (isLoading) {\n return <></>\n }\n\n // Check if there's a request for this dataset\n const entityRequest = findRequestForDataset(\n requestsResponse?.items ?? [],\n datasetCode,\n )\n\n const restrictionUiType =\n getRestrictionUiTypeFromAridhiaRequest(entityRequest)\n\n const icon = <AccessIcon restrictionUiType={restrictionUiType} />\n\n // If URL provided, wrap icon in link\n return url ? (\n <a href={url} target=\"_blank\" rel=\"noopener noreferrer\">\n {icon}\n </a>\n ) : (\n icon\n )\n}\n"],"mappings":";;;;;;;;;;AAUA,IAAM,IAAW;CAAE,GAAG;CAAO,UAAU;CAAS;AAehD,SAAwB,EAAoB,GAAiC;CAC3E,IAAM,EAAE,gBAAa,WAAQ,GACvB,EAAE,uBAAoB,GAAmB,EACzC,EAAE,MAAM,GAAkB,iBAAc,GAAuB;AAErE,KAAI,CAAC,EACH,QACE,kBAAC,GAAD;EACE,IAAI;EACJ,WAAW;EACX,UAAS,MAAM;AACb,OAAI,EAAG,WAAW;IAehB,IAAM,IAAa,IAAI,WAAW,SAAS,EAAE,SAAS,IAAM,CAAC;AAC7D,MAAG,cAAc,cAAc,EAAW;;;YAI9C,kBAAC,GAAD,EACE,mBAAmB,EAAkB,0BACrC,CAAA;EACK,CAAA;AAKb,KAAI,EACF,QAAO,kBAAA,GAAA,EAAK,CAAA;CAYd,IAAM,IAAO,kBAAC,GAAD,EAA+B,mBAF1C,EANoB,EACpB,GAAkB,SAAS,EAAE,EAC7B,EAIuC,CAEG,EAAqB,CAAA;AAGjE,QAAO,IACL,kBAAC,KAAD;EAAG,MAAM;EAAK,QAAO;EAAS,KAAI;YAC/B;EACC,CAAA,GAEJ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthenticationMethodSelection.d.ts","sourceRoot":"","sources":["../../../src/components/Authentication/AuthenticationMethodSelection.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAsB,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"AuthenticationMethodSelection.d.ts","sourceRoot":"","sources":["../../../src/components/Authentication/AuthenticationMethodSelection.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAsB,MAAM,SAAS,CAAA;AAazD,OAAO,EAAE,KAAK,EAAE,MAAM,kCAAkC,CAAA;AAMxD,KAAK,kCAAkC,GAAG;IACxC,cAAc,CAAC,EAAE,MAAM,CAAA;IAEvB,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAA;IAC/B,2BAA2B,EAAE,MAAM,IAAI,CAAA;IACvC,KAAK,CAAC,EAAE,WAAW,CAAA;IACnB,KAAK,CAAC,EAAE,KAAK,CAAA;CACd,CAAA;AAID;;;;GAIG;AACH,MAAM,CAAC,OAAO,UAAU,6BAA6B,CACnD,KAAK,EAAE,kCAAkC,2CAgF1C"}
|
|
@@ -1,62 +1,63 @@
|
|
|
1
1
|
import { OAUTH2_PROVIDERS as e } from "../../utils/SynapseConstants.js";
|
|
2
2
|
import t from "../../synapse-client/index.js";
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
import i from "
|
|
6
|
-
import { hasArcusProvider as a } from "../../utils/functions/RealmUtils.js";
|
|
3
|
+
import { generateCsrfToken as n } from "../../utils/functions/generateCsrfToken.js";
|
|
4
|
+
import r from "./LoginMethodButton.js";
|
|
5
|
+
import { hasArcusProvider as i, hasSageBionetworksProvider as a } from "../../utils/functions/RealmUtils.js";
|
|
7
6
|
import { Box as o } from "@mui/material";
|
|
8
7
|
import { Fragment as s, jsx as c, jsxs as l } from "react/jsx-runtime";
|
|
9
|
-
import { FeatureFlagEnum as u } from "@sage-bionetworks/synapse-types";
|
|
10
8
|
//#region src/components/Authentication/AuthenticationMethodSelection.tsx
|
|
11
|
-
var
|
|
12
|
-
function
|
|
13
|
-
let { onBeginOAuthSignIn:
|
|
14
|
-
...
|
|
15
|
-
csrfToken:
|
|
9
|
+
var u = n();
|
|
10
|
+
function d(n) {
|
|
11
|
+
let { onBeginOAuthSignIn: d, ssoRedirectUrl: f, onSelectUsernameAndPassword: p, state: m, realm: h } = n, g = i(h), _ = a(h), v = g || _, y = {
|
|
12
|
+
...m,
|
|
13
|
+
csrfToken: u
|
|
16
14
|
};
|
|
17
15
|
function b(e, n) {
|
|
18
|
-
|
|
19
|
-
let r =
|
|
16
|
+
d && d(), e.preventDefault();
|
|
17
|
+
let r = f ? `${f}${n}` : `${t.getRootURL()}?provider=${n}`;
|
|
20
18
|
t.oAuthUrlRequest(n, r, y).then((e) => {
|
|
21
19
|
window.location.href = e.authorizationUrl;
|
|
22
20
|
}).catch((e) => {
|
|
23
21
|
console.log("Error on oAuth url ", e);
|
|
24
22
|
});
|
|
25
23
|
}
|
|
26
|
-
return /* @__PURE__ */ l(o, { children: [
|
|
27
|
-
/* @__PURE__ */
|
|
28
|
-
|
|
29
|
-
|
|
24
|
+
return /* @__PURE__ */ l(o, { children: [
|
|
25
|
+
!v && /* @__PURE__ */ l(s, { children: [
|
|
26
|
+
/* @__PURE__ */ c(r, {
|
|
27
|
+
loginMethod: "GOOGLE",
|
|
28
|
+
iconName: "google24",
|
|
29
|
+
onClick: (t) => {
|
|
30
|
+
b(t, e.GOOGLE);
|
|
31
|
+
}
|
|
32
|
+
}),
|
|
33
|
+
/* @__PURE__ */ c(r, {
|
|
34
|
+
loginMethod: "ORCID",
|
|
35
|
+
iconName: "orcid",
|
|
36
|
+
onClick: (t) => {
|
|
37
|
+
b(t, e.ORCID);
|
|
38
|
+
}
|
|
39
|
+
}),
|
|
40
|
+
/* @__PURE__ */ c(r, {
|
|
41
|
+
loginMethod: "EMAIL",
|
|
42
|
+
iconName: "email",
|
|
43
|
+
onClick: p
|
|
44
|
+
})
|
|
45
|
+
] }),
|
|
46
|
+
g && /* @__PURE__ */ c(r, {
|
|
47
|
+
loginMethod: "ARCUS",
|
|
30
48
|
onClick: (t) => {
|
|
31
|
-
b(t, e.
|
|
49
|
+
b(t, e.ARCUS);
|
|
32
50
|
}
|
|
33
51
|
}),
|
|
34
|
-
/* @__PURE__ */ c(
|
|
35
|
-
loginMethod: "ORCID",
|
|
36
|
-
iconName: "orcid",
|
|
37
|
-
onClick: (t) => {
|
|
38
|
-
b(t, e.ORCID);
|
|
39
|
-
}
|
|
40
|
-
}),
|
|
41
|
-
/* @__PURE__ */ c(i, {
|
|
42
|
-
loginMethod: "EMAIL",
|
|
43
|
-
iconName: "email",
|
|
44
|
-
onClick: m
|
|
45
|
-
}),
|
|
46
|
-
v && /* @__PURE__ */ c(i, {
|
|
52
|
+
_ && /* @__PURE__ */ c(r, {
|
|
47
53
|
loginMethod: "SAGE_BIONETWORKS",
|
|
48
54
|
onClick: (t) => {
|
|
49
55
|
b(t, e.SAGE_BIONETWORKS);
|
|
50
56
|
}
|
|
51
57
|
})
|
|
52
|
-
] })
|
|
53
|
-
loginMethod: "ARCUS",
|
|
54
|
-
onClick: (t) => {
|
|
55
|
-
b(t, e.ARCUS);
|
|
56
|
-
}
|
|
57
|
-
})] });
|
|
58
|
+
] });
|
|
58
59
|
}
|
|
59
60
|
//#endregion
|
|
60
|
-
export {
|
|
61
|
+
export { d as default };
|
|
61
62
|
|
|
62
63
|
//# sourceMappingURL=AuthenticationMethodSelection.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthenticationMethodSelection.js","names":[],"sources":["../../../src/components/Authentication/AuthenticationMethodSelection.tsx"],"sourcesContent":["import SynapseClient from '@/synapse-client'\nimport { OAuth2State, SynapseClientError } from '@/utils'\nimport { generateCsrfToken } from '@/utils/functions/generateCsrfToken'\nimport {\n LOGIN_METHOD_EMAIL,\n LOGIN_METHOD_OAUTH2_ARCUS,\n LOGIN_METHOD_OAUTH2_GOOGLE,\n LOGIN_METHOD_OAUTH2_ORCID,\n LOGIN_METHOD_OAUTH2_SAGE_BIONETWORKS,\n OAUTH2_PROVIDERS,\n} from '@/utils/SynapseConstants'\nimport { Box } from '@mui/material'\nimport { MouseEvent } from 'react'\nimport LoginMethodButton from './LoginMethodButton'\nimport {
|
|
1
|
+
{"version":3,"file":"AuthenticationMethodSelection.js","names":[],"sources":["../../../src/components/Authentication/AuthenticationMethodSelection.tsx"],"sourcesContent":["import SynapseClient from '@/synapse-client'\nimport { OAuth2State, SynapseClientError } from '@/utils'\nimport { generateCsrfToken } from '@/utils/functions/generateCsrfToken'\nimport {\n LOGIN_METHOD_EMAIL,\n LOGIN_METHOD_OAUTH2_ARCUS,\n LOGIN_METHOD_OAUTH2_GOOGLE,\n LOGIN_METHOD_OAUTH2_ORCID,\n LOGIN_METHOD_OAUTH2_SAGE_BIONETWORKS,\n OAUTH2_PROVIDERS,\n} from '@/utils/SynapseConstants'\nimport { Box } from '@mui/material'\nimport { MouseEvent } from 'react'\nimport LoginMethodButton from './LoginMethodButton'\nimport { Realm } from '@sage-bionetworks/synapse-client'\nimport {\n hasArcusProvider,\n hasSageBionetworksProvider,\n} from '@/utils/functions/RealmUtils'\n\ntype AuthenticationMethodSelectionProps = {\n ssoRedirectUrl?: string\n /* Invoked before redirecting to OAuth provider. Useful in portals where we may want to store the current URL to redirect back here. */\n onBeginOAuthSignIn?: () => void\n onSelectUsernameAndPassword: () => void\n state?: OAuth2State\n realm?: Realm\n}\n\nconst csrfToken = generateCsrfToken()\n\n/**\n * To support Google SSO in your portal, you must add your domain to the Authorized Redirect URIs for Synapse authentication.\n * This can be done by visiting https://sagebionetworks.jira.com/servicedesk/customer/portal/9 to set up a collaboration.\n * Synapse engineers must add your redirect URL in the Google API console found at https://console.cloud.google.com/ for this functionality to work.\n */\nexport default function AuthenticationMethodSelection(\n props: AuthenticationMethodSelectionProps,\n) {\n const {\n onBeginOAuthSignIn,\n ssoRedirectUrl,\n onSelectUsernameAndPassword,\n state,\n realm,\n } = props\n\n const showArcusSSOButtonOnly = hasArcusProvider(realm)\n const showSageBionetworksSSOButtonOnly = hasSageBionetworksProvider(realm)\n\n const isSingleIdpOnly =\n showArcusSSOButtonOnly || showSageBionetworksSSOButtonOnly\n const stateWithCSRF: OAuth2State = { ...state, csrfToken }\n\n function onSSOSignIn(event: MouseEvent<HTMLButtonElement>, provider: string) {\n if (onBeginOAuthSignIn) {\n onBeginOAuthSignIn()\n }\n\n event.preventDefault()\n const redirectUrl = ssoRedirectUrl\n ? `${ssoRedirectUrl}${provider}`\n : `${SynapseClient.getRootURL()}?provider=${provider}`\n SynapseClient.oAuthUrlRequest(provider, redirectUrl, stateWithCSRF)\n .then(data => {\n // Send the user to the authorization URL\n window.location.href = data.authorizationUrl\n })\n .catch((err: SynapseClientError) => {\n console.log('Error on oAuth url ', err)\n })\n }\n\n return (\n <Box>\n {!isSingleIdpOnly && (\n <>\n <LoginMethodButton\n loginMethod={LOGIN_METHOD_OAUTH2_GOOGLE}\n iconName=\"google24\"\n onClick={event => {\n onSSOSignIn(event, OAUTH2_PROVIDERS.GOOGLE)\n }}\n />\n <LoginMethodButton\n loginMethod={LOGIN_METHOD_OAUTH2_ORCID}\n iconName=\"orcid\"\n onClick={event => {\n onSSOSignIn(event, OAUTH2_PROVIDERS.ORCID)\n }}\n />\n <LoginMethodButton\n loginMethod={LOGIN_METHOD_EMAIL}\n iconName=\"email\"\n onClick={onSelectUsernameAndPassword}\n />\n </>\n )}\n {showArcusSSOButtonOnly && (\n <LoginMethodButton\n loginMethod={LOGIN_METHOD_OAUTH2_ARCUS}\n // iconName=\"arcusbio\"\n onClick={event => {\n onSSOSignIn(event, OAUTH2_PROVIDERS.ARCUS)\n }}\n />\n )}\n {showSageBionetworksSSOButtonOnly && (\n <LoginMethodButton\n loginMethod={LOGIN_METHOD_OAUTH2_SAGE_BIONETWORKS}\n onClick={event => {\n onSSOSignIn(event, OAUTH2_PROVIDERS.SAGE_BIONETWORKS)\n }}\n />\n )}\n </Box>\n )\n}\n"],"mappings":";;;;;;;;AA6BA,IAAM,IAAY,GAAmB;AAOrC,SAAwB,EACtB,GACA;CACA,IAAM,EACJ,uBACA,mBACA,gCACA,UACA,aACE,GAEE,IAAyB,EAAiB,EAAM,EAChD,IAAmC,EAA2B,EAAM,EAEpE,IACJ,KAA0B,GACtB,IAA6B;EAAE,GAAG;EAAO;EAAW;CAE1D,SAAS,EAAY,GAAsC,GAAkB;AAK3E,EAJI,KACF,GAAoB,EAGtB,EAAM,gBAAgB;EACtB,IAAM,IAAc,IAChB,GAAG,IAAiB,MACpB,GAAG,EAAc,YAAY,CAAC,YAAY;AAC9C,IAAc,gBAAgB,GAAU,GAAa,EAAc,CAChE,MAAK,MAAQ;AAEZ,UAAO,SAAS,OAAO,EAAK;IAC5B,CACD,OAAO,MAA4B;AAClC,WAAQ,IAAI,uBAAuB,EAAI;IACvC;;AAGN,QACE,kBAAC,GAAD,EAAA,UAAA;EACG,CAAC,KACA,kBAAA,GAAA,EAAA,UAAA;GACE,kBAAC,GAAD;IACE,aAAA;IACA,UAAS;IACT,UAAS,MAAS;AAChB,OAAY,GAAO,EAAiB,OAAO;;IAE7C,CAAA;GACF,kBAAC,GAAD;IACE,aAAA;IACA,UAAS;IACT,UAAS,MAAS;AAChB,OAAY,GAAO,EAAiB,MAAM;;IAE5C,CAAA;GACF,kBAAC,GAAD;IACE,aAAA;IACA,UAAS;IACT,SAAS;IACT,CAAA;GACD,EAAA,CAAA;EAEJ,KACC,kBAAC,GAAD;GACE,aAAA;GAEA,UAAS,MAAS;AAChB,MAAY,GAAO,EAAiB,MAAM;;GAE5C,CAAA;EAEH,KACC,kBAAC,GAAD;GACE,aAAA;GACA,UAAS,MAAS;AAChB,MAAY,GAAO,EAAiB,iBAAiB;;GAEvD,CAAA;EAEA,EAAA,CAAA"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export declare const TOTP_GUIDANCE_TEXT = "Enter the 6-digit, time-based verification code provided by your authenticator app.";
|
|
2
2
|
export declare const RECOVERY_CODE_GUIDANCE_TEXT_SHORT = "Enter a one-time backup code. Your backup code is a 16 digit code, with groups of 4 letters or numbers separated by hyphens.";
|
|
3
|
+
export declare const TOTP_CLOCK_SKEW_ERROR_APPENDAGE = "Please ensure automatic date and time is enabled in your device settings and try again.";
|
|
3
4
|
//# sourceMappingURL=Constants.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Constants.d.ts","sourceRoot":"","sources":["../../../src/components/Authentication/Constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,kBAAkB,wFACwD,CAAA;AAEvF,eAAO,MAAM,iCAAiC,iIACkF,CAAA"}
|
|
1
|
+
{"version":3,"file":"Constants.d.ts","sourceRoot":"","sources":["../../../src/components/Authentication/Constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,kBAAkB,wFACwD,CAAA;AAEvF,eAAO,MAAM,iCAAiC,iIACkF,CAAA;AAEhI,eAAO,MAAM,+BAA+B,4FAC+C,CAAA"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
//#region src/components/Authentication/Constants.ts
|
|
2
|
-
var e = "Enter the 6-digit, time-based verification code provided by your authenticator app.", t = "Enter a one-time backup code. Your backup code is a 16 digit code, with groups of 4 letters or numbers separated by hyphens.";
|
|
2
|
+
var e = "Enter the 6-digit, time-based verification code provided by your authenticator app.", t = "Enter a one-time backup code. Your backup code is a 16 digit code, with groups of 4 letters or numbers separated by hyphens.", n = "Please ensure automatic date and time is enabled in your device settings and try again.";
|
|
3
3
|
//#endregion
|
|
4
|
-
export { t as RECOVERY_CODE_GUIDANCE_TEXT_SHORT, e as TOTP_GUIDANCE_TEXT };
|
|
4
|
+
export { t as RECOVERY_CODE_GUIDANCE_TEXT_SHORT, n as TOTP_CLOCK_SKEW_ERROR_APPENDAGE, e as TOTP_GUIDANCE_TEXT };
|
|
5
5
|
|
|
6
6
|
//# sourceMappingURL=Constants.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Constants.js","names":[],"sources":["../../../src/components/Authentication/Constants.ts"],"sourcesContent":["export const TOTP_GUIDANCE_TEXT =\n 'Enter the 6-digit, time-based verification code provided by your authenticator app.'\n\nexport const RECOVERY_CODE_GUIDANCE_TEXT_SHORT =\n 'Enter a one-time backup code. Your backup code is a 16 digit code, with groups of 4 letters or numbers separated by hyphens.'\n"],"mappings":";AAAA,IAAa,IACX,uFAEW,IACX"}
|
|
1
|
+
{"version":3,"file":"Constants.js","names":[],"sources":["../../../src/components/Authentication/Constants.ts"],"sourcesContent":["export const TOTP_GUIDANCE_TEXT =\n 'Enter the 6-digit, time-based verification code provided by your authenticator app.'\n\nexport const RECOVERY_CODE_GUIDANCE_TEXT_SHORT =\n 'Enter a one-time backup code. Your backup code is a 16 digit code, with groups of 4 letters or numbers separated by hyphens.'\n\nexport const TOTP_CLOCK_SKEW_ERROR_APPENDAGE =\n 'Please ensure automatic date and time is enabled in your device settings and try again.'\n"],"mappings":";AAAA,IAAa,IACX,uFAEW,IACX,gIAEW,IACX"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LastLoginInfo.js","names":[],"sources":["../../../src/components/Authentication/LastLoginInfo.tsx"],"sourcesContent":["import { formatDate } from '@/utils/functions/DateFormatter'\nimport {\n CURRENT_SOURCEAPP_NAME_LOCALSTORAGE_KEY,\n LAST_LOGIN_DATE_LOCALSTORAGE_KEY,\n LAST_LOGIN_METHOD_LOCALSTORAGE_KEY,\n LAST_LOGIN_SOURCEAPP_NAME_LOCALSTORAGE_KEY,\n LAST_LOGIN_SOURCEAPP_URL_LOCALSTORAGE_KEY,\n} from '@/utils/SynapseConstants'\nimport { InfoTwoTone } from '@mui/icons-material'\nimport { Box, Link, Tooltip, Typography } from '@mui/material'\nimport { useLocalStorageValue } from '@react-hookz/web'\nimport dayjs from 'dayjs'\nimport { getLoginMethodFriendlyName, LoginMethod } from './LoginMethod'\n\nexport type LastLoginInfoProps = {\n currentSourceAppName: string | undefined\n lastLoginMethod: LoginMethod | undefined\n lastLoginSourceAppName: string | undefined\n lastLoginSourceAppURL: string | undefined\n lastLoginDate: string | undefined\n display: 'sentence' | 'box'\n}\n\nexport function useLastLoginInfoState() {\n return {\n currentSourceAppNameState: useLocalStorageValue<string>(\n CURRENT_SOURCEAPP_NAME_LOCALSTORAGE_KEY,\n ),\n lastLoginMethodState: useLocalStorageValue<LoginMethod>(\n LAST_LOGIN_METHOD_LOCALSTORAGE_KEY,\n ),\n lastLoginSourceAppNameState: useLocalStorageValue<string>(\n LAST_LOGIN_SOURCEAPP_NAME_LOCALSTORAGE_KEY,\n ),\n lastLoginSourceAppURLState: useLocalStorageValue<string>(\n LAST_LOGIN_SOURCEAPP_URL_LOCALSTORAGE_KEY,\n ),\n lastLoginDateState: useLocalStorageValue<string>(\n LAST_LOGIN_DATE_LOCALSTORAGE_KEY,\n ),\n }\n}\n\nexport function useLastLoginInfo() {\n const states = useLastLoginInfoState()\n return {\n currentSourceAppName: states.currentSourceAppNameState.value,\n lastLoginMethod: states.lastLoginMethodState.value,\n lastLoginSourceAppName: states.lastLoginSourceAppNameState.value,\n lastLoginSourceAppURL: states.lastLoginSourceAppURLState.value,\n lastLoginDate: states.lastLoginDateState.value,\n }\n}\n\nexport function clearLastLoginInfo() {\n const keys = [\n CURRENT_SOURCEAPP_NAME_LOCALSTORAGE_KEY,\n LAST_LOGIN_METHOD_LOCALSTORAGE_KEY,\n LAST_LOGIN_SOURCEAPP_NAME_LOCALSTORAGE_KEY,\n LAST_LOGIN_SOURCEAPP_URL_LOCALSTORAGE_KEY,\n LAST_LOGIN_DATE_LOCALSTORAGE_KEY,\n ]\n keys.forEach(key => localStorage.removeItem(key))\n}\n\nfunction getSourceAppIndefiniteArticle(val: string) {\n return val.match(/^[aeiou]/i) ? 'an' : 'a'\n}\n\nfunction getSourceAppDefiniteArticle(val: string) {\n return val.match(' Portal$') ? 'the ' : ''\n}\n\nexport default function LastLoginInfo(props: LastLoginInfoProps) {\n const {\n currentSourceAppName,\n lastLoginMethod,\n lastLoginSourceAppName,\n lastLoginSourceAppURL,\n lastLoginDate,\n display,\n } = props\n\n const showLastLoginInfo =\n currentSourceAppName &&\n lastLoginMethod &&\n lastLoginSourceAppName &&\n lastLoginSourceAppURL &&\n lastLoginDate &&\n currentSourceAppName !== lastLoginSourceAppName\n\n if (!showLastLoginInfo) {\n return null\n }\n\n const currentSourceAppIndefiniteArticle =\n getSourceAppIndefiniteArticle(currentSourceAppName)\n const currentSourceAppDefiniteArticle =\n getSourceAppDefiniteArticle(currentSourceAppName)\n const lastLoginSourceAppDefiniteArticle = getSourceAppDefiniteArticle(\n lastLoginSourceAppName,\n )\n\n const title = `You may already have ${currentSourceAppIndefiniteArticle} ${currentSourceAppName} account`\n const accountLastUsed = `Account last used on ${formatDate(\n dayjs(lastLoginDate),\n 'MMMM D, YYYY',\n )}`\n\n const tooltipText = (\n <>\n <Typography\n variant=\"smallText2\"\n sx={{\n mb: 1,\n }}\n >\n {title}\n </Typography>\n <Typography\n variant=\"smallText1\"\n color=\"white\"\n sx={{\n mb: 1,\n }}\n >\n {`This computer was used to sign in to an account on ${lastLoginSourceAppDefiniteArticle}${lastLoginSourceAppName}. \n You can use the same account to sign in to ${currentSourceAppDefiniteArticle}${currentSourceAppName}.`}\n </Typography>\n <Typography variant=\"smallText1\" color=\"white\">\n {accountLastUsed}\n </Typography>\n </>\n )\n\n const boxText = (\n <>\n <Typography\n variant=\"smallText2\"\n sx={{\n mb: 1,\n color: 'grey.900',\n fontSize: '12px',\n }}\n >\n {title}\n </Typography>\n <Typography\n variant=\"smallText1\"\n sx={{\n mb: 1,\n color: 'grey.900',\n fontSize: '12px',\n }}\n >\n It looks like you already have an account, last used on{' '}\n {lastLoginSourceAppDefiniteArticle}\n <Link href={lastLoginSourceAppURL}>{lastLoginSourceAppName}</Link>.{' '}\n {`You can use this account to sign in via ${getLoginMethodFriendlyName(\n lastLoginMethod,\n )}.`}\n </Typography>\n <Typography\n variant=\"smallText1\"\n sx={{ color: 'grey.700', fontSize: '10px' }}\n >\n {accountLastUsed}\n </Typography>\n </>\n )\n\n return (\n <>\n {display === 'sentence' ? (\n <Typography\n variant=\"smallText1\"\n sx={{ color: 'grey.700', textTransform: 'none' }}\n >\n You may be able to use an existing account\n <Tooltip\n title={tooltipText}\n placement={'top'}\n slotProps={{\n tooltip: {\n sx: {\n bgcolor: '#63676C',\n '& .MuiTooltip-arrow': {\n color: '#63676C',\n },\n },\n },\n }}\n >\n <InfoTwoTone\n sx={{\n color: 'grey.700',\n width: '12px',\n height: '12px',\n ml: '4px',\n verticalAlign: 'middle',\n }}\n />\n </Tooltip>\n </Typography>\n ) : (\n <Box sx={{ backgroundColor: 'grey.100', p: '10px' }}>{boxText}</Box>\n )}\n </>\n )\n}\n"],"mappings":";;;;;;;;;AAuBA,SAAgB,IAAwB;AACtC,QAAO;EACL,2BAA2B,EACzB,EACD;EACD,sBAAsB,EACpB,EACD;EACD,6BAA6B,EAC3B,EACD;EACD,4BAA4B,EAC1B,EACD;EACD,oBAAoB,EAClB,EACD;EACF;;AAGH,SAAgB,IAAmB;CACjC,IAAM,IAAS,GAAuB;AACtC,QAAO;EACL,sBAAsB,EAAO,0BAA0B;EACvD,iBAAiB,EAAO,qBAAqB;EAC7C,wBAAwB,EAAO,4BAA4B;EAC3D,uBAAuB,EAAO,2BAA2B;EACzD,eAAe,EAAO,mBAAmB;EAC1C;;AAGH,SAAgB,IAAqB;
|
|
1
|
+
{"version":3,"file":"LastLoginInfo.js","names":[],"sources":["../../../src/components/Authentication/LastLoginInfo.tsx"],"sourcesContent":["import { formatDate } from '@/utils/functions/DateFormatter'\nimport {\n CURRENT_SOURCEAPP_NAME_LOCALSTORAGE_KEY,\n LAST_LOGIN_DATE_LOCALSTORAGE_KEY,\n LAST_LOGIN_METHOD_LOCALSTORAGE_KEY,\n LAST_LOGIN_SOURCEAPP_NAME_LOCALSTORAGE_KEY,\n LAST_LOGIN_SOURCEAPP_URL_LOCALSTORAGE_KEY,\n} from '@/utils/SynapseConstants'\nimport { InfoTwoTone } from '@mui/icons-material'\nimport { Box, Link, Tooltip, Typography } from '@mui/material'\nimport { useLocalStorageValue } from '@react-hookz/web'\nimport dayjs from 'dayjs'\nimport { getLoginMethodFriendlyName, LoginMethod } from './LoginMethod'\n\nexport type LastLoginInfoProps = {\n currentSourceAppName: string | undefined\n lastLoginMethod: LoginMethod | undefined\n lastLoginSourceAppName: string | undefined\n lastLoginSourceAppURL: string | undefined\n lastLoginDate: string | undefined\n display: 'sentence' | 'box'\n}\n\nexport function useLastLoginInfoState() {\n return {\n currentSourceAppNameState: useLocalStorageValue<string>(\n CURRENT_SOURCEAPP_NAME_LOCALSTORAGE_KEY,\n ),\n lastLoginMethodState: useLocalStorageValue<LoginMethod>(\n LAST_LOGIN_METHOD_LOCALSTORAGE_KEY,\n ),\n lastLoginSourceAppNameState: useLocalStorageValue<string>(\n LAST_LOGIN_SOURCEAPP_NAME_LOCALSTORAGE_KEY,\n ),\n lastLoginSourceAppURLState: useLocalStorageValue<string>(\n LAST_LOGIN_SOURCEAPP_URL_LOCALSTORAGE_KEY,\n ),\n lastLoginDateState: useLocalStorageValue<string>(\n LAST_LOGIN_DATE_LOCALSTORAGE_KEY,\n ),\n }\n}\n\nexport function useLastLoginInfo() {\n const states = useLastLoginInfoState()\n return {\n currentSourceAppName: states.currentSourceAppNameState.value,\n lastLoginMethod: states.lastLoginMethodState.value,\n lastLoginSourceAppName: states.lastLoginSourceAppNameState.value,\n lastLoginSourceAppURL: states.lastLoginSourceAppURLState.value,\n lastLoginDate: states.lastLoginDateState.value,\n }\n}\n\nexport function clearLastLoginInfo() {\n const keys = [\n CURRENT_SOURCEAPP_NAME_LOCALSTORAGE_KEY,\n LAST_LOGIN_METHOD_LOCALSTORAGE_KEY,\n LAST_LOGIN_SOURCEAPP_NAME_LOCALSTORAGE_KEY,\n LAST_LOGIN_SOURCEAPP_URL_LOCALSTORAGE_KEY,\n LAST_LOGIN_DATE_LOCALSTORAGE_KEY,\n ]\n keys.forEach(key => localStorage.removeItem(key))\n}\n\nfunction getSourceAppIndefiniteArticle(val: string) {\n return val.match(/^[aeiou]/i) ? 'an' : 'a'\n}\n\nfunction getSourceAppDefiniteArticle(val: string) {\n return val.match(' Portal$') ? 'the ' : ''\n}\n\nexport default function LastLoginInfo(props: LastLoginInfoProps) {\n const {\n currentSourceAppName,\n lastLoginMethod,\n lastLoginSourceAppName,\n lastLoginSourceAppURL,\n lastLoginDate,\n display,\n } = props\n\n const showLastLoginInfo =\n currentSourceAppName &&\n lastLoginMethod &&\n lastLoginSourceAppName &&\n lastLoginSourceAppURL &&\n lastLoginDate &&\n currentSourceAppName !== lastLoginSourceAppName\n\n if (!showLastLoginInfo) {\n return null\n }\n\n const currentSourceAppIndefiniteArticle =\n getSourceAppIndefiniteArticle(currentSourceAppName)\n const currentSourceAppDefiniteArticle =\n getSourceAppDefiniteArticle(currentSourceAppName)\n const lastLoginSourceAppDefiniteArticle = getSourceAppDefiniteArticle(\n lastLoginSourceAppName,\n )\n\n const title = `You may already have ${currentSourceAppIndefiniteArticle} ${currentSourceAppName} account`\n const accountLastUsed = `Account last used on ${formatDate(\n dayjs(lastLoginDate),\n 'MMMM D, YYYY',\n )}`\n\n const tooltipText = (\n <>\n <Typography\n variant=\"smallText2\"\n sx={{\n mb: 1,\n }}\n >\n {title}\n </Typography>\n <Typography\n variant=\"smallText1\"\n color=\"white\"\n sx={{\n mb: 1,\n }}\n >\n {`This computer was used to sign in to an account on ${lastLoginSourceAppDefiniteArticle}${lastLoginSourceAppName}. \n You can use the same account to sign in to ${currentSourceAppDefiniteArticle}${currentSourceAppName}.`}\n </Typography>\n <Typography variant=\"smallText1\" color=\"white\">\n {accountLastUsed}\n </Typography>\n </>\n )\n\n const boxText = (\n <>\n <Typography\n variant=\"smallText2\"\n sx={{\n mb: 1,\n color: 'grey.900',\n fontSize: '12px',\n }}\n >\n {title}\n </Typography>\n <Typography\n variant=\"smallText1\"\n sx={{\n mb: 1,\n color: 'grey.900',\n fontSize: '12px',\n }}\n >\n It looks like you already have an account, last used on{' '}\n {lastLoginSourceAppDefiniteArticle}\n <Link href={lastLoginSourceAppURL}>{lastLoginSourceAppName}</Link>.{' '}\n {`You can use this account to sign in via ${getLoginMethodFriendlyName(\n lastLoginMethod,\n )}.`}\n </Typography>\n <Typography\n variant=\"smallText1\"\n sx={{ color: 'grey.700', fontSize: '10px' }}\n >\n {accountLastUsed}\n </Typography>\n </>\n )\n\n return (\n <>\n {display === 'sentence' ? (\n <Typography\n variant=\"smallText1\"\n sx={{ color: 'grey.700', textTransform: 'none' }}\n >\n You may be able to use an existing account\n <Tooltip\n title={tooltipText}\n placement={'top'}\n slotProps={{\n tooltip: {\n sx: {\n bgcolor: '#63676C',\n '& .MuiTooltip-arrow': {\n color: '#63676C',\n },\n },\n },\n }}\n >\n <InfoTwoTone\n sx={{\n color: 'grey.700',\n width: '12px',\n height: '12px',\n ml: '4px',\n verticalAlign: 'middle',\n }}\n />\n </Tooltip>\n </Typography>\n ) : (\n <Box sx={{ backgroundColor: 'grey.100', p: '10px' }}>{boxText}</Box>\n )}\n </>\n )\n}\n"],"mappings":";;;;;;;;;AAuBA,SAAgB,IAAwB;AACtC,QAAO;EACL,2BAA2B,EACzB,EACD;EACD,sBAAsB,EACpB,EACD;EACD,6BAA6B,EAC3B,EACD;EACD,4BAA4B,EAC1B,EACD;EACD,oBAAoB,EAClB,EACD;EACF;;AAGH,SAAgB,IAAmB;CACjC,IAAM,IAAS,GAAuB;AACtC,QAAO;EACL,sBAAsB,EAAO,0BAA0B;EACvD,iBAAiB,EAAO,qBAAqB;EAC7C,wBAAwB,EAAO,4BAA4B;EAC3D,uBAAuB,EAAO,2BAA2B;EACzD,eAAe,EAAO,mBAAmB;EAC1C;;AAGH,SAAgB,IAAqB;AAQnC;EANE;EACA;EACA;EACA;EACA;EAEF,CAAK,SAAQ,MAAO,aAAa,WAAW,EAAI,CAAC;;AAGnD,SAAS,EAA8B,GAAa;AAClD,QAAO,EAAI,MAAM,YAAY,GAAG,OAAO;;AAGzC,SAAS,EAA4B,GAAa;AAChD,QAAO,EAAI,MAAM,WAAW,GAAG,SAAS;;AAG1C,SAAwB,EAAc,GAA2B;CAC/D,IAAM,EACJ,yBACA,oBACA,2BACA,0BACA,kBACA,eACE;AAUJ,KAAI,EAPF,KACA,KACA,KACA,KACA,KACA,MAAyB,GAGzB,QAAO;CAGT,IAAM,IACJ,EAA8B,EAAqB,EAC/C,IACJ,EAA4B,EAAqB,EAC7C,IAAoC,EACxC,EACD,EAEK,IAAQ,wBAAwB,EAAkC,GAAG,EAAqB,WAC1F,IAAkB,wBAAwB,EAC9C,EAAM,EAAc,EACpB,eACD,IAEK,IACJ,kBAAA,GAAA,EAAA,UAAA;EACE,kBAAC,GAAD;GACE,SAAQ;GACR,IAAI,EACF,IAAI,GACL;aAEA;GACU,CAAA;EACb,kBAAC,GAAD;GACE,SAAQ;GACR,OAAM;GACN,IAAI,EACF,IAAI,GACL;aAEA,sDAAsD,IAAoC,EAAuB;uDACnE,IAAkC,EAAqB;GAC3F,CAAA;EACb,kBAAC,GAAD;GAAY,SAAQ;GAAa,OAAM;aACpC;GACU,CAAA;EACZ,EAAA,CAAA,EAGC,IACJ,kBAAA,GAAA,EAAA,UAAA;EACE,kBAAC,GAAD;GACE,SAAQ;GACR,IAAI;IACF,IAAI;IACJ,OAAO;IACP,UAAU;IACX;aAEA;GACU,CAAA;EACb,kBAAC,GAAD;GACE,SAAQ;GACR,IAAI;IACF,IAAI;IACJ,OAAO;IACP,UAAU;IACX;aANH;IAOC;IACyD;IACvD;IACD,kBAAC,GAAD;KAAM,MAAM;eAAwB;KAA8B,CAAA;;IAAE;IACnE,2CAA2C,EAC1C,EACD,CAAC;IACS;;EACb,kBAAC,GAAD;GACE,SAAQ;GACR,IAAI;IAAE,OAAO;IAAY,UAAU;IAAQ;aAE1C;GACU,CAAA;EACZ,EAAA,CAAA;AAGL,QACE,kBAAA,GAAA,EAAA,UACG,MAAY,aACX,kBAAC,GAAD;EACE,SAAQ;EACR,IAAI;GAAE,OAAO;GAAY,eAAe;GAAQ;YAFlD,CAGC,8CAEC,kBAAC,GAAD;GACE,OAAO;GACP,WAAW;GACX,WAAW,EACT,SAAS,EACP,IAAI;IACF,SAAS;IACT,uBAAuB,EACrB,OAAO,WACR;IACF,EACF,EACF;aAED,kBAAC,GAAD,EACE,IAAI;IACF,OAAO;IACP,OAAO;IACP,QAAQ;IACR,IAAI;IACJ,eAAe;IAChB,EACD,CAAA;GACM,CAAA,CACC;MAEb,kBAAC,GAAD;EAAK,IAAI;GAAE,iBAAiB;GAAY,GAAG;GAAQ;YAAG;EAAc,CAAA,EAErE,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RecoveryCodeForm.js","names":[],"sources":["../../../src/components/Authentication/RecoveryCodeForm.tsx"],"sourcesContent":["import { UseLoginReturn } from '@/utils/hooks'\nimport { Box, Button } from '@mui/material'\nimport { useState } from 'react'\nimport TextField from '../TextField/TextField'\n\n// 16 characters separated into chunks of 4 by 3 hyphens\nconst RECOVERY_CODE_LENGTH = 19\n\ntype RecoveryCodeFormProps = {\n onSubmit: (value: string) => void\n loginIsPending: UseLoginReturn['loginIsPending']\n}\n\nexport default function RecoveryCodeForm(props: RecoveryCodeFormProps) {\n const { onSubmit, loginIsPending } = props\n const [recoveryCode, setRecoveryCode] = useState('')\n return (\n <Box>\n <TextField\n placeholder=\"Enter backup code\"\n value={recoveryCode}\n onChange={e => {\n // coerce the input to lowercase and remove any nonalphanumeric or hyphen characters\n const valueWithAllowedChars = e.target.value\n .toLowerCase()\n .replace(/[^a-z0-9-]/gi, '')\n setRecoveryCode(valueWithAllowedChars)\n }}\n />\n\n <Button\n fullWidth\n type=\"submit\"\n color=\"primary\"\n variant=\"contained\"\n sx={{\n height: '50px',\n mt: 4,\n mb: 2,\n }}\n disabled={\n recoveryCode.length !== RECOVERY_CODE_LENGTH || loginIsPending\n }\n onClick={e => {\n e.preventDefault()\n onSubmit(recoveryCode)\n }}\n >\n {loginIsPending ? 'Verifying...' : 'Submit'}\n </Button>\n </Box>\n )\n}\n"],"mappings":";;;;;AAMA,IAAM,IAAuB;AAO7B,SAAwB,EAAiB,GAA8B;CACrE,IAAM,EAAE,aAAU,sBAAmB,GAC/B,CAAC,GAAc,KAAmB,EAAS,GAAG;AACpD,QACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;EACE,aAAY;EACZ,OAAO;EACP,WAAU,MAAK;AAKb,KAH8B,EAAE,OAAO,MACpC,aAAa,CACb,QAAQ,gBAAgB,
|
|
1
|
+
{"version":3,"file":"RecoveryCodeForm.js","names":[],"sources":["../../../src/components/Authentication/RecoveryCodeForm.tsx"],"sourcesContent":["import { UseLoginReturn } from '@/utils/hooks'\nimport { Box, Button } from '@mui/material'\nimport { useState } from 'react'\nimport TextField from '../TextField/TextField'\n\n// 16 characters separated into chunks of 4 by 3 hyphens\nconst RECOVERY_CODE_LENGTH = 19\n\ntype RecoveryCodeFormProps = {\n onSubmit: (value: string) => void\n loginIsPending: UseLoginReturn['loginIsPending']\n}\n\nexport default function RecoveryCodeForm(props: RecoveryCodeFormProps) {\n const { onSubmit, loginIsPending } = props\n const [recoveryCode, setRecoveryCode] = useState('')\n return (\n <Box>\n <TextField\n placeholder=\"Enter backup code\"\n value={recoveryCode}\n onChange={e => {\n // coerce the input to lowercase and remove any nonalphanumeric or hyphen characters\n const valueWithAllowedChars = e.target.value\n .toLowerCase()\n .replace(/[^a-z0-9-]/gi, '')\n setRecoveryCode(valueWithAllowedChars)\n }}\n />\n\n <Button\n fullWidth\n type=\"submit\"\n color=\"primary\"\n variant=\"contained\"\n sx={{\n height: '50px',\n mt: 4,\n mb: 2,\n }}\n disabled={\n recoveryCode.length !== RECOVERY_CODE_LENGTH || loginIsPending\n }\n onClick={e => {\n e.preventDefault()\n onSubmit(recoveryCode)\n }}\n >\n {loginIsPending ? 'Verifying...' : 'Submit'}\n </Button>\n </Box>\n )\n}\n"],"mappings":";;;;;AAMA,IAAM,IAAuB;AAO7B,SAAwB,EAAiB,GAA8B;CACrE,IAAM,EAAE,aAAU,sBAAmB,GAC/B,CAAC,GAAc,KAAmB,EAAS,GAAG;AACpD,QACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;EACE,aAAY;EACZ,OAAO;EACP,WAAU,MAAK;AAKb,KAH8B,EAAE,OAAO,MACpC,aAAa,CACb,QAAQ,gBAAgB,GACX,CAAsB;;EAExC,CAAA,EAEF,kBAAC,GAAD;EACE,WAAA;EACA,MAAK;EACL,OAAM;EACN,SAAQ;EACR,IAAI;GACF,QAAQ;GACR,IAAI;GACJ,IAAI;GACL;EACD,UACE,EAAa,WAAW,KAAwB;EAElD,UAAS,MAAK;AAEZ,GADA,EAAE,gBAAgB,EAClB,EAAS,EAAa;;YAGvB,IAAiB,iBAAiB;EAC5B,CAAA,CACL,EAAA,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RecoveryCodeGrid.js","names":[],"sources":["../../../src/components/Authentication/RecoveryCodeGrid.tsx"],"sourcesContent":["import ConditionalWrapper from '@/components/utils/ConditionalWrapper'\nimport { Box } from '@mui/material'\nimport Skeleton from '@mui/material/Skeleton'\nimport { TwoFactorAuthRecoveryCodes } from '@sage-bionetworks/synapse-types'\n\nconst DEFAULT_RECOVERY_CODE_COUNT = 10\n\n// Placeholder codes used to render skeletons while loading\nconst PLACEHOLDER_RECOVERY_CODE = '1234-5678-9012-3456'\nconst PLACEHOLDER_RECOVERY_CODES = Array(DEFAULT_RECOVERY_CODE_COUNT).fill(\n PLACEHOLDER_RECOVERY_CODE,\n)\n\ntype RecoveryCodeGridProps = {\n recoveryCodes?: TwoFactorAuthRecoveryCodes\n}\n\nexport function RecoveryCodeGrid(props: RecoveryCodeGridProps) {\n const { recoveryCodes } = props\n return (\n <Box\n sx={{\n display: 'grid',\n gridTemplateColumns: '47.5% 47.5%',\n columnGap: '5%',\n gridTemplateRows: 'repeat(5, 1fr)',\n fontFamily: 'Menlo, Courier New, Courier, monospace',\n my: 2,\n }}\n >\n {(recoveryCodes?.codes ?? PLACEHOLDER_RECOVERY_CODES).map(\n (code, index) => {\n return (\n <ConditionalWrapper\n key={index}\n condition={!recoveryCodes}\n wrapper={Skeleton}\n wrapperProps={{ width: '100%', height: '100%' }}\n >\n <Box\n sx={{\n my: 1,\n fontSize: '13px',\n }}\n >\n {code}\n </Box>\n </ConditionalWrapper>\n )\n },\n )}\n </Box>\n )\n}\n"],"mappings":";;;;;AASA,IAAM,IAA6B,
|
|
1
|
+
{"version":3,"file":"RecoveryCodeGrid.js","names":[],"sources":["../../../src/components/Authentication/RecoveryCodeGrid.tsx"],"sourcesContent":["import ConditionalWrapper from '@/components/utils/ConditionalWrapper'\nimport { Box } from '@mui/material'\nimport Skeleton from '@mui/material/Skeleton'\nimport { TwoFactorAuthRecoveryCodes } from '@sage-bionetworks/synapse-types'\n\nconst DEFAULT_RECOVERY_CODE_COUNT = 10\n\n// Placeholder codes used to render skeletons while loading\nconst PLACEHOLDER_RECOVERY_CODE = '1234-5678-9012-3456'\nconst PLACEHOLDER_RECOVERY_CODES = Array(DEFAULT_RECOVERY_CODE_COUNT).fill(\n PLACEHOLDER_RECOVERY_CODE,\n)\n\ntype RecoveryCodeGridProps = {\n recoveryCodes?: TwoFactorAuthRecoveryCodes\n}\n\nexport function RecoveryCodeGrid(props: RecoveryCodeGridProps) {\n const { recoveryCodes } = props\n return (\n <Box\n sx={{\n display: 'grid',\n gridTemplateColumns: '47.5% 47.5%',\n columnGap: '5%',\n gridTemplateRows: 'repeat(5, 1fr)',\n fontFamily: 'Menlo, Courier New, Courier, monospace',\n my: 2,\n }}\n >\n {(recoveryCodes?.codes ?? PLACEHOLDER_RECOVERY_CODES).map(\n (code, index) => {\n return (\n <ConditionalWrapper\n key={index}\n condition={!recoveryCodes}\n wrapper={Skeleton}\n wrapperProps={{ width: '100%', height: '100%' }}\n >\n <Box\n sx={{\n my: 1,\n fontSize: '13px',\n }}\n >\n {code}\n </Box>\n </ConditionalWrapper>\n )\n },\n )}\n </Box>\n )\n}\n"],"mappings":";;;;;AASA,IAAM,IAA6B,MAAM,GAA4B,CAAC,KACpE,sBACD;AAMD,SAAgB,EAAiB,GAA8B;CAC7D,IAAM,EAAE,qBAAkB;AAC1B,QACE,kBAAC,GAAD;EACE,IAAI;GACF,SAAS;GACT,qBAAqB;GACrB,WAAW;GACX,kBAAkB;GAClB,YAAY;GACZ,IAAI;GACL;aAEC,GAAe,SAAS,GAA4B,KACnD,GAAM,MAEH,kBAAC,GAAD;GAEE,WAAW,CAAC;GACZ,SAAS;GACT,cAAc;IAAE,OAAO;IAAQ,QAAQ;IAAQ;aAE/C,kBAAC,GAAD;IACE,IAAI;KACF,IAAI;KACJ,UAAU;KACX;cAEA;IACG,CAAA;GACa,EAbd,EAac,CAG1B;EACG,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RegenerateBackupCodesWarning.js","names":[],"sources":["../../../src/components/Authentication/RegenerateBackupCodesWarning.tsx"],"sourcesContent":["import FrontHand from '@/assets/icons/FrontHand'\nimport { Avatar, Box, Button, Paper, Typography, useTheme } from '@mui/material'\n\ntype RegenerateBackupCodesWarningProps = {\n onConfirm: () => void\n onCancel: () => void\n}\n\nexport function RegenerateBackupCodesWarning(\n props: RegenerateBackupCodesWarningProps,\n) {\n const { onConfirm, onCancel } = props\n const theme = useTheme()\n return (\n <Paper sx={{ m: 'auto', maxWidth: '500px', p: 8 }}>\n <Avatar\n sx={{\n bgcolor: theme.palette.primary.main,\n height: '100px',\n width: '100px',\n }}\n >\n <FrontHand sx={{ height: '54px', width: '54px' }} />\n </Avatar>\n <Box sx={{ my: 5 }}>\n <Typography variant={'headline1'} sx={{ mb: 2 }}>\n Really regenerate backup codes?\n </Typography>\n <Typography variant={'body1'} sx={{ my: 1 }}>\n This will invalidate your old backup codes\n </Typography>\n <Typography variant={'body1'} sx={{ my: 1 }}>\n If you click “yes”, below, we will generate 10 new backup codes,\n replacing your old ones, which will no longer function.\n </Typography>\n </Box>\n <Button\n fullWidth\n variant=\"contained\"\n onClick={onConfirm}\n sx={{ height: '50px', my: 1 }}\n >\n Yes, regenerate backup codes\n </Button>\n <Button\n fullWidth\n variant=\"text\"\n onClick={onCancel}\n sx={{ height: '50px', my: 1 }}\n >\n Nevermind\n </Button>\n </Paper>\n )\n}\n"],"mappings":";;;;AAQA,SAAgB,EACd,GACA;CACA,IAAM,EAAE,cAAW,gBAAa;AAEhC,QACE,kBAAC,GAAD;EAAO,IAAI;GAAE,GAAG;GAAQ,UAAU;GAAS,GAAG;GAAG;YAAjD;GACE,kBAAC,GAAD;IACE,IAAI;KACF,SALM,
|
|
1
|
+
{"version":3,"file":"RegenerateBackupCodesWarning.js","names":[],"sources":["../../../src/components/Authentication/RegenerateBackupCodesWarning.tsx"],"sourcesContent":["import FrontHand from '@/assets/icons/FrontHand'\nimport { Avatar, Box, Button, Paper, Typography, useTheme } from '@mui/material'\n\ntype RegenerateBackupCodesWarningProps = {\n onConfirm: () => void\n onCancel: () => void\n}\n\nexport function RegenerateBackupCodesWarning(\n props: RegenerateBackupCodesWarningProps,\n) {\n const { onConfirm, onCancel } = props\n const theme = useTheme()\n return (\n <Paper sx={{ m: 'auto', maxWidth: '500px', p: 8 }}>\n <Avatar\n sx={{\n bgcolor: theme.palette.primary.main,\n height: '100px',\n width: '100px',\n }}\n >\n <FrontHand sx={{ height: '54px', width: '54px' }} />\n </Avatar>\n <Box sx={{ my: 5 }}>\n <Typography variant={'headline1'} sx={{ mb: 2 }}>\n Really regenerate backup codes?\n </Typography>\n <Typography variant={'body1'} sx={{ my: 1 }}>\n This will invalidate your old backup codes\n </Typography>\n <Typography variant={'body1'} sx={{ my: 1 }}>\n If you click “yes”, below, we will generate 10 new backup codes,\n replacing your old ones, which will no longer function.\n </Typography>\n </Box>\n <Button\n fullWidth\n variant=\"contained\"\n onClick={onConfirm}\n sx={{ height: '50px', my: 1 }}\n >\n Yes, regenerate backup codes\n </Button>\n <Button\n fullWidth\n variant=\"text\"\n onClick={onCancel}\n sx={{ height: '50px', my: 1 }}\n >\n Nevermind\n </Button>\n </Paper>\n )\n}\n"],"mappings":";;;;AAQA,SAAgB,EACd,GACA;CACA,IAAM,EAAE,cAAW,gBAAa;AAEhC,QACE,kBAAC,GAAD;EAAO,IAAI;GAAE,GAAG;GAAQ,UAAU;GAAS,GAAG;GAAG;YAAjD;GACE,kBAAC,GAAD;IACE,IAAI;KACF,SALM,GAKG,CAAM,QAAQ,QAAQ;KAC/B,QAAQ;KACR,OAAO;KACR;cAED,kBAAC,GAAD,EAAW,IAAI;KAAE,QAAQ;KAAQ,OAAO;KAAQ,EAAI,CAAA;IAC7C,CAAA;GACT,kBAAC,GAAD;IAAK,IAAI,EAAE,IAAI,GAAG;cAAlB;KACE,kBAAC,GAAD;MAAY,SAAS;MAAa,IAAI,EAAE,IAAI,GAAG;gBAAE;MAEpC,CAAA;KACb,kBAAC,GAAD;MAAY,SAAS;MAAS,IAAI,EAAE,IAAI,GAAG;gBAAE;MAEhC,CAAA;KACb,kBAAC,GAAD;MAAY,SAAS;MAAS,IAAI,EAAE,IAAI,GAAG;gBAAE;MAGhC,CAAA;KACT;;GACN,kBAAC,GAAD;IACE,WAAA;IACA,SAAQ;IACR,SAAS;IACT,IAAI;KAAE,QAAQ;KAAQ,IAAI;KAAG;cAC9B;IAEQ,CAAA;GACT,kBAAC,GAAD;IACE,WAAA;IACA,SAAQ;IACR,SAAS;IACT,IAAI;KAAE,QAAQ;KAAQ,IAAI;KAAG;cAC9B;IAEQ,CAAA;GACH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Reset2FAWarning.js","names":[],"sources":["../../../src/components/Authentication/Reset2FAWarning.tsx"],"sourcesContent":["import FrontHand from '@/assets/icons/FrontHand'\nimport { Avatar, Box, Button, Paper, Typography, useTheme } from '@mui/material'\n\ntype Reset2FAWarningProps = {\n onConfirm: () => void\n onCancel: () => void\n}\n\nexport default function Reset2FAWarning(props: Reset2FAWarningProps) {\n const { onConfirm, onCancel } = props\n const theme = useTheme()\n return (\n <Paper sx={{ m: 'auto', maxWidth: '500px', p: 8 }}>\n <Avatar\n sx={{\n bgcolor: theme.palette.primary.main,\n height: '100px',\n width: '100px',\n }}\n >\n <FrontHand sx={{ height: '54px', width: '54px' }} />\n </Avatar>\n <Box sx={{ my: 5 }}>\n <Typography variant={'headline1'} sx={{ mb: 2 }}>\n Really reset 2FA?\n </Typography>\n <Typography variant={'body1'} sx={{ my: 1 }}>\n You'll set up new security codes on the next screen using your\n authenticator app. Your current codes will keep working until you\n finish setting up the new ones.\n </Typography>\n <Typography variant={'body1'} sx={{ my: 1 }}>\n Once setup is complete, only your new codes will work for logging in.\n </Typography>\n </Box>\n <Button\n fullWidth\n variant=\"contained\"\n onClick={onConfirm}\n sx={{ height: '50px', my: 1 }}\n >\n Yes, reset 2FA\n </Button>\n <Button\n fullWidth\n variant=\"text\"\n onClick={onCancel}\n sx={{ height: '50px', my: 1 }}\n >\n Nevermind\n </Button>\n </Paper>\n )\n}\n"],"mappings":";;;;AAQA,SAAwB,EAAgB,GAA6B;CACnE,IAAM,EAAE,cAAW,gBAAa;AAEhC,QACE,kBAAC,GAAD;EAAO,IAAI;GAAE,GAAG;GAAQ,UAAU;GAAS,GAAG;GAAG;YAAjD;GACE,kBAAC,GAAD;IACE,IAAI;KACF,SALM,
|
|
1
|
+
{"version":3,"file":"Reset2FAWarning.js","names":[],"sources":["../../../src/components/Authentication/Reset2FAWarning.tsx"],"sourcesContent":["import FrontHand from '@/assets/icons/FrontHand'\nimport { Avatar, Box, Button, Paper, Typography, useTheme } from '@mui/material'\n\ntype Reset2FAWarningProps = {\n onConfirm: () => void\n onCancel: () => void\n}\n\nexport default function Reset2FAWarning(props: Reset2FAWarningProps) {\n const { onConfirm, onCancel } = props\n const theme = useTheme()\n return (\n <Paper sx={{ m: 'auto', maxWidth: '500px', p: 8 }}>\n <Avatar\n sx={{\n bgcolor: theme.palette.primary.main,\n height: '100px',\n width: '100px',\n }}\n >\n <FrontHand sx={{ height: '54px', width: '54px' }} />\n </Avatar>\n <Box sx={{ my: 5 }}>\n <Typography variant={'headline1'} sx={{ mb: 2 }}>\n Really reset 2FA?\n </Typography>\n <Typography variant={'body1'} sx={{ my: 1 }}>\n You'll set up new security codes on the next screen using your\n authenticator app. Your current codes will keep working until you\n finish setting up the new ones.\n </Typography>\n <Typography variant={'body1'} sx={{ my: 1 }}>\n Once setup is complete, only your new codes will work for logging in.\n </Typography>\n </Box>\n <Button\n fullWidth\n variant=\"contained\"\n onClick={onConfirm}\n sx={{ height: '50px', my: 1 }}\n >\n Yes, reset 2FA\n </Button>\n <Button\n fullWidth\n variant=\"text\"\n onClick={onCancel}\n sx={{ height: '50px', my: 1 }}\n >\n Nevermind\n </Button>\n </Paper>\n )\n}\n"],"mappings":";;;;AAQA,SAAwB,EAAgB,GAA6B;CACnE,IAAM,EAAE,cAAW,gBAAa;AAEhC,QACE,kBAAC,GAAD;EAAO,IAAI;GAAE,GAAG;GAAQ,UAAU;GAAS,GAAG;GAAG;YAAjD;GACE,kBAAC,GAAD;IACE,IAAI;KACF,SALM,GAKG,CAAM,QAAQ,QAAQ;KAC/B,QAAQ;KACR,OAAO;KACR;cAED,kBAAC,GAAD,EAAW,IAAI;KAAE,QAAQ;KAAQ,OAAO;KAAQ,EAAI,CAAA;IAC7C,CAAA;GACT,kBAAC,GAAD;IAAK,IAAI,EAAE,IAAI,GAAG;cAAlB;KACE,kBAAC,GAAD;MAAY,SAAS;MAAa,IAAI,EAAE,IAAI,GAAG;gBAAE;MAEpC,CAAA;KACb,kBAAC,GAAD;MAAY,SAAS;MAAS,IAAI,EAAE,IAAI,GAAG;gBAAE;MAIhC,CAAA;KACb,kBAAC,GAAD;MAAY,SAAS;MAAS,IAAI,EAAE,IAAI,GAAG;gBAAE;MAEhC,CAAA;KACT;;GACN,kBAAC,GAAD;IACE,WAAA;IACA,SAAQ;IACR,SAAS;IACT,IAAI;KAAE,QAAQ;KAAQ,IAAI;KAAG;cAC9B;IAEQ,CAAA;GACT,kBAAC,GAAD;IACE,WAAA;IACA,SAAQ;IACR,SAAS;IACT,IAAI;KAAE,QAAQ;KAAQ,IAAI;KAAG;cAC9B;IAEQ,CAAA;GACH"}
|