synapse-react-client 4.0.45 → 4.0.46
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/AridhiaKeyFactory.d.ts +1 -0
- package/dist/aridhia-queries/AridhiaKeyFactory.d.ts.map +1 -1
- package/dist/aridhia-queries/AridhiaKeyFactory.js +3 -0
- package/dist/aridhia-queries/AridhiaKeyFactory.js.map +1 -1
- package/dist/aridhia-queries/aridhiaTokenExchange.js +6 -6
- package/dist/aridhia-queries/index.d.ts +1 -0
- package/dist/aridhia-queries/index.d.ts.map +1 -1
- package/dist/aridhia-queries/index.js +11 -10
- package/dist/aridhia-queries/useGetAridhiaVocabularyTerm.d.ts +19 -0
- package/dist/aridhia-queries/useGetAridhiaVocabularyTerm.d.ts.map +1 -0
- package/dist/aridhia-queries/useGetAridhiaVocabularyTerm.js +14 -0
- package/dist/aridhia-queries/useGetAridhiaVocabularyTerm.js.map +1 -0
- package/dist/components/AccessRequirementList/AccessApprovalCheckMark.d.ts.map +1 -1
- package/dist/components/AccessRequirementList/AccessApprovalCheckMark.js +6 -4
- package/dist/components/AccessRequirementList/AccessApprovalCheckMark.js.map +1 -1
- package/dist/components/AccessRequirementList/AccessRequirementList.js.map +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/AccessorRequirementHelpText.js +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/AccessorRequirementHelpText.js.map +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/ResearchProjectForm/ResearchProjectForm.js +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/ResearchProjectForm/ResearchProjectForm.js.map +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/ReviewCollaboratorsAndSigningOfficialAccordion.js +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/ReviewCollaboratorsAndSigningOfficialAccordion.js.map +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/SignatureStatusStep/SignatureStatusStep.d.ts.map +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/SignatureStatusStep/SignatureStatusStep.js +11 -8
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/SignatureStatusStep/SignatureStatusStep.js.map +1 -1
- package/dist/components/AccessTokenPage/AccessTokenPage.js +1 -1
- package/dist/components/AccessTokenPage/AccessTokenPage.js.map +1 -1
- package/dist/components/AcknowledgementsPage/AcknowledgementsPage.js +1 -1
- package/dist/components/AcknowledgementsPage/AcknowledgementsPage.js.map +1 -1
- package/dist/components/Aridhia/DarWizard/DarSectionForm.d.ts.map +1 -1
- package/dist/components/Aridhia/DarWizard/DarSectionForm.js +17 -13
- package/dist/components/Aridhia/DarWizard/DarSectionForm.js.map +1 -1
- package/dist/components/Aridhia/DarWizard/DarSubmittedPanel.d.ts +3 -3
- package/dist/components/Aridhia/DarWizard/DarSubmittedPanel.d.ts.map +1 -1
- package/dist/components/Aridhia/DarWizard/DarSubmittedPanel.js +33 -34
- package/dist/components/Aridhia/DarWizard/DarSubmittedPanel.js.map +1 -1
- package/dist/components/Aridhia/fairFormToRjsf.js +1 -1
- package/dist/components/Aridhia/fairFormToRjsf.js.map +1 -1
- package/dist/components/Authentication/LastLoginInfo.js +1 -1
- package/dist/components/Authentication/LastLoginInfo.js.map +1 -1
- package/dist/components/CertificationQuiz/CertificationQuiz.js +1 -1
- package/dist/components/CertificationQuiz/CertificationQuiz.js.map +1 -1
- package/dist/components/ChallengeSubmission/AvailableEvaluationQueueList.js +1 -1
- package/dist/components/ChallengeSubmission/AvailableEvaluationQueueList.js.map +1 -1
- package/dist/components/ChallengeSubmission/EvaluationQueueCurrentRoundInfo.js +1 -1
- package/dist/components/ChallengeSubmission/EvaluationQueueCurrentRoundInfo.js.map +1 -1
- package/dist/components/ChallengeSubmission/SubmissionDirectoryList.js +6 -6
- package/dist/components/ChallengeSubmission/SubmissionDirectoryList.js.map +1 -1
- package/dist/components/ChallengeTeamWizard/ChallengeTeamTable.d.ts.map +1 -1
- package/dist/components/ChallengeTeamWizard/ChallengeTeamTable.js +4 -4
- package/dist/components/ChallengeTeamWizard/ChallengeTeamTable.js.map +1 -1
- package/dist/components/ChallengeTeamWizard/SelectChallengeTeam.js +4 -4
- package/dist/components/CitationPopover/CitationPopoverContent.js +4 -4
- package/dist/components/CitationPopover/CitationPopoverContent.js.map +1 -1
- package/dist/components/ComponentCollapse.d.ts.map +1 -1
- package/dist/components/ComponentCollapse.js +2 -1
- package/dist/components/ComponentCollapse.js.map +1 -1
- package/dist/components/DataGrid/SynapseGrid.d.ts.map +1 -1
- package/dist/components/DataGrid/SynapseGrid.js +231 -219
- package/dist/components/DataGrid/SynapseGrid.js.map +1 -1
- package/dist/components/DataGrid/SyncGridWithSourceButton.d.ts.map +1 -1
- package/dist/components/DataGrid/SyncGridWithSourceButton.js +5 -4
- package/dist/components/DataGrid/SyncGridWithSourceButton.js.map +1 -1
- package/dist/components/DataGrid/components/ColumnHeaderWithTooltip.d.ts.map +1 -1
- package/dist/components/DataGrid/components/ColumnHeaderWithTooltip.js +7 -5
- package/dist/components/DataGrid/components/ColumnHeaderWithTooltip.js.map +1 -1
- package/dist/components/DataGrid/components/ExportCsvFromGridButton.js +4 -4
- package/dist/components/DataGrid/components/ExportCsvFromGridButton.js.map +1 -1
- package/dist/components/DataGrid/components/ReorderColumnsButton.js +4 -4
- package/dist/components/DataGrid/components/ReorderColumnsButton.js.map +1 -1
- package/dist/components/DataGrid/components/ReorderColumnsDialog.d.ts.map +1 -1
- package/dist/components/DataGrid/components/ReorderColumnsDialog.js +12 -8
- package/dist/components/DataGrid/components/ReorderColumnsDialog.js.map +1 -1
- package/dist/components/DataGrid/components/UploadCsvToGridButton.js +1 -1
- package/dist/components/DataGrid/components/UploadCsvToGridButton.js.map +1 -1
- package/dist/components/DataGrid/hooks/useGridUndoRedo.js +5 -5
- package/dist/components/DataGrid/utils/applyModelChange.d.ts.map +1 -1
- package/dist/components/DataGrid/utils/applyModelChange.js +14 -14
- package/dist/components/DataGrid/utils/applyModelChange.js.map +1 -1
- package/dist/components/DataGrid/utils/columnFactory.js +1 -1
- package/dist/components/DataGrid/utils/columnFactory.js.map +1 -1
- package/dist/components/DataGrid/utils/splitPatch.d.ts.map +1 -1
- package/dist/components/DataGrid/utils/splitPatch.js +22 -13
- package/dist/components/DataGrid/utils/splitPatch.js.map +1 -1
- package/dist/components/DownloadCart/DownloadCartPage.js +1 -1
- package/dist/components/DownloadCart/DownloadCartPage.js.map +1 -1
- package/dist/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.d.ts.map +1 -1
- package/dist/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.js +2 -1
- package/dist/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.js.map +1 -1
- package/dist/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.module.js.map +1 -1
- package/dist/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.module.scss +1 -3
- package/dist/components/EntityBadgeIcons/EntityBadgeIcons.d.ts.map +1 -1
- package/dist/components/EntityBadgeIcons/EntityBadgeIcons.js +16 -10
- package/dist/components/EntityBadgeIcons/EntityBadgeIcons.js.map +1 -1
- package/dist/components/EntityDownloadButton/EntityDownloadButton.js +1 -1
- package/dist/components/EntityDownloadButton/EntityDownloadButton.js.map +1 -1
- package/dist/components/EntityFinder/EntityFinder.js +4 -4
- package/dist/components/EntityFinder/EntityIdTextField.js +1 -1
- package/dist/components/EntityFinder/EntityIdTextField.js.map +1 -1
- package/dist/components/EntityFinder/tree/VirtualizedTree.d.ts.map +1 -1
- package/dist/components/EntityFinder/tree/VirtualizedTree.js +5 -4
- package/dist/components/EntityFinder/tree/VirtualizedTree.js.map +1 -1
- package/dist/components/EntityHeaderTable/EntityHeaderTable.js +1 -1
- package/dist/components/EntityHeaderTable/EntityHeaderTable.js.map +1 -1
- package/dist/components/EntityTreeTable/components/EntityNameCell.d.ts.map +1 -1
- package/dist/components/EntityTreeTable/components/EntityNameCell.js +2 -1
- package/dist/components/EntityTreeTable/components/EntityNameCell.js.map +1 -1
- package/dist/components/EntityUpload/FileUploadProgress.d.ts.map +1 -1
- package/dist/components/EntityUpload/FileUploadProgress.js +11 -7
- package/dist/components/EntityUpload/FileUploadProgress.js.map +1 -1
- package/dist/components/Evaluation/round_limits/EvaluationRoundLimitOptionsList.d.ts.map +1 -1
- package/dist/components/Evaluation/round_limits/EvaluationRoundLimitOptionsList.js +4 -3
- package/dist/components/Evaluation/round_limits/EvaluationRoundLimitOptionsList.js.map +1 -1
- package/dist/components/ExperimentalMode/ExperimentalMode.js +1 -1
- package/dist/components/ExperimentalMode/ExperimentalMode.js.map +1 -1
- package/dist/components/ExternalFileHandleLink/ExternalFileHandleLink.js +1 -1
- package/dist/components/ExternalFileHandleLink/ExternalFileHandleLink.js.map +1 -1
- package/dist/components/FormTemplateEditor/ChoiceOptionsEditor.d.ts.map +1 -1
- package/dist/components/FormTemplateEditor/ChoiceOptionsEditor.js +2 -1
- package/dist/components/FormTemplateEditor/ChoiceOptionsEditor.js.map +1 -1
- package/dist/components/FormTemplateEditor/FieldDefinitionDrawer.d.ts.map +1 -1
- package/dist/components/FormTemplateEditor/FieldDefinitionDrawer.js +2 -1
- package/dist/components/FormTemplateEditor/FieldDefinitionDrawer.js.map +1 -1
- package/dist/components/FormTemplateEditor/FieldLibrary.d.ts.map +1 -1
- package/dist/components/FormTemplateEditor/FieldLibrary.js +2 -1
- package/dist/components/FormTemplateEditor/FieldLibrary.js.map +1 -1
- package/dist/components/FormTemplateEditor/FieldLibraryRow.js +4 -4
- package/dist/components/FormTemplateEditor/FieldLibraryRow.js.map +1 -1
- package/dist/components/FormTemplateEditor/FormStructurePanel.js +1 -1
- package/dist/components/FormTemplateEditor/FormStructurePanel.js.map +1 -1
- package/dist/components/FormTemplateEditor/FormTemplateEditorForm.js +1 -1
- package/dist/components/FormTemplateEditor/FormTemplateEditorForm.js.map +1 -1
- package/dist/components/FormTemplateEditor/StepCard.d.ts.map +1 -1
- package/dist/components/FormTemplateEditor/StepCard.js +15 -10
- package/dist/components/FormTemplateEditor/StepCard.js.map +1 -1
- package/dist/components/FormTemplateEditor/StepFieldRow.d.ts.map +1 -1
- package/dist/components/FormTemplateEditor/StepFieldRow.js +11 -6
- package/dist/components/FormTemplateEditor/StepFieldRow.js.map +1 -1
- package/dist/components/FormTemplateEditor/TemplateFileHandleField.d.ts.map +1 -1
- package/dist/components/FormTemplateEditor/TemplateFileHandleField.js +2 -1
- package/dist/components/FormTemplateEditor/TemplateFileHandleField.js.map +1 -1
- package/dist/components/GenericCard/DuoTermTags/DuoTermTags.js +45 -45
- package/dist/components/GenericCard/PortalDOI/PortalDOI.js +5 -5
- package/dist/components/GenericCard/PortalDOI/PortalDOI.js.map +1 -1
- package/dist/components/GenericCard/TableRowGenericCard.js +1 -1
- package/dist/components/GenericCard/TableRowGenericCard.js.map +1 -1
- package/dist/components/HelpPopover/HelpPopover.js +1 -1
- package/dist/components/HelpPopover/HelpPopover.js.map +1 -1
- package/dist/components/IconSvg/IconSvg.d.ts.map +1 -1
- package/dist/components/IconSvg/IconSvg.js +154 -47
- package/dist/components/IconSvg/IconSvg.js.map +1 -1
- package/dist/components/JsonSchemaForm/templates/ButtonTemplate.d.ts.map +1 -1
- package/dist/components/JsonSchemaForm/templates/ButtonTemplate.js +19 -16
- package/dist/components/JsonSchemaForm/templates/ButtonTemplate.js.map +1 -1
- package/dist/components/JsonSchemaForm/templates/RJSFInputLabel.d.ts.map +1 -1
- package/dist/components/JsonSchemaForm/templates/RJSFInputLabel.js +2 -1
- package/dist/components/JsonSchemaForm/templates/RJSFInputLabel.js.map +1 -1
- package/dist/components/JsonSchemaForm/widgets/PhoneWidget.d.ts +9 -0
- package/dist/components/JsonSchemaForm/widgets/PhoneWidget.d.ts.map +1 -0
- package/dist/components/JsonSchemaForm/widgets/PhoneWidget.js +21 -0
- package/dist/components/JsonSchemaForm/widgets/PhoneWidget.js.map +1 -0
- package/dist/components/Markdown/MarkdownCollapse.d.ts.map +1 -1
- package/dist/components/Markdown/MarkdownCollapse.js +3 -1
- package/dist/components/Markdown/MarkdownCollapse.js.map +1 -1
- package/dist/components/MissingQueryResultsWarning/MissingQueryResultsWarning.js +1 -1
- package/dist/components/MissingQueryResultsWarning/MissingQueryResultsWarning.js.map +1 -1
- package/dist/components/OAuthClientManagement/OAuthManagement.js +14 -13
- package/dist/components/OAuthClientManagement/OAuthManagement.js.map +1 -1
- package/dist/components/PortalList/PortalCard.d.ts.map +1 -1
- package/dist/components/PortalList/PortalCard.js +6 -5
- package/dist/components/PortalList/PortalCard.js.map +1 -1
- package/dist/components/PortalList/PortalList.js +4 -4
- package/dist/components/PortalList/PortalList.js.map +1 -1
- package/dist/components/ProjectVisibilityChip/ProjectVisibilityChip.js +6 -6
- package/dist/components/QueryBuilder/FilterConditionRow.js +4 -4
- package/dist/components/QueryCountButton/QueryCountButton.js +5 -5
- package/dist/components/QueryCountButton/QueryCountButton.js.map +1 -1
- package/dist/components/ReleaseCard/ReleaseCardLarge.js +5 -5
- package/dist/components/ReleaseCard/ReleaseCardLarge.js.map +1 -1
- package/dist/components/SetAccessRequirementCommonFields/SetAccessRequirementCommonFields.js +1 -1
- package/dist/components/SetAccessRequirementCommonFields/SetAccessRequirementCommonFields.js.map +1 -1
- package/dist/components/ShareThisPage/ShareThisPage.js +4 -4
- package/dist/components/ShareThisPage/ShareThisPage.js.map +1 -1
- package/dist/components/SustainabilityScorecard/DialLayout.js +1 -1
- package/dist/components/SustainabilityScorecard/DialLayout.js.map +1 -1
- package/dist/components/SustainabilityScorecard/SustainabilityScorecard.js +1 -1
- package/dist/components/SustainabilityScorecard/SustainabilityScorecard.js.map +1 -1
- package/dist/components/SynapseChat/SynapseChat.js +1 -1
- package/dist/components/SynapseChat/SynapseChat.js.map +1 -1
- package/dist/components/SynapseChat/SynapseChatInteraction.d.ts.map +1 -1
- package/dist/components/SynapseChat/SynapseChatInteraction.js +2 -1
- package/dist/components/SynapseChat/SynapseChatInteraction.js.map +1 -1
- package/dist/components/SynapseChat/components/ChatInputArea/ChatInputArea.js +1 -1
- package/dist/components/SynapseChat/components/ChatInputArea/ChatInputArea.js.map +1 -1
- package/dist/components/SynapseFooter/SynapseFooter.js +1 -1
- package/dist/components/SynapseFooter/SynapseFooter.js.map +1 -1
- package/dist/components/SynapseHomepageV2/SynapseFeaturedDatasetItem.js +1 -1
- package/dist/components/SynapseHomepageV2/SynapseFeaturedDatasetItem.js.map +1 -1
- package/dist/components/SynapseHomepageV2/SynapseHomepageNavBar.d.ts.map +1 -1
- package/dist/components/SynapseHomepageV2/SynapseHomepageNavBar.js +2 -1
- package/dist/components/SynapseHomepageV2/SynapseHomepageNavBar.js.map +1 -1
- package/dist/components/SynapseHomepageV2/SynapseInActionItem.js +4 -4
- package/dist/components/SynapseHomepageV2/SynapseInActionItem.js.map +1 -1
- package/dist/components/SynapseHomepageV2/SynapseTrendingProjectsItem.js +1 -1
- package/dist/components/SynapseHomepageV2/SynapseTrendingProjectsItem.js.map +1 -1
- package/dist/components/SynapseNavDrawer/SynapseNavDrawer.d.ts.map +1 -1
- package/dist/components/SynapseNavDrawer/SynapseNavDrawer.js +4 -1
- package/dist/components/SynapseNavDrawer/SynapseNavDrawer.js.map +1 -1
- package/dist/components/SynapsePortalBanners/SynapsePortalBanners.js +1 -1
- package/dist/components/SynapsePortalBanners/SynapsePortalBanners.js.map +1 -1
- package/dist/components/SynapseSearchPageResults/SynapseSearchPageResults.js +1 -1
- package/dist/components/SynapseSearchPageResults/SynapseSearchPageResults.js.map +1 -1
- package/dist/components/SynapseSearchPageResults/SynapseSearchResultsCard.d.ts.map +1 -1
- package/dist/components/SynapseSearchPageResults/SynapseSearchResultsCard.js +12 -9
- package/dist/components/SynapseSearchPageResults/SynapseSearchResultsCard.js.map +1 -1
- package/dist/components/SynapseTable/RowSelection/RowSelectionControls.js +4 -4
- package/dist/components/SynapseTable/RowSelection/RowSelectionControls.js.map +1 -1
- package/dist/components/SynapseTable/datasets/DatasetItemsEditor.js +140 -140
- package/dist/components/SynapseTable/datasets/DatasetItemsEditor.js.map +1 -1
- package/dist/components/TableColumnSchemaEditor/ColumnModelForm.js +1 -1
- package/dist/components/TableColumnSchemaEditor/ColumnModelForm.js.map +1 -1
- package/dist/components/TableColumnSchemaEditor/ImportTableColumnsButton.js +1 -1
- package/dist/components/TableColumnSchemaEditor/ImportTableColumnsButton.js.map +1 -1
- package/dist/components/TableColumnSchemaEditor/TableColumnSchemaEditorUtils.d.ts.map +1 -1
- package/dist/components/TableColumnSchemaEditor/TableColumnSchemaEditorUtils.js.map +1 -1
- package/dist/components/TableColumnSchemaEditor/TableColumnSchemaForm.js +9 -9
- package/dist/components/TableColumnSchemaEditor/TableColumnSchemaForm.js.map +1 -1
- package/dist/components/TableColumnSchemaEditor/TableColumnSchemaFormActions.d.ts.map +1 -1
- package/dist/components/TableColumnSchemaEditor/TableColumnSchemaFormActions.js +6 -4
- package/dist/components/TableColumnSchemaEditor/TableColumnSchemaFormActions.js.map +1 -1
- package/dist/components/TanStackTable/ColumnHeader.js +1 -1
- package/dist/components/TanStackTable/ColumnHeader.js.map +1 -1
- package/dist/components/TeamSubjectsSelector/TeamBadgeOrError.js +1 -1
- package/dist/components/TeamSubjectsSelector/TeamBadgeOrError.js.map +1 -1
- package/dist/components/TeamSubjectsSelector/TeamSubjectsSelector.d.ts.map +1 -1
- package/dist/components/TeamSubjectsSelector/TeamSubjectsSelector.js +4 -3
- package/dist/components/TeamSubjectsSelector/TeamSubjectsSelector.js.map +1 -1
- package/dist/components/Webhook/WebhookDashboard.js +1 -1
- package/dist/components/Webhook/WebhookDashboard.js.map +1 -1
- package/dist/components/dataaccess/AccessRequirementDashboard.js +4 -4
- package/dist/components/dataaccess/AccessRequirementDashboard.js.map +1 -1
- package/dist/components/dataaccess/AccessRequirementTable.js +1 -1
- package/dist/components/dataaccess/AccessRequirementTable.js.map +1 -1
- package/dist/components/dataaccess/EDucTemplateTable.d.ts.map +1 -1
- package/dist/components/dataaccess/EDucTemplateTable.js +13 -11
- package/dist/components/dataaccess/EDucTemplateTable.js.map +1 -1
- package/dist/components/dataaccess/FormTemplateTable.js +6 -6
- package/dist/components/dataaccess/FormTemplateTable.js.map +1 -1
- package/dist/components/dataaccess/ReviewerDashboard.js +17 -17
- package/dist/components/dataaccess/ReviewerDashboard.js.map +1 -1
- package/dist/components/dataaccess/SubmissionPage/SubmissionPage.js +4 -4
- package/dist/components/doi/CreateOrUpdateDoiModal.js +1 -1
- package/dist/components/doi/CreateOrUpdateDoiModal.js.map +1 -1
- package/dist/components/download_list/DownloadDetails.d.ts.map +1 -1
- package/dist/components/download_list/DownloadDetails.js +12 -10
- package/dist/components/download_list/DownloadDetails.js.map +1 -1
- package/dist/components/entity/metadata/AnnotationsTable.js +1 -1
- package/dist/components/entity/metadata/AnnotationsTable.js.map +1 -1
- package/dist/components/entity/page/CreatedByModifiedBy.js +1 -1
- package/dist/components/entity/page/CreatedByModifiedBy.js.map +1 -1
- package/dist/components/entity/page/action_menu/EntityActionMenu.d.ts.map +1 -1
- package/dist/components/entity/page/action_menu/EntityActionMenu.js.map +1 -1
- package/dist/components/entity/page/title_bar/useGetEntityTitleBarProperties.js +1 -1
- package/dist/components/entity/page/title_bar/useGetEntityTitleBarProperties.js.map +1 -1
- package/dist/components/error/ErrorChip.d.ts.map +1 -1
- package/dist/components/error/ErrorChip.js +2 -1
- package/dist/components/error/ErrorChip.js.map +1 -1
- package/dist/components/table/CsvPreview/CreateTableFromCsvDialog.js +14 -14
- package/dist/components/table/CsvPreview/CsvPreviewWithOptions.js +4 -4
- package/dist/components/table/CsvPreview/CsvPreviewWithOptions.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/features/curator/dashboard/components/NextStepButton.d.ts.map +1 -1
- package/dist/features/curator/dashboard/components/NextStepButton.js +7 -6
- package/dist/features/curator/dashboard/components/NextStepButton.js.map +1 -1
- package/dist/features/entity/metadata-task/components/CreateOrUpdateCurationTaskDialog.js +8 -8
- package/dist/features/entity/metadata-task/components/CreateOrUpdateCurationTaskDialog.js.map +1 -1
- package/dist/features/entity/metadata-task/components/MetadataTaskTableActionCell.js +4 -4
- package/dist/features/entity/metadata-task/components/MetadataTaskTableActionCell.js.map +1 -1
- package/dist/features/entity/metadata-task/components/MetadataTasksPage.js +4 -4
- package/dist/features/entity/metadata-task/components/MetadataTasksPage.js.map +1 -1
- package/dist/features/entity/metadata-task/components/MetadataTasksTableAssigneeCell.js +1 -1
- package/dist/features/entity/metadata-task/components/MetadataTasksTableAssigneeCell.js.map +1 -1
- package/dist/features/entity/metadata-task/create-task/CurateTaskForm.js +4 -4
- package/dist/features/entity/metadata-task/create-task/CurateTaskForm.js.map +1 -1
- package/dist/features/entity/metadata-task/create-task/TaskCategoryCard.js +1 -1
- package/dist/features/entity/metadata-task/create-task/TaskCategoryCard.js.map +1 -1
- package/dist/features/entity/metadata-task/create-task/TaskFormHeader.js +1 -1
- package/dist/features/entity/metadata-task/create-task/TaskFormHeader.js.map +1 -1
- package/dist/features/entity/metadata-task/create-task/curationTaskFlowRoutes.js +10 -10
- package/dist/features/entity/metadata-task/create-task/curationTaskFlowRoutes.js.map +1 -1
- package/dist/features/team/invitation/components/OpenInvitationsToUserCard.js +1 -1
- package/dist/features/team/invitation/components/OpenInvitationsToUserCard.js.map +1 -1
- package/dist/mocks/msw/handlers/aridhiaHandlers.d.ts +8 -0
- package/dist/mocks/msw/handlers/aridhiaHandlers.d.ts.map +1 -1
- package/dist/mocks/msw/handlers/aridhiaHandlers.js +52 -41
- package/dist/mocks/msw/handlers/aridhiaHandlers.js.map +1 -1
- package/dist/mocks/msw/handlers/entityHandlers.d.ts.map +1 -1
- package/dist/mocks/msw/handlers/entityHandlers.js +70 -67
- package/dist/mocks/msw/handlers/entityHandlers.js.map +1 -1
- package/dist/mocks/msw/handlers/gridHandlers.js +2 -2
- package/dist/mocks/msw/handlers/gridHandlers.js.map +1 -1
- package/dist/mocks/msw/server.d.ts.map +1 -1
- package/dist/mocks/msw/server.js +4 -2
- package/dist/mocks/msw/server.js.map +1 -1
- package/dist/synapse-queries/user/useGetUserChallenges.d.ts.map +1 -1
- package/dist/synapse-queries/user/useGetUserChallenges.js.map +1 -1
- package/dist/theme/DefaultTheme.d.ts.map +1 -1
- package/dist/theme/DefaultTheme.js +4 -1
- package/dist/theme/DefaultTheme.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/utils/APIConstants.d.ts.map +1 -1
- package/dist/utils/APIConstants.js.map +1 -1
- package/dist/utils/AppUtils/AppUtils.js +1 -1
- package/dist/utils/AppUtils/AppUtils.js.map +1 -1
- package/dist/utils/functions/EntityTypeUtils.d.ts.map +1 -1
- package/dist/utils/functions/EntityTypeUtils.js.map +1 -1
- package/package.json +7 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TableColumnSchemaForm.js","names":[],"sources":["../../../src/components/TableColumnSchemaEditor/TableColumnSchemaForm.tsx"],"sourcesContent":["import AddToList from '@/assets/icons/AddToList'\nimport {\n useGetAnnotationColumnModels,\n useGetDefaultColumnModels,\n} from '@/synapse-queries/table/useColumnModel'\nimport {\n convertToConcreteEntityType,\n entityTypeToFriendlyName,\n} from '@/utils/functions/EntityTypeUtils'\nimport { AddCircleTwoTone } from '@mui/icons-material'\nimport { Box, Button, styled } from '@mui/material'\nimport { EntityType } from '@sage-bionetworks/synapse-client'\nimport {\n ColumnModel,\n ColumnTypeEnum,\n VIEW_CONCRETE_TYPE_VALUES,\n ViewScope,\n} from '@sage-bionetworks/synapse-types'\nimport { atom, Provider, useAtomValue, useSetAtom } from 'jotai'\nimport { selectAtom, useAtomCallback } from 'jotai/utils'\nimport { groupBy, isEqual, noop, omit, times } from 'lodash-es'\nimport pluralize from 'pluralize'\nimport {\n ForwardedRef,\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useMemo,\n useState,\n} from 'react'\nimport { SetOptional } from 'type-fest'\nimport { ZodError, ZodIssue } from 'zod'\nimport { SynapseSpinner } from '../LoadingScreen/LoadingScreen'\nimport { displayToast } from '../ToastMessage'\nimport ColumnModelForm from './ColumnModelForm'\nimport ImportTableColumnsButton from './ImportTableColumnsButton'\nimport {\n findMatchingColumnModel,\n getAllowedColumnTypes,\n transformColumnModelsToFormData,\n} from './TableColumnSchemaEditorUtils'\nimport { TableColumnSchemaFormActions } from './TableColumnSchemaFormActions'\nimport { tableColumnSchemaFormDataAtom } from './TableColumnSchemaFormReducer'\nimport { validateColumnModelFormData } from './Validators/ColumnModelValidator'\n\nconst COLUMN_SCHEMA_FORM_GRID_TEMPLATE_COLUMNS =\n '18px 18px 1.75fr 1.75fr 0.75fr 1fr 1.25fr 1.25fr 1fr 1.25fr'\nconst GRID_CONTAINER_Y_MARGIN_PX = 6\nexport const HIERARCHY_VERTICAL_LINE_COMPONENT = (\n <Box\n sx={{\n width: '1px',\n height: `calc(100% + 2 * ${GRID_CONTAINER_Y_MARGIN_PX}px)`,\n backgroundColor: 'grey.400',\n marginLeft: '8px',\n }}\n />\n)\nexport const HIERARCHY_END_COMPONENT = (\n <Box\n sx={theme => ({\n width: '50%',\n height: '60%',\n borderLeft: `1px solid ${theme.palette.grey[400]}`,\n borderBottom: `1px solid ${theme.palette.grey[400]}`,\n marginLeft: '8px',\n marginBottom: 'auto',\n marginRight: '0',\n borderBottomLeftRadius: '5px',\n })}\n />\n)\n\nexport type SubmitHandle = {\n // Allow the parent component to trigger a submit of the form, so this may be embedded in an arbitrary modal.\n submit: () => void\n // Imperative handle to get the data out of the form for SWC compatibility\n getEditedColumnModels: () => SetOptional<ColumnModel, 'id'>[]\n // Used to check if all form data is valid. Returns the current validity state\n validate: () => boolean\n}\n\ntype TableColumnSchemaFormProps = {\n /* The type of the Table, which determines various schema restrictions and form functionality */\n entityType: EntityType\n /* If this is an entity view, the ViewScope can be used to determine the default column models and fetch annotation column models */\n viewScope?: ViewScope\n initialData?: SetOptional<ColumnModel, 'id'>[]\n onSubmit?: (newColumnModels: SetOptional<ColumnModel, 'id'>[]) => void\n isSubmitting?: boolean\n /** The original/current column models that are applied to the table, if they exist. */\n originalColumnModels?: ColumnModel[]\n}\n\nconst ColumnHeader = styled(Box, {\n label: 'ColumnHeader',\n})({\n fontWeight: 700,\n})\n\nexport const ADD_ALL_ANNOTATIONS_BUTTON_TEXT = 'Add All Annotations'\n\nfunction TableColumnSchemaFormInternal(\n props: TableColumnSchemaFormProps,\n ref: ForwardedRef<SubmitHandle>,\n) {\n const {\n initialData,\n entityType,\n viewScope,\n onSubmit = noop,\n isSubmitting = false,\n originalColumnModels,\n } = props\n\n const numColumnModels = useAtomValue(\n useMemo(() => atom(get => get(tableColumnSchemaFormDataAtom).length), []),\n )\n\n const dispatch = useSetAtom(tableColumnSchemaFormDataAtom)\n const [validationErrors, setValidationErrors] = useState<ZodError | null>(\n null,\n )\n\n // useAtomCallback will let us imperatively read the form data, instead of tracking it in state and triggering a full re-render of the form when any data changes\n const readFormData = useAtomCallback(\n useCallback(get => {\n return get(tableColumnSchemaFormDataAtom)\n }, []),\n )\n const concreteTableType = convertToConcreteEntityType(entityType)\n const isView = VIEW_CONCRETE_TYPE_VALUES.includes(\n concreteTableType as (typeof VIEW_CONCRETE_TYPE_VALUES)[number],\n )\n const hasAnnotationColumnModels = isView,\n hasDefaultColumnModels = isView\n\n const { data: defaultColumnModels, isLoading: isLoadingDefaultColumns } =\n useGetDefaultColumnModels(\n viewScope?.viewEntityType!,\n viewScope?.viewTypeMask,\n {\n enabled: hasDefaultColumnModels,\n staleTime: Infinity, // The default column models will never change\n },\n )\n\n const annotationColumnModelsQuery = useGetAnnotationColumnModels(\n {\n viewScope: viewScope!,\n includeDerivedAnnotations: true,\n concreteType:\n 'org.sagebionetworks.repo.model.table.ViewColumnModelRequest',\n },\n {\n enabled: hasAnnotationColumnModels,\n },\n )\n\n const {\n data: annotationColumnModels,\n isLoading: isLoadingAnnotationColumns,\n } = annotationColumnModelsQuery\n\n /**\n * Set the initialData in the form state atom on mount, if it exists and we have no data.\n */\n useEffect(() => {\n if (initialData && !isLoadingDefaultColumns) {\n dispatch({\n type: 'setValue',\n value: transformColumnModelsToFormData(\n initialData,\n defaultColumnModels ?? [],\n ),\n })\n }\n // Don't re-run if initial data changes\n // oxlint-disable-next-line react-hooks/exhaustive-deps\n }, [isLoadingDefaultColumns])\n\n const validateInternal = useCallback(() => {\n const result = validateColumnModelFormData(readFormData())\n if (result.success) {\n setValidationErrors(null)\n } else {\n setValidationErrors(result.error)\n }\n return result\n }, [readFormData])\n\n useImperativeHandle(ref, () => {\n return {\n submit() {\n const result = validateInternal()\n if (result.success) {\n onSubmit(result.data)\n }\n },\n getEditedColumnModels() {\n const result = validateInternal()\n if (!result.success) {\n throw new Error('Column models were not valid')\n }\n return result.data\n },\n validate() {\n const result = validateInternal()\n return result.success\n },\n }\n }, [onSubmit, validateInternal])\n\n // Generic function to add a set of columns to the schema (e.g. default columns, annotation columns)\n const addColumnSet = useCallback(\n (newColumns: SetOptional<ColumnModel, 'id'>[]) => {\n const currentFormData = readFormData()\n let columnsToAdd = newColumns.filter(\n (cm: SetOptional<ColumnModel, 'id'>) => {\n // Don't add columns that cannot be added (for example, Views cannot have JSON columns)\n if (\n !getAllowedColumnTypes(isView, false).includes(\n cm.columnType as ColumnTypeEnum,\n )\n ) {\n return false\n }\n // Only add columns that are not already present\n // Use the name column to match because the ID may vary, e.g. if the facetType was changed\n return !currentFormData.find(fd => fd.name === cm.name)\n },\n )\n // Remove the ID column so TableColumnSchemaUtils.createTableUpdateTransactionRequest recognizes these as new columns\n // createTableUpdateTransactionRequest uses the existing column ID to track column updates in the table, so any new columns should have no ID\n // The user can also modify these columns before submitting them, so the ID may not be accurate when we end up submitting them\n columnsToAdd = columnsToAdd.map(cm => omit(cm, ['id']))\n if (columnsToAdd.length > 0) {\n dispatch({\n type: 'setValue',\n value: [\n ...currentFormData,\n ...transformColumnModelsToFormData(\n columnsToAdd,\n defaultColumnModels,\n ),\n ],\n })\n displayToast(\n `${columnsToAdd.length} ${pluralize(\n 'column',\n columnsToAdd.length,\n )} added to schema.`,\n 'success',\n )\n } else {\n displayToast(\n 'No columns added. All columns to add are present in the column schema.',\n 'info',\n )\n }\n },\n [defaultColumnModels, dispatch, isView, readFormData],\n )\n\n const addDefaultColumns = useCallback(() => {\n if (defaultColumnModels) {\n addColumnSet(defaultColumnModels)\n }\n }, [defaultColumnModels, addColumnSet])\n\n const addAnnotationColumns = useCallback(() => {\n if (annotationColumnModels) {\n addColumnSet(annotationColumnModels)\n }\n }, [annotationColumnModels, addColumnSet])\n\n // Put the errors into a map of columnModelIndex -> errors\n const errorsByColumnModel = useMemo(() => {\n if (validationErrors) {\n return groupBy(validationErrors.issues, e => e.path[0])\n }\n return {}\n }, [validationErrors])\n\n return (\n <Box\n component={'form'}\n sx={{\n py: 2.5,\n }}\n >\n <TableColumnSchemaFormActions\n disabled={isSubmitting}\n annotationColumnModelsQuery={annotationColumnModelsQuery}\n />\n <Box\n sx={{\n display: 'grid',\n gap: '8px',\n gridTemplateColumns: COLUMN_SCHEMA_FORM_GRID_TEMPLATE_COLUMNS,\n py: 2.5,\n }}\n >\n <ColumnHeader>{/* Checkbox */}</ColumnHeader>\n <ColumnHeader sx={{ gridColumn: '2 / span 2' }}>\n Column Name\n </ColumnHeader>\n <ColumnHeader>Column Type</ColumnHeader>\n <ColumnHeader>Size</ColumnHeader>\n <ColumnHeader>Max List Length</ColumnHeader>\n <ColumnHeader>Default Value</ColumnHeader>\n <ColumnHeader>Restrict Values</ColumnHeader>\n <ColumnHeader>Facet</ColumnHeader>\n <ColumnHeader>Sort Facet Values</ColumnHeader>\n <Box\n sx={{\n gridColumn: '1 / span 11',\n backgroundColor: 'grey.300',\n height: '2px',\n }}\n />\n {times(numColumnModels, index => {\n return (\n <TableColumnSchemaFormRow\n entityType={entityType}\n columnModelIndex={index}\n disabled={isSubmitting}\n key={index}\n columnModelValidationErrors={errorsByColumnModel[index]}\n annotationColumnModels={annotationColumnModels}\n originalColumnModels={originalColumnModels}\n />\n )\n })}\n </Box>\n <Box\n sx={{\n display: 'flex',\n gap: 1,\n }}\n >\n <Button\n variant={'outlined'}\n onClick={() => {\n dispatch({ type: 'appendColumn' })\n }}\n startIcon={<AddCircleTwoTone />}\n disabled={isSubmitting}\n >\n Add Column\n </Button>\n\n {hasDefaultColumnModels && (\n <Button\n variant={'outlined'}\n startIcon={\n isLoadingDefaultColumns ? (\n <SynapseSpinner />\n ) : (\n <AddCircleTwoTone />\n )\n }\n onClick={() => {\n addDefaultColumns()\n }}\n disabled={isLoadingDefaultColumns || isSubmitting}\n >\n Add Default {entityTypeToFriendlyName(entityType)} Columns\n </Button>\n )}\n\n {hasAnnotationColumnModels && (\n <Button\n variant={'outlined'}\n startIcon={\n isLoadingAnnotationColumns ? (\n <SynapseSpinner />\n ) : (\n <AddCircleTwoTone />\n )\n }\n disabled={isLoadingAnnotationColumns || isSubmitting}\n onClick={() => {\n addAnnotationColumns()\n }}\n >\n {ADD_ALL_ANNOTATIONS_BUTTON_TEXT}\n </Button>\n )}\n <ImportTableColumnsButton\n onAddColumns={cms => {\n addColumnSet(cms)\n }}\n disabled={isSubmitting}\n />\n </Box>\n </Box>\n )\n}\n\ntype TableColumnSchemaFormRowProps = {\n entityType: EntityType\n columnModelIndex: number\n disabled: boolean\n columnModelValidationErrors: ZodIssue[] | null\n annotationColumnModels?: ColumnModel[]\n originalColumnModels?: ColumnModel[]\n}\n\nfunction TableColumnSchemaFormRow(props: TableColumnSchemaFormRowProps) {\n const {\n columnModelIndex,\n entityType,\n disabled,\n columnModelValidationErrors = null,\n annotationColumnModels,\n originalColumnModels,\n } = props\n const dispatch = useSetAtom(tableColumnSchemaFormDataAtom)\n const columnModel = useAtomValue(\n useMemo(\n () =>\n selectAtom(\n tableColumnSchemaFormDataAtom,\n formData => formData[columnModelIndex],\n isEqual,\n ),\n [columnModelIndex],\n ),\n )\n\n // Find the original column model that matches the current column model by name and type, so we can tell the user what fields have changed\n const originalColumnModel = originalColumnModels\n ? findMatchingColumnModel(originalColumnModels, columnModel)\n : undefined\n\n // Find the closest match between passed column model and current column model with name and type\n const defaultAnnotationModel = annotationColumnModels\n ? findMatchingColumnModel(annotationColumnModels, columnModel)\n : undefined\n\n // Organize the JSON Subcolumn errors into a map of subcolumn index to errors\n const errorsForSubcolumns = useMemo(() => {\n if (columnModelValidationErrors) {\n const errorsForAllSubcolumns = columnModelValidationErrors.filter(e => {\n return e.path[0] === columnModelIndex && e.path[1] == 'jsonSubColumns'\n })\n return groupBy(errorsForAllSubcolumns, e => e.path[2])\n }\n return {}\n }, [columnModelIndex, columnModelValidationErrors])\n\n if (!columnModel) {\n return <></>\n }\n const isDefaultColumn = columnModel.isOriginallyDefaultColumn\n\n return (\n <>\n <ColumnModelForm\n entityType={entityType}\n columnModelIndex={columnModelIndex}\n isDefaultColumn={isDefaultColumn}\n disabled={disabled}\n validationErrors={columnModelValidationErrors}\n defaultAnnotationModel={defaultAnnotationModel}\n originalColumnModel={originalColumnModel}\n />\n {columnModel.columnType === ColumnTypeEnum.JSON &&\n columnModel.jsonSubColumns &&\n columnModel.jsonSubColumns.map((subColumnFacet, index) => (\n <ColumnModelForm\n key={index}\n entityType={entityType}\n columnModelIndex={columnModelIndex}\n jsonSubColumnIndex={index}\n isDefaultColumn={isDefaultColumn}\n disabled={disabled}\n validationErrors={errorsForSubcolumns[index]}\n />\n ))}\n {columnModel.columnType === ColumnTypeEnum.JSON && (\n <>\n <Box\n sx={{\n gridColumn: '1 / span 2',\n }}\n >\n {HIERARCHY_END_COMPONENT}\n </Box>\n <Box\n sx={{\n gridColumn: '3 / span 5',\n }}\n >\n <Button\n startIcon={<AddToList />}\n variant={'text'}\n disabled={disabled}\n onClick={() =>\n dispatch({ type: 'appendJsonSubColumn', columnModelIndex })\n }\n >\n Add sub-column\n </Button>\n </Box>\n </>\n )}\n </>\n )\n}\n\nconst TableColumnSchemaFormInternalWithForwardRef = forwardRef<\n SubmitHandle,\n TableColumnSchemaFormProps\n>(TableColumnSchemaFormInternal)\n\nconst TableColumnSchemaFormWrapped = forwardRef<\n SubmitHandle,\n TableColumnSchemaFormProps\n>(function TableColumnSchemaForm(props: TableColumnSchemaFormProps, ref) {\n // Wrap the form in a Jotai provider so that the internal atoms are scoped to just this component instance\n // Use forwardRef to ensure that the ref can be passed along\n return (\n <Provider>\n <TableColumnSchemaFormInternalWithForwardRef {...props} ref={ref} />\n </Provider>\n )\n})\n\nexport default TableColumnSchemaFormWrapped\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TableColumnSchemaForm.js","names":[],"sources":["../../../src/components/TableColumnSchemaEditor/TableColumnSchemaForm.tsx"],"sourcesContent":["import AddToList from '@/assets/icons/AddToList'\nimport {\n useGetAnnotationColumnModels,\n useGetDefaultColumnModels,\n} from '@/synapse-queries/table/useColumnModel'\nimport {\n convertToConcreteEntityType,\n entityTypeToFriendlyName,\n} from '@/utils/functions/EntityTypeUtils'\nimport AddCircleTwoTone from '@mui/icons-material/AddCircleTwoTone'\nimport { Box, Button, styled } from '@mui/material'\nimport { EntityType } from '@sage-bionetworks/synapse-client'\nimport {\n ColumnModel,\n ColumnTypeEnum,\n VIEW_CONCRETE_TYPE_VALUES,\n ViewScope,\n} from '@sage-bionetworks/synapse-types'\nimport { atom, Provider, useAtomValue, useSetAtom } from 'jotai'\nimport { selectAtom, useAtomCallback } from 'jotai/utils'\nimport { groupBy, isEqual, noop, omit, times } from 'lodash-es'\nimport pluralize from 'pluralize'\nimport {\n ForwardedRef,\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useMemo,\n useState,\n} from 'react'\nimport { SetOptional } from 'type-fest'\nimport { ZodError, ZodIssue } from 'zod'\nimport { SynapseSpinner } from '../LoadingScreen/LoadingScreen'\nimport { displayToast } from '../ToastMessage'\nimport ColumnModelForm from './ColumnModelForm'\nimport ImportTableColumnsButton from './ImportTableColumnsButton'\nimport {\n findMatchingColumnModel,\n getAllowedColumnTypes,\n transformColumnModelsToFormData,\n} from './TableColumnSchemaEditorUtils'\nimport { TableColumnSchemaFormActions } from './TableColumnSchemaFormActions'\nimport { tableColumnSchemaFormDataAtom } from './TableColumnSchemaFormReducer'\nimport { validateColumnModelFormData } from './Validators/ColumnModelValidator'\n\nconst COLUMN_SCHEMA_FORM_GRID_TEMPLATE_COLUMNS =\n '18px 18px 1.75fr 1.75fr 0.75fr 1fr 1.25fr 1.25fr 1fr 1.25fr'\nconst GRID_CONTAINER_Y_MARGIN_PX = 6\nexport const HIERARCHY_VERTICAL_LINE_COMPONENT = (\n <Box\n sx={{\n width: '1px',\n height: `calc(100% + 2 * ${GRID_CONTAINER_Y_MARGIN_PX}px)`,\n backgroundColor: 'grey.400',\n marginLeft: '8px',\n }}\n />\n)\nexport const HIERARCHY_END_COMPONENT = (\n <Box\n sx={theme => ({\n width: '50%',\n height: '60%',\n borderLeft: `1px solid ${theme.palette.grey[400]}`,\n borderBottom: `1px solid ${theme.palette.grey[400]}`,\n marginLeft: '8px',\n marginBottom: 'auto',\n marginRight: '0',\n borderBottomLeftRadius: '5px',\n })}\n />\n)\n\nexport type SubmitHandle = {\n // Allow the parent component to trigger a submit of the form, so this may be embedded in an arbitrary modal.\n submit: () => void\n // Imperative handle to get the data out of the form for SWC compatibility\n getEditedColumnModels: () => SetOptional<ColumnModel, 'id'>[]\n // Used to check if all form data is valid. Returns the current validity state\n validate: () => boolean\n}\n\ntype TableColumnSchemaFormProps = {\n /* The type of the Table, which determines various schema restrictions and form functionality */\n entityType: EntityType\n /* If this is an entity view, the ViewScope can be used to determine the default column models and fetch annotation column models */\n viewScope?: ViewScope\n initialData?: SetOptional<ColumnModel, 'id'>[]\n onSubmit?: (newColumnModels: SetOptional<ColumnModel, 'id'>[]) => void\n isSubmitting?: boolean\n /** The original/current column models that are applied to the table, if they exist. */\n originalColumnModels?: ColumnModel[]\n}\n\nconst ColumnHeader = styled(Box, {\n label: 'ColumnHeader',\n})({\n fontWeight: 700,\n})\n\nexport const ADD_ALL_ANNOTATIONS_BUTTON_TEXT = 'Add All Annotations'\n\nfunction TableColumnSchemaFormInternal(\n props: TableColumnSchemaFormProps,\n ref: ForwardedRef<SubmitHandle>,\n) {\n const {\n initialData,\n entityType,\n viewScope,\n onSubmit = noop,\n isSubmitting = false,\n originalColumnModels,\n } = props\n\n const numColumnModels = useAtomValue(\n useMemo(() => atom(get => get(tableColumnSchemaFormDataAtom).length), []),\n )\n\n const dispatch = useSetAtom(tableColumnSchemaFormDataAtom)\n const [validationErrors, setValidationErrors] = useState<ZodError | null>(\n null,\n )\n\n // useAtomCallback will let us imperatively read the form data, instead of tracking it in state and triggering a full re-render of the form when any data changes\n const readFormData = useAtomCallback(\n useCallback(get => {\n return get(tableColumnSchemaFormDataAtom)\n }, []),\n )\n const concreteTableType = convertToConcreteEntityType(entityType)\n const isView = VIEW_CONCRETE_TYPE_VALUES.includes(\n concreteTableType as (typeof VIEW_CONCRETE_TYPE_VALUES)[number],\n )\n const hasAnnotationColumnModels = isView,\n hasDefaultColumnModels = isView\n\n const { data: defaultColumnModels, isLoading: isLoadingDefaultColumns } =\n useGetDefaultColumnModels(\n viewScope?.viewEntityType!,\n viewScope?.viewTypeMask,\n {\n enabled: hasDefaultColumnModels,\n staleTime: Infinity, // The default column models will never change\n },\n )\n\n const annotationColumnModelsQuery = useGetAnnotationColumnModels(\n {\n viewScope: viewScope!,\n includeDerivedAnnotations: true,\n concreteType:\n 'org.sagebionetworks.repo.model.table.ViewColumnModelRequest',\n },\n {\n enabled: hasAnnotationColumnModels,\n },\n )\n\n const {\n data: annotationColumnModels,\n isLoading: isLoadingAnnotationColumns,\n } = annotationColumnModelsQuery\n\n /**\n * Set the initialData in the form state atom on mount, if it exists and we have no data.\n */\n useEffect(() => {\n if (initialData && !isLoadingDefaultColumns) {\n dispatch({\n type: 'setValue',\n value: transformColumnModelsToFormData(\n initialData,\n defaultColumnModels ?? [],\n ),\n })\n }\n // Don't re-run if initial data changes\n // oxlint-disable-next-line react-hooks/exhaustive-deps\n }, [isLoadingDefaultColumns])\n\n const validateInternal = useCallback(() => {\n const result = validateColumnModelFormData(readFormData())\n if (result.success) {\n setValidationErrors(null)\n } else {\n setValidationErrors(result.error)\n }\n return result\n }, [readFormData])\n\n useImperativeHandle(ref, () => {\n return {\n submit() {\n const result = validateInternal()\n if (result.success) {\n onSubmit(result.data)\n }\n },\n getEditedColumnModels() {\n const result = validateInternal()\n if (!result.success) {\n throw new Error('Column models were not valid')\n }\n return result.data\n },\n validate() {\n const result = validateInternal()\n return result.success\n },\n }\n }, [onSubmit, validateInternal])\n\n // Generic function to add a set of columns to the schema (e.g. default columns, annotation columns)\n const addColumnSet = useCallback(\n (newColumns: SetOptional<ColumnModel, 'id'>[]) => {\n const currentFormData = readFormData()\n let columnsToAdd = newColumns.filter(\n (cm: SetOptional<ColumnModel, 'id'>) => {\n // Don't add columns that cannot be added (for example, Views cannot have JSON columns)\n if (\n !getAllowedColumnTypes(isView, false).includes(\n cm.columnType as ColumnTypeEnum,\n )\n ) {\n return false\n }\n // Only add columns that are not already present\n // Use the name column to match because the ID may vary, e.g. if the facetType was changed\n return !currentFormData.find(fd => fd.name === cm.name)\n },\n )\n // Remove the ID column so TableColumnSchemaUtils.createTableUpdateTransactionRequest recognizes these as new columns\n // createTableUpdateTransactionRequest uses the existing column ID to track column updates in the table, so any new columns should have no ID\n // The user can also modify these columns before submitting them, so the ID may not be accurate when we end up submitting them\n columnsToAdd = columnsToAdd.map(cm => omit(cm, ['id']))\n if (columnsToAdd.length > 0) {\n dispatch({\n type: 'setValue',\n value: [\n ...currentFormData,\n ...transformColumnModelsToFormData(\n columnsToAdd,\n defaultColumnModels,\n ),\n ],\n })\n displayToast(\n `${columnsToAdd.length} ${pluralize(\n 'column',\n columnsToAdd.length,\n )} added to schema.`,\n 'success',\n )\n } else {\n displayToast(\n 'No columns added. All columns to add are present in the column schema.',\n 'info',\n )\n }\n },\n [defaultColumnModels, dispatch, isView, readFormData],\n )\n\n const addDefaultColumns = useCallback(() => {\n if (defaultColumnModels) {\n addColumnSet(defaultColumnModels)\n }\n }, [defaultColumnModels, addColumnSet])\n\n const addAnnotationColumns = useCallback(() => {\n if (annotationColumnModels) {\n addColumnSet(annotationColumnModels)\n }\n }, [annotationColumnModels, addColumnSet])\n\n // Put the errors into a map of columnModelIndex -> errors\n const errorsByColumnModel = useMemo(() => {\n if (validationErrors) {\n return groupBy(validationErrors.issues, e => e.path[0])\n }\n return {}\n }, [validationErrors])\n\n return (\n <Box\n component={'form'}\n sx={{\n py: 2.5,\n }}\n >\n <TableColumnSchemaFormActions\n disabled={isSubmitting}\n annotationColumnModelsQuery={annotationColumnModelsQuery}\n />\n <Box\n sx={{\n display: 'grid',\n gap: '8px',\n gridTemplateColumns: COLUMN_SCHEMA_FORM_GRID_TEMPLATE_COLUMNS,\n py: 2.5,\n }}\n >\n <ColumnHeader>{/* Checkbox */}</ColumnHeader>\n <ColumnHeader sx={{ gridColumn: '2 / span 2' }}>\n Column Name\n </ColumnHeader>\n <ColumnHeader>Column Type</ColumnHeader>\n <ColumnHeader>Size</ColumnHeader>\n <ColumnHeader>Max List Length</ColumnHeader>\n <ColumnHeader>Default Value</ColumnHeader>\n <ColumnHeader>Restrict Values</ColumnHeader>\n <ColumnHeader>Facet</ColumnHeader>\n <ColumnHeader>Sort Facet Values</ColumnHeader>\n <Box\n sx={{\n gridColumn: '1 / span 11',\n backgroundColor: 'grey.300',\n height: '2px',\n }}\n />\n {times(numColumnModels, index => {\n return (\n <TableColumnSchemaFormRow\n entityType={entityType}\n columnModelIndex={index}\n disabled={isSubmitting}\n key={index}\n columnModelValidationErrors={errorsByColumnModel[index]}\n annotationColumnModels={annotationColumnModels}\n originalColumnModels={originalColumnModels}\n />\n )\n })}\n </Box>\n <Box\n sx={{\n display: 'flex',\n gap: 1,\n }}\n >\n <Button\n variant={'outlined'}\n onClick={() => {\n dispatch({ type: 'appendColumn' })\n }}\n startIcon={<AddCircleTwoTone />}\n disabled={isSubmitting}\n >\n Add Column\n </Button>\n\n {hasDefaultColumnModels && (\n <Button\n variant={'outlined'}\n startIcon={\n isLoadingDefaultColumns ? (\n <SynapseSpinner />\n ) : (\n <AddCircleTwoTone />\n )\n }\n onClick={() => {\n addDefaultColumns()\n }}\n disabled={isLoadingDefaultColumns || isSubmitting}\n >\n Add Default {entityTypeToFriendlyName(entityType)} Columns\n </Button>\n )}\n\n {hasAnnotationColumnModels && (\n <Button\n variant={'outlined'}\n startIcon={\n isLoadingAnnotationColumns ? (\n <SynapseSpinner />\n ) : (\n <AddCircleTwoTone />\n )\n }\n disabled={isLoadingAnnotationColumns || isSubmitting}\n onClick={() => {\n addAnnotationColumns()\n }}\n >\n {ADD_ALL_ANNOTATIONS_BUTTON_TEXT}\n </Button>\n )}\n <ImportTableColumnsButton\n onAddColumns={cms => {\n addColumnSet(cms)\n }}\n disabled={isSubmitting}\n />\n </Box>\n </Box>\n )\n}\n\ntype TableColumnSchemaFormRowProps = {\n entityType: EntityType\n columnModelIndex: number\n disabled: boolean\n columnModelValidationErrors: ZodIssue[] | null\n annotationColumnModels?: ColumnModel[]\n originalColumnModels?: ColumnModel[]\n}\n\nfunction TableColumnSchemaFormRow(props: TableColumnSchemaFormRowProps) {\n const {\n columnModelIndex,\n entityType,\n disabled,\n columnModelValidationErrors = null,\n annotationColumnModels,\n originalColumnModels,\n } = props\n const dispatch = useSetAtom(tableColumnSchemaFormDataAtom)\n const columnModel = useAtomValue(\n useMemo(\n () =>\n selectAtom(\n tableColumnSchemaFormDataAtom,\n formData => formData[columnModelIndex],\n isEqual,\n ),\n [columnModelIndex],\n ),\n )\n\n // Find the original column model that matches the current column model by name and type, so we can tell the user what fields have changed\n const originalColumnModel = originalColumnModels\n ? findMatchingColumnModel(originalColumnModels, columnModel)\n : undefined\n\n // Find the closest match between passed column model and current column model with name and type\n const defaultAnnotationModel = annotationColumnModels\n ? findMatchingColumnModel(annotationColumnModels, columnModel)\n : undefined\n\n // Organize the JSON Subcolumn errors into a map of subcolumn index to errors\n const errorsForSubcolumns = useMemo(() => {\n if (columnModelValidationErrors) {\n const errorsForAllSubcolumns = columnModelValidationErrors.filter(e => {\n return e.path[0] === columnModelIndex && e.path[1] == 'jsonSubColumns'\n })\n return groupBy(errorsForAllSubcolumns, e => e.path[2])\n }\n return {}\n }, [columnModelIndex, columnModelValidationErrors])\n\n if (!columnModel) {\n return <></>\n }\n const isDefaultColumn = columnModel.isOriginallyDefaultColumn\n\n return (\n <>\n <ColumnModelForm\n entityType={entityType}\n columnModelIndex={columnModelIndex}\n isDefaultColumn={isDefaultColumn}\n disabled={disabled}\n validationErrors={columnModelValidationErrors}\n defaultAnnotationModel={defaultAnnotationModel}\n originalColumnModel={originalColumnModel}\n />\n {columnModel.columnType === ColumnTypeEnum.JSON &&\n columnModel.jsonSubColumns &&\n columnModel.jsonSubColumns.map((subColumnFacet, index) => (\n <ColumnModelForm\n key={index}\n entityType={entityType}\n columnModelIndex={columnModelIndex}\n jsonSubColumnIndex={index}\n isDefaultColumn={isDefaultColumn}\n disabled={disabled}\n validationErrors={errorsForSubcolumns[index]}\n />\n ))}\n {columnModel.columnType === ColumnTypeEnum.JSON && (\n <>\n <Box\n sx={{\n gridColumn: '1 / span 2',\n }}\n >\n {HIERARCHY_END_COMPONENT}\n </Box>\n <Box\n sx={{\n gridColumn: '3 / span 5',\n }}\n >\n <Button\n startIcon={<AddToList />}\n variant={'text'}\n disabled={disabled}\n onClick={() =>\n dispatch({ type: 'appendJsonSubColumn', columnModelIndex })\n }\n >\n Add sub-column\n </Button>\n </Box>\n </>\n )}\n </>\n )\n}\n\nconst TableColumnSchemaFormInternalWithForwardRef = forwardRef<\n SubmitHandle,\n TableColumnSchemaFormProps\n>(TableColumnSchemaFormInternal)\n\nconst TableColumnSchemaFormWrapped = forwardRef<\n SubmitHandle,\n TableColumnSchemaFormProps\n>(function TableColumnSchemaForm(props: TableColumnSchemaFormProps, ref) {\n // Wrap the form in a Jotai provider so that the internal atoms are scoped to just this component instance\n // Use forwardRef to ensure that the ref can be passed along\n return (\n <Provider>\n <TableColumnSchemaFormInternalWithForwardRef {...props} ref={ref} />\n </Provider>\n )\n})\n\nexport default TableColumnSchemaFormWrapped\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TableColumnSchemaFormActions.d.ts","sourceRoot":"","sources":["../../../src/components/TableColumnSchemaEditor/TableColumnSchemaFormActions.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,4BAA4B,EAAE,MAAM,wCAAwC,CAAA;
|
|
1
|
+
{"version":3,"file":"TableColumnSchemaFormActions.d.ts","sourceRoot":"","sources":["../../../src/components/TableColumnSchemaEditor/TableColumnSchemaFormActions.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,4BAA4B,EAAE,MAAM,wCAAwC,CAAA;AA0BrF,eAAO,MAAM,iCAAiC,0BAA0B,CAAA;AAiBxE,KAAK,iCAAiC,GAAG;IACvC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,2BAA2B,EAAE,UAAU,CAAC,OAAO,4BAA4B,CAAC,CAAA;CAC7E,CAAA;AAED,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,iCAAiC,2CAmKzC"}
|
|
@@ -7,8 +7,10 @@ import { getIsAllSelected as i, getNumberOfSelectedItems as a, tableColumnSchema
|
|
|
7
7
|
import { useState as s } from "react";
|
|
8
8
|
import { Box as c, Button as l, ButtonGroup as u, Checkbox as d, Link as f, Tooltip as p, Typography as m } from "@mui/material";
|
|
9
9
|
import { Fragment as h, jsx as g, jsxs as _ } from "react/jsx-runtime";
|
|
10
|
-
import
|
|
11
|
-
import
|
|
10
|
+
import v from "pluralize";
|
|
11
|
+
import y from "@mui/icons-material/North";
|
|
12
|
+
import b from "@mui/icons-material/South";
|
|
13
|
+
import x from "@mui/icons-material/Healing";
|
|
12
14
|
import { useAtomValue as S, useSetAtom as C } from "jotai/index";
|
|
13
15
|
//#region src/components/TableColumnSchemaEditor/TableColumnSchemaFormActions.tsx
|
|
14
16
|
var w = "Use Recommended Sizes", T = /* @__PURE__ */ _(h, { children: [
|
|
@@ -114,7 +116,7 @@ function E(w) {
|
|
|
114
116
|
onCancel: () => {
|
|
115
117
|
N(!1);
|
|
116
118
|
},
|
|
117
|
-
title: `This will change ${F.toLocaleString()} ${
|
|
119
|
+
title: `This will change ${F.toLocaleString()} ${v("column", F)} in this schema`,
|
|
118
120
|
content: T,
|
|
119
121
|
confirmButtonProps: { children: "Use Recommended Sizes" }
|
|
120
122
|
}), /* @__PURE__ */ g(p, {
|
|
@@ -122,7 +124,7 @@ function E(w) {
|
|
|
122
124
|
children: /* @__PURE__ */ g(c, { children: /* @__PURE__ */ g(l, {
|
|
123
125
|
sx: { height: "100%" },
|
|
124
126
|
variant: "outlined",
|
|
125
|
-
startIcon: D.isLoading ? /* @__PURE__ */ g(e, {}) : /* @__PURE__ */ g(
|
|
127
|
+
startIcon: D.isLoading ? /* @__PURE__ */ g(e, {}) : /* @__PURE__ */ g(x, {}),
|
|
126
128
|
onClick: () => {
|
|
127
129
|
N(!0);
|
|
128
130
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TableColumnSchemaFormActions.js","names":[],"sources":["../../../src/components/TableColumnSchemaEditor/TableColumnSchemaFormActions.tsx"],"sourcesContent":["import { useGetAnnotationColumnModels } from '@/synapse-queries/table/useColumnModel'\nimport
|
|
1
|
+
{"version":3,"file":"TableColumnSchemaFormActions.js","names":[],"sources":["../../../src/components/TableColumnSchemaEditor/TableColumnSchemaFormActions.tsx"],"sourcesContent":["import { useGetAnnotationColumnModels } from '@/synapse-queries/table/useColumnModel'\nimport Healing from '@mui/icons-material/Healing'\nimport North from '@mui/icons-material/North'\nimport South from '@mui/icons-material/South'\nimport {\n Box,\n Button,\n ButtonGroup,\n Checkbox,\n Link,\n Tooltip,\n Typography,\n} from '@mui/material'\nimport { useAtomValue, useSetAtom } from 'jotai/index'\nimport pluralize from 'pluralize'\nimport { useState } from 'react'\nimport { ConfirmationDialog } from '../ConfirmationDialog'\nimport IconSvg from '../IconSvg'\nimport { SynapseSpinner } from '../LoadingScreen/LoadingScreen'\nimport { getNumberOfColumnModelsWithValuesBelowMinimumRecommendedSizes } from './TableColumnSchemaEditorUtils'\nimport {\n getIsAllSelected,\n getNumberOfSelectedItems,\n tableColumnSchemaFormDataAtom,\n} from './TableColumnSchemaFormReducer'\n\nexport const USE_RECOMMENDED_SIZES_BUTTON_TEXT = 'Use Recommended Sizes'\n\nconst RECOMMENDED_SIZES_CONFIRMATION_MODAL_CONTENT = (\n <>\n <Typography variant={'body1'}>\n Proceeding will adjust columns with size values that are shorter than\n longest data in your annotations.\n </Typography>\n <Typography variant={'body1'}>\n Changed size values will appear in blue. Hover to see the previous value.\n </Typography>\n <Typography variant={'body1'}>\n Changes are saved only after clicking “Save” in the Schema editor. Click\n “Cancel” to discard unsaved changes.\n </Typography>\n </>\n)\ntype TableColumnSchemaFormActionsProps = {\n disabled?: boolean\n annotationColumnModelsQuery: ReturnType<typeof useGetAnnotationColumnModels>\n}\n\nexport function TableColumnSchemaFormActions(\n props: TableColumnSchemaFormActionsProps,\n) {\n const { disabled = false, annotationColumnModelsQuery } = props\n const dispatch = useSetAtom(tableColumnSchemaFormDataAtom)\n\n const columnModels = useAtomValue(tableColumnSchemaFormDataAtom)\n const allSelected = getIsAllSelected(columnModels)\n const numSelected = getNumberOfSelectedItems(columnModels)\n\n const [\n showUseRecommendedSizesConfirmationDialog,\n setShowUseRecommendedSizesConfirmationDialog,\n ] = useState(false)\n\n const showUseRecommendedSizesButton =\n annotationColumnModelsQuery.isLoading || annotationColumnModelsQuery.data\n const numberOfColumnsBelowRecommendedSizes = annotationColumnModelsQuery.data\n ? getNumberOfColumnModelsWithValuesBelowMinimumRecommendedSizes(\n columnModels,\n annotationColumnModelsQuery.data,\n )\n : 0\n\n return (\n <Box\n sx={{\n display: 'flex',\n alignItems: 'flex-start',\n gap: 1,\n }}\n >\n <Button\n aria-label={'Select All'}\n variant={'outlined'}\n color={'neutral'}\n onClick={() => {\n dispatch({ type: 'toggleSelectAll' })\n }}\n sx={{ alignSelf: 'stretch' }}\n disabled={disabled || columnModels.length == 0}\n >\n <Checkbox\n sx={{ mr: 1 }}\n checked={allSelected}\n indeterminate={numSelected > 0 && !allSelected}\n disabled={disabled || columnModels.length == 0}\n />\n <Typography\n variant=\"smallText1\"\n sx={{\n color: 'text.secondary',\n }}\n >\n {numSelected} selected\n </Typography>\n </Button>\n <ButtonGroup sx={{ alignSelf: 'stretch' }}>\n <Button\n aria-label={'Move Down'}\n variant={'outlined'}\n color={'neutral'}\n onClick={() => {\n dispatch({ type: 'moveDown' })\n }}\n disabled={disabled || numSelected == 0}\n >\n <South fontSize={'small'} />\n </Button>\n <Button\n aria-label={'Move Up'}\n variant={'outlined'}\n color={'neutral'}\n onClick={() => {\n dispatch({ type: 'moveUp' })\n }}\n disabled={disabled || numSelected == 0}\n >\n <North fontSize={'small'} />\n </Button>\n </ButtonGroup>\n <Button\n aria-label={'Delete'}\n variant={'outlined'}\n color={'neutral'}\n onClick={() => {\n dispatch({ type: 'delete' })\n }}\n sx={{ alignSelf: 'stretch' }}\n disabled={disabled || numSelected == 0}\n >\n <IconSvg fontSize={'small'} icon={'delete'} wrap={false} />\n </Button>\n <Box\n sx={{\n flexGrow: 1,\n }}\n >\n {/* spacer */}\n </Box>\n <Link\n sx={{ display: 'block', py: '10px', mr: '10px', textAlign: 'right' }}\n href=\"https://help.synapse.org/docs/Organizing-Data-With-Tables.2011038095.html\"\n target=\"_blank\"\n >\n About schemas and column types\n </Link>\n {showUseRecommendedSizesButton && (\n <>\n <ConfirmationDialog\n open={showUseRecommendedSizesConfirmationDialog}\n onConfirm={() => {\n dispatch({\n type: 'updateColumnSizesToRecommendedValues',\n annotationColumnModels: annotationColumnModelsQuery.data!,\n })\n setShowUseRecommendedSizesConfirmationDialog(false)\n }}\n onCancel={() => {\n setShowUseRecommendedSizesConfirmationDialog(false)\n }}\n title={`This will change ${numberOfColumnsBelowRecommendedSizes.toLocaleString()} ${pluralize(\n 'column',\n numberOfColumnsBelowRecommendedSizes,\n )} in this schema`}\n content={RECOMMENDED_SIZES_CONFIRMATION_MODAL_CONTENT}\n confirmButtonProps={{\n children: USE_RECOMMENDED_SIZES_BUTTON_TEXT,\n }}\n />\n <Tooltip\n title={\n numberOfColumnsBelowRecommendedSizes > 0\n ? ''\n : 'All schema values meet the minimum recommended sizes.'\n }\n >\n <Box>\n <Button\n sx={{ height: '100%' }}\n variant={'outlined'}\n startIcon={\n annotationColumnModelsQuery.isLoading ? (\n <SynapseSpinner />\n ) : (\n <Healing />\n )\n }\n onClick={() => {\n setShowUseRecommendedSizesConfirmationDialog(true)\n }}\n disabled={\n annotationColumnModelsQuery.isLoading ||\n numberOfColumnsBelowRecommendedSizes == 0\n }\n >\n Use Recommended Sizes\n </Button>\n </Box>\n </Tooltip>\n </>\n )}\n </Box>\n )\n}\n"],"mappings":"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"}
|
|
@@ -3,7 +3,7 @@ import { ColumnHeaderEnumFilter as t } from "./ColumnHeaderEnumFilter.js";
|
|
|
3
3
|
import { useCallback as n } from "react";
|
|
4
4
|
import { Box as r, IconButton as i, Tooltip as a } from "@mui/material";
|
|
5
5
|
import { Fragment as o, jsx as s, jsxs as c } from "react/jsx-runtime";
|
|
6
|
-
import
|
|
6
|
+
import l from "@mui/icons-material/HelpTwoTone";
|
|
7
7
|
//#region src/components/TanStackTable/ColumnHeader.tsx
|
|
8
8
|
function u(u) {
|
|
9
9
|
let { column: d, title: f = u.column.id, wrap: p = !1, helpText: m, filterControl: h, additionalButtons: g, sortIconRenderer: _, iconPlacement: v = "right", iconColor: y, iconSize: b } = u, x = n(() => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ColumnHeader.js","names":[],"sources":["../../../src/components/TanStackTable/ColumnHeader.tsx"],"sourcesContent":["import { HeaderContext } from '@tanstack/react-table'\nimport { Box, IconButton, Tooltip } from '@mui/material'\nimport
|
|
1
|
+
{"version":3,"file":"ColumnHeader.js","names":[],"sources":["../../../src/components/TanStackTable/ColumnHeader.tsx"],"sourcesContent":["import { HeaderContext } from '@tanstack/react-table'\nimport { Box, IconButton, Tooltip } from '@mui/material'\nimport HelpTwoTone from '@mui/icons-material/HelpTwoTone'\nimport IconSvg from '../IconSvg'\nimport { ReactNode, useCallback } from 'react'\nimport { ColumnHeaderEnumFilter } from './ColumnHeaderEnumFilter'\n\ntype SortIconRendererParams = {\n isSorted: 'asc' | 'desc' | false\n}\n\ntype ColumnHeaderProps = {\n title?: string\n helpText?: ReactNode\n additionalButtons?: ReactNode\n wrap?: boolean\n sortIconRenderer?: (params: SortIconRendererParams) => ReactNode\n iconPlacement?: 'left' | 'right'\n iconColor?: string\n iconSize?: string | number\n\n // TODO: Replace with props that can be passed to a reusable filter control\n filterControl?: ReactNode\n}\n\n/**\n * Styled table column header component for use with @tanstack/react-table, with extra optional props for additional\n * UI features\n */\nexport default function ColumnHeader<TData = unknown, TValue = unknown>(\n props: ColumnHeaderProps & HeaderContext<TData, TValue>,\n) {\n const {\n column,\n title = props.column.id,\n wrap = false,\n helpText,\n filterControl: filterControlFromProps,\n additionalButtons,\n sortIconRenderer,\n iconPlacement = 'right',\n iconColor,\n iconSize,\n } = props\n\n const getFilterControl = useCallback(() => {\n if (filterControlFromProps) {\n return filterControlFromProps\n }\n if (column.getCanFilter()) {\n if (column.columnDef.meta?.filterVariant === 'enumeration') {\n return <ColumnHeaderEnumFilter column={column} title={title} />\n }\n // As needed, extend ColumnMeta.filterVariant to support other types of filters\n console.warn(\n `column.getCanFilter() was true for column ID: ${column.id} but no filterControlFromProps was passed and component for filterVariant: ${column.columnDef.meta?.filterVariant} is not implemented`,\n )\n }\n return <></>\n }, [column, filterControlFromProps, title])\n\n const filterControl = getFilterControl()\n const isSorted = column.getIsSorted()\n\n return (\n <Box\n sx={{\n display: 'flex',\n alignContent: 'center',\n alignItems: 'center',\n ...(iconPlacement === 'right' && {\n justifyContent: 'space-between',\n }),\n overflow: 'hidden',\n minWidth: 0,\n }}\n >\n <span\n style={{\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: wrap ? 'pre-wrap' : 'nowrap',\n minWidth: 0,\n }}\n title={title}\n >\n {title}\n </span>\n <Box\n role={'menubar'}\n sx={{\n display: 'flex',\n alignItems: 'center',\n height: '22px',\n ml: iconPlacement === 'left' ? 1 : 2,\n gap: 0.25,\n }}\n >\n {helpText && (\n <Tooltip title={helpText} placement={'top'}>\n <IconButton size={'small'}>\n <HelpTwoTone fontSize={'inherit'} />\n </IconButton>\n </Tooltip>\n )}\n {column.getCanFilter() && filterControl}\n {column.getCanSort() && (\n <Tooltip title={`Sort by ${title}`} placement={'top'}>\n <IconButton\n role=\"button\"\n size={'small'}\n aria-label={`Sort by ${title}`}\n tabIndex={0}\n onKeyPress={() => column.toggleSorting()}\n onClick={() => column.toggleSorting()}\n >\n {sortIconRenderer ? (\n sortIconRenderer({ isSorted })\n ) : (\n <IconSvg\n icon={isSorted === 'asc' ? 'sortUp' : 'sortDown'}\n wrap={false}\n sx={{\n color:\n iconColor ?? (isSorted ? 'primary.main' : 'grey.700'),\n backgroundColor: 'none',\n ...(iconSize && { fontSize: iconSize }),\n }}\n />\n )}\n </IconButton>\n </Tooltip>\n )}\n {additionalButtons}\n </Box>\n </Box>\n )\n}\n"],"mappings":";;;;;;;AA6BA,SAAwB,EACtB,GACA;CACA,IAAM,EACJ,WACA,WAAQ,EAAM,OAAO,IACrB,UAAO,IACP,aACA,eAAe,GACf,sBACA,qBACA,mBAAgB,SAChB,cACA,gBACE,GAkBE,IAhBmB,QAAkB;EACzC,IAAI,GACF,OAAO;EAET,IAAI,EAAO,aAAa,GAAG;GACzB,IAAI,EAAO,UAAU,MAAM,kBAAkB,eAC3C,OAAO,kBAAC,GAAD;IAAgC;IAAe;GAAQ,CAAA;GAGhE,QAAQ,KACN,iDAAiD,EAAO,GAAG,6EAA6E,EAAO,UAAU,MAAM,cAAc,oBAC/K;EACF;EACA,OAAO,kBAAA,GAAA,CAAI,CAAA;CACb,GAAG;EAAC;EAAQ;EAAwB;CAAK,CAEnB,EAAiB,GACjC,IAAW,EAAO,YAAY;CAEpC,OACE,kBAAC,GAAD;EACE,IAAI;GACF,SAAS;GACT,cAAc;GACd,YAAY;GACZ,GAAI,MAAkB,WAAW,EAC/B,gBAAgB,gBAClB;GACA,UAAU;GACV,UAAU;EACZ;YAVF,CAYE,kBAAC,QAAD;GACE,OAAO;IACL,UAAU;IACV,cAAc;IACd,YAAY,IAAO,aAAa;IAChC,UAAU;GACZ;GACO;aAEN;EACG,CAAA,GACN,kBAAC,GAAD;GACE,MAAM;GACN,IAAI;IACF,SAAS;IACT,YAAY;IACZ,QAAQ;IACR,IAAI,MAAkB,SAAS,IAAI;IACnC,KAAK;GACP;aARF;IAUG,KACC,kBAAC,GAAD;KAAS,OAAO;KAAU,WAAW;eACnC,kBAAC,GAAD;MAAY,MAAM;gBAChB,kBAAC,GAAD,EAAa,UAAU,UAAY,CAAA;KACzB,CAAA;IACL,CAAA;IAEV,EAAO,aAAa,KAAK;IACzB,EAAO,WAAW,KACjB,kBAAC,GAAD;KAAS,OAAO,WAAW;KAAS,WAAW;eAC7C,kBAAC,GAAD;MACE,MAAK;MACL,MAAM;MACN,cAAY,WAAW;MACvB,UAAU;MACV,kBAAkB,EAAO,cAAc;MACvC,eAAe,EAAO,cAAc;gBAEnC,IACC,EAAiB,EAAE,YAAS,CAAC,IAE7B,kBAAC,GAAD;OACE,MAAM,MAAa,QAAQ,WAAW;OACtC,MAAM;OACN,IAAI;QACF,OACE,MAAc,IAAW,iBAAiB;QAC5C,iBAAiB;QACjB,GAAI,KAAY,EAAE,UAAU,EAAS;OACvC;MACD,CAAA;KAEO,CAAA;IACL,CAAA;IAEV;GACE;IACF;;AAET"}
|
|
@@ -3,7 +3,7 @@ import "../../synapse-queries/index.js";
|
|
|
3
3
|
import t from "../TeamBadge.js";
|
|
4
4
|
import { Skeleton as n, Stack as r, Typography as i } from "@mui/material";
|
|
5
5
|
import { jsx as a, jsxs as o } from "react/jsx-runtime";
|
|
6
|
-
import
|
|
6
|
+
import s from "@mui/icons-material/ErrorTwoTone";
|
|
7
7
|
//#region src/components/TeamSubjectsSelector/TeamBadgeOrError.tsx
|
|
8
8
|
function c(c) {
|
|
9
9
|
let { teamId: l } = c, { data: u, isLoading: d, error: f } = e(l);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TeamBadgeOrError.js","names":[],"sources":["../../../src/components/TeamSubjectsSelector/TeamBadgeOrError.tsx"],"sourcesContent":["import { useGetTeam } from '@/synapse-queries'\nimport
|
|
1
|
+
{"version":3,"file":"TeamBadgeOrError.js","names":[],"sources":["../../../src/components/TeamSubjectsSelector/TeamBadgeOrError.tsx"],"sourcesContent":["import { useGetTeam } from '@/synapse-queries'\nimport ErrorTwoTone from '@mui/icons-material/ErrorTwoTone'\nimport { Skeleton, Stack, Typography } from '@mui/material'\nimport TeamBadge from '../TeamBadge'\n\nexport type TeamBadgeOrErrorProps = {\n teamId: string\n}\n\nexport function TeamBadgeOrError(props: TeamBadgeOrErrorProps) {\n const { teamId } = props\n\n const { data: team, isLoading, error } = useGetTeam(teamId)\n\n if (error) {\n return (\n <Stack\n direction=\"row\"\n role=\"alert\"\n sx={{\n gap: '5px',\n alignItems: 'center',\n }}\n >\n <ErrorTwoTone color=\"error\" />\n <Typography variant=\"smallText1\" color=\"error\">\n {error?.reason || `Error: ${teamId}`}\n </Typography>\n </Stack>\n )\n } else if (isLoading || !team) {\n return <Skeleton width={125} height={30} />\n }\n return <TeamBadge teamId={team.id} teamName={team.name} />\n}\n"],"mappings":";;;;;;;AASA,SAAgB,EAAiB,GAA8B;CAC7D,IAAM,EAAE,cAAW,GAEb,EAAE,MAAM,GAAM,cAAW,aAAU,EAAW,CAAM;CAqB1D,OAnBI,IAEA,kBAAC,GAAD;EACE,WAAU;EACV,MAAK;EACL,IAAI;GACF,KAAK;GACL,YAAY;EACd;YANF,CAQE,kBAAC,GAAD,EAAc,OAAM,QAAS,CAAA,GAC7B,kBAAC,GAAD;GAAY,SAAQ;GAAa,OAAM;aACpC,GAAO,UAAU,UAAU;EAClB,CAAA,CACP;MAEA,KAAa,CAAC,IAChB,kBAAC,GAAD;EAAU,OAAO;EAAK,QAAQ;CAAK,CAAA,IAErC,kBAAC,GAAD;EAAW,QAAQ,EAAK;EAAI,UAAU,EAAK;CAAO,CAAA;AAC3D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TeamSubjectsSelector.d.ts","sourceRoot":"","sources":["../../../src/components/TeamSubjectsSelector/TeamSubjectsSelector.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"TeamSubjectsSelector.d.ts","sourceRoot":"","sources":["../../../src/components/TeamSubjectsSelector/TeamSubjectsSelector.tsx"],"names":[],"mappings":"AAaA,OAAO,EACL,4BAA4B,EAE7B,MAAM,iCAAiC,CAAA;AAMxC,MAAM,MAAM,yBAAyB,GAAG;IAEtC,QAAQ,EAAE,4BAA4B,EAAE,CAAA;IACxC,QAAQ,EAAE,CAAC,QAAQ,EAAE,4BAA4B,EAAE,KAAK,IAAI,CAAA;IAC5D,sBAAsB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;CACjD,CAAA;AAED,eAAO,MAAM,qBAAqB,GAAI,QAAQ,MAAM,WACC,CAAA;AACrD,eAAO,MAAM,kBAAkB,GAAI,QAAQ,MAAM,WACS,CAAA;AAC1D,eAAO,MAAM,iBAAiB,uBAAuB,CAAA;AACrD,eAAO,MAAM,WAAW,mCAAmC,CAAA;AAC3D,eAAO,MAAM,SAAS,mCAAmC,CAAA;AAGzD,iBAAS,oBAAoB,CAAC,KAAK,EAAE,yBAAyB,2CAoI7D;AAED,eAAe,oBAAoB,CAAA"}
|
|
@@ -5,7 +5,8 @@ import { noop as i } from "lodash-es";
|
|
|
5
5
|
import { Alert as a, Box as o, Button as s, IconButton as c, InputLabel as l, Stack as u, TextField as d, Tooltip as f, Typography as p } from "@mui/material";
|
|
6
6
|
import { Fragment as m, jsx as h, jsxs as g } from "react/jsx-runtime";
|
|
7
7
|
import { RestrictableObjectType as _ } from "@sage-bionetworks/synapse-types";
|
|
8
|
-
import
|
|
8
|
+
import v from "@mui/icons-material/HelpOutlineTwoTone";
|
|
9
|
+
import y from "@mui/icons-material/AddCircleTwoTone";
|
|
9
10
|
//#region src/components/TeamSubjectsSelector/TeamSubjectsSelector.tsx
|
|
10
11
|
var b = (e) => `Team ${e} has already been added to this AR.`, x = (e) => `Parsing errors encountered. Invalid Team ID: ${e}`, S = "No teams selected.", C = "Remove from Access Requirement", w = "Enter Team IDs (i.e. 123, 456)", T = "";
|
|
11
12
|
function E(S) {
|
|
@@ -89,7 +90,7 @@ function E(S) {
|
|
|
89
90
|
fullWidth: !0
|
|
90
91
|
}),
|
|
91
92
|
/* @__PURE__ */ h(s, {
|
|
92
|
-
startIcon: /* @__PURE__ */ h(
|
|
93
|
+
startIcon: /* @__PURE__ */ h(y, {}),
|
|
93
94
|
variant: "outlined",
|
|
94
95
|
sx: {
|
|
95
96
|
flexShrink: 0,
|
|
@@ -102,7 +103,7 @@ function E(S) {
|
|
|
102
103
|
/* @__PURE__ */ h(f, {
|
|
103
104
|
title: w,
|
|
104
105
|
placement: "right",
|
|
105
|
-
children: /* @__PURE__ */ h(
|
|
106
|
+
children: /* @__PURE__ */ h(v, { sx: { color: "grey.600" } })
|
|
106
107
|
})
|
|
107
108
|
]
|
|
108
109
|
}),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TeamSubjectsSelector.js","names":[],"sources":["../../../src/components/TeamSubjectsSelector/TeamSubjectsSelector.tsx"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"file":"TeamSubjectsSelector.js","names":[],"sources":["../../../src/components/TeamSubjectsSelector/TeamSubjectsSelector.tsx"],"sourcesContent":["import AddCircleTwoTone from '@mui/icons-material/AddCircleTwoTone'\nimport HelpOutlineTwoTone from '@mui/icons-material/HelpOutlineTwoTone'\nimport {\n Alert,\n Box,\n Button,\n IconButton,\n InputLabel,\n Stack,\n TextField,\n Tooltip,\n Typography,\n} from '@mui/material'\nimport {\n RestrictableObjectDescriptor,\n RestrictableObjectType,\n} from '@sage-bionetworks/synapse-types'\nimport { noop } from 'lodash-es'\nimport { useMemo, useState } from 'react'\nimport IconSvg from '../IconSvg'\nimport { TeamBadgeOrError } from './TeamBadgeOrError'\n\nexport type TeamSubjectsSelectorProps = {\n // will be filtered to only team subjects\n subjects: RestrictableObjectDescriptor[]\n onUpdate: (subjects: RestrictableObjectDescriptor[]) => void\n onUpdateTeamIDsTextbox?: (value: string) => void // called when the team IDs text box is updated\n}\n\nexport const TEAM_ALREADY_SELECTED = (teamId: string) =>\n `Team ${teamId} has already been added to this AR.`\nexport const TEAM_PARSING_ERROR = (teamId: string) =>\n `Parsing errors encountered. Invalid Team ID: ${teamId}`\nexport const NO_TEAMS_SELECTED = 'No teams selected.'\nexport const REMOVE_TEXT = 'Remove from Access Requirement'\nexport const HELP_TEXT = 'Enter Team IDs (i.e. 123, 456)'\nconst teamIdsStringDefault = ''\n\nfunction TeamSubjectsSelector(props: TeamSubjectsSelectorProps) {\n const { subjects, onUpdate, onUpdateTeamIDsTextbox = noop } = props\n const [teamIdsString, setTeamIdsString] =\n useState<string>(teamIdsStringDefault)\n const [error, setError] = useState<string | null>(null)\n\n const teamSubjects = useMemo(() => {\n return subjects.filter(subject => {\n return subject.type === RestrictableObjectType.TEAM ? subject : null\n })\n }, [subjects])\n\n const onChangeTeamIdsTextbox = (value: string) => {\n setTeamIdsString(value)\n onUpdateTeamIDsTextbox(value)\n }\n\n const onRemove = (subjectId: string) => {\n const updatedSubjects = teamSubjects.filter(subject => {\n return subject.id !== subjectId\n })\n onUpdate(updatedSubjects)\n }\n\n const onAddTeams = (teamIdsString: string | null) => {\n const teamIds = teamIdsString?.split(',').map(item => item.trim())\n const dedupedTeamIds = [...new Set(teamIds)]\n if (dedupedTeamIds && dedupedTeamIds.length > 0) {\n const updatedTeamSubjects = [...teamSubjects]\n for (const teamId of dedupedTeamIds) {\n const validId = /^\\d+$/.test(teamId)\n const alreadyAdded = teamSubjects.some(subject => subject.id === teamId)\n if (!validId) {\n setError(TEAM_PARSING_ERROR(teamId))\n return\n } else if (alreadyAdded) {\n setError(TEAM_ALREADY_SELECTED(teamId))\n return\n } else {\n const newSubject: RestrictableObjectDescriptor = {\n id: teamId,\n type: RestrictableObjectType.TEAM,\n }\n updatedTeamSubjects.push(newSubject)\n }\n }\n onChangeTeamIdsTextbox(teamIdsStringDefault)\n onUpdate(updatedTeamSubjects)\n }\n setError(null)\n }\n\n return (\n <>\n <Box\n sx={{\n display: 'flex',\n flexWrap: 'wrap',\n gap: '0px 15px',\n pb: '10px',\n }}\n >\n {teamSubjects.length === 0 && (\n <Typography\n variant=\"body1Italic\"\n sx={{\n pb: 2,\n }}\n >\n {NO_TEAMS_SELECTED}\n </Typography>\n )}\n {teamSubjects.map(subject => {\n return (\n <Stack\n key={subject.id}\n direction=\"row\"\n data-testid=\"selected-team\"\n sx={{\n alignItems: 'center',\n pb: 1,\n }}\n >\n <TeamBadgeOrError teamId={subject.id} />\n <IconButton\n aria-label={REMOVE_TEXT}\n onClick={() => onRemove(subject.id)}\n sx={{\n '&:hover': {\n color: 'error.main',\n },\n }}\n >\n <IconSvg icon={'delete'} fontSize={'inherit'} wrap={false} />\n </IconButton>\n </Stack>\n )\n })}\n </Box>\n <InputLabel htmlFor=\"teamIDs\">Add Team IDs</InputLabel>\n <Stack\n direction=\"row\"\n sx={{\n gap: 1,\n alignItems: 'center',\n mb: 2,\n }}\n >\n <TextField\n id=\"teamIDs\"\n name=\"teamIDs\"\n placeholder={HELP_TEXT}\n value={teamIdsString}\n onChange={event => onChangeTeamIdsTextbox(event.target.value)}\n fullWidth\n />\n <Button\n startIcon={<AddCircleTwoTone />}\n variant=\"outlined\"\n sx={{ flexShrink: 0, height: '53px' }}\n onClick={() => onAddTeams(teamIdsString)}\n disabled={teamIdsString === ''}\n >\n Add Teams\n </Button>\n <Tooltip title={HELP_TEXT} placement=\"right\">\n <HelpOutlineTwoTone sx={{ color: 'grey.600' }} />\n </Tooltip>\n </Stack>\n {error && <Alert severity=\"warning\">{error}</Alert>}\n </>\n )\n}\n\nexport default TeamSubjectsSelector\n"],"mappings":"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"}
|
|
@@ -12,7 +12,7 @@ import { upperFirst as m } from "lodash-es";
|
|
|
12
12
|
import { Box as h, Button as g, Link as _, Stack as v, Typography as y, useMediaQuery as b, useTheme as x } from "@mui/material";
|
|
13
13
|
import { Fragment as S, jsx as C, jsxs as w } from "react/jsx-runtime";
|
|
14
14
|
import { SynapseObjectType as T, WebhookVerificationStatus as E } from "@sage-bionetworks/synapse-client";
|
|
15
|
-
import
|
|
15
|
+
import D from "@mui/icons-material/AddCircleTwoTone";
|
|
16
16
|
import O from "dayjs";
|
|
17
17
|
import { createColumnHelper as k, getCoreRowModel as A, useReactTable as j } from "@tanstack/react-table";
|
|
18
18
|
//#region src/components/Webhook/WebhookDashboard.tsx
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WebhookDashboard.js","names":[],"sources":["../../../src/components/Webhook/WebhookDashboard.tsx"],"sourcesContent":["import InfiniteTableLayout from '@/components/layout/InfiniteTableLayout'\nimport {\n useGetWebhooksInfinite,\n useResendVerificationCode,\n} from '@/synapse-queries/webhook/useWebhook'\nimport { formatDate } from '@/utils/functions/DateFormatter'\nimport { AddCircleTwoTone } from '@mui/icons-material'\nimport {\n Box,\n Button,\n Link,\n Stack,\n Typography,\n useMediaQuery,\n useTheme,\n} from '@mui/material'\nimport {\n SynapseObjectType,\n Webhook,\n WebhookVerificationStatus,\n} from '@sage-bionetworks/synapse-client'\nimport {\n createColumnHelper,\n getCoreRowModel,\n useReactTable,\n} from '@tanstack/react-table'\nimport dayjs from 'dayjs'\nimport { upperFirst } from 'lodash-es'\nimport { useCallback, useEffect, useMemo, useState } from 'react'\nimport { EntityLink } from '../EntityLink'\nimport { HelpPopover } from '../HelpPopover/HelpPopover'\nimport { SynapseSpinner } from '../LoadingScreen/LoadingScreen'\nimport StyledTanStackTable from '../TanStackTable/StyledTanStackTable'\nimport CreateWebhookModal from './CreateWebhookModal'\nimport { WebhookVerificationDialog } from './WebhookVerificationDialog'\n\nconst WEBHOOK_CAN_RESEND_CODE_STATES: WebhookVerificationStatus[] = [\n WebhookVerificationStatus.FAILED,\n WebhookVerificationStatus.REVOKED,\n]\n\nconst columnHelper = createColumnHelper<Webhook>()\n\nfunction getWebhookTableColumns(\n onClickVerifyWebhook: (webhook: Webhook) => void,\n onClickResendVerificationCode: (webhook: Webhook) => void,\n onClickEditWebhook: (webhook: Webhook) => void,\n) {\n return [\n columnHelper.accessor('id', {\n header: 'ID',\n size: 75,\n cell: ctx => ctx.cell.getValue(),\n }),\n columnHelper.display({\n header: 'Object',\n cell: ctx => {\n if (ctx.row.original.objectType === SynapseObjectType.ENTITY) {\n return (\n <>\n <EntityLink entity={ctx.row.original.objectId!} /> (syn\n {ctx.row.original.objectId})\n </>\n )\n }\n return `${ctx.row.original.objectType}: ${ctx.row.original.objectId}`\n },\n }),\n columnHelper.accessor('eventTypes', {\n header: 'Event Type(s)',\n cell: ctx => (\n <Stack>\n {Array.from<string>(ctx.cell.getValue()!)\n .map(s => s.toLowerCase())\n .map(upperFirst)\n .map(val => (\n <span key={val}>{val}</span>\n ))}\n </Stack>\n ),\n }),\n columnHelper.accessor('isEnabled', {\n header: 'Enabled',\n size: 10,\n cell: ctx => (ctx.cell.getValue() ? 'Yes' : 'No'),\n }),\n columnHelper.accessor('createdOn', {\n header: 'Created On',\n cell: ({ getValue }) => formatDate(dayjs(getValue())),\n }),\n columnHelper.accessor('modifiedOn', {\n header: 'Modified On',\n cell: ({ getValue }) => formatDate(dayjs(getValue())),\n }),\n columnHelper.accessor('verificationStatus', {\n header: 'Verification Status',\n cell: ctx => (\n <Stack\n sx={{\n flexDirection: 'row',\n alignItems: 'center',\n gap: 1,\n }}\n >\n {ctx.row.original.verificationStatus === 'PENDING' && (\n // useEffect above will trigger a refetch until this resolves\n <SynapseSpinner size={20} />\n )}\n {ctx.row.original.verificationStatus !==\n WebhookVerificationStatus.PENDING &&\n upperFirst(\n (ctx.row.original.verificationStatus || '')\n .toLowerCase()\n .replaceAll('_', ' '),\n )}\n {ctx.row.original.verificationMsg && (\n <HelpPopover markdownText={ctx.row.original.verificationMsg} />\n )}\n </Stack>\n ),\n }),\n columnHelper.display({\n id: 'actions',\n header: 'Actions',\n size: 10,\n meta: {\n textAlign: 'right',\n },\n cell: ctx => (\n <Stack\n sx={{\n flexDirection: 'row',\n justifyContent: 'flex-end',\n alignItems: 'center',\n gap: 2,\n }}\n >\n {ctx.row.original.verificationStatus ===\n WebhookVerificationStatus.CODE_SENT && (\n <Button\n variant={'outlined'}\n onClick={() => {\n onClickVerifyWebhook(ctx.row.original)\n }}\n >\n Verify code\n </Button>\n )}\n\n {WEBHOOK_CAN_RESEND_CODE_STATES.includes(\n ctx.row.original.verificationStatus as WebhookVerificationStatus,\n ) && (\n <Button\n variant={'outlined'}\n onClick={() => {\n onClickResendVerificationCode(ctx.row.original)\n }}\n >\n Resend code\n </Button>\n )}\n <Button\n size=\"small\"\n variant=\"contained\"\n onClick={() => {\n onClickEditWebhook(ctx.row.original)\n }}\n >\n Edit\n </Button>\n </Stack>\n ),\n }),\n ]\n}\n\nexport default function WebhookDashboard() {\n const [showCreateModal, setShowCreateModal] = useState(false)\n const [showVerificationDialog, setShowVerificationDialog] = useState(false)\n const [webhookToUpdate, setWebhookToUpdate] = useState<Webhook | undefined>(\n undefined,\n )\n\n const theme = useTheme()\n const hideOptionalColumns = useMediaQuery(theme.breakpoints.down('md'))\n\n const {\n data: infiniteData,\n refetch,\n hasNextPage,\n fetchNextPage,\n isFetchingNextPage,\n isLoading,\n } = useGetWebhooksInfinite()\n const webhooks = useMemo(\n () => infiniteData?.pages.flatMap(page => page.page!) ?? [],\n [infiniteData],\n )\n\n // If the Webhook verification status is PENDING, Synapse may not have sent the verification code, or may have not reported a response.\n // Refetch on an interval to check if the verification status has changed.\n useEffect(() => {\n let intervalId: NodeJS.Timeout\n if (webhooks.some(webhook => webhook.verificationStatus === 'PENDING')) {\n intervalId = setInterval(() => {\n void refetch()\n }, 2500)\n }\n return () => clearInterval(intervalId)\n }, [refetch, webhooks])\n\n const { mutate: resendVerificationCode } = useResendVerificationCode()\n\n const onClickVerifyWebhook = useCallback((webhook: Webhook) => {\n setWebhookToUpdate(webhook)\n setShowVerificationDialog(true)\n }, [])\n const onClickEditWebhook = useCallback((webhook: Webhook) => {\n setWebhookToUpdate(webhook)\n setShowCreateModal(true)\n }, [])\n const onClickResendVerificationCode = useCallback(\n (webhook: Webhook) => {\n resendVerificationCode(webhook.id!)\n },\n [resendVerificationCode],\n )\n\n const columns = useMemo(\n () =>\n getWebhookTableColumns(\n onClickVerifyWebhook,\n onClickResendVerificationCode,\n onClickEditWebhook,\n ),\n [onClickEditWebhook, onClickResendVerificationCode, onClickVerifyWebhook],\n )\n\n const webhookTable = useReactTable<Webhook>({\n data: webhooks,\n columns: columns,\n state: {\n columnVisibility: {\n createdOn: !hideOptionalColumns,\n modifiedOn: !hideOptionalColumns,\n },\n },\n getCoreRowModel: getCoreRowModel(),\n })\n\n const isEmpty = !isLoading && webhookTable.getRowModel().rows.length === 0\n\n return (\n <div>\n <WebhookVerificationDialog\n key={webhookToUpdate?.id}\n open={showVerificationDialog}\n onClose={() => setShowVerificationDialog(false)}\n webhookId={webhookToUpdate?.id!}\n />\n <Typography variant={'headline3'}>Webhook Dashboard</Typography>\n <Box\n sx={{\n display: 'flex',\n flexDirection: 'row',\n my: 2,\n gap: 3,\n justifyContent: 'space-between',\n alignItems: 'flex-start',\n }}\n >\n <div>\n <Typography variant={'body1'} gutterBottom>\n Webhooks can be used to programmatically receive alerts that are\n triggered by events in Synapse. A webhook can specify a Synapse\n entity to receive events related to that entity. For entities that\n represent a container (folder and project), matching events are\n published to the webhook endpoint for any entity in its hierarchy.\n </Typography>\n <Typography variant={'body1'} gutterBottom>\n For more information, see the{' '}\n <Link\n href={\n 'http://dev.release.rest.doc.sagebase.org.s3-website-us-east-1.amazonaws.com/index.html#org.sagebionetworks.repo.web.controller.WebhookController'\n }\n target={'blank'}\n >\n Synapse API REST Docs section on Webhooks\n </Link>\n .\n </Typography>\n </div>\n <Button\n size=\"large\"\n variant=\"contained\"\n startIcon={<AddCircleTwoTone />}\n onClick={() => {\n setWebhookToUpdate(undefined)\n setShowCreateModal(true)\n }}\n sx={{ flexShrink: 0 }}\n >\n Create Webhook\n </Button>\n <CreateWebhookModal\n initialData={webhookToUpdate}\n open={showCreateModal}\n onClose={() => setShowCreateModal(false)}\n />\n </Box>\n <InfiniteTableLayout\n table={<StyledTanStackTable table={webhookTable} />}\n isLoading={isLoading}\n noResults={\n <Typography variant=\"body1\">\n You have not created any webhooks. Click "Create Webhook"\n above to begin.\n </Typography>\n }\n isEmpty={isEmpty}\n hasNextPage={hasNextPage}\n onFetchNextPageClicked={() => {\n void fetchNextPage()\n }}\n isFetchingNextPage={isFetchingNextPage}\n />\n </div>\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"WebhookDashboard.js","names":[],"sources":["../../../src/components/Webhook/WebhookDashboard.tsx"],"sourcesContent":["import InfiniteTableLayout from '@/components/layout/InfiniteTableLayout'\nimport {\n useGetWebhooksInfinite,\n useResendVerificationCode,\n} from '@/synapse-queries/webhook/useWebhook'\nimport { formatDate } from '@/utils/functions/DateFormatter'\nimport AddCircleTwoTone from '@mui/icons-material/AddCircleTwoTone'\nimport {\n Box,\n Button,\n Link,\n Stack,\n Typography,\n useMediaQuery,\n useTheme,\n} from '@mui/material'\nimport {\n SynapseObjectType,\n Webhook,\n WebhookVerificationStatus,\n} from '@sage-bionetworks/synapse-client'\nimport {\n createColumnHelper,\n getCoreRowModel,\n useReactTable,\n} from '@tanstack/react-table'\nimport dayjs from 'dayjs'\nimport { upperFirst } from 'lodash-es'\nimport { useCallback, useEffect, useMemo, useState } from 'react'\nimport { EntityLink } from '../EntityLink'\nimport { HelpPopover } from '../HelpPopover/HelpPopover'\nimport { SynapseSpinner } from '../LoadingScreen/LoadingScreen'\nimport StyledTanStackTable from '../TanStackTable/StyledTanStackTable'\nimport CreateWebhookModal from './CreateWebhookModal'\nimport { WebhookVerificationDialog } from './WebhookVerificationDialog'\n\nconst WEBHOOK_CAN_RESEND_CODE_STATES: WebhookVerificationStatus[] = [\n WebhookVerificationStatus.FAILED,\n WebhookVerificationStatus.REVOKED,\n]\n\nconst columnHelper = createColumnHelper<Webhook>()\n\nfunction getWebhookTableColumns(\n onClickVerifyWebhook: (webhook: Webhook) => void,\n onClickResendVerificationCode: (webhook: Webhook) => void,\n onClickEditWebhook: (webhook: Webhook) => void,\n) {\n return [\n columnHelper.accessor('id', {\n header: 'ID',\n size: 75,\n cell: ctx => ctx.cell.getValue(),\n }),\n columnHelper.display({\n header: 'Object',\n cell: ctx => {\n if (ctx.row.original.objectType === SynapseObjectType.ENTITY) {\n return (\n <>\n <EntityLink entity={ctx.row.original.objectId!} /> (syn\n {ctx.row.original.objectId})\n </>\n )\n }\n return `${ctx.row.original.objectType}: ${ctx.row.original.objectId}`\n },\n }),\n columnHelper.accessor('eventTypes', {\n header: 'Event Type(s)',\n cell: ctx => (\n <Stack>\n {Array.from<string>(ctx.cell.getValue()!)\n .map(s => s.toLowerCase())\n .map(upperFirst)\n .map(val => (\n <span key={val}>{val}</span>\n ))}\n </Stack>\n ),\n }),\n columnHelper.accessor('isEnabled', {\n header: 'Enabled',\n size: 10,\n cell: ctx => (ctx.cell.getValue() ? 'Yes' : 'No'),\n }),\n columnHelper.accessor('createdOn', {\n header: 'Created On',\n cell: ({ getValue }) => formatDate(dayjs(getValue())),\n }),\n columnHelper.accessor('modifiedOn', {\n header: 'Modified On',\n cell: ({ getValue }) => formatDate(dayjs(getValue())),\n }),\n columnHelper.accessor('verificationStatus', {\n header: 'Verification Status',\n cell: ctx => (\n <Stack\n sx={{\n flexDirection: 'row',\n alignItems: 'center',\n gap: 1,\n }}\n >\n {ctx.row.original.verificationStatus === 'PENDING' && (\n // useEffect above will trigger a refetch until this resolves\n <SynapseSpinner size={20} />\n )}\n {ctx.row.original.verificationStatus !==\n WebhookVerificationStatus.PENDING &&\n upperFirst(\n (ctx.row.original.verificationStatus || '')\n .toLowerCase()\n .replaceAll('_', ' '),\n )}\n {ctx.row.original.verificationMsg && (\n <HelpPopover markdownText={ctx.row.original.verificationMsg} />\n )}\n </Stack>\n ),\n }),\n columnHelper.display({\n id: 'actions',\n header: 'Actions',\n size: 10,\n meta: {\n textAlign: 'right',\n },\n cell: ctx => (\n <Stack\n sx={{\n flexDirection: 'row',\n justifyContent: 'flex-end',\n alignItems: 'center',\n gap: 2,\n }}\n >\n {ctx.row.original.verificationStatus ===\n WebhookVerificationStatus.CODE_SENT && (\n <Button\n variant={'outlined'}\n onClick={() => {\n onClickVerifyWebhook(ctx.row.original)\n }}\n >\n Verify code\n </Button>\n )}\n\n {WEBHOOK_CAN_RESEND_CODE_STATES.includes(\n ctx.row.original.verificationStatus as WebhookVerificationStatus,\n ) && (\n <Button\n variant={'outlined'}\n onClick={() => {\n onClickResendVerificationCode(ctx.row.original)\n }}\n >\n Resend code\n </Button>\n )}\n <Button\n size=\"small\"\n variant=\"contained\"\n onClick={() => {\n onClickEditWebhook(ctx.row.original)\n }}\n >\n Edit\n </Button>\n </Stack>\n ),\n }),\n ]\n}\n\nexport default function WebhookDashboard() {\n const [showCreateModal, setShowCreateModal] = useState(false)\n const [showVerificationDialog, setShowVerificationDialog] = useState(false)\n const [webhookToUpdate, setWebhookToUpdate] = useState<Webhook | undefined>(\n undefined,\n )\n\n const theme = useTheme()\n const hideOptionalColumns = useMediaQuery(theme.breakpoints.down('md'))\n\n const {\n data: infiniteData,\n refetch,\n hasNextPage,\n fetchNextPage,\n isFetchingNextPage,\n isLoading,\n } = useGetWebhooksInfinite()\n const webhooks = useMemo(\n () => infiniteData?.pages.flatMap(page => page.page!) ?? [],\n [infiniteData],\n )\n\n // If the Webhook verification status is PENDING, Synapse may not have sent the verification code, or may have not reported a response.\n // Refetch on an interval to check if the verification status has changed.\n useEffect(() => {\n let intervalId: NodeJS.Timeout\n if (webhooks.some(webhook => webhook.verificationStatus === 'PENDING')) {\n intervalId = setInterval(() => {\n void refetch()\n }, 2500)\n }\n return () => clearInterval(intervalId)\n }, [refetch, webhooks])\n\n const { mutate: resendVerificationCode } = useResendVerificationCode()\n\n const onClickVerifyWebhook = useCallback((webhook: Webhook) => {\n setWebhookToUpdate(webhook)\n setShowVerificationDialog(true)\n }, [])\n const onClickEditWebhook = useCallback((webhook: Webhook) => {\n setWebhookToUpdate(webhook)\n setShowCreateModal(true)\n }, [])\n const onClickResendVerificationCode = useCallback(\n (webhook: Webhook) => {\n resendVerificationCode(webhook.id!)\n },\n [resendVerificationCode],\n )\n\n const columns = useMemo(\n () =>\n getWebhookTableColumns(\n onClickVerifyWebhook,\n onClickResendVerificationCode,\n onClickEditWebhook,\n ),\n [onClickEditWebhook, onClickResendVerificationCode, onClickVerifyWebhook],\n )\n\n const webhookTable = useReactTable<Webhook>({\n data: webhooks,\n columns: columns,\n state: {\n columnVisibility: {\n createdOn: !hideOptionalColumns,\n modifiedOn: !hideOptionalColumns,\n },\n },\n getCoreRowModel: getCoreRowModel(),\n })\n\n const isEmpty = !isLoading && webhookTable.getRowModel().rows.length === 0\n\n return (\n <div>\n <WebhookVerificationDialog\n key={webhookToUpdate?.id}\n open={showVerificationDialog}\n onClose={() => setShowVerificationDialog(false)}\n webhookId={webhookToUpdate?.id!}\n />\n <Typography variant={'headline3'}>Webhook Dashboard</Typography>\n <Box\n sx={{\n display: 'flex',\n flexDirection: 'row',\n my: 2,\n gap: 3,\n justifyContent: 'space-between',\n alignItems: 'flex-start',\n }}\n >\n <div>\n <Typography variant={'body1'} gutterBottom>\n Webhooks can be used to programmatically receive alerts that are\n triggered by events in Synapse. A webhook can specify a Synapse\n entity to receive events related to that entity. For entities that\n represent a container (folder and project), matching events are\n published to the webhook endpoint for any entity in its hierarchy.\n </Typography>\n <Typography variant={'body1'} gutterBottom>\n For more information, see the{' '}\n <Link\n href={\n 'http://dev.release.rest.doc.sagebase.org.s3-website-us-east-1.amazonaws.com/index.html#org.sagebionetworks.repo.web.controller.WebhookController'\n }\n target={'blank'}\n >\n Synapse API REST Docs section on Webhooks\n </Link>\n .\n </Typography>\n </div>\n <Button\n size=\"large\"\n variant=\"contained\"\n startIcon={<AddCircleTwoTone />}\n onClick={() => {\n setWebhookToUpdate(undefined)\n setShowCreateModal(true)\n }}\n sx={{ flexShrink: 0 }}\n >\n Create Webhook\n </Button>\n <CreateWebhookModal\n initialData={webhookToUpdate}\n open={showCreateModal}\n onClose={() => setShowCreateModal(false)}\n />\n </Box>\n <InfiniteTableLayout\n table={<StyledTanStackTable table={webhookTable} />}\n isLoading={isLoading}\n noResults={\n <Typography variant=\"body1\">\n You have not created any webhooks. Click "Create Webhook"\n above to begin.\n </Typography>\n }\n isEmpty={isEmpty}\n hasNextPage={hasNextPage}\n onFetchNextPageClicked={() => {\n void fetchNextPage()\n }}\n isFetchingNextPage={isFetchingNextPage}\n />\n </div>\n )\n}\n"],"mappings":"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"}
|
|
@@ -9,13 +9,13 @@ import { omitBy as u } from "lodash-es";
|
|
|
9
9
|
import { Grid as d, InputAdornment as f, TextField as p, Typography as m } from "@mui/material";
|
|
10
10
|
import { Fragment as h, jsx as g, jsxs as _ } from "react/jsx-runtime";
|
|
11
11
|
import { EntityType as v } from "@sage-bionetworks/synapse-client";
|
|
12
|
-
import {
|
|
13
|
-
import
|
|
12
|
+
import { useLocation as y, useNavigate as b } from "react-router";
|
|
13
|
+
import x from "@mui/icons-material/SearchOutlined";
|
|
14
14
|
import { useDebouncedState as S } from "@react-hookz/web";
|
|
15
15
|
//#region src/components/dataaccess/AccessRequirementDashboard.tsx
|
|
16
16
|
var C = "nameOrID", w = "relatedProjectId", T = "reviewerId", E = "type";
|
|
17
17
|
function D(D) {
|
|
18
|
-
let { onCreateNewAccessRequirementClicked: O } = D, k =
|
|
18
|
+
let { onCreateNewAccessRequirementClicked: O } = D, k = y(), A = c(() => new URLSearchParams(k.search), [k.search]), j = b(), [M, N] = S(A.get("nameOrID") ?? "", 500), [P, F] = S(A.get("relatedProjectId") ?? void 0, 500), [I, L] = S(A.get("reviewerId") ?? void 0, 500), [R, z] = l(A.get("type") ?? void 0), B = c(() => !!(P && !e.exec(P)), [P]), [V, H] = l(!1);
|
|
19
19
|
s(() => {
|
|
20
20
|
let e = u({
|
|
21
21
|
[C]: M,
|
|
@@ -82,7 +82,7 @@ function D(D) {
|
|
|
82
82
|
},
|
|
83
83
|
slotProps: { input: { endAdornment: /* @__PURE__ */ g(f, {
|
|
84
84
|
position: "end",
|
|
85
|
-
children: /* @__PURE__ */ g(
|
|
85
|
+
children: /* @__PURE__ */ g(x, {})
|
|
86
86
|
}) } }
|
|
87
87
|
})
|
|
88
88
|
}),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AccessRequirementDashboard.js","names":[],"sources":["../../../src/components/dataaccess/AccessRequirementDashboard.tsx"],"sourcesContent":["import { InputSizedButton } from '@/components/styled/InputSizedButton'\nimport { SYNAPSE_ENTITY_ID_REGEX } from '@/utils/functions/RegularExpressions'\nimport { SearchOutlined } from '@mui/icons-material'\nimport { Grid, InputAdornment, TextField, Typography } from '@mui/material'\nimport { useDebouncedState } from '@react-hookz/web'\nimport { EntityType } from '@sage-bionetworks/synapse-client'\nimport { omitBy } from 'lodash-es'\nimport { useCallback, useEffect, useMemo, useState } from 'react'\nimport { useLocation, useNavigate } from 'react-router'\nimport { EntityFinderModal } from '../EntityFinder/EntityFinderModal'\nimport { FinderScope } from '../EntityFinder/tree/EntityTree'\nimport UserSearchBox from '../UserSearchBox/UserSearchBox'\nimport { AccessRequirementTable } from './AccessRequirementTable'\n\nexport const AR_NAME_OR_ID_SEARCH_PARAM_KEY = 'nameOrID'\nexport const RELATED_PROJECT_ID_SEARCH_PARAM_KEY = 'relatedProjectId'\nexport const REVIEWER_ID_SEARCH_PARAM_KEY = 'reviewerId'\nexport const AR_TYPE_SEARCH_PARAM_KEY = 'type'\n\nexport type AccessRequirementDashboardProps = {\n onCreateNewAccessRequirementClicked?: () => void\n}\n\nexport function AccessRequirementDashboard(\n props: AccessRequirementDashboardProps,\n) {\n // Amount of time to wait after an input value changes before sending a new request\n const INPUT_CHANGE_DEBOUNCE_DELAY_MS = 500\n\n const { onCreateNewAccessRequirementClicked } = props\n\n const location = useLocation()\n const urlSearchParams = useMemo(\n () => new URLSearchParams(location.search),\n [location.search],\n )\n const navigate = useNavigate()\n\n /**\n * When an input changes, update the props passed to the table and update the search params.\n *\n * Debounced to prevent firing many queries while the user is entering text.\n */\n const [nameOrID, setNameOrID] = useDebouncedState<string>(\n urlSearchParams.get(AR_NAME_OR_ID_SEARCH_PARAM_KEY) ?? '',\n INPUT_CHANGE_DEBOUNCE_DELAY_MS,\n )\n const [relatedProjectId, setRelatedProjectId] = useDebouncedState<\n string | undefined\n >(\n urlSearchParams.get(RELATED_PROJECT_ID_SEARCH_PARAM_KEY) ?? undefined,\n INPUT_CHANGE_DEBOUNCE_DELAY_MS,\n )\n const [reviewerId, setReviewerId] = useDebouncedState<string | undefined>(\n urlSearchParams.get(REVIEWER_ID_SEARCH_PARAM_KEY) ?? undefined,\n INPUT_CHANGE_DEBOUNCE_DELAY_MS,\n )\n const [typeFilter, setTypeFilter] = useState<string | undefined>(\n urlSearchParams.get(AR_TYPE_SEARCH_PARAM_KEY) ?? undefined,\n )\n\n const projectFilterFieldIsError: boolean = useMemo(\n () =>\n !!(relatedProjectId && !SYNAPSE_ENTITY_ID_REGEX.exec(relatedProjectId)),\n [relatedProjectId],\n )\n\n const [showEntityFinder, setShowEntityFinder] = useState(false)\n\n // Update the QueryParams when the filter state changes\n useEffect(() => {\n // Don't include undefined/empty parameters\n const params = omitBy(\n {\n // Sync the search params state with the debounced props\n [AR_NAME_OR_ID_SEARCH_PARAM_KEY]: nameOrID,\n [RELATED_PROJECT_ID_SEARCH_PARAM_KEY]: relatedProjectId,\n [REVIEWER_ID_SEARCH_PARAM_KEY]: reviewerId,\n [AR_TYPE_SEARCH_PARAM_KEY]: typeFilter, // typeFilter state is not debounced\n },\n item => item === undefined || item === '',\n ) as Record<string, string>\n\n // Add the new params to the URL\n // Replace history because intuitively, the user has not navigated to a new page\n const paramsObject = new URLSearchParams(params)\n navigate(\n {\n pathname: location.pathname,\n search: paramsObject.toString(),\n },\n { replace: true },\n )\n }, [\n nameOrID,\n relatedProjectId,\n reviewerId,\n typeFilter,\n navigate,\n location.pathname,\n ])\n\n const onReviewerChange = useCallback(\n (selected: string | null) => {\n if (selected) {\n setReviewerId(selected)\n } else {\n setReviewerId(undefined)\n }\n },\n [setReviewerId],\n )\n\n const accessRequirementsPanel = (\n <>\n <EntityFinderModal\n configuration={{\n initialScope: FinderScope.ALL_PROJECTS,\n initialContainer: null,\n selectMultiple: false,\n selectableTypes: [EntityType.project],\n treeOnly: true,\n }}\n show={showEntityFinder}\n onCancel={() => {\n setShowEntityFinder(false)\n }}\n title={'Select Project to Filter Access Requirements'}\n promptCopy={\n 'Select a project to find Access Requirements that are associated with that project. Access Requirements will be found if the Access Requirement is applied to the project, or if it is applied to any item inside the project.'\n }\n onConfirm={selected => {\n setRelatedProjectId(selected[0].targetId)\n setShowEntityFinder(false)\n }}\n confirmButtonCopy={'Select'}\n />\n <Grid component={'form'} container spacing={2} className=\"InputPanel\">\n <Grid size={{ xs: 12, md: 4 }}>\n <TextField\n label=\"Filter by Access Requirement Name or ID\"\n id=\"ar-name-filter\"\n type=\"text\"\n fullWidth\n placeholder=\"Search for an Access Requirement Name or ID\"\n onChange={e => {\n setNameOrID(e.target.value)\n }}\n slotProps={{\n input: {\n endAdornment: (\n <InputAdornment position=\"end\">\n <SearchOutlined />\n </InputAdornment>\n ),\n },\n }}\n />\n </Grid>\n <Grid\n size={{ xs: 12, md: 4 }}\n sx={{\n display: 'flex',\n gap: '5px',\n alignItems: 'stretch',\n }}\n >\n <TextField\n label=\"Filter by Project\"\n id=\"project-id-filter\"\n type=\"text\"\n fullWidth\n placeholder=\"Enter a project SynID\"\n error={projectFilterFieldIsError}\n helperText={\n projectFilterFieldIsError\n ? 'Value must be a Synapse ID, e.g. \"syn1234\"'\n : undefined\n }\n onChange={e => {\n const newValue = e.target.value\n if (newValue === '') {\n setRelatedProjectId(undefined)\n } else {\n setRelatedProjectId(newValue)\n }\n }}\n />\n <InputSizedButton\n variant=\"outlined\"\n color=\"primary\"\n onClick={() => {\n setShowEntityFinder(true)\n }}\n >\n Browse\n </InputSizedButton>\n </Grid>\n <Grid size={{ xs: 12, md: 4 }}>\n <Typography\n component=\"label\"\n variant=\"smallText2\"\n htmlFor=\"reviewer-filter\"\n >\n Filter by Reviewer\n </Typography>\n <UserSearchBox\n inputId=\"reviewer-filter\"\n placeholder=\"Search for a username or team name\"\n defaultValue={reviewerId}\n onChange={onReviewerChange}\n />\n </Grid>\n </Grid>\n <AccessRequirementTable\n nameOrID={nameOrID}\n relatedProjectId={relatedProjectId}\n reviewerId={reviewerId}\n onCreateNewAccessRequirementClicked={\n onCreateNewAccessRequirementClicked\n }\n typeFilter={typeFilter}\n onTypeFilterChange={setTypeFilter}\n />\n </>\n )\n\n return (\n <div className=\"AccessRequirementDashboard\">{accessRequirementsPanel}</div>\n )\n}\n\nexport default AccessRequirementDashboard\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AccessRequirementDashboard.js","names":[],"sources":["../../../src/components/dataaccess/AccessRequirementDashboard.tsx"],"sourcesContent":["import { InputSizedButton } from '@/components/styled/InputSizedButton'\nimport { SYNAPSE_ENTITY_ID_REGEX } from '@/utils/functions/RegularExpressions'\nimport SearchOutlined from '@mui/icons-material/SearchOutlined'\nimport { Grid, InputAdornment, TextField, Typography } from '@mui/material'\nimport { useDebouncedState } from '@react-hookz/web'\nimport { EntityType } from '@sage-bionetworks/synapse-client'\nimport { omitBy } from 'lodash-es'\nimport { useCallback, useEffect, useMemo, useState } from 'react'\nimport { useLocation, useNavigate } from 'react-router'\nimport { EntityFinderModal } from '../EntityFinder/EntityFinderModal'\nimport { FinderScope } from '../EntityFinder/tree/EntityTree'\nimport UserSearchBox from '../UserSearchBox/UserSearchBox'\nimport { AccessRequirementTable } from './AccessRequirementTable'\n\nexport const AR_NAME_OR_ID_SEARCH_PARAM_KEY = 'nameOrID'\nexport const RELATED_PROJECT_ID_SEARCH_PARAM_KEY = 'relatedProjectId'\nexport const REVIEWER_ID_SEARCH_PARAM_KEY = 'reviewerId'\nexport const AR_TYPE_SEARCH_PARAM_KEY = 'type'\n\nexport type AccessRequirementDashboardProps = {\n onCreateNewAccessRequirementClicked?: () => void\n}\n\nexport function AccessRequirementDashboard(\n props: AccessRequirementDashboardProps,\n) {\n // Amount of time to wait after an input value changes before sending a new request\n const INPUT_CHANGE_DEBOUNCE_DELAY_MS = 500\n\n const { onCreateNewAccessRequirementClicked } = props\n\n const location = useLocation()\n const urlSearchParams = useMemo(\n () => new URLSearchParams(location.search),\n [location.search],\n )\n const navigate = useNavigate()\n\n /**\n * When an input changes, update the props passed to the table and update the search params.\n *\n * Debounced to prevent firing many queries while the user is entering text.\n */\n const [nameOrID, setNameOrID] = useDebouncedState<string>(\n urlSearchParams.get(AR_NAME_OR_ID_SEARCH_PARAM_KEY) ?? '',\n INPUT_CHANGE_DEBOUNCE_DELAY_MS,\n )\n const [relatedProjectId, setRelatedProjectId] = useDebouncedState<\n string | undefined\n >(\n urlSearchParams.get(RELATED_PROJECT_ID_SEARCH_PARAM_KEY) ?? undefined,\n INPUT_CHANGE_DEBOUNCE_DELAY_MS,\n )\n const [reviewerId, setReviewerId] = useDebouncedState<string | undefined>(\n urlSearchParams.get(REVIEWER_ID_SEARCH_PARAM_KEY) ?? undefined,\n INPUT_CHANGE_DEBOUNCE_DELAY_MS,\n )\n const [typeFilter, setTypeFilter] = useState<string | undefined>(\n urlSearchParams.get(AR_TYPE_SEARCH_PARAM_KEY) ?? undefined,\n )\n\n const projectFilterFieldIsError: boolean = useMemo(\n () =>\n !!(relatedProjectId && !SYNAPSE_ENTITY_ID_REGEX.exec(relatedProjectId)),\n [relatedProjectId],\n )\n\n const [showEntityFinder, setShowEntityFinder] = useState(false)\n\n // Update the QueryParams when the filter state changes\n useEffect(() => {\n // Don't include undefined/empty parameters\n const params = omitBy(\n {\n // Sync the search params state with the debounced props\n [AR_NAME_OR_ID_SEARCH_PARAM_KEY]: nameOrID,\n [RELATED_PROJECT_ID_SEARCH_PARAM_KEY]: relatedProjectId,\n [REVIEWER_ID_SEARCH_PARAM_KEY]: reviewerId,\n [AR_TYPE_SEARCH_PARAM_KEY]: typeFilter, // typeFilter state is not debounced\n },\n item => item === undefined || item === '',\n ) as Record<string, string>\n\n // Add the new params to the URL\n // Replace history because intuitively, the user has not navigated to a new page\n const paramsObject = new URLSearchParams(params)\n navigate(\n {\n pathname: location.pathname,\n search: paramsObject.toString(),\n },\n { replace: true },\n )\n }, [\n nameOrID,\n relatedProjectId,\n reviewerId,\n typeFilter,\n navigate,\n location.pathname,\n ])\n\n const onReviewerChange = useCallback(\n (selected: string | null) => {\n if (selected) {\n setReviewerId(selected)\n } else {\n setReviewerId(undefined)\n }\n },\n [setReviewerId],\n )\n\n const accessRequirementsPanel = (\n <>\n <EntityFinderModal\n configuration={{\n initialScope: FinderScope.ALL_PROJECTS,\n initialContainer: null,\n selectMultiple: false,\n selectableTypes: [EntityType.project],\n treeOnly: true,\n }}\n show={showEntityFinder}\n onCancel={() => {\n setShowEntityFinder(false)\n }}\n title={'Select Project to Filter Access Requirements'}\n promptCopy={\n 'Select a project to find Access Requirements that are associated with that project. Access Requirements will be found if the Access Requirement is applied to the project, or if it is applied to any item inside the project.'\n }\n onConfirm={selected => {\n setRelatedProjectId(selected[0].targetId)\n setShowEntityFinder(false)\n }}\n confirmButtonCopy={'Select'}\n />\n <Grid component={'form'} container spacing={2} className=\"InputPanel\">\n <Grid size={{ xs: 12, md: 4 }}>\n <TextField\n label=\"Filter by Access Requirement Name or ID\"\n id=\"ar-name-filter\"\n type=\"text\"\n fullWidth\n placeholder=\"Search for an Access Requirement Name or ID\"\n onChange={e => {\n setNameOrID(e.target.value)\n }}\n slotProps={{\n input: {\n endAdornment: (\n <InputAdornment position=\"end\">\n <SearchOutlined />\n </InputAdornment>\n ),\n },\n }}\n />\n </Grid>\n <Grid\n size={{ xs: 12, md: 4 }}\n sx={{\n display: 'flex',\n gap: '5px',\n alignItems: 'stretch',\n }}\n >\n <TextField\n label=\"Filter by Project\"\n id=\"project-id-filter\"\n type=\"text\"\n fullWidth\n placeholder=\"Enter a project SynID\"\n error={projectFilterFieldIsError}\n helperText={\n projectFilterFieldIsError\n ? 'Value must be a Synapse ID, e.g. \"syn1234\"'\n : undefined\n }\n onChange={e => {\n const newValue = e.target.value\n if (newValue === '') {\n setRelatedProjectId(undefined)\n } else {\n setRelatedProjectId(newValue)\n }\n }}\n />\n <InputSizedButton\n variant=\"outlined\"\n color=\"primary\"\n onClick={() => {\n setShowEntityFinder(true)\n }}\n >\n Browse\n </InputSizedButton>\n </Grid>\n <Grid size={{ xs: 12, md: 4 }}>\n <Typography\n component=\"label\"\n variant=\"smallText2\"\n htmlFor=\"reviewer-filter\"\n >\n Filter by Reviewer\n </Typography>\n <UserSearchBox\n inputId=\"reviewer-filter\"\n placeholder=\"Search for a username or team name\"\n defaultValue={reviewerId}\n onChange={onReviewerChange}\n />\n </Grid>\n </Grid>\n <AccessRequirementTable\n nameOrID={nameOrID}\n relatedProjectId={relatedProjectId}\n reviewerId={reviewerId}\n onCreateNewAccessRequirementClicked={\n onCreateNewAccessRequirementClicked\n }\n typeFilter={typeFilter}\n onTypeFilterChange={setTypeFilter}\n />\n </>\n )\n\n return (\n <div className=\"AccessRequirementDashboard\">{accessRequirementsPanel}</div>\n )\n}\n\nexport default AccessRequirementDashboard\n"],"mappings":"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"}
|
|
@@ -4,7 +4,7 @@ import { useAccessRequirementTable as n } from "./UseAccessRequirementTable.js";
|
|
|
4
4
|
import { noop as r } from "lodash-es";
|
|
5
5
|
import { Button as i, Typography as a } from "@mui/material";
|
|
6
6
|
import { jsx as o, jsxs as s } from "react/jsx-runtime";
|
|
7
|
-
import
|
|
7
|
+
import c from "@mui/icons-material/StarTwoTone";
|
|
8
8
|
//#region src/components/dataaccess/AccessRequirementTable.tsx
|
|
9
9
|
function l(l) {
|
|
10
10
|
let { nameOrID: u, relatedProjectId: d, reviewerId: f, accessType: p, onCreateNewAccessRequirementClicked: m, typeFilter: h, onTypeFilterChange: g = r } = l, { table: _, isLoading: v, hasNextPage: y, fetchNextPage: b, isFetchingNextPage: x } = n({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AccessRequirementTable.js","names":[],"sources":["../../../src/components/dataaccess/AccessRequirementTable.tsx"],"sourcesContent":["import InfiniteTableLayout from '@/components/layout/InfiniteTableLayout'\nimport { ACCESS_TYPE } from '@sage-bionetworks/synapse-types'\nimport { Button, Typography } from '@mui/material'\nimport
|
|
1
|
+
{"version":3,"file":"AccessRequirementTable.js","names":[],"sources":["../../../src/components/dataaccess/AccessRequirementTable.tsx"],"sourcesContent":["import InfiniteTableLayout from '@/components/layout/InfiniteTableLayout'\nimport { ACCESS_TYPE } from '@sage-bionetworks/synapse-types'\nimport { Button, Typography } from '@mui/material'\nimport StarTwoTone from '@mui/icons-material/StarTwoTone'\nimport { useAccessRequirementTable } from './UseAccessRequirementTable'\nimport StyledTanStackTable from '../TanStackTable/StyledTanStackTable'\nimport { noop } from 'lodash-es'\n\nexport type AccessRequirementTableProps = {\n nameOrID?: string\n relatedProjectId?: string\n reviewerId?: string\n accessType?: ACCESS_TYPE\n onCreateNewAccessRequirementClicked?: () => void\n typeFilter?: string\n onTypeFilterChange?: (typeFilter: string | undefined) => void\n}\n\nexport function AccessRequirementTable(props: AccessRequirementTableProps) {\n const {\n nameOrID,\n relatedProjectId,\n reviewerId,\n accessType,\n onCreateNewAccessRequirementClicked,\n typeFilter,\n onTypeFilterChange = noop,\n } = props\n\n const { table, isLoading, hasNextPage, fetchNextPage, isFetchingNextPage } =\n useAccessRequirementTable({\n nameOrID,\n relatedProjectId,\n reviewerId,\n accessType,\n typeFilter,\n onTypeFilterChange,\n })\n\n const isEmpty = !isLoading && table.getRowModel().rows.length === 0\n\n return (\n <div>\n <div className=\"SRC-split\">\n <Typography variant=\"headline3\" style={{ marginBottom: 0 }}>\n Access Requirements\n </Typography>\n {onCreateNewAccessRequirementClicked && (\n <Button\n variant=\"outlined\"\n color=\"primary\"\n onClick={onCreateNewAccessRequirementClicked}\n startIcon={<StarTwoTone />}\n >\n New Access Requirement\n </Button>\n )}\n </div>\n <InfiniteTableLayout\n table={\n <StyledTanStackTable\n table={table}\n styledTableContainerProps={{ sx: { my: 2 } }}\n />\n }\n isLoading={isLoading}\n isEmpty={isEmpty}\n hasNextPage={hasNextPage}\n onFetchNextPageClicked={() => {\n fetchNextPage()\n }}\n isFetchingNextPage={isFetchingNextPage}\n />\n </div>\n )\n}\n"],"mappings":";;;;;;;;AAkBA,SAAgB,EAAuB,GAAoC;CACzE,IAAM,EACJ,aACA,qBACA,eACA,eACA,wCACA,eACA,wBAAqB,MACnB,GAEE,EAAE,UAAO,cAAW,gBAAa,kBAAe,0BACpD,EAA0B;EACxB;EACA;EACA;EACA;EACA;EACA;CACF,CAAC,GAEG,IAAU,CAAC,KAAa,EAAM,YAAY,EAAE,KAAK,WAAW;CAElE,OACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,GAAD;GAAY,SAAQ;GAAY,OAAO,EAAE,cAAc,EAAE;aAAG;EAEhD,CAAA,GACX,KACC,kBAAC,GAAD;GACE,SAAQ;GACR,OAAM;GACN,SAAS;GACT,WAAW,kBAAC,GAAD,CAAc,CAAA;aAC1B;EAEO,CAAA,CAEP;KACL,kBAAC,GAAD;EACE,OACE,kBAAC,GAAD;GACS;GACP,2BAA2B,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;EAC5C,CAAA;EAEQ;EACF;EACI;EACb,8BAA8B;GAC5B,EAAc;EAChB;EACoB;CACrB,CAAA,CACE,EAAA,CAAA;AAET"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EDucTemplateTable.d.ts","sourceRoot":"","sources":["../../../src/components/dataaccess/EDucTemplateTable.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"EDucTemplateTable.d.ts","sourceRoot":"","sources":["../../../src/components/dataaccess/EDucTemplateTable.tsx"],"names":[],"mappings":"AAmKA,wBAAgB,iBAAiB,4CAuEhC;AAED,eAAe,iBAAiB,CAAA"}
|