synapse-react-client 4.0.9 → 4.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/SWC.index.d.ts +1 -0
- package/dist/SWC.index.d.ts.map +1 -1
- package/dist/SWC.index.js +2 -1
- package/dist/SWC.index.js.map +1 -1
- package/dist/aridhia-queries/aridhiaTokenExchange.js.map +1 -1
- package/dist/aridhia-queries/useGetAridhiaRequests.js.map +1 -1
- package/dist/assets/icons/CloudWarning.d.ts +5 -0
- package/dist/assets/icons/CloudWarning.d.ts.map +1 -0
- package/dist/assets/icons/CloudWarning.js +47 -0
- package/dist/assets/icons/CloudWarning.js.map +1 -0
- package/dist/assets/icons/TasksIcon.d.ts.map +1 -1
- package/dist/assets/icons/TasksIcon.js +6 -10
- package/dist/assets/icons/TasksIcon.js.map +1 -1
- package/dist/components/AccessRequirementAclEditor/AccessRequirementAclEditor.d.ts.map +1 -1
- package/dist/components/AccessRequirementAclEditor/AccessRequirementAclEditor.js +69 -63
- package/dist/components/AccessRequirementAclEditor/AccessRequirementAclEditor.js.map +1 -1
- package/dist/components/AccessRequirementList/AccessApprovalCheckMark.js.map +1 -1
- package/dist/components/AccessRequirementList/AccessRequirementList.js.map +1 -1
- package/dist/components/AccessRequirementList/AccessRequirementListUtils.js.map +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/DataAccessRequestAccessorsEditor.js.map +1 -1
- package/dist/components/AccessRequirementList/RequirementItem/SelfSignAccessRequirementItem.js.map +1 -1
- package/dist/components/AccessRequirementRelatedProjectsList/AccessRequirementRelatedProjectsList.js.map +1 -1
- package/dist/components/AccessTokenPage/AccessTokenCard/AccessTokenCard.js.map +1 -1
- package/dist/components/AcknowledgementsPage/StudyAcknowledgements.js.map +1 -1
- package/dist/components/AclEditor/PermissionLevelMenu.js.map +1 -1
- package/dist/components/AclEditor/ResourceAccessAndUserGroupHeader.js.map +1 -1
- package/dist/components/AclEditor/useSortResourceAccessList.js.map +1 -1
- package/dist/components/AclEditor/useUpdateAcl.js.map +1 -1
- package/dist/components/Aridhia/AridhiaAccessStatus.js.map +1 -1
- package/dist/components/Authentication/AuthenticationMethodSelection.d.ts.map +1 -1
- package/dist/components/Authentication/AuthenticationMethodSelection.js +38 -37
- package/dist/components/Authentication/AuthenticationMethodSelection.js.map +1 -1
- package/dist/components/Authentication/Constants.d.ts +1 -0
- package/dist/components/Authentication/Constants.d.ts.map +1 -1
- package/dist/components/Authentication/Constants.js +2 -2
- package/dist/components/Authentication/Constants.js.map +1 -1
- package/dist/components/Authentication/LastLoginInfo.js.map +1 -1
- package/dist/components/Authentication/RecoveryCodeForm.js.map +1 -1
- package/dist/components/Authentication/RecoveryCodeGrid.js.map +1 -1
- package/dist/components/Authentication/RegenerateBackupCodesWarning.js.map +1 -1
- package/dist/components/Authentication/Reset2FAWarning.js.map +1 -1
- package/dist/components/Authentication/StandaloneLoginForm.js +1 -1
- package/dist/components/Authentication/TwoFactorBackupCodes.js.map +1 -1
- package/dist/components/Authentication/TwoFactorEnrollmentForm.d.ts.map +1 -1
- package/dist/components/Authentication/TwoFactorEnrollmentForm.js +2 -1
- package/dist/components/Authentication/TwoFactorEnrollmentForm.js.map +1 -1
- package/dist/components/BasePortalCard/ColorfulPortalCardWithChips/ColorfulPortalCardWithChips.js.map +1 -1
- package/dist/components/CardContainer/CardContainer.js.map +1 -1
- package/dist/components/CardDeck/CardDeck.Mobile.js.map +1 -1
- package/dist/components/CardDeck/TableQueryCardDeck.js.map +1 -1
- package/dist/components/CertificationQuiz/CertificationQuiz.js.map +1 -1
- package/dist/components/ChallengeDataDownload/ChallengeDataDownload.js.map +1 -1
- package/dist/components/ChallengeSubmission/ChallengeSubmission.js.map +1 -1
- package/dist/components/ChallengeSubmission/ChallengeSubmissionStepper.js.map +1 -1
- package/dist/components/ChallengeSubmission/EvaluationQueueCurrentRoundInfo.js.map +1 -1
- package/dist/components/ChallengeSubmission/EvaluationQueueList.js.map +1 -1
- package/dist/components/ChallengeSubmission/SubmissionDirectoryList.d.ts.map +1 -1
- package/dist/components/ChallengeSubmission/SubmissionDirectoryList.js +143 -140
- package/dist/components/ChallengeSubmission/SubmissionDirectoryList.js.map +1 -1
- package/dist/components/ChallengeTeamWizard/ChallengeTeamWizard.js.map +1 -1
- package/dist/components/ChallengeTeamWizard/CreateChallengeTeam.js.map +1 -1
- package/dist/components/ChangePassword/ChangePassword.js.map +1 -1
- package/dist/components/ChangePassword/ChangePasswordWithToken.js.map +1 -1
- package/dist/components/ChangePassword/useChangePasswordFormState.js +1 -1
- package/dist/components/ChangePassword/useChangePasswordFormState.js.map +1 -1
- package/dist/components/CitationPopover/CitationPopoverContent.js.map +1 -1
- package/dist/components/ColumnFilter/ColumnFilter.js.map +1 -1
- package/dist/components/ComponentCollapse.js.map +1 -1
- package/dist/components/CookiesNotification/CookiesNotification.js.map +1 -1
- package/dist/components/CreateProjectModal/CreateProjectModal.js.map +1 -1
- package/dist/components/CreateTableViewWizard/CreateTableViewWizardUtils.js.map +1 -1
- package/dist/components/DataGrid/DataGrid.d.ts +0 -1
- package/dist/components/DataGrid/DataGrid.d.ts.map +1 -1
- package/dist/components/DataGrid/DataGrid.js +72 -72
- package/dist/components/DataGrid/DataGrid.js.map +1 -1
- package/dist/components/DataGrid/DataGridWebSocket.d.ts +4 -0
- package/dist/components/DataGrid/DataGridWebSocket.d.ts.map +1 -1
- package/dist/components/DataGrid/DataGridWebSocket.js +9 -8
- package/dist/components/DataGrid/DataGridWebSocket.js.map +1 -1
- package/dist/components/DataGrid/SynapseGrid.d.ts.map +1 -1
- package/dist/components/DataGrid/SynapseGrid.js +326 -268
- package/dist/components/DataGrid/SynapseGrid.js.map +1 -1
- package/dist/components/DataGrid/columns/AutocompleteColumn.d.ts +2 -0
- package/dist/components/DataGrid/columns/AutocompleteColumn.d.ts.map +1 -1
- package/dist/components/DataGrid/columns/AutocompleteColumn.js +124 -67
- package/dist/components/DataGrid/columns/AutocompleteColumn.js.map +1 -1
- package/dist/components/DataGrid/columns/AutocompleteMultipleEnumColumn.d.ts +2 -1
- package/dist/components/DataGrid/columns/AutocompleteMultipleEnumColumn.d.ts.map +1 -1
- package/dist/components/DataGrid/columns/AutocompleteMultipleEnumColumn.js +126 -122
- package/dist/components/DataGrid/columns/AutocompleteMultipleEnumColumn.js.map +1 -1
- package/dist/components/DataGrid/columns/useGridAutocompleteState.d.ts +58 -0
- package/dist/components/DataGrid/columns/useGridAutocompleteState.d.ts.map +1 -0
- package/dist/components/DataGrid/columns/useGridAutocompleteState.js +52 -0
- package/dist/components/DataGrid/columns/useGridAutocompleteState.js.map +1 -0
- package/dist/components/DataGrid/components/ValidationAlert.d.ts +5 -2
- package/dist/components/DataGrid/components/ValidationAlert.d.ts.map +1 -1
- package/dist/components/DataGrid/components/ValidationAlert.js +429 -24
- package/dist/components/DataGrid/components/ValidationAlert.js.map +1 -1
- package/dist/components/DataGrid/hooks/useColumnResizeHandles.js.map +1 -1
- package/dist/components/DataGrid/hooks/useGetSchemaForGrid.js.map +1 -1
- package/dist/components/DataGrid/hooks/useGridUndoRedo.js.map +1 -1
- package/dist/components/DataGrid/hooks/useStack.js.map +1 -1
- package/dist/components/DataGrid/useCRDTModelView.js.map +1 -1
- package/dist/components/DataGrid/useDataGridWebsocket.d.ts +7 -0
- package/dist/components/DataGrid/useDataGridWebsocket.d.ts.map +1 -1
- package/dist/components/DataGrid/useDataGridWebsocket.js +16 -2
- package/dist/components/DataGrid/useDataGridWebsocket.js.map +1 -1
- package/dist/components/DataGrid/useInitializeGridConnection.js.map +1 -1
- package/dist/components/DataGrid/useMergeGridWithRecordSet.js.map +1 -1
- package/dist/components/DataGrid/useMergeGridWithSource.js.map +1 -1
- package/dist/components/DataGrid/useMergeGridWithTable.js.map +1 -1
- package/dist/components/DataGrid/utils/DataGridUtils.js.map +1 -1
- package/dist/components/DataGrid/utils/applyModelChange.d.ts +1 -1
- package/dist/components/DataGrid/utils/applyModelChange.d.ts.map +1 -1
- package/dist/components/DataGrid/utils/applyModelChange.js +27 -24
- package/dist/components/DataGrid/utils/applyModelChange.js.map +1 -1
- package/dist/components/DataGrid/utils/columnFactory.d.ts +8 -0
- package/dist/components/DataGrid/utils/columnFactory.d.ts.map +1 -1
- package/dist/components/DataGrid/utils/columnFactory.js +47 -44
- package/dist/components/DataGrid/utils/columnFactory.js.map +1 -1
- package/dist/components/DataGrid/utils/computeReplicaSelectionModel.js.map +1 -1
- package/dist/components/DataGrid/utils/extractColumnValidationMessages.js.map +1 -1
- package/dist/components/DataGrid/utils/getCellClassName.d.ts.map +1 -1
- package/dist/components/DataGrid/utils/getCellClassName.js +8 -8
- package/dist/components/DataGrid/utils/getCellClassName.js.map +1 -1
- package/dist/components/DataGrid/utils/getEmptyValue.d.ts +2 -0
- package/dist/components/DataGrid/utils/getEmptyValue.d.ts.map +1 -0
- package/dist/components/DataGrid/utils/getEmptyValue.js +8 -0
- package/dist/components/DataGrid/utils/getEmptyValue.js.map +1 -0
- package/dist/components/DataGrid/utils/json-rx/JsonRx.js.map +1 -1
- package/dist/components/DataGrid/utils/modelColsToGrid.d.ts.map +1 -1
- package/dist/components/DataGrid/utils/modelColsToGrid.js +2 -1
- package/dist/components/DataGrid/utils/modelColsToGrid.js.map +1 -1
- package/dist/components/DataGrid/utils/modelRowsToGrid.js.map +1 -1
- package/dist/components/DataGrid/utils/parseFreeTextUsingJsonSchemaType.js.map +1 -1
- package/dist/components/DataGrid/utils/schemaAwarePasteValue.d.ts +32 -0
- package/dist/components/DataGrid/utils/schemaAwarePasteValue.d.ts.map +1 -0
- package/dist/components/DataGrid/utils/schemaAwarePasteValue.js +22 -0
- package/dist/components/DataGrid/utils/schemaAwarePasteValue.js.map +1 -0
- package/dist/components/DataGrid/utils/splitPatch.js.map +1 -1
- package/dist/components/DateTimePicker/DateTimePicker.js.map +1 -1
- package/dist/components/DirectDownload/DirectDownload.js.map +1 -1
- package/dist/components/DirectDownloadButton.js.map +1 -1
- package/dist/components/DownloadCart/CreatePackageV2.js.map +1 -1
- package/dist/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.css +1 -0
- package/dist/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.d.ts.map +1 -1
- package/dist/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.js +199 -132
- package/dist/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.js.map +1 -1
- package/dist/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.module.js +22 -0
- package/dist/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.module.js.map +1 -0
- package/dist/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.module.scss +170 -0
- package/dist/components/DownloadCart/DownloadListActionsRequired.js.map +1 -1
- package/dist/components/DownloadCart/DownloadListTable.js.map +1 -1
- package/dist/components/DownloadCart/fileNameUtils.js.map +1 -1
- package/dist/components/DraggableDialog/DraggableDialog.js.map +1 -1
- package/dist/components/DynamicForm/DynamicFormModal.js.map +1 -1
- package/dist/components/Ecosystem/TableQueryEcosystem.js.map +1 -1
- package/dist/components/EntityAclEditor/EntityAclEditor.d.ts.map +1 -1
- package/dist/components/EntityAclEditor/EntityAclEditor.js +103 -103
- package/dist/components/EntityAclEditor/EntityAclEditor.js.map +1 -1
- package/dist/components/EntityAclEditor/useNotifyNewACLUsers.js.map +1 -1
- package/dist/components/EntityBadgeIcons/EntityBadgeIcons.js.map +1 -1
- package/dist/components/EntityCitation/EntityCitation.js.map +1 -1
- package/dist/components/EntityDownloadButton/EntityDownloadButton.d.ts.map +1 -1
- package/dist/components/EntityDownloadButton/EntityDownloadButton.js +1 -0
- package/dist/components/EntityDownloadButton/EntityDownloadButton.js.map +1 -1
- package/dist/components/EntityDownloadConfirmation/EntityDownloadConfirmation.d.ts.map +1 -1
- package/dist/components/EntityDownloadConfirmation/EntityDownloadConfirmation.js +36 -30
- package/dist/components/EntityDownloadConfirmation/EntityDownloadConfirmation.js.map +1 -1
- package/dist/components/EntityFinder/EntityFinder.js.map +1 -1
- package/dist/components/EntityFinder/VersionSelectionType.js.map +1 -1
- package/dist/components/EntityFinder/details/configurations/EntityChildrenDetails.js.map +1 -1
- package/dist/components/EntityFinder/details/configurations/FavoritesDetails.js.map +1 -1
- package/dist/components/EntityFinder/details/configurations/ProjectListDetails.js.map +1 -1
- package/dist/components/EntityFinder/details/view/DetailsView.js.map +1 -1
- package/dist/components/EntityFinder/tree/EntityTree.js.map +1 -1
- package/dist/components/EntityFinder/tree/VirtualizedTree.js.map +1 -1
- package/dist/components/EntityFinder/useEntitySelection.js.map +1 -1
- package/dist/components/EntityForm/EntityForm.js.map +1 -1
- package/dist/components/EntityHeaderTable/EntityHeaderTable.js.map +1 -1
- package/dist/components/EntityHeaderTable/Filter.js.map +1 -1
- package/dist/components/EntityHeaderTable/useEntityHeaderTableState.js.map +1 -1
- package/dist/components/EntitySubjectsSelector/EntitySubjectsSelector.js.map +1 -1
- package/dist/components/EntityTreeTable/components/IdColumnHeader.js.map +1 -1
- package/dist/components/EntityTreeTable/hooks/useEntityTreeState.js.map +1 -1
- package/dist/components/EntityTreeTable/hooks/useTableColumns.js.map +1 -1
- package/dist/components/EntityTreeTable/hooks/useTableData.js.map +1 -1
- package/dist/components/EntityTreeTable/hooks/useTreeOperationsWithDirectFetch.js.map +1 -1
- package/dist/components/EntityUpload/EntityUpload.js.map +1 -1
- package/dist/components/EntityViewScopeEditor/EntityViewMaskEditor.d.ts.map +1 -1
- package/dist/components/EntityViewScopeEditor/EntityViewMaskEditor.js +15 -14
- package/dist/components/EntityViewScopeEditor/EntityViewMaskEditor.js.map +1 -1
- package/dist/components/ExperimentalMode/ExperimentalMode.js.map +1 -1
- package/dist/components/ExternalFileHandleLink/ExternalFileHandleLink.js.map +1 -1
- package/dist/components/FeaturedDataTabs/FacetPlotsCard.js.map +1 -1
- package/dist/components/FeaturedDataTabs/QueryPerFacetPlotsCard.js.map +1 -1
- package/dist/components/FeaturedDataTabs/SingleQueryFacetPlotsCards.js.map +1 -1
- package/dist/components/FeaturedResearch/FeaturedResearch.js.map +1 -1
- package/dist/components/FeaturedToolsList/FeaturedToolsList.js.map +1 -1
- package/dist/components/FilePreview/FileHandleContentRenderer.js.map +1 -1
- package/dist/components/FilePreview/HtmlPreview/HtmlPreview.js.map +1 -1
- package/dist/components/FilePreview/PreviewRendererType.js.map +1 -1
- package/dist/components/Forum/DiscussionReply.d.ts +1 -0
- package/dist/components/Forum/DiscussionReply.d.ts.map +1 -1
- package/dist/components/Forum/DiscussionReply.js +19 -19
- package/dist/components/Forum/DiscussionReply.js.map +1 -1
- package/dist/components/Forum/DiscussionSearchResult.js.map +1 -1
- package/dist/components/Forum/DiscussionThread.d.ts +1 -0
- package/dist/components/Forum/DiscussionThread.d.ts.map +1 -1
- package/dist/components/Forum/DiscussionThread.js +73 -72
- package/dist/components/Forum/DiscussionThread.js.map +1 -1
- package/dist/components/Forum/ForumTable.js.map +1 -1
- package/dist/components/Forum/ForumThreadEditor.js.map +1 -1
- package/dist/components/FullTextSearch/FullTextSearchUtils.js.map +1 -1
- package/dist/components/GenericCard/BioregistryRules.d.ts.map +1 -1
- package/dist/components/GenericCard/BioregistryRules.js +7 -3
- package/dist/components/GenericCard/BioregistryRules.js.map +1 -1
- package/dist/components/GenericCard/GenericCard.d.ts.map +1 -1
- package/dist/components/GenericCard/GenericCard.js +12 -7
- package/dist/components/GenericCard/GenericCard.js.map +1 -1
- package/dist/components/GenericCard/Linkify.js.map +1 -1
- package/dist/components/GenericCard/SynapseCardLabel.js.map +1 -1
- package/dist/components/GenericCard/TableRowGenericCard.js +105 -105
- package/dist/components/GenericCard/TableRowGenericCard.js.map +1 -1
- package/dist/components/Goals/Goals.Mobile.js.map +1 -1
- package/dist/components/Goals/Goals.js.map +1 -1
- package/dist/components/GoalsV2/GoalsV2.Mobile.js.map +1 -1
- package/dist/components/GoalsV2/GoalsV2.js.map +1 -1
- package/dist/components/GoalsV3/GoalsV3.Mobile.js.map +1 -1
- package/dist/components/GoalsV3/GoalsV3.js.map +1 -1
- package/dist/components/GoogleMap/SynapseUserMarker.js.map +1 -1
- package/dist/components/HasAccess/AccessIcon.js.map +1 -1
- package/dist/components/HasAccess/useHasAccess.js.map +1 -1
- package/dist/components/HeaderCard/HeaderCardV2.js.map +1 -1
- package/dist/components/HeaderCard.d.ts +6 -1
- package/dist/components/HeaderCard.d.ts.map +1 -1
- package/dist/components/HeaderCard.js +107 -76
- package/dist/components/HeaderCard.js.map +1 -1
- package/dist/components/HexGrid/HexGrid.js.map +1 -1
- package/dist/components/IconList.js.map +1 -1
- package/dist/components/IconSvg/IconSvg.d.ts.map +1 -1
- package/dist/components/IconSvg/IconSvg.js +2 -1
- package/dist/components/IconSvg/IconSvg.js.map +1 -1
- package/dist/components/ImageCardGridWithLinks/ImageCardGridWithLinks.js.map +1 -1
- package/dist/components/ImageFromSynapseTable.js.map +1 -1
- package/dist/components/JSONArrayEditor/useParseCsv.js.map +1 -1
- package/dist/components/JsonSchemaForm/templates/ArrayFieldDescriptionTemplate.js.map +1 -1
- package/dist/components/JsonSchemaForm/templates/ArrayFieldItemTemplate.js.map +1 -1
- package/dist/components/JsonSchemaForm/templates/BaseInputTemplate.js.map +1 -1
- package/dist/components/JsonSchemaForm/templates/FieldTemplate.js.map +1 -1
- package/dist/components/JsonSchemaForm/templates/RJSFInputLabel.js.map +1 -1
- package/dist/components/Markdown/MarkdownGithub.js.map +1 -1
- package/dist/components/Markdown/MarkdownSynapse.js.map +1 -1
- package/dist/components/Markdown/MarkdownUtils.js.map +1 -1
- package/dist/components/Markdown/SynapseWikiContext.js.map +1 -1
- package/dist/components/Markdown/UserMentionModal.js.map +1 -1
- package/dist/components/Markdown/widget/MarkdownProvenanceGraph.js.map +1 -1
- package/dist/components/MissingQueryResultsWarning/MissingQueryResultsWarning.js.map +1 -1
- package/dist/components/ModalDownload/ModalDownload.js.map +1 -1
- package/dist/components/OAuthClientAclEditor/OAuthClientAclEditor.d.ts.map +1 -1
- package/dist/components/OAuthClientAclEditor/OAuthClientAclEditor.js +45 -39
- package/dist/components/OAuthClientAclEditor/OAuthClientAclEditor.js.map +1 -1
- package/dist/components/OAuthClientManagement/OAuthManagement.js.map +1 -1
- package/dist/components/PageProgress/PageProgress.js.map +1 -1
- package/dist/components/Plot/DotPlot.js.map +1 -1
- package/dist/components/Plot/Plot.js.map +1 -1
- package/dist/components/Plot/SynapsePlot.js.map +1 -1
- package/dist/components/Plot/ThemesPlot.js.map +1 -1
- package/dist/components/Plot/UpsetPlot.js.map +1 -1
- package/dist/components/PortalAclEditor/PortalAclEditor.d.ts.map +1 -1
- package/dist/components/PortalAclEditor/PortalAclEditor.js +43 -41
- package/dist/components/PortalAclEditor/PortalAclEditor.js.map +1 -1
- package/dist/components/PortalFeaturedPartners/PortalFeaturedPartners.js.map +1 -1
- package/dist/components/PortalList/CreatePortalModal.js.map +1 -1
- package/dist/components/ProgrammaticInstructionsModal/ProgrammaticInstructionsModal.js.map +1 -1
- package/dist/components/ProgrammaticTableDownload/ProgrammaticTableDownload.js.map +1 -1
- package/dist/components/Programs/Programs.Mobile.js.map +1 -1
- package/dist/components/Programs/Programs.js.map +1 -1
- package/dist/components/ProvenanceGraph/ProvenanceExternalIcon.js.map +1 -1
- package/dist/components/ProvenanceGraph/ProvenanceGraph.js.map +1 -1
- package/dist/components/ProvenanceGraph/ProvenanceGraphUtils.js.map +1 -1
- package/dist/components/ProvenanceGraph/ProvenanceUtils.js.map +1 -1
- package/dist/components/QueryCount/QueryCount.js.map +1 -1
- package/dist/components/QueryCountButton/QueryCountButton.js.map +1 -1
- package/dist/components/QueryVisualizationWrapper/QueryVisualizationWrapper.js.map +1 -1
- package/dist/components/QueryWrapper/QueryWrapper.js.map +1 -1
- package/dist/components/QueryWrapper/TableQueryUseQueryOptions.js.map +1 -1
- package/dist/components/QueryWrapper/TableRowSelectionState.js.map +1 -1
- package/dist/components/QueryWrapper/generateEncodedPathAndQueryForSelectedFacetURL.js.map +1 -1
- package/dist/components/QueryWrapper/useGetQueryMetadata.js.map +1 -1
- package/dist/components/QueryWrapperErrorBoundary.js.map +1 -1
- package/dist/components/QueryWrapperPlotNav/QueryWrapperPlotNav.js.map +1 -1
- package/dist/components/QueryWrapperPlotNav/UseRowSet.js.map +1 -1
- package/dist/components/RecentPublicationsGrid/RecentPublicationsGrid.js.map +1 -1
- package/dist/components/ReleaseCard/ReleaseCardUtils.js.map +1 -1
- package/dist/components/ResizableContainer/hooks/useResizable.js.map +1 -1
- package/dist/components/Resources/Resources.Mobile.js.map +1 -1
- package/dist/components/Resources/Resources.js.map +1 -1
- package/dist/components/RowDataTable/RowDataTableWithQuery.js.map +1 -1
- package/dist/components/SageResourcesPopover/SageResourcesPopover.js.map +1 -1
- package/dist/components/SchemaDrivenAnnotationEditor/AnnotationEditorUtils.js.map +1 -1
- package/dist/components/SetAccessRequirementCommonFields/SetAccessRequirementCommonFields.js.map +1 -1
- package/dist/components/SetManagedAccessRequirementFields/SetManagedAccessRequirementFields.js.map +1 -1
- package/dist/components/SmartLink/SmartButton.js.map +1 -1
- package/dist/components/SmartLink/SmartLink.js.map +1 -1
- package/dist/components/SourceAppImage.js.map +1 -1
- package/dist/components/StandaloneQueryWrapper/StandaloneQueryWrapper.js.map +1 -1
- package/dist/components/StatisticsPlot.js.map +1 -1
- package/dist/components/StorybookComponentWrapper.js.map +1 -1
- package/dist/components/SubsectionRowRenderer/SubsectionRowRenderer.js.map +1 -1
- package/dist/components/SustainabilityScorecard/SustainabilityScorecard.js.map +1 -1
- package/dist/components/SynapseChat/GridAgentChat.js.map +1 -1
- package/dist/components/SynapseChat/SynapseChatInteraction.js.map +1 -1
- package/dist/components/SynapseChat/SynapseChatMessage.js.map +1 -1
- package/dist/components/SynapseChat/extractMessageFromTraceEvent.js.map +1 -1
- package/dist/components/SynapseForm/StepsSideNav.js.map +1 -1
- package/dist/components/SynapseForm/SummaryTable.js.map +1 -1
- package/dist/components/SynapseForm/SynapseForm.js +4 -2
- package/dist/components/SynapseForm/SynapseForm.js.map +1 -1
- package/dist/components/SynapseForm/SynapseFormWrapper.js.map +1 -1
- package/dist/components/SynapseHomepageV2/SynapseByTheNumbersItem.js.map +1 -1
- package/dist/components/SynapseHomepageV2/SynapseFeatureItem.js.map +1 -1
- package/dist/components/SynapseHomepageV2/SynapseHomepageChatSearch.js.map +1 -1
- package/dist/components/SynapseHomepageV2/SynapseHomepageSearch.js.map +1 -1
- package/dist/components/SynapseHomepageV2/SynapseInActionItem.js.map +1 -1
- package/dist/components/SynapseHomepageV2/SynapsePlans.js.map +1 -1
- package/dist/components/SynapseHomepageV2/SynapseTrendingProjects.js.map +1 -1
- package/dist/components/SynapseNavDrawer/SynapseNavDrawer.d.ts +8 -7
- package/dist/components/SynapseNavDrawer/SynapseNavDrawer.d.ts.map +1 -1
- package/dist/components/SynapseNavDrawer/SynapseNavDrawer.js +173 -164
- package/dist/components/SynapseNavDrawer/SynapseNavDrawer.js.map +1 -1
- package/dist/components/SynapsePortalBanners/SynapsePortalBanners.js.map +1 -1
- package/dist/components/SynapseSearchPageResults/SearchFacetPanel/SearchFacetPanel.js.map +1 -1
- package/dist/components/SynapseSearchPageResults/SearchFacetPanel/SearchFacetPanelUtils.js.map +1 -1
- package/dist/components/SynapseSearchPageResults/SynapseSearchPageResults.js.map +1 -1
- package/dist/components/SynapseTable/EntityIDColumnCopyIcon.js.map +1 -1
- package/dist/components/SynapseTable/NoContentPlaceholderType.js.map +1 -1
- package/dist/components/SynapseTable/RowSelection/RowSelectionControls.js.map +1 -1
- package/dist/components/SynapseTable/SynapseTableCell/SynapseTableCell.js.map +1 -1
- package/dist/components/SynapseTable/SynapseTableRenderers.js.map +1 -1
- package/dist/components/SynapseTable/datasets/DatasetItemsEditor.js.map +1 -1
- package/dist/components/SynapseTable/table-top/ColumnSelection.js.map +1 -1
- package/dist/components/SynapseTable/table-top/DownloadOptions.js.map +1 -1
- package/dist/components/SynapseTable/usePrefetchTableData.js.map +1 -1
- package/dist/components/TableColumnSchemaEditor/ColumnModelForm.js.map +1 -1
- package/dist/components/TableColumnSchemaEditor/ColumnModelFormFields/DefaultValueField.js.map +1 -1
- package/dist/components/TableColumnSchemaEditor/ImportTableColumnsButton.js.map +1 -1
- package/dist/components/TableColumnSchemaEditor/TableColumnSchemaEditorUtils.d.ts +1 -1
- package/dist/components/TableColumnSchemaEditor/TableColumnSchemaEditorUtils.d.ts.map +1 -1
- package/dist/components/TableColumnSchemaEditor/TableColumnSchemaEditorUtils.js.map +1 -1
- package/dist/components/TableColumnSchemaEditor/TableColumnSchemaForm.js.map +1 -1
- package/dist/components/TableColumnSchemaEditor/TableColumnSchemaFormReducer.js.map +1 -1
- package/dist/components/TableColumnSchemaEditor/Validators/ColumnModelValidator.js.map +1 -1
- package/dist/components/TableColumnSchemaEditor/Validators/DatetimeSchema.js.map +1 -1
- package/dist/components/TanStackTable/ColumnHeader.d.ts +1 -0
- package/dist/components/TanStackTable/ColumnHeader.d.ts.map +1 -1
- package/dist/components/TanStackTable/ColumnHeader.js +8 -8
- package/dist/components/TanStackTable/ColumnHeader.js.map +1 -1
- package/dist/components/TanStackTable/ColumnHeaderEnumFilter.js.map +1 -1
- package/dist/components/TanStackTable/TableBody.js.map +1 -1
- package/dist/components/TeamSubjectsSelector/TeamSubjectsSelector.js.map +1 -1
- package/dist/components/TextField/TextField.js.map +1 -1
- package/dist/components/TimelinePlot/TimelinePhase.js.map +1 -1
- package/dist/components/TimelinePlot/TimelinePlot.js.map +1 -1
- package/dist/components/TimelinePlot/TimelinePlotSpeciesSelector.js.map +1 -1
- package/dist/components/UserCard/Avatar.js.map +1 -1
- package/dist/components/UserCardList/UserCardList.js.map +1 -1
- package/dist/components/UserCardList/UserCardListGroups/UserCardListGroups.Mobile.js.map +1 -1
- package/dist/components/UserCardList/UserCardListRotate.js.map +1 -1
- package/dist/components/UserOrTeamBadge/useUserOrTeam.js.map +1 -1
- package/dist/components/UserProfileLinks/UserProjects.js.map +1 -1
- package/dist/components/UserSearchBox/UserSearchBox.js.map +1 -1
- package/dist/components/Webhook/WebhookDashboard.js.map +1 -1
- package/dist/components/WikiMarkdownEditor/WikiMarkdownEditor.js.map +1 -1
- package/dist/components/WikiMarkdownEditorButton/WikiMarkdownEditorButton.js.map +1 -1
- package/dist/components/dataaccess/AccessApprovalsTable.js.map +1 -1
- package/dist/components/dataaccess/AccessRequestSubmissionTable.js.map +1 -1
- package/dist/components/dataaccess/SubmissionPage/SubmissionPage.d.ts.map +1 -1
- package/dist/components/dataaccess/SubmissionPage/SubmissionPage.js +157 -148
- package/dist/components/dataaccess/SubmissionPage/SubmissionPage.js.map +1 -1
- package/dist/components/dataaccess/UseAccessRequirementTable.js.map +1 -1
- package/dist/components/dataaccess/UserAccessRequestHistory/UserAccessRequestHistoryTable.js.map +1 -1
- package/dist/components/doi/CreateOrUpdateDoiModal.d.ts.map +1 -1
- package/dist/components/doi/CreateOrUpdateDoiModal.js +20 -19
- package/dist/components/doi/CreateOrUpdateDoiModal.js.map +1 -1
- package/dist/components/entity/page/CreatedByModifiedBy.js.map +1 -1
- package/dist/components/entity/page/action_menu/EntityActionMenu.js.map +1 -1
- package/dist/components/entity/page/title_bar/useDataCiteUsage.js.map +1 -1
- package/dist/components/entity/page/title_bar/useGetMentions.js.map +1 -1
- package/dist/components/error/ErrorPage.js.map +1 -1
- package/dist/components/favorites/FavoritesPage.js.map +1 -1
- package/dist/components/file/upload/BasicFileHandleUpload.js.map +1 -1
- package/dist/components/layout/SWCHeader.d.ts +9 -0
- package/dist/components/layout/SWCHeader.d.ts.map +1 -0
- package/dist/components/layout/SWCHeader.js +19 -0
- package/dist/components/layout/SWCHeader.js.map +1 -0
- package/dist/components/layout/SWCPageLayout.d.ts +9 -0
- package/dist/components/layout/SWCPageLayout.d.ts.map +1 -0
- package/dist/components/layout/SWCPageLayout.js +14 -0
- package/dist/components/layout/SWCPageLayout.js.map +1 -0
- package/dist/components/menu/ComplexMenu.js.map +1 -1
- package/dist/components/row_renderers/utils/ChipContainer.js.map +1 -1
- package/dist/components/styled/StyledPopover.js.map +1 -1
- package/dist/components/table/CsvPreview/CsvPreview.js +2 -1
- package/dist/components/table/CsvPreview/CsvPreview.js.map +1 -1
- package/dist/components/table/CsvPreview/CsvPreviewDialog.js.map +1 -1
- package/dist/components/trash/TrashCanList.js.map +1 -1
- package/dist/components/widgets/FileHandleLink.js.map +1 -1
- package/dist/components/widgets/RangeSlider/RangeSlider.js.map +1 -1
- package/dist/components/widgets/SynapseVideo.js.map +1 -1
- package/dist/components/widgets/facet-nav/FacetNavPanel.js.map +1 -1
- package/dist/components/widgets/facet-nav/PlotsContainer.js.map +1 -1
- package/dist/components/widgets/facet-nav/SelectionCriteriaPills.js.map +1 -1
- package/dist/components/widgets/facet-nav/useFacetPlots.js.map +1 -1
- package/dist/components/widgets/query-filter/CombinedRangeFacetFilter.js.map +1 -1
- package/dist/components/widgets/query-filter/EnumFacetFilter/EnumFacetFilter.js.map +1 -1
- package/dist/components/widgets/query-filter/FacetFilterControls.js.map +1 -1
- package/dist/components/widgets/query-filter/RangeFacetFilter.js.map +1 -1
- package/dist/components/widgets/query-filter/RangeFacetFilterUI.js.map +1 -1
- package/dist/features/curator/GridPage/components/GridPageTitle.d.ts.map +1 -1
- package/dist/features/curator/GridPage/components/GridPageTitle.js +23 -30
- package/dist/features/curator/GridPage/components/GridPageTitle.js.map +1 -1
- package/dist/features/curator/dashboard/CuratorDashboard.d.ts +2 -0
- package/dist/features/curator/dashboard/CuratorDashboard.d.ts.map +1 -0
- package/dist/features/curator/dashboard/CuratorDashboard.js +45 -0
- package/dist/features/curator/dashboard/CuratorDashboard.js.map +1 -0
- package/dist/features/curator/dashboard/components/CurationTaskCard.css +1 -0
- package/dist/features/curator/dashboard/components/CurationTaskCard.d.ts +9 -0
- package/dist/features/curator/dashboard/components/CurationTaskCard.d.ts.map +1 -0
- package/dist/features/curator/dashboard/components/CurationTaskCard.js +106 -0
- package/dist/features/curator/dashboard/components/CurationTaskCard.js.map +1 -0
- package/dist/features/curator/dashboard/components/CurationTaskCard.module.js +12 -0
- package/dist/features/curator/dashboard/components/CurationTaskCard.module.js.map +1 -0
- package/dist/features/curator/dashboard/components/CurationTaskCard.module.scss +52 -0
- package/dist/features/curator/dashboard/components/NextStepButton.css +1 -0
- package/dist/features/curator/dashboard/components/NextStepButton.d.ts +14 -0
- package/dist/features/curator/dashboard/components/NextStepButton.d.ts.map +1 -0
- package/dist/features/curator/dashboard/components/NextStepButton.js +35 -0
- package/dist/features/curator/dashboard/components/NextStepButton.js.map +1 -0
- package/dist/features/curator/dashboard/components/NextStepButton.module.js +11 -0
- package/dist/features/curator/dashboard/components/NextStepButton.module.js.map +1 -0
- package/dist/features/curator/dashboard/components/NextStepButton.module.scss +57 -0
- package/dist/features/curator/dashboard/components/UserOrTeamChip.css +1 -1
- package/dist/features/curator/dashboard/components/UserOrTeamChip.module.js +1 -1
- package/dist/features/curator/dashboard/components/UserOrTeamChip.module.js.map +1 -1
- package/dist/features/curator/dashboard/components/UserOrTeamChip.module.scss +5 -5
- package/dist/features/curator/dashboard/components/shared.css +1 -0
- package/dist/features/curator/dashboard/components/shared.module.js +5 -0
- package/dist/features/curator/dashboard/components/shared.module.js.map +1 -0
- package/dist/features/curator/dashboard/components/shared.module.scss +8 -0
- package/dist/features/entity/metadata-task/components/MetadataTaskTableActionCell.d.ts +0 -2
- package/dist/features/entity/metadata-task/components/MetadataTaskTableActionCell.d.ts.map +1 -1
- package/dist/features/entity/metadata-task/components/MetadataTaskTableActionCell.js +16 -34
- package/dist/features/entity/metadata-task/components/MetadataTaskTableActionCell.js.map +1 -1
- package/dist/features/entity/metadata-task/components/MetadataTasksTableAssigneeCell.d.ts.map +1 -1
- package/dist/features/entity/metadata-task/components/MetadataTasksTableAssigneeCell.js +1 -1
- package/dist/features/entity/metadata-task/components/MetadataTasksTableAssigneeCell.js.map +1 -1
- package/dist/features/entity/metadata-task/hooks/useGetOrCreateGridSessionForSource.js.map +1 -1
- package/dist/features/entity/metadata-task/hooks/useGridSessionForCurationTask.js.map +1 -1
- package/dist/features/entity/metadata-task/hooks/useGridSessionForCurationTask_legacy.js.map +1 -1
- package/dist/features/entity/metadata-task/hooks/useMetadataTaskTable.js +1 -1
- package/dist/features/entity/metadata-task/hooks/useMetadataTaskTable.js.map +1 -1
- package/dist/features/entity/metadata-task/hooks/useOpenCuratorButton.d.ts +10 -0
- package/dist/features/entity/metadata-task/hooks/useOpenCuratorButton.d.ts.map +1 -0
- package/dist/features/entity/metadata-task/hooks/useOpenCuratorButton.js +37 -0
- package/dist/features/entity/metadata-task/hooks/useOpenCuratorButton.js.map +1 -0
- package/dist/features/entity/metadata-task/utils/constants.d.ts +5 -0
- package/dist/features/entity/metadata-task/utils/constants.d.ts.map +1 -0
- package/dist/features/entity/metadata-task/utils/constants.js +6 -0
- package/dist/features/entity/metadata-task/utils/constants.js.map +1 -0
- package/dist/mocks/challenge/mockChallenge.js.map +1 -1
- package/dist/mocks/entity/mockDataset.js.map +1 -1
- package/dist/mocks/entity/mockDatasetCollection.js.map +1 -1
- package/dist/mocks/entity/mockFileEntity.js.map +1 -1
- package/dist/mocks/entity/mockFileView.js.map +1 -1
- package/dist/mocks/entity/mockGeneratedEntityData.js.map +1 -1
- package/dist/mocks/entity/mockProject.js.map +1 -1
- package/dist/mocks/entity/mockProjectView.js.map +1 -1
- package/dist/mocks/entity/mockRootEntity.js.map +1 -1
- package/dist/mocks/entity/mockTableEntity.js.map +1 -1
- package/dist/mocks/mockWiki.js.map +1 -1
- package/dist/mocks/msw/handlers/asyncJobHandlers.js.map +1 -1
- package/dist/mocks/msw/handlers/challengeHandlers.js.map +1 -1
- package/dist/mocks/msw/handlers/changePasswordHandlers.js.map +1 -1
- package/dist/mocks/msw/handlers/discussionHandlers.js.map +1 -1
- package/dist/mocks/msw/handlers/entityHandlers.js.map +1 -1
- package/dist/mocks/msw/handlers/fileHandlers.js.map +1 -1
- package/dist/mocks/msw/handlers/gridHandlers.js.map +1 -1
- package/dist/mocks/msw/handlers/personalAccessTokenHandlers.js.map +1 -1
- package/dist/mocks/msw/handlers/subscriptionHandlers.js.map +1 -1
- package/dist/mocks/msw/handlers/teamHandlers.js.map +1 -1
- package/dist/mocks/msw/handlers/userProfileHandlers.js.map +1 -1
- package/dist/mocks/msw/handlers/wikiHandlers.js.map +1 -1
- package/dist/mocks/provenance/mockActivity.js.map +1 -1
- package/dist/mocks/query/mockReleaseCardsTableQueryResultBundle.js.map +1 -1
- package/dist/ror-client/index.js.map +1 -1
- package/dist/style/components/_cards.scss +4 -0
- package/dist/style/components/_data-grid-extra.css +1 -1
- package/dist/style/components/_data-grid-extra.scss +2 -0
- package/dist/style/main.css +1 -1
- package/dist/synapse-client/HttpClient.js.map +1 -1
- package/dist/synapse-client/SynapseClient.js.map +1 -1
- package/dist/synapse-queries/KeyFactory.d.ts +1 -0
- package/dist/synapse-queries/KeyFactory.d.ts.map +1 -1
- package/dist/synapse-queries/KeyFactory.js +3 -0
- package/dist/synapse-queries/KeyFactory.js.map +1 -1
- package/dist/synapse-queries/QueryMatching.test-utils.js.map +1 -1
- package/dist/synapse-queries/auth/useTwoFactorEnrollment.js.map +1 -1
- package/dist/synapse-queries/curation/task/useCurationTask.d.ts +1 -1
- package/dist/synapse-queries/curation/task/useCurationTask.d.ts.map +1 -1
- package/dist/synapse-queries/curation/task/useCurationTask.js +1 -1
- package/dist/synapse-queries/curation/task/useCurationTask.js.map +1 -1
- package/dist/synapse-queries/dataaccess/useRestrictionInformation.js.map +1 -1
- package/dist/synapse-queries/doi/useDOI.js.map +1 -1
- package/dist/synapse-queries/download/useDownloadList.js.map +1 -1
- package/dist/synapse-queries/entity/useEntity.js.map +1 -1
- package/dist/synapse-queries/entity/useEntityBundle.js.map +1 -1
- package/dist/synapse-queries/entity/useExportTableQueryToAnalysisPlatform.js.map +1 -1
- package/dist/synapse-queries/entity/useExportToTerra.js.map +1 -1
- package/dist/synapse-queries/entity/useGetQueryResultBundle.js.map +1 -1
- package/dist/synapse-queries/entity/useSchema.js.map +1 -1
- package/dist/synapse-queries/file/UploadToS3.js.map +1 -1
- package/dist/synapse-queries/file/useDirectUploadToS3.js.map +1 -1
- package/dist/synapse-queries/file/useFiles.js.map +1 -1
- package/dist/synapse-queries/forum/useReply.js.map +1 -1
- package/dist/synapse-queries/forum/useThread.d.ts +1 -0
- package/dist/synapse-queries/forum/useThread.d.ts.map +1 -1
- package/dist/synapse-queries/forum/useThread.js +19 -12
- package/dist/synapse-queries/forum/useThread.js.map +1 -1
- package/dist/synapse-queries/grid/useEstablishWebsocketConnection.d.ts +2 -0
- package/dist/synapse-queries/grid/useEstablishWebsocketConnection.d.ts.map +1 -1
- package/dist/synapse-queries/grid/useEstablishWebsocketConnection.js.map +1 -1
- package/dist/synapse-queries/grid/useExportGrid.js.map +1 -1
- package/dist/synapse-queries/grid/useGridSession.js.map +1 -1
- package/dist/synapse-queries/grid/useImportCsvIntoGrid.js.map +1 -1
- package/dist/synapse-queries/subscription/useSubscription.js.map +1 -1
- package/dist/synapse-queries/table/useGetCsvPreview.js.map +1 -1
- package/dist/synapse-queries/table/useTableUpdateTransaction.js.map +1 -1
- package/dist/synapse-queries/team/useTeamMembers.js.map +1 -1
- package/dist/synapse-queries/user/useGetUserChallenges.js.map +1 -1
- package/dist/synapse-queries/user/useUserBundle.js.map +1 -1
- package/dist/synapse-queries/user/useUserGroupHeader.js.map +1 -1
- package/dist/testutils/ReactQueryMockUtils.js.map +1 -1
- package/dist/theme/ThemeProvider.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/utils/APIConstants.d.ts +1 -0
- package/dist/utils/APIConstants.d.ts.map +1 -1
- package/dist/utils/APIConstants.js +2 -2
- package/dist/utils/APIConstants.js.map +1 -1
- package/dist/utils/AppUtils/session/ApplicationSessionManager.d.ts.map +1 -1
- package/dist/utils/AppUtils/session/ApplicationSessionManager.js +7 -4
- package/dist/utils/AppUtils/session/ApplicationSessionManager.js.map +1 -1
- package/dist/utils/AppUtils/session/SynapseSessionManager.js.map +1 -1
- package/dist/utils/AppUtils/session/useSessionManager.js.map +1 -1
- package/dist/utils/PermissionLevelToAccessType.js.map +1 -1
- package/dist/utils/challenge/evaluation/EvaluationUtils.js.map +1 -1
- package/dist/utils/context/SynapseContext.js.map +1 -1
- package/dist/utils/functions/AccessControlListUtils.d.ts +4 -0
- package/dist/utils/functions/AccessControlListUtils.d.ts.map +1 -1
- package/dist/utils/functions/AccessControlListUtils.js +12 -1
- package/dist/utils/functions/AccessControlListUtils.js.map +1 -1
- package/dist/utils/functions/EntityTypeUtils.d.ts.map +1 -1
- package/dist/utils/functions/EntityTypeUtils.js +15 -4
- package/dist/utils/functions/EntityTypeUtils.js.map +1 -1
- package/dist/utils/functions/GridApiUtils.js.map +1 -1
- package/dist/utils/functions/QueryFilterUtils.js.map +1 -1
- package/dist/utils/functions/RealmUtils.d.ts +4 -0
- package/dist/utils/functions/RealmUtils.d.ts.map +1 -1
- package/dist/utils/functions/RealmUtils.js +9 -3
- package/dist/utils/functions/RealmUtils.js.map +1 -1
- package/dist/utils/functions/SanitizeHtmlUtils.js.map +1 -1
- package/dist/utils/functions/SanitizeHtmlUtils.test-utils.js.map +1 -1
- package/dist/utils/functions/SqlFunctions.js.map +1 -1
- package/dist/utils/functions/StringUtils.js.map +1 -1
- package/dist/utils/functions/deepLinkingUtils.js.map +1 -1
- package/dist/utils/functions/getDataFromFromStorage.js.map +1 -1
- package/dist/utils/functions/getEndpoint.js.map +1 -1
- package/dist/utils/functions/getUserData.js.map +1 -1
- package/dist/utils/functions/queryUtils.js.map +1 -1
- package/dist/utils/functions/testDownloadSpeed.js.map +1 -1
- package/dist/utils/hooks/useConfirmItems.js.map +1 -1
- package/dist/utils/hooks/useCookiePreferences.js.map +1 -1
- package/dist/utils/hooks/useCreateShortUrl.js.map +1 -1
- package/dist/utils/hooks/useDetectSSOCode.js.map +1 -1
- package/dist/utils/hooks/useDirectDownloadHandler.js.map +1 -1
- package/dist/utils/hooks/useGetGoalData.js.map +1 -1
- package/dist/utils/hooks/useGetInfoFromIds.js.map +1 -1
- package/dist/utils/hooks/useImageUrlUtils.js.map +1 -1
- package/dist/utils/hooks/useImmutableTableQuery/useImmutableTableQuery.js.map +1 -1
- package/dist/utils/hooks/useImmutableTableQuery/useTableQueryReducer.js.map +1 -1
- package/dist/utils/hooks/useIsBot.js.map +1 -1
- package/dist/utils/hooks/useListState.js.map +1 -1
- package/dist/utils/hooks/useLogin.d.ts.map +1 -1
- package/dist/utils/hooks/useLogin.js +53 -52
- package/dist/utils/hooks/useLogin.js.map +1 -1
- package/dist/utils/hooks/useMutuallyExclusiveState.js.map +1 -1
- package/dist/utils/hooks/useOverlay.js.map +1 -1
- package/dist/utils/hooks/usePreFetchResource.js.map +1 -1
- package/dist/utils/hooks/useQuerySearchParam.js.map +1 -1
- package/dist/utils/hooks/useScrollFadeTransition.js.map +1 -1
- package/dist/utils/hooks/useSet.js.map +1 -1
- package/dist/utils/hooks/useSourceAppConfigs.js.map +1 -1
- package/dist/utils/hooks/useTableImageUrl.js.map +1 -1
- package/dist/utils/hooks/useUploadFileEntity/useCreatePathsAndGetParentId.js.map +1 -1
- package/dist/utils/hooks/useUploadFileEntity/useLinkFileEntityToURL.js.map +1 -1
- package/dist/utils/hooks/useUploadFileEntity/usePrepareFileEntityUpload.js.map +1 -1
- package/dist/utils/hooks/useUploadFileEntity/useTrackFileUploads.js.map +1 -1
- package/dist/utils/hooks/useUploadFileEntity/useUploadFileEntities.js.map +1 -1
- package/dist/utils/hooks/useUploadFileEntity/useUploadFiles.js.map +1 -1
- package/dist/utils/hooks/useUploadFileEntity/willUploadsExceedStorageLimit.js.map +1 -1
- package/dist/utils/html/TargetEnum.js.map +1 -1
- package/dist/utils/jsonschema/SchemaAnnotationUtils.js.map +1 -1
- package/package.json +5 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MissingQueryResultsWarning.js","names":[],"sources":["../../../src/components/MissingQueryResultsWarning/MissingQueryResultsWarning.tsx"],"sourcesContent":["import { useGetQueryResultBundleWithAsyncStatus } from '@/synapse-queries'\nimport { SynapseConstants } from '@/utils'\nimport { isEntityRefCollectionView } from '@/utils/functions/EntityTypeUtils'\nimport { WarningSharp } from '@mui/icons-material'\nimport { Typography } from '@mui/material'\nimport { QueryBundleRequest, Table } from '@sage-bionetworks/synapse-types'\nimport { HelpPopover } from '../HelpPopover/HelpPopover'\n\nconst DATASETS_CURRENT_VERSION_HELP =\n 'Files may be unavailable because you do not have permission to see them, they have been deleted, or the Dataset has been misconfigured.'\n\n// Help text for snapshot does not indicate that files were deleted, because the deleted file would have been captured in the snapshot\nconst DATASETS_SNAPSHOT_HELP =\n 'Files may be unavailable because you do not have permission to see them or the Dataset was misconfigured.'\n\nexport type MissingQueryResultsWarningProps = {\n entity: Table\n versionNumber?: number\n}\n\n/**\n * If possible, this component will render a warning message if results may be missing from the query due to user permissions or\n * entities being deleted. If not possible, it will render an empty fragment.\n */\nfunction MissingQueryResultsWarning({\n entity,\n}: MissingQueryResultsWarningProps) {\n // Currently, Datasets and Dataset collections are the only table type for which we can reliably get this info.\n // Other cases will need a new service, tracked by PLFM-7046\n const isMissingResultsCalculable = entity && isEntityRefCollectionView(entity)\n\n const request: QueryBundleRequest = {\n concreteType: 'org.sagebionetworks.repo.model.table.QueryBundleRequest',\n query: {\n sql: `SELECT * FROM ${entity.id!}${\n !entity.isLatestVersion && entity.versionNumber\n ? `.${entity.versionNumber}`\n : ''\n }`,\n },\n entityId: entity.id!,\n partMask: SynapseConstants.BUNDLE_MASK_QUERY_COUNT,\n }\n\n const { data: queryResult } = useGetQueryResultBundleWithAsyncStatus(\n request,\n {\n enabled: isMissingResultsCalculable,\n },\n )\n if (isMissingResultsCalculable && queryResult && entity) {\n const totalVisibleResults = queryResult.responseBody!.queryCount!\n const totalResults = entity.items?.length ?? 0\n\n if (totalVisibleResults >= totalResults) {\n // All the results are visible, so there is no need to show a warning.\n // SWC-6727 / PLFM-8326 - `totalVisibleResults` should never be greater than `totalResults`, but in case it is (e.g. stale cache),\n // don't show the warning.\n return <></>\n }\n\n const difference = totalResults - totalVisibleResults\n\n let helpMessage = ''\n\n if (entity.isLatestVersion) {\n helpMessage = DATASETS_CURRENT_VERSION_HELP\n } else {\n helpMessage = DATASETS_SNAPSHOT_HELP\n }\n\n return (\n <Typography\n component={'div'}\n className=\"SRC-centerContent\"\n style={{\n marginLeft: 10,\n }}\n variant=\"smallText1\"\n color=\"textSecondary\"\n >\n <WarningSharp\n className=\"SRC-color-warning\"\n style={{ fontSize: '16px' }}\n />\n {difference.toLocaleString() + ' Unavailable'}\n <HelpPopover\n className=\"SRC-margin-left-5\"\n markdownText={helpMessage}\n placement=\"right\"\n ></HelpPopover>\n </Typography>\n )\n } else {\n return <></>\n }\n}\n\nexport default MissingQueryResultsWarning\n"],"mappings":";;;;;;;;;;AAQA,IAAM,IACJ,2IAGI,IACJ;AAWF,SAAS,EAA2B,EAClC,aACkC;CAGlC,IAAM,IAA6B,KAAU,EAA0B,EAAO,EAexE,EAAE,MAAM,MAAgB,
|
|
1
|
+
{"version":3,"file":"MissingQueryResultsWarning.js","names":[],"sources":["../../../src/components/MissingQueryResultsWarning/MissingQueryResultsWarning.tsx"],"sourcesContent":["import { useGetQueryResultBundleWithAsyncStatus } from '@/synapse-queries'\nimport { SynapseConstants } from '@/utils'\nimport { isEntityRefCollectionView } from '@/utils/functions/EntityTypeUtils'\nimport { WarningSharp } from '@mui/icons-material'\nimport { Typography } from '@mui/material'\nimport { QueryBundleRequest, Table } from '@sage-bionetworks/synapse-types'\nimport { HelpPopover } from '../HelpPopover/HelpPopover'\n\nconst DATASETS_CURRENT_VERSION_HELP =\n 'Files may be unavailable because you do not have permission to see them, they have been deleted, or the Dataset has been misconfigured.'\n\n// Help text for snapshot does not indicate that files were deleted, because the deleted file would have been captured in the snapshot\nconst DATASETS_SNAPSHOT_HELP =\n 'Files may be unavailable because you do not have permission to see them or the Dataset was misconfigured.'\n\nexport type MissingQueryResultsWarningProps = {\n entity: Table\n versionNumber?: number\n}\n\n/**\n * If possible, this component will render a warning message if results may be missing from the query due to user permissions or\n * entities being deleted. If not possible, it will render an empty fragment.\n */\nfunction MissingQueryResultsWarning({\n entity,\n}: MissingQueryResultsWarningProps) {\n // Currently, Datasets and Dataset collections are the only table type for which we can reliably get this info.\n // Other cases will need a new service, tracked by PLFM-7046\n const isMissingResultsCalculable = entity && isEntityRefCollectionView(entity)\n\n const request: QueryBundleRequest = {\n concreteType: 'org.sagebionetworks.repo.model.table.QueryBundleRequest',\n query: {\n sql: `SELECT * FROM ${entity.id!}${\n !entity.isLatestVersion && entity.versionNumber\n ? `.${entity.versionNumber}`\n : ''\n }`,\n },\n entityId: entity.id!,\n partMask: SynapseConstants.BUNDLE_MASK_QUERY_COUNT,\n }\n\n const { data: queryResult } = useGetQueryResultBundleWithAsyncStatus(\n request,\n {\n enabled: isMissingResultsCalculable,\n },\n )\n if (isMissingResultsCalculable && queryResult && entity) {\n const totalVisibleResults = queryResult.responseBody!.queryCount!\n const totalResults = entity.items?.length ?? 0\n\n if (totalVisibleResults >= totalResults) {\n // All the results are visible, so there is no need to show a warning.\n // SWC-6727 / PLFM-8326 - `totalVisibleResults` should never be greater than `totalResults`, but in case it is (e.g. stale cache),\n // don't show the warning.\n return <></>\n }\n\n const difference = totalResults - totalVisibleResults\n\n let helpMessage = ''\n\n if (entity.isLatestVersion) {\n helpMessage = DATASETS_CURRENT_VERSION_HELP\n } else {\n helpMessage = DATASETS_SNAPSHOT_HELP\n }\n\n return (\n <Typography\n component={'div'}\n className=\"SRC-centerContent\"\n style={{\n marginLeft: 10,\n }}\n variant=\"smallText1\"\n color=\"textSecondary\"\n >\n <WarningSharp\n className=\"SRC-color-warning\"\n style={{ fontSize: '16px' }}\n />\n {difference.toLocaleString() + ' Unavailable'}\n <HelpPopover\n className=\"SRC-margin-left-5\"\n markdownText={helpMessage}\n placement=\"right\"\n ></HelpPopover>\n </Typography>\n )\n } else {\n return <></>\n }\n}\n\nexport default MissingQueryResultsWarning\n"],"mappings":";;;;;;;;;;AAQA,IAAM,IACJ,2IAGI,IACJ;AAWF,SAAS,EAA2B,EAClC,aACkC;CAGlC,IAAM,IAA6B,KAAU,EAA0B,EAAO,EAexE,EAAE,MAAM,MAAgB,EAC5B;EAbA,cAAc;EACd,OAAO,EACL,KAAK,iBAAiB,EAAO,KAC3B,CAAC,EAAO,mBAAmB,EAAO,gBAC9B,IAAI,EAAO,kBACX,MAEP;EACD,UAAU,EAAO;EACjB,UAAU;EAIV,EACA,EACE,SAAS,GACV,CACF;AACD,KAAI,KAA8B,KAAe,GAAQ;EACvD,IAAM,IAAsB,EAAY,aAAc,YAChD,IAAe,EAAO,OAAO,UAAU;AAE7C,MAAI,KAAuB,EAIzB,QAAO,kBAAA,GAAA,EAAK,CAAA;EAGd,IAAM,IAAa,IAAe,GAE9B,IAAc;AAQlB,SANA,AAGE,IAHE,EAAO,kBACK,IAEA,GAId,kBAAC,GAAD;GACE,WAAW;GACX,WAAU;GACV,OAAO,EACL,YAAY,IACb;GACD,SAAQ;GACR,OAAM;aAPR;IASE,kBAAC,GAAD;KACE,WAAU;KACV,OAAO,EAAE,UAAU,QAAQ;KAC3B,CAAA;IACD,EAAW,gBAAgB,GAAG;IAC/B,kBAAC,GAAD;KACE,WAAU;KACV,cAAc;KACd,WAAU;KACG,CAAA;IACJ;;OAGf,QAAO,kBAAA,GAAA,EAAK,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ModalDownload.js","names":[],"sources":["../../../src/components/ModalDownload/ModalDownload.tsx"],"sourcesContent":["import SynapseClient from '@/synapse-client'\nimport { SynapseContext } from '@/utils/context/SynapseContext'\nimport { parseEntityIdFromSqlStatement } from '@/utils/functions/SqlFunctions'\nimport { Button } from '@mui/material'\nimport Form, { IChangeEvent } from '@rjsf/core'\nimport validator from '@rjsf/validator-ajv8'\nimport {\n DownloadFromTableRequest,\n DownloadFromTableResult,\n QueryBundleRequest,\n SortItem,\n} from '@sage-bionetworks/synapse-types'\nimport { Component, ContextType, CSSProperties, Fragment } from 'react'\nimport { DialogBase } from '../DialogBase'\nimport SynapseFormCheckboxesWidget from '../SynapseForm/SynapseFormCheckboxesWidget'\nimport SynapseFormCheckboxWidget from '../SynapseForm/SynapseFormCheckboxWidget'\nimport SynapseFormRadioWidget from '../SynapseForm/SynapseFormRadioWidget'\nimport {\n csvOption,\n formSchemaArray,\n formSchemaUIArray,\n includeRowIdAndRowVersionOption,\n writeHeaderOption,\n} from './ModalDownload.FormSchema'\n\ntype ModalDownloadState = {\n isLoading: boolean\n step: number\n data?: DownloadFromTableResult\n formData: Record<string, unknown>\n}\n\nexport type ModalDownloadProps = {\n onClose: (...args: any[]) => void\n includeEntityEtag?: boolean\n queryBundleRequest?: QueryBundleRequest // either the query bundle request needs to be provided, or getLastQueryRequest\n getLastQueryRequest?: () => QueryBundleRequest\n offset?: number\n limit?: number\n sort?: SortItem[]\n}\n\nexport class ModalDownload extends Component<\n ModalDownloadProps,\n ModalDownloadState\n> {\n static contextType = SynapseContext\n declare context: NonNullable<ContextType<typeof SynapseContext>>\n\n constructor(props: ModalDownloadProps) {\n super(props)\n this.state = {\n isLoading: false,\n step: 0,\n formData: {\n 'File Type': csvOption,\n Contents: [writeHeaderOption, includeRowIdAndRowVersionOption],\n },\n }\n }\n\n handleSubmit = (event: IChangeEvent) => {\n if (this.state.step === 0) {\n this.handleDownloadSetup(event)\n } else {\n this.onDownload()\n }\n }\n\n handleDownloadSetup = (event: IChangeEvent) => {\n this.setState({\n isLoading: true,\n })\n const { formData } = event\n const fileType = formData['File Type']\n const contents = formData.Contents as string[]\n const { queryBundleRequest, getLastQueryRequest } = this.props\n const separator = fileType === csvOption ? ',' : '\\t'\n const writeHeader = contents.includes(writeHeaderOption)\n const includeRowIdAndRowVersion = contents.includes(\n includeRowIdAndRowVersionOption,\n )\n const queryRequest = queryBundleRequest ?? getLastQueryRequest!()\n const sql = queryRequest.query.sql\n const downloadFromTableRequest: DownloadFromTableRequest = {\n sql,\n entityId: parseEntityIdFromSqlStatement(sql),\n selectedFacets: queryRequest.query.selectedFacets,\n concreteType:\n 'org.sagebionetworks.repo.model.table.DownloadFromTableRequest',\n writeHeader,\n includeRowIdAndRowVersion,\n csvTableDescriptor: { separator },\n additionalFilters: queryRequest.query.additionalFilters,\n }\n SynapseClient.createTableCsvForDownload(\n downloadFromTableRequest,\n this.context.accessToken,\n )\n .then(data => {\n this.setState({\n isLoading: false,\n step: 1,\n data,\n })\n })\n .catch(err => {\n console.log('Error getDownloadFromTableRequest: ', err)\n })\n }\n\n onDownload = () => {\n const { data } = this.state\n // data will always be defined if calling this function\n SynapseClient.getFileHandleByIdURL(\n data!.resultsFileHandleId,\n this.context.accessToken,\n ).then(url => {\n window.location.href = url\n this.props.onClose()\n })\n }\n\n handleChange = (event: IChangeEvent) => {\n const { formData } = event\n this.setState({\n formData,\n })\n }\n\n render() {\n const spinnerStyle: CSSProperties = {\n height: 50,\n width: 50,\n backgroundSize: 50,\n }\n return (\n <DialogBase\n open={true}\n onCancel={this.props.onClose}\n title=\"Download query results\"\n content={\n <>\n <Form\n validator={validator}\n id=\"modal-download-form\"\n schema={formSchemaArray[this.state.step]}\n uiSchema={formSchemaUIArray[this.state.step]}\n onChange={this.handleChange}\n formData={this.state.formData}\n onSubmit={this.handleSubmit}\n widgets={{\n CheckboxWidget: SynapseFormCheckboxWidget,\n CheckboxesWidget: SynapseFormCheckboxesWidget,\n RadioWidget: SynapseFormRadioWidget,\n }}\n >\n {this.state.isLoading && (\n <div className=\"SRC-centerAndJustifyContent\">\n <div className=\"SRC-center-text\">\n <p> Creating the File </p>\n <div style={spinnerStyle} className=\"spinner\" />\n <p> Loading... </p>\n </div>\n </div>\n )}\n <Fragment />\n </Form>\n </>\n }\n actions={\n <>\n <Button\n variant=\"outlined\"\n color=\"primary\"\n onClick={this.props.onClose}\n >\n Cancel\n </Button>\n <Button\n form=\"modal-download-form\"\n type=\"submit\"\n variant=\"contained\"\n color=\"primary\"\n >\n {this.state.step === 0 ? 'Next' : 'Download'}\n </Button>\n </>\n }\n />\n )\n }\n}\n\nexport default ModalDownload\n"],"mappings":";;;;;;;;;;;;;;AA0CA,IAAa,IAAb,cAAmC,EAGjC;CACA,OAAO,cAAc;CAGrB,YAAY,GAA2B;AAErC,EADA,MAAM,EAAM,EACZ,KAAK,QAAQ;GACX,WAAW;GACX,MAAM;GACN,UAAU;IACR,aAAa;IACb,UAAU,CAAC,GAAmB,EAAgC;IAC/D;GACF;;CAGH,gBAAgB,MAAwB;AACtC,EAAI,KAAK,MAAM,SAAS,IACtB,KAAK,oBAAoB,EAAM,GAE/B,KAAK,YAAY;;CAIrB,uBAAuB,MAAwB;AAC7C,OAAK,SAAS,EACZ,WAAW,IACZ,CAAC;EACF,IAAM,EAAE,gBAAa,GACf,IAAW,EAAS,cACpB,IAAW,EAAS,UACpB,EAAE,uBAAoB,2BAAwB,KAAK,OACnD,IAAY,MAAA,iCAAyB,MAAM,KAC3C,IAAc,EAAS,SAAS,EAAkB,EAClD,IAA4B,EAAS,SACzC,EACD,EACK,IAAe,KAAsB,GAAsB,EAC3D,IAAM,EAAa,MAAM,KACzB,IAAqD;GACzD;GACA,UAAU,EAA8B,EAAI;GAC5C,gBAAgB,EAAa,MAAM;GACnC,cACE;GACF;GACA;GACA,oBAAoB,EAAE,cAAW;GACjC,mBAAmB,EAAa,MAAM;GACvC;AACD,IAAc,0BACZ,GACA,KAAK,QAAQ,YACd,CACE,MAAK,MAAQ;AACZ,QAAK,SAAS;IACZ,WAAW;IACX,MAAM;IACN;IACD,CAAC;IACF,CACD,OAAM,MAAO;AACZ,WAAQ,IAAI,uCAAuC,EAAI;IACvD;;CAGN,mBAAmB;EACjB,IAAM,EAAE,YAAS,KAAK;AAEtB,IAAc,qBACZ,EAAM,qBACN,KAAK,QAAQ,YACd,CAAC,MAAK,MAAO;AAEZ,GADA,OAAO,SAAS,OAAO,GACvB,KAAK,MAAM,SAAS;IACpB;;CAGJ,gBAAgB,MAAwB;EACtC,IAAM,EAAE,gBAAa;AACrB,OAAK,SAAS,EACZ,aACD,CAAC;;CAGJ,SAAS;AAMP,SACE,kBAAC,GAAD;GACE,MAAM;GACN,UAAU,KAAK,MAAM;GACrB,OAAM;GACN,SACE,kBAAA,GAAA,EAAA,UACE,kBAAC,GAAD;IACa;IACX,IAAG;IACH,QAAQ,EAAgB,KAAK,MAAM;IACnC,UAAU,EAAkB,KAAK,MAAM;IACvC,UAAU,KAAK;IACf,UAAU,KAAK,MAAM;IACrB,UAAU,KAAK;IACf,SAAS;KACP,gBAAgB;KAChB,kBAAkB;KAClB,aAAa;KACd;cAZH,CAcG,KAAK,MAAM,aACV,kBAAC,OAAD;KAAK,WAAU;eACb,kBAAC,OAAD;MAAK,WAAU;gBAAf;OACE,kBAAC,KAAD,EAAA,UAAG,uBAAuB,CAAA;OAC1B,kBAAC,OAAD;QAAK,
|
|
1
|
+
{"version":3,"file":"ModalDownload.js","names":[],"sources":["../../../src/components/ModalDownload/ModalDownload.tsx"],"sourcesContent":["import SynapseClient from '@/synapse-client'\nimport { SynapseContext } from '@/utils/context/SynapseContext'\nimport { parseEntityIdFromSqlStatement } from '@/utils/functions/SqlFunctions'\nimport { Button } from '@mui/material'\nimport Form, { IChangeEvent } from '@rjsf/core'\nimport validator from '@rjsf/validator-ajv8'\nimport {\n DownloadFromTableRequest,\n DownloadFromTableResult,\n QueryBundleRequest,\n SortItem,\n} from '@sage-bionetworks/synapse-types'\nimport { Component, ContextType, CSSProperties, Fragment } from 'react'\nimport { DialogBase } from '../DialogBase'\nimport SynapseFormCheckboxesWidget from '../SynapseForm/SynapseFormCheckboxesWidget'\nimport SynapseFormCheckboxWidget from '../SynapseForm/SynapseFormCheckboxWidget'\nimport SynapseFormRadioWidget from '../SynapseForm/SynapseFormRadioWidget'\nimport {\n csvOption,\n formSchemaArray,\n formSchemaUIArray,\n includeRowIdAndRowVersionOption,\n writeHeaderOption,\n} from './ModalDownload.FormSchema'\n\ntype ModalDownloadState = {\n isLoading: boolean\n step: number\n data?: DownloadFromTableResult\n formData: Record<string, unknown>\n}\n\nexport type ModalDownloadProps = {\n onClose: (...args: any[]) => void\n includeEntityEtag?: boolean\n queryBundleRequest?: QueryBundleRequest // either the query bundle request needs to be provided, or getLastQueryRequest\n getLastQueryRequest?: () => QueryBundleRequest\n offset?: number\n limit?: number\n sort?: SortItem[]\n}\n\nexport class ModalDownload extends Component<\n ModalDownloadProps,\n ModalDownloadState\n> {\n static contextType = SynapseContext\n declare context: NonNullable<ContextType<typeof SynapseContext>>\n\n constructor(props: ModalDownloadProps) {\n super(props)\n this.state = {\n isLoading: false,\n step: 0,\n formData: {\n 'File Type': csvOption,\n Contents: [writeHeaderOption, includeRowIdAndRowVersionOption],\n },\n }\n }\n\n handleSubmit = (event: IChangeEvent) => {\n if (this.state.step === 0) {\n this.handleDownloadSetup(event)\n } else {\n this.onDownload()\n }\n }\n\n handleDownloadSetup = (event: IChangeEvent) => {\n this.setState({\n isLoading: true,\n })\n const { formData } = event\n const fileType = formData['File Type']\n const contents = formData.Contents as string[]\n const { queryBundleRequest, getLastQueryRequest } = this.props\n const separator = fileType === csvOption ? ',' : '\\t'\n const writeHeader = contents.includes(writeHeaderOption)\n const includeRowIdAndRowVersion = contents.includes(\n includeRowIdAndRowVersionOption,\n )\n const queryRequest = queryBundleRequest ?? getLastQueryRequest!()\n const sql = queryRequest.query.sql\n const downloadFromTableRequest: DownloadFromTableRequest = {\n sql,\n entityId: parseEntityIdFromSqlStatement(sql),\n selectedFacets: queryRequest.query.selectedFacets,\n concreteType:\n 'org.sagebionetworks.repo.model.table.DownloadFromTableRequest',\n writeHeader,\n includeRowIdAndRowVersion,\n csvTableDescriptor: { separator },\n additionalFilters: queryRequest.query.additionalFilters,\n }\n SynapseClient.createTableCsvForDownload(\n downloadFromTableRequest,\n this.context.accessToken,\n )\n .then(data => {\n this.setState({\n isLoading: false,\n step: 1,\n data,\n })\n })\n .catch(err => {\n console.log('Error getDownloadFromTableRequest: ', err)\n })\n }\n\n onDownload = () => {\n const { data } = this.state\n // data will always be defined if calling this function\n SynapseClient.getFileHandleByIdURL(\n data!.resultsFileHandleId,\n this.context.accessToken,\n ).then(url => {\n window.location.href = url\n this.props.onClose()\n })\n }\n\n handleChange = (event: IChangeEvent) => {\n const { formData } = event\n this.setState({\n formData,\n })\n }\n\n render() {\n const spinnerStyle: CSSProperties = {\n height: 50,\n width: 50,\n backgroundSize: 50,\n }\n return (\n <DialogBase\n open={true}\n onCancel={this.props.onClose}\n title=\"Download query results\"\n content={\n <>\n <Form\n validator={validator}\n id=\"modal-download-form\"\n schema={formSchemaArray[this.state.step]}\n uiSchema={formSchemaUIArray[this.state.step]}\n onChange={this.handleChange}\n formData={this.state.formData}\n onSubmit={this.handleSubmit}\n widgets={{\n CheckboxWidget: SynapseFormCheckboxWidget,\n CheckboxesWidget: SynapseFormCheckboxesWidget,\n RadioWidget: SynapseFormRadioWidget,\n }}\n >\n {this.state.isLoading && (\n <div className=\"SRC-centerAndJustifyContent\">\n <div className=\"SRC-center-text\">\n <p> Creating the File </p>\n <div style={spinnerStyle} className=\"spinner\" />\n <p> Loading... </p>\n </div>\n </div>\n )}\n <Fragment />\n </Form>\n </>\n }\n actions={\n <>\n <Button\n variant=\"outlined\"\n color=\"primary\"\n onClick={this.props.onClose}\n >\n Cancel\n </Button>\n <Button\n form=\"modal-download-form\"\n type=\"submit\"\n variant=\"contained\"\n color=\"primary\"\n >\n {this.state.step === 0 ? 'Next' : 'Download'}\n </Button>\n </>\n }\n />\n )\n }\n}\n\nexport default ModalDownload\n"],"mappings":";;;;;;;;;;;;;;AA0CA,IAAa,IAAb,cAAmC,EAGjC;CACA,OAAO,cAAc;CAGrB,YAAY,GAA2B;AAErC,EADA,MAAM,EAAM,EACZ,KAAK,QAAQ;GACX,WAAW;GACX,MAAM;GACN,UAAU;IACR,aAAa;IACb,UAAU,CAAC,GAAmB,EAAgC;IAC/D;GACF;;CAGH,gBAAgB,MAAwB;AACtC,EAAI,KAAK,MAAM,SAAS,IACtB,KAAK,oBAAoB,EAAM,GAE/B,KAAK,YAAY;;CAIrB,uBAAuB,MAAwB;AAC7C,OAAK,SAAS,EACZ,WAAW,IACZ,CAAC;EACF,IAAM,EAAE,gBAAa,GACf,IAAW,EAAS,cACpB,IAAW,EAAS,UACpB,EAAE,uBAAoB,2BAAwB,KAAK,OACnD,IAAY,MAAA,iCAAyB,MAAM,KAC3C,IAAc,EAAS,SAAS,EAAkB,EAClD,IAA4B,EAAS,SACzC,EACD,EACK,IAAe,KAAsB,GAAsB,EAC3D,IAAM,EAAa,MAAM,KACzB,IAAqD;GACzD;GACA,UAAU,EAA8B,EAAI;GAC5C,gBAAgB,EAAa,MAAM;GACnC,cACE;GACF;GACA;GACA,oBAAoB,EAAE,cAAW;GACjC,mBAAmB,EAAa,MAAM;GACvC;AACD,IAAc,0BACZ,GACA,KAAK,QAAQ,YACd,CACE,MAAK,MAAQ;AACZ,QAAK,SAAS;IACZ,WAAW;IACX,MAAM;IACN;IACD,CAAC;IACF,CACD,OAAM,MAAO;AACZ,WAAQ,IAAI,uCAAuC,EAAI;IACvD;;CAGN,mBAAmB;EACjB,IAAM,EAAE,YAAS,KAAK;AAEtB,IAAc,qBACZ,EAAM,qBACN,KAAK,QAAQ,YACd,CAAC,MAAK,MAAO;AAEZ,GADA,OAAO,SAAS,OAAO,GACvB,KAAK,MAAM,SAAS;IACpB;;CAGJ,gBAAgB,MAAwB;EACtC,IAAM,EAAE,gBAAa;AACrB,OAAK,SAAS,EACZ,aACD,CAAC;;CAGJ,SAAS;AAMP,SACE,kBAAC,GAAD;GACE,MAAM;GACN,UAAU,KAAK,MAAM;GACrB,OAAM;GACN,SACE,kBAAA,GAAA,EAAA,UACE,kBAAC,GAAD;IACa;IACX,IAAG;IACH,QAAQ,EAAgB,KAAK,MAAM;IACnC,UAAU,EAAkB,KAAK,MAAM;IACvC,UAAU,KAAK;IACf,UAAU,KAAK,MAAM;IACrB,UAAU,KAAK;IACf,SAAS;KACP,gBAAgB;KAChB,kBAAkB;KAClB,aAAa;KACd;cAZH,CAcG,KAAK,MAAM,aACV,kBAAC,OAAD;KAAK,WAAU;eACb,kBAAC,OAAD;MAAK,WAAU;gBAAf;OACE,kBAAC,KAAD,EAAA,UAAG,uBAAuB,CAAA;OAC1B,kBAAC,OAAD;QAAK,OAAO;SA7B1B,QAAQ;SACR,OAAO;SACP,gBAAgB;SA2BU;QAAc,WAAU;QAAY,CAAA;OAChD,kBAAC,KAAD,EAAA,UAAG,gBAAgB,CAAA;OACf;;KACF,CAAA,EAER,kBAAC,GAAD,EAAY,CAAA,CACP;OACN,CAAA;GAEL,SACE,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD;IACE,SAAQ;IACR,OAAM;IACN,SAAS,KAAK,MAAM;cACrB;IAEQ,CAAA,EACT,kBAAC,GAAD;IACE,MAAK;IACL,MAAK;IACL,SAAQ;IACR,OAAM;cAEL,KAAK,MAAM,SAAS,IAAI,SAAS;IAC3B,CAAA,CACR,EAAA,CAAA;GAEL,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OAuthClientAclEditor.d.ts","sourceRoot":"","sources":["../../../src/components/OAuthClientAclEditor/OAuthClientAclEditor.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"OAuthClientAclEditor.d.ts","sourceRoot":"","sources":["../../../src/components/OAuthClientAclEditor/OAuthClientAclEditor.tsx"],"names":[],"mappings":"AAgCA,MAAM,MAAM,0BAA0B,GAAG;IAEvC,IAAI,EAAE,MAAM,IAAI,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,yBAAyB,GAAG;IACtC,QAAQ,EAAE,MAAM,CAAA;IAChB,cAAc,EAAE,CAAC,cAAc,EAAE,OAAO,KAAK,IAAI,CAAA;CAClD,CAAA;AAED,eAAO,MAAM,oBAAoB,kIAyH/B,CAAA"}
|
|
@@ -1,61 +1,67 @@
|
|
|
1
1
|
import { getAccessTypeFromPermissionLevel as e } from "../../utils/PermissionLevelToAccessType.js";
|
|
2
2
|
import { useGetOAuthClientACL as t, useUpdateOAuthClientACL as n } from "../../synapse-queries/oauth/useOAuthClient.js";
|
|
3
3
|
import "../../synapse-queries/index.js";
|
|
4
|
-
import {
|
|
5
|
-
import { AclEditor as
|
|
6
|
-
import
|
|
7
|
-
import { forwardRef as
|
|
8
|
-
import { isEqual as
|
|
9
|
-
import { Alert as
|
|
10
|
-
import { jsx as
|
|
4
|
+
import { consolidateResourceAccessList as r, convertResourceAccessSetToSRC as i, updateACLWithSRCResourceAccessList as a } from "../../utils/functions/AccessControlListUtils.js";
|
|
5
|
+
import { AclEditor as o } from "../AclEditor/AclEditor.js";
|
|
6
|
+
import s from "../AclEditor/useUpdateAcl.js";
|
|
7
|
+
import { forwardRef as c, useEffect as l, useImperativeHandle as u, useMemo as d, useState as f } from "react";
|
|
8
|
+
import { isEqual as p } from "lodash-es";
|
|
9
|
+
import { Alert as m, Stack as h } from "@mui/material";
|
|
10
|
+
import { jsx as g, jsxs as _ } from "react/jsx-runtime";
|
|
11
11
|
//#region src/components/OAuthClientAclEditor/OAuthClientAclEditor.tsx
|
|
12
|
-
var
|
|
13
|
-
let { clientId:
|
|
14
|
-
|
|
15
|
-
},
|
|
16
|
-
|
|
17
|
-
}, { data:
|
|
18
|
-
onChange: () =>
|
|
19
|
-
onError:
|
|
12
|
+
var v = ["CAN_ADMINISTER_OAUTH_CLIENT"], y = c(function(c, y) {
|
|
13
|
+
let { clientId: b, onSaveComplete: x } = c, [S, C] = f(null), w = () => {
|
|
14
|
+
C(null), x(!0);
|
|
15
|
+
}, T = (e) => {
|
|
16
|
+
C(e.reason), x(!1);
|
|
17
|
+
}, { data: E, isLoading: D } = t(b, { staleTime: Infinity }), O = d(() => r(i(E?.resourceAccess)), [E]), { resourceAccessList: k, setResourceAccessList: A, addResourceAccessItem: j, updateResourceAccessItem: M, removeResourceAccessItem: N, resetDirtyState: P } = s({
|
|
18
|
+
onChange: () => C(null),
|
|
19
|
+
onError: C
|
|
20
20
|
});
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}, [
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
l(() => {
|
|
22
|
+
E && (P(), A(O));
|
|
23
|
+
}, [
|
|
24
|
+
E,
|
|
25
|
+
O,
|
|
26
|
+
P,
|
|
27
|
+
A
|
|
28
|
+
]);
|
|
29
|
+
let { mutate: F } = n({
|
|
30
|
+
onSuccess: () => w(),
|
|
31
|
+
onError: (e) => T(e)
|
|
27
32
|
});
|
|
28
|
-
return
|
|
29
|
-
let e =
|
|
30
|
-
|
|
33
|
+
return u(y, () => ({ save() {
|
|
34
|
+
let e = a(E, k);
|
|
35
|
+
E === null && e == null || p(O, k) && E?.id === e?.id ? x(!0) : F(e);
|
|
31
36
|
} }), [
|
|
32
|
-
|
|
33
|
-
w,
|
|
37
|
+
b,
|
|
34
38
|
E,
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
39
|
+
O,
|
|
40
|
+
k,
|
|
41
|
+
x,
|
|
42
|
+
F
|
|
43
|
+
]), /* @__PURE__ */ _(h, {
|
|
38
44
|
direction: "column",
|
|
39
45
|
sx: { gap: "20px" },
|
|
40
|
-
children: [/* @__PURE__ */
|
|
41
|
-
resourceAccessList:
|
|
42
|
-
availablePermissionLevels:
|
|
43
|
-
isLoading:
|
|
46
|
+
children: [/* @__PURE__ */ g(o, {
|
|
47
|
+
resourceAccessList: k,
|
|
48
|
+
availablePermissionLevels: v,
|
|
49
|
+
isLoading: D,
|
|
44
50
|
canEdit: !0,
|
|
45
51
|
emptyText: "",
|
|
46
|
-
onAddPrincipalToAcl: (t) =>
|
|
47
|
-
updateResourceAccessItem:
|
|
48
|
-
removeResourceAccessItem:
|
|
52
|
+
onAddPrincipalToAcl: (t) => j(t, e("CAN_ADMINISTER_OAUTH_CLIENT")),
|
|
53
|
+
updateResourceAccessItem: M,
|
|
54
|
+
removeResourceAccessItem: N,
|
|
49
55
|
showAddRemovePublicButton: !1,
|
|
50
56
|
showNotifyCheckbox: !1,
|
|
51
57
|
isInherited: !1
|
|
52
|
-
}),
|
|
58
|
+
}), S && /* @__PURE__ */ g(m, {
|
|
53
59
|
severity: "error",
|
|
54
|
-
children:
|
|
60
|
+
children: S
|
|
55
61
|
})]
|
|
56
62
|
});
|
|
57
63
|
});
|
|
58
64
|
//#endregion
|
|
59
|
-
export {
|
|
65
|
+
export { y as OAuthClientAclEditor };
|
|
60
66
|
|
|
61
67
|
//# sourceMappingURL=OAuthClientAclEditor.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OAuthClientAclEditor.js","names":[],"sources":["../../../src/components/OAuthClientAclEditor/OAuthClientAclEditor.tsx"],"sourcesContent":["import {\n useGetOAuthClientACL,\n useUpdateOAuthClientACL,\n} from '@/synapse-queries'\nimport {\n getAccessTypeFromPermissionLevel,\n PermissionLevel,\n} from '@/utils/PermissionLevelToAccessType'\nimport { Alert, Stack } from '@mui/material'\nimport { SynapseClientError } from '@sage-bionetworks/synapse-client/util/SynapseClientError'\nimport { isEqual } from 'lodash-es'\nimport {\n ForwardedRef,\n forwardRef,\n useEffect,\n useImperativeHandle,\n useState,\n} from 'react'\nimport { AclEditor } from '../AclEditor/AclEditor'\nimport useUpdateAcl from '../AclEditor/useUpdateAcl'\nimport { AccessControlList } from '@sage-bionetworks/synapse-client'\
|
|
1
|
+
{"version":3,"file":"OAuthClientAclEditor.js","names":[],"sources":["../../../src/components/OAuthClientAclEditor/OAuthClientAclEditor.tsx"],"sourcesContent":["import {\n useGetOAuthClientACL,\n useUpdateOAuthClientACL,\n} from '@/synapse-queries'\nimport {\n getAccessTypeFromPermissionLevel,\n PermissionLevel,\n} from '@/utils/PermissionLevelToAccessType'\nimport { Alert, Stack } from '@mui/material'\nimport { SynapseClientError } from '@sage-bionetworks/synapse-client/util/SynapseClientError'\nimport {\n consolidateResourceAccessList,\n convertResourceAccessSetToSRC,\n updateACLWithSRCResourceAccessList,\n} from '@/utils/functions/AccessControlListUtils'\nimport { isEqual } from 'lodash-es'\nimport {\n ForwardedRef,\n forwardRef,\n useEffect,\n useImperativeHandle,\n useMemo,\n useState,\n} from 'react'\nimport { AclEditor } from '../AclEditor/AclEditor'\nimport useUpdateAcl from '../AclEditor/useUpdateAcl'\nimport { AccessControlList } from '@sage-bionetworks/synapse-client'\n\nconst availablePermissionLevels: PermissionLevel[] = [\n 'CAN_ADMINISTER_OAUTH_CLIENT',\n]\n\nexport type OAuthClientAclEditorHandle = {\n /* Allow the parent component to trigger saving the ACL, so this may be embedded in an arbitrary modal. */\n save: () => void\n}\n\nexport type OAuthClientAclEditorProps = {\n clientId: string\n onSaveComplete: (saveSuccessful: boolean) => void\n}\n\nexport const OAuthClientAclEditor = forwardRef(function OAuthClientAclEditor(\n props: OAuthClientAclEditorProps,\n ref: ForwardedRef<OAuthClientAclEditorHandle>,\n) {\n const { clientId, onSaveComplete } = props\n const [error, setError] = useState<string | null>(null)\n\n const onMutationSuccess = () => {\n setError(null)\n onSaveComplete(true)\n }\n\n const onMutationError = (error: SynapseClientError) => {\n setError(error.reason)\n onSaveComplete(false)\n }\n\n const { data: originalAcl, isLoading: isLoadingOriginalAcl } =\n useGetOAuthClientACL(clientId, {\n // Infinite staleTime ensures this won't get re-fetched unless explicitly invalidated by the mutation\n staleTime: Infinity,\n })\n\n const consolidatedOriginalResourceAccess = useMemo(\n () =>\n consolidateResourceAccessList(\n convertResourceAccessSetToSRC(originalAcl?.resourceAccess),\n ),\n [originalAcl],\n )\n\n const {\n resourceAccessList,\n setResourceAccessList,\n addResourceAccessItem,\n updateResourceAccessItem,\n removeResourceAccessItem,\n resetDirtyState,\n } = useUpdateAcl({\n onChange: () => setError(null),\n onError: setError,\n })\n\n // set resourceAccessList when the fetched acl changes\n useEffect(() => {\n if (originalAcl) {\n resetDirtyState()\n setResourceAccessList(consolidatedOriginalResourceAccess)\n }\n }, [\n originalAcl,\n consolidatedOriginalResourceAccess,\n resetDirtyState,\n setResourceAccessList,\n ])\n\n const { mutate: updateAcl } = useUpdateOAuthClientACL({\n onSuccess: () => onMutationSuccess(),\n onError: (error: SynapseClientError) => onMutationError(error),\n })\n\n useImperativeHandle(\n ref,\n () => {\n return {\n save() {\n const updatedAcl: AccessControlList =\n updateACLWithSRCResourceAccessList(originalAcl, resourceAccessList)\n const aclIsUnchanged =\n (originalAcl === null && updatedAcl == null) ||\n // ignore properties that will change when the ACL is saved (etag, modifiedOn)\n (isEqual(consolidatedOriginalResourceAccess, resourceAccessList) &&\n originalAcl?.id === updatedAcl?.id)\n\n if (aclIsUnchanged) {\n // noop\n onSaveComplete(true)\n } else {\n updateAcl(updatedAcl)\n }\n },\n }\n },\n [\n clientId,\n originalAcl,\n consolidatedOriginalResourceAccess,\n resourceAccessList,\n onSaveComplete,\n updateAcl,\n ],\n )\n\n return (\n <Stack\n direction=\"column\"\n sx={{\n gap: '20px',\n }}\n >\n <AclEditor\n resourceAccessList={resourceAccessList}\n availablePermissionLevels={availablePermissionLevels}\n isLoading={isLoadingOriginalAcl}\n canEdit={true}\n emptyText={/* This should never happen */ ''}\n onAddPrincipalToAcl={id =>\n addResourceAccessItem(\n id,\n getAccessTypeFromPermissionLevel('CAN_ADMINISTER_OAUTH_CLIENT'),\n )\n }\n updateResourceAccessItem={updateResourceAccessItem}\n removeResourceAccessItem={removeResourceAccessItem}\n showAddRemovePublicButton={false}\n showNotifyCheckbox={false}\n isInherited={false}\n />\n {error && <Alert severity=\"error\">{error}</Alert>}\n </Stack>\n )\n})\n"],"mappings":";;;;;;;;;;;AA4BA,IAAM,IAA+C,CACnD,8BACD,EAYY,IAAuB,EAAW,SAC7C,GACA,GACA;CACA,IAAM,EAAE,aAAU,sBAAmB,GAC/B,CAAC,GAAO,KAAY,EAAwB,KAAK,EAEjD,UAA0B;AAE9B,EADA,EAAS,KAAK,EACd,EAAe,GAAK;IAGhB,KAAmB,MAA8B;AAErD,EADA,EAAS,EAAM,OAAO,EACtB,EAAe,GAAM;IAGjB,EAAE,MAAM,GAAa,WAAW,MACpC,EAAqB,GAAU,EAE7B,WAAW,UACZ,CAAC,EAEE,IAAqC,QAEvC,EACE,EAA8B,GAAa,eAAe,CAC3D,EACH,CAAC,EAAY,CACd,EAEK,EACJ,uBACA,0BACA,0BACA,6BACA,6BACA,uBACE,EAAa;EACf,gBAAgB,EAAS,KAAK;EAC9B,SAAS;EACV,CAAC;AAGF,SAAgB;AACd,EAAI,MACF,GAAiB,EACjB,EAAsB,EAAmC;IAE1D;EACD;EACA;EACA;EACA;EACD,CAAC;CAEF,IAAM,EAAE,QAAQ,MAAc,EAAwB;EACpD,iBAAiB,GAAmB;EACpC,UAAU,MAA8B,EAAgB,EAAM;EAC/D,CAAC;AAkCF,QAhCA,EACE,UAES,EACL,OAAO;EACL,IAAM,IACJ,EAAmC,GAAa,EAAmB;AAOrE,EALG,MAAgB,QAAQ,KAAc,QAEtC,EAAQ,GAAoC,EAAmB,IAC9D,GAAa,OAAO,GAAY,KAIlC,EAAe,GAAK,GAEpB,EAAU,EAAW;IAG1B,GAEH;EACE;EACA;EACA;EACA;EACA;EACA;EACD,CACF,EAGC,kBAAC,GAAD;EACE,WAAU;EACV,IAAI,EACF,KAAK,QACN;YAJH,CAME,kBAAC,GAAD;GACsB;GACO;GAC3B,WAAW;GACX,SAAS;GACT,WAA0C;GAC1C,sBAAqB,MACnB,EACE,GACA,EAAiC,8BAA8B,CAChE;GAEuB;GACA;GAC1B,2BAA2B;GAC3B,oBAAoB;GACpB,aAAa;GACb,CAAA,EACD,KAAS,kBAAC,GAAD;GAAO,UAAS;aAAS;GAAc,CAAA,CAC3C;;EAEV"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OAuthManagement.js","names":[],"sources":["../../../src/components/OAuthClientManagement/OAuthManagement.tsx"],"sourcesContent":["import InfiniteTableLayout from '@/components/layout/InfiniteTableLayout'\nimport SynapseClient from '@/synapse-client'\nimport { useGetOAuthClientInfinite } from '@/synapse-queries'\nimport { MoreVert } from '@mui/icons-material'\nimport { useSynapseContext } from '@/utils'\nimport { formatDate } from '@/utils/functions/DateFormatter'\nimport { AddCircleTwoTone } from '@mui/icons-material'\nimport { Box, Button, Link, IconButton, Menu, MenuItem } from '@mui/material'\nimport { OAuthClient } from '@sage-bionetworks/synapse-client/generated/models/OAuthClient'\nimport {\n createColumnHelper,\n getCoreRowModel,\n Row,\n Table,\n useReactTable,\n} from '@tanstack/react-table'\nimport dayjs from 'dayjs'\nimport { useMemo, useState } from 'react'\nimport CopyToClipboardInput from '../CopyToClipboardInput/CopyToClipboardInput'\nimport { DialogBase } from '../DialogBase'\nimport WarningDialog from '../SynapseForm/WarningDialog'\nimport ColumnHeader from '../TanStackTable/ColumnHeader'\nimport StyledTanStackTable from '../TanStackTable/StyledTanStackTable'\nimport { displayToast } from '../ToastMessage'\nimport { CreateOAuthModal } from './CreateOAuthClient'\nimport OAuthAclEditorModal from '../OAuthClientAclEditor/OAuthAclEditorModal'\n\nconst columnHelper = createColumnHelper<OAuthClient>()\nfunction getColumns(columnOptions: {\n setIsShowingVerification: (value: boolean) => void\n setSelectedClient: (value: OAuthClient) => void\n setIsShowingSecretWarning: (value: boolean) => void\n setIsEdit: (value: boolean) => void\n setIsShowingCreateClientModal: (value: boolean) => void\n setIsShowingSharingSettings: (value: boolean) => void\n}) {\n const {\n setIsShowingVerification,\n setSelectedClient,\n setIsShowingSecretWarning,\n setIsEdit,\n setIsShowingCreateClientModal,\n setIsShowingSharingSettings,\n } = columnOptions\n return [\n columnHelper.accessor('createdOn', {\n header: props => <ColumnHeader {...props} title={'Created'} />,\n cell: info => formatDate(dayjs(info.getValue())),\n }),\n columnHelper.accessor('modifiedOn', {\n header: props => <ColumnHeader {...props} title={'Modified'} />,\n cell: info => formatDate(dayjs(info.getValue())),\n }),\n columnHelper.accessor('client_id', {\n header: props => <ColumnHeader {...props} title={'ID'} />,\n }),\n columnHelper.accessor('client_name', {\n header: props => <ColumnHeader {...props} title={'Client'} />,\n }),\n columnHelper.accessor('verified', {\n header: props => <ColumnHeader {...props} title={'Verified'} />,\n cell: ({ getValue }) =>\n getValue() ? (\n 'Yes'\n ) : (\n <Button\n variant=\"outlined\"\n size=\"small\"\n onClick={() => setIsShowingVerification(true)}\n >\n Submit Verification\n </Button>\n ),\n }),\n columnHelper.display({\n id: 'actions',\n header: props => <ColumnHeader {...props} title={'Actions'} />,\n cell: ({ row }) => (\n <ActionsMenuCell\n row={row}\n setSelectedClient={setSelectedClient}\n setIsEdit={setIsEdit}\n setIsShowingCreateClientModal={setIsShowingCreateClientModal}\n setIsShowingSecretWarning={setIsShowingSecretWarning}\n setIsShowingSharingSettings={setIsShowingSharingSettings}\n />\n ),\n }),\n ]\n}\n\nfunction ActionsMenuCell({\n row,\n setSelectedClient,\n setIsEdit,\n setIsShowingCreateClientModal,\n setIsShowingSecretWarning,\n setIsShowingSharingSettings,\n}: {\n row: Row<OAuthClient>\n setSelectedClient: (value: OAuthClient) => void\n setIsEdit: (value: boolean) => void\n setIsShowingCreateClientModal: (value: boolean) => void\n setIsShowingSecretWarning: (value: boolean) => void\n setIsShowingSharingSettings: (value: boolean) => void\n}) {\n const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null)\n const open = Boolean(anchorEl)\n const handleMenuOpen = (event: React.MouseEvent<HTMLElement>) => {\n setAnchorEl(event.currentTarget)\n }\n const handleMenuClose = () => {\n setAnchorEl(null)\n }\n return (\n <>\n <IconButton\n aria-label=\"more\"\n aria-controls={`actions-menu-${row.id}`}\n aria-haspopup=\"true\"\n onClick={handleMenuOpen}\n size=\"small\"\n >\n <MoreVert />\n </IconButton>\n <Menu\n id={`actions-menu-${row.id}`}\n anchorEl={anchorEl}\n open={open}\n onClose={handleMenuClose}\n anchorOrigin={{\n vertical: 'bottom',\n horizontal: 'right',\n }}\n transformOrigin={{\n vertical: 'top',\n horizontal: 'right',\n }}\n >\n <MenuItem\n onClick={() => {\n setSelectedClient(row.original)\n setIsEdit(true)\n setIsShowingCreateClientModal(true)\n handleMenuClose()\n }}\n >\n Edit\n </MenuItem>\n <MenuItem\n onClick={() => {\n setSelectedClient(row.original)\n setIsShowingSecretWarning(true)\n handleMenuClose()\n }}\n >\n Generate Secret\n </MenuItem>\n <MenuItem\n onClick={() => {\n setSelectedClient(row.original)\n setIsShowingSharingSettings(true)\n handleMenuClose()\n }}\n >\n Sharing Settings\n </MenuItem>\n </Menu>\n </>\n )\n}\n\nexport function OAuthManagement() {\n const { accessToken } = useSynapseContext()\n const [isShowingSharingSettings, setIsShowingSharingSettings] =\n useState(false)\n const [isShowingCreateClientModal, setIsShowingCreateClientModal] =\n useState(false)\n const [isEdit, setIsEdit] = useState<boolean>(false)\n const [selectedClient, setSelectedClient] = useState<OAuthClient>()\n const [isShowingConfirmModal, setIsShowingConfirmModal] = useState(false)\n const [isShowingSecretWarning, setIsShowingSecretWarning] = useState(false)\n const [isShowingSecret, setIsShowingSecret] = useState(false)\n const [secret, setSecret] = useState<string>()\n const [isShowingVerification, setIsShowingVerification] = useState(false)\n\n const { data, isLoading, hasNextPage, fetchNextPage, isFetchingNextPage } =\n useGetOAuthClientInfinite()\n const oAuthClientList = useMemo(\n () => data?.pages.flatMap(page => page.results || []) || [],\n [data],\n )\n\n const warningHeader = 'Are you absolutely sure?'\n const warningBody =\n 'If you have an existing secret, generating a new secret will make your application invalid after generation. This action cannot be undone.'\n\n const onShowSecret = async () => {\n setIsShowingSecretWarning(false)\n try {\n const secret = await SynapseClient.createOAuthClientSecret(\n accessToken!,\n selectedClient?.client_id!,\n )\n setSelectedClient(undefined)\n setIsShowingSecret(true)\n setSecret(secret.client_secret)\n } catch (err: any) {\n displayToast(err.reason as string, 'danger')\n }\n }\n\n const columns = useMemo(\n () =>\n getColumns({\n setIsShowingVerification,\n setSelectedClient,\n setIsShowingSecretWarning,\n setIsEdit,\n setIsShowingCreateClientModal,\n setIsShowingSharingSettings,\n }),\n [],\n )\n\n const table: Table<OAuthClient> = useReactTable<OAuthClient>({\n data: oAuthClientList,\n columns,\n getRowId: row => row.client_id!,\n enableRowSelection: true,\n enableSorting: false,\n getCoreRowModel: getCoreRowModel(),\n columnResizeMode: 'onChange',\n })\n\n const isEmpty = !isLoading && table.getRowModel().rows.length === 0\n\n return (\n <div>\n <Box\n sx={{\n display: 'flex',\n width: '100%',\n justifyContent: 'flex-end',\n mb: 2,\n }}\n >\n <Button\n variant=\"contained\"\n color=\"primary\"\n onClick={() => {\n setIsShowingCreateClientModal(true)\n setIsEdit(false)\n }}\n sx={{ float: 'right' }}\n startIcon={<AddCircleTwoTone />}\n >\n Create New Client\n </Button>\n </Box>\n <InfiniteTableLayout\n table={<StyledTanStackTable table={table} />}\n isLoading={isLoading}\n isEmpty={isEmpty}\n hasNextPage={hasNextPage}\n onFetchNextPageClicked={() => {\n void fetchNextPage()\n }}\n isFetchingNextPage={isFetchingNextPage}\n />\n <CreateOAuthModal\n onClose={() => {\n setIsShowingCreateClientModal(false)\n }}\n isShowingModal={isShowingCreateClientModal}\n client={isEdit ? selectedClient : undefined}\n isEdit={isEdit}\n setIsShowingConfirmModal={setIsShowingConfirmModal}\n isShowingConfirmModal={isShowingConfirmModal}\n setIsShowingModal={setIsShowingCreateClientModal}\n />\n <DialogBase\n open={isShowingVerification}\n onCancel={() => setIsShowingVerification(false)}\n title=\"Submit Verification\"\n content={\n <>\n <p>\n In order to verify an OAuth client please submit a request to the{' '}\n <Link\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n href=\"https://sagebionetworks.jira.com/servicedesk/customer/portal/9\"\n >\n Synapse Service Desk.\n </Link>\n </p>\n <b>Please list the following items in your request:</b>\n <ul>\n <li>Your name</li>\n <li>\n The ID of the client to be verified <br />\n </li>\n <li>A description of your application</li>\n </ul>\n {/* <p>\n Verification can take up to X weeks and we will notify you via X.\n </p> */}\n </>\n }\n />\n <OAuthAclEditorModal\n clientId={selectedClient?.client_id!}\n open={isShowingSharingSettings}\n onClose={() => setIsShowingSharingSettings(false)}\n />\n <WarningDialog\n open={isShowingSecretWarning}\n title={warningHeader}\n content={warningBody}\n onCancel={() => {\n setIsShowingSecretWarning(false)\n setSelectedClient(undefined)\n }}\n onConfirm={onShowSecret}\n confirmButtonColor=\"error\"\n confirmButtonText=\"Yes, Continue\"\n />\n {secret && (\n <DialogBase\n open={isShowingSecret}\n title=\"App Secret\"\n onCancel={() => {\n setIsShowingSecret(false)\n setSecret(undefined)\n }}\n content={\n <>\n <p>\n <b>This secret will not be able to be retrieved again.</b> If\n needed, in order to generate a new secret select Generate from\n the Client List.\n </p>\n <CopyToClipboardInput value={secret} inputWidth={'400px'} />\n </>\n }\n />\n )}\n </div>\n )\n}\n\nexport default OAuthManagement\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"OAuthManagement.js","names":[],"sources":["../../../src/components/OAuthClientManagement/OAuthManagement.tsx"],"sourcesContent":["import InfiniteTableLayout from '@/components/layout/InfiniteTableLayout'\nimport SynapseClient from '@/synapse-client'\nimport { useGetOAuthClientInfinite } from '@/synapse-queries'\nimport { MoreVert } from '@mui/icons-material'\nimport { useSynapseContext } from '@/utils'\nimport { formatDate } from '@/utils/functions/DateFormatter'\nimport { AddCircleTwoTone } from '@mui/icons-material'\nimport { Box, Button, Link, IconButton, Menu, MenuItem } from '@mui/material'\nimport { OAuthClient } from '@sage-bionetworks/synapse-client/generated/models/OAuthClient'\nimport {\n createColumnHelper,\n getCoreRowModel,\n Row,\n Table,\n useReactTable,\n} from '@tanstack/react-table'\nimport dayjs from 'dayjs'\nimport { useMemo, useState } from 'react'\nimport CopyToClipboardInput from '../CopyToClipboardInput/CopyToClipboardInput'\nimport { DialogBase } from '../DialogBase'\nimport WarningDialog from '../SynapseForm/WarningDialog'\nimport ColumnHeader from '../TanStackTable/ColumnHeader'\nimport StyledTanStackTable from '../TanStackTable/StyledTanStackTable'\nimport { displayToast } from '../ToastMessage'\nimport { CreateOAuthModal } from './CreateOAuthClient'\nimport OAuthAclEditorModal from '../OAuthClientAclEditor/OAuthAclEditorModal'\n\nconst columnHelper = createColumnHelper<OAuthClient>()\nfunction getColumns(columnOptions: {\n setIsShowingVerification: (value: boolean) => void\n setSelectedClient: (value: OAuthClient) => void\n setIsShowingSecretWarning: (value: boolean) => void\n setIsEdit: (value: boolean) => void\n setIsShowingCreateClientModal: (value: boolean) => void\n setIsShowingSharingSettings: (value: boolean) => void\n}) {\n const {\n setIsShowingVerification,\n setSelectedClient,\n setIsShowingSecretWarning,\n setIsEdit,\n setIsShowingCreateClientModal,\n setIsShowingSharingSettings,\n } = columnOptions\n return [\n columnHelper.accessor('createdOn', {\n header: props => <ColumnHeader {...props} title={'Created'} />,\n cell: info => formatDate(dayjs(info.getValue())),\n }),\n columnHelper.accessor('modifiedOn', {\n header: props => <ColumnHeader {...props} title={'Modified'} />,\n cell: info => formatDate(dayjs(info.getValue())),\n }),\n columnHelper.accessor('client_id', {\n header: props => <ColumnHeader {...props} title={'ID'} />,\n }),\n columnHelper.accessor('client_name', {\n header: props => <ColumnHeader {...props} title={'Client'} />,\n }),\n columnHelper.accessor('verified', {\n header: props => <ColumnHeader {...props} title={'Verified'} />,\n cell: ({ getValue }) =>\n getValue() ? (\n 'Yes'\n ) : (\n <Button\n variant=\"outlined\"\n size=\"small\"\n onClick={() => setIsShowingVerification(true)}\n >\n Submit Verification\n </Button>\n ),\n }),\n columnHelper.display({\n id: 'actions',\n header: props => <ColumnHeader {...props} title={'Actions'} />,\n cell: ({ row }) => (\n <ActionsMenuCell\n row={row}\n setSelectedClient={setSelectedClient}\n setIsEdit={setIsEdit}\n setIsShowingCreateClientModal={setIsShowingCreateClientModal}\n setIsShowingSecretWarning={setIsShowingSecretWarning}\n setIsShowingSharingSettings={setIsShowingSharingSettings}\n />\n ),\n }),\n ]\n}\n\nfunction ActionsMenuCell({\n row,\n setSelectedClient,\n setIsEdit,\n setIsShowingCreateClientModal,\n setIsShowingSecretWarning,\n setIsShowingSharingSettings,\n}: {\n row: Row<OAuthClient>\n setSelectedClient: (value: OAuthClient) => void\n setIsEdit: (value: boolean) => void\n setIsShowingCreateClientModal: (value: boolean) => void\n setIsShowingSecretWarning: (value: boolean) => void\n setIsShowingSharingSettings: (value: boolean) => void\n}) {\n const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null)\n const open = Boolean(anchorEl)\n const handleMenuOpen = (event: React.MouseEvent<HTMLElement>) => {\n setAnchorEl(event.currentTarget)\n }\n const handleMenuClose = () => {\n setAnchorEl(null)\n }\n return (\n <>\n <IconButton\n aria-label=\"more\"\n aria-controls={`actions-menu-${row.id}`}\n aria-haspopup=\"true\"\n onClick={handleMenuOpen}\n size=\"small\"\n >\n <MoreVert />\n </IconButton>\n <Menu\n id={`actions-menu-${row.id}`}\n anchorEl={anchorEl}\n open={open}\n onClose={handleMenuClose}\n anchorOrigin={{\n vertical: 'bottom',\n horizontal: 'right',\n }}\n transformOrigin={{\n vertical: 'top',\n horizontal: 'right',\n }}\n >\n <MenuItem\n onClick={() => {\n setSelectedClient(row.original)\n setIsEdit(true)\n setIsShowingCreateClientModal(true)\n handleMenuClose()\n }}\n >\n Edit\n </MenuItem>\n <MenuItem\n onClick={() => {\n setSelectedClient(row.original)\n setIsShowingSecretWarning(true)\n handleMenuClose()\n }}\n >\n Generate Secret\n </MenuItem>\n <MenuItem\n onClick={() => {\n setSelectedClient(row.original)\n setIsShowingSharingSettings(true)\n handleMenuClose()\n }}\n >\n Sharing Settings\n </MenuItem>\n </Menu>\n </>\n )\n}\n\nexport function OAuthManagement() {\n const { accessToken } = useSynapseContext()\n const [isShowingSharingSettings, setIsShowingSharingSettings] =\n useState(false)\n const [isShowingCreateClientModal, setIsShowingCreateClientModal] =\n useState(false)\n const [isEdit, setIsEdit] = useState<boolean>(false)\n const [selectedClient, setSelectedClient] = useState<OAuthClient>()\n const [isShowingConfirmModal, setIsShowingConfirmModal] = useState(false)\n const [isShowingSecretWarning, setIsShowingSecretWarning] = useState(false)\n const [isShowingSecret, setIsShowingSecret] = useState(false)\n const [secret, setSecret] = useState<string>()\n const [isShowingVerification, setIsShowingVerification] = useState(false)\n\n const { data, isLoading, hasNextPage, fetchNextPage, isFetchingNextPage } =\n useGetOAuthClientInfinite()\n const oAuthClientList = useMemo(\n () => data?.pages.flatMap(page => page.results || []) || [],\n [data],\n )\n\n const warningHeader = 'Are you absolutely sure?'\n const warningBody =\n 'If you have an existing secret, generating a new secret will make your application invalid after generation. This action cannot be undone.'\n\n const onShowSecret = async () => {\n setIsShowingSecretWarning(false)\n try {\n const secret = await SynapseClient.createOAuthClientSecret(\n accessToken!,\n selectedClient?.client_id!,\n )\n setSelectedClient(undefined)\n setIsShowingSecret(true)\n setSecret(secret.client_secret)\n } catch (err: any) {\n displayToast(err.reason as string, 'danger')\n }\n }\n\n const columns = useMemo(\n () =>\n getColumns({\n setIsShowingVerification,\n setSelectedClient,\n setIsShowingSecretWarning,\n setIsEdit,\n setIsShowingCreateClientModal,\n setIsShowingSharingSettings,\n }),\n [],\n )\n\n const table: Table<OAuthClient> = useReactTable<OAuthClient>({\n data: oAuthClientList,\n columns,\n getRowId: row => row.client_id!,\n enableRowSelection: true,\n enableSorting: false,\n getCoreRowModel: getCoreRowModel(),\n columnResizeMode: 'onChange',\n })\n\n const isEmpty = !isLoading && table.getRowModel().rows.length === 0\n\n return (\n <div>\n <Box\n sx={{\n display: 'flex',\n width: '100%',\n justifyContent: 'flex-end',\n mb: 2,\n }}\n >\n <Button\n variant=\"contained\"\n color=\"primary\"\n onClick={() => {\n setIsShowingCreateClientModal(true)\n setIsEdit(false)\n }}\n sx={{ float: 'right' }}\n startIcon={<AddCircleTwoTone />}\n >\n Create New Client\n </Button>\n </Box>\n <InfiniteTableLayout\n table={<StyledTanStackTable table={table} />}\n isLoading={isLoading}\n isEmpty={isEmpty}\n hasNextPage={hasNextPage}\n onFetchNextPageClicked={() => {\n void fetchNextPage()\n }}\n isFetchingNextPage={isFetchingNextPage}\n />\n <CreateOAuthModal\n onClose={() => {\n setIsShowingCreateClientModal(false)\n }}\n isShowingModal={isShowingCreateClientModal}\n client={isEdit ? selectedClient : undefined}\n isEdit={isEdit}\n setIsShowingConfirmModal={setIsShowingConfirmModal}\n isShowingConfirmModal={isShowingConfirmModal}\n setIsShowingModal={setIsShowingCreateClientModal}\n />\n <DialogBase\n open={isShowingVerification}\n onCancel={() => setIsShowingVerification(false)}\n title=\"Submit Verification\"\n content={\n <>\n <p>\n In order to verify an OAuth client please submit a request to the{' '}\n <Link\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n href=\"https://sagebionetworks.jira.com/servicedesk/customer/portal/9\"\n >\n Synapse Service Desk.\n </Link>\n </p>\n <b>Please list the following items in your request:</b>\n <ul>\n <li>Your name</li>\n <li>\n The ID of the client to be verified <br />\n </li>\n <li>A description of your application</li>\n </ul>\n {/* <p>\n Verification can take up to X weeks and we will notify you via X.\n </p> */}\n </>\n }\n />\n <OAuthAclEditorModal\n clientId={selectedClient?.client_id!}\n open={isShowingSharingSettings}\n onClose={() => setIsShowingSharingSettings(false)}\n />\n <WarningDialog\n open={isShowingSecretWarning}\n title={warningHeader}\n content={warningBody}\n onCancel={() => {\n setIsShowingSecretWarning(false)\n setSelectedClient(undefined)\n }}\n onConfirm={onShowSecret}\n confirmButtonColor=\"error\"\n confirmButtonText=\"Yes, Continue\"\n />\n {secret && (\n <DialogBase\n open={isShowingSecret}\n title=\"App Secret\"\n onCancel={() => {\n setIsShowingSecret(false)\n setSecret(undefined)\n }}\n content={\n <>\n <p>\n <b>This secret will not be able to be retrieved again.</b> If\n needed, in order to generate a new secret select Generate from\n the Client List.\n </p>\n <CopyToClipboardInput value={secret} inputWidth={'400px'} />\n </>\n }\n />\n )}\n </div>\n )\n}\n\nexport default OAuthManagement\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PageProgress.js","names":[],"sources":["../../../src/components/PageProgress/PageProgress.tsx"],"sourcesContent":["import { useEffect, useState, MouseEvent } from 'react'\nimport { Box, Button, LinearProgress } from '@mui/material'\n\nexport type PageProgressProps = {\n barColor: string\n barPercent: number\n backBtnLabel: string\n backBtnCallback?: () => void\n forwardBtnLabel: string\n forwardBtnCallback?: () => void\n forwardBtnActive: boolean\n}\n\nexport function PageProgress(props: PageProgressProps) {\n const {\n barColor,\n barPercent,\n backBtnLabel,\n forwardBtnLabel,\n forwardBtnActive,\n backBtnCallback,\n forwardBtnCallback,\n } = props\n const [progressPercent, setProgressPercent] = useState<number>(0)\n let mounted = true\n\n useEffect(() => {\n if (mounted) {\n setProgressPercent(barPercent)\n }\n return () => {\n mounted = false\n }\n }, [barPercent])\n\n const handleBackButtonClick = (e: MouseEvent) => {\n if (backBtnCallback) {\n backBtnCallback()\n }\n }\n\n const handleNextButtonClick = (e: MouseEvent) => {\n if (forwardBtnCallback && forwardBtnActive) {\n forwardBtnCallback()\n }\n }\n\n const buttonSx = {\n padding: '10px 120px',\n marginRight: '30px',\n }\n const progressSx = {\n backgroundColor: 'transparent',\n '& .MuiLinearProgress-bar': {\n backgroundColor: barColor,\n },\n height: '10px',\n }\n\n return (\n <section>\n <LinearProgress\n value={progressPercent}\n variant=\"determinate\"\n sx={progressSx}\n />\n <Box\n sx={{\n padding: '30px 0',\n textAlign: 'center',\n }}\n >\n <Button\n onClick={handleBackButtonClick}\n sx={buttonSx}\n variant=\"outlined\"\n color=\"primary\"\n >\n {backBtnLabel}\n </Button>\n <Button\n onClick={handleNextButtonClick}\n disabled={!forwardBtnActive}\n sx={buttonSx}\n variant=\"contained\"\n color=\"primary\"\n >\n {forwardBtnLabel}\n </Button>\n </Box>\n </section>\n )\n}\n\nexport default PageProgress\n"],"mappings":";;;;AAaA,SAAgB,EAAa,GAA0B;CACrD,IAAM,EACJ,aACA,eACA,iBACA,oBACA,qBACA,oBACA,0BACE,GACE,CAAC,GAAiB,KAAsB,EAAiB,EAAE,EAC7D,IAAU;AAEd,UACM,KACF,EAAmB,EAAW,QAEnB;AACX,MAAU;KAEX,CAAC,EAAW,CAAC;CAEhB,IAAM,KAAyB,MAAkB;AAC/C,EAAI,KACF,GAAiB;IAIf,KAAyB,MAAkB;AAC/C,EAAI,KAAsB,KACxB,GAAoB;IAIlB,IAAW;EACf,SAAS;EACT,aAAa;EACd;AASD,QACE,kBAAC,WAAD,EAAA,UAAA,CACE,kBAAC,GAAD;EACE,OAAO;EACP,SAAQ;EACR,
|
|
1
|
+
{"version":3,"file":"PageProgress.js","names":[],"sources":["../../../src/components/PageProgress/PageProgress.tsx"],"sourcesContent":["import { useEffect, useState, MouseEvent } from 'react'\nimport { Box, Button, LinearProgress } from '@mui/material'\n\nexport type PageProgressProps = {\n barColor: string\n barPercent: number\n backBtnLabel: string\n backBtnCallback?: () => void\n forwardBtnLabel: string\n forwardBtnCallback?: () => void\n forwardBtnActive: boolean\n}\n\nexport function PageProgress(props: PageProgressProps) {\n const {\n barColor,\n barPercent,\n backBtnLabel,\n forwardBtnLabel,\n forwardBtnActive,\n backBtnCallback,\n forwardBtnCallback,\n } = props\n const [progressPercent, setProgressPercent] = useState<number>(0)\n let mounted = true\n\n useEffect(() => {\n if (mounted) {\n setProgressPercent(barPercent)\n }\n return () => {\n mounted = false\n }\n }, [barPercent])\n\n const handleBackButtonClick = (e: MouseEvent) => {\n if (backBtnCallback) {\n backBtnCallback()\n }\n }\n\n const handleNextButtonClick = (e: MouseEvent) => {\n if (forwardBtnCallback && forwardBtnActive) {\n forwardBtnCallback()\n }\n }\n\n const buttonSx = {\n padding: '10px 120px',\n marginRight: '30px',\n }\n const progressSx = {\n backgroundColor: 'transparent',\n '& .MuiLinearProgress-bar': {\n backgroundColor: barColor,\n },\n height: '10px',\n }\n\n return (\n <section>\n <LinearProgress\n value={progressPercent}\n variant=\"determinate\"\n sx={progressSx}\n />\n <Box\n sx={{\n padding: '30px 0',\n textAlign: 'center',\n }}\n >\n <Button\n onClick={handleBackButtonClick}\n sx={buttonSx}\n variant=\"outlined\"\n color=\"primary\"\n >\n {backBtnLabel}\n </Button>\n <Button\n onClick={handleNextButtonClick}\n disabled={!forwardBtnActive}\n sx={buttonSx}\n variant=\"contained\"\n color=\"primary\"\n >\n {forwardBtnLabel}\n </Button>\n </Box>\n </section>\n )\n}\n\nexport default PageProgress\n"],"mappings":";;;;AAaA,SAAgB,EAAa,GAA0B;CACrD,IAAM,EACJ,aACA,eACA,iBACA,oBACA,qBACA,oBACA,0BACE,GACE,CAAC,GAAiB,KAAsB,EAAiB,EAAE,EAC7D,IAAU;AAEd,UACM,KACF,EAAmB,EAAW,QAEnB;AACX,MAAU;KAEX,CAAC,EAAW,CAAC;CAEhB,IAAM,KAAyB,MAAkB;AAC/C,EAAI,KACF,GAAiB;IAIf,KAAyB,MAAkB;AAC/C,EAAI,KAAsB,KACxB,GAAoB;IAIlB,IAAW;EACf,SAAS;EACT,aAAa;EACd;AASD,QACE,kBAAC,WAAD,EAAA,UAAA,CACE,kBAAC,GAAD;EACE,OAAO;EACP,SAAQ;EACR,IAAI;GAZR,iBAAiB;GACjB,4BAA4B,EAC1B,iBAAiB,GAClB;GACD,QAAQ;GAQA;EACJ,CAAA,EACF,kBAAC,GAAD;EACE,IAAI;GACF,SAAS;GACT,WAAW;GACZ;YAJH,CAME,kBAAC,GAAD;GACE,SAAS;GACT,IAAI;GACJ,SAAQ;GACR,OAAM;aAEL;GACM,CAAA,EACT,kBAAC,GAAD;GACE,SAAS;GACT,UAAU,CAAC;GACX,IAAI;GACJ,SAAQ;GACR,OAAM;aAEL;GACM,CAAA,CACL;IACE,EAAA,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DotPlot.js","names":[],"sources":["../../../src/components/Plot/DotPlot.tsx"],"sourcesContent":["import cloneDeep from 'lodash-es/cloneDeep'\nimport countBy from 'lodash-es/countBy'\nimport noop from 'lodash-es/noop'\nimport uniq from 'lodash-es/uniq'\nimport Plotly from 'plotly.js-basic-dist'\nimport { CSSProperties } from 'react'\nimport Plot from './Plot'\nimport { Dictionary, GraphItem, PlotStyle } from './types'\n\nexport type DotPlotProps = {\n plotData: GraphItem[]\n layoutConfig: Partial<Plotly.Layout>\n optionsConfig: Partial<Plotly.Config>\n label?: string\n style?: CSSProperties\n id: string\n isLegend?: boolean\n isXAxis?: boolean\n xMax?: number\n plotStyle?: PlotStyle\n markerSymbols?: Dictionary\n onClick?: (e: Readonly<Plotly.PlotMouseEvent>) => void\n}\n\ntype LayoutOptions = {\n isLegend: boolean\n isXAxis: boolean\n maxValue?: number\n backgroundColor?: string\n}\n\nfunction getLayout(\n dotPlotLayoutConfig: Partial<Plotly.Layout>,\n layoutOptions?: LayoutOptions,\n): Partial<Plotly.Layout> {\n const result = cloneDeep(dotPlotLayoutConfig)\n if (!layoutOptions) {\n return result\n }\n if (layoutOptions.backgroundColor) {\n result.plot_bgcolor = layoutOptions.backgroundColor\n }\n result.yaxis!.showgrid = false\n result.yaxis!.zeroline = true\n result.yaxis!.zerolinecolor = '#aeb5bc'\n result.yaxis!.showticklabels = false\n if (result.xaxis!.type === 'log') {\n result.xaxis!.tickformat = 'f'\n result.xaxis!.range = [-0.1, Math.log10(layoutOptions.maxValue!) + 0.1]\n } else {\n result.xaxis!.range = [\n (layoutOptions.maxValue! / 50) * -1,\n layoutOptions.maxValue! + 30,\n ]\n }\n result.xaxis!.visible = layoutOptions.isXAxis\n result.showlegend = layoutOptions.isLegend\n result.margin = {\n t: 0,\n b: layoutOptions.isXAxis ? 50 : 0,\n l: 0,\n r: 0,\n pad: 15,\n }\n let height = 40\n if (layoutOptions.isLegend) {\n height = 35\n result.margin.pad = 0\n result.xaxis = {\n visible: false,\n zeroline: false,\n showgrid: false,\n showline: false,\n range: [0, 1],\n }\n\n result.yaxis = {\n visible: false,\n showline: false,\n }\n }\n if (layoutOptions.isXAxis) {\n result.yaxis = {\n visible: false,\n showgrid: false,\n showline: false,\n }\n height = 50\n }\n\n result.height = height\n\n return result\n}\n\nfunction createArrayOfGroupValues(\n headers: string[],\n items: GraphItem[],\n): number[] {\n const result: number[] = new Array(headers.length)\n items.forEach(item => {\n const index = headers.indexOf(item.y)\n if (index !== -1) {\n result[index] = item.x\n }\n })\n return result\n}\n\n/**\n * Generates a sequence of n numbers centered around 0\n *\n * Examples:\n * if n is 4, the result would be [-1.5, -0.5, 0.5, 1.5]\n * if n is 5 the result would be [-2, -1, 0, 1, 2]\n * @param n\n */\nexport function generateCenteredSequence(n: number): number[] {\n const sequence: number[] = []\n const half = (n - 1) / 2\n for (let i = 0; i < n; i++) {\n sequence.push(i - half)\n }\n return sequence\n}\n\n/**\n * Returns a set of y values where\n * - if an x value is unique, the y value is 0\n * - if an x value is repeated, the y value is an offset from 0\n *\n * This has the effect of preventing overlapping points in a dot plot\n * @param xDataByGroup\n */\nexport function getYDataForDotPlotOffset(\n xDataByGroup: Record<string, number[]>,\n): Record<string, number[]> {\n const counts = countBy(xDataByGroup, val => val[0])\n\n const yDataByGroup: Record<string, number[]> = {}\n // keep track of how many times we have seen each duplicate value\n const seen: Record<number, number> = {}\n Object.keys(xDataByGroup).forEach(group => {\n const value = xDataByGroup[group][0]\n if (counts[value] === 1) {\n // The value is not duplicated by another group, so the y-value (vertical offset) is 0\n yDataByGroup[group] = [0]\n } else {\n // The value is duplicated by another group, so get an offset value that will be\n // - centered around 0\n // - unique for this item among all items with the same value\n if (seen[value] == undefined) {\n seen[value] = 0\n }\n const offsets = generateCenteredSequence(counts[value])\n const offset = offsets[seen[value]]\n\n yDataByGroup[group] = [offset]\n seen[value] = seen[value] + 1\n }\n })\n return yDataByGroup\n}\n\nfunction getPlotDataPoints(\n graphItems: GraphItem[],\n plotStyle: PlotStyle,\n ySorted?: string[],\n markerSymbols?: Dictionary,\n): Plotly.Data[] {\n const isFakeData = ySorted === undefined\n const groups = uniq(graphItems.map(item => item.group))\n const defaultSymbols = [\n 'y-down',\n 'triangle-up',\n 'cross-thin-open',\n 'triangle-up-open-dot',\n 'star-square-open',\n 'diamond-x',\n ]\n\n const xDataByGroup: Record<string, number[]> = groups.reduce(\n (prev, group) => {\n const xDataForGroup = isFakeData\n ? [-100] // fake datavalue outside of the bounds\n : createArrayOfGroupValues(\n ySorted,\n graphItems.filter(row => row.group === group),\n )\n return { ...prev, [group]: xDataForGroup }\n },\n {},\n )\n const yDataByGroup: Record<string, number[]> =\n getYDataForDotPlotOffset(xDataByGroup)\n\n const data: Plotly.Data[] = groups.map((group, i) => {\n const xData: number[] = xDataByGroup[group]\n const yData: number[] = yDataByGroup[group]\n return {\n type: 'scatter',\n x: xData,\n y: yData,\n text: [group],\n hovertemplate: `%{x} %{text}<extra></extra>`,\n mode: 'markers',\n name: group,\n marker: {\n color: plotStyle.markerFill,\n line: {\n color: plotStyle.markerLine,\n width: 1,\n },\n\n symbol: markerSymbols ? markerSymbols[group] : defaultSymbols[i],\n size: plotStyle.markerSize,\n },\n }\n })\n\n return data\n}\n\nconst DEFAULT_DOTPLOT_PLOTSTYLE: PlotStyle = {\n markerFill: '#515359',\n markerLine: '#515359',\n markerSize: 9,\n backgroundColor: 'transparent',\n}\nconst DEFAULT_DOTPLOT_STYLE: CSSProperties = {\n width: '100%',\n height: '100%',\n}\n\nfunction DotPlot({\n plotData,\n optionsConfig,\n layoutConfig,\n label,\n id,\n xMax,\n style = DEFAULT_DOTPLOT_STYLE,\n markerSymbols,\n plotStyle = DEFAULT_DOTPLOT_PLOTSTYLE,\n onClick,\n isLegend = false,\n isXAxis = false,\n}: DotPlotProps) {\n const pointsTypes = label ? [label] : undefined\n\n return (\n <Plot\n key={`dotPlot_${id}`}\n layout={getLayout(layoutConfig, {\n isLegend: isLegend,\n isXAxis: isXAxis,\n maxValue: xMax,\n backgroundColor: plotStyle.backgroundColor,\n })}\n style={style}\n data={getPlotDataPoints(plotData, plotStyle, pointsTypes, markerSymbols)}\n config={optionsConfig}\n onClick={e => (onClick ? onClick(e) : noop)}\n />\n )\n}\n\nexport default DotPlot\n"],"mappings":";;;;;;;AA+BA,SAAS,EACP,GACA,GACwB;CACxB,IAAM,IAAS,EAAU,EAAoB;AAC7C,KAAI,CAAC,EACH,QAAO;AAoBT,CAlBI,EAAc,oBAChB,EAAO,eAAe,EAAc,kBAEtC,EAAO,MAAO,WAAW,IACzB,EAAO,MAAO,WAAW,IACzB,EAAO,MAAO,gBAAgB,WAC9B,EAAO,MAAO,iBAAiB,IAC3B,EAAO,MAAO,SAAS,SACzB,EAAO,MAAO,aAAa,KAC3B,EAAO,MAAO,QAAQ,CAAC,KAAM,KAAK,MAAM,EAAc,SAAU,GAAG,GAAI,IAEvE,EAAO,MAAO,QAAQ,CACnB,EAAc,WAAY,KAAM,IACjC,EAAc,WAAY,GAC3B,EAEH,EAAO,MAAO,UAAU,EAAc,SACtC,EAAO,aAAa,EAAc,UAClC,EAAO,SAAS;EACd,GAAG;EACH,GAAG,EAAc,UAAU,KAAK;EAChC,GAAG;EACH,GAAG;EACH,KAAK;EACN;CACD,IAAI,IAAS;AA4Bb,QA3BI,EAAc,aAChB,IAAS,IACT,EAAO,OAAO,MAAM,GACpB,EAAO,QAAQ;EACb,SAAS;EACT,UAAU;EACV,UAAU;EACV,UAAU;EACV,OAAO,CAAC,GAAG,EAAE;EACd,EAED,EAAO,QAAQ;EACb,SAAS;EACT,UAAU;EACX,GAEC,EAAc,YAChB,EAAO,QAAQ;EACb,SAAS;EACT,UAAU;EACV,UAAU;EACX,EACD,IAAS,KAGX,EAAO,SAAS,GAET;;AAGT,SAAS,EACP,GACA,GACU;CACV,IAAM,IAAuB,MAAM,EAAQ,OAAO;AAOlD,QANA,EAAM,SAAQ,MAAQ;EACpB,IAAM,IAAQ,EAAQ,QAAQ,EAAK,EAAE;AACrC,EAAI,MAAU,OACZ,EAAO,KAAS,EAAK;GAEvB,EACK;;AAWT,SAAgB,EAAyB,GAAqB;CAC5D,IAAM,IAAqB,EAAE,EACvB,KAAQ,IAAI,KAAK;AACvB,MAAK,IAAI,IAAI,GAAG,IAAI,GAAG,IACrB,GAAS,KAAK,IAAI,EAAK;AAEzB,QAAO;;AAWT,SAAgB,EACd,GAC0B;CAC1B,IAAM,IAAS,EAAQ,IAAc,MAAO,EAAI,GAAG,EAE7C,IAAyC,EAAE,EAE3C,IAA+B,EAAE;AAoBvC,QAnBA,OAAO,KAAK,EAAa,CAAC,SAAQ,MAAS;EACzC,IAAM,IAAQ,EAAa,GAAO;AAClC,EAAI,EAAO,OAAW,IAEpB,EAAa,KAAS,CAAC,EAAE,IAKrB,EAAK,OACP,EAAK,KAAS,IAKhB,EAAa,KAAS,CAHN,EAAyB,EAAO,
|
|
1
|
+
{"version":3,"file":"DotPlot.js","names":[],"sources":["../../../src/components/Plot/DotPlot.tsx"],"sourcesContent":["import cloneDeep from 'lodash-es/cloneDeep'\nimport countBy from 'lodash-es/countBy'\nimport noop from 'lodash-es/noop'\nimport uniq from 'lodash-es/uniq'\nimport Plotly from 'plotly.js-basic-dist'\nimport { CSSProperties } from 'react'\nimport Plot from './Plot'\nimport { Dictionary, GraphItem, PlotStyle } from './types'\n\nexport type DotPlotProps = {\n plotData: GraphItem[]\n layoutConfig: Partial<Plotly.Layout>\n optionsConfig: Partial<Plotly.Config>\n label?: string\n style?: CSSProperties\n id: string\n isLegend?: boolean\n isXAxis?: boolean\n xMax?: number\n plotStyle?: PlotStyle\n markerSymbols?: Dictionary\n onClick?: (e: Readonly<Plotly.PlotMouseEvent>) => void\n}\n\ntype LayoutOptions = {\n isLegend: boolean\n isXAxis: boolean\n maxValue?: number\n backgroundColor?: string\n}\n\nfunction getLayout(\n dotPlotLayoutConfig: Partial<Plotly.Layout>,\n layoutOptions?: LayoutOptions,\n): Partial<Plotly.Layout> {\n const result = cloneDeep(dotPlotLayoutConfig)\n if (!layoutOptions) {\n return result\n }\n if (layoutOptions.backgroundColor) {\n result.plot_bgcolor = layoutOptions.backgroundColor\n }\n result.yaxis!.showgrid = false\n result.yaxis!.zeroline = true\n result.yaxis!.zerolinecolor = '#aeb5bc'\n result.yaxis!.showticklabels = false\n if (result.xaxis!.type === 'log') {\n result.xaxis!.tickformat = 'f'\n result.xaxis!.range = [-0.1, Math.log10(layoutOptions.maxValue!) + 0.1]\n } else {\n result.xaxis!.range = [\n (layoutOptions.maxValue! / 50) * -1,\n layoutOptions.maxValue! + 30,\n ]\n }\n result.xaxis!.visible = layoutOptions.isXAxis\n result.showlegend = layoutOptions.isLegend\n result.margin = {\n t: 0,\n b: layoutOptions.isXAxis ? 50 : 0,\n l: 0,\n r: 0,\n pad: 15,\n }\n let height = 40\n if (layoutOptions.isLegend) {\n height = 35\n result.margin.pad = 0\n result.xaxis = {\n visible: false,\n zeroline: false,\n showgrid: false,\n showline: false,\n range: [0, 1],\n }\n\n result.yaxis = {\n visible: false,\n showline: false,\n }\n }\n if (layoutOptions.isXAxis) {\n result.yaxis = {\n visible: false,\n showgrid: false,\n showline: false,\n }\n height = 50\n }\n\n result.height = height\n\n return result\n}\n\nfunction createArrayOfGroupValues(\n headers: string[],\n items: GraphItem[],\n): number[] {\n const result: number[] = new Array(headers.length)\n items.forEach(item => {\n const index = headers.indexOf(item.y)\n if (index !== -1) {\n result[index] = item.x\n }\n })\n return result\n}\n\n/**\n * Generates a sequence of n numbers centered around 0\n *\n * Examples:\n * if n is 4, the result would be [-1.5, -0.5, 0.5, 1.5]\n * if n is 5 the result would be [-2, -1, 0, 1, 2]\n * @param n\n */\nexport function generateCenteredSequence(n: number): number[] {\n const sequence: number[] = []\n const half = (n - 1) / 2\n for (let i = 0; i < n; i++) {\n sequence.push(i - half)\n }\n return sequence\n}\n\n/**\n * Returns a set of y values where\n * - if an x value is unique, the y value is 0\n * - if an x value is repeated, the y value is an offset from 0\n *\n * This has the effect of preventing overlapping points in a dot plot\n * @param xDataByGroup\n */\nexport function getYDataForDotPlotOffset(\n xDataByGroup: Record<string, number[]>,\n): Record<string, number[]> {\n const counts = countBy(xDataByGroup, val => val[0])\n\n const yDataByGroup: Record<string, number[]> = {}\n // keep track of how many times we have seen each duplicate value\n const seen: Record<number, number> = {}\n Object.keys(xDataByGroup).forEach(group => {\n const value = xDataByGroup[group][0]\n if (counts[value] === 1) {\n // The value is not duplicated by another group, so the y-value (vertical offset) is 0\n yDataByGroup[group] = [0]\n } else {\n // The value is duplicated by another group, so get an offset value that will be\n // - centered around 0\n // - unique for this item among all items with the same value\n if (seen[value] == undefined) {\n seen[value] = 0\n }\n const offsets = generateCenteredSequence(counts[value])\n const offset = offsets[seen[value]]\n\n yDataByGroup[group] = [offset]\n seen[value] = seen[value] + 1\n }\n })\n return yDataByGroup\n}\n\nfunction getPlotDataPoints(\n graphItems: GraphItem[],\n plotStyle: PlotStyle,\n ySorted?: string[],\n markerSymbols?: Dictionary,\n): Plotly.Data[] {\n const isFakeData = ySorted === undefined\n const groups = uniq(graphItems.map(item => item.group))\n const defaultSymbols = [\n 'y-down',\n 'triangle-up',\n 'cross-thin-open',\n 'triangle-up-open-dot',\n 'star-square-open',\n 'diamond-x',\n ]\n\n const xDataByGroup: Record<string, number[]> = groups.reduce(\n (prev, group) => {\n const xDataForGroup = isFakeData\n ? [-100] // fake datavalue outside of the bounds\n : createArrayOfGroupValues(\n ySorted,\n graphItems.filter(row => row.group === group),\n )\n return { ...prev, [group]: xDataForGroup }\n },\n {},\n )\n const yDataByGroup: Record<string, number[]> =\n getYDataForDotPlotOffset(xDataByGroup)\n\n const data: Plotly.Data[] = groups.map((group, i) => {\n const xData: number[] = xDataByGroup[group]\n const yData: number[] = yDataByGroup[group]\n return {\n type: 'scatter',\n x: xData,\n y: yData,\n text: [group],\n hovertemplate: `%{x} %{text}<extra></extra>`,\n mode: 'markers',\n name: group,\n marker: {\n color: plotStyle.markerFill,\n line: {\n color: plotStyle.markerLine,\n width: 1,\n },\n\n symbol: markerSymbols ? markerSymbols[group] : defaultSymbols[i],\n size: plotStyle.markerSize,\n },\n }\n })\n\n return data\n}\n\nconst DEFAULT_DOTPLOT_PLOTSTYLE: PlotStyle = {\n markerFill: '#515359',\n markerLine: '#515359',\n markerSize: 9,\n backgroundColor: 'transparent',\n}\nconst DEFAULT_DOTPLOT_STYLE: CSSProperties = {\n width: '100%',\n height: '100%',\n}\n\nfunction DotPlot({\n plotData,\n optionsConfig,\n layoutConfig,\n label,\n id,\n xMax,\n style = DEFAULT_DOTPLOT_STYLE,\n markerSymbols,\n plotStyle = DEFAULT_DOTPLOT_PLOTSTYLE,\n onClick,\n isLegend = false,\n isXAxis = false,\n}: DotPlotProps) {\n const pointsTypes = label ? [label] : undefined\n\n return (\n <Plot\n key={`dotPlot_${id}`}\n layout={getLayout(layoutConfig, {\n isLegend: isLegend,\n isXAxis: isXAxis,\n maxValue: xMax,\n backgroundColor: plotStyle.backgroundColor,\n })}\n style={style}\n data={getPlotDataPoints(plotData, plotStyle, pointsTypes, markerSymbols)}\n config={optionsConfig}\n onClick={e => (onClick ? onClick(e) : noop)}\n />\n )\n}\n\nexport default DotPlot\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Plot.js","names":[],"sources":["../../../src/components/Plot/Plot.tsx"],"sourcesContent":["import { PlotParams } from 'react-plotly.js'\nimport createPlotlyComponent from './safe-react-plotly-factory'\nimport { lazy, Suspense } from 'react'\n\n// Lazy-load plotly.js since it is very large!\nconst safeESModule = <T,>(a: T | { default: T }): T => {\n const b = a as any\n return b.__esModule || b[Symbol.toStringTag] === 'Module' ? b.default : b\n}\n\nconst LazyLoadedPlot = lazy(async () => {\n const Plotly = await import('plotly.js-basic-dist')\n const plotly = safeESModule(Plotly)\n return { default: createPlotlyComponent(plotly) }\n})\n\n/**\n * Wrapper around react-plotly.js, lazy loads the plotly.js library.\n * @param props\n * @constructor\n */\nexport function Plot(props: PlotParams) {\n return (\n <Suspense>\n <LazyLoadedPlot {...props} />\n </Suspense>\n )\n}\n\nexport default Plot\n"],"mappings":";;;;AAKA,IAAM,KAAoB,MAA6B;CACrD,IAAM,IAAI;AACV,QAAO,EAAE,cAAc,EAAE,OAAO,iBAAiB,WAAW,EAAE,UAAU;GAGpE,IAAiB,EAAK,aAGnB,EAAE,SAAS,EADH,
|
|
1
|
+
{"version":3,"file":"Plot.js","names":[],"sources":["../../../src/components/Plot/Plot.tsx"],"sourcesContent":["import { PlotParams } from 'react-plotly.js'\nimport createPlotlyComponent from './safe-react-plotly-factory'\nimport { lazy, Suspense } from 'react'\n\n// Lazy-load plotly.js since it is very large!\nconst safeESModule = <T,>(a: T | { default: T }): T => {\n const b = a as any\n return b.__esModule || b[Symbol.toStringTag] === 'Module' ? b.default : b\n}\n\nconst LazyLoadedPlot = lazy(async () => {\n const Plotly = await import('plotly.js-basic-dist')\n const plotly = safeESModule(Plotly)\n return { default: createPlotlyComponent(plotly) }\n})\n\n/**\n * Wrapper around react-plotly.js, lazy loads the plotly.js library.\n * @param props\n * @constructor\n */\nexport function Plot(props: PlotParams) {\n return (\n <Suspense>\n <LazyLoadedPlot {...props} />\n </Suspense>\n )\n}\n\nexport default Plot\n"],"mappings":";;;;AAKA,IAAM,KAAoB,MAA6B;CACrD,IAAM,IAAI;AACV,QAAO,EAAE,cAAc,EAAE,OAAO,iBAAiB,WAAW,EAAE,UAAU;GAGpE,IAAiB,EAAK,aAGnB,EAAE,SAAS,EADH,EAAa,MADP,OAAO,wBAEY,CAAO,EAAE,EACjD;AAOF,SAAgB,EAAK,GAAmB;AACtC,QACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAgB,GAAI,GAAS,CAAA,EACpB,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SynapsePlot.js","names":[],"sources":["../../../src/components/Plot/SynapsePlot.tsx"],"sourcesContent":["import React from 'react'\nimport { useGetFullTableQueryResults } from '@/synapse-queries'\nimport { SynapseConstants } from '@/utils'\nimport { parseEntityIdFromSqlStatement } from '@/utils/functions/SqlFunctions'\nimport { Skeleton } from '@mui/material'\nimport {\n FacetColumnRequest,\n QueryBundleRequest,\n QueryFilter,\n Row,\n} from '@sage-bionetworks/synapse-types'\nimport Plotly, { AxisType, PlotType } from 'plotly.js-basic-dist'\nimport { QueryContextType } from '../QueryContext'\nimport { QueryWrapperSynapsePlotRowClickEvent } from '../QueryWrapperPlotNav/QueryWrapperSynapsePlot'\nimport Plot from './Plot'\nimport './SynapsePlot.scss'\n\nexport type SynapsePlotWidgetParams = {\n query: string //sql string\n title?: string //plot title\n xtitle?: Plotly.LayoutAxis['title'] // x-axis title\n ytitle?: Plotly.LayoutAxis['title'] // y-axis title\n type: PlotType\n xaxistype?: AxisType\n showlegend?: Plotly.Layout['showlegend'] // sets the legend visibility\n horizontal?: boolean // sets the if a bar chart should be horizontal or vertical\n barmode?: Plotly.Layout['barmode'] // Plotly barmode\n displayModeBar?: Plotly.Config['displayModeBar'] // sets the modebar visibility\n hoverinfo?: Plotly.PlotData['hoverinfo'] // sets the hover info\n}\n\n// QueryWrapperPlotNav customPlot parameters, undefined otherwise\nexport type QueryWrapperPlotNavCustomPlotParams = {\n selectedFacets: FacetColumnRequest[]\n additionalFilters: QueryFilter[]\n onCustomPlotClick?: (event: QueryWrapperSynapsePlotRowClickEvent) => void\n queryContext?: QueryContextType\n}\nexport type SynapsePlotProps = {\n synapsePlotWidgetParams: SynapsePlotWidgetParams\n customPlotParams?: QueryWrapperPlotNavCustomPlotParams\n}\n\nexport const SynapsePlot = (props: SynapsePlotProps): React.ReactNode => {\n const { query } = props.synapsePlotWidgetParams\n const { selectedFacets, additionalFilters, onCustomPlotClick, queryContext } =\n props.customPlotParams ?? {}\n const queryRequest: QueryBundleRequest = {\n concreteType: 'org.sagebionetworks.repo.model.table.QueryBundleRequest',\n partMask: SynapseConstants.BUNDLE_MASK_QUERY_RESULTS,\n entityId: parseEntityIdFromSqlStatement(query),\n query: {\n sql: query,\n selectedFacets,\n additionalFilters,\n },\n }\n const { data: queryData, isLoading } =\n useGetFullTableQueryResults(queryRequest)\n if (isLoading) {\n return <Skeleton width={'100%'} height={'200px'} />\n }\n if (!queryData) {\n return <></>\n }\n\n const {\n title,\n xtitle,\n ytitle,\n type,\n xaxistype,\n showlegend,\n barmode,\n horizontal,\n displayModeBar,\n hoverinfo,\n } = props.synapsePlotWidgetParams\n\n const config: Partial<Plotly.Config> = {\n displayModeBar,\n }\n const layout: Partial<Plotly.Layout> = {\n showlegend: showlegend,\n title,\n barmode: barmode,\n }\n if (xtitle) {\n layout.xaxis = {\n title: xtitle,\n }\n }\n if (xaxistype) {\n layout.xaxis = {\n ...layout.xaxis,\n type: xaxistype,\n }\n }\n if (ytitle) {\n layout.yaxis = {\n title: ytitle,\n }\n }\n // init plot_data\n const plotData: Partial<Plotly.PlotData>[] = []\n const orientation = horizontal ? 'h' : 'v'\n const headers = queryData.queryResult?.queryResults.headers ?? []\n const rows = queryData.queryResult?.queryResults.rows ?? []\n if (headers.length == 0 || rows.length == 0) {\n return <></>\n }\n for (let i = 0; i < headers.length - 1; i += 1) {\n // make an entry for each set of data points\n plotData[i] = {\n orientation,\n name: headers[i + 1].name,\n type: type,\n x: [],\n y: [],\n customdata: [],\n ...(hoverinfo !== undefined && { hoverinfo }),\n }\n }\n // grab all the data\n for (const row of rows) {\n for (let j = 1; j < row.values.length; j += 1) {\n // create pairs of data\n const rowValues = row.values\n const xArray = plotData[j - 1].x as Plotly.Datum[]\n const yArray = plotData[j - 1].y as Plotly.Datum[]\n const customdata = plotData[j - 1].customdata as Plotly.Datum[]\n\n xArray.push(horizontal ? rowValues[j] : rowValues[0])\n yArray.push(horizontal ? rowValues[0] : rowValues[j])\n customdata.push(JSON.stringify(row))\n }\n }\n let onPlotClick:\n | ((event: Readonly<Plotly.PlotMouseEvent>) => void)\n | undefined\n if (onCustomPlotClick) {\n onPlotClick = eventData => {\n const selectedRow = JSON.parse(\n eventData.points[0].customdata as string,\n ) as Row\n onCustomPlotClick({\n row: selectedRow,\n queryContext,\n })\n }\n }\n\n return (\n <Plot\n style={{ width: '100%', height: '450px' }}\n className={onPlotClick ? 'SynapsePlot--clickable' : undefined}\n layout={layout}\n data={plotData}\n config={config}\n onClick={onPlotClick}\n />\n )\n}\n\nexport default SynapsePlot\n"],"mappings":";;;;;;;;;;;AA2CA,IAAa,KAAe,MAA6C;CACvE,IAAM,EAAE,aAAU,EAAM,yBAClB,EAAE,mBAAgB,sBAAmB,sBAAmB,oBAC5D,EAAM,oBAAoB,EAAE,EAWxB,EAAE,MAAM,GAAW,iBACvB,
|
|
1
|
+
{"version":3,"file":"SynapsePlot.js","names":[],"sources":["../../../src/components/Plot/SynapsePlot.tsx"],"sourcesContent":["import React from 'react'\nimport { useGetFullTableQueryResults } from '@/synapse-queries'\nimport { SynapseConstants } from '@/utils'\nimport { parseEntityIdFromSqlStatement } from '@/utils/functions/SqlFunctions'\nimport { Skeleton } from '@mui/material'\nimport {\n FacetColumnRequest,\n QueryBundleRequest,\n QueryFilter,\n Row,\n} from '@sage-bionetworks/synapse-types'\nimport Plotly, { AxisType, PlotType } from 'plotly.js-basic-dist'\nimport { QueryContextType } from '../QueryContext'\nimport { QueryWrapperSynapsePlotRowClickEvent } from '../QueryWrapperPlotNav/QueryWrapperSynapsePlot'\nimport Plot from './Plot'\nimport './SynapsePlot.scss'\n\nexport type SynapsePlotWidgetParams = {\n query: string //sql string\n title?: string //plot title\n xtitle?: Plotly.LayoutAxis['title'] // x-axis title\n ytitle?: Plotly.LayoutAxis['title'] // y-axis title\n type: PlotType\n xaxistype?: AxisType\n showlegend?: Plotly.Layout['showlegend'] // sets the legend visibility\n horizontal?: boolean // sets the if a bar chart should be horizontal or vertical\n barmode?: Plotly.Layout['barmode'] // Plotly barmode\n displayModeBar?: Plotly.Config['displayModeBar'] // sets the modebar visibility\n hoverinfo?: Plotly.PlotData['hoverinfo'] // sets the hover info\n}\n\n// QueryWrapperPlotNav customPlot parameters, undefined otherwise\nexport type QueryWrapperPlotNavCustomPlotParams = {\n selectedFacets: FacetColumnRequest[]\n additionalFilters: QueryFilter[]\n onCustomPlotClick?: (event: QueryWrapperSynapsePlotRowClickEvent) => void\n queryContext?: QueryContextType\n}\nexport type SynapsePlotProps = {\n synapsePlotWidgetParams: SynapsePlotWidgetParams\n customPlotParams?: QueryWrapperPlotNavCustomPlotParams\n}\n\nexport const SynapsePlot = (props: SynapsePlotProps): React.ReactNode => {\n const { query } = props.synapsePlotWidgetParams\n const { selectedFacets, additionalFilters, onCustomPlotClick, queryContext } =\n props.customPlotParams ?? {}\n const queryRequest: QueryBundleRequest = {\n concreteType: 'org.sagebionetworks.repo.model.table.QueryBundleRequest',\n partMask: SynapseConstants.BUNDLE_MASK_QUERY_RESULTS,\n entityId: parseEntityIdFromSqlStatement(query),\n query: {\n sql: query,\n selectedFacets,\n additionalFilters,\n },\n }\n const { data: queryData, isLoading } =\n useGetFullTableQueryResults(queryRequest)\n if (isLoading) {\n return <Skeleton width={'100%'} height={'200px'} />\n }\n if (!queryData) {\n return <></>\n }\n\n const {\n title,\n xtitle,\n ytitle,\n type,\n xaxistype,\n showlegend,\n barmode,\n horizontal,\n displayModeBar,\n hoverinfo,\n } = props.synapsePlotWidgetParams\n\n const config: Partial<Plotly.Config> = {\n displayModeBar,\n }\n const layout: Partial<Plotly.Layout> = {\n showlegend: showlegend,\n title,\n barmode: barmode,\n }\n if (xtitle) {\n layout.xaxis = {\n title: xtitle,\n }\n }\n if (xaxistype) {\n layout.xaxis = {\n ...layout.xaxis,\n type: xaxistype,\n }\n }\n if (ytitle) {\n layout.yaxis = {\n title: ytitle,\n }\n }\n // init plot_data\n const plotData: Partial<Plotly.PlotData>[] = []\n const orientation = horizontal ? 'h' : 'v'\n const headers = queryData.queryResult?.queryResults.headers ?? []\n const rows = queryData.queryResult?.queryResults.rows ?? []\n if (headers.length == 0 || rows.length == 0) {\n return <></>\n }\n for (let i = 0; i < headers.length - 1; i += 1) {\n // make an entry for each set of data points\n plotData[i] = {\n orientation,\n name: headers[i + 1].name,\n type: type,\n x: [],\n y: [],\n customdata: [],\n ...(hoverinfo !== undefined && { hoverinfo }),\n }\n }\n // grab all the data\n for (const row of rows) {\n for (let j = 1; j < row.values.length; j += 1) {\n // create pairs of data\n const rowValues = row.values\n const xArray = plotData[j - 1].x as Plotly.Datum[]\n const yArray = plotData[j - 1].y as Plotly.Datum[]\n const customdata = plotData[j - 1].customdata as Plotly.Datum[]\n\n xArray.push(horizontal ? rowValues[j] : rowValues[0])\n yArray.push(horizontal ? rowValues[0] : rowValues[j])\n customdata.push(JSON.stringify(row))\n }\n }\n let onPlotClick:\n | ((event: Readonly<Plotly.PlotMouseEvent>) => void)\n | undefined\n if (onCustomPlotClick) {\n onPlotClick = eventData => {\n const selectedRow = JSON.parse(\n eventData.points[0].customdata as string,\n ) as Row\n onCustomPlotClick({\n row: selectedRow,\n queryContext,\n })\n }\n }\n\n return (\n <Plot\n style={{ width: '100%', height: '450px' }}\n className={onPlotClick ? 'SynapsePlot--clickable' : undefined}\n layout={layout}\n data={plotData}\n config={config}\n onClick={onPlotClick}\n />\n )\n}\n\nexport default SynapsePlot\n"],"mappings":";;;;;;;;;;;AA2CA,IAAa,KAAe,MAA6C;CACvE,IAAM,EAAE,aAAU,EAAM,yBAClB,EAAE,mBAAgB,sBAAmB,sBAAmB,oBAC5D,EAAM,oBAAoB,EAAE,EAWxB,EAAE,MAAM,GAAW,iBACvB,EAA4B;EAV5B,cAAc;EACd,UAAU;EACV,UAAU,EAA8B,EAAM;EAC9C,OAAO;GACL,KAAK;GACL;GACA;GACD;EAG2B,CAAa;AAC3C,KAAI,EACF,QAAO,kBAAC,GAAD;EAAU,OAAO;EAAQ,QAAQ;EAAW,CAAA;AAErD,KAAI,CAAC,EACH,QAAO,kBAAA,GAAA,EAAK,CAAA;CAGd,IAAM,EACJ,UACA,WACA,WACA,SACA,cACA,eACA,YACA,eACA,mBACA,iBACE,EAAM,yBAEJ,IAAiC,EACrC,mBACD,EACK,IAAiC;EACzB;EACZ;EACS;EACV;AAYD,CAXI,MACF,EAAO,QAAQ,EACb,OAAO,GACR,GAEC,MACF,EAAO,QAAQ;EACb,GAAG,EAAO;EACV,MAAM;EACP,GAEC,MACF,EAAO,QAAQ,EACb,OAAO,GACR;CAGH,IAAM,IAAuC,EAAE,EACzC,IAAc,IAAa,MAAM,KACjC,IAAU,EAAU,aAAa,aAAa,WAAW,EAAE,EAC3D,IAAO,EAAU,aAAa,aAAa,QAAQ,EAAE;AAC3D,KAAI,EAAQ,UAAU,KAAK,EAAK,UAAU,EACxC,QAAO,kBAAA,GAAA,EAAK,CAAA;AAEd,MAAK,IAAI,IAAI,GAAG,IAAI,EAAQ,SAAS,GAAG,KAAK,EAE3C,GAAS,KAAK;EACZ;EACA,MAAM,EAAQ,IAAI,GAAG;EACf;EACN,GAAG,EAAE;EACL,GAAG,EAAE;EACL,YAAY,EAAE;EACd,GAAI,MAAc,KAAA,KAAa,EAAE,cAAW;EAC7C;AAGH,MAAK,IAAM,KAAO,EAChB,MAAK,IAAI,IAAI,GAAG,IAAI,EAAI,OAAO,QAAQ,KAAK,GAAG;EAE7C,IAAM,IAAY,EAAI,QAChB,IAAS,EAAS,IAAI,GAAG,GACzB,IAAS,EAAS,IAAI,GAAG,GACzB,IAAa,EAAS,IAAI,GAAG;AAInC,EAFA,EAAO,KAAK,IAAa,EAAU,KAAK,EAAU,GAAG,EACrD,EAAO,KAAK,IAAa,EAAU,KAAK,EAAU,GAAG,EACrD,EAAW,KAAK,KAAK,UAAU,EAAI,CAAC;;CAGxC,IAAI;AAeJ,QAZI,MACF,KAAc,MAAa;AAIzB,IAAkB;GAChB,KAJkB,KAAK,MACvB,EAAU,OAAO,GAAG,WAGf;GACL;GACD,CAAC;KAKJ,kBAAC,GAAD;EACE,OAAO;GAAE,OAAO;GAAQ,QAAQ;GAAS;EACzC,WAAW,IAAc,2BAA2B,KAAA;EAC5C;EACR,MAAM;EACE;EACR,SAAS;EACT,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ThemesPlot.js","names":[],"sources":["../../../src/components/Plot/ThemesPlot.tsx"],"sourcesContent":["import { getFullQueryTableResults } from '@/synapse-client'\nimport { SynapseConstants, useSynapseContext } from '@/utils'\nimport { resultToJson } from '@/utils/functions'\nimport { unCamelCase } from '@/utils/functions/unCamelCase'\nimport { Tooltip } from '@mui/material'\nimport {\n QueryBundleRequest,\n QueryResultBundle,\n RowSet,\n} from '@sage-bionetworks/synapse-types'\nimport Plotly from 'plotly.js-basic-dist'\nimport { useEffect, useState } from 'react'\nimport { RequiredKeysOf } from 'type-fest'\nimport loadingScreen from '../LoadingScreen/LoadingScreen'\nimport BarPlot from './BarPlot'\nimport DotPlot from './DotPlot'\nimport {\n BarPlotColors,\n ClickCallbackParams,\n GraphItem,\n PlotProps,\n} from './types'\nimport first from 'lodash-es/first'\nimport orderBy from 'lodash-es/orderBy'\nimport cloneDeep from 'lodash-es/cloneDeep'\n\nexport type ThemesPlotProps = {\n onPointClick: ({ facetValue, type, event }: ClickCallbackParams) => void\n onIndividualThemeBarPlotPointClick?: ({\n facetValue,\n type,\n event,\n }: ClickCallbackParams) => void\n dotPlot: PlotProps\n topBarPlot: PlotProps\n sideBarPlot: PlotProps\n dotPlotYAxisLabel?: string\n}\n\ntype TotalsGroupByY = { y: string; count: number }\ntype TotalsGroupByGroup = { group: string; count: number }\n\nconst optionsConfig: Partial<Plotly.Config> = {\n displayModeBar: false,\n responsive: true,\n scrollZoom: false,\n editable: false,\n autosizable: true,\n}\n\nconst dotPlotLayoutConfig: Partial<Plotly.Layout> = {\n showlegend: true,\n dragmode: false,\n legend: {\n font: {\n size: 11,\n },\n\n y: 1.1,\n xanchor: 'right',\n x: 1,\n\n orientation: 'h',\n },\n xaxis: {\n visible: true,\n fixedrange: true,\n zeroline: false,\n showgrid: false,\n showline: true,\n linecolor: '#ddd', //bottom line\n autotick: true,\n ticks: 'outside',\n tickcolor: '#ddd',\n type: 'log',\n },\n\n yaxis: {\n fixedrange: true,\n zeroline: false,\n gridcolor: '#ddd', //horizontal lines\n automargin: true,\n },\n\n margin: {\n pad: 20,\n },\n hovermode: 'closest',\n}\n\nconst barLayoutConfig: Partial<Plotly.Layout> = {\n barmode: 'stack',\n showlegend: false,\n dragmode: false,\n hovermode: 'closest',\n yaxis: { visible: false, fixedrange: true },\n margin: {\n l: 0,\n r: 0,\n b: 0,\n t: 0,\n pad: 0,\n },\n}\n\nfunction fetchData(\n token: string,\n { xField, yField, groupField, entityId, whereClause, infoField }: PlotProps,\n): Promise<RowSet> {\n const sql = `SELECT ${xField} as \"x\", ${yField} as \"y\", ${\n infoField ? infoField + ' as \"info\", ' : ''\n } ${groupField} as \"group\"\n FROM ${entityId} ${whereClause ? ' WHERE ' + whereClause : ''}`\n\n const queryRequest: QueryBundleRequest = {\n concreteType: 'org.sagebionetworks.repo.model.table.QueryBundleRequest',\n partMask: SynapseConstants.BUNDLE_MASK_QUERY_RESULTS,\n entityId: entityId,\n query: {\n sql: sql,\n },\n }\n\n return getFullQueryTableResults(queryRequest, token).then(\n (data: QueryResultBundle) => {\n return data.queryResult!.queryResults\n },\n )\n}\n\nfunction getTotalsByProp<T>(\n data: GraphItem[],\n prop: RequiredKeysOf<GraphItem>,\n): T[] {\n const resultObject = data.reduce((res: Record<string, number>, obj) => {\n res[obj[prop]] =\n (obj[prop] in res ? Number(res[obj[prop]]) : 0) + Number(obj.x)\n return res\n }, {})\n const result: T[] = []\n for (const property in resultObject) {\n result.push({\n [prop]: property,\n count: resultObject[property],\n } as unknown as T)\n }\n return result\n}\n\nconst getClickTargetData = (\n e: Plotly.PlotMouseEvent,\n swap: boolean,\n): ClickCallbackParams => {\n const pointData = e.points[0].data\n\n let facetValue = pointData.y[0] as string\n let type = pointData.name\n\n if (swap) {\n ;[facetValue, type] = [type, facetValue]\n }\n return { facetValue, type, event: e.event }\n}\n\nconst renderTopBarLegend = (\n colors: BarPlotColors | undefined,\n xLabels: string[],\n) => (\n <div className=\"ThemesPlot__barPlotLegend\">\n {xLabels.map((item, i) => (\n <div style={{ float: 'left' }} key={`topBar_${i}`}>\n <div\n className=\"ThemesPlot__barPlotLegend__label\"\n key=\"topBar_label\"\n style={{\n backgroundColor: `${colors ? colors[item] : 'transparent'}`,\n }}\n ></div>\n <div className=\"ThemesPlot__barPlotLegend__graph\" key=\"topBar_graph\">\n {item}\n </div>{' '}\n </div>\n ))}\n </div>\n)\n\nconst fadeColors = (colors: { [key: string]: string }, opacity: string) => {\n for (const key in colors) {\n colors[key] = colors[key]\n .replace(',1)', `, ${opacity})`)\n .replace(',1.0)', `, ${opacity})`)\n }\n return colors\n}\n\nconst getTooltip = (data: GraphItem[], filter: string) => {\n return first(data.filter(item => item.y === filter).map(item => item.info))\n}\n\nexport function ThemesPlot({\n dotPlot,\n topBarPlot,\n sideBarPlot,\n onPointClick,\n onIndividualThemeBarPlotPointClick,\n dotPlotYAxisLabel = 'Research Themes',\n}: ThemesPlotProps) {\n const { accessToken } = useSynapseContext()\n const [isLoaded, setIsLoaded] = useState(false)\n const [dotPlotQueryData, setDotPlotQueryData] = useState<GraphItem[]>([])\n const [topBarPlotData, setTopBarQueryData] = useState<GraphItem[]>([])\n const [sideBarPlotData, setSideBarQueryData] = useState<GraphItem[]>([])\n\n useEffect(() => {\n const dotPlotData = fetchData(accessToken!, dotPlot)\n const topBarPlotData = fetchData(accessToken!, topBarPlot)\n const sideBarPlotData = fetchData(accessToken!, sideBarPlot)\n Promise.all([dotPlotData, topBarPlotData, sideBarPlotData])\n .then(result => {\n setDotPlotQueryData(\n resultToJson(\n result[0].headers,\n result[0].rows,\n ) as unknown as GraphItem[],\n )\n setTopBarQueryData(\n resultToJson(\n result[1].headers,\n result[1].rows,\n ) as unknown as GraphItem[],\n )\n setSideBarQueryData(\n resultToJson(\n result[2].headers,\n result[2].rows,\n ) as unknown as GraphItem[],\n )\n setIsLoaded(true)\n })\n .catch(err => {\n throw err\n })\n return () => {}\n }, [accessToken, dotPlot, topBarPlot, sideBarPlot])\n let yLabelsForDotPlot: string[] = []\n let xLabelsForTopBarPlot: string[] = []\n let xMaxForDotPlot = 0\n let topBarPlotDataSorted: TotalsGroupByY[] = []\n let totalsByDotPlotY: TotalsGroupByY[] = []\n if (isLoaded) {\n totalsByDotPlotY = getTotalsByProp(sideBarPlotData, 'y')\n yLabelsForDotPlot = totalsByDotPlotY\n .sort((a, b) => b.count - a.count)\n .map(item => item.y)\n xMaxForDotPlot = Math.max(...dotPlotQueryData.map(item => Number(item.x)))\n topBarPlotDataSorted = orderBy(getTotalsByProp(topBarPlotData, 'y'), ['y'])\n xLabelsForTopBarPlot = orderBy(\n getTotalsByProp<TotalsGroupByGroup>(topBarPlotData, 'group'),\n ['group'],\n ).map(item => item.group)\n }\n\n return (\n <>\n {!isLoaded && loadingScreen}\n\n {isLoaded && (\n <div className=\"ThemesPlot\">\n <div className=\"ThemesPlot__dotPlotLegend\">\n <DotPlot\n id=\"head\"\n plotData={dotPlotQueryData}\n isLegend={true}\n markerSymbols={dotPlot.markerSymbols}\n style={{ width: '100%', height: '100%' }}\n layoutConfig={dotPlotLayoutConfig}\n optionsConfig={{\n ...optionsConfig,\n responsive: true,\n staticPlot: true,\n }}\n plotStyle={{\n ...dotPlot.plotStyle!,\n backgroundColor: 'transparent',\n }}\n ></DotPlot>\n </div>\n {topBarPlot.colors &&\n renderTopBarLegend(topBarPlot.colors, xLabelsForTopBarPlot)}\n {topBarPlotDataSorted.map((item, i) => (\n <div className=\"ThemesPlot__topBarPlot\" key={`topBarDiv_${i}`}>\n <div className=\"ThemesPlot__topBarPlot__label\">\n {item.count} {unCamelCase(item.y)}\n </div>\n <div className=\"ThemesPlot__topBarPlot__plot\">\n <BarPlot\n style={{ width: '100%', height: '100%' }}\n layoutConfig={cloneDeep(barLayoutConfig)}\n optionsConfig={{ ...optionsConfig }}\n plotData={topBarPlotData}\n isTop={true}\n label={item.y}\n xMax={item.count}\n onClick={(e: any) =>\n onPointClick(getClickTargetData(e, true))\n }\n colors={\n // we are not actually fading colors for now. But keeping implemenation in case it changes\n i % 2 === 0\n ? topBarPlot.colors\n : fadeColors({ ...topBarPlot.colors }, '1')\n }\n />\n </div>\n </div>\n ))}\n <div style={{ display: 'flex', position: 'relative' }}>\n <div className=\"ThemesPlot__dotPlotYLabel\">{dotPlotYAxisLabel}</div>\n <div className=\"ThemesPlot__dotPlot\">\n {yLabelsForDotPlot.map((label, i) => (\n <div\n key={`plotDiv_${+i}`}\n className=\"ThemesPlot__dotPlot__row\"\n style={{\n backgroundColor: dotPlot.plotStyle?.backgroundColor,\n }}\n >\n <div className=\"ThemesPlot__dotPlot__barColumn\">\n <Tooltip\n title={`${getTooltip(dotPlotQueryData, label)} `}\n placement={'right'}\n >\n <div>\n <span className=\"ThemesPlot__dotPlot__themeLabel\">\n {label}\n </span>\n <br />\n <span className=\"ThemesPlot__dotPlot__countLabel\">\n {totalsByDotPlotY[i].count} {sideBarPlot.countLabel}\n </span>\n <br />\n <BarPlot\n style={{ width: '100%' }}\n layoutConfig={barLayoutConfig}\n optionsConfig={optionsConfig}\n plotData={sideBarPlotData}\n isTop={false}\n // PORTALS-3061: No longer use a global x max for the side bar (where the bar size of 1 grant is consistent),\n // Instead, each bar chart is independent (the size of 1 grant differs across bar charts).\n xMax={totalsByDotPlotY[i].count}\n label={label}\n colors={fadeColors({ ...topBarPlot.colors }, '1')}\n onClick={(e: any) => {\n if (onIndividualThemeBarPlotPointClick) {\n onIndividualThemeBarPlotPointClick(\n getClickTargetData(e, false),\n )\n }\n }}\n />\n </div>\n </Tooltip>\n </div>\n <div className=\"ThemesPlot__dotPlot__dotPlotColumn\">\n <div\n style={{\n width: '100%',\n backgroundColor: dotPlot.plotStyle?.backgroundColor,\n }}\n >\n <DotPlot\n id={`${i}`}\n onClick={(e: any) => {\n const { type, event } = getClickTargetData(e, false)\n onPointClick({ facetValue: label, type, event })\n }}\n plotData={dotPlotQueryData}\n plotStyle={dotPlot.plotStyle}\n markerSymbols={dotPlot.markerSymbols}\n xMax={xMaxForDotPlot}\n label={label}\n layoutConfig={dotPlotLayoutConfig}\n optionsConfig={{\n ...optionsConfig,\n responsive: false,\n }}\n ></DotPlot>\n </div>\n </div>\n </div>\n ))}\n <div className=\"ThemesPlot__dotPlot__row\">\n <div\n className=\"ThemesPlot__dotPlot__barColumn\"\n style={{ textAlign: 'right' }}\n >\n VOLUME:\n </div>\n <div\n className=\"ThemesPlot__dotPlot__dotPlotColumn\"\n style={{ marginTop: '0px' }}\n >\n <DotPlot\n id={'footer'}\n plotData={dotPlotQueryData}\n isXAxis={true}\n xMax={xMaxForDotPlot}\n layoutConfig={dotPlotLayoutConfig}\n optionsConfig={{ ...optionsConfig, responsive: false }}\n ></DotPlot>\n </div>\n </div>\n </div>\n </div>\n <div></div>\n </div>\n )}\n </>\n )\n}\n\nexport default ThemesPlot\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ThemesPlot.js","names":[],"sources":["../../../src/components/Plot/ThemesPlot.tsx"],"sourcesContent":["import { getFullQueryTableResults } from '@/synapse-client'\nimport { SynapseConstants, useSynapseContext } from '@/utils'\nimport { resultToJson } from '@/utils/functions'\nimport { unCamelCase } from '@/utils/functions/unCamelCase'\nimport { Tooltip } from '@mui/material'\nimport {\n QueryBundleRequest,\n QueryResultBundle,\n RowSet,\n} from '@sage-bionetworks/synapse-types'\nimport Plotly from 'plotly.js-basic-dist'\nimport { useEffect, useState } from 'react'\nimport { RequiredKeysOf } from 'type-fest'\nimport loadingScreen from '../LoadingScreen/LoadingScreen'\nimport BarPlot from './BarPlot'\nimport DotPlot from './DotPlot'\nimport {\n BarPlotColors,\n ClickCallbackParams,\n GraphItem,\n PlotProps,\n} from './types'\nimport first from 'lodash-es/first'\nimport orderBy from 'lodash-es/orderBy'\nimport cloneDeep from 'lodash-es/cloneDeep'\n\nexport type ThemesPlotProps = {\n onPointClick: ({ facetValue, type, event }: ClickCallbackParams) => void\n onIndividualThemeBarPlotPointClick?: ({\n facetValue,\n type,\n event,\n }: ClickCallbackParams) => void\n dotPlot: PlotProps\n topBarPlot: PlotProps\n sideBarPlot: PlotProps\n dotPlotYAxisLabel?: string\n}\n\ntype TotalsGroupByY = { y: string; count: number }\ntype TotalsGroupByGroup = { group: string; count: number }\n\nconst optionsConfig: Partial<Plotly.Config> = {\n displayModeBar: false,\n responsive: true,\n scrollZoom: false,\n editable: false,\n autosizable: true,\n}\n\nconst dotPlotLayoutConfig: Partial<Plotly.Layout> = {\n showlegend: true,\n dragmode: false,\n legend: {\n font: {\n size: 11,\n },\n\n y: 1.1,\n xanchor: 'right',\n x: 1,\n\n orientation: 'h',\n },\n xaxis: {\n visible: true,\n fixedrange: true,\n zeroline: false,\n showgrid: false,\n showline: true,\n linecolor: '#ddd', //bottom line\n autotick: true,\n ticks: 'outside',\n tickcolor: '#ddd',\n type: 'log',\n },\n\n yaxis: {\n fixedrange: true,\n zeroline: false,\n gridcolor: '#ddd', //horizontal lines\n automargin: true,\n },\n\n margin: {\n pad: 20,\n },\n hovermode: 'closest',\n}\n\nconst barLayoutConfig: Partial<Plotly.Layout> = {\n barmode: 'stack',\n showlegend: false,\n dragmode: false,\n hovermode: 'closest',\n yaxis: { visible: false, fixedrange: true },\n margin: {\n l: 0,\n r: 0,\n b: 0,\n t: 0,\n pad: 0,\n },\n}\n\nfunction fetchData(\n token: string,\n { xField, yField, groupField, entityId, whereClause, infoField }: PlotProps,\n): Promise<RowSet> {\n const sql = `SELECT ${xField} as \"x\", ${yField} as \"y\", ${\n infoField ? infoField + ' as \"info\", ' : ''\n } ${groupField} as \"group\"\n FROM ${entityId} ${whereClause ? ' WHERE ' + whereClause : ''}`\n\n const queryRequest: QueryBundleRequest = {\n concreteType: 'org.sagebionetworks.repo.model.table.QueryBundleRequest',\n partMask: SynapseConstants.BUNDLE_MASK_QUERY_RESULTS,\n entityId: entityId,\n query: {\n sql: sql,\n },\n }\n\n return getFullQueryTableResults(queryRequest, token).then(\n (data: QueryResultBundle) => {\n return data.queryResult!.queryResults\n },\n )\n}\n\nfunction getTotalsByProp<T>(\n data: GraphItem[],\n prop: RequiredKeysOf<GraphItem>,\n): T[] {\n const resultObject = data.reduce((res: Record<string, number>, obj) => {\n res[obj[prop]] =\n (obj[prop] in res ? Number(res[obj[prop]]) : 0) + Number(obj.x)\n return res\n }, {})\n const result: T[] = []\n for (const property in resultObject) {\n result.push({\n [prop]: property,\n count: resultObject[property],\n } as unknown as T)\n }\n return result\n}\n\nconst getClickTargetData = (\n e: Plotly.PlotMouseEvent,\n swap: boolean,\n): ClickCallbackParams => {\n const pointData = e.points[0].data\n\n let facetValue = pointData.y[0] as string\n let type = pointData.name\n\n if (swap) {\n ;[facetValue, type] = [type, facetValue]\n }\n return { facetValue, type, event: e.event }\n}\n\nconst renderTopBarLegend = (\n colors: BarPlotColors | undefined,\n xLabels: string[],\n) => (\n <div className=\"ThemesPlot__barPlotLegend\">\n {xLabels.map((item, i) => (\n <div style={{ float: 'left' }} key={`topBar_${i}`}>\n <div\n className=\"ThemesPlot__barPlotLegend__label\"\n key=\"topBar_label\"\n style={{\n backgroundColor: `${colors ? colors[item] : 'transparent'}`,\n }}\n ></div>\n <div className=\"ThemesPlot__barPlotLegend__graph\" key=\"topBar_graph\">\n {item}\n </div>{' '}\n </div>\n ))}\n </div>\n)\n\nconst fadeColors = (colors: { [key: string]: string }, opacity: string) => {\n for (const key in colors) {\n colors[key] = colors[key]\n .replace(',1)', `, ${opacity})`)\n .replace(',1.0)', `, ${opacity})`)\n }\n return colors\n}\n\nconst getTooltip = (data: GraphItem[], filter: string) => {\n return first(data.filter(item => item.y === filter).map(item => item.info))\n}\n\nexport function ThemesPlot({\n dotPlot,\n topBarPlot,\n sideBarPlot,\n onPointClick,\n onIndividualThemeBarPlotPointClick,\n dotPlotYAxisLabel = 'Research Themes',\n}: ThemesPlotProps) {\n const { accessToken } = useSynapseContext()\n const [isLoaded, setIsLoaded] = useState(false)\n const [dotPlotQueryData, setDotPlotQueryData] = useState<GraphItem[]>([])\n const [topBarPlotData, setTopBarQueryData] = useState<GraphItem[]>([])\n const [sideBarPlotData, setSideBarQueryData] = useState<GraphItem[]>([])\n\n useEffect(() => {\n const dotPlotData = fetchData(accessToken!, dotPlot)\n const topBarPlotData = fetchData(accessToken!, topBarPlot)\n const sideBarPlotData = fetchData(accessToken!, sideBarPlot)\n Promise.all([dotPlotData, topBarPlotData, sideBarPlotData])\n .then(result => {\n setDotPlotQueryData(\n resultToJson(\n result[0].headers,\n result[0].rows,\n ) as unknown as GraphItem[],\n )\n setTopBarQueryData(\n resultToJson(\n result[1].headers,\n result[1].rows,\n ) as unknown as GraphItem[],\n )\n setSideBarQueryData(\n resultToJson(\n result[2].headers,\n result[2].rows,\n ) as unknown as GraphItem[],\n )\n setIsLoaded(true)\n })\n .catch(err => {\n throw err\n })\n return () => {}\n }, [accessToken, dotPlot, topBarPlot, sideBarPlot])\n let yLabelsForDotPlot: string[] = []\n let xLabelsForTopBarPlot: string[] = []\n let xMaxForDotPlot = 0\n let topBarPlotDataSorted: TotalsGroupByY[] = []\n let totalsByDotPlotY: TotalsGroupByY[] = []\n if (isLoaded) {\n totalsByDotPlotY = getTotalsByProp(sideBarPlotData, 'y')\n yLabelsForDotPlot = totalsByDotPlotY\n .sort((a, b) => b.count - a.count)\n .map(item => item.y)\n xMaxForDotPlot = Math.max(...dotPlotQueryData.map(item => Number(item.x)))\n topBarPlotDataSorted = orderBy(getTotalsByProp(topBarPlotData, 'y'), ['y'])\n xLabelsForTopBarPlot = orderBy(\n getTotalsByProp<TotalsGroupByGroup>(topBarPlotData, 'group'),\n ['group'],\n ).map(item => item.group)\n }\n\n return (\n <>\n {!isLoaded && loadingScreen}\n\n {isLoaded && (\n <div className=\"ThemesPlot\">\n <div className=\"ThemesPlot__dotPlotLegend\">\n <DotPlot\n id=\"head\"\n plotData={dotPlotQueryData}\n isLegend={true}\n markerSymbols={dotPlot.markerSymbols}\n style={{ width: '100%', height: '100%' }}\n layoutConfig={dotPlotLayoutConfig}\n optionsConfig={{\n ...optionsConfig,\n responsive: true,\n staticPlot: true,\n }}\n plotStyle={{\n ...dotPlot.plotStyle!,\n backgroundColor: 'transparent',\n }}\n ></DotPlot>\n </div>\n {topBarPlot.colors &&\n renderTopBarLegend(topBarPlot.colors, xLabelsForTopBarPlot)}\n {topBarPlotDataSorted.map((item, i) => (\n <div className=\"ThemesPlot__topBarPlot\" key={`topBarDiv_${i}`}>\n <div className=\"ThemesPlot__topBarPlot__label\">\n {item.count} {unCamelCase(item.y)}\n </div>\n <div className=\"ThemesPlot__topBarPlot__plot\">\n <BarPlot\n style={{ width: '100%', height: '100%' }}\n layoutConfig={cloneDeep(barLayoutConfig)}\n optionsConfig={{ ...optionsConfig }}\n plotData={topBarPlotData}\n isTop={true}\n label={item.y}\n xMax={item.count}\n onClick={(e: any) =>\n onPointClick(getClickTargetData(e, true))\n }\n colors={\n // we are not actually fading colors for now. But keeping implemenation in case it changes\n i % 2 === 0\n ? topBarPlot.colors\n : fadeColors({ ...topBarPlot.colors }, '1')\n }\n />\n </div>\n </div>\n ))}\n <div style={{ display: 'flex', position: 'relative' }}>\n <div className=\"ThemesPlot__dotPlotYLabel\">{dotPlotYAxisLabel}</div>\n <div className=\"ThemesPlot__dotPlot\">\n {yLabelsForDotPlot.map((label, i) => (\n <div\n key={`plotDiv_${+i}`}\n className=\"ThemesPlot__dotPlot__row\"\n style={{\n backgroundColor: dotPlot.plotStyle?.backgroundColor,\n }}\n >\n <div className=\"ThemesPlot__dotPlot__barColumn\">\n <Tooltip\n title={`${getTooltip(dotPlotQueryData, label)} `}\n placement={'right'}\n >\n <div>\n <span className=\"ThemesPlot__dotPlot__themeLabel\">\n {label}\n </span>\n <br />\n <span className=\"ThemesPlot__dotPlot__countLabel\">\n {totalsByDotPlotY[i].count} {sideBarPlot.countLabel}\n </span>\n <br />\n <BarPlot\n style={{ width: '100%' }}\n layoutConfig={barLayoutConfig}\n optionsConfig={optionsConfig}\n plotData={sideBarPlotData}\n isTop={false}\n // PORTALS-3061: No longer use a global x max for the side bar (where the bar size of 1 grant is consistent),\n // Instead, each bar chart is independent (the size of 1 grant differs across bar charts).\n xMax={totalsByDotPlotY[i].count}\n label={label}\n colors={fadeColors({ ...topBarPlot.colors }, '1')}\n onClick={(e: any) => {\n if (onIndividualThemeBarPlotPointClick) {\n onIndividualThemeBarPlotPointClick(\n getClickTargetData(e, false),\n )\n }\n }}\n />\n </div>\n </Tooltip>\n </div>\n <div className=\"ThemesPlot__dotPlot__dotPlotColumn\">\n <div\n style={{\n width: '100%',\n backgroundColor: dotPlot.plotStyle?.backgroundColor,\n }}\n >\n <DotPlot\n id={`${i}`}\n onClick={(e: any) => {\n const { type, event } = getClickTargetData(e, false)\n onPointClick({ facetValue: label, type, event })\n }}\n plotData={dotPlotQueryData}\n plotStyle={dotPlot.plotStyle}\n markerSymbols={dotPlot.markerSymbols}\n xMax={xMaxForDotPlot}\n label={label}\n layoutConfig={dotPlotLayoutConfig}\n optionsConfig={{\n ...optionsConfig,\n responsive: false,\n }}\n ></DotPlot>\n </div>\n </div>\n </div>\n ))}\n <div className=\"ThemesPlot__dotPlot__row\">\n <div\n className=\"ThemesPlot__dotPlot__barColumn\"\n style={{ textAlign: 'right' }}\n >\n VOLUME:\n </div>\n <div\n className=\"ThemesPlot__dotPlot__dotPlotColumn\"\n style={{ marginTop: '0px' }}\n >\n <DotPlot\n id={'footer'}\n plotData={dotPlotQueryData}\n isXAxis={true}\n xMax={xMaxForDotPlot}\n layoutConfig={dotPlotLayoutConfig}\n optionsConfig={{ ...optionsConfig, responsive: false }}\n ></DotPlot>\n </div>\n </div>\n </div>\n </div>\n <div></div>\n </div>\n )}\n </>\n )\n}\n\nexport default ThemesPlot\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UpsetPlot.js","names":[],"sources":["../../../src/components/Plot/UpsetPlot.tsx"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport LargeButton from '@/components/styled/LargeButton'\nimport SynapseClient from '@/synapse-client'\nimport { SynapseConstants } from '@/utils'\nimport { useSynapseContext } from '@/utils/context/SynapseContext'\nimport { parseEntityIdFromSqlStatement } from '@/utils/functions/SqlFunctions'\nimport { QueryBundleRequest } from '@sage-bionetworks/synapse-types'\nimport { ReactComponent as DiagonalLinePattern } from '@/assets/illustrations/diagonalLinePattern.svg'\n\nimport UpSetJS, {\n extractSets,\n generateCombinations,\n ISet,\n ISetCombinations,\n ISetLike,\n ISets,\n UpSetFontSizes,\n UpSetSelectionProps,\n} from '@upsetjs/react'\n/* eslint-disable @typescript-eslint/no-unsafe-member-access */\n/* eslint-disable @typescript-eslint/no-unsafe-assignment */\nimport { useEffect, useState } from 'react'\nimport { getColorPalette } from '../ColorGradient/ColorGradient'\nimport { ErrorBanner } from '../error/ErrorBanner'\nimport loadingScreen from '../LoadingScreen/LoadingScreen'\nimport { Box, SxProps, useTheme } from '@mui/material'\nimport { useMeasure } from '@react-hookz/web'\n\nexport type UpsetPlotProps = {\n sql: string // first column should contain values, second column should contain a single set value. ie. SELECT distinct individualID, assay FROM syn20821313\n rgbIndex?: number // color plot based on portal\n customPlotColor?: string\n selectionOpacity?: number\n variant?: 'ampals'\n maxBarCount?: number // will show all if not set\n setName?: string // instead of \"Set Size\"\n combinationName?: string // instead of \"Intersection Size\"\n height?: number\n summaryLinkText?: string // text for home page link below chart\n summaryLink?: string // url for home page link below chart\n} & Pick<UpSetSelectionProps, 'onClick'>\n\nexport type UpsetPlotData = {\n sets: ISets<any>\n combinations: ISetCombinations<any>\n}\n/**\n * Upset plot. See https://medium.com/@sgratzl/upset-js-javascript-tutorial-1b84bfd6896d\n * Currently this is driven by a Synapse Table/View, but we may want to alter it to read in the data from a flat file instead.\n */\nexport function UpsetPlot({\n sql,\n variant,\n rgbIndex,\n maxBarCount,\n setName,\n combinationName,\n height = 700,\n summaryLinkText,\n summaryLink,\n onClick,\n customPlotColor,\n selectionOpacity,\n}: UpsetPlotProps) {\n const { accessToken } = useSynapseContext()\n const [isLoading, setIsLoading] = useState<boolean>()\n const [data, setData] = useState<UpsetPlotData>()\n const [error, setError] = useState<string>()\n const [selection, setSelection] = useState(null as ISetLike<any> | null)\n const theme = useTheme()\n\n const [plotContainerMeasurements, plotContainerRef] = useMeasure()\n\n const variantStyles: Record<string, SxProps> = {\n default: {\n 'text[class^=\"sChartTextStyle-upset-\"], text[class^= \"cChartTextStyle-upset-\"]':\n {\n textTransform: 'uppercase',\n },\n },\n ampals: {\n width: '100%',\n '& .selectionHint-upset-': {\n stroke: 'transparent !important',\n },\n '& [class^=\"selectionHint-upset-\"]': {\n stroke: 'transparent !important',\n },\n '& g[class^=\"interactive-upset-\"]:hover line[class^=\"upsetLine-\"]': {\n stroke: theme.palette.primary.main,\n strokeWidth: '4px',\n strokeOpacity: 1,\n },\n '& g[class^=\"interactive-upset-\"]:hover circle[class^=\"fillNotMember-upset-\"]':\n {\n opacity: 0.2,\n },\n '& line[class^=\"upsetLine-\"]': {\n strokeOpacity: 0,\n },\n '& rect[class^=\"fillPrimary-upset-\"]': {\n fill: 'url(#diagonalLinePattern)',\n stroke: theme.palette.grey[700],\n strokeWidth: 2,\n },\n '& circle[class^=\"fillNotMember-upset-\"]': {\n stroke: theme.palette.grey[600],\n strokeWidth: 2,\n },\n '& text[class^=\"sChartTextStyle-upset-\"], & text[class^=\"cChartTextStyle-upset-\"]':\n {\n fontWeight: 700,\n fill: theme.palette.grey[800],\n lineHeight: '150%',\n },\n '& text[class^=\"cChartTextStyle-upset-\"]': {\n transform: 'translate(-60px, 190px) rotate(-90deg)',\n },\n '& text[class^=\"sChartTextStyle-upset-\"]': {\n transform: 'translate(-10px, 100px) rotate(-90deg)',\n },\n },\n }\n\n let plotColor: string, selectionColor: string\n if (rgbIndex != null) {\n const { colorPalette } = getColorPalette(rgbIndex, 2)\n plotColor = colorPalette[0]\n selectionColor = colorPalette[0]\n } else {\n plotColor = theme.palette.grey[700]\n selectionColor = customPlotColor || theme.palette.primary.main\n }\n\n const updateFontSizes: UpSetFontSizes = {\n setLabel: '14px',\n }\n\n useEffect(() => {\n let isCancelled: boolean = false\n const getPlotData = async () => {\n setIsLoading(true)\n try {\n const entityId = parseEntityIdFromSqlStatement(sql)\n const partMask = SynapseConstants.BUNDLE_MASK_QUERY_RESULTS\n const queryRequest: QueryBundleRequest = {\n partMask,\n concreteType:\n 'org.sagebionetworks.repo.model.table.QueryBundleRequest',\n entityId,\n query: {\n sql,\n },\n }\n const { queryResult } = await SynapseClient.getFullQueryTableResults(\n queryRequest,\n accessToken,\n )\n // transform query data into plot data, and store.\n // collect all values for each key\n const keyValuesMap: Record<string, { name: string; sets: string[] }> =\n {}\n // keyValuesMap looks like { 'A': {name: 'A', sets: ['S1', 'S2'] }, 'B': { name: 'B', sets: ['S1'] }, ... }\n // It's a little redundant, but makes the next step much easier.\n\n const caseInsensitiveSetNames: Record<string, string> = {}\n // caseInsensitiveSetNames looks like { 'RNASEQ': 'rnaSeq', 'NOMe-SEQ': 'NOMe-seq'}.\n\n for (const row of queryResult?.queryResults.rows ?? []) {\n for (let j = 1; j < row.values.length; j += 1) {\n const rowValues: string[] = row.values as string[]\n if (rowValues.some(value => value === null)) {\n console.warn('Row has null value(s) when no nulls expected')\n }\n\n const key = rowValues[0]\n let newValue = rowValues[j]\n keyValuesMap[key] = keyValuesMap[key] || {}\n keyValuesMap[key].name = key\n\n keyValuesMap[key].sets = keyValuesMap[key].sets || []\n const found = keyValuesMap[key].sets.find((v: any) => v == newValue)\n if (!found && newValue) {\n if (caseInsensitiveSetNames[newValue.toUpperCase()]) {\n newValue = caseInsensitiveSetNames[newValue.toUpperCase()]\n } else {\n caseInsensitiveSetNames[newValue.toUpperCase()] = newValue\n }\n keyValuesMap[key].sets.push(newValue)\n }\n }\n }\n // now create the expected elems set\n const elems = Object.values(keyValuesMap)\n // elems looks like [{ name: 'A', sets: ['S1', 'S2'] }, { name: 'B', sets: ['S1'] }, ...]\n const sets = extractSets(elems)\n // PORTALS-1673: sort by assay name\n const sortedSets = (sets as ISet[]).sort((a, b) => {\n return ('' + b.name).localeCompare(a.name)\n })\n\n const combinations = generateCombinations(sortedSets, {\n type: 'intersection',\n min: 1,\n limit: maxBarCount,\n order: 'cardinality:desc',\n })\n if (!isCancelled) {\n setData({ sets, combinations })\n setIsLoading(false)\n }\n } catch (err) {\n if (!isCancelled) {\n setIsLoading(false)\n let errorMessage = err['reason']\n if (!errorMessage) {\n console.error(err)\n errorMessage = 'Error retrieving data'\n }\n setError(errorMessage)\n }\n }\n }\n getPlotData()\n return () => {\n isCancelled = true\n }\n }, [sql, accessToken])\n\n return (\n <>\n {isLoading && loadingScreen}\n {!isLoading && data && (\n <>\n {variantStyles['ampals'] && (\n // Render DiagonalLinePattern so UpsetPlot can use `fill: url(#diagonalLinePattern)`.\n // The SVG element must be added to the DOM so we can reference its ID (which is set in the SVG file) in the `fill` style\n // Ideally, we would reference the asset URL imported by Vite, but this isn't working.\n <Box\n sx={{\n '& path': {\n stroke: '#D9D9D9 !important',\n },\n width: 0,\n height: 0,\n position: 'absolute',\n }}\n >\n <DiagonalLinePattern />\n </Box>\n )}\n <Box\n className=\"UpsetPlot\"\n sx={variant ? variantStyles[variant] : variantStyles['default']}\n ref={plotContainerRef}\n >\n <UpSetJS\n sets={data.sets}\n combinations={data.combinations}\n width={plotContainerMeasurements?.width || 800}\n height={height}\n onHover={setSelection}\n onClick={onClick}\n selection={selection}\n color={plotColor}\n selectionColor={selectionColor}\n hoverHintColor={'orange'}\n hasSelectionOpacity={selectionOpacity ? selectionOpacity : 0.3}\n // alternatingBackgroundColor={false}\n setName={setName}\n combinationName={combinationName}\n fontFamily=\"'DM Sans', sans-serif\"\n fontSizes={updateFontSizes}\n exportButtons={false}\n notMemberColor=\"transparent\"\n />\n {summaryLink && summaryLinkText && (\n <div className=\"UpsetPlot__summary\">\n <LargeButton\n color=\"secondary\"\n variant=\"contained\"\n href={summaryLink}\n >\n {summaryLinkText}\n </LargeButton>\n </div>\n )}\n </Box>\n </>\n )}\n <ErrorBanner error={error} />\n </>\n )\n}\n\nexport default UpsetPlot\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"UpsetPlot.js","names":[],"sources":["../../../src/components/Plot/UpsetPlot.tsx"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport LargeButton from '@/components/styled/LargeButton'\nimport SynapseClient from '@/synapse-client'\nimport { SynapseConstants } from '@/utils'\nimport { useSynapseContext } from '@/utils/context/SynapseContext'\nimport { parseEntityIdFromSqlStatement } from '@/utils/functions/SqlFunctions'\nimport { QueryBundleRequest } from '@sage-bionetworks/synapse-types'\nimport { ReactComponent as DiagonalLinePattern } from '@/assets/illustrations/diagonalLinePattern.svg'\n\nimport UpSetJS, {\n extractSets,\n generateCombinations,\n ISet,\n ISetCombinations,\n ISetLike,\n ISets,\n UpSetFontSizes,\n UpSetSelectionProps,\n} from '@upsetjs/react'\n/* eslint-disable @typescript-eslint/no-unsafe-member-access */\n/* eslint-disable @typescript-eslint/no-unsafe-assignment */\nimport { useEffect, useState } from 'react'\nimport { getColorPalette } from '../ColorGradient/ColorGradient'\nimport { ErrorBanner } from '../error/ErrorBanner'\nimport loadingScreen from '../LoadingScreen/LoadingScreen'\nimport { Box, SxProps, useTheme } from '@mui/material'\nimport { useMeasure } from '@react-hookz/web'\n\nexport type UpsetPlotProps = {\n sql: string // first column should contain values, second column should contain a single set value. ie. SELECT distinct individualID, assay FROM syn20821313\n rgbIndex?: number // color plot based on portal\n customPlotColor?: string\n selectionOpacity?: number\n variant?: 'ampals'\n maxBarCount?: number // will show all if not set\n setName?: string // instead of \"Set Size\"\n combinationName?: string // instead of \"Intersection Size\"\n height?: number\n summaryLinkText?: string // text for home page link below chart\n summaryLink?: string // url for home page link below chart\n} & Pick<UpSetSelectionProps, 'onClick'>\n\nexport type UpsetPlotData = {\n sets: ISets<any>\n combinations: ISetCombinations<any>\n}\n/**\n * Upset plot. See https://medium.com/@sgratzl/upset-js-javascript-tutorial-1b84bfd6896d\n * Currently this is driven by a Synapse Table/View, but we may want to alter it to read in the data from a flat file instead.\n */\nexport function UpsetPlot({\n sql,\n variant,\n rgbIndex,\n maxBarCount,\n setName,\n combinationName,\n height = 700,\n summaryLinkText,\n summaryLink,\n onClick,\n customPlotColor,\n selectionOpacity,\n}: UpsetPlotProps) {\n const { accessToken } = useSynapseContext()\n const [isLoading, setIsLoading] = useState<boolean>()\n const [data, setData] = useState<UpsetPlotData>()\n const [error, setError] = useState<string>()\n const [selection, setSelection] = useState(null as ISetLike<any> | null)\n const theme = useTheme()\n\n const [plotContainerMeasurements, plotContainerRef] = useMeasure()\n\n const variantStyles: Record<string, SxProps> = {\n default: {\n 'text[class^=\"sChartTextStyle-upset-\"], text[class^= \"cChartTextStyle-upset-\"]':\n {\n textTransform: 'uppercase',\n },\n },\n ampals: {\n width: '100%',\n '& .selectionHint-upset-': {\n stroke: 'transparent !important',\n },\n '& [class^=\"selectionHint-upset-\"]': {\n stroke: 'transparent !important',\n },\n '& g[class^=\"interactive-upset-\"]:hover line[class^=\"upsetLine-\"]': {\n stroke: theme.palette.primary.main,\n strokeWidth: '4px',\n strokeOpacity: 1,\n },\n '& g[class^=\"interactive-upset-\"]:hover circle[class^=\"fillNotMember-upset-\"]':\n {\n opacity: 0.2,\n },\n '& line[class^=\"upsetLine-\"]': {\n strokeOpacity: 0,\n },\n '& rect[class^=\"fillPrimary-upset-\"]': {\n fill: 'url(#diagonalLinePattern)',\n stroke: theme.palette.grey[700],\n strokeWidth: 2,\n },\n '& circle[class^=\"fillNotMember-upset-\"]': {\n stroke: theme.palette.grey[600],\n strokeWidth: 2,\n },\n '& text[class^=\"sChartTextStyle-upset-\"], & text[class^=\"cChartTextStyle-upset-\"]':\n {\n fontWeight: 700,\n fill: theme.palette.grey[800],\n lineHeight: '150%',\n },\n '& text[class^=\"cChartTextStyle-upset-\"]': {\n transform: 'translate(-60px, 190px) rotate(-90deg)',\n },\n '& text[class^=\"sChartTextStyle-upset-\"]': {\n transform: 'translate(-10px, 100px) rotate(-90deg)',\n },\n },\n }\n\n let plotColor: string, selectionColor: string\n if (rgbIndex != null) {\n const { colorPalette } = getColorPalette(rgbIndex, 2)\n plotColor = colorPalette[0]\n selectionColor = colorPalette[0]\n } else {\n plotColor = theme.palette.grey[700]\n selectionColor = customPlotColor || theme.palette.primary.main\n }\n\n const updateFontSizes: UpSetFontSizes = {\n setLabel: '14px',\n }\n\n useEffect(() => {\n let isCancelled: boolean = false\n const getPlotData = async () => {\n setIsLoading(true)\n try {\n const entityId = parseEntityIdFromSqlStatement(sql)\n const partMask = SynapseConstants.BUNDLE_MASK_QUERY_RESULTS\n const queryRequest: QueryBundleRequest = {\n partMask,\n concreteType:\n 'org.sagebionetworks.repo.model.table.QueryBundleRequest',\n entityId,\n query: {\n sql,\n },\n }\n const { queryResult } = await SynapseClient.getFullQueryTableResults(\n queryRequest,\n accessToken,\n )\n // transform query data into plot data, and store.\n // collect all values for each key\n const keyValuesMap: Record<string, { name: string; sets: string[] }> =\n {}\n // keyValuesMap looks like { 'A': {name: 'A', sets: ['S1', 'S2'] }, 'B': { name: 'B', sets: ['S1'] }, ... }\n // It's a little redundant, but makes the next step much easier.\n\n const caseInsensitiveSetNames: Record<string, string> = {}\n // caseInsensitiveSetNames looks like { 'RNASEQ': 'rnaSeq', 'NOMe-SEQ': 'NOMe-seq'}.\n\n for (const row of queryResult?.queryResults.rows ?? []) {\n for (let j = 1; j < row.values.length; j += 1) {\n const rowValues: string[] = row.values as string[]\n if (rowValues.some(value => value === null)) {\n console.warn('Row has null value(s) when no nulls expected')\n }\n\n const key = rowValues[0]\n let newValue = rowValues[j]\n keyValuesMap[key] = keyValuesMap[key] || {}\n keyValuesMap[key].name = key\n\n keyValuesMap[key].sets = keyValuesMap[key].sets || []\n const found = keyValuesMap[key].sets.find((v: any) => v == newValue)\n if (!found && newValue) {\n if (caseInsensitiveSetNames[newValue.toUpperCase()]) {\n newValue = caseInsensitiveSetNames[newValue.toUpperCase()]\n } else {\n caseInsensitiveSetNames[newValue.toUpperCase()] = newValue\n }\n keyValuesMap[key].sets.push(newValue)\n }\n }\n }\n // now create the expected elems set\n const elems = Object.values(keyValuesMap)\n // elems looks like [{ name: 'A', sets: ['S1', 'S2'] }, { name: 'B', sets: ['S1'] }, ...]\n const sets = extractSets(elems)\n // PORTALS-1673: sort by assay name\n const sortedSets = (sets as ISet[]).sort((a, b) => {\n return ('' + b.name).localeCompare(a.name)\n })\n\n const combinations = generateCombinations(sortedSets, {\n type: 'intersection',\n min: 1,\n limit: maxBarCount,\n order: 'cardinality:desc',\n })\n if (!isCancelled) {\n setData({ sets, combinations })\n setIsLoading(false)\n }\n } catch (err) {\n if (!isCancelled) {\n setIsLoading(false)\n let errorMessage = err['reason']\n if (!errorMessage) {\n console.error(err)\n errorMessage = 'Error retrieving data'\n }\n setError(errorMessage)\n }\n }\n }\n getPlotData()\n return () => {\n isCancelled = true\n }\n }, [sql, accessToken])\n\n return (\n <>\n {isLoading && loadingScreen}\n {!isLoading && data && (\n <>\n {variantStyles['ampals'] && (\n // Render DiagonalLinePattern so UpsetPlot can use `fill: url(#diagonalLinePattern)`.\n // The SVG element must be added to the DOM so we can reference its ID (which is set in the SVG file) in the `fill` style\n // Ideally, we would reference the asset URL imported by Vite, but this isn't working.\n <Box\n sx={{\n '& path': {\n stroke: '#D9D9D9 !important',\n },\n width: 0,\n height: 0,\n position: 'absolute',\n }}\n >\n <DiagonalLinePattern />\n </Box>\n )}\n <Box\n className=\"UpsetPlot\"\n sx={variant ? variantStyles[variant] : variantStyles['default']}\n ref={plotContainerRef}\n >\n <UpSetJS\n sets={data.sets}\n combinations={data.combinations}\n width={plotContainerMeasurements?.width || 800}\n height={height}\n onHover={setSelection}\n onClick={onClick}\n selection={selection}\n color={plotColor}\n selectionColor={selectionColor}\n hoverHintColor={'orange'}\n hasSelectionOpacity={selectionOpacity ? selectionOpacity : 0.3}\n // alternatingBackgroundColor={false}\n setName={setName}\n combinationName={combinationName}\n fontFamily=\"'DM Sans', sans-serif\"\n fontSizes={updateFontSizes}\n exportButtons={false}\n notMemberColor=\"transparent\"\n />\n {summaryLink && summaryLinkText && (\n <div className=\"UpsetPlot__summary\">\n <LargeButton\n color=\"secondary\"\n variant=\"contained\"\n href={summaryLink}\n >\n {summaryLinkText}\n </LargeButton>\n </div>\n )}\n </Box>\n </>\n )}\n <ErrorBanner error={error} />\n </>\n )\n}\n\nexport default UpsetPlot\n"],"mappings":"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"}
|