synapse-react-client 4.0.36 → 4.0.38
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.js +1 -1
- package/dist/aridhia-queries/index.js +11 -11
- package/dist/aridhia-queries/useAridhiaQuery.d.ts +1 -0
- package/dist/aridhia-queries/useAridhiaQuery.d.ts.map +1 -1
- package/dist/aridhia-queries/useAridhiaQuery.js +24 -17
- package/dist/aridhia-queries/useAridhiaQuery.js.map +1 -1
- package/dist/assets/icons/emailWithNotification.js +15 -15
- package/dist/assets/icons/emailWithNotification.js.map +1 -1
- package/dist/assets/icons/emailWithNotification.svg +13 -13
- package/dist/components/AccessRequirementList/AccessRequirementList.d.ts.map +1 -1
- package/dist/components/AccessRequirementList/AccessRequirementList.js +124 -117
- package/dist/components/AccessRequirementList/AccessRequirementList.js.map +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/DataAccessRequestAccessorsFilesForm/DataAccessRequestAccessorsFilesForm.d.ts.map +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/DataAccessRequestAccessorsFilesForm/DataAccessRequestAccessorsFilesForm.js +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/DataAccessRequestAccessorsFilesForm/DataAccessRequestAccessorsFilesForm.js.map +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/EDucPreviewStep/EDucPreviewStep.d.ts.map +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/EDucPreviewStep/EDucPreviewStep.js +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/EDucPreviewStep/EDucPreviewStep.js.map +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/ManualUploadDucStep/ManualUploadDucStep.d.ts.map +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/ManualUploadDucStep/ManualUploadDucStep.js +33 -32
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/ManualUploadDucStep/ManualUploadDucStep.js.map +1 -1
- package/dist/components/Aridhia/AridhiaAccessStatus.d.ts.map +1 -1
- package/dist/components/Aridhia/AridhiaAccessStatus.js +39 -18
- package/dist/components/Aridhia/AridhiaAccessStatus.js.map +1 -1
- package/dist/components/Aridhia/DarWizard/AridhiaDarWizard.d.ts +32 -0
- package/dist/components/Aridhia/DarWizard/AridhiaDarWizard.d.ts.map +1 -0
- package/dist/components/Aridhia/DarWizard/AridhiaDarWizard.js +285 -0
- package/dist/components/Aridhia/DarWizard/AridhiaDarWizard.js.map +1 -0
- package/dist/components/Aridhia/DarWizard/DarAboutStep.d.ts +4 -0
- package/dist/components/Aridhia/DarWizard/DarAboutStep.d.ts.map +1 -0
- package/dist/components/Aridhia/DarWizard/DarAboutStep.js +17 -0
- package/dist/components/Aridhia/DarWizard/DarAboutStep.js.map +1 -0
- package/dist/components/Aridhia/DarWizard/DarCompleteStep.d.ts +27 -0
- package/dist/components/Aridhia/DarWizard/DarCompleteStep.d.ts.map +1 -0
- package/dist/components/Aridhia/DarWizard/DarCompleteStep.js +96 -0
- package/dist/components/Aridhia/DarWizard/DarCompleteStep.js.map +1 -0
- package/dist/components/Aridhia/DarWizard/DarDestinationStep.d.ts +28 -0
- package/dist/components/Aridhia/DarWizard/DarDestinationStep.d.ts.map +1 -0
- package/dist/components/Aridhia/DarWizard/DarDestinationStep.js +128 -0
- package/dist/components/Aridhia/DarWizard/DarDestinationStep.js.map +1 -0
- package/dist/components/Aridhia/DarWizard/DarProjectStep.d.ts +4 -0
- package/dist/components/Aridhia/DarWizard/DarProjectStep.d.ts.map +1 -0
- package/dist/components/Aridhia/DarWizard/DarProjectStep.js +17 -0
- package/dist/components/Aridhia/DarWizard/DarProjectStep.js.map +1 -0
- package/dist/components/Aridhia/DarWizard/DarSectionForm.d.ts +13 -0
- package/dist/components/Aridhia/DarWizard/DarSectionForm.d.ts.map +1 -0
- package/dist/components/Aridhia/DarWizard/DarSectionForm.js +23 -0
- package/dist/components/Aridhia/DarWizard/DarSectionForm.js.map +1 -0
- package/dist/components/Aridhia/DarWizard/DarSubmittedPanel.d.ts +11 -0
- package/dist/components/Aridhia/DarWizard/DarSubmittedPanel.d.ts.map +1 -0
- package/dist/components/Aridhia/DarWizard/DarSubmittedPanel.js +47 -0
- package/dist/components/Aridhia/DarWizard/DarSubmittedPanel.js.map +1 -0
- package/dist/components/Aridhia/DarWizard/DarWorkspaceStep.d.ts +16 -0
- package/dist/components/Aridhia/DarWizard/DarWorkspaceStep.d.ts.map +1 -0
- package/dist/components/Aridhia/DarWizard/DarWorkspaceStep.js +33 -0
- package/dist/components/Aridhia/DarWizard/DarWorkspaceStep.js.map +1 -0
- package/dist/components/Aridhia/DarWizard/useDarDraft.d.ts +32 -0
- package/dist/components/Aridhia/DarWizard/useDarDraft.d.ts.map +1 -0
- package/dist/components/Aridhia/DarWizard/useDarDraft.js +44 -0
- package/dist/components/Aridhia/DarWizard/useDarDraft.js.map +1 -0
- package/dist/components/Aridhia/FairLabelField.d.ts +8 -0
- package/dist/components/Aridhia/FairLabelField.d.ts.map +1 -0
- package/dist/components/Aridhia/FairLabelField.js +13 -0
- package/dist/components/Aridhia/FairLabelField.js.map +1 -0
- package/dist/components/Aridhia/fairFormToRjsf.d.ts +36 -0
- package/dist/components/Aridhia/fairFormToRjsf.d.ts.map +1 -0
- package/dist/components/Aridhia/fairFormToRjsf.js +137 -0
- package/dist/components/Aridhia/fairFormToRjsf.js.map +1 -0
- package/dist/components/CannedRejectionDialog/CannedRejectionDialog.d.ts.map +1 -1
- package/dist/components/CannedRejectionDialog/CannedRejectionDialog.js +2 -2
- package/dist/components/CannedRejectionDialog/CannedRejectionDialog.js.map +1 -1
- package/dist/components/CardContainer/CardContainer.d.ts.map +1 -1
- package/dist/components/CardContainer/CardContainer.js +1 -1
- package/dist/components/CardContainer/CardContainer.js.map +1 -1
- package/dist/components/ChallengeSubmission/ChallengeSubmission.d.ts.map +1 -1
- package/dist/components/ChallengeSubmission/ChallengeSubmission.js +2 -2
- package/dist/components/ChallengeSubmission/ChallengeSubmission.js.map +1 -1
- package/dist/components/ChallengeTeamWizard/ChallengeTeamWizard.d.ts.map +1 -1
- package/dist/components/ChallengeTeamWizard/ChallengeTeamWizard.js +3 -3
- package/dist/components/ChallengeTeamWizard/ChallengeTeamWizard.js.map +1 -1
- package/dist/components/ChallengeTeamWizard/CreateChallengeTeam.js +1 -1
- package/dist/components/ChallengeTeamWizard/CreateChallengeTeam.js.map +1 -1
- package/dist/components/CreateTableViewWizard/CreateTableViewWizard.js +2 -2
- package/dist/components/CreateTableViewWizard/CreateTableViewWizard.js.map +1 -1
- package/dist/components/DataGrid/SynapseGrid.d.ts.map +1 -1
- package/dist/components/DataGrid/SynapseGrid.js +121 -117
- package/dist/components/DataGrid/SynapseGrid.js.map +1 -1
- package/dist/components/DataGrid/columns/DateTimeColumn.d.ts +21 -1
- package/dist/components/DataGrid/columns/DateTimeColumn.d.ts.map +1 -1
- package/dist/components/DataGrid/columns/DateTimeColumn.js +73 -29
- package/dist/components/DataGrid/columns/DateTimeColumn.js.map +1 -1
- package/dist/components/DataGrid/columns/NumberColumn.d.ts +31 -0
- package/dist/components/DataGrid/columns/NumberColumn.d.ts.map +1 -0
- package/dist/components/DataGrid/columns/NumberColumn.js +27 -0
- package/dist/components/DataGrid/columns/NumberColumn.js.map +1 -0
- package/dist/components/DataGrid/components/ReorderColumnsButton.d.ts +1 -0
- package/dist/components/DataGrid/components/ReorderColumnsButton.d.ts.map +1 -1
- package/dist/components/DataGrid/components/ReorderColumnsButton.js +17 -16
- package/dist/components/DataGrid/components/ReorderColumnsButton.js.map +1 -1
- package/dist/components/DataGrid/components/ReorderColumnsDialog.d.ts +2 -0
- package/dist/components/DataGrid/components/ReorderColumnsDialog.d.ts.map +1 -1
- package/dist/components/DataGrid/components/ReorderColumnsDialog.js +104 -65
- package/dist/components/DataGrid/components/ReorderColumnsDialog.js.map +1 -1
- package/dist/components/DataGrid/useDataGridWebsocket.js +1 -1
- package/dist/components/DataGrid/useDataGridWebsocket.js.map +1 -1
- package/dist/components/DataGrid/utils/columnFactory.d.ts.map +1 -1
- package/dist/components/DataGrid/utils/columnFactory.js +55 -51
- package/dist/components/DataGrid/utils/columnFactory.js.map +1 -1
- package/dist/components/DataGrid/utils/computeDefaultColumnOrder.d.ts.map +1 -1
- package/dist/components/DataGrid/utils/computeDefaultColumnOrder.js +9 -8
- package/dist/components/DataGrid/utils/computeDefaultColumnOrder.js.map +1 -1
- package/dist/components/DatasetHosting/DatasetDownloadButton.d.ts +10 -5
- package/dist/components/DatasetHosting/DatasetDownloadButton.d.ts.map +1 -1
- package/dist/components/DatasetHosting/DatasetDownloadButton.js +66 -74
- package/dist/components/DatasetHosting/DatasetDownloadButton.js.map +1 -1
- package/dist/components/DatasetHosting/DatasetHosting.d.ts +6 -0
- package/dist/components/DatasetHosting/DatasetHosting.d.ts.map +1 -1
- package/dist/components/DatasetHosting/DatasetHosting.js +6 -0
- package/dist/components/DatasetHosting/DatasetHosting.js.map +1 -1
- package/dist/components/DatasetHosting/DatasetHostingAdornment.d.ts +15 -0
- package/dist/components/DatasetHosting/DatasetHostingAdornment.d.ts.map +1 -0
- package/dist/components/DatasetHosting/DatasetHostingAdornment.js +23 -0
- package/dist/components/DatasetHosting/DatasetHostingAdornment.js.map +1 -0
- package/dist/components/DatasetHosting/index.d.ts +2 -0
- package/dist/components/DatasetHosting/index.d.ts.map +1 -1
- package/dist/components/DatasetHosting/index.js +2 -1
- package/dist/components/DownloadCart/DownloadCartPage.d.ts.map +1 -1
- package/dist/components/DownloadCart/DownloadCartPage.js +1 -1
- package/dist/components/DownloadCart/DownloadCartPage.js.map +1 -1
- package/dist/components/DropdownSelect/DropdownSelect.d.ts.map +1 -1
- package/dist/components/DropdownSelect/DropdownSelect.js +1 -1
- package/dist/components/DropdownSelect/DropdownSelect.js.map +1 -1
- package/dist/components/EntityFinder/tree/EntityTree.d.ts.map +1 -1
- package/dist/components/EntityFinder/tree/EntityTree.js +1 -1
- package/dist/components/EntityFinder/tree/EntityTree.js.map +1 -1
- package/dist/components/EntityFinder/tree/VirtualizedTree.js +1 -1
- package/dist/components/EntityFinder/tree/VirtualizedTree.js.map +1 -1
- package/dist/components/FeaturedDataTabs/FacetPlotsCard.js +1 -1
- package/dist/components/FeaturedDataTabs/FacetPlotsCard.js.map +1 -1
- package/dist/components/GenericCard/TableRowGenericCard.d.ts.map +1 -1
- package/dist/components/GenericCard/TableRowGenericCard.js +176 -170
- package/dist/components/GenericCard/TableRowGenericCard.js.map +1 -1
- package/dist/components/JsonSchemaForm/CustomFormContext.d.ts +9 -0
- package/dist/components/JsonSchemaForm/CustomFormContext.d.ts.map +1 -1
- package/dist/components/JsonSchemaForm/JsonSchemaForm.d.ts.map +1 -1
- package/dist/components/JsonSchemaForm/JsonSchemaForm.js +2 -1
- package/dist/components/JsonSchemaForm/JsonSchemaForm.js.map +1 -1
- package/dist/components/JsonSchemaForm/templates/ArrayFieldTemplate.d.ts.map +1 -1
- package/dist/components/JsonSchemaForm/templates/ArrayFieldTemplate.js +1 -1
- package/dist/components/JsonSchemaForm/templates/ArrayFieldTemplate.js.map +1 -1
- package/dist/components/JsonSchemaForm/templates/FieldTemplate.d.ts.map +1 -1
- package/dist/components/JsonSchemaForm/templates/FieldTemplate.js +6 -6
- package/dist/components/JsonSchemaForm/templates/FieldTemplate.js.map +1 -1
- package/dist/components/JsonSchemaForm/widgets/DateWidget.d.ts +9 -0
- package/dist/components/JsonSchemaForm/widgets/DateWidget.d.ts.map +1 -0
- package/dist/components/JsonSchemaForm/widgets/DateWidget.js +23 -0
- package/dist/components/JsonSchemaForm/widgets/DateWidget.js.map +1 -0
- package/dist/components/MailchimpSubscribeSection/MailchimpSubscribeSection.css +1 -1
- package/dist/components/MailchimpSubscribeSection/MailchimpSubscribeSection.d.ts +3 -2
- package/dist/components/MailchimpSubscribeSection/MailchimpSubscribeSection.d.ts.map +1 -1
- package/dist/components/MailchimpSubscribeSection/MailchimpSubscribeSection.js +10 -12
- package/dist/components/MailchimpSubscribeSection/MailchimpSubscribeSection.js.map +1 -1
- package/dist/components/MailchimpSubscribeSection/MailchimpSubscribeSection.module.js +8 -7
- package/dist/components/MailchimpSubscribeSection/MailchimpSubscribeSection.module.js.map +1 -1
- package/dist/components/MailchimpSubscribeSection/MailchimpSubscribeSection.module.scss +12 -2
- package/dist/components/Markdown/MarkdownEditor.js +1 -1
- package/dist/components/Markdown/MarkdownEditor.js.map +1 -1
- package/dist/components/ProvenanceGraph/ProvenanceGraph.d.ts.map +1 -1
- package/dist/components/ProvenanceGraph/ProvenanceGraph.js +46 -46
- package/dist/components/ProvenanceGraph/ProvenanceGraph.js.map +1 -1
- package/dist/components/QueryBuilder/queryBuilderTranslation.js +1 -1
- package/dist/components/QueryBuilder/queryBuilderTranslation.js.map +1 -1
- package/dist/components/QueryWrapperPlotNav/LastUpdatedOn.js +1 -1
- package/dist/components/QueryWrapperPlotNav/LastUpdatedOn.js.map +1 -1
- package/dist/components/QueryWrapperPlotNav/QueryWrapperPlotNav.d.ts +1 -1
- package/dist/components/QueryWrapperPlotNav/QueryWrapperPlotNav.d.ts.map +1 -1
- package/dist/components/QueryWrapperPlotNav/QueryWrapperPlotNav.js +27 -25
- package/dist/components/QueryWrapperPlotNav/QueryWrapperPlotNav.js.map +1 -1
- package/dist/components/SchemaDrivenAnnotationEditor/AnnotationEditorUtils.d.ts +0 -9
- package/dist/components/SchemaDrivenAnnotationEditor/AnnotationEditorUtils.d.ts.map +1 -1
- package/dist/components/SchemaDrivenAnnotationEditor/AnnotationEditorUtils.js +23 -31
- package/dist/components/SchemaDrivenAnnotationEditor/AnnotationEditorUtils.js.map +1 -1
- package/dist/components/SchemaDrivenAnnotationEditor/SchemaDrivenAnnotationEditor.d.ts.map +1 -1
- package/dist/components/SchemaDrivenAnnotationEditor/SchemaDrivenAnnotationEditor.js +5 -4
- package/dist/components/SchemaDrivenAnnotationEditor/SchemaDrivenAnnotationEditor.js.map +1 -1
- package/dist/components/SchemaDrivenAnnotationEditor/field/SynapseAnnotationsRJSFObjectField.d.ts.map +1 -1
- package/dist/components/SchemaDrivenAnnotationEditor/field/SynapseAnnotationsRJSFObjectField.js +6 -5
- package/dist/components/SchemaDrivenAnnotationEditor/field/SynapseAnnotationsRJSFObjectField.js.map +1 -1
- package/dist/components/SearchQueryWrapper/SearchQueryUseQueryOptions.d.ts +2 -0
- package/dist/components/SearchQueryWrapper/SearchQueryUseQueryOptions.d.ts.map +1 -1
- package/dist/components/SearchQueryWrapper/SearchQueryUseQueryOptions.js +18 -13
- package/dist/components/SearchQueryWrapper/SearchQueryUseQueryOptions.js.map +1 -1
- package/dist/components/StatisticsPlot.d.ts.map +1 -1
- package/dist/components/StatisticsPlot.js +1 -1
- package/dist/components/StatisticsPlot.js.map +1 -1
- package/dist/components/SynapseForm/SynapseFormWrapper.js +1 -1
- package/dist/components/SynapseForm/SynapseFormWrapper.js.map +1 -1
- package/dist/components/SynapseHomepageV2/HotdropsAndNews.css +1 -1
- package/dist/components/SynapseHomepageV2/HotdropsAndNews.module.js +9 -9
- package/dist/components/SynapseHomepageV2/HotdropsAndNews.module.js.map +1 -1
- package/dist/components/SynapseHomepageV2/HotdropsAndNews.module.scss +15 -0
- package/dist/components/SynapseHomepageV2/SynapseHomepageChatSearch.js +1 -1
- package/dist/components/SynapseHomepageV2/SynapseHomepageChatSearch.js.map +1 -1
- package/dist/components/SynapseSearchPageResults/SynapseSearchPage.js +1 -1
- package/dist/components/SynapseSearchPageResults/SynapseSearchPage.js.map +1 -1
- package/dist/components/SynapseTable/SynapseTableRenderers.d.ts.map +1 -1
- package/dist/components/SynapseTable/SynapseTableRenderers.js +1 -1
- package/dist/components/SynapseTable/SynapseTableRenderers.js.map +1 -1
- package/dist/components/SynapseTable/TopLevelControls/TopLevelControls.d.ts +4 -0
- package/dist/components/SynapseTable/TopLevelControls/TopLevelControls.d.ts.map +1 -1
- package/dist/components/SynapseTable/TopLevelControls/TopLevelControls.js +71 -69
- package/dist/components/SynapseTable/TopLevelControls/TopLevelControls.js.map +1 -1
- package/dist/components/SynapseTable/table-top/DownloadOptions.d.ts +4 -0
- package/dist/components/SynapseTable/table-top/DownloadOptions.d.ts.map +1 -1
- package/dist/components/SynapseTable/table-top/DownloadOptions.js +14 -13
- package/dist/components/SynapseTable/table-top/DownloadOptions.js.map +1 -1
- package/dist/components/SynapseTable/usePrefetchTableData.js +1 -1
- package/dist/components/SynapseTable/usePrefetchTableData.js.map +1 -1
- package/dist/components/TableColumnSchemaEditor/TableColumnSchemaFormReducer.js +4 -4
- package/dist/components/TableColumnSchemaEditor/TableColumnSchemaFormReducer.js.map +1 -1
- package/dist/components/TanStackTable/TableCellRenderer.d.ts.map +1 -1
- package/dist/components/TanStackTable/TableCellRenderer.js +1 -1
- package/dist/components/TanStackTable/TableCellRenderer.js.map +1 -1
- package/dist/components/TermsAndConditions/TermsAndConditions.js +1 -1
- package/dist/components/TermsAndConditions/TermsAndConditions.js.map +1 -1
- package/dist/components/Webhook/CreateWebhookModal.d.ts.map +1 -1
- package/dist/components/Webhook/CreateWebhookModal.js +1 -1
- package/dist/components/Webhook/CreateWebhookModal.js.map +1 -1
- package/dist/components/dataaccess/UserAccessRequestHistory/InFlightEDucSignaturesTable.d.ts.map +1 -1
- package/dist/components/dataaccess/UserAccessRequestHistory/InFlightEDucSignaturesTable.js +172 -63
- package/dist/components/dataaccess/UserAccessRequestHistory/InFlightEDucSignaturesTable.js.map +1 -1
- package/dist/components/dataaccess/UserAccessRequestHistory/RouteConstants.d.ts +3 -0
- package/dist/components/dataaccess/UserAccessRequestHistory/RouteConstants.d.ts.map +1 -1
- package/dist/components/dataaccess/UserAccessRequestHistory/RouteConstants.js +2 -2
- package/dist/components/dataaccess/UserAccessRequestHistory/RouteConstants.js.map +1 -1
- package/dist/components/dataaccess/UserAccessRequestHistory/UserAccessRequestHistoryPage.d.ts.map +1 -1
- package/dist/components/dataaccess/UserAccessRequestHistory/UserAccessRequestHistoryPage.js +10 -8
- package/dist/components/dataaccess/UserAccessRequestHistory/UserAccessRequestHistoryPage.js.map +1 -1
- package/dist/components/dataaccess/UserAccessRequestHistory/UserAccessRequestHistoryPlace.d.ts.map +1 -1
- package/dist/components/dataaccess/UserAccessRequestHistory/UserAccessRequestHistoryPlace.js +74 -43
- package/dist/components/dataaccess/UserAccessRequestHistory/UserAccessRequestHistoryPlace.js.map +1 -1
- package/dist/components/dataaccess/UserAccessRequestHistory/UserAccessRequestHistoryTable.d.ts.map +1 -1
- package/dist/components/dataaccess/UserAccessRequestHistory/UserAccessRequestHistoryTable.js +2 -2
- package/dist/components/dataaccess/UserAccessRequestHistory/UserAccessRequestHistoryTable.js.map +1 -1
- package/dist/components/doi/CreateOrUpdateDoiModal.js +5 -5
- package/dist/components/doi/CreateOrUpdateDoiModal.js.map +1 -1
- package/dist/components/entity/metadata/EntityModal.js +1 -1
- package/dist/components/entity/metadata/EntityModal.js.map +1 -1
- package/dist/components/entity/page/action_menu/EntityActionMenu.js +2 -2
- package/dist/components/entity/page/action_menu/EntityActionMenu.js.map +1 -1
- package/dist/components/index.js +113 -112
- package/dist/components/menu/DropdownMenu.d.ts.map +1 -1
- package/dist/components/menu/DropdownMenu.js +1 -1
- package/dist/components/menu/DropdownMenu.js.map +1 -1
- package/dist/components/row_renderers/Dataset.js +1 -1
- package/dist/components/row_renderers/Dataset.js.map +1 -1
- package/dist/components/styled/LeftRightPanel.d.ts +8 -0
- package/dist/components/styled/LeftRightPanel.d.ts.map +1 -1
- package/dist/components/styled/LeftRightPanel.js +10 -1
- package/dist/components/styled/LeftRightPanel.js.map +1 -1
- package/dist/components/widgets/facet-nav/FacetNavPanel.js +1 -1
- package/dist/components/widgets/facet-nav/FacetNavPanel.js.map +1 -1
- package/dist/components/widgets/query-filter/EnumFacetFilter/EnumFacetFilter.d.ts.map +1 -1
- package/dist/components/widgets/query-filter/EnumFacetFilter/EnumFacetFilter.js +1 -1
- package/dist/components/widgets/query-filter/EnumFacetFilter/EnumFacetFilter.js.map +1 -1
- package/dist/components/widgets/query-filter/FacetFilterControls.js +1 -1
- package/dist/components/widgets/query-filter/FacetFilterControls.js.map +1 -1
- package/dist/features/entity/metadata-task/components/CreateOrUpdateCurationTaskDialog.d.ts.map +1 -1
- package/dist/features/entity/metadata-task/components/CreateOrUpdateCurationTaskDialog.js +1 -1
- package/dist/features/entity/metadata-task/components/CreateOrUpdateCurationTaskDialog.js.map +1 -1
- package/dist/index.js +174 -173
- package/dist/index.js.map +1 -1
- package/dist/mocks/msw/handlers/aridhiaHandlers.d.ts +73 -0
- package/dist/mocks/msw/handlers/aridhiaHandlers.d.ts.map +1 -0
- package/dist/mocks/msw/handlers/aridhiaHandlers.js +119 -0
- package/dist/mocks/msw/handlers/aridhiaHandlers.js.map +1 -0
- package/dist/mocks/msw/handlers/dataAccessRequestHandlers.js +1 -1
- package/dist/mocks/msw/handlers/dataAccessRequestHandlers.js.map +1 -1
- package/dist/mocks/msw/handlers/entityHandlers.d.ts.map +1 -1
- package/dist/mocks/msw/handlers/entityHandlers.js +4 -4
- package/dist/mocks/msw/handlers/entityHandlers.js.map +1 -1
- package/dist/mocks/msw/handlers/userProfileHandlers.js +2 -2
- package/dist/mocks/msw/handlers/userProfileHandlers.js.map +1 -1
- package/dist/mocks/msw/handlers.d.ts.map +1 -1
- package/dist/mocks/msw/handlers.js +72 -69
- package/dist/mocks/msw/handlers.js.map +1 -1
- package/dist/style/components/_terms-and-conditions.scss +25 -3
- package/dist/style/main.css +1 -1
- package/dist/testutils/RjsfFormTestUtils.js +12 -0
- package/dist/testutils/RjsfFormTestUtils.js.map +1 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/utils/featureflag/FeatureFlags.d.ts +1 -0
- package/dist/utils/featureflag/FeatureFlags.d.ts.map +1 -1
- package/dist/utils/featureflag/FeatureFlags.js +1 -1
- package/dist/utils/featureflag/FeatureFlags.js.map +1 -1
- package/dist/utils/functions/QueryFilterUtils.js +1 -1
- package/dist/utils/functions/QueryFilterUtils.js.map +1 -1
- package/dist/utils/functions/SqlFunctions.js +1 -1
- package/dist/utils/functions/SqlFunctions.js.map +1 -1
- package/dist/utils/functions/queryUtils.js +1 -1
- package/dist/utils/functions/queryUtils.js.map +1 -1
- package/dist/utils/hooks/useDetectSSOCode.d.ts.map +1 -1
- package/dist/utils/hooks/useDetectSSOCode.js +1 -1
- package/dist/utils/hooks/useDetectSSOCode.js.map +1 -1
- package/dist/utils/hooks/useImmutableTableQuery/useImmutableTableQuery.js +1 -1
- package/dist/utils/hooks/useImmutableTableQuery/useImmutableTableQuery.js.map +1 -1
- package/dist/utils/jsonschema/SchemaAnnotationUtils.js +1 -1
- package/dist/utils/jsonschema/SchemaAnnotationUtils.js.map +1 -1
- package/dist/utils/jsonschema/collectTopLevelProperties.d.ts +22 -0
- package/dist/utils/jsonschema/collectTopLevelProperties.d.ts.map +1 -0
- package/dist/utils/jsonschema/collectTopLevelProperties.js +31 -0
- package/dist/utils/jsonschema/collectTopLevelProperties.js.map +1 -0
- package/dist/utils/jsonschema/getSchemaPropertyInfo.d.ts.map +1 -1
- package/dist/utils/jsonschema/getSchemaPropertyInfo.js +1 -1
- package/dist/utils/jsonschema/getSchemaPropertyInfo.js.map +1 -1
- package/package.json +5 -5
package/dist/components/dataaccess/UserAccessRequestHistory/UserAccessRequestHistoryTable.js
CHANGED
|
@@ -31,7 +31,7 @@ var b = _(), x = [
|
|
|
31
31
|
title: "Status"
|
|
32
32
|
}),
|
|
33
33
|
enableSorting: !1,
|
|
34
|
-
cell: (e) => e.row.original.userAccessApproval
|
|
34
|
+
cell: (e) => e.row.original.userAccessApproval?.expiredOn && g(e.row.original.userAccessApproval.expiredOn).isBefore(g()) ? "Expired" : d(e.getValue().toLocaleLowerCase()),
|
|
35
35
|
enableColumnFilter: !1,
|
|
36
36
|
size: 75
|
|
37
37
|
}),
|
|
@@ -52,7 +52,7 @@ var b = _(), x = [
|
|
|
52
52
|
title: "Expires"
|
|
53
53
|
}),
|
|
54
54
|
enableSorting: !1,
|
|
55
|
-
cell: (e) => e.row.original.userAccessApproval
|
|
55
|
+
cell: (e) => e.row.original.userAccessApproval?.expiredOn ? n(g(e.row.original.userAccessApproval.expiredOn)) : null,
|
|
56
56
|
size: 75,
|
|
57
57
|
enableColumnFilter: !1
|
|
58
58
|
}),
|
package/dist/components/dataaccess/UserAccessRequestHistory/UserAccessRequestHistoryTable.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UserAccessRequestHistoryTable.js","names":[],"sources":["../../../../src/components/dataaccess/UserAccessRequestHistory/UserAccessRequestHistoryTable.tsx"],"sourcesContent":["import { getSortApiRequestFromTableSortState } from '@/components/dataaccess/UserAccessRequestHistory/SubmissionSortStateTranslator'\nimport InfiniteTableLayout from '@/components/layout/InfiniteTableLayout'\nimport { SkeletonTable } from '@/components/Skeleton'\nimport UserOrTeamBadge from '@/components/UserOrTeamBadge/UserOrTeamBadge'\nimport { useSearchAccessSubmissionUserRequestsInfinite } from '@/synapse-queries/dataaccess/useDataAccessSubmission'\nimport { formatDate } from '@/utils/functions/DateFormatter'\nimport { Typography } from '@mui/material'\nimport { UserSubmissionSearchResult } from '@sage-bionetworks/synapse-client'\nimport {\n createColumnHelper,\n getCoreRowModel,\n SortingState,\n useReactTable,\n} from '@tanstack/react-table'\nimport dayjs from 'dayjs'\nimport { upperFirst } from 'lodash-es'\nimport { useMemo, useState } from 'react'\nimport { Link } from 'react-router'\nimport ColumnHeader from '../../TanStackTable/ColumnHeader'\nimport StyledTanStackTable from '../../TanStackTable/StyledTanStackTable'\nimport { USER_ACCESS_HISTORY_SUBMISSION_SUBPATH } from './RouteConstants'\n\nconst columnHelper = createColumnHelper<UserSubmissionSearchResult>()\nconst columns = [\n columnHelper.accessor('accessRequirementName', {\n header: props => (\n <ColumnHeader {...props} title={'Access Requirement Name'} />\n ),\n enableSorting: false,\n enableColumnFilter: false,\n }),\n columnHelper.accessor('state', {\n header: props => <ColumnHeader {...props} title={'Status'} />,\n enableSorting: false,\n cell: ctx => {\n if (\n ctx.row.original.userAccessApproval
|
|
1
|
+
{"version":3,"file":"UserAccessRequestHistoryTable.js","names":[],"sources":["../../../../src/components/dataaccess/UserAccessRequestHistory/UserAccessRequestHistoryTable.tsx"],"sourcesContent":["import { getSortApiRequestFromTableSortState } from '@/components/dataaccess/UserAccessRequestHistory/SubmissionSortStateTranslator'\nimport InfiniteTableLayout from '@/components/layout/InfiniteTableLayout'\nimport { SkeletonTable } from '@/components/Skeleton'\nimport UserOrTeamBadge from '@/components/UserOrTeamBadge/UserOrTeamBadge'\nimport { useSearchAccessSubmissionUserRequestsInfinite } from '@/synapse-queries/dataaccess/useDataAccessSubmission'\nimport { formatDate } from '@/utils/functions/DateFormatter'\nimport { Typography } from '@mui/material'\nimport { UserSubmissionSearchResult } from '@sage-bionetworks/synapse-client'\nimport {\n createColumnHelper,\n getCoreRowModel,\n SortingState,\n useReactTable,\n} from '@tanstack/react-table'\nimport dayjs from 'dayjs'\nimport { upperFirst } from 'lodash-es'\nimport { useMemo, useState } from 'react'\nimport { Link } from 'react-router'\nimport ColumnHeader from '../../TanStackTable/ColumnHeader'\nimport StyledTanStackTable from '../../TanStackTable/StyledTanStackTable'\nimport { USER_ACCESS_HISTORY_SUBMISSION_SUBPATH } from './RouteConstants'\n\nconst columnHelper = createColumnHelper<UserSubmissionSearchResult>()\nconst columns = [\n columnHelper.accessor('accessRequirementName', {\n header: props => (\n <ColumnHeader {...props} title={'Access Requirement Name'} />\n ),\n enableSorting: false,\n enableColumnFilter: false,\n }),\n columnHelper.accessor('state', {\n header: props => <ColumnHeader {...props} title={'Status'} />,\n enableSorting: false,\n cell: ctx => {\n if (\n ctx.row.original.userAccessApproval?.expiredOn &&\n dayjs(ctx.row.original.userAccessApproval.expiredOn).isBefore(dayjs())\n ) {\n return 'Expired'\n }\n return upperFirst(ctx.getValue()!.toLocaleLowerCase())\n },\n enableColumnFilter: false,\n size: 75,\n }),\n columnHelper.accessor('createdOn', {\n header: props => <ColumnHeader {...props} title={'Date Submitted'} />,\n enableSorting: true,\n cell: ctx => formatDate(dayjs(ctx.getValue())),\n sortDescFirst: true,\n enableColumnFilter: false,\n }),\n columnHelper.display({\n id: 'expires',\n header: props => <ColumnHeader {...props} title={'Expires'} />,\n enableSorting: false,\n cell: ctx => {\n if (ctx.row.original.userAccessApproval?.expiredOn) {\n return formatDate(dayjs(ctx.row.original.userAccessApproval.expiredOn))\n }\n return null\n },\n size: 75,\n enableColumnFilter: false,\n }),\n\n columnHelper.accessor('submitterId', {\n header: props => <ColumnHeader {...props} title={'Submitter'} />,\n enableSorting: false,\n cell: ctx => <UserOrTeamBadge principalId={ctx.getValue()} />,\n enableColumnFilter: false,\n }),\n\n columnHelper.accessor('id', {\n header: props => <ColumnHeader {...props} title={''} />,\n enableSorting: false,\n cell: ctx => (\n <>\n <Link\n to={`/${USER_ACCESS_HISTORY_SUBMISSION_SUBPATH}/${ctx.getValue()}`}\n >\n View Request\n </Link>\n </>\n ),\n size: 95,\n enableColumnFilter: false,\n }),\n]\n\nexport function UserAccessRequestHistoryTable() {\n const [tableSortState, setTableSortState] = useState<SortingState>([\n {\n desc: true,\n id: 'createdOn',\n },\n ])\n\n const {\n data: infiniteData,\n isLoading,\n hasNextPage,\n isFetchingNextPage,\n fetchNextPage,\n } = useSearchAccessSubmissionUserRequestsInfinite({\n sort: getSortApiRequestFromTableSortState(tableSortState),\n })\n\n const data = useMemo(\n () => infiniteData?.pages.flatMap(page => page.results || []) || [],\n [infiniteData],\n )\n\n const table = useReactTable({\n data: data,\n columns,\n getCoreRowModel: getCoreRowModel(),\n manualSorting: true,\n columnResizeMode: 'onChange',\n state: {\n sorting: tableSortState,\n },\n onSortingChange: setTableSortState,\n })\n\n const isEmpty = !isLoading && table.getRowModel().rows.length === 0\n\n return (\n <InfiniteTableLayout\n table={<StyledTanStackTable table={table} fullWidth={true} />}\n isLoading={isLoading}\n loader={<SkeletonTable numCols={columns.length} fullWidthCells />}\n isEmpty={isEmpty}\n noResults={\n <Typography variant={'body1'} sx={{ textAlign: 'center', my: 2 }}>\n You have no access requests\n </Typography>\n }\n hasNextPage={hasNextPage}\n onFetchNextPageClicked={() => {\n void fetchNextPage()\n }}\n isFetchingNextPage={isFetchingNextPage}\n />\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAsBA,IAAM,IAAe,EAA+C,GAC9D,IAAU;CACd,EAAa,SAAS,yBAAyB;EAC7C,SAAQ,MACN,kBAAC,GAAD;GAAc,GAAI;GAAO,OAAO;EAA4B,CAAA;EAE9D,eAAe;EACf,oBAAoB;CACtB,CAAC;CACD,EAAa,SAAS,SAAS;EAC7B,SAAQ,MAAS,kBAAC,GAAD;GAAc,GAAI;GAAO,OAAO;EAAW,CAAA;EAC5D,eAAe;EACf,OAAM,MAEF,EAAI,IAAI,SAAS,oBAAoB,aACrC,EAAM,EAAI,IAAI,SAAS,mBAAmB,SAAS,EAAE,SAAS,EAAM,CAAC,IAE9D,YAEF,EAAW,EAAI,SAAS,EAAG,kBAAkB,CAAC;EAEvD,oBAAoB;EACpB,MAAM;CACR,CAAC;CACD,EAAa,SAAS,aAAa;EACjC,SAAQ,MAAS,kBAAC,GAAD;GAAc,GAAI;GAAO,OAAO;EAAmB,CAAA;EACpE,eAAe;EACf,OAAM,MAAO,EAAW,EAAM,EAAI,SAAS,CAAC,CAAC;EAC7C,eAAe;EACf,oBAAoB;CACtB,CAAC;CACD,EAAa,QAAQ;EACnB,IAAI;EACJ,SAAQ,MAAS,kBAAC,GAAD;GAAc,GAAI;GAAO,OAAO;EAAY,CAAA;EAC7D,eAAe;EACf,OAAM,MACA,EAAI,IAAI,SAAS,oBAAoB,YAChC,EAAW,EAAM,EAAI,IAAI,SAAS,mBAAmB,SAAS,CAAC,IAEjE;EAET,MAAM;EACN,oBAAoB;CACtB,CAAC;CAED,EAAa,SAAS,eAAe;EACnC,SAAQ,MAAS,kBAAC,GAAD;GAAc,GAAI;GAAO,OAAO;EAAc,CAAA;EAC/D,eAAe;EACf,OAAM,MAAO,kBAAC,GAAD,EAAiB,aAAa,EAAI,SAAS,EAAI,CAAA;EAC5D,oBAAoB;CACtB,CAAC;CAED,EAAa,SAAS,MAAM;EAC1B,SAAQ,MAAS,kBAAC,GAAD;GAAc,GAAI;GAAO,OAAO;EAAK,CAAA;EACtD,eAAe;EACf,OAAM,MACJ,kBAAA,GAAA,EAAA,UACE,kBAAC,GAAD;GACE,IAAI,IAAI,EAAuC,GAAG,EAAI,SAAS;aAChE;EAEK,CAAA,EACN,CAAA;EAEJ,MAAM;EACN,oBAAoB;CACtB,CAAC;AACH;AAEA,SAAgB,IAAgC;CAC9C,IAAM,CAAC,GAAgB,KAAqB,EAAuB,CACjE;EACE,MAAM;EACN,IAAI;CACN,CACF,CAAC,GAEK,EACJ,MAAM,GACN,cACA,gBACA,uBACA,qBACE,EAA8C,EAChD,MAAM,EAAoC,CAAc,EAC1D,CAAC,GAOK,IAAQ,EAAc;EACpB,MANK,QACL,GAAc,MAAM,SAAQ,MAAQ,EAAK,WAAW,CAAC,CAAC,KAAK,CAAC,GAClE,CAAC,CAAY,CAIP;EACN;EACA,iBAAiB,EAAgB;EACjC,eAAe;EACf,kBAAkB;EAClB,OAAO,EACL,SAAS,EACX;EACA,iBAAiB;CACnB,CAAC,GAEK,IAAU,CAAC,KAAa,EAAM,YAAY,EAAE,KAAK,WAAW;CAElE,OACE,kBAAC,GAAD;EACE,OAAO,kBAAC,GAAD;GAA4B;GAAO,WAAW;EAAO,CAAA;EACjD;EACX,QAAQ,kBAAC,GAAD;GAAe,SAAS,EAAQ;GAAQ,gBAAA;EAAgB,CAAA;EACvD;EACT,WACE,kBAAC,GAAD;GAAY,SAAS;GAAS,IAAI;IAAE,WAAW;IAAU,IAAI;GAAE;aAAG;EAEtD,CAAA;EAED;EACb,8BAA8B;GAC5B,EAAmB;EACrB;EACoB;CACrB,CAAA;AAEL"}
|
|
@@ -11,8 +11,8 @@ import { useGetPortal as r } from "../../synapse-queries/portal/usePortal.js";
|
|
|
11
11
|
import { useGetCurrentUserProfile as i } from "../../synapse-queries/user/useUserBundle.js";
|
|
12
12
|
import { useCreateOrUpdateDOI as a, useGetDOI as ue } from "../../synapse-queries/doi/useDOI.js";
|
|
13
13
|
import { MarkdownPopover as de } from "../Markdown/MarkdownPopover.js";
|
|
14
|
-
import { DialogBase as
|
|
15
|
-
import
|
|
14
|
+
import { DialogBase as o } from "../DialogBase.js";
|
|
15
|
+
import fe from "../Dialog/ConfirmCloseWithoutSavingDialog.js";
|
|
16
16
|
import { doiFormSchema as pe, doiFormUiSchema as me } from "./DoiFormSchemas.js";
|
|
17
17
|
import { PrivateEntityDoiWarning as he } from "./PrivateEntityDoiWarning.js";
|
|
18
18
|
import { JsonSchemaForm as ge } from "../JsonSchemaForm/JsonSchemaForm.js";
|
|
@@ -117,7 +117,7 @@ function E(u) {
|
|
|
117
117
|
H
|
|
118
118
|
]);
|
|
119
119
|
function Ne() {
|
|
120
|
-
if (J.current
|
|
120
|
+
if (J.current?.validateForm()) {
|
|
121
121
|
let e = T(z);
|
|
122
122
|
e.objectType = D, e.objectId = O, e.objectVersion = L, e.etag = W?.etag, e.portalId = A, je({
|
|
123
123
|
doi: e,
|
|
@@ -224,7 +224,7 @@ function E(u) {
|
|
|
224
224
|
})
|
|
225
225
|
})
|
|
226
226
|
] });
|
|
227
|
-
return /* @__PURE__ */ _(h, { children: [/* @__PURE__ */ g(
|
|
227
|
+
return /* @__PURE__ */ _(h, { children: [/* @__PURE__ */ g(fe, {
|
|
228
228
|
open: we,
|
|
229
229
|
onCancel: () => {
|
|
230
230
|
j(!1);
|
|
@@ -232,7 +232,7 @@ function E(u) {
|
|
|
232
232
|
onConfirm: () => {
|
|
233
233
|
j(!1), E();
|
|
234
234
|
}
|
|
235
|
-
}), /* @__PURE__ */ g(
|
|
235
|
+
}), /* @__PURE__ */ g(o, {
|
|
236
236
|
open: y,
|
|
237
237
|
onCancel: I,
|
|
238
238
|
title: M === "warning" ? "This page is private" : "Create or Update a DOI",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CreateOrUpdateDoiModal.js","names":[],"sources":["../../../src/components/doi/CreateOrUpdateDoiModal.tsx"],"sourcesContent":["import ConfirmCloseWithoutSavingDialog from '@/components/Dialog/ConfirmCloseWithoutSavingDialog'\nimport { DialogBase } from '@/components/DialogBase'\nimport { doiFormSchema, doiFormUiSchema } from '@/components/doi/DoiFormSchemas'\nimport { PrivateEntityDoiWarning } from '@/components/doi/PrivateEntityDoiWarning'\nimport { JsonSchemaForm } from '@/components/JsonSchemaForm/JsonSchemaForm'\nimport { MarkdownPopover } from '@/components/Markdown/MarkdownPopover'\nimport { StyledFormControl } from '@/components/styled/StyledFormControl'\nimport { displayToast } from '@/components/ToastMessage/ToastMessage'\nimport { useCreateOrUpdateDOI, useGetDOI } from '@/synapse-queries/doi/useDOI'\nimport { useGetVersions } from '@/synapse-queries/entity/useEntity'\nimport { useGetEntityBundle } from '@/synapse-queries/entity/useEntityBundle'\nimport { useGetPortal } from '@/synapse-queries/portal/usePortal'\nimport { useGetRealmPrincipals } from '@/synapse-queries/realm/useRealmPrincipals'\nimport { useGetCurrentUserProfile } from '@/synapse-queries/user/useUserBundle'\nimport { useGlobalIsEditingContext } from '@/utils/context/GlobalIsEditingContext'\nimport { isEntityPublic } from '@/utils/functions/AccessControlListUtils'\nimport {\n entityTypeToFriendlyName,\n isDataset,\n isTable,\n isVersionableEntity,\n} from '@/utils/functions/EntityTypeUtils'\nimport {\n BackendDestinationEnum,\n getEndpoint,\n} from '@/utils/functions/getEndpoint'\nimport { DATA_CATALOG_PATH_SEGMENT } from '@/utils/SynapseConstants'\nimport { HelpTwoTone } from '@mui/icons-material'\nimport {\n Alert,\n Button,\n InputLabel,\n Link,\n MenuItem,\n Select,\n TextField,\n Typography,\n} from '@mui/material'\nimport RJSF from '@rjsf/core'\nimport {\n DoiObjectType,\n DoiResourceTypeGeneral,\n DoiResourceTypeResourceTypeGeneralEnum,\n EntityType,\n V2Doi,\n} from '@sage-bionetworks/synapse-client'\nimport { isEmpty } from 'lodash-es'\nimport { useEffect, useMemo, useRef, useState } from 'react'\nimport { SynapseSpinner } from '../LoadingScreen/LoadingScreen'\n\ntype CreateOrUpdateDoiModalStep = 'warning' | 'form'\n\nexport type CreateOrUpdateDoiModalProps = {\n /** Whether the dialog is open */\n open: boolean\n /** Callback to call when the dialog is closed */\n onClose: () => void\n /** The type of object */\n objectType: DoiObjectType\n /** The ID of the object */\n objectId: string\n /** The optional version number of the object used to populate the form. */\n defaultVersionNumber?: number\n /** If minting a DOI for a portal, the ID of the portal object in Synapse */\n portalId?: string\n}\n\ntype DoiFormData = {\n titles?: string[]\n creators?: string[]\n resourceTypeGeneral?: DoiResourceTypeResourceTypeGeneralEnum\n publicationYear?: number\n}\n\nfunction getSuggestedResourceTypeGeneral(\n type: EntityType,\n): DoiResourceTypeGeneral {\n if (type === EntityType.project || type === EntityType.folder) {\n return DoiResourceTypeGeneral.Collection\n } else {\n return DoiResourceTypeGeneral.Dataset\n }\n}\n\nfunction convertDoiToFormData(doi: V2Doi): DoiFormData {\n return {\n titles: (doi.titles || []).map(title => title.title!),\n creators: (doi.creators || []).map(creator => creator.creatorName!),\n resourceTypeGeneral: doi.resourceType?.resourceTypeGeneral,\n publicationYear: doi.publicationYear,\n }\n}\n\n/**\n * Returns true if the DOI has fields that are not exposed in the UI, so we can let the user know that any changes\n * may be destructive to hidden fields.\n */\nfunction getWasModifiedViaAPI(doi: V2Doi) {\n if (doi.creators?.some(creator => !isEmpty(creator.nameIdentifiers))) {\n return true\n }\n return false\n}\n\nfunction convertFormDataToDoi(formData: DoiFormData): V2Doi {\n return {\n titles: formData.titles?.map(title => ({ title })) || [],\n creators:\n formData.creators?.map(creator => ({ creatorName: creator })) || [],\n resourceType: {\n resourceTypeGeneral: formData.resourceTypeGeneral,\n },\n publicationYear: formData.publicationYear,\n }\n}\n\nexport function CreateOrUpdateDoiModal(props: CreateOrUpdateDoiModalProps) {\n const {\n open,\n onClose,\n objectType,\n objectId,\n defaultVersionNumber,\n portalId,\n } = props\n\n const [showConfirmCloseModal, setShowConfirmCloseDialog] = useState(false)\n const [currentStep, setCurrentStep] =\n useState<CreateOrUpdateDoiModalStep | null>(null)\n const hasSetInitialStepForThisSession = useRef(false)\n const { isEditing, setIsEditing } = useGlobalIsEditingContext()\n useEffect(() => {\n setIsEditing(open)\n\n return () => {\n setIsEditing(false)\n }\n }, [open, setIsEditing])\n\n function handleClose() {\n if (isEditing) {\n setShowConfirmCloseDialog(true)\n } else {\n onClose()\n }\n }\n\n const [selectedVersionNumber, setSelectedVersionNumber] =\n useState(defaultVersionNumber)\n\n const { data: portal } = useGetPortal(portalId!, {\n enabled: Boolean(portalId),\n })\n\n const [formData, setFormData] = useState<DoiFormData>({\n titles: [''],\n creators: [''],\n })\n const { data: currentUser, isLoading: isLoadingCurrentUser } =\n useGetCurrentUserProfile()\n const { data: entityBundle, isLoading: isLoadingEntity } = useGetEntityBundle(\n objectId,\n selectedVersionNumber,\n {\n includeEntity: true,\n includeBenefactorACL: true,\n },\n {\n enabled: objectType === DoiObjectType.ENTITY,\n staleTime: Infinity,\n throwOnError: true,\n },\n )\n const { data: realmPrincipals, isLoading: isLoadingRealmPrincipals } =\n useGetRealmPrincipals()\n const { data: doi, isLoading: isLoadingDoi } = useGetDOI(\n {\n id: objectId,\n version: selectedVersionNumber,\n type: objectType,\n portalId: portalId,\n },\n {\n staleTime: Infinity,\n throwOnError: true,\n },\n )\n\n const shouldShowWarning = useMemo(() => {\n if (objectType !== DoiObjectType.ENTITY) {\n return false\n }\n return (\n open &&\n doi === null && // Creating new DOI\n entityBundle?.benefactorAcl &&\n realmPrincipals &&\n !isEntityPublic(\n entityBundle.benefactorAcl.resourceAccess,\n realmPrincipals,\n )\n )\n }, [open, doi, entityBundle, realmPrincipals, objectType])\n\n useEffect(() => {\n if (\n open &&\n !hasSetInitialStepForThisSession.current &&\n doi !== undefined && // Wait for DOI query to resolve before determining step\n shouldShowWarning !== undefined\n ) {\n const newStep = shouldShowWarning ? 'warning' : 'form'\n setCurrentStep(newStep)\n hasSetInitialStepForThisSession.current = true\n } else if (!open) {\n setCurrentStep(null)\n hasSetInitialStepForThisSession.current = false\n }\n }, [shouldShowWarning, open, doi])\n\n const doiCanBeAppliedToVersion =\n objectType === DoiObjectType.ENTITY &&\n entityBundle?.entity &&\n isVersionableEntity(entityBundle.entity)\n\n const { data: entityVersions } = useGetVersions(\n objectId,\n undefined,\n undefined,\n {\n enabled: doiCanBeAppliedToVersion,\n },\n )\n const formRef = useRef<RJSF>(null)\n\n const entityType = entityBundle?.entityType ?? EntityType.file\n const entityTypeDisplay = entityTypeToFriendlyName(entityType)\n let versionHelpMarkdown = `A DOI can be associated with a specific version of this ${entityTypeDisplay}.\n \n Versioned DOIs will link to the specified version of the ${entityTypeDisplay}.\n \n A DOI without a version will always link to the newest version of this ${entityTypeDisplay},\n so the data that someone retrieves using the DOI may change over time.`\n if (entityBundle?.entity && isTable(entityBundle.entity)) {\n const tableVersionCopy = isDataset(entityBundle.entity)\n ? 'version'\n : 'snapshot'\n versionHelpMarkdown += `\\n\\nTo create a DOI that will always link to the current set of data in the ${entityTypeDisplay},\n create a new ${tableVersionCopy} and mint a DOI for that ${tableVersionCopy}.`\n }\n\n const {\n mutate: createOrUpdateDoi,\n isPending: updateIsPending,\n error: updateDoiError,\n } = useCreateOrUpdateDOI({\n onSuccess: () => {\n displayToast('The DOI was successfully updated.', 'success')\n onClose()\n },\n })\n\n const isLoading =\n updateIsPending ||\n isLoadingCurrentUser ||\n isLoadingEntity ||\n isLoadingDoi ||\n isLoadingRealmPrincipals\n\n const wasModifiedViaAPI = Boolean(doi && getWasModifiedViaAPI(doi))\n\n useEffect(() => {\n if (doi) {\n setFormData(convertDoiToFormData(doi))\n }\n // If there is no DOI, then pre-fill the form.\n if (currentUser && entityBundle?.entity && doi === null) {\n const newFormData = {\n titles: [entityBundle.entity.name],\n creators: new Array<string>(),\n resourceTypeGeneral: getSuggestedResourceTypeGeneral(\n entityBundle.entityType,\n ),\n publicationYear: new Date().getFullYear(),\n } satisfies DoiFormData\n if (currentUser.lastName && currentUser.firstName) {\n newFormData.creators.push(\n `${currentUser.lastName}, ${currentUser.firstName}`,\n )\n }\n setFormData(newFormData)\n }\n }, [currentUser, doi, entityBundle])\n\n function onSave() {\n if (formRef.current && formRef.current.validateForm()) {\n const requestDoi: V2Doi = convertFormDataToDoi(formData)\n requestDoi.objectType = objectType\n requestDoi.objectId = objectId\n requestDoi.objectVersion = selectedVersionNumber\n requestDoi.etag = doi?.etag\n requestDoi.portalId = portalId\n createOrUpdateDoi({\n doi: requestDoi,\n concreteType: 'org.sagebionetworks.repo.model.doi.v2.DoiRequest',\n })\n }\n }\n\n const dialogContent = (\n <>\n <Typography variant={'body1'} gutterBottom>\n Minting a DOI allows you to credit contributors and makes it easy to\n cite your work.\n </Typography>\n <Typography variant={'body1'} gutterBottom sx={{ mb: 2 }}>\n Note that while the DOI and its associated metadata will be publicly\n visible outside of Synapse, your data will still adhere to its existing\n access conditions. If your data is private, it will remain restricted,\n but the DOI will still be listed. Resources with DOIs may be added to\n the{' '}\n <Link\n href={`${getEndpoint(\n BackendDestinationEnum.PORTAL_ENDPOINT,\n )}${DATA_CATALOG_PATH_SEGMENT}`}\n target=\"_blank\"\n rel=\"noopener\"\n >\n Synapse Data Catalog\n </Link>\n .\n </Typography>\n {portalId && (\n <TextField\n label={'Publisher'}\n fullWidth\n value={portal?.name || ''}\n disabled\n />\n )}\n {doiCanBeAppliedToVersion && (\n <StyledFormControl className=\"limit-type\" fullWidth sx={{ my: 2 }}>\n <InputLabel\n id=\"doi-version-select\"\n sx={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n width: '100%',\n }}\n >\n <span>Version</span>\n <MarkdownPopover\n contentProps={{ markdown: versionHelpMarkdown }}\n maxWidth=\"350px\"\n >\n <HelpTwoTone className={`HelpButton`} />\n </MarkdownPopover>\n </InputLabel>\n <Select\n labelId=\"doi-version-select\"\n value={selectedVersionNumber ?? -1}\n onChange={e => {\n if (e.target.value === -1) {\n setSelectedVersionNumber(undefined)\n } else {\n setSelectedVersionNumber(e.target.value)\n }\n }}\n >\n <MenuItem value={-1}>No version</MenuItem>\n {entityVersions &&\n entityVersions.results.map(version => (\n <MenuItem\n key={version.versionNumber}\n value={version.versionNumber}\n >\n Version {version.versionNumber}\n {/* display the version label if it exists & is different from the number itself */}\n {version.versionLabel &&\n version.versionLabel !== String(version.versionNumber)\n ? ` / ${version.versionLabel}`\n : ''}\n </MenuItem>\n ))}\n </Select>\n </StyledFormControl>\n )}\n <JsonSchemaForm\n formRef={formRef}\n disabled={isLoading || wasModifiedViaAPI}\n schema={doiFormSchema}\n formData={formData}\n onChange={e => {\n setFormData(e.formData)\n }}\n uiSchema={doiFormUiSchema}\n showErrorList={false}\n />\n {doi && (\n <Alert severity={'warning'}>\n <Typography variant={'body1'}>\n A DOI has already been created. Updating the DOI information will\n cause old information to be lost!\n </Typography>\n </Alert>\n )}\n {wasModifiedViaAPI && (\n <Alert severity={'warning'} sx={{ my: 1 }}>\n <Typography variant={'body1'}>\n The metadata for this DOI was modified using a programmatic client,\n so data may be hidden from this view. Any changes may result in\n metadata being lost.\n </Typography>\n </Alert>\n )}\n {updateDoiError && (\n <Alert severity={'error'} sx={{ mt: 1 }}>\n <Typography variant={'body1'}>{updateDoiError.message}</Typography>\n </Alert>\n )}\n </>\n )\n\n const dialogActions = (\n <>\n <Button variant=\"outlined\" disabled={isLoading} onClick={handleClose}>\n Cancel\n </Button>\n <Button\n variant=\"contained\"\n disabled={isLoading}\n onClick={\n currentStep === 'warning'\n ? () => setCurrentStep('form')\n : e => {\n // SWC-7055 - The default action may trigger `beforeunload` and erroneously warn the user about leaving the page.\n e.preventDefault()\n onSave()\n }\n }\n >\n {currentStep === 'warning' ? 'Continue' : 'Save'}\n </Button>\n </>\n )\n\n return (\n <>\n <ConfirmCloseWithoutSavingDialog\n open={showConfirmCloseModal}\n onCancel={() => {\n setShowConfirmCloseDialog(false)\n }}\n onConfirm={() => {\n setShowConfirmCloseDialog(false)\n onClose()\n }}\n />\n <DialogBase\n open={open}\n onCancel={handleClose}\n title={\n currentStep === 'warning'\n ? 'This page is private'\n : 'Create or Update a DOI'\n }\n content={\n !currentStep ? (\n <SynapseSpinner />\n ) : (\n <>\n {currentStep === 'warning' && <PrivateEntityDoiWarning />}\n {currentStep === 'form' && dialogContent}\n </>\n )\n }\n actions={dialogActions}\n />\n </>\n )\n}\n\nexport default CreateOrUpdateDoiModal\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CreateOrUpdateDoiModal.js","names":[],"sources":["../../../src/components/doi/CreateOrUpdateDoiModal.tsx"],"sourcesContent":["import ConfirmCloseWithoutSavingDialog from '@/components/Dialog/ConfirmCloseWithoutSavingDialog'\nimport { DialogBase } from '@/components/DialogBase'\nimport { doiFormSchema, doiFormUiSchema } from '@/components/doi/DoiFormSchemas'\nimport { PrivateEntityDoiWarning } from '@/components/doi/PrivateEntityDoiWarning'\nimport { JsonSchemaForm } from '@/components/JsonSchemaForm/JsonSchemaForm'\nimport { MarkdownPopover } from '@/components/Markdown/MarkdownPopover'\nimport { StyledFormControl } from '@/components/styled/StyledFormControl'\nimport { displayToast } from '@/components/ToastMessage/ToastMessage'\nimport { useCreateOrUpdateDOI, useGetDOI } from '@/synapse-queries/doi/useDOI'\nimport { useGetVersions } from '@/synapse-queries/entity/useEntity'\nimport { useGetEntityBundle } from '@/synapse-queries/entity/useEntityBundle'\nimport { useGetPortal } from '@/synapse-queries/portal/usePortal'\nimport { useGetRealmPrincipals } from '@/synapse-queries/realm/useRealmPrincipals'\nimport { useGetCurrentUserProfile } from '@/synapse-queries/user/useUserBundle'\nimport { useGlobalIsEditingContext } from '@/utils/context/GlobalIsEditingContext'\nimport { isEntityPublic } from '@/utils/functions/AccessControlListUtils'\nimport {\n entityTypeToFriendlyName,\n isDataset,\n isTable,\n isVersionableEntity,\n} from '@/utils/functions/EntityTypeUtils'\nimport {\n BackendDestinationEnum,\n getEndpoint,\n} from '@/utils/functions/getEndpoint'\nimport { DATA_CATALOG_PATH_SEGMENT } from '@/utils/SynapseConstants'\nimport { HelpTwoTone } from '@mui/icons-material'\nimport {\n Alert,\n Button,\n InputLabel,\n Link,\n MenuItem,\n Select,\n TextField,\n Typography,\n} from '@mui/material'\nimport RJSF from '@rjsf/core'\nimport {\n DoiObjectType,\n DoiResourceTypeGeneral,\n DoiResourceTypeResourceTypeGeneralEnum,\n EntityType,\n V2Doi,\n} from '@sage-bionetworks/synapse-client'\nimport { isEmpty } from 'lodash-es'\nimport { useEffect, useMemo, useRef, useState } from 'react'\nimport { SynapseSpinner } from '../LoadingScreen/LoadingScreen'\n\ntype CreateOrUpdateDoiModalStep = 'warning' | 'form'\n\nexport type CreateOrUpdateDoiModalProps = {\n /** Whether the dialog is open */\n open: boolean\n /** Callback to call when the dialog is closed */\n onClose: () => void\n /** The type of object */\n objectType: DoiObjectType\n /** The ID of the object */\n objectId: string\n /** The optional version number of the object used to populate the form. */\n defaultVersionNumber?: number\n /** If minting a DOI for a portal, the ID of the portal object in Synapse */\n portalId?: string\n}\n\ntype DoiFormData = {\n titles?: string[]\n creators?: string[]\n resourceTypeGeneral?: DoiResourceTypeResourceTypeGeneralEnum\n publicationYear?: number\n}\n\nfunction getSuggestedResourceTypeGeneral(\n type: EntityType,\n): DoiResourceTypeGeneral {\n if (type === EntityType.project || type === EntityType.folder) {\n return DoiResourceTypeGeneral.Collection\n } else {\n return DoiResourceTypeGeneral.Dataset\n }\n}\n\nfunction convertDoiToFormData(doi: V2Doi): DoiFormData {\n return {\n titles: (doi.titles || []).map(title => title.title!),\n creators: (doi.creators || []).map(creator => creator.creatorName!),\n resourceTypeGeneral: doi.resourceType?.resourceTypeGeneral,\n publicationYear: doi.publicationYear,\n }\n}\n\n/**\n * Returns true if the DOI has fields that are not exposed in the UI, so we can let the user know that any changes\n * may be destructive to hidden fields.\n */\nfunction getWasModifiedViaAPI(doi: V2Doi) {\n if (doi.creators?.some(creator => !isEmpty(creator.nameIdentifiers))) {\n return true\n }\n return false\n}\n\nfunction convertFormDataToDoi(formData: DoiFormData): V2Doi {\n return {\n titles: formData.titles?.map(title => ({ title })) || [],\n creators:\n formData.creators?.map(creator => ({ creatorName: creator })) || [],\n resourceType: {\n resourceTypeGeneral: formData.resourceTypeGeneral,\n },\n publicationYear: formData.publicationYear,\n }\n}\n\nexport function CreateOrUpdateDoiModal(props: CreateOrUpdateDoiModalProps) {\n const {\n open,\n onClose,\n objectType,\n objectId,\n defaultVersionNumber,\n portalId,\n } = props\n\n const [showConfirmCloseModal, setShowConfirmCloseDialog] = useState(false)\n const [currentStep, setCurrentStep] =\n useState<CreateOrUpdateDoiModalStep | null>(null)\n const hasSetInitialStepForThisSession = useRef(false)\n const { isEditing, setIsEditing } = useGlobalIsEditingContext()\n useEffect(() => {\n setIsEditing(open)\n\n return () => {\n setIsEditing(false)\n }\n }, [open, setIsEditing])\n\n function handleClose() {\n if (isEditing) {\n setShowConfirmCloseDialog(true)\n } else {\n onClose()\n }\n }\n\n const [selectedVersionNumber, setSelectedVersionNumber] =\n useState(defaultVersionNumber)\n\n const { data: portal } = useGetPortal(portalId!, {\n enabled: Boolean(portalId),\n })\n\n const [formData, setFormData] = useState<DoiFormData>({\n titles: [''],\n creators: [''],\n })\n const { data: currentUser, isLoading: isLoadingCurrentUser } =\n useGetCurrentUserProfile()\n const { data: entityBundle, isLoading: isLoadingEntity } = useGetEntityBundle(\n objectId,\n selectedVersionNumber,\n {\n includeEntity: true,\n includeBenefactorACL: true,\n },\n {\n enabled: objectType === DoiObjectType.ENTITY,\n staleTime: Infinity,\n throwOnError: true,\n },\n )\n const { data: realmPrincipals, isLoading: isLoadingRealmPrincipals } =\n useGetRealmPrincipals()\n const { data: doi, isLoading: isLoadingDoi } = useGetDOI(\n {\n id: objectId,\n version: selectedVersionNumber,\n type: objectType,\n portalId: portalId,\n },\n {\n staleTime: Infinity,\n throwOnError: true,\n },\n )\n\n const shouldShowWarning = useMemo(() => {\n if (objectType !== DoiObjectType.ENTITY) {\n return false\n }\n return (\n open &&\n doi === null && // Creating new DOI\n entityBundle?.benefactorAcl &&\n realmPrincipals &&\n !isEntityPublic(\n entityBundle.benefactorAcl.resourceAccess,\n realmPrincipals,\n )\n )\n }, [open, doi, entityBundle, realmPrincipals, objectType])\n\n useEffect(() => {\n if (\n open &&\n !hasSetInitialStepForThisSession.current &&\n doi !== undefined && // Wait for DOI query to resolve before determining step\n shouldShowWarning !== undefined\n ) {\n const newStep = shouldShowWarning ? 'warning' : 'form'\n setCurrentStep(newStep)\n hasSetInitialStepForThisSession.current = true\n } else if (!open) {\n setCurrentStep(null)\n hasSetInitialStepForThisSession.current = false\n }\n }, [shouldShowWarning, open, doi])\n\n const doiCanBeAppliedToVersion =\n objectType === DoiObjectType.ENTITY &&\n entityBundle?.entity &&\n isVersionableEntity(entityBundle.entity)\n\n const { data: entityVersions } = useGetVersions(\n objectId,\n undefined,\n undefined,\n {\n enabled: doiCanBeAppliedToVersion,\n },\n )\n const formRef = useRef<RJSF>(null)\n\n const entityType = entityBundle?.entityType ?? EntityType.file\n const entityTypeDisplay = entityTypeToFriendlyName(entityType)\n let versionHelpMarkdown = `A DOI can be associated with a specific version of this ${entityTypeDisplay}.\n \n Versioned DOIs will link to the specified version of the ${entityTypeDisplay}.\n \n A DOI without a version will always link to the newest version of this ${entityTypeDisplay},\n so the data that someone retrieves using the DOI may change over time.`\n if (entityBundle?.entity && isTable(entityBundle.entity)) {\n const tableVersionCopy = isDataset(entityBundle.entity)\n ? 'version'\n : 'snapshot'\n versionHelpMarkdown += `\\n\\nTo create a DOI that will always link to the current set of data in the ${entityTypeDisplay},\n create a new ${tableVersionCopy} and mint a DOI for that ${tableVersionCopy}.`\n }\n\n const {\n mutate: createOrUpdateDoi,\n isPending: updateIsPending,\n error: updateDoiError,\n } = useCreateOrUpdateDOI({\n onSuccess: () => {\n displayToast('The DOI was successfully updated.', 'success')\n onClose()\n },\n })\n\n const isLoading =\n updateIsPending ||\n isLoadingCurrentUser ||\n isLoadingEntity ||\n isLoadingDoi ||\n isLoadingRealmPrincipals\n\n const wasModifiedViaAPI = Boolean(doi && getWasModifiedViaAPI(doi))\n\n useEffect(() => {\n if (doi) {\n setFormData(convertDoiToFormData(doi))\n }\n // If there is no DOI, then pre-fill the form.\n if (currentUser && entityBundle?.entity && doi === null) {\n const newFormData = {\n titles: [entityBundle.entity.name],\n creators: new Array<string>(),\n resourceTypeGeneral: getSuggestedResourceTypeGeneral(\n entityBundle.entityType,\n ),\n publicationYear: new Date().getFullYear(),\n } satisfies DoiFormData\n if (currentUser.lastName && currentUser.firstName) {\n newFormData.creators.push(\n `${currentUser.lastName}, ${currentUser.firstName}`,\n )\n }\n setFormData(newFormData)\n }\n }, [currentUser, doi, entityBundle])\n\n function onSave() {\n if (formRef.current?.validateForm()) {\n const requestDoi: V2Doi = convertFormDataToDoi(formData)\n requestDoi.objectType = objectType\n requestDoi.objectId = objectId\n requestDoi.objectVersion = selectedVersionNumber\n requestDoi.etag = doi?.etag\n requestDoi.portalId = portalId\n createOrUpdateDoi({\n doi: requestDoi,\n concreteType: 'org.sagebionetworks.repo.model.doi.v2.DoiRequest',\n })\n }\n }\n\n const dialogContent = (\n <>\n <Typography variant={'body1'} gutterBottom>\n Minting a DOI allows you to credit contributors and makes it easy to\n cite your work.\n </Typography>\n <Typography variant={'body1'} gutterBottom sx={{ mb: 2 }}>\n Note that while the DOI and its associated metadata will be publicly\n visible outside of Synapse, your data will still adhere to its existing\n access conditions. If your data is private, it will remain restricted,\n but the DOI will still be listed. Resources with DOIs may be added to\n the{' '}\n <Link\n href={`${getEndpoint(\n BackendDestinationEnum.PORTAL_ENDPOINT,\n )}${DATA_CATALOG_PATH_SEGMENT}`}\n target=\"_blank\"\n rel=\"noopener\"\n >\n Synapse Data Catalog\n </Link>\n .\n </Typography>\n {portalId && (\n <TextField\n label={'Publisher'}\n fullWidth\n value={portal?.name || ''}\n disabled\n />\n )}\n {doiCanBeAppliedToVersion && (\n <StyledFormControl className=\"limit-type\" fullWidth sx={{ my: 2 }}>\n <InputLabel\n id=\"doi-version-select\"\n sx={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n width: '100%',\n }}\n >\n <span>Version</span>\n <MarkdownPopover\n contentProps={{ markdown: versionHelpMarkdown }}\n maxWidth=\"350px\"\n >\n <HelpTwoTone className={`HelpButton`} />\n </MarkdownPopover>\n </InputLabel>\n <Select\n labelId=\"doi-version-select\"\n value={selectedVersionNumber ?? -1}\n onChange={e => {\n if (e.target.value === -1) {\n setSelectedVersionNumber(undefined)\n } else {\n setSelectedVersionNumber(e.target.value)\n }\n }}\n >\n <MenuItem value={-1}>No version</MenuItem>\n {entityVersions &&\n entityVersions.results.map(version => (\n <MenuItem\n key={version.versionNumber}\n value={version.versionNumber}\n >\n Version {version.versionNumber}\n {/* display the version label if it exists & is different from the number itself */}\n {version.versionLabel &&\n version.versionLabel !== String(version.versionNumber)\n ? ` / ${version.versionLabel}`\n : ''}\n </MenuItem>\n ))}\n </Select>\n </StyledFormControl>\n )}\n <JsonSchemaForm\n formRef={formRef}\n disabled={isLoading || wasModifiedViaAPI}\n schema={doiFormSchema}\n formData={formData}\n onChange={e => {\n setFormData(e.formData)\n }}\n uiSchema={doiFormUiSchema}\n showErrorList={false}\n />\n {doi && (\n <Alert severity={'warning'}>\n <Typography variant={'body1'}>\n A DOI has already been created. Updating the DOI information will\n cause old information to be lost!\n </Typography>\n </Alert>\n )}\n {wasModifiedViaAPI && (\n <Alert severity={'warning'} sx={{ my: 1 }}>\n <Typography variant={'body1'}>\n The metadata for this DOI was modified using a programmatic client,\n so data may be hidden from this view. Any changes may result in\n metadata being lost.\n </Typography>\n </Alert>\n )}\n {updateDoiError && (\n <Alert severity={'error'} sx={{ mt: 1 }}>\n <Typography variant={'body1'}>{updateDoiError.message}</Typography>\n </Alert>\n )}\n </>\n )\n\n const dialogActions = (\n <>\n <Button variant=\"outlined\" disabled={isLoading} onClick={handleClose}>\n Cancel\n </Button>\n <Button\n variant=\"contained\"\n disabled={isLoading}\n onClick={\n currentStep === 'warning'\n ? () => setCurrentStep('form')\n : e => {\n // SWC-7055 - The default action may trigger `beforeunload` and erroneously warn the user about leaving the page.\n e.preventDefault()\n onSave()\n }\n }\n >\n {currentStep === 'warning' ? 'Continue' : 'Save'}\n </Button>\n </>\n )\n\n return (\n <>\n <ConfirmCloseWithoutSavingDialog\n open={showConfirmCloseModal}\n onCancel={() => {\n setShowConfirmCloseDialog(false)\n }}\n onConfirm={() => {\n setShowConfirmCloseDialog(false)\n onClose()\n }}\n />\n <DialogBase\n open={open}\n onCancel={handleClose}\n title={\n currentStep === 'warning'\n ? 'This page is private'\n : 'Create or Update a DOI'\n }\n content={\n !currentStep ? (\n <SynapseSpinner />\n ) : (\n <>\n {currentStep === 'warning' && <PrivateEntityDoiWarning />}\n {currentStep === 'form' && dialogContent}\n </>\n )\n }\n actions={dialogActions}\n />\n </>\n )\n}\n\nexport default CreateOrUpdateDoiModal\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AA0EA,SAAS,EACP,GACwB;CAItB,OAHE,MAAS,EAAW,WAAW,MAAS,EAAW,SAC9C,EAAuB,aAEvB,EAAuB;AAElC;AAEA,SAAS,EAAqB,GAAyB;CACrD,OAAO;EACL,SAAS,EAAI,UAAU,CAAC,GAAG,KAAI,MAAS,EAAM,KAAM;EACpD,WAAW,EAAI,YAAY,CAAC,GAAG,KAAI,MAAW,EAAQ,WAAY;EAClE,qBAAqB,EAAI,cAAc;EACvC,iBAAiB,EAAI;CACvB;AACF;AAMA,SAAS,EAAqB,GAAY;CAIxC,OAHA,EAAI,EAAI,UAAU,MAAK,MAAW,CAAC,EAAQ,EAAQ,eAAe,CAAC;AAIrE;AAEA,SAAS,EAAqB,GAA8B;CAC1D,OAAO;EACL,QAAQ,EAAS,QAAQ,KAAI,OAAU,EAAE,SAAM,EAAE,KAAK,CAAC;EACvD,UACE,EAAS,UAAU,KAAI,OAAY,EAAE,aAAa,EAAQ,EAAE,KAAK,CAAC;EACpE,cAAc,EACZ,qBAAqB,EAAS,oBAChC;EACA,iBAAiB,EAAS;CAC5B;AACF;AAEA,SAAgB,EAAuB,GAAoC;CACzE,IAAM,EACJ,SACA,YACA,eACA,aACA,yBACA,gBACE,GAEE,CAAC,IAAuB,KAA6B,EAAS,EAAK,GACnE,CAAC,GAAa,KAClB,EAA4C,IAAI,GAC5C,IAAkC,EAAO,EAAK,GAC9C,EAAE,eAAW,oBAAiB,GAA0B;CAC9D,SACE,EAAa,CAAI,SAEJ;EACX,EAAa,EAAK;CACpB,IACC,CAAC,GAAM,CAAY,CAAC;CAEvB,SAAS,IAAc;EACrB,AAAI,KACF,EAA0B,EAAI,IAE9B,EAAQ;CAEZ;CAEA,IAAM,CAAC,GAAuB,KAC5B,EAAS,CAAoB,GAEzB,EAAE,MAAM,OAAW,EAAa,GAAW,EAC/C,SAAS,EAAQ,EACnB,CAAC,GAEK,CAAC,GAAU,KAAe,EAAsB;EACpD,QAAQ,CAAC,EAAE;EACX,UAAU,CAAC,EAAE;CACf,CAAC,GACK,EAAE,MAAM,GAAa,WAAW,OACpC,EAAyB,GACrB,EAAE,MAAM,GAAc,WAAW,OAAoB,EACzD,GACA,GACA;EACE,eAAe;EACf,sBAAsB;CACxB,GACA;EACE,SAAS,MAAe,EAAc;EACtC,WAAW;EACX,cAAc;CAChB,CACF,GACM,EAAE,MAAM,GAAiB,WAAW,OACxC,GAAsB,GAClB,EAAE,MAAM,GAAK,WAAW,OAAiB,GAC7C;EACE,IAAI;EACJ,SAAS;EACT,MAAM;EACI;CACZ,GACA;EACE,WAAW;EACX,cAAc;CAChB,CACF,GAEM,IAAoB,SACpB,MAAe,EAAc,SAI/B,KACA,MAAQ,QACR,GAAc,iBACd,KACA,CAAC,GACC,EAAa,cAAc,gBAC3B,CACF,IAVO,IAYR;EAAC;EAAM;EAAK;EAAc;EAAiB;CAAU,CAAC;CAEzD,QAAgB;EACd,AACE,KACA,CAAC,EAAgC,WACjC,MAAQ,KAAA,KACR,MAAsB,KAAA,KAGtB,EADgB,IAAoB,YAAY,MAC1B,GACtB,EAAgC,UAAU,MAChC,MACV,EAAe,IAAI,GACnB,EAAgC,UAAU;CAE9C,GAAG;EAAC;EAAmB;EAAM;CAAG,CAAC;CAEjC,IAAM,IACJ,MAAe,EAAc,UAC7B,GAAc,UACd,GAAoB,EAAa,MAAM,GAEnC,EAAE,MAAM,MAAmB,EAC/B,GACA,KAAA,GACA,KAAA,GACA,EACE,SAAS,EACX,CACF,GACM,IAAU,EAAa,IAAI,GAG3B,IAAoB,GADP,GAAc,cAAc,EAAW,IACG,GACzD,IAAsB,2DAA2D,EAAkB;;6DAE5C,EAAkB;;2EAEJ,EAAkB;;CAE3F,IAAI,GAAc,UAAU,GAAQ,EAAa,MAAM,GAAG;EACxD,IAAM,IAAmB,GAAU,EAAa,MAAM,IAClD,YACA;EACJ,KAAuB,+EAA+E,EAAkB;oBACxG,EAAiB,2BAA2B,EAAiB;CAC/E;CAEA,IAAM,EACJ,QAAQ,IACR,WAAW,IACX,OAAO,MACL,EAAqB,EACvB,iBAAiB;EAEf,AADA,EAAa,qCAAqC,SAAS,GAC3D,EAAQ;CACV,EACF,CAAC,GAEK,IACJ,MACA,MACA,MACA,MACA,IAEI,IAAoB,GAAQ,KAAO,EAAqB,CAAG;CAEjE,QAAgB;EAKd,IAJI,KACF,EAAY,EAAqB,CAAG,CAAC,GAGnC,KAAe,GAAc,UAAU,MAAQ,MAAM;GACvD,IAAM,IAAc;IAClB,QAAQ,CAAC,EAAa,OAAO,IAAI;IACjC,UAAU,CAAkB;IAC5B,qBAAqB,EACnB,EAAa,UACf;IACA,kCAAiB,IAAI,KAAK,GAAE,YAAY;GAC1C;GAMA,AALI,EAAY,YAAY,EAAY,aACtC,EAAY,SAAS,KACnB,GAAG,EAAY,SAAS,IAAI,EAAY,WAC1C,GAEF,EAAY,CAAW;EACzB;CACF,GAAG;EAAC;EAAa;EAAK;CAAY,CAAC;CAEnC,SAAS,KAAS;EAChB,IAAI,EAAQ,SAAS,aAAa,GAAG;GACnC,IAAM,IAAoB,EAAqB,CAAQ;GAMvD,AALA,EAAW,aAAa,GACxB,EAAW,WAAW,GACtB,EAAW,gBAAgB,GAC3B,EAAW,OAAO,GAAK,MACvB,EAAW,WAAW,GACtB,GAAkB;IAChB,KAAK;IACL,cAAc;GAChB,CAAC;EACH;CACF;CAEA,IAAM,KACJ,kBAAA,GAAA,EAAA,UAAA;EACE,kBAAC,GAAD;GAAY,SAAS;GAAS,cAAA;aAAa;EAG/B,CAAA;EACZ,kBAAC,GAAD;GAAY,SAAS;GAAS,cAAA;GAAa,IAAI,EAAE,IAAI,EAAE;aAAvD;IAA0D;IAKpD;IACJ,kBAAC,IAAD;KACE,MAAM,GAAG,GACP,GAAuB,eACzB,IAAI;KACJ,QAAO;KACP,KAAI;eACL;IAEK,CAAA;IAAC;GAEG;;EACX,KACC,kBAAC,IAAD;GACE,OAAO;GACP,WAAA;GACA,OAAO,IAAQ,QAAQ;GACvB,UAAA;EACD,CAAA;EAEF,KACC,kBAAC,IAAD;GAAmB,WAAU;GAAa,WAAA;GAAU,IAAI,EAAE,IAAI,EAAE;aAAhE,CACE,kBAAC,IAAD;IACE,IAAG;IACH,IAAI;KACF,SAAS;KACT,YAAY;KACZ,gBAAgB;KAChB,OAAO;IACT;cAPF,CASE,kBAAC,QAAD,EAAA,UAAM,UAAa,CAAA,GACnB,kBAAC,IAAD;KACE,cAAc,EAAE,UAAU,EAAoB;KAC9C,UAAS;eAET,kBAAC,GAAD,EAAa,WAAW,aAAe,CAAA;IACxB,CAAA,CACP;OACZ,kBAAC,IAAD;IACE,SAAQ;IACR,OAAO,KAAyB;IAChC,WAAU,MAAK;KACb,AAAI,EAAE,OAAO,UAAU,KACrB,EAAyB,KAAA,CAAS,IAElC,EAAyB,EAAE,OAAO,KAAK;IAE3C;cATF,CAWE,kBAAC,GAAD;KAAU,OAAO;eAAI;IAAoB,CAAA,GACxC,KACC,EAAe,QAAQ,KAAI,MACzB,kBAAC,GAAD;KAEE,OAAO,EAAQ;eAFjB;MAGC;MACU,EAAQ;MAEhB,EAAQ,gBACT,EAAQ,iBAAiB,OAAO,EAAQ,aAAa,IACjD,MAAM,EAAQ,iBACd;KACI;OATH,EAAQ,aASL,CACX,CACG;KACS;;EAErB,kBAAC,IAAD;GACW;GACT,UAAU,KAAa;GACvB,QAAQ;GACE;GACV,WAAU,MAAK;IACb,EAAY,EAAE,QAAQ;GACxB;GACA,UAAU;GACV,eAAe;EAChB,CAAA;EACA,KACC,kBAAC,GAAD;GAAO,UAAU;aACf,kBAAC,GAAD;IAAY,SAAS;cAAS;GAGlB,CAAA;EACP,CAAA;EAER,KACC,kBAAC,GAAD;GAAO,UAAU;GAAW,IAAI,EAAE,IAAI,EAAE;aACtC,kBAAC,GAAD;IAAY,SAAS;cAAS;GAIlB,CAAA;EACP,CAAA;EAER,KACC,kBAAC,GAAD;GAAO,UAAU;GAAS,IAAI,EAAE,IAAI,EAAE;aACpC,kBAAC,GAAD;IAAY,SAAS;cAAU,EAAe;GAAoB,CAAA;EAC7D,CAAA;CAET,EAAA,CAAA;CA0BJ,OACE,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,IAAD;EACE,MAAM;EACN,gBAAgB;GACd,EAA0B,EAAK;EACjC;EACA,iBAAiB;GAEf,AADA,EAA0B,EAAK,GAC/B,EAAQ;EACV;CACD,CAAA,GACD,kBAAC,GAAD;EACQ;EACN,UAAU;EACV,OACE,MAAgB,YACZ,yBACA;EAEN,SACG,IAGC,kBAAA,GAAA,EAAA,UAAA,CACG,MAAgB,aAAa,kBAAC,IAAD,CAA0B,CAAA,GACvD,MAAgB,UAAU,EAC3B,EAAA,CAAA,IALF,kBAAC,IAAD,CAAiB,CAAA;EAQrB,SApDJ,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD;GAAQ,SAAQ;GAAW,UAAU;GAAW,SAAS;aAAa;EAE9D,CAAA,GACR,kBAAC,GAAD;GACE,SAAQ;GACR,UAAU;GACV,SACE,MAAgB,kBACN,EAAe,MAAM,KAC3B,MAAK;IAGH,AADA,EAAE,eAAe,GACjB,GAAO;GACT;aAGL,MAAgB,YAAY,aAAa;EACpC,CAAA,CACR,EAAA,CAiCW;CACV,CAAA,CACD,EAAA,CAAA;AAEN"}
|
|
@@ -21,7 +21,7 @@ function w(w) {
|
|
|
21
21
|
f(() => (j(L), () => {
|
|
22
22
|
j(!1);
|
|
23
23
|
}), [L, j]);
|
|
24
|
-
let { data: B } = o(T, E), V = B
|
|
24
|
+
let { data: B } = o(T, E), V = B?.permissions?.canEdit, H = B && i(B.entityType), U = H && B.entity.isLatestVersion, W = N === "METADATA" && B && !(typeof window < "u" && window.location.href.includes(T)), G = /* @__PURE__ */ x(_, {
|
|
25
25
|
variant: "contained",
|
|
26
26
|
onClick: () => window.open(`${n(t.PORTAL_ENDPOINT)}Synapse:${T}`, "_blank", "noopener"),
|
|
27
27
|
children: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EntityModal.js","names":[],"sources":["../../../../src/components/entity/metadata/EntityModal.tsx"],"sourcesContent":["import useGetEntityBundle from '@/synapse-queries/entity/useEntityBundle'\nimport {\n entityTypeToFriendlyName,\n isVersionableEntityType,\n} from '@/utils/functions/EntityTypeUtils'\nimport {\n BackendDestinationEnum,\n getEndpoint,\n} from '@/utils/functions/getEndpoint'\nimport { Button, Tooltip } from '@mui/material'\nimport Skeleton from '@mui/material/Skeleton'\nimport Form from '@rjsf/core'\nimport { VersionableEntity } from '@sage-bionetworks/synapse-types'\nimport { noop } from 'lodash-es'\nimport { useEffect, useMemo, useRef, useState } from 'react'\nimport { ConfirmationDialog } from '../../ConfirmationDialog'\nimport { DialogBase } from '../../DialogBase'\nimport { SynapseErrorBoundary } from '../../error/ErrorBanner'\nimport { SchemaDrivenAnnotationEditor } from '../../SchemaDrivenAnnotationEditor/SchemaDrivenAnnotationEditor'\nimport { displayToast } from '../../ToastMessage/ToastMessage'\nimport { AnnotationsTable } from './AnnotationsTable'\nimport { MetadataTable } from './MetadataTable'\n\nexport const EntityModalTabs = [\n // non-annotation metadata about the entity\n 'METADATA',\n // annotation and schema information\n 'ANNOTATIONS',\n // TODO: Access -- we haven't yet built a viewer/editor for ACLs in SRC -- consider a redesign before building\n //'ACCESS', // ACLs (and maybe ARs?)\n // TODO: Previews - we would need preview renderers that accomplish feature parity with SWC\n //'PREVIEW' // should only show this tab if a preview exists\n] as const\ntype EntityModalTab = (typeof EntityModalTabs)[number]\n\nexport type EntityModalProps = {\n readonly show: boolean\n readonly entityId: string\n readonly versionNumber?: number\n readonly onClose: () => void\n readonly initialTab?: EntityModalTab\n readonly showTabs?: boolean\n readonly onEditModeChanged?: (isInEditMode: boolean) => void\n}\n\nexport function EntityModal(props: EntityModalProps) {\n const {\n entityId,\n versionNumber,\n show,\n onClose,\n initialTab = 'METADATA',\n showTabs = true,\n onEditModeChanged = noop,\n } = props\n const annotationEditorFormRef = useRef<Form>(null)\n\n const [currentTab, setCurrentTab] = useState<EntityModalTab>(initialTab)\n const [showEditCancellationWarning, setShowEditCancellationWarning] =\n useState(false)\n const [isInEditMode, setIsInEditMode] = useState(false)\n\n // Need to store variable behavior for when the user confirms they want to cancel editing\n // We may return to the readonly view, or we might close the entire modal, depending on what they clicked.\n const [onCancelEdit, setOnCancelEdit] = useState<() => void>(() =>\n setIsInEditMode(false),\n )\n\n // Call the callback if `isInEditMode` changes\n // e.g. to set the global isInEditMode tracker in SWC\n useEffect(() => {\n onEditModeChanged(isInEditMode)\n return () => {\n // Ensure we disable edit mode when the component unmounts\n onEditModeChanged(false)\n }\n }, [isInEditMode, onEditModeChanged])\n\n const { data: entityBundle } = useGetEntityBundle(entityId, versionNumber)\n const canEdit = entityBundle && entityBundle.permissions.canEdit\n\n const isVersionable =\n entityBundle && isVersionableEntityType(entityBundle.entityType)\n\n const isLatestVersion =\n isVersionable && (entityBundle.entity as VersionableEntity).isLatestVersion!\n\n const showOpenEntityPageButton =\n currentTab === 'METADATA' &&\n entityBundle &&\n !(typeof window !== 'undefined' && window.location.href.includes(entityId))\n const openEntityPageButton = (\n <Button\n variant={'contained'}\n onClick={() =>\n window.open(\n `${getEndpoint(\n BackendDestinationEnum.PORTAL_ENDPOINT,\n )}Synapse:${entityId}`,\n '_blank',\n 'noopener',\n )\n }\n >\n Open{' '}\n {entityBundle ? entityTypeToFriendlyName(entityBundle?.entityType) : ''}\n </Button>\n )\n\n const showSaveAnnotationsButton = currentTab === 'ANNOTATIONS' && isInEditMode\n const saveAnnotationsButton = (\n <Button\n variant={'contained'}\n onClick={() => {\n // Workaround for https://github.com/rjsf-team/react-jsonschema-form/issues/3121\n annotationEditorFormRef.current!.formElement.current.requestSubmit()\n }}\n >\n Save Annotations\n </Button>\n )\n\n const showCancelAnnotationEditsButton =\n currentTab === 'ANNOTATIONS' && isInEditMode\n const cancelAnnotationEditsButton = (\n <Button\n variant={'outlined'}\n onClick={() => {\n setOnCancelEdit(() => () => setIsInEditMode(false))\n setShowEditCancellationWarning(true)\n }}\n >\n Cancel\n </Button>\n )\n\n const showEditAnnotationsButton =\n canEdit && currentTab === 'ANNOTATIONS' && !isInEditMode\n const disableEditingOldVersion = isVersionable && !isLatestVersion\n const editAnnotationsButton = (\n <Tooltip\n title={\n disableEditingOldVersion\n ? 'Annotations can only be edited on the latest version'\n : undefined\n }\n >\n {/* Wrap in span so tooltip works even when disabled */}\n <span>\n <Button\n variant={'contained'}\n disabled={disableEditingOldVersion}\n onClick={() => {\n setIsInEditMode(true)\n }}\n >\n Edit\n </Button>\n </span>\n </Tooltip>\n )\n\n const dialogContent = (\n <>\n {showTabs && !isInEditMode ? (\n <div className=\"Tabs\">\n {EntityModalTabs.map(tabName => {\n return (\n <div\n className=\"Tab\"\n role=\"tab\"\n key={tabName}\n onClick={e => {\n e.stopPropagation()\n setCurrentTab(tabName)\n }}\n aria-selected={tabName === currentTab}\n >\n {tabName}\n </div>\n )\n })}\n </div>\n ) : null}\n <div style={currentTab === 'ANNOTATIONS' ? {} : { display: 'none' }}>\n {isInEditMode ? (\n <SynapseErrorBoundary>\n <SchemaDrivenAnnotationEditor\n entityId={entityId}\n formRef={annotationEditorFormRef}\n hideActions\n onSuccess={() => {\n displayToast('Annotations successfully updated.', 'success')\n setIsInEditMode(false)\n }}\n onCancel={() => setIsInEditMode(false)}\n />\n </SynapseErrorBoundary>\n ) : (\n <AnnotationsTable entityId={entityId} versionNumber={versionNumber} />\n )}\n </div>\n <div style={currentTab === 'METADATA' ? {} : { display: 'none' }}>\n <MetadataTable entityId={entityId} versionNumber={versionNumber} />\n </div>\n </>\n )\n\n const cancelEditingConfirmationModal = (\n <ConfirmationDialog\n open={showEditCancellationWarning}\n title=\"Unsaved Changes\"\n content=\"Any unsaved changes will be lost. Are you sure you want to close the editor?\"\n onCancel={() => {\n setShowEditCancellationWarning(false)\n }}\n onConfirm={() => {\n setShowEditCancellationWarning(false)\n onCancelEdit()\n }}\n />\n )\n\n const modalTitle = useMemo(() => {\n if (!entityBundle?.entity.name) {\n return <Skeleton width={'40%'} />\n } else if (currentTab === 'ANNOTATIONS') {\n return `${isInEditMode ? 'Edit ' : ''}Annotations for ${\n entityBundle.entity.name\n }`\n }\n return entityBundle.entity.name\n }, [currentTab, entityBundle?.entity.name, isInEditMode])\n\n return (\n <DialogBase\n className={`EntityMetadata`}\n open={show}\n onCancel={() => {\n if (isInEditMode) {\n setShowEditCancellationWarning(true)\n setOnCancelEdit(() => {\n // Need to return a function in a function because passing a function to setState has a different meaning\n return () => {\n setIsInEditMode(false)\n onClose()\n }\n })\n } else {\n onClose()\n }\n }}\n maxWidth={isInEditMode ? 'md' : 'sm'}\n title={modalTitle}\n content={dialogContent}\n actions={\n <>\n {cancelEditingConfirmationModal}\n {showCancelAnnotationEditsButton && cancelAnnotationEditsButton}\n {showSaveAnnotationsButton && saveAnnotationsButton}\n {showEditAnnotationsButton && editAnnotationsButton}\n {showOpenEntityPageButton && openEntityPageButton}\n </>\n }\n />\n )\n}\n\nexport default EntityModal\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"EntityModal.js","names":[],"sources":["../../../../src/components/entity/metadata/EntityModal.tsx"],"sourcesContent":["import useGetEntityBundle from '@/synapse-queries/entity/useEntityBundle'\nimport {\n entityTypeToFriendlyName,\n isVersionableEntityType,\n} from '@/utils/functions/EntityTypeUtils'\nimport {\n BackendDestinationEnum,\n getEndpoint,\n} from '@/utils/functions/getEndpoint'\nimport { Button, Tooltip } from '@mui/material'\nimport Skeleton from '@mui/material/Skeleton'\nimport Form from '@rjsf/core'\nimport { VersionableEntity } from '@sage-bionetworks/synapse-types'\nimport { noop } from 'lodash-es'\nimport { useEffect, useMemo, useRef, useState } from 'react'\nimport { ConfirmationDialog } from '../../ConfirmationDialog'\nimport { DialogBase } from '../../DialogBase'\nimport { SynapseErrorBoundary } from '../../error/ErrorBanner'\nimport { SchemaDrivenAnnotationEditor } from '../../SchemaDrivenAnnotationEditor/SchemaDrivenAnnotationEditor'\nimport { displayToast } from '../../ToastMessage/ToastMessage'\nimport { AnnotationsTable } from './AnnotationsTable'\nimport { MetadataTable } from './MetadataTable'\n\nexport const EntityModalTabs = [\n // non-annotation metadata about the entity\n 'METADATA',\n // annotation and schema information\n 'ANNOTATIONS',\n // TODO: Access -- we haven't yet built a viewer/editor for ACLs in SRC -- consider a redesign before building\n //'ACCESS', // ACLs (and maybe ARs?)\n // TODO: Previews - we would need preview renderers that accomplish feature parity with SWC\n //'PREVIEW' // should only show this tab if a preview exists\n] as const\ntype EntityModalTab = (typeof EntityModalTabs)[number]\n\nexport type EntityModalProps = {\n readonly show: boolean\n readonly entityId: string\n readonly versionNumber?: number\n readonly onClose: () => void\n readonly initialTab?: EntityModalTab\n readonly showTabs?: boolean\n readonly onEditModeChanged?: (isInEditMode: boolean) => void\n}\n\nexport function EntityModal(props: EntityModalProps) {\n const {\n entityId,\n versionNumber,\n show,\n onClose,\n initialTab = 'METADATA',\n showTabs = true,\n onEditModeChanged = noop,\n } = props\n const annotationEditorFormRef = useRef<Form>(null)\n\n const [currentTab, setCurrentTab] = useState<EntityModalTab>(initialTab)\n const [showEditCancellationWarning, setShowEditCancellationWarning] =\n useState(false)\n const [isInEditMode, setIsInEditMode] = useState(false)\n\n // Need to store variable behavior for when the user confirms they want to cancel editing\n // We may return to the readonly view, or we might close the entire modal, depending on what they clicked.\n const [onCancelEdit, setOnCancelEdit] = useState<() => void>(() =>\n setIsInEditMode(false),\n )\n\n // Call the callback if `isInEditMode` changes\n // e.g. to set the global isInEditMode tracker in SWC\n useEffect(() => {\n onEditModeChanged(isInEditMode)\n return () => {\n // Ensure we disable edit mode when the component unmounts\n onEditModeChanged(false)\n }\n }, [isInEditMode, onEditModeChanged])\n\n const { data: entityBundle } = useGetEntityBundle(entityId, versionNumber)\n const canEdit = entityBundle?.permissions?.canEdit\n\n const isVersionable =\n entityBundle && isVersionableEntityType(entityBundle.entityType)\n\n const isLatestVersion =\n isVersionable && (entityBundle.entity as VersionableEntity).isLatestVersion!\n\n const showOpenEntityPageButton =\n currentTab === 'METADATA' &&\n entityBundle &&\n !(typeof window !== 'undefined' && window.location.href.includes(entityId))\n const openEntityPageButton = (\n <Button\n variant={'contained'}\n onClick={() =>\n window.open(\n `${getEndpoint(\n BackendDestinationEnum.PORTAL_ENDPOINT,\n )}Synapse:${entityId}`,\n '_blank',\n 'noopener',\n )\n }\n >\n Open{' '}\n {entityBundle ? entityTypeToFriendlyName(entityBundle?.entityType) : ''}\n </Button>\n )\n\n const showSaveAnnotationsButton = currentTab === 'ANNOTATIONS' && isInEditMode\n const saveAnnotationsButton = (\n <Button\n variant={'contained'}\n onClick={() => {\n // Workaround for https://github.com/rjsf-team/react-jsonschema-form/issues/3121\n annotationEditorFormRef.current!.formElement.current.requestSubmit()\n }}\n >\n Save Annotations\n </Button>\n )\n\n const showCancelAnnotationEditsButton =\n currentTab === 'ANNOTATIONS' && isInEditMode\n const cancelAnnotationEditsButton = (\n <Button\n variant={'outlined'}\n onClick={() => {\n setOnCancelEdit(() => () => setIsInEditMode(false))\n setShowEditCancellationWarning(true)\n }}\n >\n Cancel\n </Button>\n )\n\n const showEditAnnotationsButton =\n canEdit && currentTab === 'ANNOTATIONS' && !isInEditMode\n const disableEditingOldVersion = isVersionable && !isLatestVersion\n const editAnnotationsButton = (\n <Tooltip\n title={\n disableEditingOldVersion\n ? 'Annotations can only be edited on the latest version'\n : undefined\n }\n >\n {/* Wrap in span so tooltip works even when disabled */}\n <span>\n <Button\n variant={'contained'}\n disabled={disableEditingOldVersion}\n onClick={() => {\n setIsInEditMode(true)\n }}\n >\n Edit\n </Button>\n </span>\n </Tooltip>\n )\n\n const dialogContent = (\n <>\n {showTabs && !isInEditMode ? (\n <div className=\"Tabs\">\n {EntityModalTabs.map(tabName => {\n return (\n <div\n className=\"Tab\"\n role=\"tab\"\n key={tabName}\n onClick={e => {\n e.stopPropagation()\n setCurrentTab(tabName)\n }}\n aria-selected={tabName === currentTab}\n >\n {tabName}\n </div>\n )\n })}\n </div>\n ) : null}\n <div style={currentTab === 'ANNOTATIONS' ? {} : { display: 'none' }}>\n {isInEditMode ? (\n <SynapseErrorBoundary>\n <SchemaDrivenAnnotationEditor\n entityId={entityId}\n formRef={annotationEditorFormRef}\n hideActions\n onSuccess={() => {\n displayToast('Annotations successfully updated.', 'success')\n setIsInEditMode(false)\n }}\n onCancel={() => setIsInEditMode(false)}\n />\n </SynapseErrorBoundary>\n ) : (\n <AnnotationsTable entityId={entityId} versionNumber={versionNumber} />\n )}\n </div>\n <div style={currentTab === 'METADATA' ? {} : { display: 'none' }}>\n <MetadataTable entityId={entityId} versionNumber={versionNumber} />\n </div>\n </>\n )\n\n const cancelEditingConfirmationModal = (\n <ConfirmationDialog\n open={showEditCancellationWarning}\n title=\"Unsaved Changes\"\n content=\"Any unsaved changes will be lost. Are you sure you want to close the editor?\"\n onCancel={() => {\n setShowEditCancellationWarning(false)\n }}\n onConfirm={() => {\n setShowEditCancellationWarning(false)\n onCancelEdit()\n }}\n />\n )\n\n const modalTitle = useMemo(() => {\n if (!entityBundle?.entity.name) {\n return <Skeleton width={'40%'} />\n } else if (currentTab === 'ANNOTATIONS') {\n return `${isInEditMode ? 'Edit ' : ''}Annotations for ${\n entityBundle.entity.name\n }`\n }\n return entityBundle.entity.name\n }, [currentTab, entityBundle?.entity.name, isInEditMode])\n\n return (\n <DialogBase\n className={`EntityMetadata`}\n open={show}\n onCancel={() => {\n if (isInEditMode) {\n setShowEditCancellationWarning(true)\n setOnCancelEdit(() => {\n // Need to return a function in a function because passing a function to setState has a different meaning\n return () => {\n setIsInEditMode(false)\n onClose()\n }\n })\n } else {\n onClose()\n }\n }}\n maxWidth={isInEditMode ? 'md' : 'sm'}\n title={modalTitle}\n content={dialogContent}\n actions={\n <>\n {cancelEditingConfirmationModal}\n {showCancelAnnotationEditsButton && cancelAnnotationEditsButton}\n {showSaveAnnotationsButton && saveAnnotationsButton}\n {showEditAnnotationsButton && editAnnotationsButton}\n {showOpenEntityPageButton && openEntityPageButton}\n </>\n }\n />\n )\n}\n\nexport default EntityModal\n"],"mappings":"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"}
|
|
@@ -14,7 +14,7 @@ function a(e, t) {
|
|
|
14
14
|
function o(e, t) {
|
|
15
15
|
return e.reduce((e, n) => {
|
|
16
16
|
let r = t[n.action];
|
|
17
|
-
return r
|
|
17
|
+
return r?.visible && e.push({
|
|
18
18
|
text: r.text ?? n.action,
|
|
19
19
|
onClick: r.onClick,
|
|
20
20
|
href: r.href,
|
|
@@ -37,7 +37,7 @@ function c(o) {
|
|
|
37
37
|
Object.entries(d).length > 0 && (console.warn("Actions are visible but have not been configured in the layout:", Object.entries(d).map((e) => e[0])), u.primaryMenuActions.unshift(Object.entries(d).map((e) => ({ action: e[0] }))));
|
|
38
38
|
let f = u.buttonActions.reduce((e, t) => {
|
|
39
39
|
let n = c[t.action];
|
|
40
|
-
if (n
|
|
40
|
+
if (n?.visible) {
|
|
41
41
|
let r = n.onClick;
|
|
42
42
|
r == null && !n.href && (console.warn(`No handler registered for ${t.action}`), r = () => {
|
|
43
43
|
console.warn(`No handler registered for ${t.action}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EntityActionMenu.js","names":[],"sources":["../../../../../src/components/entity/page/action_menu/EntityActionMenu.tsx"],"sourcesContent":["import { Box, ButtonProps, SxProps, Theme } from '@mui/material'\nimport { ComplexMenu, ComplexMenuButtonProps } from '../../../menu/ComplexMenu'\nimport IconSvg, { IconName } from '../../../IconSvg/IconSvg'\nimport { DropdownMenuItem, DropdownMenuProps } from '../../../menu/DropdownMenu'\nimport { MouseEvent } from 'react'\nimport { SystemStyleObject } from '@mui/system'\n\nconst outlinedButtonHoverBackgroundColor = 'rgba(0, 0, 0, 0.01)'\n\n// Represents the two types of dropdown menus that will be displayed on the entity page\ntype EntityActionMenuDropdownMenuType = 'DOWNLOAD' | 'PRIMARY'\n\ntype EntityActionMenuDropdownMenuConfiguration = {\n visible: boolean\n tooltipText?: string\n disabled?: boolean\n showFileAccessRequestNotice?: boolean\n}\n\nexport type ActionConfiguration = {\n visible: boolean\n text: string\n disabled?: boolean\n tooltipText?: string\n onClick?: (e: MouseEvent) => void\n href?: string\n}\n\nexport type ActionConfigurationMap = Record<string, ActionConfiguration>\n\nexport type MenuConfigurationMap = Record<\n EntityActionMenuDropdownMenuType,\n EntityActionMenuDropdownMenuConfiguration\n>\n\nexport type ActionViewProps = {\n action: string\n icon?: IconName\n textSx?: SxProps\n iconSx?: SxProps\n variant?: ButtonProps['variant']\n}\n\nexport type EntityActionMenuLayout = {\n buttonActions: ActionViewProps[]\n downloadMenuActions: ActionViewProps[][]\n primaryMenuActions: ActionViewProps[][]\n primaryMenuText: string\n primaryMenuEndIcon: IconName\n primaryMenuEndIconSx?: SxProps\n menuButtonSx?: SystemStyleObject<Theme>\n downloadMenuVariant?: ButtonProps['variant']\n primaryMenuVariant?: ButtonProps['variant']\n}\n\nexport type EntityActionMenuProps = {\n /* Maps a unique action string to a dynamic configuration for that particular action */\n actionConfiguration: ActionConfigurationMap\n /* Maps each dropdown menu to a dynamic configuration for that particular menu */\n menuConfiguration: MenuConfigurationMap\n /* Defines the layout of the actions. Typically depends on just the entity type and area. */\n layout: EntityActionMenuLayout\n}\n\n/*\n * All visible actions should be specified in the layout, but this is not guaranteed at compile time.\n * Find all visible actions in the action configuration that are not in the layout.\n */\nfunction getUnmappedActions(\n actionConfiguration: ActionConfigurationMap,\n layout: EntityActionMenuLayout,\n): ActionConfigurationMap {\n return Object.fromEntries(\n Object.entries(actionConfiguration).filter(([action, config]) => {\n // We don't care about actions that are not configured or should not be visible\n if (!config || !config.visible) {\n return false\n }\n\n const allLayoutActions: ActionViewProps[] = [\n ...layout.buttonActions,\n ...layout.primaryMenuActions.flat(),\n ...layout.downloadMenuActions.flat(),\n ]\n // Action is unmapped if it's visible and the layout doesn't have it\n return !allLayoutActions.some(\n layoutAction => layoutAction.action === action,\n )\n }),\n )\n}\n\n/**\n * Given a group of dropdown menu items and an action configuration,\n * return a list of dropdown menu items with non-visible and non-configured actions removed.\n * @param group\n * @param actionConfiguration\n */\nfunction mapAndFilterItemsInMenuGroup(\n group: ActionViewProps[],\n actionConfiguration: ActionConfigurationMap,\n): DropdownMenuItem[] {\n return group.reduce(\n (itemAcc: DropdownMenuItem[], actionViewProps: ActionViewProps) => {\n const configForAction = actionConfiguration[actionViewProps.action]\n // Only show the item if it's configured + visible\n if (configForAction && configForAction.visible) {\n itemAcc.push({\n text: configForAction.text ?? actionViewProps.action,\n onClick: configForAction.onClick,\n href: configForAction.href,\n tooltipText: configForAction.tooltipText,\n disabled: configForAction.disabled,\n icon: actionViewProps.icon,\n textSx: actionViewProps.textSx,\n iconSx: actionViewProps.iconSx,\n })\n }\n return itemAcc\n },\n [],\n )\n}\n\n/**\n * Given a list of groups of dropdown menu actions, returns a list of dropdown menu item\n * groups where non-visible actions have been removed, and groups with no visible actions\n * have been removed.\n * @param menuActions\n * @param actionConfiguration\n */\nfunction mapAndFilterMenuGroups(\n menuActions: ActionViewProps[][],\n actionConfiguration: ActionConfigurationMap,\n): DropdownMenuItem[][] {\n return menuActions.reduce(\n (groupAcc: DropdownMenuItem[][], group: ActionViewProps[]) => {\n const itemGroup = mapAndFilterItemsInMenuGroup(group, actionConfiguration)\n // Only show the group if it contains visible items\n if (itemGroup.length > 0) {\n groupAcc.push(itemGroup)\n }\n return groupAcc\n },\n [],\n )\n}\n\n/**\n * The EntityActionMenu renders a menu that displays the actions that can be invoked on an Entity page.\n */\nexport default function EntityActionMenu(props: EntityActionMenuProps) {\n const { actionConfiguration, menuConfiguration, layout } = props\n\n /*\n * All actions should be specified in the layout, but this is not guaranteed at compile time.\n * Find all visible actions in the action configuration that are not in the layout.\n */\n const unmappedActions = getUnmappedActions(actionConfiguration, layout)\n // Warn if unmapped actions were found and push them on to the layout.\n if (Object.entries(unmappedActions).length > 0) {\n console.warn(\n 'Actions are visible but have not been configured in the layout:',\n Object.entries(unmappedActions).map(entry => entry[0]),\n )\n // Modify the layout: put the unmapped actions in their own group at the top of the menu\n layout.primaryMenuActions.unshift(\n Object.entries(unmappedActions).map(\n (entry): ActionViewProps => ({\n action: entry[0],\n }),\n ),\n )\n }\n\n // Map button actions to a button configuration and omit non-visible actions\n const iconButtonConfigs: ComplexMenuButtonProps[] =\n layout.buttonActions.reduce(\n (acc: ComplexMenuButtonProps[], buttonViewProps: ActionViewProps) => {\n const configForAction = actionConfiguration[buttonViewProps.action]\n if (configForAction && configForAction.visible) {\n let onClick = configForAction.onClick\n if (onClick == null && !configForAction.href) {\n console.warn(`No handler registered for ${buttonViewProps.action}`)\n onClick = () => {\n console.warn(\n `No handler registered for ${buttonViewProps.action}`,\n )\n }\n }\n acc.push({\n icon: buttonViewProps.icon as IconName,\n onClick: onClick,\n tooltipText: configForAction.text,\n text: configForAction.text,\n variant: buttonViewProps.variant,\n iconSx: buttonViewProps.iconSx,\n disabled: configForAction.disabled,\n href: configForAction.href,\n })\n }\n return acc\n },\n [],\n )\n\n const downloadMenuConfig: DropdownMenuProps = {\n dropdownButtonText: 'Download Options',\n convertSingleItemToButton: true,\n renderMenuIfNoItems: false,\n variant: layout.downloadMenuVariant,\n showFileAccessRequestNotice:\n menuConfiguration.DOWNLOAD.showFileAccessRequestNotice ?? false,\n paperSx: {\n borderRadius: '5px',\n border: '1px solid #E2E4EA',\n width: '279px',\n padding: '12px 16px',\n },\n elevation: 3,\n buttonTooltip: menuConfiguration.DOWNLOAD.tooltipText,\n buttonProps: {\n disabled: menuConfiguration.DOWNLOAD.disabled,\n endIcon: <IconSvg icon={'expandMore'} wrap={false} />,\n },\n items: mapAndFilterMenuGroups(\n layout.downloadMenuActions,\n actionConfiguration,\n ),\n }\n\n const primaryMenuConfig: DropdownMenuProps = {\n dropdownButtonText: layout.primaryMenuText,\n convertSingleItemToButton: true,\n renderMenuIfNoItems: false,\n variant: layout.primaryMenuVariant,\n buttonProps: {\n endIcon: (\n <IconSvg\n icon={layout.primaryMenuEndIcon}\n wrap={false}\n sx={layout.primaryMenuEndIconSx}\n />\n ),\n },\n items: mapAndFilterMenuGroups(\n layout.primaryMenuActions,\n actionConfiguration,\n ),\n }\n\n const menuButtonSx = layout.menuButtonSx ?? {}\n\n return (\n <Box\n sx={{\n '& .MuiButton-root': {\n borderRadius: '6px',\n fontWeight: 540,\n padding: '10px 12px',\n },\n // Optional per-layout overrides (e.g. background/border color for entity\n // menu buttons).\n '& .MuiButton-outlined': {\n ...menuButtonSx,\n\n '&:hover': {\n ...menuButtonSx,\n backgroundColor: outlinedButtonHoverBackgroundColor,\n },\n },\n '& .MuiButton-text': {\n ...menuButtonSx,\n backgroundColor: 'transparent',\n\n '&:hover': {\n ...menuButtonSx,\n backgroundColor: outlinedButtonHoverBackgroundColor,\n textDecoration: 'none',\n },\n },\n '& .MuiButton-root .MuiTypography-root': {\n fontWeight: 540,\n },\n }}\n >\n <ComplexMenu\n iconButtons={iconButtonConfigs}\n dropdownMenus={[primaryMenuConfig, downloadMenuConfig]}\n />\n </Box>\n )\n}\n\nexport const EXPORTED_FOR_UNIT_TESTING = {\n getUnmappedActions,\n mapAndFilterItemsInMenuGroup,\n mapAndFilterMenuGroups,\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"EntityActionMenu.js","names":[],"sources":["../../../../../src/components/entity/page/action_menu/EntityActionMenu.tsx"],"sourcesContent":["import { Box, ButtonProps, SxProps, Theme } from '@mui/material'\nimport { ComplexMenu, ComplexMenuButtonProps } from '../../../menu/ComplexMenu'\nimport IconSvg, { IconName } from '../../../IconSvg/IconSvg'\nimport { DropdownMenuItem, DropdownMenuProps } from '../../../menu/DropdownMenu'\nimport { MouseEvent } from 'react'\nimport { SystemStyleObject } from '@mui/system'\n\nconst outlinedButtonHoverBackgroundColor = 'rgba(0, 0, 0, 0.01)'\n\n// Represents the two types of dropdown menus that will be displayed on the entity page\ntype EntityActionMenuDropdownMenuType = 'DOWNLOAD' | 'PRIMARY'\n\ntype EntityActionMenuDropdownMenuConfiguration = {\n visible: boolean\n tooltipText?: string\n disabled?: boolean\n showFileAccessRequestNotice?: boolean\n}\n\nexport type ActionConfiguration = {\n visible: boolean\n text: string\n disabled?: boolean\n tooltipText?: string\n onClick?: (e: MouseEvent) => void\n href?: string\n}\n\nexport type ActionConfigurationMap = Record<string, ActionConfiguration>\n\nexport type MenuConfigurationMap = Record<\n EntityActionMenuDropdownMenuType,\n EntityActionMenuDropdownMenuConfiguration\n>\n\nexport type ActionViewProps = {\n action: string\n icon?: IconName\n textSx?: SxProps\n iconSx?: SxProps\n variant?: ButtonProps['variant']\n}\n\nexport type EntityActionMenuLayout = {\n buttonActions: ActionViewProps[]\n downloadMenuActions: ActionViewProps[][]\n primaryMenuActions: ActionViewProps[][]\n primaryMenuText: string\n primaryMenuEndIcon: IconName\n primaryMenuEndIconSx?: SxProps\n menuButtonSx?: SystemStyleObject<Theme>\n downloadMenuVariant?: ButtonProps['variant']\n primaryMenuVariant?: ButtonProps['variant']\n}\n\nexport type EntityActionMenuProps = {\n /* Maps a unique action string to a dynamic configuration for that particular action */\n actionConfiguration: ActionConfigurationMap\n /* Maps each dropdown menu to a dynamic configuration for that particular menu */\n menuConfiguration: MenuConfigurationMap\n /* Defines the layout of the actions. Typically depends on just the entity type and area. */\n layout: EntityActionMenuLayout\n}\n\n/*\n * All visible actions should be specified in the layout, but this is not guaranteed at compile time.\n * Find all visible actions in the action configuration that are not in the layout.\n */\nfunction getUnmappedActions(\n actionConfiguration: ActionConfigurationMap,\n layout: EntityActionMenuLayout,\n): ActionConfigurationMap {\n return Object.fromEntries(\n Object.entries(actionConfiguration).filter(([action, config]) => {\n // We don't care about actions that are not configured or should not be visible\n if (!config || !config.visible) {\n return false\n }\n\n const allLayoutActions: ActionViewProps[] = [\n ...layout.buttonActions,\n ...layout.primaryMenuActions.flat(),\n ...layout.downloadMenuActions.flat(),\n ]\n // Action is unmapped if it's visible and the layout doesn't have it\n return !allLayoutActions.some(\n layoutAction => layoutAction.action === action,\n )\n }),\n )\n}\n\n/**\n * Given a group of dropdown menu items and an action configuration,\n * return a list of dropdown menu items with non-visible and non-configured actions removed.\n * @param group\n * @param actionConfiguration\n */\nfunction mapAndFilterItemsInMenuGroup(\n group: ActionViewProps[],\n actionConfiguration: ActionConfigurationMap,\n): DropdownMenuItem[] {\n return group.reduce(\n (itemAcc: DropdownMenuItem[], actionViewProps: ActionViewProps) => {\n const configForAction = actionConfiguration[actionViewProps.action]\n // Only show the item if it's configured + visible\n if (configForAction?.visible) {\n itemAcc.push({\n text: configForAction.text ?? actionViewProps.action,\n onClick: configForAction.onClick,\n href: configForAction.href,\n tooltipText: configForAction.tooltipText,\n disabled: configForAction.disabled,\n icon: actionViewProps.icon,\n textSx: actionViewProps.textSx,\n iconSx: actionViewProps.iconSx,\n })\n }\n return itemAcc\n },\n [],\n )\n}\n\n/**\n * Given a list of groups of dropdown menu actions, returns a list of dropdown menu item\n * groups where non-visible actions have been removed, and groups with no visible actions\n * have been removed.\n * @param menuActions\n * @param actionConfiguration\n */\nfunction mapAndFilterMenuGroups(\n menuActions: ActionViewProps[][],\n actionConfiguration: ActionConfigurationMap,\n): DropdownMenuItem[][] {\n return menuActions.reduce(\n (groupAcc: DropdownMenuItem[][], group: ActionViewProps[]) => {\n const itemGroup = mapAndFilterItemsInMenuGroup(group, actionConfiguration)\n // Only show the group if it contains visible items\n if (itemGroup.length > 0) {\n groupAcc.push(itemGroup)\n }\n return groupAcc\n },\n [],\n )\n}\n\n/**\n * The EntityActionMenu renders a menu that displays the actions that can be invoked on an Entity page.\n */\nexport default function EntityActionMenu(props: EntityActionMenuProps) {\n const { actionConfiguration, menuConfiguration, layout } = props\n\n /*\n * All actions should be specified in the layout, but this is not guaranteed at compile time.\n * Find all visible actions in the action configuration that are not in the layout.\n */\n const unmappedActions = getUnmappedActions(actionConfiguration, layout)\n // Warn if unmapped actions were found and push them on to the layout.\n if (Object.entries(unmappedActions).length > 0) {\n console.warn(\n 'Actions are visible but have not been configured in the layout:',\n Object.entries(unmappedActions).map(entry => entry[0]),\n )\n // Modify the layout: put the unmapped actions in their own group at the top of the menu\n layout.primaryMenuActions.unshift(\n Object.entries(unmappedActions).map(\n (entry): ActionViewProps => ({\n action: entry[0],\n }),\n ),\n )\n }\n\n // Map button actions to a button configuration and omit non-visible actions\n const iconButtonConfigs: ComplexMenuButtonProps[] =\n layout.buttonActions.reduce(\n (acc: ComplexMenuButtonProps[], buttonViewProps: ActionViewProps) => {\n const configForAction = actionConfiguration[buttonViewProps.action]\n if (configForAction?.visible) {\n let onClick = configForAction.onClick\n if (onClick == null && !configForAction.href) {\n console.warn(`No handler registered for ${buttonViewProps.action}`)\n onClick = () => {\n console.warn(\n `No handler registered for ${buttonViewProps.action}`,\n )\n }\n }\n acc.push({\n icon: buttonViewProps.icon as IconName,\n onClick: onClick,\n tooltipText: configForAction.text,\n text: configForAction.text,\n variant: buttonViewProps.variant,\n iconSx: buttonViewProps.iconSx,\n disabled: configForAction.disabled,\n href: configForAction.href,\n })\n }\n return acc\n },\n [],\n )\n\n const downloadMenuConfig: DropdownMenuProps = {\n dropdownButtonText: 'Download Options',\n convertSingleItemToButton: true,\n renderMenuIfNoItems: false,\n variant: layout.downloadMenuVariant,\n showFileAccessRequestNotice:\n menuConfiguration.DOWNLOAD.showFileAccessRequestNotice ?? false,\n paperSx: {\n borderRadius: '5px',\n border: '1px solid #E2E4EA',\n width: '279px',\n padding: '12px 16px',\n },\n elevation: 3,\n buttonTooltip: menuConfiguration.DOWNLOAD.tooltipText,\n buttonProps: {\n disabled: menuConfiguration.DOWNLOAD.disabled,\n endIcon: <IconSvg icon={'expandMore'} wrap={false} />,\n },\n items: mapAndFilterMenuGroups(\n layout.downloadMenuActions,\n actionConfiguration,\n ),\n }\n\n const primaryMenuConfig: DropdownMenuProps = {\n dropdownButtonText: layout.primaryMenuText,\n convertSingleItemToButton: true,\n renderMenuIfNoItems: false,\n variant: layout.primaryMenuVariant,\n buttonProps: {\n endIcon: (\n <IconSvg\n icon={layout.primaryMenuEndIcon}\n wrap={false}\n sx={layout.primaryMenuEndIconSx}\n />\n ),\n },\n items: mapAndFilterMenuGroups(\n layout.primaryMenuActions,\n actionConfiguration,\n ),\n }\n\n const menuButtonSx = layout.menuButtonSx ?? {}\n\n return (\n <Box\n sx={{\n '& .MuiButton-root': {\n borderRadius: '6px',\n fontWeight: 540,\n padding: '10px 12px',\n },\n // Optional per-layout overrides (e.g. background/border color for entity\n // menu buttons).\n '& .MuiButton-outlined': {\n ...menuButtonSx,\n\n '&:hover': {\n ...menuButtonSx,\n backgroundColor: outlinedButtonHoverBackgroundColor,\n },\n },\n '& .MuiButton-text': {\n ...menuButtonSx,\n backgroundColor: 'transparent',\n\n '&:hover': {\n ...menuButtonSx,\n backgroundColor: outlinedButtonHoverBackgroundColor,\n textDecoration: 'none',\n },\n },\n '& .MuiButton-root .MuiTypography-root': {\n fontWeight: 540,\n },\n }}\n >\n <ComplexMenu\n iconButtons={iconButtonConfigs}\n dropdownMenus={[primaryMenuConfig, downloadMenuConfig]}\n />\n </Box>\n )\n}\n\nexport const EXPORTED_FOR_UNIT_TESTING = {\n getUnmappedActions,\n mapAndFilterItemsInMenuGroup,\n mapAndFilterMenuGroups,\n}\n"],"mappings":"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"}
|