synapse-react-client 4.0.9 → 4.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/SWC.index.d.ts +1 -0
- package/dist/SWC.index.d.ts.map +1 -1
- package/dist/SWC.index.js +2 -1
- package/dist/SWC.index.js.map +1 -1
- package/dist/aridhia-queries/aridhiaTokenExchange.js.map +1 -1
- package/dist/aridhia-queries/useGetAridhiaRequests.js.map +1 -1
- package/dist/assets/icons/TasksIcon.d.ts.map +1 -1
- package/dist/assets/icons/TasksIcon.js +6 -10
- package/dist/assets/icons/TasksIcon.js.map +1 -1
- package/dist/components/AccessRequirementAclEditor/AccessRequirementAclEditor.d.ts.map +1 -1
- package/dist/components/AccessRequirementAclEditor/AccessRequirementAclEditor.js +69 -63
- package/dist/components/AccessRequirementAclEditor/AccessRequirementAclEditor.js.map +1 -1
- package/dist/components/AccessRequirementList/AccessApprovalCheckMark.js.map +1 -1
- package/dist/components/AccessRequirementList/AccessRequirementList.js.map +1 -1
- package/dist/components/AccessRequirementList/AccessRequirementListUtils.js.map +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/DataAccessRequestAccessorsEditor.js.map +1 -1
- package/dist/components/AccessRequirementList/RequirementItem/SelfSignAccessRequirementItem.js.map +1 -1
- package/dist/components/AccessRequirementRelatedProjectsList/AccessRequirementRelatedProjectsList.js.map +1 -1
- package/dist/components/AccessTokenPage/AccessTokenCard/AccessTokenCard.js.map +1 -1
- package/dist/components/AcknowledgementsPage/StudyAcknowledgements.js.map +1 -1
- package/dist/components/AclEditor/PermissionLevelMenu.js.map +1 -1
- package/dist/components/AclEditor/ResourceAccessAndUserGroupHeader.js.map +1 -1
- package/dist/components/AclEditor/useSortResourceAccessList.js.map +1 -1
- package/dist/components/AclEditor/useUpdateAcl.js.map +1 -1
- package/dist/components/Aridhia/AridhiaAccessStatus.js.map +1 -1
- package/dist/components/Authentication/AuthenticationMethodSelection.d.ts.map +1 -1
- package/dist/components/Authentication/AuthenticationMethodSelection.js +38 -37
- package/dist/components/Authentication/AuthenticationMethodSelection.js.map +1 -1
- package/dist/components/Authentication/Constants.d.ts +1 -0
- package/dist/components/Authentication/Constants.d.ts.map +1 -1
- package/dist/components/Authentication/Constants.js +2 -2
- package/dist/components/Authentication/Constants.js.map +1 -1
- package/dist/components/Authentication/LastLoginInfo.js.map +1 -1
- package/dist/components/Authentication/RecoveryCodeForm.js.map +1 -1
- package/dist/components/Authentication/RecoveryCodeGrid.js.map +1 -1
- package/dist/components/Authentication/RegenerateBackupCodesWarning.js.map +1 -1
- package/dist/components/Authentication/Reset2FAWarning.js.map +1 -1
- package/dist/components/Authentication/StandaloneLoginForm.js +1 -1
- package/dist/components/Authentication/TwoFactorBackupCodes.js.map +1 -1
- package/dist/components/Authentication/TwoFactorEnrollmentForm.d.ts.map +1 -1
- package/dist/components/Authentication/TwoFactorEnrollmentForm.js +2 -1
- package/dist/components/Authentication/TwoFactorEnrollmentForm.js.map +1 -1
- package/dist/components/BasePortalCard/ColorfulPortalCardWithChips/ColorfulPortalCardWithChips.js.map +1 -1
- package/dist/components/CardContainer/CardContainer.js.map +1 -1
- package/dist/components/CardDeck/CardDeck.Mobile.js.map +1 -1
- package/dist/components/CardDeck/TableQueryCardDeck.js.map +1 -1
- package/dist/components/CertificationQuiz/CertificationQuiz.js.map +1 -1
- package/dist/components/ChallengeDataDownload/ChallengeDataDownload.js.map +1 -1
- package/dist/components/ChallengeSubmission/ChallengeSubmission.js.map +1 -1
- package/dist/components/ChallengeSubmission/ChallengeSubmissionStepper.js.map +1 -1
- package/dist/components/ChallengeSubmission/EvaluationQueueCurrentRoundInfo.js.map +1 -1
- package/dist/components/ChallengeSubmission/EvaluationQueueList.js.map +1 -1
- package/dist/components/ChallengeSubmission/SubmissionDirectoryList.js.map +1 -1
- package/dist/components/ChallengeTeamWizard/ChallengeTeamWizard.js.map +1 -1
- package/dist/components/ChallengeTeamWizard/CreateChallengeTeam.js.map +1 -1
- package/dist/components/ChangePassword/ChangePassword.js.map +1 -1
- package/dist/components/ChangePassword/ChangePasswordWithToken.js.map +1 -1
- package/dist/components/ChangePassword/useChangePasswordFormState.js +1 -1
- package/dist/components/ChangePassword/useChangePasswordFormState.js.map +1 -1
- package/dist/components/CitationPopover/CitationPopoverContent.js.map +1 -1
- package/dist/components/ColumnFilter/ColumnFilter.js.map +1 -1
- package/dist/components/ComponentCollapse.js.map +1 -1
- package/dist/components/CookiesNotification/CookiesNotification.js.map +1 -1
- package/dist/components/CreateProjectModal/CreateProjectModal.js.map +1 -1
- package/dist/components/CreateTableViewWizard/CreateTableViewWizardUtils.js.map +1 -1
- package/dist/components/DataGrid/DataGrid.d.ts +0 -1
- package/dist/components/DataGrid/DataGrid.d.ts.map +1 -1
- package/dist/components/DataGrid/DataGrid.js +72 -72
- package/dist/components/DataGrid/DataGrid.js.map +1 -1
- package/dist/components/DataGrid/DataGridWebSocket.d.ts +4 -0
- package/dist/components/DataGrid/DataGridWebSocket.d.ts.map +1 -1
- package/dist/components/DataGrid/DataGridWebSocket.js +9 -8
- package/dist/components/DataGrid/DataGridWebSocket.js.map +1 -1
- package/dist/components/DataGrid/SynapseGrid.d.ts.map +1 -1
- package/dist/components/DataGrid/SynapseGrid.js +326 -268
- package/dist/components/DataGrid/SynapseGrid.js.map +1 -1
- package/dist/components/DataGrid/columns/AutocompleteColumn.d.ts +2 -0
- package/dist/components/DataGrid/columns/AutocompleteColumn.d.ts.map +1 -1
- package/dist/components/DataGrid/columns/AutocompleteColumn.js +113 -67
- package/dist/components/DataGrid/columns/AutocompleteColumn.js.map +1 -1
- package/dist/components/DataGrid/columns/AutocompleteMultipleEnumColumn.d.ts +2 -1
- package/dist/components/DataGrid/columns/AutocompleteMultipleEnumColumn.d.ts.map +1 -1
- package/dist/components/DataGrid/columns/AutocompleteMultipleEnumColumn.js +126 -122
- package/dist/components/DataGrid/columns/AutocompleteMultipleEnumColumn.js.map +1 -1
- package/dist/components/DataGrid/columns/useGridAutocompleteState.d.ts +58 -0
- package/dist/components/DataGrid/columns/useGridAutocompleteState.d.ts.map +1 -0
- package/dist/components/DataGrid/columns/useGridAutocompleteState.js +52 -0
- package/dist/components/DataGrid/columns/useGridAutocompleteState.js.map +1 -0
- package/dist/components/DataGrid/components/ValidationAlert.d.ts +5 -2
- package/dist/components/DataGrid/components/ValidationAlert.d.ts.map +1 -1
- package/dist/components/DataGrid/components/ValidationAlert.js +429 -24
- package/dist/components/DataGrid/components/ValidationAlert.js.map +1 -1
- package/dist/components/DataGrid/hooks/useColumnResizeHandles.js.map +1 -1
- package/dist/components/DataGrid/hooks/useGetSchemaForGrid.js.map +1 -1
- package/dist/components/DataGrid/hooks/useGridUndoRedo.js.map +1 -1
- package/dist/components/DataGrid/hooks/useStack.js.map +1 -1
- package/dist/components/DataGrid/useCRDTModelView.js.map +1 -1
- package/dist/components/DataGrid/useDataGridWebsocket.d.ts +7 -0
- package/dist/components/DataGrid/useDataGridWebsocket.d.ts.map +1 -1
- package/dist/components/DataGrid/useDataGridWebsocket.js +16 -2
- package/dist/components/DataGrid/useDataGridWebsocket.js.map +1 -1
- package/dist/components/DataGrid/useInitializeGridConnection.js.map +1 -1
- package/dist/components/DataGrid/useMergeGridWithRecordSet.js.map +1 -1
- package/dist/components/DataGrid/useMergeGridWithSource.js.map +1 -1
- package/dist/components/DataGrid/useMergeGridWithTable.js.map +1 -1
- package/dist/components/DataGrid/utils/DataGridUtils.js.map +1 -1
- package/dist/components/DataGrid/utils/applyModelChange.js.map +1 -1
- package/dist/components/DataGrid/utils/columnFactory.js.map +1 -1
- package/dist/components/DataGrid/utils/computeReplicaSelectionModel.js.map +1 -1
- package/dist/components/DataGrid/utils/extractColumnValidationMessages.js.map +1 -1
- package/dist/components/DataGrid/utils/getCellClassName.d.ts.map +1 -1
- package/dist/components/DataGrid/utils/getCellClassName.js +8 -8
- package/dist/components/DataGrid/utils/getCellClassName.js.map +1 -1
- package/dist/components/DataGrid/utils/json-rx/JsonRx.js.map +1 -1
- package/dist/components/DataGrid/utils/modelRowsToGrid.js.map +1 -1
- package/dist/components/DataGrid/utils/parseFreeTextUsingJsonSchemaType.js.map +1 -1
- package/dist/components/DataGrid/utils/splitPatch.js.map +1 -1
- package/dist/components/DateTimePicker/DateTimePicker.js.map +1 -1
- package/dist/components/DirectDownload/DirectDownload.js.map +1 -1
- package/dist/components/DirectDownloadButton.js.map +1 -1
- package/dist/components/DownloadCart/CreatePackageV2.js.map +1 -1
- package/dist/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.js.map +1 -1
- package/dist/components/DownloadCart/DownloadListActionsRequired.js.map +1 -1
- package/dist/components/DownloadCart/DownloadListTable.js.map +1 -1
- package/dist/components/DownloadCart/fileNameUtils.js.map +1 -1
- package/dist/components/DraggableDialog/DraggableDialog.js.map +1 -1
- package/dist/components/DynamicForm/DynamicFormModal.js.map +1 -1
- package/dist/components/Ecosystem/TableQueryEcosystem.js.map +1 -1
- package/dist/components/EntityAclEditor/EntityAclEditor.d.ts.map +1 -1
- package/dist/components/EntityAclEditor/EntityAclEditor.js +103 -103
- package/dist/components/EntityAclEditor/EntityAclEditor.js.map +1 -1
- package/dist/components/EntityAclEditor/useNotifyNewACLUsers.js.map +1 -1
- package/dist/components/EntityBadgeIcons/EntityBadgeIcons.js.map +1 -1
- package/dist/components/EntityCitation/EntityCitation.js.map +1 -1
- package/dist/components/EntityDownloadButton/EntityDownloadButton.js.map +1 -1
- package/dist/components/EntityDownloadConfirmation/EntityDownloadConfirmation.d.ts.map +1 -1
- package/dist/components/EntityDownloadConfirmation/EntityDownloadConfirmation.js +36 -30
- package/dist/components/EntityDownloadConfirmation/EntityDownloadConfirmation.js.map +1 -1
- package/dist/components/EntityFinder/EntityFinder.js.map +1 -1
- package/dist/components/EntityFinder/VersionSelectionType.js.map +1 -1
- package/dist/components/EntityFinder/details/configurations/EntityChildrenDetails.js.map +1 -1
- package/dist/components/EntityFinder/details/configurations/FavoritesDetails.js.map +1 -1
- package/dist/components/EntityFinder/details/configurations/ProjectListDetails.js.map +1 -1
- package/dist/components/EntityFinder/details/view/DetailsView.js.map +1 -1
- package/dist/components/EntityFinder/tree/EntityTree.js.map +1 -1
- package/dist/components/EntityFinder/tree/VirtualizedTree.js.map +1 -1
- package/dist/components/EntityFinder/useEntitySelection.js.map +1 -1
- package/dist/components/EntityForm/EntityForm.js.map +1 -1
- package/dist/components/EntityHeaderTable/EntityHeaderTable.js.map +1 -1
- package/dist/components/EntityHeaderTable/Filter.js.map +1 -1
- package/dist/components/EntityHeaderTable/useEntityHeaderTableState.js.map +1 -1
- package/dist/components/EntitySubjectsSelector/EntitySubjectsSelector.js.map +1 -1
- package/dist/components/EntityTreeTable/components/IdColumnHeader.js.map +1 -1
- package/dist/components/EntityTreeTable/hooks/useEntityTreeState.js.map +1 -1
- package/dist/components/EntityTreeTable/hooks/useTableColumns.js.map +1 -1
- package/dist/components/EntityTreeTable/hooks/useTableData.js.map +1 -1
- package/dist/components/EntityTreeTable/hooks/useTreeOperationsWithDirectFetch.js.map +1 -1
- package/dist/components/EntityUpload/EntityUpload.js.map +1 -1
- package/dist/components/ExperimentalMode/ExperimentalMode.js.map +1 -1
- package/dist/components/ExternalFileHandleLink/ExternalFileHandleLink.js.map +1 -1
- package/dist/components/FeaturedDataTabs/FacetPlotsCard.js.map +1 -1
- package/dist/components/FeaturedDataTabs/QueryPerFacetPlotsCard.js.map +1 -1
- package/dist/components/FeaturedDataTabs/SingleQueryFacetPlotsCards.js.map +1 -1
- package/dist/components/FeaturedResearch/FeaturedResearch.js.map +1 -1
- package/dist/components/FeaturedToolsList/FeaturedToolsList.js.map +1 -1
- package/dist/components/FilePreview/FileHandleContentRenderer.js.map +1 -1
- package/dist/components/FilePreview/HtmlPreview/HtmlPreview.js.map +1 -1
- package/dist/components/FilePreview/PreviewRendererType.js.map +1 -1
- package/dist/components/Forum/DiscussionReply.js.map +1 -1
- package/dist/components/Forum/DiscussionSearchResult.js.map +1 -1
- package/dist/components/Forum/ForumTable.js.map +1 -1
- package/dist/components/Forum/ForumThreadEditor.js.map +1 -1
- package/dist/components/FullTextSearch/FullTextSearchUtils.js.map +1 -1
- package/dist/components/GenericCard/GenericCard.d.ts.map +1 -1
- package/dist/components/GenericCard/GenericCard.js +12 -7
- package/dist/components/GenericCard/GenericCard.js.map +1 -1
- package/dist/components/GenericCard/Linkify.js.map +1 -1
- package/dist/components/GenericCard/SynapseCardLabel.js.map +1 -1
- package/dist/components/GenericCard/TableRowGenericCard.js +105 -105
- package/dist/components/GenericCard/TableRowGenericCard.js.map +1 -1
- package/dist/components/Goals/Goals.Mobile.js.map +1 -1
- package/dist/components/Goals/Goals.js.map +1 -1
- package/dist/components/GoalsV2/GoalsV2.Mobile.js.map +1 -1
- package/dist/components/GoalsV2/GoalsV2.js.map +1 -1
- package/dist/components/GoalsV3/GoalsV3.Mobile.js.map +1 -1
- package/dist/components/GoalsV3/GoalsV3.js.map +1 -1
- package/dist/components/GoogleMap/SynapseUserMarker.js.map +1 -1
- package/dist/components/HasAccess/AccessIcon.js.map +1 -1
- package/dist/components/HasAccess/useHasAccess.js.map +1 -1
- package/dist/components/HeaderCard/HeaderCardV2.js.map +1 -1
- package/dist/components/HeaderCard.d.ts +6 -1
- package/dist/components/HeaderCard.d.ts.map +1 -1
- package/dist/components/HeaderCard.js +107 -76
- package/dist/components/HeaderCard.js.map +1 -1
- package/dist/components/HexGrid/HexGrid.js.map +1 -1
- package/dist/components/IconList.js.map +1 -1
- package/dist/components/ImageCardGridWithLinks/ImageCardGridWithLinks.js.map +1 -1
- package/dist/components/ImageFromSynapseTable.js.map +1 -1
- package/dist/components/JSONArrayEditor/useParseCsv.js.map +1 -1
- package/dist/components/JsonSchemaForm/templates/ArrayFieldDescriptionTemplate.js.map +1 -1
- package/dist/components/JsonSchemaForm/templates/ArrayFieldItemTemplate.js.map +1 -1
- package/dist/components/JsonSchemaForm/templates/BaseInputTemplate.js.map +1 -1
- package/dist/components/JsonSchemaForm/templates/FieldTemplate.js.map +1 -1
- package/dist/components/JsonSchemaForm/templates/RJSFInputLabel.js.map +1 -1
- package/dist/components/Markdown/MarkdownGithub.js.map +1 -1
- package/dist/components/Markdown/MarkdownSynapse.js.map +1 -1
- package/dist/components/Markdown/MarkdownUtils.js.map +1 -1
- package/dist/components/Markdown/SynapseWikiContext.js.map +1 -1
- package/dist/components/Markdown/UserMentionModal.js.map +1 -1
- package/dist/components/Markdown/widget/MarkdownProvenanceGraph.js.map +1 -1
- package/dist/components/MissingQueryResultsWarning/MissingQueryResultsWarning.js.map +1 -1
- package/dist/components/ModalDownload/ModalDownload.js.map +1 -1
- package/dist/components/OAuthClientAclEditor/OAuthClientAclEditor.d.ts.map +1 -1
- package/dist/components/OAuthClientAclEditor/OAuthClientAclEditor.js +45 -39
- package/dist/components/OAuthClientAclEditor/OAuthClientAclEditor.js.map +1 -1
- package/dist/components/OAuthClientManagement/OAuthManagement.js.map +1 -1
- package/dist/components/PageProgress/PageProgress.js.map +1 -1
- package/dist/components/Plot/DotPlot.js.map +1 -1
- package/dist/components/Plot/Plot.js.map +1 -1
- package/dist/components/Plot/SynapsePlot.js.map +1 -1
- package/dist/components/Plot/ThemesPlot.js.map +1 -1
- package/dist/components/Plot/UpsetPlot.js.map +1 -1
- package/dist/components/PortalAclEditor/PortalAclEditor.d.ts.map +1 -1
- package/dist/components/PortalAclEditor/PortalAclEditor.js +43 -41
- package/dist/components/PortalAclEditor/PortalAclEditor.js.map +1 -1
- package/dist/components/PortalFeaturedPartners/PortalFeaturedPartners.js.map +1 -1
- package/dist/components/PortalList/CreatePortalModal.js.map +1 -1
- package/dist/components/ProgrammaticInstructionsModal/ProgrammaticInstructionsModal.js.map +1 -1
- package/dist/components/ProgrammaticTableDownload/ProgrammaticTableDownload.js.map +1 -1
- package/dist/components/Programs/Programs.Mobile.js.map +1 -1
- package/dist/components/Programs/Programs.js.map +1 -1
- package/dist/components/ProvenanceGraph/ProvenanceExternalIcon.js.map +1 -1
- package/dist/components/ProvenanceGraph/ProvenanceGraph.js.map +1 -1
- package/dist/components/ProvenanceGraph/ProvenanceGraphUtils.js.map +1 -1
- package/dist/components/ProvenanceGraph/ProvenanceUtils.js.map +1 -1
- package/dist/components/QueryCount/QueryCount.js.map +1 -1
- package/dist/components/QueryCountButton/QueryCountButton.js.map +1 -1
- package/dist/components/QueryVisualizationWrapper/QueryVisualizationWrapper.js.map +1 -1
- package/dist/components/QueryWrapper/QueryWrapper.js.map +1 -1
- package/dist/components/QueryWrapper/TableQueryUseQueryOptions.js.map +1 -1
- package/dist/components/QueryWrapper/TableRowSelectionState.js.map +1 -1
- package/dist/components/QueryWrapper/generateEncodedPathAndQueryForSelectedFacetURL.js.map +1 -1
- package/dist/components/QueryWrapper/useGetQueryMetadata.js.map +1 -1
- package/dist/components/QueryWrapperErrorBoundary.js.map +1 -1
- package/dist/components/QueryWrapperPlotNav/QueryWrapperPlotNav.js.map +1 -1
- package/dist/components/QueryWrapperPlotNav/UseRowSet.js.map +1 -1
- package/dist/components/RecentPublicationsGrid/RecentPublicationsGrid.js.map +1 -1
- package/dist/components/ReleaseCard/ReleaseCardUtils.js.map +1 -1
- package/dist/components/ResizableContainer/hooks/useResizable.js.map +1 -1
- package/dist/components/Resources/Resources.Mobile.js.map +1 -1
- package/dist/components/Resources/Resources.js.map +1 -1
- package/dist/components/RowDataTable/RowDataTableWithQuery.js.map +1 -1
- package/dist/components/SageResourcesPopover/SageResourcesPopover.js.map +1 -1
- package/dist/components/SchemaDrivenAnnotationEditor/AnnotationEditorUtils.js.map +1 -1
- package/dist/components/SetAccessRequirementCommonFields/SetAccessRequirementCommonFields.js.map +1 -1
- package/dist/components/SetManagedAccessRequirementFields/SetManagedAccessRequirementFields.js.map +1 -1
- package/dist/components/SmartLink/SmartButton.js.map +1 -1
- package/dist/components/SmartLink/SmartLink.js.map +1 -1
- package/dist/components/SourceAppImage.js.map +1 -1
- package/dist/components/StandaloneQueryWrapper/StandaloneQueryWrapper.js.map +1 -1
- package/dist/components/StatisticsPlot.js.map +1 -1
- package/dist/components/StorybookComponentWrapper.js.map +1 -1
- package/dist/components/SubsectionRowRenderer/SubsectionRowRenderer.js.map +1 -1
- package/dist/components/SustainabilityScorecard/SustainabilityScorecard.js.map +1 -1
- package/dist/components/SynapseChat/GridAgentChat.js.map +1 -1
- package/dist/components/SynapseChat/SynapseChatInteraction.js.map +1 -1
- package/dist/components/SynapseChat/SynapseChatMessage.js.map +1 -1
- package/dist/components/SynapseChat/extractMessageFromTraceEvent.js.map +1 -1
- package/dist/components/SynapseForm/StepsSideNav.js.map +1 -1
- package/dist/components/SynapseForm/SummaryTable.js.map +1 -1
- package/dist/components/SynapseForm/SynapseForm.js +4 -2
- package/dist/components/SynapseForm/SynapseForm.js.map +1 -1
- package/dist/components/SynapseForm/SynapseFormWrapper.js.map +1 -1
- package/dist/components/SynapseHomepageV2/SynapseByTheNumbersItem.js.map +1 -1
- package/dist/components/SynapseHomepageV2/SynapseFeatureItem.js.map +1 -1
- package/dist/components/SynapseHomepageV2/SynapseHomepageChatSearch.js.map +1 -1
- package/dist/components/SynapseHomepageV2/SynapseHomepageSearch.js.map +1 -1
- package/dist/components/SynapseHomepageV2/SynapseInActionItem.js.map +1 -1
- package/dist/components/SynapseHomepageV2/SynapsePlans.js.map +1 -1
- package/dist/components/SynapseHomepageV2/SynapseTrendingProjects.js.map +1 -1
- package/dist/components/SynapseNavDrawer/SynapseNavDrawer.d.ts +8 -7
- package/dist/components/SynapseNavDrawer/SynapseNavDrawer.d.ts.map +1 -1
- package/dist/components/SynapseNavDrawer/SynapseNavDrawer.js +173 -164
- package/dist/components/SynapseNavDrawer/SynapseNavDrawer.js.map +1 -1
- package/dist/components/SynapsePortalBanners/SynapsePortalBanners.js.map +1 -1
- package/dist/components/SynapseSearchPageResults/SearchFacetPanel/SearchFacetPanel.js.map +1 -1
- package/dist/components/SynapseSearchPageResults/SearchFacetPanel/SearchFacetPanelUtils.js.map +1 -1
- package/dist/components/SynapseSearchPageResults/SynapseSearchPageResults.js.map +1 -1
- package/dist/components/SynapseTable/EntityIDColumnCopyIcon.js.map +1 -1
- package/dist/components/SynapseTable/NoContentPlaceholderType.js.map +1 -1
- package/dist/components/SynapseTable/RowSelection/RowSelectionControls.js.map +1 -1
- package/dist/components/SynapseTable/SynapseTableCell/SynapseTableCell.js.map +1 -1
- package/dist/components/SynapseTable/SynapseTableRenderers.js.map +1 -1
- package/dist/components/SynapseTable/datasets/DatasetItemsEditor.js.map +1 -1
- package/dist/components/SynapseTable/table-top/ColumnSelection.js.map +1 -1
- package/dist/components/SynapseTable/table-top/DownloadOptions.js.map +1 -1
- package/dist/components/SynapseTable/usePrefetchTableData.js.map +1 -1
- package/dist/components/TableColumnSchemaEditor/ColumnModelForm.js.map +1 -1
- package/dist/components/TableColumnSchemaEditor/ColumnModelFormFields/DefaultValueField.js.map +1 -1
- package/dist/components/TableColumnSchemaEditor/ImportTableColumnsButton.js.map +1 -1
- package/dist/components/TableColumnSchemaEditor/TableColumnSchemaEditorUtils.d.ts +1 -1
- package/dist/components/TableColumnSchemaEditor/TableColumnSchemaEditorUtils.d.ts.map +1 -1
- package/dist/components/TableColumnSchemaEditor/TableColumnSchemaEditorUtils.js.map +1 -1
- package/dist/components/TableColumnSchemaEditor/TableColumnSchemaForm.js.map +1 -1
- package/dist/components/TableColumnSchemaEditor/TableColumnSchemaFormReducer.js.map +1 -1
- package/dist/components/TableColumnSchemaEditor/Validators/ColumnModelValidator.js.map +1 -1
- package/dist/components/TableColumnSchemaEditor/Validators/DatetimeSchema.js.map +1 -1
- package/dist/components/TanStackTable/ColumnHeader.d.ts +1 -0
- package/dist/components/TanStackTable/ColumnHeader.d.ts.map +1 -1
- package/dist/components/TanStackTable/ColumnHeader.js +8 -8
- package/dist/components/TanStackTable/ColumnHeader.js.map +1 -1
- package/dist/components/TanStackTable/ColumnHeaderEnumFilter.js.map +1 -1
- package/dist/components/TanStackTable/TableBody.js.map +1 -1
- package/dist/components/TeamSubjectsSelector/TeamSubjectsSelector.js.map +1 -1
- package/dist/components/TextField/TextField.js.map +1 -1
- package/dist/components/TimelinePlot/TimelinePhase.js.map +1 -1
- package/dist/components/TimelinePlot/TimelinePlot.js.map +1 -1
- package/dist/components/TimelinePlot/TimelinePlotSpeciesSelector.js.map +1 -1
- package/dist/components/UserCard/Avatar.js.map +1 -1
- package/dist/components/UserCardList/UserCardList.js.map +1 -1
- package/dist/components/UserCardList/UserCardListGroups/UserCardListGroups.Mobile.js.map +1 -1
- package/dist/components/UserCardList/UserCardListRotate.js.map +1 -1
- package/dist/components/UserOrTeamBadge/useUserOrTeam.js.map +1 -1
- package/dist/components/UserProfileLinks/UserProjects.js.map +1 -1
- package/dist/components/UserSearchBox/UserSearchBox.js.map +1 -1
- package/dist/components/Webhook/WebhookDashboard.js.map +1 -1
- package/dist/components/WikiMarkdownEditor/WikiMarkdownEditor.js.map +1 -1
- package/dist/components/WikiMarkdownEditorButton/WikiMarkdownEditorButton.js.map +1 -1
- package/dist/components/dataaccess/AccessApprovalsTable.js.map +1 -1
- package/dist/components/dataaccess/AccessRequestSubmissionTable.js.map +1 -1
- package/dist/components/dataaccess/SubmissionPage/SubmissionPage.js.map +1 -1
- package/dist/components/dataaccess/UseAccessRequirementTable.js.map +1 -1
- package/dist/components/dataaccess/UserAccessRequestHistory/UserAccessRequestHistoryTable.js.map +1 -1
- package/dist/components/doi/CreateOrUpdateDoiModal.js.map +1 -1
- package/dist/components/entity/page/CreatedByModifiedBy.js.map +1 -1
- package/dist/components/entity/page/action_menu/EntityActionMenu.js.map +1 -1
- package/dist/components/entity/page/title_bar/useDataCiteUsage.js.map +1 -1
- package/dist/components/entity/page/title_bar/useGetMentions.js.map +1 -1
- package/dist/components/error/ErrorPage.js.map +1 -1
- package/dist/components/favorites/FavoritesPage.js.map +1 -1
- package/dist/components/file/upload/BasicFileHandleUpload.js.map +1 -1
- package/dist/components/layout/SWCHeader.d.ts +9 -0
- package/dist/components/layout/SWCHeader.d.ts.map +1 -0
- package/dist/components/layout/SWCHeader.js +19 -0
- package/dist/components/layout/SWCHeader.js.map +1 -0
- package/dist/components/layout/SWCPageLayout.d.ts +9 -0
- package/dist/components/layout/SWCPageLayout.d.ts.map +1 -0
- package/dist/components/layout/SWCPageLayout.js +14 -0
- package/dist/components/layout/SWCPageLayout.js.map +1 -0
- package/dist/components/menu/ComplexMenu.js.map +1 -1
- package/dist/components/row_renderers/utils/ChipContainer.js.map +1 -1
- package/dist/components/styled/StyledPopover.js.map +1 -1
- package/dist/components/table/CsvPreview/CsvPreview.js +2 -1
- package/dist/components/table/CsvPreview/CsvPreview.js.map +1 -1
- package/dist/components/table/CsvPreview/CsvPreviewDialog.js.map +1 -1
- package/dist/components/trash/TrashCanList.js.map +1 -1
- package/dist/components/widgets/FileHandleLink.js.map +1 -1
- package/dist/components/widgets/RangeSlider/RangeSlider.js.map +1 -1
- package/dist/components/widgets/SynapseVideo.js.map +1 -1
- package/dist/components/widgets/facet-nav/FacetNavPanel.js.map +1 -1
- package/dist/components/widgets/facet-nav/PlotsContainer.js.map +1 -1
- package/dist/components/widgets/facet-nav/SelectionCriteriaPills.js.map +1 -1
- package/dist/components/widgets/facet-nav/useFacetPlots.js.map +1 -1
- package/dist/components/widgets/query-filter/CombinedRangeFacetFilter.js.map +1 -1
- package/dist/components/widgets/query-filter/EnumFacetFilter/EnumFacetFilter.js.map +1 -1
- package/dist/components/widgets/query-filter/FacetFilterControls.js.map +1 -1
- package/dist/components/widgets/query-filter/RangeFacetFilter.js.map +1 -1
- package/dist/components/widgets/query-filter/RangeFacetFilterUI.js.map +1 -1
- package/dist/features/curator/GridPage/components/GridPageTitle.d.ts.map +1 -1
- package/dist/features/curator/GridPage/components/GridPageTitle.js +23 -30
- package/dist/features/curator/GridPage/components/GridPageTitle.js.map +1 -1
- package/dist/features/curator/dashboard/CuratorDashboard.d.ts +2 -0
- package/dist/features/curator/dashboard/CuratorDashboard.d.ts.map +1 -0
- package/dist/features/curator/dashboard/CuratorDashboard.js +45 -0
- package/dist/features/curator/dashboard/CuratorDashboard.js.map +1 -0
- package/dist/features/curator/dashboard/components/CurationTaskCard.css +1 -0
- package/dist/features/curator/dashboard/components/CurationTaskCard.d.ts +9 -0
- package/dist/features/curator/dashboard/components/CurationTaskCard.d.ts.map +1 -0
- package/dist/features/curator/dashboard/components/CurationTaskCard.js +106 -0
- package/dist/features/curator/dashboard/components/CurationTaskCard.js.map +1 -0
- package/dist/features/curator/dashboard/components/CurationTaskCard.module.js +12 -0
- package/dist/features/curator/dashboard/components/CurationTaskCard.module.js.map +1 -0
- package/dist/features/curator/dashboard/components/CurationTaskCard.module.scss +52 -0
- package/dist/features/curator/dashboard/components/NextStepButton.css +1 -0
- package/dist/features/curator/dashboard/components/NextStepButton.d.ts +14 -0
- package/dist/features/curator/dashboard/components/NextStepButton.d.ts.map +1 -0
- package/dist/features/curator/dashboard/components/NextStepButton.js +35 -0
- package/dist/features/curator/dashboard/components/NextStepButton.js.map +1 -0
- package/dist/features/curator/dashboard/components/NextStepButton.module.js +11 -0
- package/dist/features/curator/dashboard/components/NextStepButton.module.js.map +1 -0
- package/dist/features/curator/dashboard/components/NextStepButton.module.scss +57 -0
- package/dist/features/curator/dashboard/components/UserOrTeamChip.css +1 -1
- package/dist/features/curator/dashboard/components/UserOrTeamChip.module.js +1 -1
- package/dist/features/curator/dashboard/components/UserOrTeamChip.module.js.map +1 -1
- package/dist/features/curator/dashboard/components/UserOrTeamChip.module.scss +5 -5
- package/dist/features/curator/dashboard/components/shared.css +1 -0
- package/dist/features/curator/dashboard/components/shared.module.js +5 -0
- package/dist/features/curator/dashboard/components/shared.module.js.map +1 -0
- package/dist/features/curator/dashboard/components/shared.module.scss +8 -0
- package/dist/features/entity/metadata-task/components/MetadataTaskTableActionCell.d.ts +0 -2
- package/dist/features/entity/metadata-task/components/MetadataTaskTableActionCell.d.ts.map +1 -1
- package/dist/features/entity/metadata-task/components/MetadataTaskTableActionCell.js +16 -34
- package/dist/features/entity/metadata-task/components/MetadataTaskTableActionCell.js.map +1 -1
- package/dist/features/entity/metadata-task/components/MetadataTasksTableAssigneeCell.js.map +1 -1
- package/dist/features/entity/metadata-task/hooks/useGetOrCreateGridSessionForSource.js.map +1 -1
- package/dist/features/entity/metadata-task/hooks/useGridSessionForCurationTask.js.map +1 -1
- package/dist/features/entity/metadata-task/hooks/useGridSessionForCurationTask_legacy.js.map +1 -1
- package/dist/features/entity/metadata-task/hooks/useMetadataTaskTable.js +1 -1
- package/dist/features/entity/metadata-task/hooks/useMetadataTaskTable.js.map +1 -1
- package/dist/features/entity/metadata-task/hooks/useOpenCuratorButton.d.ts +10 -0
- package/dist/features/entity/metadata-task/hooks/useOpenCuratorButton.d.ts.map +1 -0
- package/dist/features/entity/metadata-task/hooks/useOpenCuratorButton.js +37 -0
- package/dist/features/entity/metadata-task/hooks/useOpenCuratorButton.js.map +1 -0
- package/dist/features/entity/metadata-task/utils/constants.d.ts +5 -0
- package/dist/features/entity/metadata-task/utils/constants.d.ts.map +1 -0
- package/dist/features/entity/metadata-task/utils/constants.js +6 -0
- package/dist/features/entity/metadata-task/utils/constants.js.map +1 -0
- package/dist/mocks/challenge/mockChallenge.js.map +1 -1
- package/dist/mocks/entity/mockDataset.js.map +1 -1
- package/dist/mocks/entity/mockDatasetCollection.js.map +1 -1
- package/dist/mocks/entity/mockFileEntity.js.map +1 -1
- package/dist/mocks/entity/mockFileView.js.map +1 -1
- package/dist/mocks/entity/mockGeneratedEntityData.js.map +1 -1
- package/dist/mocks/entity/mockProject.js.map +1 -1
- package/dist/mocks/entity/mockProjectView.js.map +1 -1
- package/dist/mocks/entity/mockRootEntity.js.map +1 -1
- package/dist/mocks/entity/mockTableEntity.js.map +1 -1
- package/dist/mocks/mockWiki.js.map +1 -1
- package/dist/mocks/msw/handlers/asyncJobHandlers.js.map +1 -1
- package/dist/mocks/msw/handlers/challengeHandlers.js.map +1 -1
- package/dist/mocks/msw/handlers/changePasswordHandlers.js.map +1 -1
- package/dist/mocks/msw/handlers/discussionHandlers.js.map +1 -1
- package/dist/mocks/msw/handlers/entityHandlers.js.map +1 -1
- package/dist/mocks/msw/handlers/fileHandlers.js.map +1 -1
- package/dist/mocks/msw/handlers/gridHandlers.js.map +1 -1
- package/dist/mocks/msw/handlers/personalAccessTokenHandlers.js.map +1 -1
- package/dist/mocks/msw/handlers/subscriptionHandlers.js.map +1 -1
- package/dist/mocks/msw/handlers/teamHandlers.js.map +1 -1
- package/dist/mocks/msw/handlers/userProfileHandlers.js.map +1 -1
- package/dist/mocks/msw/handlers/wikiHandlers.js.map +1 -1
- package/dist/mocks/provenance/mockActivity.js.map +1 -1
- package/dist/mocks/query/mockReleaseCardsTableQueryResultBundle.js.map +1 -1
- package/dist/ror-client/index.js.map +1 -1
- package/dist/style/components/_cards.scss +4 -0
- package/dist/style/components/_data-grid-extra.css +1 -1
- package/dist/style/components/_data-grid-extra.scss +2 -0
- package/dist/style/main.css +1 -1
- package/dist/synapse-client/HttpClient.js.map +1 -1
- package/dist/synapse-client/SynapseClient.js.map +1 -1
- package/dist/synapse-queries/QueryMatching.test-utils.js.map +1 -1
- package/dist/synapse-queries/auth/useTwoFactorEnrollment.js.map +1 -1
- package/dist/synapse-queries/curation/task/useCurationTask.d.ts +1 -1
- package/dist/synapse-queries/curation/task/useCurationTask.d.ts.map +1 -1
- package/dist/synapse-queries/curation/task/useCurationTask.js +1 -1
- package/dist/synapse-queries/curation/task/useCurationTask.js.map +1 -1
- package/dist/synapse-queries/dataaccess/useRestrictionInformation.js.map +1 -1
- package/dist/synapse-queries/doi/useDOI.js.map +1 -1
- package/dist/synapse-queries/download/useDownloadList.js.map +1 -1
- package/dist/synapse-queries/entity/useEntity.js.map +1 -1
- package/dist/synapse-queries/entity/useEntityBundle.js.map +1 -1
- package/dist/synapse-queries/entity/useExportTableQueryToAnalysisPlatform.js.map +1 -1
- package/dist/synapse-queries/entity/useExportToTerra.js.map +1 -1
- package/dist/synapse-queries/entity/useGetQueryResultBundle.js.map +1 -1
- package/dist/synapse-queries/entity/useSchema.js.map +1 -1
- package/dist/synapse-queries/file/UploadToS3.js.map +1 -1
- package/dist/synapse-queries/file/useDirectUploadToS3.js.map +1 -1
- package/dist/synapse-queries/file/useFiles.js.map +1 -1
- package/dist/synapse-queries/forum/useReply.js.map +1 -1
- package/dist/synapse-queries/forum/useThread.js.map +1 -1
- package/dist/synapse-queries/grid/useEstablishWebsocketConnection.d.ts +2 -0
- package/dist/synapse-queries/grid/useEstablishWebsocketConnection.d.ts.map +1 -1
- package/dist/synapse-queries/grid/useEstablishWebsocketConnection.js.map +1 -1
- package/dist/synapse-queries/grid/useExportGrid.js.map +1 -1
- package/dist/synapse-queries/grid/useGridSession.js.map +1 -1
- package/dist/synapse-queries/grid/useImportCsvIntoGrid.js.map +1 -1
- package/dist/synapse-queries/subscription/useSubscription.js.map +1 -1
- package/dist/synapse-queries/table/useGetCsvPreview.js.map +1 -1
- package/dist/synapse-queries/table/useTableUpdateTransaction.js.map +1 -1
- package/dist/synapse-queries/team/useTeamMembers.js.map +1 -1
- package/dist/synapse-queries/user/useGetUserChallenges.js.map +1 -1
- package/dist/synapse-queries/user/useUserBundle.js.map +1 -1
- package/dist/synapse-queries/user/useUserGroupHeader.js.map +1 -1
- package/dist/testutils/ReactQueryMockUtils.js.map +1 -1
- package/dist/theme/ThemeProvider.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/utils/AppUtils/session/SynapseSessionManager.js.map +1 -1
- package/dist/utils/AppUtils/session/useSessionManager.js.map +1 -1
- package/dist/utils/PermissionLevelToAccessType.js.map +1 -1
- package/dist/utils/challenge/evaluation/EvaluationUtils.js.map +1 -1
- package/dist/utils/context/SynapseContext.js.map +1 -1
- package/dist/utils/functions/AccessControlListUtils.d.ts +4 -0
- package/dist/utils/functions/AccessControlListUtils.d.ts.map +1 -1
- package/dist/utils/functions/AccessControlListUtils.js +12 -1
- package/dist/utils/functions/AccessControlListUtils.js.map +1 -1
- package/dist/utils/functions/GridApiUtils.js.map +1 -1
- package/dist/utils/functions/QueryFilterUtils.js.map +1 -1
- package/dist/utils/functions/RealmUtils.d.ts +4 -0
- package/dist/utils/functions/RealmUtils.d.ts.map +1 -1
- package/dist/utils/functions/RealmUtils.js +9 -3
- package/dist/utils/functions/RealmUtils.js.map +1 -1
- package/dist/utils/functions/SanitizeHtmlUtils.js.map +1 -1
- package/dist/utils/functions/SanitizeHtmlUtils.test-utils.js.map +1 -1
- package/dist/utils/functions/SqlFunctions.js.map +1 -1
- package/dist/utils/functions/StringUtils.js.map +1 -1
- package/dist/utils/functions/deepLinkingUtils.js.map +1 -1
- package/dist/utils/functions/getDataFromFromStorage.js.map +1 -1
- package/dist/utils/functions/getEndpoint.js.map +1 -1
- package/dist/utils/functions/getUserData.js.map +1 -1
- package/dist/utils/functions/queryUtils.js.map +1 -1
- package/dist/utils/functions/testDownloadSpeed.js.map +1 -1
- package/dist/utils/hooks/useConfirmItems.js.map +1 -1
- package/dist/utils/hooks/useCookiePreferences.js.map +1 -1
- package/dist/utils/hooks/useCreateShortUrl.js.map +1 -1
- package/dist/utils/hooks/useDetectSSOCode.js.map +1 -1
- package/dist/utils/hooks/useDirectDownloadHandler.js.map +1 -1
- package/dist/utils/hooks/useGetGoalData.js.map +1 -1
- package/dist/utils/hooks/useGetInfoFromIds.js.map +1 -1
- package/dist/utils/hooks/useImageUrlUtils.js.map +1 -1
- package/dist/utils/hooks/useImmutableTableQuery/useImmutableTableQuery.js.map +1 -1
- package/dist/utils/hooks/useImmutableTableQuery/useTableQueryReducer.js.map +1 -1
- package/dist/utils/hooks/useIsBot.js.map +1 -1
- package/dist/utils/hooks/useListState.js.map +1 -1
- package/dist/utils/hooks/useLogin.d.ts.map +1 -1
- package/dist/utils/hooks/useLogin.js +53 -52
- package/dist/utils/hooks/useLogin.js.map +1 -1
- package/dist/utils/hooks/useMutuallyExclusiveState.js.map +1 -1
- package/dist/utils/hooks/useOverlay.js.map +1 -1
- package/dist/utils/hooks/usePreFetchResource.js.map +1 -1
- package/dist/utils/hooks/useQuerySearchParam.js.map +1 -1
- package/dist/utils/hooks/useScrollFadeTransition.js.map +1 -1
- package/dist/utils/hooks/useSet.js.map +1 -1
- package/dist/utils/hooks/useSourceAppConfigs.js.map +1 -1
- package/dist/utils/hooks/useTableImageUrl.js.map +1 -1
- package/dist/utils/hooks/useUploadFileEntity/useCreatePathsAndGetParentId.js.map +1 -1
- package/dist/utils/hooks/useUploadFileEntity/useLinkFileEntityToURL.js.map +1 -1
- package/dist/utils/hooks/useUploadFileEntity/usePrepareFileEntityUpload.js.map +1 -1
- package/dist/utils/hooks/useUploadFileEntity/useTrackFileUploads.js.map +1 -1
- package/dist/utils/hooks/useUploadFileEntity/useUploadFileEntities.js.map +1 -1
- package/dist/utils/hooks/useUploadFileEntity/useUploadFiles.js.map +1 -1
- package/dist/utils/hooks/useUploadFileEntity/willUploadsExceedStorageLimit.js.map +1 -1
- package/dist/utils/html/TargetEnum.js.map +1 -1
- package/dist/utils/jsonschema/SchemaAnnotationUtils.js.map +1 -1
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ColumnModelForm.js","names":[],"sources":["../../../src/components/TableColumnSchemaEditor/ColumnModelForm.tsx"],"sourcesContent":["import { convertToConcreteEntityType } from '@/utils/functions/EntityTypeUtils'\nimport { InfoTwoTone } from '@mui/icons-material'\nimport {\n Box,\n Checkbox,\n FormControl,\n Link,\n MenuItem,\n Select,\n SxProps,\n TextField,\n Tooltip,\n} from '@mui/material'\nimport FormHelperText from '@mui/material/FormHelperText'\nimport { EntityType } from '@sage-bionetworks/synapse-client'\nimport {\n ColumnModel,\n ColumnTypeEnum,\n FacetType,\n VIEW_CONCRETE_TYPE_VALUES,\n FacetColumnSortConfig,\n} from '@sage-bionetworks/synapse-types'\nimport { useAtomValue, useSetAtom } from 'jotai'\nimport { selectAtom } from 'jotai/utils'\nimport { isArray, isEmpty, isEqual } from 'lodash-es'\nimport { useMemo } from 'react'\nimport { ZodIssue } from 'zod'\nimport DefaultValueField from './ColumnModelFormFields/DefaultValueField'\nimport { FieldWithRecommendedMinimum } from './ColumnModelFormFields/FieldWithRecommendedMinimum'\nimport MultiValueField from './ColumnModelFormFields/MultiValueField'\nimport {\n canHaveDefault,\n canHaveMaxListLength,\n canHaveRestrictedValues,\n canHaveSize,\n configureFacetsForType,\n getAllowedColumnTypes,\n getColumnTypeFriendlyName,\n getFacetTypeFriendlyName,\n getMaxSizeForType,\n} from './TableColumnSchemaEditorUtils'\nimport { HIERARCHY_VERTICAL_LINE_COMPONENT } from './TableColumnSchemaForm'\nimport { tableColumnSchemaFormDataAtom } from './TableColumnSchemaFormReducer'\nimport {\n ColumnModelFormData,\n JsonSubColumnModelFormData,\n} from './Validators/ColumnModelValidator'\n\ntype ColumnModelFormProps = {\n entityType: EntityType\n columnModelIndex: number\n jsonSubColumnIndex?: number\n /* Default Columns are read-only, except for the facetType */\n isDefaultColumn: boolean\n disabled?: boolean\n /* Can be used to override the schema used for validating ColumnModels */\n validationErrors?: ZodIssue[] | null\n defaultAnnotationModel?: ColumnModel | null\n originalColumnModel?: ColumnModel | null\n}\nconst jsonSubColumnFieldSx: SxProps = {\n height: '28px',\n fontSize: '12px',\n}\nconst topLevelColumnModelFieldSx: SxProps = {\n height: '38px',\n fontSize: '14px',\n}\n\nfunction renderDefaultValue(\n defaultValue: string | unknown[] | undefined,\n _columnType: ColumnTypeEnum,\n): string {\n if (defaultValue == null) {\n return ''\n }\n\n if (isArray(defaultValue)) {\n return defaultValue.map(String).join(', ')\n }\n return defaultValue\n}\n\n// Helper type for the combined sort configuration value\ntype FacetSortValue =\n | 'FREQUENCY_DESC'\n | 'FREQUENCY_ASC'\n | 'VALUE_DESC'\n | 'VALUE_ASC'\n | ''\n\n/**\n * Converts a FacetColumnSortConfig object to a single string value for the select dropdown\n */\nfunction facetSortConfigToValue(\n config: FacetColumnSortConfig | undefined,\n): FacetSortValue {\n if (!config || (!config.property && !config.direction)) {\n return ''\n }\n const property = config.property || 'FREQUENCY'\n const direction = config.direction || 'DESC'\n return `${property}_${direction}` as FacetSortValue\n}\n\n/**\n * Converts a select dropdown value to a FacetColumnSortConfig object\n */\nfunction valueToFacetSortConfig(\n value: FacetSortValue,\n): FacetColumnSortConfig | undefined {\n if (!value) {\n return undefined\n }\n const [property, direction] = value.split('_') as [\n 'FREQUENCY' | 'VALUE',\n 'DESC' | 'ASC',\n ]\n return { property, direction }\n}\n\n/*\n * Disable immediate MUI/Emotion style injection because it causes performance issues when adding many columns at once.\n * This can be a common occurence when adding annotation columns\n */\nconst DISABLE_INJECTING_GLOBAL_STYLES_VALUE = true\n\nexport default function ColumnModelForm(props: ColumnModelFormProps) {\n const {\n columnModelIndex,\n jsonSubColumnIndex,\n entityType,\n isDefaultColumn,\n disabled = false,\n validationErrors = null,\n defaultAnnotationModel,\n originalColumnModel,\n } = props\n const isJsonSubColumn = jsonSubColumnIndex != undefined\n const dispatch = useSetAtom(tableColumnSchemaFormDataAtom)\n const isView = (VIEW_CONCRETE_TYPE_VALUES as readonly string[]).includes(\n convertToConcreteEntityType(entityType),\n )\n\n const columnModelAtom = useMemo(\n () =>\n selectAtom(\n tableColumnSchemaFormDataAtom,\n v =>\n isJsonSubColumn\n ? v[columnModelIndex].jsonSubColumns![jsonSubColumnIndex]\n : v[columnModelIndex],\n isEqual,\n ),\n [columnModelIndex, isJsonSubColumn, jsonSubColumnIndex],\n )\n\n const columnModel = useAtomValue(columnModelAtom)\n\n const allowedColumnTypes = useMemo(\n () => getAllowedColumnTypes(isView, isJsonSubColumn),\n [isView, isJsonSubColumn],\n )\n\n const allowedFacetTypes = useMemo(\n () => configureFacetsForType(columnModel.columnType, isJsonSubColumn),\n [columnModel.columnType, isJsonSubColumn],\n )\n const fieldSx: SxProps = useMemo(\n () => (isJsonSubColumn ? jsonSubColumnFieldSx : topLevelColumnModelFieldSx),\n [isJsonSubColumn],\n )\n\n const errorsByField = useMemo(() => {\n if (validationErrors && isArray(validationErrors)) {\n const errorsByField: Record<string, string> = {}\n validationErrors.forEach(e => {\n if (e.path) {\n errorsByField[e.path[e.path.length - 1]] = e.message\n }\n })\n return errorsByField\n }\n return {}\n }, [validationErrors])\n\n return (\n <>\n <Box\n sx={{\n display: 'grid',\n gridColumn: '1 / span 11',\n gridTemplateColumns: 'subgrid',\n }}\n >\n {isJsonSubColumn && (\n <Box sx={{ gridColumn: '1 / span 1' }}>\n {HIERARCHY_VERTICAL_LINE_COMPONENT}\n </Box>\n )}\n <Box\n data-testid={`ColumnModelForm`}\n sx={{\n display: 'flex',\n alignItems: 'start',\n gridColumn: isJsonSubColumn ? '2 / span 1' : ' 1 / span 1',\n // Checkbox is offset from top; vertical centering causes issues when validation errors are displayed\n mt: isJsonSubColumn ? '0px' : '5px',\n }}\n >\n <Checkbox\n checked={columnModel.isSelected}\n inputProps={{ 'aria-label': 'Select' }}\n disabled={disabled}\n onChange={() => {\n dispatch({\n type: 'toggleSelect',\n columnModelIndex,\n jsonSubColumnModelIndex: jsonSubColumnIndex,\n })\n }}\n />\n </Box>\n <Box\n sx={{\n my: isDefaultColumn ? 'auto' : undefined,\n gridColumn: isJsonSubColumn\n ? /* If this is a JSON Subcolumn, we reduce the width of this grid column to create space to render the visual hierarchical line */\n '3 / span 1'\n : /* Otherwise, span across both grid columns */\n '2 / span 2',\n }}\n >\n {isDefaultColumn ? (\n columnModel.name\n ) : (\n <TextField\n value={columnModel.name}\n placeholder={isJsonSubColumn ? 'Facet name' : 'Column name'}\n onChange={e => {\n dispatch({\n type: 'setColumnModelValue',\n columnModelIndex,\n jsonSubColumnModelIndex: jsonSubColumnIndex,\n value: {\n ...columnModel,\n name: e.target.value,\n },\n })\n }}\n disabled={disabled}\n fullWidth\n error={!!errorsByField['name']}\n helperText={errorsByField['name']}\n slotProps={{\n input: {\n disableInjectingGlobalStyles:\n DISABLE_INJECTING_GLOBAL_STYLES_VALUE,\n sx: fieldSx,\n slotProps: {\n input: {\n 'aria-label': 'Name',\n },\n },\n },\n }}\n />\n )}\n </Box>\n <Box\n sx={{\n my: isDefaultColumn ? 'auto' : undefined,\n }}\n >\n {isDefaultColumn ? (\n getColumnTypeFriendlyName(columnModel.columnType)\n ) : (\n <FormControl fullWidth>\n <Select\n label=\"Column Type\"\n value={columnModel.columnType}\n onChange={e => {\n dispatch({\n type: 'changeColumnModelType',\n columnModelIndex,\n jsonSubColumnModelIndex: jsonSubColumnIndex,\n newColumnType: e.target.value as ColumnTypeEnum,\n })\n }}\n slotProps={{\n input: {\n 'aria-label': 'Column Type',\n },\n }}\n sx={fieldSx}\n disabled={disabled}\n error={!!errorsByField['columnType']}\n >\n {allowedColumnTypes.map(value => {\n return (\n <MenuItem value={value} key={value}>\n {getColumnTypeFriendlyName(value)}\n </MenuItem>\n )\n })}\n </Select>\n {errorsByField['columnType'] && (\n <FormHelperText color={'error.main'}>\n {errorsByField['columnType']}\n </FormHelperText>\n )}\n </FormControl>\n )}\n </Box>\n <Box\n sx={{\n my: isDefaultColumn ? 'auto' : undefined,\n }}\n >\n {isDefaultColumn ? (\n (columnModel as ColumnModelFormData).maximumSize ?? ''\n ) : (\n <FieldWithRecommendedMinimum\n value={(columnModel as ColumnModelFormData).maximumSize ?? ''}\n originalValue={originalColumnModel?.maximumSize}\n recommendedValue={defaultAnnotationModel?.maximumSize}\n columnType={columnModel.columnType as ColumnTypeEnum}\n disabled={disabled || !canHaveSize(columnModel.columnType)}\n InputProps={{\n disableInjectingGlobalStyles:\n DISABLE_INJECTING_GLOBAL_STYLES_VALUE,\n\n slotProps: {\n input: {\n 'aria-label': 'Maximum Size',\n min: 1,\n max: canHaveSize(columnModel.columnType)\n ? getMaxSizeForType(columnModel.columnType)\n : undefined,\n },\n },\n sx: fieldSx,\n }}\n onChange={e => {\n dispatch({\n type: 'setColumnModelValue',\n columnModelIndex,\n jsonSubColumnModelIndex: jsonSubColumnIndex,\n value: {\n ...columnModel,\n maximumSize: e.target.value,\n },\n })\n }}\n fullWidth\n error={!!errorsByField['maximumSize']}\n helperText={errorsByField['maximumSize']}\n />\n )}\n </Box>\n <Box\n sx={{\n my: isDefaultColumn ? 'auto' : undefined,\n }}\n >\n {isDefaultColumn ? (\n (columnModel as ColumnModelFormData).maximumListLength ?? ''\n ) : (\n <FieldWithRecommendedMinimum\n value={\n (columnModel as ColumnModelFormData).maximumListLength ?? ''\n }\n originalValue={originalColumnModel?.maximumListLength}\n recommendedValue={defaultAnnotationModel?.maximumListLength}\n columnType={columnModel.columnType as ColumnTypeEnum}\n disabled={\n disabled || !canHaveMaxListLength(columnModel.columnType)\n }\n onChange={e => {\n dispatch({\n type: 'setColumnModelValue',\n columnModelIndex,\n jsonSubColumnModelIndex: jsonSubColumnIndex,\n value: {\n ...columnModel,\n maximumListLength: e.target.value,\n },\n })\n }}\n InputProps={{\n disableInjectingGlobalStyles:\n DISABLE_INJECTING_GLOBAL_STYLES_VALUE,\n slotProps: {\n input: {\n 'aria-label': 'Maximum List Length',\n },\n },\n sx: fieldSx,\n }}\n fullWidth\n error={!!errorsByField['maximumListLength']}\n helperText={errorsByField['maximumListLength']}\n />\n )}\n </Box>\n <Box\n sx={{\n my: isDefaultColumn ? 'auto' : undefined,\n }}\n >\n {isDefaultColumn ? (\n renderDefaultValue(\n (columnModel as ColumnModelFormData)?.defaultValue,\n columnModel.columnType as ColumnTypeEnum,\n )\n ) : (\n <DefaultValueField\n TextFieldProps={{\n InputProps: {\n disableInjectingGlobalStyles:\n DISABLE_INJECTING_GLOBAL_STYLES_VALUE,\n slotProps: {\n input: {\n 'aria-label': 'Default Value',\n },\n },\n sx: fieldSx,\n },\n fullWidth: true,\n error: !!errorsByField['defaultValue'],\n helperText: errorsByField['defaultValue'],\n }}\n SelectProps={{\n label: 'Default Value',\n sx: fieldSx,\n slotProps: {\n input: {\n 'aria-label': 'Default Value',\n },\n },\n error: !!errorsByField['defaultValue'],\n }}\n selectFormHelperText={errorsByField['defaultValue']}\n columnModel={columnModel as ColumnModelFormData}\n value={(columnModel as ColumnModelFormData)?.defaultValue || null}\n onChange={value => {\n dispatch({\n type: 'setColumnModelValue',\n columnModelIndex,\n jsonSubColumnModelIndex: jsonSubColumnIndex,\n value: {\n ...columnModel,\n defaultValue: value || undefined,\n },\n })\n }}\n disabled={\n disabled ||\n !canHaveDefault(columnModel.columnType, isView, isJsonSubColumn)\n }\n />\n )}\n </Box>\n <Box>\n <MultiValueField\n value={(columnModel as ColumnModelFormData)?.enumValues}\n onChange={newValue => {\n dispatch({\n type: 'setColumnModelValue',\n columnModelIndex,\n jsonSubColumnModelIndex: jsonSubColumnIndex,\n value: {\n ...columnModel,\n enumValues:\n newValue == null || isEmpty(newValue)\n ? undefined\n : newValue,\n },\n })\n }}\n columnType={columnModel.columnType as ColumnTypeEnum}\n TextFieldProps={{\n fullWidth: true,\n disabled:\n disabled ||\n !canHaveRestrictedValues(\n columnModel.columnType,\n isJsonSubColumn,\n ),\n InputProps: {\n disableInjectingGlobalStyles:\n DISABLE_INJECTING_GLOBAL_STYLES_VALUE,\n // Is readOnly because edits are made with the JSONArrayEditorModal\n readOnly: true,\n sx: fieldSx,\n slotProps: {\n input: {\n 'aria-label': 'Restrict Values',\n },\n },\n },\n error: !!errorsByField['enumValues'],\n helperText: errorsByField['enumValues'],\n }}\n />\n </Box>\n <Box>\n <FormControl fullWidth>\n <Select\n label=\"Facet Type\"\n value={columnModel.facetType || ''}\n disabled={disabled || allowedFacetTypes === null}\n onChange={e => {\n dispatch({\n type: 'setColumnModelValue',\n columnModelIndex,\n jsonSubColumnModelIndex: jsonSubColumnIndex,\n value: {\n ...columnModel,\n facetType: e.target.value as FacetType,\n },\n })\n }}\n sx={fieldSx}\n slotProps={{\n input: {\n 'aria-label': 'Facet Type',\n },\n }}\n error={!!errorsByField['facetType']}\n >\n {(allowedFacetTypes ?? []).map((value, index) => {\n return (\n <MenuItem value={value} key={index}>\n {value === undefined ? '' : getFacetTypeFriendlyName(value)}\n </MenuItem>\n )\n })}\n </Select>\n {errorsByField['facetType'] && (\n <FormHelperText color={'error.main'}>\n {errorsByField['facetType']}\n </FormHelperText>\n )}\n </FormControl>\n </Box>\n <Box>\n <FormControl fullWidth>\n <Select\n label=\"Sort Facet Values\"\n value={facetSortConfigToValue(\n 'facetSortConfig' in columnModel\n ? columnModel.facetSortConfig\n : undefined,\n )}\n disabled={disabled || columnModel.facetType !== 'enumeration'}\n onChange={e => {\n dispatch({\n type: 'setColumnModelValue',\n columnModelIndex,\n jsonSubColumnModelIndex: jsonSubColumnIndex,\n value: {\n ...columnModel,\n facetSortConfig: valueToFacetSortConfig(\n e.target.value as FacetSortValue,\n ),\n },\n })\n }}\n sx={fieldSx}\n slotProps={{\n input: {\n 'aria-label': 'Sort Facet Values',\n },\n }}\n error={!!errorsByField['facetSortConfig']}\n >\n <MenuItem value=\"FREQUENCY_DESC\">Frequency Descending</MenuItem>\n <MenuItem value=\"FREQUENCY_ASC\">Frequency Ascending</MenuItem>\n <MenuItem value=\"VALUE_DESC\">Value Descending</MenuItem>\n <MenuItem value=\"VALUE_ASC\">Value Ascending</MenuItem>\n </Select>\n {errorsByField['facetSortConfig'] && (\n <FormHelperText color={'error.main'}>\n {errorsByField['facetSortConfig']}\n </FormHelperText>\n )}\n </FormControl>\n </Box>\n </Box>\n {isJsonSubColumn && (\n <Box\n sx={{\n display: 'grid',\n gridColumn: '1 / span 11',\n gridTemplateColumns: 'subgrid',\n }}\n >\n <Box\n sx={{\n gridColumn: '1 / span 1',\n }}\n >\n {HIERARCHY_VERTICAL_LINE_COMPONENT}\n </Box>\n <Box></Box>\n <Box\n sx={{\n gridColumn: '3 / span 7',\n }}\n >\n <TextField\n placeholder={'JSON Path'}\n value={(columnModel as JsonSubColumnModelFormData).jsonPath}\n onChange={e => {\n dispatch({\n type: 'setColumnModelValue',\n columnModelIndex,\n jsonSubColumnModelIndex: jsonSubColumnIndex,\n value: {\n ...(columnModel as JsonSubColumnModelFormData),\n jsonPath: e.target.value,\n },\n })\n }}\n disabled={disabled}\n fullWidth\n slotProps={{\n input: {\n disableInjectingGlobalStyles:\n DISABLE_INJECTING_GLOBAL_STYLES_VALUE,\n sx: fieldSx,\n endAdornment: (\n <Tooltip\n title={\n <>\n <p>\n <Link\n href={\n 'https://dev.mysql.com/doc/refman/8.0/en/json.html#json-path-syntax'\n }\n >\n Please use a valid JSON Path selector, following\n this format.\n </Link>\n </p>\n <p>\n This field is for linking the sub-column facet to\n the corresponding location in the JSON data, so that\n it can be used as facet filter. The correct selector\n will point to the key referenced in the sub-column\n JSON Path.\n </p>\n </>\n }\n >\n <InfoTwoTone sx={{ color: 'grey.700' }} />\n </Tooltip>\n ),\n slotProps: {\n input: { 'aria-label': 'JSON Path' },\n },\n },\n }}\n error={!!errorsByField['jsonPath']}\n helperText={errorsByField['jsonPath']}\n />\n </Box>\n </Box>\n )}\n </>\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ColumnModelForm.js","names":[],"sources":["../../../src/components/TableColumnSchemaEditor/ColumnModelForm.tsx"],"sourcesContent":["import { convertToConcreteEntityType } from '@/utils/functions/EntityTypeUtils'\nimport { InfoTwoTone } from '@mui/icons-material'\nimport {\n Box,\n Checkbox,\n FormControl,\n Link,\n MenuItem,\n Select,\n SxProps,\n TextField,\n Tooltip,\n} from '@mui/material'\nimport FormHelperText from '@mui/material/FormHelperText'\nimport { EntityType } from '@sage-bionetworks/synapse-client'\nimport {\n ColumnModel,\n ColumnTypeEnum,\n FacetType,\n VIEW_CONCRETE_TYPE_VALUES,\n FacetColumnSortConfig,\n} from '@sage-bionetworks/synapse-types'\nimport { useAtomValue, useSetAtom } from 'jotai'\nimport { selectAtom } from 'jotai/utils'\nimport { isArray, isEmpty, isEqual } from 'lodash-es'\nimport { useMemo } from 'react'\nimport { ZodIssue } from 'zod'\nimport DefaultValueField from './ColumnModelFormFields/DefaultValueField'\nimport { FieldWithRecommendedMinimum } from './ColumnModelFormFields/FieldWithRecommendedMinimum'\nimport MultiValueField from './ColumnModelFormFields/MultiValueField'\nimport {\n canHaveDefault,\n canHaveMaxListLength,\n canHaveRestrictedValues,\n canHaveSize,\n configureFacetsForType,\n getAllowedColumnTypes,\n getColumnTypeFriendlyName,\n getFacetTypeFriendlyName,\n getMaxSizeForType,\n} from './TableColumnSchemaEditorUtils'\nimport { HIERARCHY_VERTICAL_LINE_COMPONENT } from './TableColumnSchemaForm'\nimport { tableColumnSchemaFormDataAtom } from './TableColumnSchemaFormReducer'\nimport {\n ColumnModelFormData,\n JsonSubColumnModelFormData,\n} from './Validators/ColumnModelValidator'\n\ntype ColumnModelFormProps = {\n entityType: EntityType\n columnModelIndex: number\n jsonSubColumnIndex?: number\n /* Default Columns are read-only, except for the facetType */\n isDefaultColumn: boolean\n disabled?: boolean\n /* Can be used to override the schema used for validating ColumnModels */\n validationErrors?: ZodIssue[] | null\n defaultAnnotationModel?: ColumnModel | null\n originalColumnModel?: ColumnModel | null\n}\nconst jsonSubColumnFieldSx: SxProps = {\n height: '28px',\n fontSize: '12px',\n}\nconst topLevelColumnModelFieldSx: SxProps = {\n height: '38px',\n fontSize: '14px',\n}\n\nfunction renderDefaultValue(\n defaultValue: string | unknown[] | undefined,\n _columnType: ColumnTypeEnum,\n): string {\n if (defaultValue == null) {\n return ''\n }\n\n if (isArray(defaultValue)) {\n return defaultValue.map(String).join(', ')\n }\n return defaultValue\n}\n\n// Helper type for the combined sort configuration value\ntype FacetSortValue =\n | 'FREQUENCY_DESC'\n | 'FREQUENCY_ASC'\n | 'VALUE_DESC'\n | 'VALUE_ASC'\n | ''\n\n/**\n * Converts a FacetColumnSortConfig object to a single string value for the select dropdown\n */\nfunction facetSortConfigToValue(\n config: FacetColumnSortConfig | undefined,\n): FacetSortValue {\n if (!config || (!config.property && !config.direction)) {\n return ''\n }\n const property = config.property || 'FREQUENCY'\n const direction = config.direction || 'DESC'\n return `${property}_${direction}` as FacetSortValue\n}\n\n/**\n * Converts a select dropdown value to a FacetColumnSortConfig object\n */\nfunction valueToFacetSortConfig(\n value: FacetSortValue,\n): FacetColumnSortConfig | undefined {\n if (!value) {\n return undefined\n }\n const [property, direction] = value.split('_') as [\n 'FREQUENCY' | 'VALUE',\n 'DESC' | 'ASC',\n ]\n return { property, direction }\n}\n\n/*\n * Disable immediate MUI/Emotion style injection because it causes performance issues when adding many columns at once.\n * This can be a common occurence when adding annotation columns\n */\nconst DISABLE_INJECTING_GLOBAL_STYLES_VALUE = true\n\nexport default function ColumnModelForm(props: ColumnModelFormProps) {\n const {\n columnModelIndex,\n jsonSubColumnIndex,\n entityType,\n isDefaultColumn,\n disabled = false,\n validationErrors = null,\n defaultAnnotationModel,\n originalColumnModel,\n } = props\n const isJsonSubColumn = jsonSubColumnIndex != undefined\n const dispatch = useSetAtom(tableColumnSchemaFormDataAtom)\n const isView = (VIEW_CONCRETE_TYPE_VALUES as readonly string[]).includes(\n convertToConcreteEntityType(entityType),\n )\n\n const columnModelAtom = useMemo(\n () =>\n selectAtom(\n tableColumnSchemaFormDataAtom,\n v =>\n isJsonSubColumn\n ? v[columnModelIndex].jsonSubColumns![jsonSubColumnIndex]\n : v[columnModelIndex],\n isEqual,\n ),\n [columnModelIndex, isJsonSubColumn, jsonSubColumnIndex],\n )\n\n const columnModel = useAtomValue(columnModelAtom)\n\n const allowedColumnTypes = useMemo(\n () => getAllowedColumnTypes(isView, isJsonSubColumn),\n [isView, isJsonSubColumn],\n )\n\n const allowedFacetTypes = useMemo(\n () => configureFacetsForType(columnModel.columnType, isJsonSubColumn),\n [columnModel.columnType, isJsonSubColumn],\n )\n const fieldSx: SxProps = useMemo(\n () => (isJsonSubColumn ? jsonSubColumnFieldSx : topLevelColumnModelFieldSx),\n [isJsonSubColumn],\n )\n\n const errorsByField = useMemo(() => {\n if (validationErrors && isArray(validationErrors)) {\n const errorsByField: Record<string, string> = {}\n validationErrors.forEach(e => {\n if (e.path) {\n errorsByField[e.path[e.path.length - 1]] = e.message\n }\n })\n return errorsByField\n }\n return {}\n }, [validationErrors])\n\n return (\n <>\n <Box\n sx={{\n display: 'grid',\n gridColumn: '1 / span 11',\n gridTemplateColumns: 'subgrid',\n }}\n >\n {isJsonSubColumn && (\n <Box sx={{ gridColumn: '1 / span 1' }}>\n {HIERARCHY_VERTICAL_LINE_COMPONENT}\n </Box>\n )}\n <Box\n data-testid={`ColumnModelForm`}\n sx={{\n display: 'flex',\n alignItems: 'start',\n gridColumn: isJsonSubColumn ? '2 / span 1' : ' 1 / span 1',\n // Checkbox is offset from top; vertical centering causes issues when validation errors are displayed\n mt: isJsonSubColumn ? '0px' : '5px',\n }}\n >\n <Checkbox\n checked={columnModel.isSelected}\n inputProps={{ 'aria-label': 'Select' }}\n disabled={disabled}\n onChange={() => {\n dispatch({\n type: 'toggleSelect',\n columnModelIndex,\n jsonSubColumnModelIndex: jsonSubColumnIndex,\n })\n }}\n />\n </Box>\n <Box\n sx={{\n my: isDefaultColumn ? 'auto' : undefined,\n gridColumn: isJsonSubColumn\n ? /* If this is a JSON Subcolumn, we reduce the width of this grid column to create space to render the visual hierarchical line */\n '3 / span 1'\n : /* Otherwise, span across both grid columns */\n '2 / span 2',\n }}\n >\n {isDefaultColumn ? (\n columnModel.name\n ) : (\n <TextField\n value={columnModel.name}\n placeholder={isJsonSubColumn ? 'Facet name' : 'Column name'}\n onChange={e => {\n dispatch({\n type: 'setColumnModelValue',\n columnModelIndex,\n jsonSubColumnModelIndex: jsonSubColumnIndex,\n value: {\n ...columnModel,\n name: e.target.value,\n },\n })\n }}\n disabled={disabled}\n fullWidth\n error={!!errorsByField['name']}\n helperText={errorsByField['name']}\n slotProps={{\n input: {\n disableInjectingGlobalStyles:\n DISABLE_INJECTING_GLOBAL_STYLES_VALUE,\n sx: fieldSx,\n slotProps: {\n input: {\n 'aria-label': 'Name',\n },\n },\n },\n }}\n />\n )}\n </Box>\n <Box\n sx={{\n my: isDefaultColumn ? 'auto' : undefined,\n }}\n >\n {isDefaultColumn ? (\n getColumnTypeFriendlyName(columnModel.columnType)\n ) : (\n <FormControl fullWidth>\n <Select\n label=\"Column Type\"\n value={columnModel.columnType}\n onChange={e => {\n dispatch({\n type: 'changeColumnModelType',\n columnModelIndex,\n jsonSubColumnModelIndex: jsonSubColumnIndex,\n newColumnType: e.target.value as ColumnTypeEnum,\n })\n }}\n slotProps={{\n input: {\n 'aria-label': 'Column Type',\n },\n }}\n sx={fieldSx}\n disabled={disabled}\n error={!!errorsByField['columnType']}\n >\n {allowedColumnTypes.map(value => {\n return (\n <MenuItem value={value} key={value}>\n {getColumnTypeFriendlyName(value)}\n </MenuItem>\n )\n })}\n </Select>\n {errorsByField['columnType'] && (\n <FormHelperText color={'error.main'}>\n {errorsByField['columnType']}\n </FormHelperText>\n )}\n </FormControl>\n )}\n </Box>\n <Box\n sx={{\n my: isDefaultColumn ? 'auto' : undefined,\n }}\n >\n {isDefaultColumn ? (\n (columnModel as ColumnModelFormData).maximumSize ?? ''\n ) : (\n <FieldWithRecommendedMinimum\n value={(columnModel as ColumnModelFormData).maximumSize ?? ''}\n originalValue={originalColumnModel?.maximumSize}\n recommendedValue={defaultAnnotationModel?.maximumSize}\n columnType={columnModel.columnType as ColumnTypeEnum}\n disabled={disabled || !canHaveSize(columnModel.columnType)}\n InputProps={{\n disableInjectingGlobalStyles:\n DISABLE_INJECTING_GLOBAL_STYLES_VALUE,\n\n slotProps: {\n input: {\n 'aria-label': 'Maximum Size',\n min: 1,\n max: canHaveSize(columnModel.columnType)\n ? getMaxSizeForType(columnModel.columnType)\n : undefined,\n },\n },\n sx: fieldSx,\n }}\n onChange={e => {\n dispatch({\n type: 'setColumnModelValue',\n columnModelIndex,\n jsonSubColumnModelIndex: jsonSubColumnIndex,\n value: {\n ...columnModel,\n maximumSize: e.target.value,\n },\n })\n }}\n fullWidth\n error={!!errorsByField['maximumSize']}\n helperText={errorsByField['maximumSize']}\n />\n )}\n </Box>\n <Box\n sx={{\n my: isDefaultColumn ? 'auto' : undefined,\n }}\n >\n {isDefaultColumn ? (\n (columnModel as ColumnModelFormData).maximumListLength ?? ''\n ) : (\n <FieldWithRecommendedMinimum\n value={\n (columnModel as ColumnModelFormData).maximumListLength ?? ''\n }\n originalValue={originalColumnModel?.maximumListLength}\n recommendedValue={defaultAnnotationModel?.maximumListLength}\n columnType={columnModel.columnType as ColumnTypeEnum}\n disabled={\n disabled || !canHaveMaxListLength(columnModel.columnType)\n }\n onChange={e => {\n dispatch({\n type: 'setColumnModelValue',\n columnModelIndex,\n jsonSubColumnModelIndex: jsonSubColumnIndex,\n value: {\n ...columnModel,\n maximumListLength: e.target.value,\n },\n })\n }}\n InputProps={{\n disableInjectingGlobalStyles:\n DISABLE_INJECTING_GLOBAL_STYLES_VALUE,\n slotProps: {\n input: {\n 'aria-label': 'Maximum List Length',\n },\n },\n sx: fieldSx,\n }}\n fullWidth\n error={!!errorsByField['maximumListLength']}\n helperText={errorsByField['maximumListLength']}\n />\n )}\n </Box>\n <Box\n sx={{\n my: isDefaultColumn ? 'auto' : undefined,\n }}\n >\n {isDefaultColumn ? (\n renderDefaultValue(\n (columnModel as ColumnModelFormData)?.defaultValue,\n columnModel.columnType as ColumnTypeEnum,\n )\n ) : (\n <DefaultValueField\n TextFieldProps={{\n InputProps: {\n disableInjectingGlobalStyles:\n DISABLE_INJECTING_GLOBAL_STYLES_VALUE,\n slotProps: {\n input: {\n 'aria-label': 'Default Value',\n },\n },\n sx: fieldSx,\n },\n fullWidth: true,\n error: !!errorsByField['defaultValue'],\n helperText: errorsByField['defaultValue'],\n }}\n SelectProps={{\n label: 'Default Value',\n sx: fieldSx,\n slotProps: {\n input: {\n 'aria-label': 'Default Value',\n },\n },\n error: !!errorsByField['defaultValue'],\n }}\n selectFormHelperText={errorsByField['defaultValue']}\n columnModel={columnModel as ColumnModelFormData}\n value={(columnModel as ColumnModelFormData)?.defaultValue || null}\n onChange={value => {\n dispatch({\n type: 'setColumnModelValue',\n columnModelIndex,\n jsonSubColumnModelIndex: jsonSubColumnIndex,\n value: {\n ...columnModel,\n defaultValue: value || undefined,\n },\n })\n }}\n disabled={\n disabled ||\n !canHaveDefault(columnModel.columnType, isView, isJsonSubColumn)\n }\n />\n )}\n </Box>\n <Box>\n <MultiValueField\n value={(columnModel as ColumnModelFormData)?.enumValues}\n onChange={newValue => {\n dispatch({\n type: 'setColumnModelValue',\n columnModelIndex,\n jsonSubColumnModelIndex: jsonSubColumnIndex,\n value: {\n ...columnModel,\n enumValues:\n newValue == null || isEmpty(newValue)\n ? undefined\n : newValue,\n },\n })\n }}\n columnType={columnModel.columnType as ColumnTypeEnum}\n TextFieldProps={{\n fullWidth: true,\n disabled:\n disabled ||\n !canHaveRestrictedValues(\n columnModel.columnType,\n isJsonSubColumn,\n ),\n InputProps: {\n disableInjectingGlobalStyles:\n DISABLE_INJECTING_GLOBAL_STYLES_VALUE,\n // Is readOnly because edits are made with the JSONArrayEditorModal\n readOnly: true,\n sx: fieldSx,\n slotProps: {\n input: {\n 'aria-label': 'Restrict Values',\n },\n },\n },\n error: !!errorsByField['enumValues'],\n helperText: errorsByField['enumValues'],\n }}\n />\n </Box>\n <Box>\n <FormControl fullWidth>\n <Select\n label=\"Facet Type\"\n value={columnModel.facetType || ''}\n disabled={disabled || allowedFacetTypes === null}\n onChange={e => {\n dispatch({\n type: 'setColumnModelValue',\n columnModelIndex,\n jsonSubColumnModelIndex: jsonSubColumnIndex,\n value: {\n ...columnModel,\n facetType: e.target.value as FacetType,\n },\n })\n }}\n sx={fieldSx}\n slotProps={{\n input: {\n 'aria-label': 'Facet Type',\n },\n }}\n error={!!errorsByField['facetType']}\n >\n {(allowedFacetTypes ?? []).map((value, index) => {\n return (\n <MenuItem value={value} key={index}>\n {value === undefined ? '' : getFacetTypeFriendlyName(value)}\n </MenuItem>\n )\n })}\n </Select>\n {errorsByField['facetType'] && (\n <FormHelperText color={'error.main'}>\n {errorsByField['facetType']}\n </FormHelperText>\n )}\n </FormControl>\n </Box>\n <Box>\n <FormControl fullWidth>\n <Select\n label=\"Sort Facet Values\"\n value={facetSortConfigToValue(\n 'facetSortConfig' in columnModel\n ? columnModel.facetSortConfig\n : undefined,\n )}\n disabled={disabled || columnModel.facetType !== 'enumeration'}\n onChange={e => {\n dispatch({\n type: 'setColumnModelValue',\n columnModelIndex,\n jsonSubColumnModelIndex: jsonSubColumnIndex,\n value: {\n ...columnModel,\n facetSortConfig: valueToFacetSortConfig(\n e.target.value as FacetSortValue,\n ),\n },\n })\n }}\n sx={fieldSx}\n slotProps={{\n input: {\n 'aria-label': 'Sort Facet Values',\n },\n }}\n error={!!errorsByField['facetSortConfig']}\n >\n <MenuItem value=\"FREQUENCY_DESC\">Frequency Descending</MenuItem>\n <MenuItem value=\"FREQUENCY_ASC\">Frequency Ascending</MenuItem>\n <MenuItem value=\"VALUE_DESC\">Value Descending</MenuItem>\n <MenuItem value=\"VALUE_ASC\">Value Ascending</MenuItem>\n </Select>\n {errorsByField['facetSortConfig'] && (\n <FormHelperText color={'error.main'}>\n {errorsByField['facetSortConfig']}\n </FormHelperText>\n )}\n </FormControl>\n </Box>\n </Box>\n {isJsonSubColumn && (\n <Box\n sx={{\n display: 'grid',\n gridColumn: '1 / span 11',\n gridTemplateColumns: 'subgrid',\n }}\n >\n <Box\n sx={{\n gridColumn: '1 / span 1',\n }}\n >\n {HIERARCHY_VERTICAL_LINE_COMPONENT}\n </Box>\n <Box></Box>\n <Box\n sx={{\n gridColumn: '3 / span 7',\n }}\n >\n <TextField\n placeholder={'JSON Path'}\n value={(columnModel as JsonSubColumnModelFormData).jsonPath}\n onChange={e => {\n dispatch({\n type: 'setColumnModelValue',\n columnModelIndex,\n jsonSubColumnModelIndex: jsonSubColumnIndex,\n value: {\n ...(columnModel as JsonSubColumnModelFormData),\n jsonPath: e.target.value,\n },\n })\n }}\n disabled={disabled}\n fullWidth\n slotProps={{\n input: {\n disableInjectingGlobalStyles:\n DISABLE_INJECTING_GLOBAL_STYLES_VALUE,\n sx: fieldSx,\n endAdornment: (\n <Tooltip\n title={\n <>\n <p>\n <Link\n href={\n 'https://dev.mysql.com/doc/refman/8.0/en/json.html#json-path-syntax'\n }\n >\n Please use a valid JSON Path selector, following\n this format.\n </Link>\n </p>\n <p>\n This field is for linking the sub-column facet to\n the corresponding location in the JSON data, so that\n it can be used as facet filter. The correct selector\n will point to the key referenced in the sub-column\n JSON Path.\n </p>\n </>\n }\n >\n <InfoTwoTone sx={{ color: 'grey.700' }} />\n </Tooltip>\n ),\n slotProps: {\n input: { 'aria-label': 'JSON Path' },\n },\n },\n }}\n error={!!errorsByField['jsonPath']}\n helperText={errorsByField['jsonPath']}\n />\n </Box>\n </Box>\n )}\n </>\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AA4DA,IAAM,KAAgC;CACpC,QAAQ;CACR,UAAU;CACX,EACK,IAAsC;CAC1C,QAAQ;CACR,UAAU;CACX;AAED,SAAS,EACP,GACA,GACQ;AAQR,QAPI,KAAgB,OACX,KAGL,EAAQ,EAAa,GAChB,EAAa,IAAI,OAAO,CAAC,KAAK,KAAK,GAErC;;AAcT,SAAS,EACP,GACgB;AAMhB,QALI,CAAC,KAAW,CAAC,EAAO,YAAY,CAAC,EAAO,YACnC,KAIF,GAFU,EAAO,YAAY,YAEjB,GADD,EAAO,aAAa;;AAOxC,SAAS,EACP,GACmC;AACnC,KAAI,CAAC,EACH;CAEF,IAAM,CAAC,GAAU,KAAa,EAAM,MAAM,IAAI;AAI9C,QAAO;EAAE;EAAU;EAAW;;AAOhC,IAAM,IAAwC;AAE9C,SAAwB,EAAgB,GAA6B;CACnE,IAAM,EACJ,qBACA,uBACA,eACA,oBACA,cAAW,IACX,sBAAmB,MACnB,2BACA,2BACE,GACE,IAAkB,KAAsB,MACxC,IAAW,EAAW,EAA8B,EACpD,IAAU,EAAgD,SAC9D,EAA4B,EAAW,CACxC,EAeK,IAAc,EAbI,QAEpB,GACE,IACA,MACE,IACI,EAAE,GAAkB,eAAgB,KACpC,EAAE,IACR,EACD,EACH;EAAC;EAAkB;EAAiB;EAAmB,CAGxB,CAAgB,EAE3C,KAAqB,QACnB,EAAsB,GAAQ,EAAgB,EACpD,CAAC,GAAQ,EAAgB,CAC1B,EAEK,IAAoB,QAClB,GAAuB,EAAY,YAAY,EAAgB,EACrE,CAAC,EAAY,YAAY,EAAgB,CAC1C,EACK,IAAmB,QAChB,IAAkB,KAAuB,GAChD,CAAC,EAAgB,CAClB,EAEK,IAAgB,QAAc;AAClC,MAAI,KAAoB,EAAQ,EAAiB,EAAE;GACjD,IAAM,IAAwC,EAAE;AAMhD,UALA,EAAiB,SAAQ,MAAK;AAC5B,IAAI,EAAE,SACJ,EAAc,EAAE,KAAK,EAAE,KAAK,SAAS,MAAM,EAAE;KAE/C,EACK;;AAET,SAAO,EAAE;IACR,CAAC,EAAiB,CAAC;AAEtB,QACE,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD;EACE,IAAI;GACF,SAAS;GACT,YAAY;GACZ,qBAAqB;GACtB;YALH;GAOG,KACC,kBAAC,GAAD;IAAK,IAAI,EAAE,YAAY,cAAc;cAClC;IACG,CAAA;GAER,kBAAC,GAAD;IACE,eAAa;IACb,IAAI;KACF,SAAS;KACT,YAAY;KACZ,YAAY,IAAkB,eAAe;KAE7C,IAAI,IAAkB,QAAQ;KAC/B;cAED,kBAAC,GAAD;KACE,SAAS,EAAY;KACrB,YAAY,EAAE,cAAc,UAAU;KAC5B;KACV,gBAAgB;AACd,QAAS;OACP,MAAM;OACN;OACA,yBAAyB;OAC1B,CAAC;;KAEJ,CAAA;IACE,CAAA;GACN,kBAAC,GAAD;IACE,IAAI;KACF,IAAI,IAAkB,SAAS,KAAA;KAC/B,YAAY,IAER,eAEA;KACL;cAEA,IACC,EAAY,OAEZ,kBAAC,GAAD;KACE,OAAO,EAAY;KACnB,aAAa,IAAkB,eAAe;KAC9C,WAAU,MAAK;AACb,QAAS;OACP,MAAM;OACN;OACA,yBAAyB;OACzB,OAAO;QACL,GAAG;QACH,MAAM,EAAE,OAAO;QAChB;OACF,CAAC;;KAEM;KACV,WAAA;KACA,OAAO,CAAC,CAAC,EAAc;KACvB,YAAY,EAAc;KAC1B,WAAW,EACT,OAAO;MACL,8BACE;MACF,IAAI;MACJ,WAAW,EACT,OAAO,EACL,cAAc,QACf,EACF;MACF,EACF;KACD,CAAA;IAEA,CAAA;GACN,kBAAC,GAAD;IACE,IAAI,EACF,IAAI,IAAkB,SAAS,KAAA,GAChC;cAEA,IACC,EAA0B,EAAY,WAAW,GAEjD,kBAAC,GAAD;KAAa,WAAA;eAAb,CACE,kBAAC,GAAD;MACE,OAAM;MACN,OAAO,EAAY;MACnB,WAAU,MAAK;AACb,SAAS;QACP,MAAM;QACN;QACA,yBAAyB;QACzB,eAAe,EAAE,OAAO;QACzB,CAAC;;MAEJ,WAAW,EACT,OAAO,EACL,cAAc,eACf,EACF;MACD,IAAI;MACM;MACV,OAAO,CAAC,CAAC,EAAc;gBAEtB,GAAmB,KAAI,MAEpB,kBAAC,GAAD;OAAiB;iBACd,EAA0B,EAAM;OACxB,EAFkB,EAElB,CAEb;MACK,CAAA,EACR,EAAc,cACb,kBAAC,GAAD;MAAgB,OAAO;gBACpB,EAAc;MACA,CAAA,CAEP;;IAEZ,CAAA;GACN,kBAAC,GAAD;IACE,IAAI,EACF,IAAI,IAAkB,SAAS,KAAA,GAChC;cAEA,IACE,EAAoC,eAAe,KAEpD,kBAAC,GAAD;KACE,OAAQ,EAAoC,eAAe;KAC3D,eAAe,GAAqB;KACpC,kBAAkB,GAAwB;KAC1C,YAAY,EAAY;KACxB,UAAU,KAAY,CAAC,EAAY,EAAY,WAAW;KAC1D,YAAY;MACV,8BACE;MAEF,WAAW,EACT,OAAO;OACL,cAAc;OACd,KAAK;OACL,KAAK,EAAY,EAAY,WAAW,GACpC,EAAkB,EAAY,WAAW,GACzC,KAAA;OACL,EACF;MACD,IAAI;MACL;KACD,WAAU,MAAK;AACb,QAAS;OACP,MAAM;OACN;OACA,yBAAyB;OACzB,OAAO;QACL,GAAG;QACH,aAAa,EAAE,OAAO;QACvB;OACF,CAAC;;KAEJ,WAAA;KACA,OAAO,CAAC,CAAC,EAAc;KACvB,YAAY,EAAc;KAC1B,CAAA;IAEA,CAAA;GACN,kBAAC,GAAD;IACE,IAAI,EACF,IAAI,IAAkB,SAAS,KAAA,GAChC;cAEA,IACE,EAAoC,qBAAqB,KAE1D,kBAAC,GAAD;KACE,OACG,EAAoC,qBAAqB;KAE5D,eAAe,GAAqB;KACpC,kBAAkB,GAAwB;KAC1C,YAAY,EAAY;KACxB,UACE,KAAY,CAAC,EAAqB,EAAY,WAAW;KAE3D,WAAU,MAAK;AACb,QAAS;OACP,MAAM;OACN;OACA,yBAAyB;OACzB,OAAO;QACL,GAAG;QACH,mBAAmB,EAAE,OAAO;QAC7B;OACF,CAAC;;KAEJ,YAAY;MACV,8BACE;MACF,WAAW,EACT,OAAO,EACL,cAAc,uBACf,EACF;MACD,IAAI;MACL;KACD,WAAA;KACA,OAAO,CAAC,CAAC,EAAc;KACvB,YAAY,EAAc;KAC1B,CAAA;IAEA,CAAA;GACN,kBAAC,GAAD;IACE,IAAI,EACF,IAAI,IAAkB,SAAS,KAAA,GAChC;cAEA,IACC,EACG,GAAqC,cACtC,EAAY,WACb,GAED,kBAAC,GAAD;KACE,gBAAgB;MACd,YAAY;OACV,8BACE;OACF,WAAW,EACT,OAAO,EACL,cAAc,iBACf,EACF;OACD,IAAI;OACL;MACD,WAAW;MACX,OAAO,CAAC,CAAC,EAAc;MACvB,YAAY,EAAc;MAC3B;KACD,aAAa;MACX,OAAO;MACP,IAAI;MACJ,WAAW,EACT,OAAO,EACL,cAAc,iBACf,EACF;MACD,OAAO,CAAC,CAAC,EAAc;MACxB;KACD,sBAAsB,EAAc;KACvB;KACb,OAAQ,GAAqC,gBAAgB;KAC7D,WAAU,MAAS;AACjB,QAAS;OACP,MAAM;OACN;OACA,yBAAyB;OACzB,OAAO;QACL,GAAG;QACH,cAAc,KAAS,KAAA;QACxB;OACF,CAAC;;KAEJ,UACE,KACA,CAAC,EAAe,EAAY,YAAY,GAAQ,EAAgB;KAElE,CAAA;IAEA,CAAA;GACN,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;IACE,OAAQ,GAAqC;IAC7C,WAAU,MAAY;AACpB,OAAS;MACP,MAAM;MACN;MACA,yBAAyB;MACzB,OAAO;OACL,GAAG;OACH,YACE,KAAY,QAAQ,EAAQ,EAAS,GACjC,KAAA,IACA;OACP;MACF,CAAC;;IAEJ,YAAY,EAAY;IACxB,gBAAgB;KACd,WAAW;KACX,UACE,KACA,CAAC,GACC,EAAY,YACZ,EACD;KACH,YAAY;MACV,8BACE;MAEF,UAAU;MACV,IAAI;MACJ,WAAW,EACT,OAAO,EACL,cAAc,mBACf,EACF;MACF;KACD,OAAO,CAAC,CAAC,EAAc;KACvB,YAAY,EAAc;KAC3B;IACD,CAAA,EACE,CAAA;GACN,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;IAAa,WAAA;cAAb,CACE,kBAAC,GAAD;KACE,OAAM;KACN,OAAO,EAAY,aAAa;KAChC,UAAU,KAAY,MAAsB;KAC5C,WAAU,MAAK;AACb,QAAS;OACP,MAAM;OACN;OACA,yBAAyB;OACzB,OAAO;QACL,GAAG;QACH,WAAW,EAAE,OAAO;QACrB;OACF,CAAC;;KAEJ,IAAI;KACJ,WAAW,EACT,OAAO,EACL,cAAc,cACf,EACF;KACD,OAAO,CAAC,CAAC,EAAc;gBAErB,KAAqB,EAAE,EAAE,KAAK,GAAO,MAEnC,kBAAC,GAAD;MAAiB;gBACd,MAAU,KAAA,IAAY,KAAK,EAAyB,EAAM;MAClD,EAFkB,EAElB,CAEb;KACK,CAAA,EACR,EAAc,aACb,kBAAC,GAAD;KAAgB,OAAO;eACpB,EAAc;KACA,CAAA,CAEP;OACV,CAAA;GACN,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;IAAa,WAAA;cAAb,CACE,kBAAC,GAAD;KACE,OAAM;KACN,OAAO,EACL,qBAAqB,IACjB,EAAY,kBACZ,KAAA,EACL;KACD,UAAU,KAAY,EAAY,cAAc;KAChD,WAAU,MAAK;AACb,QAAS;OACP,MAAM;OACN;OACA,yBAAyB;OACzB,OAAO;QACL,GAAG;QACH,iBAAiB,EACf,EAAE,OAAO,MACV;QACF;OACF,CAAC;;KAEJ,IAAI;KACJ,WAAW,EACT,OAAO,EACL,cAAc,qBACf,EACF;KACD,OAAO,CAAC,CAAC,EAAc;eA3BzB;MA6BE,kBAAC,GAAD;OAAU,OAAM;iBAAiB;OAA+B,CAAA;MAChE,kBAAC,GAAD;OAAU,OAAM;iBAAgB;OAA8B,CAAA;MAC9D,kBAAC,GAAD;OAAU,OAAM;iBAAa;OAA2B,CAAA;MACxD,kBAAC,GAAD;OAAU,OAAM;iBAAY;OAA0B,CAAA;MAC/C;QACR,EAAc,mBACb,kBAAC,GAAD;KAAgB,OAAO;eACpB,EAAc;KACA,CAAA,CAEP;OACV,CAAA;GACF;KACL,KACC,kBAAC,GAAD;EACE,IAAI;GACF,SAAS;GACT,YAAY;GACZ,qBAAqB;GACtB;YALH;GAOE,kBAAC,GAAD;IACE,IAAI,EACF,YAAY,cACb;cAEA;IACG,CAAA;GACN,kBAAC,GAAD,EAAW,CAAA;GACX,kBAAC,GAAD;IACE,IAAI,EACF,YAAY,cACb;cAED,kBAAC,GAAD;KACE,aAAa;KACb,OAAQ,EAA2C;KACnD,WAAU,MAAK;AACb,QAAS;OACP,MAAM;OACN;OACA,yBAAyB;OACzB,OAAO;QACL,GAAI;QACJ,UAAU,EAAE,OAAO;QACpB;OACF,CAAC;;KAEM;KACV,WAAA;KACA,WAAW,EACT,OAAO;MACL,8BACE;MACF,IAAI;MACJ,cACE,kBAAC,GAAD;OACE,OACE,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,KAAD,EAAA,UACE,kBAAC,GAAD;QACE,MACE;kBAEH;QAGM,CAAA,EACL,CAAA,EACJ,kBAAC,KAAD,EAAA,UAAG,6NAMC,CAAA,CACH,EAAA,CAAA;iBAGL,kBAAC,GAAD,EAAa,IAAI,EAAE,OAAO,YAAY,EAAI,CAAA;OAClC,CAAA;MAEZ,WAAW,EACT,OAAO,EAAE,cAAc,aAAa,EACrC;MACF,EACF;KACD,OAAO,CAAC,CAAC,EAAc;KACvB,YAAY,EAAc;KAC1B,CAAA;IACE,CAAA;GACF;IAEP,EAAA,CAAA"}
|
package/dist/components/TableColumnSchemaEditor/ColumnModelFormFields/DefaultValueField.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DefaultValueField.js","names":[],"sources":["../../../../src/components/TableColumnSchemaEditor/ColumnModelFormFields/DefaultValueField.tsx"],"sourcesContent":["import { ReactNode, useMemo } from 'react'\nimport { ColumnTypeEnum } from '@sage-bionetworks/synapse-types'\nimport {\n FormControl,\n MenuItem,\n Select,\n SelectProps,\n TextField,\n TextFieldProps,\n} from '@mui/material'\nimport DateTimePicker from '../../DateTimePicker/DateTimePicker'\nimport dayjs from 'dayjs'\nimport FormHelperText from '@mui/material/FormHelperText'\nimport MultiValueField from './MultiValueField'\nimport { ColumnModelFormData } from '../Validators/ColumnModelValidator'\nimport customParseFormat from 'dayjs/plugin/customParseFormat'\n\n// required to parse unix timestamp below\ndayjs.extend(customParseFormat)\n\nexport type DefaultValueFieldProps<TValue, TReturn = TValue> = {\n columnModel: ColumnModelFormData\n value: TValue | undefined\n onChange: (newValue: TReturn | undefined) => void\n disabled?: boolean\n TextFieldProps?: Omit<TextFieldProps, 'value' | 'onChange' | 'disabled'>\n SelectProps?: Omit<SelectProps, 'variant' | 'value' | 'onChange' | 'disabled'>\n selectFormHelperText?: ReactNode\n}\n\nfunction DefaultValueBooleanField(props: DefaultValueFieldProps<string>) {\n const { onChange, value, disabled, SelectProps, selectFormHelperText } = props\n return (\n <FormControl fullWidth>\n <Select\n {...SelectProps}\n disabled={disabled}\n value={value || ''}\n onChange={e => {\n if (e.target.value == null) {\n onChange(undefined)\n } else {\n onChange(e.target.value as string)\n }\n }}\n >\n <MenuItem value={undefined}>{''}</MenuItem>\n <MenuItem value={'true'}>true</MenuItem>\n <MenuItem value={'false'}>false</MenuItem>\n </Select>\n {selectFormHelperText && (\n <FormHelperText color={'error.main'}>\n {selectFormHelperText}\n </FormHelperText>\n )}\n </FormControl>\n )\n}\n\nfunction DefaultValueDateField(props: DefaultValueFieldProps<string>) {\n const { onChange, value = null, disabled, TextFieldProps } = props\n\n const valueAsDayjs = useMemo(() => {\n if (value) {\n // The backend service returns a string that contains an integer unix timestamp with millisecond precision\n // Passing the raw string to dayjs without a format option will parse the value incorrectly\n // 'x' indicates parsing the value as a ms Unix Timestamp - https://day.js.org/docs/en/parse/string-format\n return dayjs(value, 'x')\n }\n return null\n }, [value])\n\n return (\n <DateTimePicker\n value={valueAsDayjs}\n onChange={newValue => {\n if (newValue == null) {\n onChange(undefined)\n } else {\n // onChange argument should match the backend's passed value\n onChange(String(newValue.valueOf()))\n }\n }}\n disabled={disabled}\n slotProps={{\n textField: TextFieldProps,\n }}\n />\n )\n}\n\nfunction DefaultValueListField(\n props: DefaultValueFieldProps<(string | number)[], (string | number)[]>,\n) {\n // Note the backend returns a string that is a serialized JSON array.\n // However, TableColumnSchemaEditorUtils.transformColumnModelsToFormData will parse this before this component receives the value.\n // So this component will get an array of strings or numbers\n const {\n onChange,\n value: _value = null,\n columnModel,\n TextFieldProps,\n disabled,\n } = props\n const value = useMemo(() => {\n try {\n if (\n columnModel.columnType === ColumnTypeEnum.DATE_LIST &&\n Array.isArray(_value)\n ) {\n // if it's a DATE_LIST, then the values are Unix timestamps in milliseconds\n // The `MultiValueField` component expects ISO strings to match the JSON Schema 'date-time' format\n return _value.map(v => {\n return dayjs(v, 'x').toISOString()\n })\n }\n return _value\n } catch (e) {\n return null\n }\n }, [_value, columnModel.columnType])\n\n return (\n <MultiValueField\n value={value}\n onChange={arr => {\n if (arr == null) {\n // Convert null to undefined\n onChange(undefined)\n } else if (columnModel.columnType === ColumnTypeEnum.DATE_LIST) {\n // Transform the ISO Timestamps to integer unix timestamps to match the passed value\n onChange(arr.map(val => dayjs(val).valueOf()))\n } else {\n onChange(arr)\n }\n }}\n columnType={columnModel.columnType as ColumnTypeEnum}\n TextFieldProps={{ ...TextFieldProps, disabled }}\n />\n )\n}\n\nexport default function DefaultValueField<T>(props: DefaultValueFieldProps<T>) {\n const { columnModel, onChange, value, disabled, TextFieldProps } = props\n\n const { columnType } = columnModel\n\n if (columnType === ColumnTypeEnum.BOOLEAN) {\n return (\n <DefaultValueBooleanField\n {...(props as unknown as DefaultValueFieldProps<string>)}\n />\n )\n }\n\n if (columnType === ColumnTypeEnum.DATE) {\n return (\n <DefaultValueDateField\n {...(props as unknown as DefaultValueFieldProps<string>)}\n />\n )\n }\n\n if (columnType.endsWith('_LIST')) {\n return (\n <DefaultValueListField\n {...(props as unknown as DefaultValueFieldProps<(string | number)[]>)}\n />\n )\n }\n\n return (\n <TextField\n {...TextFieldProps}\n type={'text'}\n value={value || undefined}\n onChange={event => {\n if (event.target.value == '') {\n onChange(undefined as T)\n } else {\n onChange(event.target.value as T)\n }\n }}\n disabled={disabled}\n />\n )\n}\n"],"mappings":";;;;;;;;;;AAkBA,EAAM,OAAO,EAAkB;AAY/B,SAAS,EAAyB,GAAuC;CACvE,IAAM,EAAE,aAAU,UAAO,aAAU,gBAAa,4BAAyB;AACzE,QACE,kBAAC,GAAD;EAAa,WAAA;YAAb,CACE,kBAAC,GAAD;GACE,GAAI;GACM;GACV,OAAO,KAAS;GAChB,WAAU,MAAK;AACb,IAAI,EAAE,OAAO,SAAS,OACpB,EAAS,KAAA,EAAU,GAEnB,EAAS,EAAE,OAAO,MAAgB;;aARxC;IAYE,kBAAC,GAAD;KAAU,OAAO,KAAA;eAAY;KAAc,CAAA;IAC3C,kBAAC,GAAD;KAAU,OAAO;eAAQ;KAAe,CAAA;IACxC,kBAAC,GAAD;KAAU,OAAO;eAAS;KAAgB,CAAA;IACnC;MACR,KACC,kBAAC,GAAD;GAAgB,OAAO;aACpB;GACc,CAAA,CAEP;;;AAIlB,SAAS,EAAsB,GAAuC;CACpE,IAAM,EAAE,aAAU,WAAQ,MAAM,aAAU,sBAAmB;AAY7D,QACE,kBAAC,GAAD;EACE,OAZiB,QACf,IAIK,EAAM,GAAO,IAAI,GAEnB,MACN,CAAC,EAAM,
|
|
1
|
+
{"version":3,"file":"DefaultValueField.js","names":[],"sources":["../../../../src/components/TableColumnSchemaEditor/ColumnModelFormFields/DefaultValueField.tsx"],"sourcesContent":["import { ReactNode, useMemo } from 'react'\nimport { ColumnTypeEnum } from '@sage-bionetworks/synapse-types'\nimport {\n FormControl,\n MenuItem,\n Select,\n SelectProps,\n TextField,\n TextFieldProps,\n} from '@mui/material'\nimport DateTimePicker from '../../DateTimePicker/DateTimePicker'\nimport dayjs from 'dayjs'\nimport FormHelperText from '@mui/material/FormHelperText'\nimport MultiValueField from './MultiValueField'\nimport { ColumnModelFormData } from '../Validators/ColumnModelValidator'\nimport customParseFormat from 'dayjs/plugin/customParseFormat'\n\n// required to parse unix timestamp below\ndayjs.extend(customParseFormat)\n\nexport type DefaultValueFieldProps<TValue, TReturn = TValue> = {\n columnModel: ColumnModelFormData\n value: TValue | undefined\n onChange: (newValue: TReturn | undefined) => void\n disabled?: boolean\n TextFieldProps?: Omit<TextFieldProps, 'value' | 'onChange' | 'disabled'>\n SelectProps?: Omit<SelectProps, 'variant' | 'value' | 'onChange' | 'disabled'>\n selectFormHelperText?: ReactNode\n}\n\nfunction DefaultValueBooleanField(props: DefaultValueFieldProps<string>) {\n const { onChange, value, disabled, SelectProps, selectFormHelperText } = props\n return (\n <FormControl fullWidth>\n <Select\n {...SelectProps}\n disabled={disabled}\n value={value || ''}\n onChange={e => {\n if (e.target.value == null) {\n onChange(undefined)\n } else {\n onChange(e.target.value as string)\n }\n }}\n >\n <MenuItem value={undefined}>{''}</MenuItem>\n <MenuItem value={'true'}>true</MenuItem>\n <MenuItem value={'false'}>false</MenuItem>\n </Select>\n {selectFormHelperText && (\n <FormHelperText color={'error.main'}>\n {selectFormHelperText}\n </FormHelperText>\n )}\n </FormControl>\n )\n}\n\nfunction DefaultValueDateField(props: DefaultValueFieldProps<string>) {\n const { onChange, value = null, disabled, TextFieldProps } = props\n\n const valueAsDayjs = useMemo(() => {\n if (value) {\n // The backend service returns a string that contains an integer unix timestamp with millisecond precision\n // Passing the raw string to dayjs without a format option will parse the value incorrectly\n // 'x' indicates parsing the value as a ms Unix Timestamp - https://day.js.org/docs/en/parse/string-format\n return dayjs(value, 'x')\n }\n return null\n }, [value])\n\n return (\n <DateTimePicker\n value={valueAsDayjs}\n onChange={newValue => {\n if (newValue == null) {\n onChange(undefined)\n } else {\n // onChange argument should match the backend's passed value\n onChange(String(newValue.valueOf()))\n }\n }}\n disabled={disabled}\n slotProps={{\n textField: TextFieldProps,\n }}\n />\n )\n}\n\nfunction DefaultValueListField(\n props: DefaultValueFieldProps<(string | number)[], (string | number)[]>,\n) {\n // Note the backend returns a string that is a serialized JSON array.\n // However, TableColumnSchemaEditorUtils.transformColumnModelsToFormData will parse this before this component receives the value.\n // So this component will get an array of strings or numbers\n const {\n onChange,\n value: _value = null,\n columnModel,\n TextFieldProps,\n disabled,\n } = props\n const value = useMemo(() => {\n try {\n if (\n columnModel.columnType === ColumnTypeEnum.DATE_LIST &&\n Array.isArray(_value)\n ) {\n // if it's a DATE_LIST, then the values are Unix timestamps in milliseconds\n // The `MultiValueField` component expects ISO strings to match the JSON Schema 'date-time' format\n return _value.map(v => {\n return dayjs(v, 'x').toISOString()\n })\n }\n return _value\n } catch (e) {\n return null\n }\n }, [_value, columnModel.columnType])\n\n return (\n <MultiValueField\n value={value}\n onChange={arr => {\n if (arr == null) {\n // Convert null to undefined\n onChange(undefined)\n } else if (columnModel.columnType === ColumnTypeEnum.DATE_LIST) {\n // Transform the ISO Timestamps to integer unix timestamps to match the passed value\n onChange(arr.map(val => dayjs(val).valueOf()))\n } else {\n onChange(arr)\n }\n }}\n columnType={columnModel.columnType as ColumnTypeEnum}\n TextFieldProps={{ ...TextFieldProps, disabled }}\n />\n )\n}\n\nexport default function DefaultValueField<T>(props: DefaultValueFieldProps<T>) {\n const { columnModel, onChange, value, disabled, TextFieldProps } = props\n\n const { columnType } = columnModel\n\n if (columnType === ColumnTypeEnum.BOOLEAN) {\n return (\n <DefaultValueBooleanField\n {...(props as unknown as DefaultValueFieldProps<string>)}\n />\n )\n }\n\n if (columnType === ColumnTypeEnum.DATE) {\n return (\n <DefaultValueDateField\n {...(props as unknown as DefaultValueFieldProps<string>)}\n />\n )\n }\n\n if (columnType.endsWith('_LIST')) {\n return (\n <DefaultValueListField\n {...(props as unknown as DefaultValueFieldProps<(string | number)[]>)}\n />\n )\n }\n\n return (\n <TextField\n {...TextFieldProps}\n type={'text'}\n value={value || undefined}\n onChange={event => {\n if (event.target.value == '') {\n onChange(undefined as T)\n } else {\n onChange(event.target.value as T)\n }\n }}\n disabled={disabled}\n />\n )\n}\n"],"mappings":";;;;;;;;;;AAkBA,EAAM,OAAO,EAAkB;AAY/B,SAAS,EAAyB,GAAuC;CACvE,IAAM,EAAE,aAAU,UAAO,aAAU,gBAAa,4BAAyB;AACzE,QACE,kBAAC,GAAD;EAAa,WAAA;YAAb,CACE,kBAAC,GAAD;GACE,GAAI;GACM;GACV,OAAO,KAAS;GAChB,WAAU,MAAK;AACb,IAAI,EAAE,OAAO,SAAS,OACpB,EAAS,KAAA,EAAU,GAEnB,EAAS,EAAE,OAAO,MAAgB;;aARxC;IAYE,kBAAC,GAAD;KAAU,OAAO,KAAA;eAAY;KAAc,CAAA;IAC3C,kBAAC,GAAD;KAAU,OAAO;eAAQ;KAAe,CAAA;IACxC,kBAAC,GAAD;KAAU,OAAO;eAAS;KAAgB,CAAA;IACnC;MACR,KACC,kBAAC,GAAD;GAAgB,OAAO;aACpB;GACc,CAAA,CAEP;;;AAIlB,SAAS,EAAsB,GAAuC;CACpE,IAAM,EAAE,aAAU,WAAQ,MAAM,aAAU,sBAAmB;AAY7D,QACE,kBAAC,GAAD;EACE,OAZiB,QACf,IAIK,EAAM,GAAO,IAAI,GAEnB,MACN,CAAC,EAAM,CAIC;EACP,WAAU,MAAY;AACpB,GACE,EADE,KAAY,OACL,KAAA,IAGA,OAAO,EAAS,SAAS,CAAC,CAAC;;EAG9B;EACV,WAAW,EACT,WAAW,GACZ;EACD,CAAA;;AAIN,SAAS,EACP,GACA;CAIA,IAAM,EACJ,aACA,OAAO,IAAS,MAChB,gBACA,mBACA,gBACE;AAmBJ,QACE,kBAAC,GAAD;EACS,OApBG,QAAc;AAC1B,OAAI;AAWF,WATE,EAAY,eAAe,EAAe,aAC1C,MAAM,QAAQ,EAAO,GAId,EAAO,KAAI,MACT,EAAM,GAAG,IAAI,CAAC,aAAa,CAClC,GAEG;WACG;AACV,WAAO;;KAER,CAAC,GAAQ,EAAY,WAAW,CAIxB;EACP,WAAU,MAAO;AACf,GAAI,KAAO,OAET,EAAS,KAAA,EAAU,GACV,EAAY,eAAe,EAAe,YAEnD,EAAS,EAAI,KAAI,MAAO,EAAM,EAAI,CAAC,SAAS,CAAC,CAAC,GAE9C,EAAS,EAAI;;EAGjB,YAAY,EAAY;EACxB,gBAAgB;GAAE,GAAG;GAAgB;GAAU;EAC/C,CAAA;;AAIN,SAAwB,EAAqB,GAAkC;CAC7E,IAAM,EAAE,gBAAa,aAAU,UAAO,aAAU,sBAAmB,GAE7D,EAAE,kBAAe;AA0BvB,QAxBI,MAAe,EAAe,UAE9B,kBAAC,GAAD,EACE,GAAK,GACL,CAAA,GAIF,MAAe,EAAe,OAE9B,kBAAC,GAAD,EACE,GAAK,GACL,CAAA,GAIF,EAAW,SAAS,QAAQ,GAE5B,kBAAC,GAAD,EACE,GAAK,GACL,CAAA,GAKJ,kBAAC,GAAD;EACE,GAAI;EACJ,MAAM;EACN,OAAO,KAAS,KAAA;EAChB,WAAU,MAAS;AACjB,GAAI,EAAM,OAAO,SAAS,KACxB,EAAS,KAAA,EAAe,GAExB,EAAS,EAAM,OAAO,MAAW;;EAG3B;EACV,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ImportTableColumnsButton.js","names":[],"sources":["../../../src/components/TableColumnSchemaEditor/ImportTableColumnsButton.tsx"],"sourcesContent":["import SynapseClient from '@/synapse-client'\nimport { useSynapseContext } from '@/utils'\nimport { EntityTypeGroup } from '@/utils/functions/EntityTypeUtils'\nimport { DownloadTwoTone } from '@mui/icons-material'\nimport { Button, ButtonProps } from '@mui/material'\nimport { EntityType } from '@sage-bionetworks/synapse-client'\nimport { ColumnModel, Reference } from '@sage-bionetworks/synapse-types'\nimport { useCallback, useState } from 'react'\nimport { SetOptional } from 'type-fest'\nimport { EntityFinderModal } from '../EntityFinder/EntityFinderModal'\nimport { FinderScope } from '../EntityFinder/tree/EntityTree'\nimport { VersionSelectionType } from '../EntityFinder/VersionSelectionType'\nimport { displayToast } from '../ToastMessage'\n\nexport type ImportTableColumnsButtonProps = Omit<ButtonProps, 'onClick'> & {\n initialFinderProjectId?: string\n onAddColumns: (columnModels: SetOptional<ColumnModel, 'id'>[]) => void\n}\n\nexport default function ImportTableColumnsButton(\n props: ImportTableColumnsButtonProps,\n) {\n const { initialFinderProjectId, onAddColumns, ...buttonProps } = props\n const [showFinder, setShowFinder] = useState(false)\n const { accessToken } = useSynapseContext()\n\n const fetchColumnModels = useCallback(\n async (reference: Reference): Promise<SetOptional<ColumnModel, 'id'>[]> => {\n const { tableBundle } = await SynapseClient.getEntityBundleV2(\n reference.targetId,\n { includeTableBundle: true },\n reference.targetVersionNumber,\n accessToken,\n )\n return tableBundle!.columnModels.map(columnModel => ({\n ...columnModel,\n id: undefined,\n }))\n },\n [accessToken],\n )\n\n const onConfirmEntityFinder = useCallback(\n async (selected: Reference[]) => {\n try {\n const selectedEntity = selected[0]\n\n if (selectedEntity) {\n // Get the column models from the selected table\n const columnModels = await fetchColumnModels(selectedEntity)\n onAddColumns(columnModels)\n }\n } catch (err) {\n console.error(err)\n displayToast(err.message, 'danger')\n } finally {\n setShowFinder(false)\n }\n },\n [fetchColumnModels, onAddColumns],\n )\n\n return (\n <>\n <EntityFinderModal\n configuration={{\n initialScope: initialFinderProjectId\n ? FinderScope.CURRENT_PROJECT\n : FinderScope.ALL_PROJECTS,\n initialContainer: initialFinderProjectId ?? 'root',\n selectMultiple: false,\n selectableTypes: EntityTypeGroup.ALL_TABLES,\n visibleTypesInTree: [EntityType.project],\n versionSelection: VersionSelectionType.UNTRACKED,\n }}\n show={showFinder}\n title={'Import Columns from Table'}\n promptCopy={'Find Tables to import columns'}\n titleHelpPopoverProps={{\n markdownText:\n 'Search or Browse Synapse to find an existing Table in order to import columns into this Table',\n }}\n onConfirm={selected => {\n onConfirmEntityFinder(selected)\n }}\n confirmButtonCopy={'Import Columns'}\n onCancel={() => {\n setShowFinder(false)\n }}\n />\n <Button\n variant={'outlined'}\n onClick={() => {\n setShowFinder(true)\n }}\n startIcon={<DownloadTwoTone />}\n {...buttonProps}\n >\n Import Columns\n </Button>\n </>\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;AAmBA,SAAwB,EACtB,GACA;CACA,IAAM,EAAE,2BAAwB,iBAAc,GAAG,MAAgB,GAC3D,CAAC,GAAY,KAAiB,EAAS,GAAM,EAC7C,EAAE,mBAAgB,GAAmB,EAErC,IAAoB,EACxB,OAAO,MAAoE;EACzE,IAAM,EAAE,mBAAgB,MAAM,EAAc,kBAC1C,EAAU,UACV,EAAE,oBAAoB,IAAM,EAC5B,EAAU,qBACV,EACD;AACD,SAAO,EAAa,aAAa,KAAI,OAAgB;GACnD,GAAG;GACH,IAAI,KAAA;GACL,EAAE;IAEL,CAAC,EAAY,CACd,EAEK,IAAwB,EAC5B,OAAO,MAA0B;AAC/B,MAAI;GACF,IAAM,IAAiB,EAAS;AAEhC,GAAI,KAGF,
|
|
1
|
+
{"version":3,"file":"ImportTableColumnsButton.js","names":[],"sources":["../../../src/components/TableColumnSchemaEditor/ImportTableColumnsButton.tsx"],"sourcesContent":["import SynapseClient from '@/synapse-client'\nimport { useSynapseContext } from '@/utils'\nimport { EntityTypeGroup } from '@/utils/functions/EntityTypeUtils'\nimport { DownloadTwoTone } from '@mui/icons-material'\nimport { Button, ButtonProps } from '@mui/material'\nimport { EntityType } from '@sage-bionetworks/synapse-client'\nimport { ColumnModel, Reference } from '@sage-bionetworks/synapse-types'\nimport { useCallback, useState } from 'react'\nimport { SetOptional } from 'type-fest'\nimport { EntityFinderModal } from '../EntityFinder/EntityFinderModal'\nimport { FinderScope } from '../EntityFinder/tree/EntityTree'\nimport { VersionSelectionType } from '../EntityFinder/VersionSelectionType'\nimport { displayToast } from '../ToastMessage'\n\nexport type ImportTableColumnsButtonProps = Omit<ButtonProps, 'onClick'> & {\n initialFinderProjectId?: string\n onAddColumns: (columnModels: SetOptional<ColumnModel, 'id'>[]) => void\n}\n\nexport default function ImportTableColumnsButton(\n props: ImportTableColumnsButtonProps,\n) {\n const { initialFinderProjectId, onAddColumns, ...buttonProps } = props\n const [showFinder, setShowFinder] = useState(false)\n const { accessToken } = useSynapseContext()\n\n const fetchColumnModels = useCallback(\n async (reference: Reference): Promise<SetOptional<ColumnModel, 'id'>[]> => {\n const { tableBundle } = await SynapseClient.getEntityBundleV2(\n reference.targetId,\n { includeTableBundle: true },\n reference.targetVersionNumber,\n accessToken,\n )\n return tableBundle!.columnModels.map(columnModel => ({\n ...columnModel,\n id: undefined,\n }))\n },\n [accessToken],\n )\n\n const onConfirmEntityFinder = useCallback(\n async (selected: Reference[]) => {\n try {\n const selectedEntity = selected[0]\n\n if (selectedEntity) {\n // Get the column models from the selected table\n const columnModels = await fetchColumnModels(selectedEntity)\n onAddColumns(columnModels)\n }\n } catch (err) {\n console.error(err)\n displayToast(err.message, 'danger')\n } finally {\n setShowFinder(false)\n }\n },\n [fetchColumnModels, onAddColumns],\n )\n\n return (\n <>\n <EntityFinderModal\n configuration={{\n initialScope: initialFinderProjectId\n ? FinderScope.CURRENT_PROJECT\n : FinderScope.ALL_PROJECTS,\n initialContainer: initialFinderProjectId ?? 'root',\n selectMultiple: false,\n selectableTypes: EntityTypeGroup.ALL_TABLES,\n visibleTypesInTree: [EntityType.project],\n versionSelection: VersionSelectionType.UNTRACKED,\n }}\n show={showFinder}\n title={'Import Columns from Table'}\n promptCopy={'Find Tables to import columns'}\n titleHelpPopoverProps={{\n markdownText:\n 'Search or Browse Synapse to find an existing Table in order to import columns into this Table',\n }}\n onConfirm={selected => {\n onConfirmEntityFinder(selected)\n }}\n confirmButtonCopy={'Import Columns'}\n onCancel={() => {\n setShowFinder(false)\n }}\n />\n <Button\n variant={'outlined'}\n onClick={() => {\n setShowFinder(true)\n }}\n startIcon={<DownloadTwoTone />}\n {...buttonProps}\n >\n Import Columns\n </Button>\n </>\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;AAmBA,SAAwB,EACtB,GACA;CACA,IAAM,EAAE,2BAAwB,iBAAc,GAAG,MAAgB,GAC3D,CAAC,GAAY,KAAiB,EAAS,GAAM,EAC7C,EAAE,mBAAgB,GAAmB,EAErC,IAAoB,EACxB,OAAO,MAAoE;EACzE,IAAM,EAAE,mBAAgB,MAAM,EAAc,kBAC1C,EAAU,UACV,EAAE,oBAAoB,IAAM,EAC5B,EAAU,qBACV,EACD;AACD,SAAO,EAAa,aAAa,KAAI,OAAgB;GACnD,GAAG;GACH,IAAI,KAAA;GACL,EAAE;IAEL,CAAC,EAAY,CACd,EAEK,IAAwB,EAC5B,OAAO,MAA0B;AAC/B,MAAI;GACF,IAAM,IAAiB,EAAS;AAEhC,GAAI,KAGF,EAAa,MADc,EAAkB,EAAe,CAClC;WAErB,GAAK;AAEZ,GADA,QAAQ,MAAM,EAAI,EAClB,EAAa,EAAI,SAAS,SAAS;YAC3B;AACR,KAAc,GAAM;;IAGxB,CAAC,GAAmB,EAAa,CAClC;AAED,QACE,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD;EACE,eAAe;GACb,cAAc,IACV,EAAY,kBACZ,EAAY;GAChB,kBAAkB,KAA0B;GAC5C,gBAAgB;GAChB,iBAAiB,EAAgB;GACjC,oBAAoB,CAAC,EAAW,QAAQ;GACxC,kBAAkB,EAAqB;GACxC;EACD,MAAM;EACN,OAAO;EACP,YAAY;EACZ,uBAAuB,EACrB,cACE,iGACH;EACD,YAAW,MAAY;AACrB,KAAsB,EAAS;;EAEjC,mBAAmB;EACnB,gBAAgB;AACd,KAAc,GAAM;;EAEtB,CAAA,EACF,kBAAC,GAAD;EACE,SAAS;EACT,eAAe;AACb,KAAc,GAAK;;EAErB,WAAW,kBAAC,GAAD,EAAmB,CAAA;EAC9B,GAAI;YACL;EAEQ,CAAA,CACR,EAAA,CAAA"}
|
|
@@ -9,7 +9,7 @@ import { ColumnModelFormData } from './Validators/ColumnModelValidator';
|
|
|
9
9
|
*/
|
|
10
10
|
export declare function getAllowedColumnTypes(isView: boolean, isJsonSubColumnFacet: boolean): ColumnTypeEnum[];
|
|
11
11
|
export declare function getFacetTypeFriendlyName(facetType: FacetType): "Range" | "Values";
|
|
12
|
-
export declare function getColumnTypeFriendlyName(type: ColumnType | ColumnTypeEnum): "
|
|
12
|
+
export declare function getColumnTypeFriendlyName(type: ColumnType | ColumnTypeEnum): "File" | "Link" | "String" | "Integer" | "Boolean" | "JSON" | "Double" | "Date" | "Entity" | "MediumText" | "LargeText" | "User" | "String List" | "Integer List" | "Boolean List" | "Date List" | "User ID List" | "Entity ID List" | "Evaluation" | "Submission";
|
|
13
13
|
/**
|
|
14
14
|
* Can the given type have a size?
|
|
15
15
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TableColumnSchemaEditorUtils.d.ts","sourceRoot":"","sources":["../../../src/components/TableColumnSchemaEditor/TableColumnSchemaEditorUtils.ts"],"names":[],"mappings":"AAQA,OAAO,EACL,WAAW,EACX,UAAU,EACV,cAAc,EACd,MAAM,EAGN,SAAS,EACT,SAAS,EACV,MAAM,iCAAiC,CAAA;AACxC,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AACvC,OAAO,EACL,mBAAmB,EAEpB,MAAM,mCAAmC,CAAA;AAQ1C;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,OAAO,EACf,oBAAoB,EAAE,OAAO,GAC5B,cAAc,EAAE,CAuBlB;AAED,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,SAAS,sBAS5D;AACD,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,UAAU,GAAG,cAAc,
|
|
1
|
+
{"version":3,"file":"TableColumnSchemaEditorUtils.d.ts","sourceRoot":"","sources":["../../../src/components/TableColumnSchemaEditor/TableColumnSchemaEditorUtils.ts"],"names":[],"mappings":"AAQA,OAAO,EACL,WAAW,EACX,UAAU,EACV,cAAc,EACd,MAAM,EAGN,SAAS,EACT,SAAS,EACV,MAAM,iCAAiC,CAAA;AACxC,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AACvC,OAAO,EACL,mBAAmB,EAEpB,MAAM,mCAAmC,CAAA;AAQ1C;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,OAAO,EACf,oBAAoB,EAAE,OAAO,GAC5B,cAAc,EAAE,CAuBlB;AAED,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,SAAS,sBAS5D;AACD,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,UAAU,GAAG,cAAc,sQA6C1E;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,cAAc,GAAG,OAAO,CAUtE;AAED,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,UAAU,GAAG,cAAc,GAChC,OAAO,CAYT;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,UAAU,GAAG,cAAc,EACjC,oBAAoB,EAAE,OAAO,GAC5B,CAAC,SAAS,GAAG,SAAS,CAAC,EAAE,GAAG,IAAI,CAiClC;AAED,wBAAgB,cAAc,CAC5B,IAAI,EAAE,UAAU,GAAG,cAAc,EACjC,MAAM,EAAE,OAAO,EACf,oBAAoB,EAAE,OAAO,WAwB9B;AAED,eAAO,MAAM,mBAAmB,KAAK,CAAA;AACrC,eAAO,MAAM,eAAe,OAAO,CAAA;AACnC,eAAO,MAAM,eAAe,MAAM,CAAA;AAElC;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,UAAU,GAAG,cAAc,GAAG,MAAM,CAS3E;AAED,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,UAAU,GAAG,cAAc,EACjC,oBAAoB,EAAE,OAAO,GAC5B,OAAO,CAaT;AAeD;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAC7C,YAAY,EAAE,WAAW,CAAC,WAAW,EAAE,IAAI,CAAC,EAAE,EAC9C,cAAc,GAAE,WAAW,EAAO,GACjC,mBAAmB,EAAE,CAoCvB;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAgC3E;AAED,wBAAgB,wCAAwC,CACtD,UAAU,EAAE,cAAc,GACzB,qBAAqB,CA8BvB;AASD,eAAO,MAAM,uBAAuB,GAClC,cAAc,WAAW,EAAE,EAC3B,QAAQ,mBAAmB,KAC1B,WAAW,GAAG,SAWhB,CAAA;AAED,wBAAgB,wBAAwB,CACtC,aAAa,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,GACzC,MAAM,GAAG,IAAI,CAKf;AAED,eAAO,MAAM,0CAA0C,GACrD,eAAe,MAAM,GAAG,MAAM,GAAG,SAAS,EAC1C,kBAAkB,MAAM,GAAG,SAAS,KACnC,OAKF,CAAA;AAED,wBAAgB,wCAAwC,CACtD,WAAW,EAAE,mBAAmB,EAChC,qBAAqB,CAAC,EAAE,WAAW,GAClC,OAAO,CAmBT;AAED,wBAAgB,6DAA6D,CAC3E,YAAY,EAAE,mBAAmB,EAAE,EACnC,sBAAsB,EAAE,WAAW,EAAE,GACpC,MAAM,CAYR"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TableColumnSchemaEditorUtils.js","names":[],"sources":["../../../src/components/TableColumnSchemaEditor/TableColumnSchemaEditorUtils.ts"],"sourcesContent":["import {\n convertToEntityType,\n isDataset,\n isDatasetCollection,\n isEntityView,\n isSubmissionView,\n} from '@/utils/functions/EntityTypeUtils'\nimport { ViewEntityType } from '@sage-bionetworks/synapse-client'\nimport {\n ColumnModel,\n ColumnType,\n ColumnTypeEnum,\n Entity,\n ENTITY_VIEW_TYPE_MASK_DATASET,\n ENTITY_VIEW_TYPE_MASK_FILE,\n FacetType,\n ViewScope,\n} from '@sage-bionetworks/synapse-types'\nimport { JSONSchema7Definition } from 'json-schema'\nimport { SetOptional } from 'type-fest'\nimport {\n ColumnModelFormData,\n JsonSubColumnModelFormData,\n} from './Validators/ColumnModelValidator'\n\n/**\n * These column types can only be used in Tables. They can not be used in views.\n * See SWC-6333 - for views, only allow column types that are mapped to annotation types.\n */\nconst unsupportedTypesForViews = [ColumnTypeEnum.JSON]\n\n/**\n * Get the allowed column types for a column model based on the table type.\n * @param isView - whether the base table is a view\n * @param isJsonSubColumnFacet - whether the proposed column is a JSON subcolumn facet\n */\nexport function getAllowedColumnTypes(\n isView: boolean,\n isJsonSubColumnFacet: boolean,\n): ColumnTypeEnum[] {\n return Object.values(ColumnTypeEnum)\n .filter(columnType =>\n isView ? !unsupportedTypesForViews.includes(columnType) : true,\n )\n .filter(columnType => {\n if (isJsonSubColumnFacet) {\n switch (columnType) {\n // JSON Subcolumns cannot be JSON or LIST types\n case ColumnTypeEnum.JSON:\n case ColumnTypeEnum.STRING_LIST:\n case ColumnTypeEnum.INTEGER_LIST:\n case ColumnTypeEnum.BOOLEAN_LIST:\n case ColumnTypeEnum.DATE_LIST:\n case ColumnTypeEnum.USERID_LIST:\n case ColumnTypeEnum.ENTITYID_LIST:\n return false\n default:\n return true\n }\n }\n return true\n })\n}\n\nexport function getFacetTypeFriendlyName(facetType: FacetType) {\n switch (facetType) {\n case 'enumeration':\n return 'Values'\n case 'range':\n return 'Range'\n default:\n return facetType\n }\n}\nexport function getColumnTypeFriendlyName(type: ColumnType | ColumnTypeEnum) {\n switch (type) {\n case ColumnTypeEnum.STRING:\n return 'String'\n case ColumnTypeEnum.DOUBLE:\n return 'Double'\n case ColumnTypeEnum.BOOLEAN:\n return 'Boolean'\n case ColumnTypeEnum.INTEGER:\n return 'Integer'\n case ColumnTypeEnum.DATE:\n return 'Date'\n case ColumnTypeEnum.FILEHANDLEID:\n return 'File'\n case ColumnTypeEnum.ENTITYID:\n return 'Entity'\n case ColumnTypeEnum.LINK:\n return 'Link'\n case ColumnTypeEnum.MEDIUMTEXT:\n return 'MediumText'\n case ColumnTypeEnum.LARGETEXT:\n return 'LargeText'\n case ColumnTypeEnum.USERID:\n return 'User'\n case ColumnTypeEnum.STRING_LIST:\n return 'String List'\n case ColumnTypeEnum.INTEGER_LIST:\n return 'Integer List'\n case ColumnTypeEnum.BOOLEAN_LIST:\n return 'Boolean List'\n case ColumnTypeEnum.DATE_LIST:\n return 'Date List'\n case ColumnTypeEnum.USERID_LIST:\n return 'User ID List'\n case ColumnTypeEnum.ENTITYID_LIST:\n return 'Entity ID List'\n case ColumnTypeEnum.EVALUATIONID:\n return 'Evaluation'\n case ColumnTypeEnum.SUBMISSIONID:\n return 'Submission'\n case ColumnTypeEnum.JSON:\n return 'JSON'\n default:\n return type\n }\n}\n\n/**\n * Can the given type have a size?\n *\n * @param type\n * @return\n */\nexport function canHaveSize(type: ColumnType | ColumnTypeEnum): boolean {\n switch (type) {\n case ColumnTypeEnum.STRING:\n case ColumnTypeEnum.STRING_LIST:\n case ColumnTypeEnum.LINK:\n return true\n default:\n // all others are false\n return false\n }\n}\n\nexport function canHaveMaxListLength(\n type: ColumnType | ColumnTypeEnum,\n): boolean {\n switch (type) {\n case ColumnTypeEnum.STRING_LIST:\n case ColumnTypeEnum.BOOLEAN_LIST:\n case ColumnTypeEnum.DATE_LIST:\n case ColumnTypeEnum.INTEGER_LIST:\n case ColumnTypeEnum.ENTITYID_LIST:\n return true\n default:\n // all others are false\n return false\n }\n}\n\n/**\n * Configure the facet selection based on the column type\n *\n * @param type a ColumnType for which to get the facet selection\n * @param isJsonSubColumnFacet is this a facet for a json subcolumn?\n * @return the allowed facetTypes, or null if faceting is not allowed\n */\nexport function configureFacetsForType(\n type: ColumnType | ColumnTypeEnum,\n isJsonSubColumnFacet: boolean,\n): (FacetType | undefined)[] | null {\n let allowedFacetTypes: (FacetType | undefined)[] | null\n switch (type) {\n case ColumnTypeEnum.INTEGER:\n case ColumnTypeEnum.INTEGER_LIST:\n allowedFacetTypes = ['enumeration', 'range']\n break\n case ColumnTypeEnum.STRING:\n case ColumnTypeEnum.BOOLEAN:\n case ColumnTypeEnum.USERID:\n case ColumnTypeEnum.ENTITYID:\n case ColumnTypeEnum.STRING_LIST:\n case ColumnTypeEnum.BOOLEAN_LIST:\n case ColumnTypeEnum.ENTITYID_LIST:\n case ColumnTypeEnum.USERID_LIST:\n case ColumnTypeEnum.EVALUATIONID:\n allowedFacetTypes = ['enumeration']\n break\n case ColumnTypeEnum.DOUBLE:\n case ColumnTypeEnum.DATE:\n case ColumnTypeEnum.DATE_LIST:\n allowedFacetTypes = ['range']\n break\n default:\n allowedFacetTypes = null\n }\n\n if (allowedFacetTypes && !isJsonSubColumnFacet) {\n // jsonSubColumn facets MUST have a facet definition, but regular column models do not need one\n // So allow `undefined` for regular columnModels.\n allowedFacetTypes = [undefined, ...allowedFacetTypes]\n }\n return allowedFacetTypes\n}\n\nexport function canHaveDefault(\n type: ColumnType | ColumnTypeEnum,\n isView: boolean,\n isJsonSubColumnFacet: boolean,\n) {\n // SWC-6333: default types are not allowed in views\n if (isView) {\n return false\n } else if (isJsonSubColumnFacet) {\n return false\n } else {\n switch (type) {\n case ColumnTypeEnum.ENTITYID:\n case ColumnTypeEnum.ENTITYID_LIST:\n case ColumnTypeEnum.FILEHANDLEID:\n case ColumnTypeEnum.USERID:\n case ColumnTypeEnum.USERID_LIST:\n case ColumnTypeEnum.MEDIUMTEXT:\n case ColumnTypeEnum.LARGETEXT:\n case ColumnTypeEnum.JSON:\n case ColumnTypeEnum.SUBMISSIONID:\n case ColumnTypeEnum.EVALUATIONID:\n return false\n default:\n return true\n }\n }\n}\n\nexport const DEFAULT_STRING_SIZE = 50\nexport const MAX_STRING_SIZE = 1000\nexport const MAX_LIST_LENGTH = 100\n\n/**\n * Get the default max size for a given type.\n *\n * @param type\n * @return\n */\nexport function getMaxSizeForType(type: ColumnType | ColumnTypeEnum): number {\n switch (type) {\n case ColumnTypeEnum.STRING:\n case ColumnTypeEnum.STRING_LIST:\n case ColumnTypeEnum.LINK:\n return MAX_STRING_SIZE\n default:\n throw new Error(`Type is not known to have a max size: ${type}`)\n }\n}\n\nexport function canHaveRestrictedValues(\n type: ColumnType | ColumnTypeEnum,\n isJsonSubColumnFacet: boolean,\n): boolean {\n if (isJsonSubColumnFacet) {\n return false\n }\n switch (type) {\n case ColumnTypeEnum.STRING:\n case ColumnTypeEnum.INTEGER:\n case ColumnTypeEnum.ENTITYID:\n return true\n default:\n // all other are false\n return false\n }\n}\n\nfunction transformEnumValues(\n enumValues: string[],\n columnType: ColumnType | ColumnTypeEnum,\n): (string | number)[] {\n // SWC-6622 - Special case: if these are INTEGER, convert to numbers before inserting data into form components\n // The editor validates that these are integers, so inserting the strings returned by the API causes an\n // unexpected validation error\n if (columnType === ColumnTypeEnum.INTEGER) {\n return enumValues.map(value => parseInt(value))\n }\n return enumValues\n}\n\n/**\n * Transform ColumnModels returned by Synapse into the form data for the TableColumnSchemaForm.\n * Default column models, if available, are used to determine which columns should not be editable in the form.\n * @param columnModels\n * @param defaultColumns\n */\nexport function transformColumnModelsToFormData(\n columnModels: SetOptional<ColumnModel, 'id'>[],\n defaultColumns: ColumnModel[] = [],\n): ColumnModelFormData[] {\n return columnModels.map((cm): ColumnModelFormData => {\n return {\n ...cm,\n columnType: cm.columnType as ColumnTypeEnum,\n maximumSize:\n cm.maximumSize == null ? undefined : cm.maximumSize.toString(),\n maximumListLength:\n cm.maximumListLength == null\n ? undefined\n : cm.maximumListLength.toString(),\n isSelected: false,\n // If the name matches a known default column model, then we consider it to be a default column model itself\n isOriginallyDefaultColumn: defaultColumns.some(\n dcm => dcm.name === cm.name,\n ),\n jsonSubColumns: cm.jsonSubColumns\n ? cm.jsonSubColumns.map(\n (jsc): JsonSubColumnModelFormData => ({\n ...jsc,\n columnType: jsc.columnType as ColumnTypeEnum,\n isSelected: false,\n }),\n )\n : undefined,\n // If this is defaultValue for a LIST column, the value is a serialized string\n defaultValue:\n cm.defaultValue && cm.columnType.endsWith('_LIST')\n ? JSON.parse(cm.defaultValue)\n : cm.defaultValue,\n enumValues:\n cm.enumValues != null\n ? transformEnumValues(cm.enumValues, cm.columnType)\n : undefined,\n }\n })\n}\n\nexport function getViewScopeForEntity(entity: Entity): ViewScope | undefined {\n if (isEntityView(entity)) {\n return {\n scope: entity.scopeIds,\n viewTypeMask: entity.viewTypeMask,\n viewEntityType: convertToEntityType(\n entity.concreteType,\n ) as ViewEntityType,\n }\n } else if (isDataset(entity) || isDatasetCollection(entity)) {\n const mask = isDataset(entity)\n ? ENTITY_VIEW_TYPE_MASK_FILE\n : ENTITY_VIEW_TYPE_MASK_DATASET\n return {\n scope: (entity.items ?? []).map(\n item => `${item.entityId}.${item.versionNumber}`,\n ),\n viewTypeMask: mask,\n viewEntityType: convertToEntityType(\n entity.concreteType,\n ) as ViewEntityType,\n }\n } else if (isSubmissionView(entity)) {\n return {\n scope: entity.scopeIds,\n viewTypeMask: undefined,\n viewEntityType: convertToEntityType(\n entity.concreteType,\n ) as ViewEntityType,\n }\n }\n return undefined\n}\n\nexport function getJsonSchemaItemDefinitionForColumnType(\n columnType: ColumnTypeEnum,\n): JSONSchema7Definition {\n switch (columnType) {\n case ColumnTypeEnum.STRING:\n case ColumnTypeEnum.STRING_LIST:\n return { type: 'string', minLength: 1 }\n case ColumnTypeEnum.DOUBLE:\n return { type: 'number' }\n case ColumnTypeEnum.BOOLEAN:\n case ColumnTypeEnum.BOOLEAN_LIST:\n return { type: 'boolean' }\n case ColumnTypeEnum.INTEGER:\n case ColumnTypeEnum.INTEGER_LIST:\n return { type: 'integer' }\n case ColumnTypeEnum.DATE:\n case ColumnTypeEnum.DATE_LIST:\n return { type: 'string', format: 'datetime' }\n case ColumnTypeEnum.FILEHANDLEID:\n case ColumnTypeEnum.ENTITYID:\n case ColumnTypeEnum.ENTITYID_LIST:\n case ColumnTypeEnum.LINK:\n case ColumnTypeEnum.MEDIUMTEXT:\n case ColumnTypeEnum.LARGETEXT:\n case ColumnTypeEnum.USERID:\n case ColumnTypeEnum.USERID_LIST:\n case ColumnTypeEnum.SUBMISSIONID:\n case ColumnTypeEnum.JSON:\n case ColumnTypeEnum.EVALUATIONID:\n default:\n return { type: 'string', minLength: 1 }\n }\n}\n\nconst columnModelMatchesFormData = (\n model: ColumnModel,\n target: ColumnModelFormData,\n): boolean => {\n return model.name === target.name && model.columnType === target.columnType\n}\n\nexport const findMatchingColumnModel = (\n columnModels: ColumnModel[],\n target: ColumnModelFormData,\n): ColumnModel | undefined => {\n let closestMatch: ColumnModel | undefined\n\n for (const model of columnModels) {\n if (columnModelMatchesFormData(model, target)) {\n closestMatch = model\n break\n }\n }\n\n return closestMatch\n}\n\nexport function getFormDataValueAsNumber(\n formDataValue: string | number | undefined,\n): number | null {\n const maxSize =\n formDataValue !== null ? parseFloat(String(formDataValue)) : null\n const isInteger = Number.isInteger(maxSize)\n return isInteger ? maxSize : null\n}\n\nexport const isFormDataValueSmallerThanRecommendedValue = (\n formDataValue: string | number | undefined,\n recommendedValue: number | undefined,\n): boolean => {\n const currentValue = getFormDataValueAsNumber(formDataValue)\n return recommendedValue != null && currentValue != null && currentValue > 0\n ? currentValue < recommendedValue\n : false\n}\n\nexport function doesColumnModelSatisfyAnnotationMinimums(\n columnModel: ColumnModelFormData,\n annotationColumnModel?: ColumnModel,\n): boolean {\n if (!annotationColumnModel) {\n return true\n }\n\n if (\n isFormDataValueSmallerThanRecommendedValue(\n columnModel.maximumSize,\n annotationColumnModel.maximumSize,\n ) ||\n isFormDataValueSmallerThanRecommendedValue(\n columnModel.maximumListLength,\n annotationColumnModel.maximumListLength,\n )\n ) {\n return false\n }\n\n return true\n}\n\nexport function getNumberOfColumnModelsWithValuesBelowMinimumRecommendedSizes(\n columnModels: ColumnModelFormData[],\n annotationColumnModels: ColumnModel[],\n): number {\n return columnModels.filter(cm => {\n const matchingAnnotationColumnModel = findMatchingColumnModel(\n annotationColumnModels,\n cm,\n )\n\n return !doesColumnModelSatisfyAnnotationMinimums(\n cm,\n matchingAnnotationColumnModel,\n )\n }).length\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TableColumnSchemaEditorUtils.js","names":[],"sources":["../../../src/components/TableColumnSchemaEditor/TableColumnSchemaEditorUtils.ts"],"sourcesContent":["import {\n convertToEntityType,\n isDataset,\n isDatasetCollection,\n isEntityView,\n isSubmissionView,\n} from '@/utils/functions/EntityTypeUtils'\nimport { ViewEntityType } from '@sage-bionetworks/synapse-client'\nimport {\n ColumnModel,\n ColumnType,\n ColumnTypeEnum,\n Entity,\n ENTITY_VIEW_TYPE_MASK_DATASET,\n ENTITY_VIEW_TYPE_MASK_FILE,\n FacetType,\n ViewScope,\n} from '@sage-bionetworks/synapse-types'\nimport { JSONSchema7Definition } from 'json-schema'\nimport { SetOptional } from 'type-fest'\nimport {\n ColumnModelFormData,\n JsonSubColumnModelFormData,\n} from './Validators/ColumnModelValidator'\n\n/**\n * These column types can only be used in Tables. They can not be used in views.\n * See SWC-6333 - for views, only allow column types that are mapped to annotation types.\n */\nconst unsupportedTypesForViews = [ColumnTypeEnum.JSON]\n\n/**\n * Get the allowed column types for a column model based on the table type.\n * @param isView - whether the base table is a view\n * @param isJsonSubColumnFacet - whether the proposed column is a JSON subcolumn facet\n */\nexport function getAllowedColumnTypes(\n isView: boolean,\n isJsonSubColumnFacet: boolean,\n): ColumnTypeEnum[] {\n return Object.values(ColumnTypeEnum)\n .filter(columnType =>\n isView ? !unsupportedTypesForViews.includes(columnType) : true,\n )\n .filter(columnType => {\n if (isJsonSubColumnFacet) {\n switch (columnType) {\n // JSON Subcolumns cannot be JSON or LIST types\n case ColumnTypeEnum.JSON:\n case ColumnTypeEnum.STRING_LIST:\n case ColumnTypeEnum.INTEGER_LIST:\n case ColumnTypeEnum.BOOLEAN_LIST:\n case ColumnTypeEnum.DATE_LIST:\n case ColumnTypeEnum.USERID_LIST:\n case ColumnTypeEnum.ENTITYID_LIST:\n return false\n default:\n return true\n }\n }\n return true\n })\n}\n\nexport function getFacetTypeFriendlyName(facetType: FacetType) {\n switch (facetType) {\n case 'enumeration':\n return 'Values'\n case 'range':\n return 'Range'\n default:\n return facetType\n }\n}\nexport function getColumnTypeFriendlyName(type: ColumnType | ColumnTypeEnum) {\n switch (type) {\n case ColumnTypeEnum.STRING:\n return 'String'\n case ColumnTypeEnum.DOUBLE:\n return 'Double'\n case ColumnTypeEnum.BOOLEAN:\n return 'Boolean'\n case ColumnTypeEnum.INTEGER:\n return 'Integer'\n case ColumnTypeEnum.DATE:\n return 'Date'\n case ColumnTypeEnum.FILEHANDLEID:\n return 'File'\n case ColumnTypeEnum.ENTITYID:\n return 'Entity'\n case ColumnTypeEnum.LINK:\n return 'Link'\n case ColumnTypeEnum.MEDIUMTEXT:\n return 'MediumText'\n case ColumnTypeEnum.LARGETEXT:\n return 'LargeText'\n case ColumnTypeEnum.USERID:\n return 'User'\n case ColumnTypeEnum.STRING_LIST:\n return 'String List'\n case ColumnTypeEnum.INTEGER_LIST:\n return 'Integer List'\n case ColumnTypeEnum.BOOLEAN_LIST:\n return 'Boolean List'\n case ColumnTypeEnum.DATE_LIST:\n return 'Date List'\n case ColumnTypeEnum.USERID_LIST:\n return 'User ID List'\n case ColumnTypeEnum.ENTITYID_LIST:\n return 'Entity ID List'\n case ColumnTypeEnum.EVALUATIONID:\n return 'Evaluation'\n case ColumnTypeEnum.SUBMISSIONID:\n return 'Submission'\n case ColumnTypeEnum.JSON:\n return 'JSON'\n default:\n return type\n }\n}\n\n/**\n * Can the given type have a size?\n *\n * @param type\n * @return\n */\nexport function canHaveSize(type: ColumnType | ColumnTypeEnum): boolean {\n switch (type) {\n case ColumnTypeEnum.STRING:\n case ColumnTypeEnum.STRING_LIST:\n case ColumnTypeEnum.LINK:\n return true\n default:\n // all others are false\n return false\n }\n}\n\nexport function canHaveMaxListLength(\n type: ColumnType | ColumnTypeEnum,\n): boolean {\n switch (type) {\n case ColumnTypeEnum.STRING_LIST:\n case ColumnTypeEnum.BOOLEAN_LIST:\n case ColumnTypeEnum.DATE_LIST:\n case ColumnTypeEnum.INTEGER_LIST:\n case ColumnTypeEnum.ENTITYID_LIST:\n return true\n default:\n // all others are false\n return false\n }\n}\n\n/**\n * Configure the facet selection based on the column type\n *\n * @param type a ColumnType for which to get the facet selection\n * @param isJsonSubColumnFacet is this a facet for a json subcolumn?\n * @return the allowed facetTypes, or null if faceting is not allowed\n */\nexport function configureFacetsForType(\n type: ColumnType | ColumnTypeEnum,\n isJsonSubColumnFacet: boolean,\n): (FacetType | undefined)[] | null {\n let allowedFacetTypes: (FacetType | undefined)[] | null\n switch (type) {\n case ColumnTypeEnum.INTEGER:\n case ColumnTypeEnum.INTEGER_LIST:\n allowedFacetTypes = ['enumeration', 'range']\n break\n case ColumnTypeEnum.STRING:\n case ColumnTypeEnum.BOOLEAN:\n case ColumnTypeEnum.USERID:\n case ColumnTypeEnum.ENTITYID:\n case ColumnTypeEnum.STRING_LIST:\n case ColumnTypeEnum.BOOLEAN_LIST:\n case ColumnTypeEnum.ENTITYID_LIST:\n case ColumnTypeEnum.USERID_LIST:\n case ColumnTypeEnum.EVALUATIONID:\n allowedFacetTypes = ['enumeration']\n break\n case ColumnTypeEnum.DOUBLE:\n case ColumnTypeEnum.DATE:\n case ColumnTypeEnum.DATE_LIST:\n allowedFacetTypes = ['range']\n break\n default:\n allowedFacetTypes = null\n }\n\n if (allowedFacetTypes && !isJsonSubColumnFacet) {\n // jsonSubColumn facets MUST have a facet definition, but regular column models do not need one\n // So allow `undefined` for regular columnModels.\n allowedFacetTypes = [undefined, ...allowedFacetTypes]\n }\n return allowedFacetTypes\n}\n\nexport function canHaveDefault(\n type: ColumnType | ColumnTypeEnum,\n isView: boolean,\n isJsonSubColumnFacet: boolean,\n) {\n // SWC-6333: default types are not allowed in views\n if (isView) {\n return false\n } else if (isJsonSubColumnFacet) {\n return false\n } else {\n switch (type) {\n case ColumnTypeEnum.ENTITYID:\n case ColumnTypeEnum.ENTITYID_LIST:\n case ColumnTypeEnum.FILEHANDLEID:\n case ColumnTypeEnum.USERID:\n case ColumnTypeEnum.USERID_LIST:\n case ColumnTypeEnum.MEDIUMTEXT:\n case ColumnTypeEnum.LARGETEXT:\n case ColumnTypeEnum.JSON:\n case ColumnTypeEnum.SUBMISSIONID:\n case ColumnTypeEnum.EVALUATIONID:\n return false\n default:\n return true\n }\n }\n}\n\nexport const DEFAULT_STRING_SIZE = 50\nexport const MAX_STRING_SIZE = 1000\nexport const MAX_LIST_LENGTH = 100\n\n/**\n * Get the default max size for a given type.\n *\n * @param type\n * @return\n */\nexport function getMaxSizeForType(type: ColumnType | ColumnTypeEnum): number {\n switch (type) {\n case ColumnTypeEnum.STRING:\n case ColumnTypeEnum.STRING_LIST:\n case ColumnTypeEnum.LINK:\n return MAX_STRING_SIZE\n default:\n throw new Error(`Type is not known to have a max size: ${type}`)\n }\n}\n\nexport function canHaveRestrictedValues(\n type: ColumnType | ColumnTypeEnum,\n isJsonSubColumnFacet: boolean,\n): boolean {\n if (isJsonSubColumnFacet) {\n return false\n }\n switch (type) {\n case ColumnTypeEnum.STRING:\n case ColumnTypeEnum.INTEGER:\n case ColumnTypeEnum.ENTITYID:\n return true\n default:\n // all other are false\n return false\n }\n}\n\nfunction transformEnumValues(\n enumValues: string[],\n columnType: ColumnType | ColumnTypeEnum,\n): (string | number)[] {\n // SWC-6622 - Special case: if these are INTEGER, convert to numbers before inserting data into form components\n // The editor validates that these are integers, so inserting the strings returned by the API causes an\n // unexpected validation error\n if (columnType === ColumnTypeEnum.INTEGER) {\n return enumValues.map(value => parseInt(value))\n }\n return enumValues\n}\n\n/**\n * Transform ColumnModels returned by Synapse into the form data for the TableColumnSchemaForm.\n * Default column models, if available, are used to determine which columns should not be editable in the form.\n * @param columnModels\n * @param defaultColumns\n */\nexport function transformColumnModelsToFormData(\n columnModels: SetOptional<ColumnModel, 'id'>[],\n defaultColumns: ColumnModel[] = [],\n): ColumnModelFormData[] {\n return columnModels.map((cm): ColumnModelFormData => {\n return {\n ...cm,\n columnType: cm.columnType as ColumnTypeEnum,\n maximumSize:\n cm.maximumSize == null ? undefined : cm.maximumSize.toString(),\n maximumListLength:\n cm.maximumListLength == null\n ? undefined\n : cm.maximumListLength.toString(),\n isSelected: false,\n // If the name matches a known default column model, then we consider it to be a default column model itself\n isOriginallyDefaultColumn: defaultColumns.some(\n dcm => dcm.name === cm.name,\n ),\n jsonSubColumns: cm.jsonSubColumns\n ? cm.jsonSubColumns.map(\n (jsc): JsonSubColumnModelFormData => ({\n ...jsc,\n columnType: jsc.columnType as ColumnTypeEnum,\n isSelected: false,\n }),\n )\n : undefined,\n // If this is defaultValue for a LIST column, the value is a serialized string\n defaultValue:\n cm.defaultValue && cm.columnType.endsWith('_LIST')\n ? JSON.parse(cm.defaultValue)\n : cm.defaultValue,\n enumValues:\n cm.enumValues != null\n ? transformEnumValues(cm.enumValues, cm.columnType)\n : undefined,\n }\n })\n}\n\nexport function getViewScopeForEntity(entity: Entity): ViewScope | undefined {\n if (isEntityView(entity)) {\n return {\n scope: entity.scopeIds,\n viewTypeMask: entity.viewTypeMask,\n viewEntityType: convertToEntityType(\n entity.concreteType,\n ) as ViewEntityType,\n }\n } else if (isDataset(entity) || isDatasetCollection(entity)) {\n const mask = isDataset(entity)\n ? ENTITY_VIEW_TYPE_MASK_FILE\n : ENTITY_VIEW_TYPE_MASK_DATASET\n return {\n scope: (entity.items ?? []).map(\n item => `${item.entityId}.${item.versionNumber}`,\n ),\n viewTypeMask: mask,\n viewEntityType: convertToEntityType(\n entity.concreteType,\n ) as ViewEntityType,\n }\n } else if (isSubmissionView(entity)) {\n return {\n scope: entity.scopeIds,\n viewTypeMask: undefined,\n viewEntityType: convertToEntityType(\n entity.concreteType,\n ) as ViewEntityType,\n }\n }\n return undefined\n}\n\nexport function getJsonSchemaItemDefinitionForColumnType(\n columnType: ColumnTypeEnum,\n): JSONSchema7Definition {\n switch (columnType) {\n case ColumnTypeEnum.STRING:\n case ColumnTypeEnum.STRING_LIST:\n return { type: 'string', minLength: 1 }\n case ColumnTypeEnum.DOUBLE:\n return { type: 'number' }\n case ColumnTypeEnum.BOOLEAN:\n case ColumnTypeEnum.BOOLEAN_LIST:\n return { type: 'boolean' }\n case ColumnTypeEnum.INTEGER:\n case ColumnTypeEnum.INTEGER_LIST:\n return { type: 'integer' }\n case ColumnTypeEnum.DATE:\n case ColumnTypeEnum.DATE_LIST:\n return { type: 'string', format: 'datetime' }\n case ColumnTypeEnum.FILEHANDLEID:\n case ColumnTypeEnum.ENTITYID:\n case ColumnTypeEnum.ENTITYID_LIST:\n case ColumnTypeEnum.LINK:\n case ColumnTypeEnum.MEDIUMTEXT:\n case ColumnTypeEnum.LARGETEXT:\n case ColumnTypeEnum.USERID:\n case ColumnTypeEnum.USERID_LIST:\n case ColumnTypeEnum.SUBMISSIONID:\n case ColumnTypeEnum.JSON:\n case ColumnTypeEnum.EVALUATIONID:\n default:\n return { type: 'string', minLength: 1 }\n }\n}\n\nconst columnModelMatchesFormData = (\n model: ColumnModel,\n target: ColumnModelFormData,\n): boolean => {\n return model.name === target.name && model.columnType === target.columnType\n}\n\nexport const findMatchingColumnModel = (\n columnModels: ColumnModel[],\n target: ColumnModelFormData,\n): ColumnModel | undefined => {\n let closestMatch: ColumnModel | undefined\n\n for (const model of columnModels) {\n if (columnModelMatchesFormData(model, target)) {\n closestMatch = model\n break\n }\n }\n\n return closestMatch\n}\n\nexport function getFormDataValueAsNumber(\n formDataValue: string | number | undefined,\n): number | null {\n const maxSize =\n formDataValue !== null ? parseFloat(String(formDataValue)) : null\n const isInteger = Number.isInteger(maxSize)\n return isInteger ? maxSize : null\n}\n\nexport const isFormDataValueSmallerThanRecommendedValue = (\n formDataValue: string | number | undefined,\n recommendedValue: number | undefined,\n): boolean => {\n const currentValue = getFormDataValueAsNumber(formDataValue)\n return recommendedValue != null && currentValue != null && currentValue > 0\n ? currentValue < recommendedValue\n : false\n}\n\nexport function doesColumnModelSatisfyAnnotationMinimums(\n columnModel: ColumnModelFormData,\n annotationColumnModel?: ColumnModel,\n): boolean {\n if (!annotationColumnModel) {\n return true\n }\n\n if (\n isFormDataValueSmallerThanRecommendedValue(\n columnModel.maximumSize,\n annotationColumnModel.maximumSize,\n ) ||\n isFormDataValueSmallerThanRecommendedValue(\n columnModel.maximumListLength,\n annotationColumnModel.maximumListLength,\n )\n ) {\n return false\n }\n\n return true\n}\n\nexport function getNumberOfColumnModelsWithValuesBelowMinimumRecommendedSizes(\n columnModels: ColumnModelFormData[],\n annotationColumnModels: ColumnModel[],\n): number {\n return columnModels.filter(cm => {\n const matchingAnnotationColumnModel = findMatchingColumnModel(\n annotationColumnModels,\n cm,\n )\n\n return !doesColumnModelSatisfyAnnotationMinimums(\n cm,\n matchingAnnotationColumnModel,\n )\n }).length\n}\n"],"mappings":"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"}
|
|
@@ -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 // eslint-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(\n ref,\n () => {\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 },\n [onSubmit, validateInternal],\n )\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.errors, 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'\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 // eslint-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(\n ref,\n () => {\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 },\n [onSubmit, validateInternal],\n )\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.errors, 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":"TableColumnSchemaFormReducer.js","names":[],"sources":["../../../src/components/TableColumnSchemaEditor/TableColumnSchemaFormReducer.ts"],"sourcesContent":["import { ColumnModel, ColumnTypeEnum } from '@sage-bionetworks/synapse-types'\nimport { atomWithReducer } from 'jotai/utils'\nimport { cloneDeep } from 'lodash-es'\nimport {\n canHaveMaxListLength,\n canHaveSize,\n configureFacetsForType,\n DEFAULT_STRING_SIZE,\n findMatchingColumnModel,\n isFormDataValueSmallerThanRecommendedValue,\n} from './TableColumnSchemaEditorUtils'\nimport {\n ColumnModelFormData,\n JsonSubColumnModelFormData,\n} from './Validators/ColumnModelValidator'\n\nexport function getIsAllSelected(formData: ColumnModelFormData[]) {\n return (\n formData.length > 0 &&\n formData.every(\n cm =>\n // Is selected\n cm.isSelected &&\n // And all subcolumns are selected (true if there are no subcolumns)\n (cm.jsonSubColumns ?? []).every(\n (jsc: JsonSubColumnModelFormData) => jsc.isSelected,\n ),\n )\n )\n}\n\nexport function getNumberOfSelectedItems(formData: ColumnModelFormData[]) {\n return formData.reduce((acc, curr) => {\n if (curr.isSelected) {\n acc += 1\n }\n if (curr.jsonSubColumns) {\n curr.jsonSubColumns.forEach((jsc: JsonSubColumnModelFormData) => {\n if (jsc.isSelected) {\n acc += 1\n }\n })\n }\n return acc\n }, 0)\n}\n\nexport function getDefaultColumnModelFormData(): ColumnModelFormData {\n return {\n name: '',\n columnType: ColumnTypeEnum.STRING,\n maximumSize: DEFAULT_STRING_SIZE,\n isOriginallyDefaultColumn: false,\n isSelected: false,\n }\n}\n\nexport function getDefaultJsonSubColumnFormData(): JsonSubColumnModelFormData {\n return {\n name: '',\n jsonPath: '',\n columnType: ColumnTypeEnum.STRING,\n facetType: 'enumeration',\n isSelected: false,\n }\n}\n\n/**\n * In the provided array, move items up where the predicate evaluates to true\n * @param arr the array to reorder\n * @param predicate a function that returns true if the item should be moved up\n * @returns - a new array with the reordered items\n */\nfunction moveSelectedItemsUp<T = unknown>(\n arr: T[],\n predicate: (item: T) => boolean,\n) {\n const newArr = [...arr]\n newArr.forEach((item, index) => {\n // For each item that should move up, swap it with the previous item\n if (\n // Cannot move index 0 up\n index > 0 &&\n // Only move if the predicate matches\n predicate(item) &&\n // If the previous item should also move, skip the swap\n !predicate(newArr[index - 1])\n ) {\n // swap the items\n const temp = newArr[index - 1]\n newArr[index - 1] = newArr[index]\n newArr[index] = temp\n }\n })\n return newArr\n}\n\n/**\n * In the provided array, move items down where the predicate evaluates to true\n * @param arr the array to reorder\n * @param predicate a function that returns true if the item should be moved down\n * @returns - a new array with the reordered items\n */\nfunction moveSelectedItemsDown<T = unknown>(\n arr: T[],\n predicate: (item: T) => boolean,\n) {\n const newArr = [...arr]\n // Start from the end and work backwards, otherwise items could be moved more than once\n for (let i = newArr.length - 1; i >= 0; i--) {\n const item = newArr[i]\n if (\n // Cannot move the last item down\n i < newArr.length - 1 &&\n // Only move if the predicate matches\n predicate(item) &&\n // If the next item should also be moved, don't swap\n !predicate(newArr[i + 1])\n ) {\n // swap the items\n const temp = newArr[i]\n newArr[i] = newArr[i + 1]\n newArr[i + 1] = temp\n }\n }\n return newArr\n}\n\ntype TableColumnSchemaFormReducerAction =\n | {\n type: 'setValue'\n value: ColumnModelFormData[]\n }\n | {\n type: 'toggleSelect'\n columnModelIndex: number\n jsonSubColumnModelIndex?: number\n }\n | { type: 'toggleSelectAll' }\n | {\n type: 'appendColumn'\n }\n | {\n type: 'appendJsonSubColumn'\n columnModelIndex: number\n }\n | {\n type: 'setColumnModelValue'\n columnModelIndex: number\n jsonSubColumnModelIndex?: number\n value: ColumnModelFormData | JsonSubColumnModelFormData\n }\n | {\n type: 'changeColumnModelType'\n newColumnType: ColumnTypeEnum\n columnModelIndex: number\n jsonSubColumnModelIndex?: number\n }\n | {\n type: 'move'\n from: {\n columnModelIndex: number\n jsonSubColumnModelIndex?: number\n }\n to: { columnModelIndex: number; jsonSubColumnModelIndex?: number }\n }\n | {\n type: 'moveUp'\n }\n | {\n type: 'moveDown'\n }\n | {\n type: 'delete'\n }\n | {\n type: 'updateColumnSizesToRecommendedValues'\n annotationColumnModels: ColumnModel[]\n }\n\nfunction updateColumnSizesToRecommendedValues(\n action: {\n type: 'updateColumnSizesToRecommendedValues'\n annotationColumnModels: ColumnModel[]\n },\n prevState: ColumnModelFormData[],\n): ColumnModelFormData[] {\n const { annotationColumnModels } = action\n return prevState.map(cm => {\n // Note: no need to check JSON subcolumns, because Views cannot have JSON data!\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, cm)\n : undefined\n\n if (defaultAnnotationModel == null) {\n // No matching annotation column, so do not change it\n return cm\n }\n\n if (\n isFormDataValueSmallerThanRecommendedValue(\n cm.maximumSize,\n defaultAnnotationModel.maximumSize,\n )\n ) {\n cm = { ...cm, maximumSize: defaultAnnotationModel.maximumSize }\n }\n\n if (\n isFormDataValueSmallerThanRecommendedValue(\n cm.maximumListLength,\n defaultAnnotationModel.maximumListLength,\n )\n ) {\n cm = {\n ...cm,\n maximumListLength: defaultAnnotationModel.maximumListLength,\n }\n }\n return cm\n })\n}\n\nfunction changeColumnModelType(\n action: {\n type: 'changeColumnModelType'\n newColumnType: ColumnTypeEnum\n columnModelIndex: number\n jsonSubColumnModelIndex?: number\n },\n prevState: ColumnModelFormData[],\n) {\n const { columnModelIndex, jsonSubColumnModelIndex, newColumnType } = action\n let newColumnModelValue: ColumnModelFormData | JsonSubColumnModelFormData\n\n // Create a copy of the selected column model\n if (prevState && prevState[columnModelIndex]) {\n if (\n prevState[columnModelIndex].jsonSubColumns &&\n jsonSubColumnModelIndex !== undefined\n ) {\n newColumnModelValue = cloneDeep(\n prevState[columnModelIndex].jsonSubColumns[jsonSubColumnModelIndex],\n )\n } else {\n newColumnModelValue = cloneDeep(prevState[columnModelIndex])\n }\n } else {\n throw new Error(\n 'Cannot change column model type for a column that does not exist',\n )\n }\n\n // Update the column model. Remove fields that no longer make sense for the new column type\n newColumnModelValue.columnType = newColumnType\n if (!canHaveSize(newColumnType) && 'maximumSize' in newColumnModelValue) {\n delete newColumnModelValue.maximumSize\n }\n if (\n !canHaveMaxListLength(newColumnType) &&\n 'maximumListLength' in newColumnModelValue\n ) {\n delete newColumnModelValue.maximumListLength\n }\n\n // Remove default and restricted values unconditionally since they may not adhere to the new column type\n if ('enumValues' in newColumnModelValue) {\n delete newColumnModelValue.enumValues\n }\n if ('defaultValue' in newColumnModelValue) {\n delete newColumnModelValue.defaultValue\n }\n\n const allowedFacetTypes = configureFacetsForType(\n newColumnType,\n !!jsonSubColumnModelIndex,\n )\n if (\n 'facetType' in newColumnModelValue &&\n (allowedFacetTypes === null ||\n !allowedFacetTypes.includes(newColumnModelValue.facetType))\n ) {\n delete newColumnModelValue.facetType\n }\n\n if (\n 'jsonSubColumns' in newColumnModelValue &&\n newColumnType !== ColumnTypeEnum.JSON\n ) {\n delete newColumnModelValue.jsonSubColumns\n }\n\n // Replace the value\n if (prevState && prevState[columnModelIndex]) {\n if (\n prevState[columnModelIndex].jsonSubColumns &&\n jsonSubColumnModelIndex !== undefined\n ) {\n prevState[columnModelIndex].jsonSubColumns[jsonSubColumnModelIndex] =\n newColumnModelValue as JsonSubColumnModelFormData\n } else {\n prevState[columnModelIndex] = newColumnModelValue as ColumnModelFormData\n }\n }\n}\n\nfunction toggleSelectAll(prevState: ColumnModelFormData[]) {\n const allSelected = getIsAllSelected(prevState)\n if (allSelected) {\n return prevState.map(cm => ({\n ...cm,\n jsonSubColumns: cm.jsonSubColumns?.map(jsc => ({\n ...jsc,\n isSelected: false,\n })),\n isSelected: false,\n }))\n } else {\n return prevState.map(cm => ({\n ...cm,\n jsonSubColumns: cm.jsonSubColumns?.map(jsc => ({\n ...jsc,\n isSelected: true,\n })),\n isSelected: true,\n }))\n }\n}\n\nfunction setColumnModelValue(\n action: {\n type: 'setColumnModelValue'\n columnModelIndex: number\n jsonSubColumnModelIndex?: number\n value: ColumnModelFormData | JsonSubColumnModelFormData\n },\n prevState: ColumnModelFormData[],\n) {\n const { columnModelIndex, jsonSubColumnModelIndex, value } = action\n if (prevState && prevState[columnModelIndex]) {\n if (\n prevState[columnModelIndex].jsonSubColumns &&\n jsonSubColumnModelIndex !== undefined\n ) {\n prevState[columnModelIndex].jsonSubColumns[jsonSubColumnModelIndex] =\n value as JsonSubColumnModelFormData\n } else {\n prevState[columnModelIndex] = value as ColumnModelFormData\n }\n }\n}\n\nfunction toggleSelect(\n action: {\n type: 'toggleSelect'\n columnModelIndex: number\n jsonSubColumnModelIndex?: number\n },\n prevState: ColumnModelFormData[],\n) {\n const { columnModelIndex, jsonSubColumnModelIndex } = action\n if (prevState && prevState[columnModelIndex]) {\n if (\n prevState[columnModelIndex].jsonSubColumns &&\n jsonSubColumnModelIndex !== undefined\n ) {\n const cm =\n prevState[columnModelIndex].jsonSubColumns[jsonSubColumnModelIndex]\n prevState[columnModelIndex].jsonSubColumns[jsonSubColumnModelIndex] = {\n ...cm,\n isSelected: !cm.isSelected,\n }\n } else {\n const cm = prevState[columnModelIndex]\n prevState[columnModelIndex] = { ...cm, isSelected: !cm.isSelected }\n }\n }\n}\n\nfunction deleteColumnModel(prevState: ColumnModelFormData[]) {\n return prevState\n .filter(cm => !cm.isSelected)\n .map(cm => {\n if (cm.jsonSubColumns) {\n cm = {\n ...cm,\n jsonSubColumns: cm.jsonSubColumns.filter(\n (jsc: JsonSubColumnModelFormData) => !jsc.isSelected,\n ),\n }\n }\n return cm\n })\n}\n\n/**\n * Returns a new, shallowly-cloned array that moves the object from the `fromIndex` to the `toIndex`.\n * Derived from https://stackoverflow.com/a/6470794/9723359\n *\n * Returns the same array if the `fromIndex` and `toIndex` are the same.\n * @param arrayToReorder\n * @param fromIndex\n * @param toIndex\n */\nfunction moveElementInArray<T = unknown>(\n arrayToReorder: Array<T>,\n fromIndex: number,\n toIndex: number,\n): Array<T> {\n if (fromIndex == toIndex) {\n return arrayToReorder\n }\n const newArray = [...arrayToReorder]\n const elementToMove = newArray[fromIndex]\n newArray.splice(fromIndex, 1)\n newArray.splice(toIndex, 0, elementToMove)\n return newArray\n}\n\n/**\n * Moves a column model or jsonSubColumn from the `from` index to the `to` index\n * @param action\n * @param prevState\n */\nfunction moveColumnModel(\n action: {\n type: 'move'\n from: { columnModelIndex: number; jsonSubColumnModelIndex?: number }\n to: { columnModelIndex: number; jsonSubColumnModelIndex?: number }\n },\n prevState: ColumnModelFormData[],\n): ColumnModelFormData[] {\n const { from, to } = action\n const arrayToReorder =\n from.jsonSubColumnModelIndex !== undefined\n ? prevState[from.columnModelIndex].jsonSubColumns!\n : prevState\n\n const fromIndex =\n from.jsonSubColumnModelIndex !== undefined\n ? from.jsonSubColumnModelIndex\n : from.columnModelIndex\n\n const toIndex =\n to.jsonSubColumnModelIndex !== undefined\n ? to.jsonSubColumnModelIndex\n : to.columnModelIndex\n\n // Move the element\n const newArray = moveElementInArray<unknown>(\n arrayToReorder,\n fromIndex,\n toIndex,\n ) as ColumnModelFormData[] | JsonSubColumnModelFormData[]\n\n if (from.jsonSubColumnModelIndex !== undefined) {\n // If we moved a jsonSubColumn, update state to use the new, reordered array\n prevState[from.columnModelIndex].jsonSubColumns =\n newArray as JsonSubColumnModelFormData[]\n return prevState\n } else {\n // Otherwise, return the new, reordered array of column models\n return newArray as ColumnModelFormData[]\n }\n}\n\nexport function reducer(\n prevState: ColumnModelFormData[],\n action: TableColumnSchemaFormReducerAction,\n) {\n switch (action.type) {\n case 'setValue':\n prevState = action.value\n break\n case 'toggleSelectAll': {\n prevState = toggleSelectAll(prevState)\n break\n }\n case 'setColumnModelValue': {\n setColumnModelValue(action, prevState)\n break\n }\n case 'changeColumnModelType': {\n changeColumnModelType(action, prevState)\n break\n }\n\n case 'appendColumn':\n prevState.push(getDefaultColumnModelFormData())\n break\n case 'appendJsonSubColumn': {\n const { columnModelIndex } = action\n prevState[columnModelIndex] = {\n ...prevState[columnModelIndex],\n jsonSubColumns: [\n ...(prevState[columnModelIndex].jsonSubColumns ?? []),\n getDefaultJsonSubColumnFormData(),\n ],\n }\n break\n }\n case 'toggleSelect': {\n toggleSelect(action, prevState)\n break\n }\n case 'delete':\n prevState = deleteColumnModel(prevState)\n break\n case 'move': {\n prevState = moveColumnModel(action, prevState)\n break\n }\n case 'moveUp':\n prevState = moveSelectedItemsUp(prevState, cm => cm.isSelected)\n prevState.forEach(cm => {\n if (cm.jsonSubColumns) {\n cm.jsonSubColumns = moveSelectedItemsUp(\n cm.jsonSubColumns,\n jsc => jsc.isSelected,\n )\n }\n })\n break\n case 'moveDown':\n prevState = moveSelectedItemsDown(prevState, cm => cm.isSelected)\n prevState.forEach(cm => {\n if (cm.jsonSubColumns) {\n cm.jsonSubColumns = moveSelectedItemsDown(\n cm.jsonSubColumns,\n jsc => jsc.isSelected,\n )\n }\n })\n break\n case 'updateColumnSizesToRecommendedValues':\n prevState = updateColumnSizesToRecommendedValues(action, prevState)\n break\n default:\n throw new Error(`Unexpected action`, action)\n }\n return [...prevState]\n}\n\nexport const tableColumnSchemaFormDataAtom = atomWithReducer<\n ColumnModelFormData[],\n TableColumnSchemaFormReducerAction\n>([], reducer)\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TableColumnSchemaFormReducer.js","names":[],"sources":["../../../src/components/TableColumnSchemaEditor/TableColumnSchemaFormReducer.ts"],"sourcesContent":["import { ColumnModel, ColumnTypeEnum } from '@sage-bionetworks/synapse-types'\nimport { atomWithReducer } from 'jotai/utils'\nimport { cloneDeep } from 'lodash-es'\nimport {\n canHaveMaxListLength,\n canHaveSize,\n configureFacetsForType,\n DEFAULT_STRING_SIZE,\n findMatchingColumnModel,\n isFormDataValueSmallerThanRecommendedValue,\n} from './TableColumnSchemaEditorUtils'\nimport {\n ColumnModelFormData,\n JsonSubColumnModelFormData,\n} from './Validators/ColumnModelValidator'\n\nexport function getIsAllSelected(formData: ColumnModelFormData[]) {\n return (\n formData.length > 0 &&\n formData.every(\n cm =>\n // Is selected\n cm.isSelected &&\n // And all subcolumns are selected (true if there are no subcolumns)\n (cm.jsonSubColumns ?? []).every(\n (jsc: JsonSubColumnModelFormData) => jsc.isSelected,\n ),\n )\n )\n}\n\nexport function getNumberOfSelectedItems(formData: ColumnModelFormData[]) {\n return formData.reduce((acc, curr) => {\n if (curr.isSelected) {\n acc += 1\n }\n if (curr.jsonSubColumns) {\n curr.jsonSubColumns.forEach((jsc: JsonSubColumnModelFormData) => {\n if (jsc.isSelected) {\n acc += 1\n }\n })\n }\n return acc\n }, 0)\n}\n\nexport function getDefaultColumnModelFormData(): ColumnModelFormData {\n return {\n name: '',\n columnType: ColumnTypeEnum.STRING,\n maximumSize: DEFAULT_STRING_SIZE,\n isOriginallyDefaultColumn: false,\n isSelected: false,\n }\n}\n\nexport function getDefaultJsonSubColumnFormData(): JsonSubColumnModelFormData {\n return {\n name: '',\n jsonPath: '',\n columnType: ColumnTypeEnum.STRING,\n facetType: 'enumeration',\n isSelected: false,\n }\n}\n\n/**\n * In the provided array, move items up where the predicate evaluates to true\n * @param arr the array to reorder\n * @param predicate a function that returns true if the item should be moved up\n * @returns - a new array with the reordered items\n */\nfunction moveSelectedItemsUp<T = unknown>(\n arr: T[],\n predicate: (item: T) => boolean,\n) {\n const newArr = [...arr]\n newArr.forEach((item, index) => {\n // For each item that should move up, swap it with the previous item\n if (\n // Cannot move index 0 up\n index > 0 &&\n // Only move if the predicate matches\n predicate(item) &&\n // If the previous item should also move, skip the swap\n !predicate(newArr[index - 1])\n ) {\n // swap the items\n const temp = newArr[index - 1]\n newArr[index - 1] = newArr[index]\n newArr[index] = temp\n }\n })\n return newArr\n}\n\n/**\n * In the provided array, move items down where the predicate evaluates to true\n * @param arr the array to reorder\n * @param predicate a function that returns true if the item should be moved down\n * @returns - a new array with the reordered items\n */\nfunction moveSelectedItemsDown<T = unknown>(\n arr: T[],\n predicate: (item: T) => boolean,\n) {\n const newArr = [...arr]\n // Start from the end and work backwards, otherwise items could be moved more than once\n for (let i = newArr.length - 1; i >= 0; i--) {\n const item = newArr[i]\n if (\n // Cannot move the last item down\n i < newArr.length - 1 &&\n // Only move if the predicate matches\n predicate(item) &&\n // If the next item should also be moved, don't swap\n !predicate(newArr[i + 1])\n ) {\n // swap the items\n const temp = newArr[i]\n newArr[i] = newArr[i + 1]\n newArr[i + 1] = temp\n }\n }\n return newArr\n}\n\ntype TableColumnSchemaFormReducerAction =\n | {\n type: 'setValue'\n value: ColumnModelFormData[]\n }\n | {\n type: 'toggleSelect'\n columnModelIndex: number\n jsonSubColumnModelIndex?: number\n }\n | { type: 'toggleSelectAll' }\n | {\n type: 'appendColumn'\n }\n | {\n type: 'appendJsonSubColumn'\n columnModelIndex: number\n }\n | {\n type: 'setColumnModelValue'\n columnModelIndex: number\n jsonSubColumnModelIndex?: number\n value: ColumnModelFormData | JsonSubColumnModelFormData\n }\n | {\n type: 'changeColumnModelType'\n newColumnType: ColumnTypeEnum\n columnModelIndex: number\n jsonSubColumnModelIndex?: number\n }\n | {\n type: 'move'\n from: {\n columnModelIndex: number\n jsonSubColumnModelIndex?: number\n }\n to: { columnModelIndex: number; jsonSubColumnModelIndex?: number }\n }\n | {\n type: 'moveUp'\n }\n | {\n type: 'moveDown'\n }\n | {\n type: 'delete'\n }\n | {\n type: 'updateColumnSizesToRecommendedValues'\n annotationColumnModels: ColumnModel[]\n }\n\nfunction updateColumnSizesToRecommendedValues(\n action: {\n type: 'updateColumnSizesToRecommendedValues'\n annotationColumnModels: ColumnModel[]\n },\n prevState: ColumnModelFormData[],\n): ColumnModelFormData[] {\n const { annotationColumnModels } = action\n return prevState.map(cm => {\n // Note: no need to check JSON subcolumns, because Views cannot have JSON data!\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, cm)\n : undefined\n\n if (defaultAnnotationModel == null) {\n // No matching annotation column, so do not change it\n return cm\n }\n\n if (\n isFormDataValueSmallerThanRecommendedValue(\n cm.maximumSize,\n defaultAnnotationModel.maximumSize,\n )\n ) {\n cm = { ...cm, maximumSize: defaultAnnotationModel.maximumSize }\n }\n\n if (\n isFormDataValueSmallerThanRecommendedValue(\n cm.maximumListLength,\n defaultAnnotationModel.maximumListLength,\n )\n ) {\n cm = {\n ...cm,\n maximumListLength: defaultAnnotationModel.maximumListLength,\n }\n }\n return cm\n })\n}\n\nfunction changeColumnModelType(\n action: {\n type: 'changeColumnModelType'\n newColumnType: ColumnTypeEnum\n columnModelIndex: number\n jsonSubColumnModelIndex?: number\n },\n prevState: ColumnModelFormData[],\n) {\n const { columnModelIndex, jsonSubColumnModelIndex, newColumnType } = action\n let newColumnModelValue: ColumnModelFormData | JsonSubColumnModelFormData\n\n // Create a copy of the selected column model\n if (prevState && prevState[columnModelIndex]) {\n if (\n prevState[columnModelIndex].jsonSubColumns &&\n jsonSubColumnModelIndex !== undefined\n ) {\n newColumnModelValue = cloneDeep(\n prevState[columnModelIndex].jsonSubColumns[jsonSubColumnModelIndex],\n )\n } else {\n newColumnModelValue = cloneDeep(prevState[columnModelIndex])\n }\n } else {\n throw new Error(\n 'Cannot change column model type for a column that does not exist',\n )\n }\n\n // Update the column model. Remove fields that no longer make sense for the new column type\n newColumnModelValue.columnType = newColumnType\n if (!canHaveSize(newColumnType) && 'maximumSize' in newColumnModelValue) {\n delete newColumnModelValue.maximumSize\n }\n if (\n !canHaveMaxListLength(newColumnType) &&\n 'maximumListLength' in newColumnModelValue\n ) {\n delete newColumnModelValue.maximumListLength\n }\n\n // Remove default and restricted values unconditionally since they may not adhere to the new column type\n if ('enumValues' in newColumnModelValue) {\n delete newColumnModelValue.enumValues\n }\n if ('defaultValue' in newColumnModelValue) {\n delete newColumnModelValue.defaultValue\n }\n\n const allowedFacetTypes = configureFacetsForType(\n newColumnType,\n !!jsonSubColumnModelIndex,\n )\n if (\n 'facetType' in newColumnModelValue &&\n (allowedFacetTypes === null ||\n !allowedFacetTypes.includes(newColumnModelValue.facetType))\n ) {\n delete newColumnModelValue.facetType\n }\n\n if (\n 'jsonSubColumns' in newColumnModelValue &&\n newColumnType !== ColumnTypeEnum.JSON\n ) {\n delete newColumnModelValue.jsonSubColumns\n }\n\n // Replace the value\n if (prevState && prevState[columnModelIndex]) {\n if (\n prevState[columnModelIndex].jsonSubColumns &&\n jsonSubColumnModelIndex !== undefined\n ) {\n prevState[columnModelIndex].jsonSubColumns[jsonSubColumnModelIndex] =\n newColumnModelValue as JsonSubColumnModelFormData\n } else {\n prevState[columnModelIndex] = newColumnModelValue as ColumnModelFormData\n }\n }\n}\n\nfunction toggleSelectAll(prevState: ColumnModelFormData[]) {\n const allSelected = getIsAllSelected(prevState)\n if (allSelected) {\n return prevState.map(cm => ({\n ...cm,\n jsonSubColumns: cm.jsonSubColumns?.map(jsc => ({\n ...jsc,\n isSelected: false,\n })),\n isSelected: false,\n }))\n } else {\n return prevState.map(cm => ({\n ...cm,\n jsonSubColumns: cm.jsonSubColumns?.map(jsc => ({\n ...jsc,\n isSelected: true,\n })),\n isSelected: true,\n }))\n }\n}\n\nfunction setColumnModelValue(\n action: {\n type: 'setColumnModelValue'\n columnModelIndex: number\n jsonSubColumnModelIndex?: number\n value: ColumnModelFormData | JsonSubColumnModelFormData\n },\n prevState: ColumnModelFormData[],\n) {\n const { columnModelIndex, jsonSubColumnModelIndex, value } = action\n if (prevState && prevState[columnModelIndex]) {\n if (\n prevState[columnModelIndex].jsonSubColumns &&\n jsonSubColumnModelIndex !== undefined\n ) {\n prevState[columnModelIndex].jsonSubColumns[jsonSubColumnModelIndex] =\n value as JsonSubColumnModelFormData\n } else {\n prevState[columnModelIndex] = value as ColumnModelFormData\n }\n }\n}\n\nfunction toggleSelect(\n action: {\n type: 'toggleSelect'\n columnModelIndex: number\n jsonSubColumnModelIndex?: number\n },\n prevState: ColumnModelFormData[],\n) {\n const { columnModelIndex, jsonSubColumnModelIndex } = action\n if (prevState && prevState[columnModelIndex]) {\n if (\n prevState[columnModelIndex].jsonSubColumns &&\n jsonSubColumnModelIndex !== undefined\n ) {\n const cm =\n prevState[columnModelIndex].jsonSubColumns[jsonSubColumnModelIndex]\n prevState[columnModelIndex].jsonSubColumns[jsonSubColumnModelIndex] = {\n ...cm,\n isSelected: !cm.isSelected,\n }\n } else {\n const cm = prevState[columnModelIndex]\n prevState[columnModelIndex] = { ...cm, isSelected: !cm.isSelected }\n }\n }\n}\n\nfunction deleteColumnModel(prevState: ColumnModelFormData[]) {\n return prevState\n .filter(cm => !cm.isSelected)\n .map(cm => {\n if (cm.jsonSubColumns) {\n cm = {\n ...cm,\n jsonSubColumns: cm.jsonSubColumns.filter(\n (jsc: JsonSubColumnModelFormData) => !jsc.isSelected,\n ),\n }\n }\n return cm\n })\n}\n\n/**\n * Returns a new, shallowly-cloned array that moves the object from the `fromIndex` to the `toIndex`.\n * Derived from https://stackoverflow.com/a/6470794/9723359\n *\n * Returns the same array if the `fromIndex` and `toIndex` are the same.\n * @param arrayToReorder\n * @param fromIndex\n * @param toIndex\n */\nfunction moveElementInArray<T = unknown>(\n arrayToReorder: Array<T>,\n fromIndex: number,\n toIndex: number,\n): Array<T> {\n if (fromIndex == toIndex) {\n return arrayToReorder\n }\n const newArray = [...arrayToReorder]\n const elementToMove = newArray[fromIndex]\n newArray.splice(fromIndex, 1)\n newArray.splice(toIndex, 0, elementToMove)\n return newArray\n}\n\n/**\n * Moves a column model or jsonSubColumn from the `from` index to the `to` index\n * @param action\n * @param prevState\n */\nfunction moveColumnModel(\n action: {\n type: 'move'\n from: { columnModelIndex: number; jsonSubColumnModelIndex?: number }\n to: { columnModelIndex: number; jsonSubColumnModelIndex?: number }\n },\n prevState: ColumnModelFormData[],\n): ColumnModelFormData[] {\n const { from, to } = action\n const arrayToReorder =\n from.jsonSubColumnModelIndex !== undefined\n ? prevState[from.columnModelIndex].jsonSubColumns!\n : prevState\n\n const fromIndex =\n from.jsonSubColumnModelIndex !== undefined\n ? from.jsonSubColumnModelIndex\n : from.columnModelIndex\n\n const toIndex =\n to.jsonSubColumnModelIndex !== undefined\n ? to.jsonSubColumnModelIndex\n : to.columnModelIndex\n\n // Move the element\n const newArray = moveElementInArray<unknown>(\n arrayToReorder,\n fromIndex,\n toIndex,\n ) as ColumnModelFormData[] | JsonSubColumnModelFormData[]\n\n if (from.jsonSubColumnModelIndex !== undefined) {\n // If we moved a jsonSubColumn, update state to use the new, reordered array\n prevState[from.columnModelIndex].jsonSubColumns =\n newArray as JsonSubColumnModelFormData[]\n return prevState\n } else {\n // Otherwise, return the new, reordered array of column models\n return newArray as ColumnModelFormData[]\n }\n}\n\nexport function reducer(\n prevState: ColumnModelFormData[],\n action: TableColumnSchemaFormReducerAction,\n) {\n switch (action.type) {\n case 'setValue':\n prevState = action.value\n break\n case 'toggleSelectAll': {\n prevState = toggleSelectAll(prevState)\n break\n }\n case 'setColumnModelValue': {\n setColumnModelValue(action, prevState)\n break\n }\n case 'changeColumnModelType': {\n changeColumnModelType(action, prevState)\n break\n }\n\n case 'appendColumn':\n prevState.push(getDefaultColumnModelFormData())\n break\n case 'appendJsonSubColumn': {\n const { columnModelIndex } = action\n prevState[columnModelIndex] = {\n ...prevState[columnModelIndex],\n jsonSubColumns: [\n ...(prevState[columnModelIndex].jsonSubColumns ?? []),\n getDefaultJsonSubColumnFormData(),\n ],\n }\n break\n }\n case 'toggleSelect': {\n toggleSelect(action, prevState)\n break\n }\n case 'delete':\n prevState = deleteColumnModel(prevState)\n break\n case 'move': {\n prevState = moveColumnModel(action, prevState)\n break\n }\n case 'moveUp':\n prevState = moveSelectedItemsUp(prevState, cm => cm.isSelected)\n prevState.forEach(cm => {\n if (cm.jsonSubColumns) {\n cm.jsonSubColumns = moveSelectedItemsUp(\n cm.jsonSubColumns,\n jsc => jsc.isSelected,\n )\n }\n })\n break\n case 'moveDown':\n prevState = moveSelectedItemsDown(prevState, cm => cm.isSelected)\n prevState.forEach(cm => {\n if (cm.jsonSubColumns) {\n cm.jsonSubColumns = moveSelectedItemsDown(\n cm.jsonSubColumns,\n jsc => jsc.isSelected,\n )\n }\n })\n break\n case 'updateColumnSizesToRecommendedValues':\n prevState = updateColumnSizesToRecommendedValues(action, prevState)\n break\n default:\n throw new Error(`Unexpected action`, action)\n }\n return [...prevState]\n}\n\nexport const tableColumnSchemaFormDataAtom = atomWithReducer<\n ColumnModelFormData[],\n TableColumnSchemaFormReducerAction\n>([], reducer)\n"],"mappings":"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"}
|