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":"SynapseChatMessage.js","names":[],"sources":["../../../src/components/SynapseChat/SynapseChatMessage.tsx"],"sourcesContent":["import SynapseChatInteraction from '@/components/SynapseChat/SynapseChatInteraction'\nimport usePollAsynchronousJob from '@/synapse-queries/asynchronous/usePollAsynchronousJob'\nimport { useGetChatAgentTraceEvents } from '@/synapse-queries/chat/useChat'\nimport {\n AgentChatRequest,\n AgentChatResponse,\n TraceEvent,\n} from '@sage-bionetworks/synapse-types'\nimport { useCallback, useEffect, useState } from 'react'\n\nfunction useTraceEvent(chatJobId: string, enabled: boolean) {\n const [traceEvents, setTraceEvents] = useState<TraceEvent[]>([])\n\n const appendTraceEvents = useCallback((newEvents: TraceEvent[]) => {\n setTraceEvents(prev => {\n return [...prev, ...newEvents]\n })\n }, [])\n\n const latestTraceEvent = traceEvents.at(traceEvents.length - 1)\n const { data: newTraceEvents } = useGetChatAgentTraceEvents(\n {\n jobId: chatJobId,\n newerThanTimestamp: latestTraceEvent?.timestamp,\n },\n {\n enabled: enabled,\n refetchInterval: 1000, // Re-fetch every second if enabled\n refetchIntervalInBackground: true, // Continue polling even when the tab is not active\n },\n )\n useEffect(() => {\n if (newTraceEvents && newTraceEvents.page.length > 0) {\n appendTraceEvents(newTraceEvents.page)\n\n // send trace events to the console to ease agent debugging\n // if the trace events do not contain the latest event, add the events to the array\n console.debug(newTraceEvents.page)\n }\n }, [appendTraceEvents, newTraceEvents])\n\n return {\n traceEvents,\n }\n}\n\ntype SynapseChatMessageProps = {\n chatJobId: string\n onSendChat?: (message: string) => void\n}\n\nexport default function SynapseChatMessage(props: SynapseChatMessageProps) {\n const { chatJobId, onSendChat } = props\n const { data: asyncJobStatus } = usePollAsynchronousJob(chatJobId)\n\n const chatRequest = asyncJobStatus?.requestBody as AgentChatRequest\n const chatResponse = asyncJobStatus?.responseBody as\n | AgentChatResponse\n | undefined\n const chatError = asyncJobStatus?.errorMessage\n\n // enabled if the job has not finished processing\n const enableTrace =\n !!chatJobId &&\n (!asyncJobStatus?.jobState || asyncJobStatus.jobState == 'PROCESSING')\n const { traceEvents } = useTraceEvent(chatJobId, enableTrace)\n\n return (\n <SynapseChatInteraction\n userMessage={chatRequest?.chatText}\n chatResponseText={chatResponse?.responseText}\n chatResponseTrace={traceEvents}\n chatErrorReason={chatError}\n onSendChat={onSendChat}\n />\n )\n}\n"],"mappings":";;;;;;AAUA,SAAS,EAAc,GAAmB,GAAkB;CAC1D,IAAM,CAAC,GAAa,KAAkB,EAAuB,EAAE,CAAC,EAE1D,IAAoB,GAAa,MAA4B;AACjE,KAAe,MACN,CAAC,GAAG,GAAM,GAAG,EAAU,CAC9B;IACD,EAAE,CAAC,EAGA,EAAE,MAAM,MAAmB,EAC/B;EACE,OAAO;EACP,oBAJqB,EAAY,GAAG,EAAY,SAAS,
|
|
1
|
+
{"version":3,"file":"SynapseChatMessage.js","names":[],"sources":["../../../src/components/SynapseChat/SynapseChatMessage.tsx"],"sourcesContent":["import SynapseChatInteraction from '@/components/SynapseChat/SynapseChatInteraction'\nimport usePollAsynchronousJob from '@/synapse-queries/asynchronous/usePollAsynchronousJob'\nimport { useGetChatAgentTraceEvents } from '@/synapse-queries/chat/useChat'\nimport {\n AgentChatRequest,\n AgentChatResponse,\n TraceEvent,\n} from '@sage-bionetworks/synapse-types'\nimport { useCallback, useEffect, useState } from 'react'\n\nfunction useTraceEvent(chatJobId: string, enabled: boolean) {\n const [traceEvents, setTraceEvents] = useState<TraceEvent[]>([])\n\n const appendTraceEvents = useCallback((newEvents: TraceEvent[]) => {\n setTraceEvents(prev => {\n return [...prev, ...newEvents]\n })\n }, [])\n\n const latestTraceEvent = traceEvents.at(traceEvents.length - 1)\n const { data: newTraceEvents } = useGetChatAgentTraceEvents(\n {\n jobId: chatJobId,\n newerThanTimestamp: latestTraceEvent?.timestamp,\n },\n {\n enabled: enabled,\n refetchInterval: 1000, // Re-fetch every second if enabled\n refetchIntervalInBackground: true, // Continue polling even when the tab is not active\n },\n )\n useEffect(() => {\n if (newTraceEvents && newTraceEvents.page.length > 0) {\n appendTraceEvents(newTraceEvents.page)\n\n // send trace events to the console to ease agent debugging\n // if the trace events do not contain the latest event, add the events to the array\n console.debug(newTraceEvents.page)\n }\n }, [appendTraceEvents, newTraceEvents])\n\n return {\n traceEvents,\n }\n}\n\ntype SynapseChatMessageProps = {\n chatJobId: string\n onSendChat?: (message: string) => void\n}\n\nexport default function SynapseChatMessage(props: SynapseChatMessageProps) {\n const { chatJobId, onSendChat } = props\n const { data: asyncJobStatus } = usePollAsynchronousJob(chatJobId)\n\n const chatRequest = asyncJobStatus?.requestBody as AgentChatRequest\n const chatResponse = asyncJobStatus?.responseBody as\n | AgentChatResponse\n | undefined\n const chatError = asyncJobStatus?.errorMessage\n\n // enabled if the job has not finished processing\n const enableTrace =\n !!chatJobId &&\n (!asyncJobStatus?.jobState || asyncJobStatus.jobState == 'PROCESSING')\n const { traceEvents } = useTraceEvent(chatJobId, enableTrace)\n\n return (\n <SynapseChatInteraction\n userMessage={chatRequest?.chatText}\n chatResponseText={chatResponse?.responseText}\n chatResponseTrace={traceEvents}\n chatErrorReason={chatError}\n onSendChat={onSendChat}\n />\n )\n}\n"],"mappings":";;;;;;AAUA,SAAS,EAAc,GAAmB,GAAkB;CAC1D,IAAM,CAAC,GAAa,KAAkB,EAAuB,EAAE,CAAC,EAE1D,IAAoB,GAAa,MAA4B;AACjE,KAAe,MACN,CAAC,GAAG,GAAM,GAAG,EAAU,CAC9B;IACD,EAAE,CAAC,EAGA,EAAE,MAAM,MAAmB,EAC/B;EACE,OAAO;EACP,oBAJqB,EAAY,GAAG,EAAY,SAAS,EAIrC,EAAkB;EACvC,EACD;EACW;EACT,iBAAiB;EACjB,6BAA6B;EAC9B,CACF;AAWD,QAVA,QAAgB;AACd,EAAI,KAAkB,EAAe,KAAK,SAAS,MACjD,EAAkB,EAAe,KAAK,EAItC,QAAQ,MAAM,EAAe,KAAK;IAEnC,CAAC,GAAmB,EAAe,CAAC,EAEhC,EACL,gBACD;;AAQH,SAAwB,EAAmB,GAAgC;CACzE,IAAM,EAAE,cAAW,kBAAe,GAC5B,EAAE,MAAM,MAAmB,EAAuB,EAAU,EAE5D,IAAc,GAAgB,aAC9B,IAAe,GAAgB,cAG/B,IAAY,GAAgB,cAM5B,EAAE,mBAAgB,EAAc,GAFpC,CAAC,CAAC,MACD,CAAC,GAAgB,YAAY,EAAe,YAAY,cACE;AAE7D,QACE,kBAAC,GAAD;EACE,aAAa,GAAa;EAC1B,kBAAkB,GAAc;EAChC,mBAAmB;EACnB,iBAAiB;EACL;EACZ,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extractMessageFromTraceEvent.js","names":[],"sources":["../../../src/components/SynapseChat/extractMessageFromTraceEvent.ts"],"sourcesContent":["import { TraceEvent } from '@sage-bionetworks/synapse-types'\nimport { JSONPath } from 'jsonpath-plus'\n\nexport type TraceMessage =\n | {\n reasoningText: string\n }\n | {\n toolName: string\n toolInput: string\n }\n\nexport default function extractMessageFromTraceEvent(\n event: TraceEvent,\n): TraceMessage[] | null {\n // WARNING: The message format may change when we change models.\n const messagesToAdd: TraceMessage[] = []\n let parsedMessage: object\n try {\n parsedMessage = JSON.parse(event.message) as object\n } catch (e) {\n console.error(e)\n return [{ reasoningText: event.message }]\n }\n\n const messages = JSONPath({\n path: '$.output.message.content[*]',\n json: parsedMessage,\n })\n\n messages.forEach((message: any) => {\n const reasoningMessage = JSONPath({\n path: '$.reasoningContent.reasoningText.text',\n json: message,\n })\n if (reasoningMessage[0]) {\n messagesToAdd.push({ reasoningText: reasoningMessage[0] })\n }\n const toolUseMessage = JSONPath({\n path: '$.toolUse[name,input]',\n json: message,\n })\n\n if (toolUseMessage.length > 0) {\n messagesToAdd.push({\n toolName: toolUseMessage[0],\n toolInput: toolUseMessage[1],\n })\n }\n })\n return messagesToAdd\n}\n"],"mappings":";;AAYA,SAAwB,EACtB,GACuB;CAEvB,IAAM,IAAgC,EAAE,EACpC;AACJ,KAAI;AACF,MAAgB,KAAK,MAAM,EAAM,QAAQ;UAClC,GAAG;AAEV,SADA,QAAQ,MAAM,EAAE,EACT,CAAC,EAAE,eAAe,EAAM,SAAS,CAAC;;AA4B3C,QAzBiB,EAAS;EACxB,MAAM;EACN,MAAM;EACP,
|
|
1
|
+
{"version":3,"file":"extractMessageFromTraceEvent.js","names":[],"sources":["../../../src/components/SynapseChat/extractMessageFromTraceEvent.ts"],"sourcesContent":["import { TraceEvent } from '@sage-bionetworks/synapse-types'\nimport { JSONPath } from 'jsonpath-plus'\n\nexport type TraceMessage =\n | {\n reasoningText: string\n }\n | {\n toolName: string\n toolInput: string\n }\n\nexport default function extractMessageFromTraceEvent(\n event: TraceEvent,\n): TraceMessage[] | null {\n // WARNING: The message format may change when we change models.\n const messagesToAdd: TraceMessage[] = []\n let parsedMessage: object\n try {\n parsedMessage = JSON.parse(event.message) as object\n } catch (e) {\n console.error(e)\n return [{ reasoningText: event.message }]\n }\n\n const messages = JSONPath({\n path: '$.output.message.content[*]',\n json: parsedMessage,\n })\n\n messages.forEach((message: any) => {\n const reasoningMessage = JSONPath({\n path: '$.reasoningContent.reasoningText.text',\n json: message,\n })\n if (reasoningMessage[0]) {\n messagesToAdd.push({ reasoningText: reasoningMessage[0] })\n }\n const toolUseMessage = JSONPath({\n path: '$.toolUse[name,input]',\n json: message,\n })\n\n if (toolUseMessage.length > 0) {\n messagesToAdd.push({\n toolName: toolUseMessage[0],\n toolInput: toolUseMessage[1],\n })\n }\n })\n return messagesToAdd\n}\n"],"mappings":";;AAYA,SAAwB,EACtB,GACuB;CAEvB,IAAM,IAAgC,EAAE,EACpC;AACJ,KAAI;AACF,MAAgB,KAAK,MAAM,EAAM,QAAQ;UAClC,GAAG;AAEV,SADA,QAAQ,MAAM,EAAE,EACT,CAAC,EAAE,eAAe,EAAM,SAAS,CAAC;;AA4B3C,QAzBiB,EAAS;EACxB,MAAM;EACN,MAAM;EACP,CAED,CAAS,SAAS,MAAiB;EACjC,IAAM,IAAmB,EAAS;GAChC,MAAM;GACN,MAAM;GACP,CAAC;AACF,EAAI,EAAiB,MACnB,EAAc,KAAK,EAAE,eAAe,EAAiB,IAAI,CAAC;EAE5D,IAAM,IAAiB,EAAS;GAC9B,MAAM;GACN,MAAM;GACP,CAAC;AAEF,EAAI,EAAe,SAAS,KAC1B,EAAc,KAAK;GACjB,UAAU,EAAe;GACzB,WAAW,EAAe;GAC3B,CAAC;GAEJ,EACK"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StepsSideNav.js","names":[],"sources":["../../../src/components/SynapseForm/StepsSideNav.tsx"],"sourcesContent":["import IconSvg, { IconName } from '../IconSvg/IconSvg'\nimport { Step, StepStateEnum } from './types'\n\nexport type StepsSideNavProps = {\n stepList: Step[]\n onStepChange: (step: Step) => void\n isWizardMode?: boolean\n}\n\nexport default function StepsSideNav(props: StepsSideNavProps) {\n const nonChildSteps = props.stepList.filter(step => step.child !== true)\n\n const getIcon = (\n state: StepStateEnum,\n isExcluded: boolean | undefined,\n isStatic: boolean | undefined,\n isSubmit: boolean | undefined,\n ): { iconDef: IconName } => {\n let iconDef: IconName = 'circle'\n if (isStatic || isSubmit) {\n return {\n iconDef,\n }\n }\n\n if (isExcluded) {\n iconDef = 'block'\n } else if (state === StepStateEnum.COMPLETED) {\n iconDef = 'checkCircle'\n } else if (state === StepStateEnum.ERROR) {\n iconDef = 'errorOutlined'\n }\n return { iconDef }\n }\n\n const getItemClass = (\n isInProgress: boolean,\n isStatic: boolean = false,\n ): string => {\n let liClassName = 'item'\n if (isInProgress) {\n liClassName = `${liClassName} pointed `\n }\n if (isStatic) {\n liClassName = `${liClassName} static`\n }\n return liClassName\n }\n\n const getListItem = (\n step: Step,\n isWizard: boolean,\n isRenderChild = false,\n ) => {\n if (!step || (step.child && !isRenderChild)) {\n return <></>\n }\n const renderStepName = (\n step: Step,\n isWizard: boolean,\n callback: (step: Step) => void,\n ) => {\n if (!step.inProgress && (!isWizard || !!step.final)) {\n return (\n <button className=\"btn btn-link\" onClick={() => callback(step)}>\n {step.title}\n </button>\n )\n } else {\n return <span>{step.title}</span>\n }\n }\n const icon = getIcon(step.state, step.excluded, step.static, step.final)\n const itemClass = getItemClass(step.inProgress, step.static)\n\n return (\n <div className={itemClass}>\n <IconSvg icon={icon.iconDef} />\n {renderStepName(step, isWizard, props.onStepChange)}\n </div>\n )\n }\n\n return (\n <div className=\"SRC-menuLayout json-forms-menu\" style={{ flex: '1' }}>\n <ul>\n {nonChildSteps.map((step: Step, i: number) => {\n return (\n <li className=\"item-wrap\" key={`${i}-${step.id}`}>\n {getListItem(step, !!props.isWizardMode)}\n {step.children && step.children.length > 0 && (\n <div className=\"subMenu\">\n <ul>\n {step.children &&\n step.children.map((stepChildId: string, j: number) => {\n const childStep = props.stepList.find(\n step => step.id === stepChildId,\n )\n return typeof childStep === 'undefined' ? (\n <></>\n ) : (\n <li className=\"item-wrap\" key={`${j}-${stepChildId}`}>\n {getListItem(childStep, !!props.isWizardMode, true)}\n </li>\n )\n })}\n </ul>\n </div>\n )}\n </li>\n )\n })}\n </ul>\n </div>\n )\n}\n"],"mappings":";;;;AASA,SAAwB,EAAa,GAA0B;CAC7D,IAAM,IAAgB,EAAM,SAAS,QAAO,MAAQ,EAAK,UAAU,GAAK,EAElE,KACJ,GACA,GACA,GACA,MAC0B;EAC1B,IAAI,IAAoB;AAcxB,SAbI,KAAY,MAMZ,IACF,IAAU,UACD,MAAU,EAAc,YACjC,IAAU,gBACD,MAAU,EAAc,UACjC,IAAU,mBAVH,EACL,YACD;IAaC,KACJ,GACA,IAAoB,OACT;EACX,IAAI,IAAc;AAOlB,SANI,MACF,IAAc,GAAG,EAAY,aAE3B,MACF,IAAc,GAAG,EAAY,WAExB;IAGH,KACJ,GACA,GACA,IAAgB,OACb;AACH,MAAI,CAAC,KAAS,EAAK,SAAS,CAAC,EAC3B,QAAO,kBAAA,GAAA,EAAK,CAAA;EAEd,IAAM,KACJ,GACA,GACA,MAEI,CAAC,EAAK,eAAe,CAAC,KAAc,EAAK,SAEzC,kBAAC,UAAD;GAAQ,WAAU;GAAe,eAAe,EAAS,EAAK;aAC3D,EAAK;GACC,CAAA,GAGJ,kBAAC,QAAD,EAAA,UAAO,EAAK,OAAa,CAAA,EAG9B,IAAO,EAAQ,EAAK,OAAO,EAAK,UAAU,EAAK,QAAQ,EAAK,MAAM;AAGxE,SACE,kBAAC,OAAD;GAAK,WAHW,EAAa,EAAK,YAAY,EAAK,
|
|
1
|
+
{"version":3,"file":"StepsSideNav.js","names":[],"sources":["../../../src/components/SynapseForm/StepsSideNav.tsx"],"sourcesContent":["import IconSvg, { IconName } from '../IconSvg/IconSvg'\nimport { Step, StepStateEnum } from './types'\n\nexport type StepsSideNavProps = {\n stepList: Step[]\n onStepChange: (step: Step) => void\n isWizardMode?: boolean\n}\n\nexport default function StepsSideNav(props: StepsSideNavProps) {\n const nonChildSteps = props.stepList.filter(step => step.child !== true)\n\n const getIcon = (\n state: StepStateEnum,\n isExcluded: boolean | undefined,\n isStatic: boolean | undefined,\n isSubmit: boolean | undefined,\n ): { iconDef: IconName } => {\n let iconDef: IconName = 'circle'\n if (isStatic || isSubmit) {\n return {\n iconDef,\n }\n }\n\n if (isExcluded) {\n iconDef = 'block'\n } else if (state === StepStateEnum.COMPLETED) {\n iconDef = 'checkCircle'\n } else if (state === StepStateEnum.ERROR) {\n iconDef = 'errorOutlined'\n }\n return { iconDef }\n }\n\n const getItemClass = (\n isInProgress: boolean,\n isStatic: boolean = false,\n ): string => {\n let liClassName = 'item'\n if (isInProgress) {\n liClassName = `${liClassName} pointed `\n }\n if (isStatic) {\n liClassName = `${liClassName} static`\n }\n return liClassName\n }\n\n const getListItem = (\n step: Step,\n isWizard: boolean,\n isRenderChild = false,\n ) => {\n if (!step || (step.child && !isRenderChild)) {\n return <></>\n }\n const renderStepName = (\n step: Step,\n isWizard: boolean,\n callback: (step: Step) => void,\n ) => {\n if (!step.inProgress && (!isWizard || !!step.final)) {\n return (\n <button className=\"btn btn-link\" onClick={() => callback(step)}>\n {step.title}\n </button>\n )\n } else {\n return <span>{step.title}</span>\n }\n }\n const icon = getIcon(step.state, step.excluded, step.static, step.final)\n const itemClass = getItemClass(step.inProgress, step.static)\n\n return (\n <div className={itemClass}>\n <IconSvg icon={icon.iconDef} />\n {renderStepName(step, isWizard, props.onStepChange)}\n </div>\n )\n }\n\n return (\n <div className=\"SRC-menuLayout json-forms-menu\" style={{ flex: '1' }}>\n <ul>\n {nonChildSteps.map((step: Step, i: number) => {\n return (\n <li className=\"item-wrap\" key={`${i}-${step.id}`}>\n {getListItem(step, !!props.isWizardMode)}\n {step.children && step.children.length > 0 && (\n <div className=\"subMenu\">\n <ul>\n {step.children &&\n step.children.map((stepChildId: string, j: number) => {\n const childStep = props.stepList.find(\n step => step.id === stepChildId,\n )\n return typeof childStep === 'undefined' ? (\n <></>\n ) : (\n <li className=\"item-wrap\" key={`${j}-${stepChildId}`}>\n {getListItem(childStep, !!props.isWizardMode, true)}\n </li>\n )\n })}\n </ul>\n </div>\n )}\n </li>\n )\n })}\n </ul>\n </div>\n )\n}\n"],"mappings":";;;;AASA,SAAwB,EAAa,GAA0B;CAC7D,IAAM,IAAgB,EAAM,SAAS,QAAO,MAAQ,EAAK,UAAU,GAAK,EAElE,KACJ,GACA,GACA,GACA,MAC0B;EAC1B,IAAI,IAAoB;AAcxB,SAbI,KAAY,MAMZ,IACF,IAAU,UACD,MAAU,EAAc,YACjC,IAAU,gBACD,MAAU,EAAc,UACjC,IAAU,mBAVH,EACL,YACD;IAaC,KACJ,GACA,IAAoB,OACT;EACX,IAAI,IAAc;AAOlB,SANI,MACF,IAAc,GAAG,EAAY,aAE3B,MACF,IAAc,GAAG,EAAY,WAExB;IAGH,KACJ,GACA,GACA,IAAgB,OACb;AACH,MAAI,CAAC,KAAS,EAAK,SAAS,CAAC,EAC3B,QAAO,kBAAA,GAAA,EAAK,CAAA;EAEd,IAAM,KACJ,GACA,GACA,MAEI,CAAC,EAAK,eAAe,CAAC,KAAc,EAAK,SAEzC,kBAAC,UAAD;GAAQ,WAAU;GAAe,eAAe,EAAS,EAAK;aAC3D,EAAK;GACC,CAAA,GAGJ,kBAAC,QAAD,EAAA,UAAO,EAAK,OAAa,CAAA,EAG9B,IAAO,EAAQ,EAAK,OAAO,EAAK,UAAU,EAAK,QAAQ,EAAK,MAAM;AAGxE,SACE,kBAAC,OAAD;GAAK,WAHW,EAAa,EAAK,YAAY,EAAK,OAGnC;aAAhB,CACE,kBAAC,GAAD,EAAS,MAAM,EAAK,SAAW,CAAA,EAC9B,EAAe,GAAM,GAAU,EAAM,aAAa,CAC/C;;;AAIV,QACE,kBAAC,OAAD;EAAK,WAAU;EAAiC,OAAO,EAAE,MAAM,KAAK;YAClE,kBAAC,MAAD,EAAA,UACG,EAAc,KAAK,GAAY,MAE5B,kBAAC,MAAD;GAAI,WAAU;aAAd,CACG,EAAY,GAAM,CAAC,CAAC,EAAM,aAAa,EACvC,EAAK,YAAY,EAAK,SAAS,SAAS,KACvC,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,MAAD,EAAA,UACG,EAAK,YACJ,EAAK,SAAS,KAAK,GAAqB,MAAc;KACpD,IAAM,IAAY,EAAM,SAAS,MAC/B,MAAQ,EAAK,OAAO,EACrB;AACD,YAAc,MAAc,SAC1B,kBAAA,GAAA,EAAK,CAAA,GAEL,kBAAC,MAAD;MAAI,WAAU;gBACX,EAAY,GAAW,CAAC,CAAC,EAAM,cAAc,GAAK;MAChD,EAF0B,GAAG,EAAE,GAAG,IAElC;MAEP,EACD,CAAA;IACD,CAAA,CAEL;KArB0B,GAAG,EAAE,GAAG,EAAK,KAqBvC,CAEP,EACC,CAAA;EACD,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SummaryTable.js","names":[],"sources":["../../../src/components/SynapseForm/SummaryTable.tsx"],"sourcesContent":["import { UiSchema } from '@rjsf/utils'\nimport { FormSchema, Step, SummaryFormat } from './types'\nimport {\n cloneDeep,\n find,\n first,\n get,\n isArray,\n isDate,\n isObject,\n isString,\n keys,\n} from 'lodash-es'\n\nexport interface SummaryTableProps {\n isWizard?: boolean\n formData: any\n callbackFn?: (screenId: string) => void\n steps: Step[]\n schema: FormSchema\n uiSchema: UiSchema\n}\n\nfunction findLabel(key: string, schema: any, uiSchema: UiSchema): string {\n const regex1 = /\\[\\d+\\]\\./g\n const regex3 = /\\.(\\d)+/g\n\n key = key.replace(regex3, '[$1]')\n\n const propArr = key.split('.')\n // some things require labels in schema (e.g. checkboxes) so this is preferred\n const labelFromSchema = `${propArr.join('.properties.')}.title`\n //can be overriden by label in UI\n const labelFromUi = `${key}.ui:title`\n //for array fields we need to change the property e.g.\n // ld50.experiments[0].species_other should look like 'ld50.experiments.items.species_other'\n const arrayLabelFromSchema = labelFromSchema.replace(regex1, '.items.')\n const arrayLabelFromUiSchema = labelFromUi.replace(regex1, '.items.')\n const indexMatch = labelFromSchema.match(regex1)\n let index = first(indexMatch)\n\n if (index) {\n index = index.substring(1, index.length - 2)\n index = !isNaN(parseInt(index)) ? `${parseInt(index) + 1}` : ''\n }\n\n const label =\n get(uiSchema, labelFromUi) ||\n get(schema.properties, labelFromSchema) ||\n get(uiSchema, arrayLabelFromUiSchema) ||\n get(schema.properties, arrayLabelFromSchema) ||\n `${arrayLabelFromSchema}`\n return `${index ? '[' + index + '] ' : ''}${label}`\n}\n\nexport function getFlatData(\n formData: any,\n steps: Step[],\n schema: FormSchema,\n uiSchema: UiSchema,\n): SummaryFormat[] {\n //takes nested json and converts it into flattened item list\n\n function flatten(\n object: Record<string, any>,\n flattenedObject: Record<string, any>,\n prefix: string,\n ): Record<string, any> {\n const separator = '.'\n Object.keys(object).forEach(key => {\n if (object[key] === null) {\n flattenedObject[prefix + key] = ''\n } else if (\n //if the value is a proper array\n isArray(object[key]) &&\n !isString(object[key])\n ) {\n object[key].forEach((item: any, i: number) => {\n if (isArray(item) || (isObject(object[key]) && !isString(item))) {\n flatten(item, flattenedObject, `${prefix}${key}[${i}]${separator}`)\n } else {\n let prevVal = flattenedObject[`${prefix}${key}`]\n prevVal = prevVal ? `${prevVal}, ` : ''\n flattenedObject[`${prefix}${key}`] = prevVal + item\n }\n })\n } else if (isObject(object[key]) && !isDate(object[key])) {\n flatten(object[key], flattenedObject, `${prefix}${key}${separator}`)\n } else {\n flattenedObject[prefix + key] = object[key]\n }\n })\n return flattenedObject\n }\n\n const flatData = flatten(cloneDeep(formData), {}, '')\n console.log(flatData)\n const flatFormData = keys(flatData)\n .map(key => {\n let val = flatData[key]\n if (flatData[key] === false) {\n val = 'false'\n }\n if (flatData[key] === true) {\n val = 'true'\n }\n const boundary = key.indexOf('.')\n return {\n screen: find(steps, { id: key.substring(0, boundary) }),\n label: findLabel(key, schema, uiSchema),\n value: val,\n }\n })\n .filter(item => item.label.indexOf('.properties.included.title') === -1) //included is the property we generate to help with validation of optional forms\n\n const result = flatFormData\n .filter(item => item.screen && typeof item.value !== 'undefined')\n .map(item => {\n return {\n label: item.label,\n value: item.value,\n screen: item.screen!,\n }\n })\n .sort((a, b) => a.screen.order - b.screen.order)\n\n return result\n}\n\nexport default function SummaryTable(props: SummaryTableProps) {\n let flatFormData: SummaryFormat[] = []\n\n flatFormData = getFlatData(\n cloneDeep(props.formData),\n props.steps,\n props.schema,\n props.uiSchema,\n )\n\n let prevScreenId = ''\n const table = (\n <>\n <table className=\"table summary-table-header\">\n <thead>\n <tr>\n <th>Step</th>\n <th>Label</th>\n <th>Value</th>\n </tr>\n </thead>\n </table>\n\n <div className=\"scroll-area table-body\">\n <table className=\"table summary-table\">\n <tbody>\n {flatFormData.map((line: SummaryFormat, i: number) => {\n return (\n <tr key={`${i}-${line.screen.id}-${line.label}`}>\n <td>\n {prevScreenId !== line.screen.id &&\n (prevScreenId = line.screen.id) && (\n <span>{line.screen.title}</span>\n )}\n </td>\n <td>{line.label}</td>\n\n <td>{line.value}</td>\n </tr>\n )\n })}\n </tbody>\n </table>\n </div>\n </>\n )\n\n return (\n <>\n <p className=\"step-exclude-directions\">\n Below is all of the data you have entered. Before submitting, click\n "Validate" to ensure that all of the required data has been\n entered.\n </p>\n <button className=\"nav-link pull-right\" onClick={() => window.print()}>\n Print this data\n </button>\n <div className=\"panel panel-default padding-full wrap\">\n <div className=\"summary scroll-area\">{table}</div>\n </div>\n </>\n )\n}\n"],"mappings":";;;AAuBA,SAAS,EAAU,GAAa,GAAa,GAA4B;CACvE,IAAM,IAAS;AAGf,KAAM,EAAI,
|
|
1
|
+
{"version":3,"file":"SummaryTable.js","names":[],"sources":["../../../src/components/SynapseForm/SummaryTable.tsx"],"sourcesContent":["import { UiSchema } from '@rjsf/utils'\nimport { FormSchema, Step, SummaryFormat } from './types'\nimport {\n cloneDeep,\n find,\n first,\n get,\n isArray,\n isDate,\n isObject,\n isString,\n keys,\n} from 'lodash-es'\n\nexport interface SummaryTableProps {\n isWizard?: boolean\n formData: any\n callbackFn?: (screenId: string) => void\n steps: Step[]\n schema: FormSchema\n uiSchema: UiSchema\n}\n\nfunction findLabel(key: string, schema: any, uiSchema: UiSchema): string {\n const regex1 = /\\[\\d+\\]\\./g\n const regex3 = /\\.(\\d)+/g\n\n key = key.replace(regex3, '[$1]')\n\n const propArr = key.split('.')\n // some things require labels in schema (e.g. checkboxes) so this is preferred\n const labelFromSchema = `${propArr.join('.properties.')}.title`\n //can be overriden by label in UI\n const labelFromUi = `${key}.ui:title`\n //for array fields we need to change the property e.g.\n // ld50.experiments[0].species_other should look like 'ld50.experiments.items.species_other'\n const arrayLabelFromSchema = labelFromSchema.replace(regex1, '.items.')\n const arrayLabelFromUiSchema = labelFromUi.replace(regex1, '.items.')\n const indexMatch = labelFromSchema.match(regex1)\n let index = first(indexMatch)\n\n if (index) {\n index = index.substring(1, index.length - 2)\n index = !isNaN(parseInt(index)) ? `${parseInt(index) + 1}` : ''\n }\n\n const label =\n get(uiSchema, labelFromUi) ||\n get(schema.properties, labelFromSchema) ||\n get(uiSchema, arrayLabelFromUiSchema) ||\n get(schema.properties, arrayLabelFromSchema) ||\n `${arrayLabelFromSchema}`\n return `${index ? '[' + index + '] ' : ''}${label}`\n}\n\nexport function getFlatData(\n formData: any,\n steps: Step[],\n schema: FormSchema,\n uiSchema: UiSchema,\n): SummaryFormat[] {\n //takes nested json and converts it into flattened item list\n\n function flatten(\n object: Record<string, any>,\n flattenedObject: Record<string, any>,\n prefix: string,\n ): Record<string, any> {\n const separator = '.'\n Object.keys(object).forEach(key => {\n if (object[key] === null) {\n flattenedObject[prefix + key] = ''\n } else if (\n //if the value is a proper array\n isArray(object[key]) &&\n !isString(object[key])\n ) {\n object[key].forEach((item: any, i: number) => {\n if (isArray(item) || (isObject(object[key]) && !isString(item))) {\n flatten(item, flattenedObject, `${prefix}${key}[${i}]${separator}`)\n } else {\n let prevVal = flattenedObject[`${prefix}${key}`]\n prevVal = prevVal ? `${prevVal}, ` : ''\n flattenedObject[`${prefix}${key}`] = prevVal + item\n }\n })\n } else if (isObject(object[key]) && !isDate(object[key])) {\n flatten(object[key], flattenedObject, `${prefix}${key}${separator}`)\n } else {\n flattenedObject[prefix + key] = object[key]\n }\n })\n return flattenedObject\n }\n\n const flatData = flatten(cloneDeep(formData), {}, '')\n console.log(flatData)\n const flatFormData = keys(flatData)\n .map(key => {\n let val = flatData[key]\n if (flatData[key] === false) {\n val = 'false'\n }\n if (flatData[key] === true) {\n val = 'true'\n }\n const boundary = key.indexOf('.')\n return {\n screen: find(steps, { id: key.substring(0, boundary) }),\n label: findLabel(key, schema, uiSchema),\n value: val,\n }\n })\n .filter(item => item.label.indexOf('.properties.included.title') === -1) //included is the property we generate to help with validation of optional forms\n\n const result = flatFormData\n .filter(item => item.screen && typeof item.value !== 'undefined')\n .map(item => {\n return {\n label: item.label,\n value: item.value,\n screen: item.screen!,\n }\n })\n .sort((a, b) => a.screen.order - b.screen.order)\n\n return result\n}\n\nexport default function SummaryTable(props: SummaryTableProps) {\n let flatFormData: SummaryFormat[] = []\n\n flatFormData = getFlatData(\n cloneDeep(props.formData),\n props.steps,\n props.schema,\n props.uiSchema,\n )\n\n let prevScreenId = ''\n const table = (\n <>\n <table className=\"table summary-table-header\">\n <thead>\n <tr>\n <th>Step</th>\n <th>Label</th>\n <th>Value</th>\n </tr>\n </thead>\n </table>\n\n <div className=\"scroll-area table-body\">\n <table className=\"table summary-table\">\n <tbody>\n {flatFormData.map((line: SummaryFormat, i: number) => {\n return (\n <tr key={`${i}-${line.screen.id}-${line.label}`}>\n <td>\n {prevScreenId !== line.screen.id &&\n (prevScreenId = line.screen.id) && (\n <span>{line.screen.title}</span>\n )}\n </td>\n <td>{line.label}</td>\n\n <td>{line.value}</td>\n </tr>\n )\n })}\n </tbody>\n </table>\n </div>\n </>\n )\n\n return (\n <>\n <p className=\"step-exclude-directions\">\n Below is all of the data you have entered. Before submitting, click\n "Validate" to ensure that all of the required data has been\n entered.\n </p>\n <button className=\"nav-link pull-right\" onClick={() => window.print()}>\n Print this data\n </button>\n <div className=\"panel panel-default padding-full wrap\">\n <div className=\"summary scroll-area\">{table}</div>\n </div>\n </>\n )\n}\n"],"mappings":"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"}
|
|
@@ -48,8 +48,10 @@ var I = class extends h {
|
|
|
48
48
|
...e,
|
|
49
49
|
inProgress: t === 0
|
|
50
50
|
})).sort((e, t) => e.order - t.order);
|
|
51
|
-
this.formRef = g(), this.formDivRef = g(), this.submitButtonRef = g()
|
|
52
|
-
|
|
51
|
+
this.formRef = g(), this.formDivRef = g(), this.submitButtonRef = g();
|
|
52
|
+
let n = this.getFirstStep(t, e.formData);
|
|
53
|
+
this.state = {
|
|
54
|
+
currentStep: n,
|
|
53
55
|
steps: t,
|
|
54
56
|
previousStepIds: [],
|
|
55
57
|
formData: e.formData,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SynapseForm.js","names":[],"sources":["../../../src/components/SynapseForm/SynapseForm.tsx"],"sourcesContent":["import Blocker from '@/components/utils/Blocker'\nimport Form from '@rjsf/core'\nimport { ErrorListProps, RJSFValidationError, UiSchema } from '@rjsf/utils'\nimport validator from '@rjsf/validator-ajv8'\nimport { Engine, EngineResult } from 'json-rules-engine'\nimport cloneDeep from 'lodash-es/cloneDeep'\nimport find from 'lodash-es/find'\nimport findIndex from 'lodash-es/findIndex'\nimport first from 'lodash-es/first'\nimport get from 'lodash-es/get'\nimport isEqual from 'lodash-es/isEqual'\nimport isUndefined from 'lodash-es/isUndefined'\nimport keys from 'lodash-es/keys'\nimport pick from 'lodash-es/pick'\nimport remove from 'lodash-es/remove'\nimport set from 'lodash-es/set'\nimport trimStart from 'lodash-es/trimStart'\nimport { Component, createRef, ReactNode, RefObject } from 'react'\nimport Switch from 'react-switch'\nimport { ConfirmationDialog } from '../ConfirmationDialog/ConfirmationDialog'\nimport DataDebug from './DataDebug'\nimport Header from './Header'\nimport { NavButtons, NextStepLink } from './NavButtons'\nimport StepsSideNav from './StepsSideNav'\nimport SummaryTable from './SummaryTable'\nimport SynapseFormCheckboxesWidget from './SynapseFormCheckboxesWidget'\nimport SynapseFormCheckboxWidget from './SynapseFormCheckboxWidget'\nimport SynapseFormRadioWidget from './SynapseFormRadioWidget'\nimport {\n FormSchema,\n IRulesNavigationEvent,\n IRulesValidationEvent,\n NavActionEnum,\n StatusEnum,\n Step,\n StepStateEnum,\n} from './types'\nimport WarningDialog from './WarningDialog'\n\nexport interface IFormData {\n [key: string]: {\n included?: boolean\n [key: string]: any\n }\n}\n\nexport type SynapseFormProps = {\n schema: FormSchema\n uiSchema: UiSchema\n navSchema: {\n steps: any[]\n }\n formData: IFormData\n onSubmit: (formData: IFormData) => void\n onSave: (formData: IFormData) => void\n formTitle: string\n formClass?: string\n isWizardMode?: boolean\n callbackStatus?: StatusEnum\n isSubmitted?: boolean\n}\n\ntype SynapseFormState = {\n formData: IFormData // form data that prepopulates the form\n currentStep: Step\n nextStep?: Step\n steps: Step[]\n previousStepIds: string[]\n hasValidated?: boolean //validation has been called and it passed\n doShowErrors: boolean //if we should show error summary at the top of the page\n doShowHelp: boolean\n modalContext?: { action: (...args: any[]) => void; arguments: any[] }\n hasUnsavedChanges: boolean\n isSubmitted?: boolean\n isLoadingSaved: boolean\n}\n\nexport interface SummaryFormat {\n label: string\n value: string\n}\n\nexport default class SynapseForm extends Component<\n SynapseFormProps,\n SynapseFormState\n> {\n excludeWarningText = (\n <div>\n <p>\n This action will clear any entered data on this page and remove this\n form from your submission. You can include it again at anytime. Only\n this page will be affected.\n </p>\n <p>Are you sure you want to skip this step and clear any entered data?</p>\n </div>\n )\n excludeWarningHeader = 'Skip This Step?'\n unsavedDataWarning = `You might have some unsaved data. Are you sure you want to leave?`\n formRef: RefObject<Form<IFormData> | null> //ref to form for submission\n submitButtonRef: RefObject<HTMLButtonElement | null>\n formDivRef: any // ref to the div containing form (for scrolling on validation failure)\n navAction: NavActionEnum = NavActionEnum.NONE\n uiSchema: UiSchema\n nextStep: Step | undefined\n extraErrors: RJSFValidationError[] = []\n\n isNewForm = (formData: IFormData): boolean => {\n return (\n (Object.keys(formData).length == 1 &&\n Object.keys(formData)[0] === 'metadata') ||\n Object.keys(formData).length == 0\n )\n }\n\n getFirstStep = (steps: Step[], formData: IFormData): Step => {\n if (!this.isNewForm(formData)) {\n return steps.find(step => step.final === true) || steps[0]\n } else {\n return steps[0]\n }\n }\n\n constructor(props: SynapseFormProps) {\n super(props)\n\n //will modify the ui:help to render html vs text\n this.uiSchema = stringToElementForProp(\n cloneDeep(props.uiSchema),\n 'ui:help',\n ) as UiSchema\n //create steps array from the navSchema\n const steps = props.navSchema.steps\n .map((step, i) => {\n return {\n ...step,\n inProgress: i === 0 ? true : false,\n }\n })\n .sort((a, b) => a.order - b.order)\n\n this.formRef = createRef()\n this.formDivRef = createRef()\n this.submitButtonRef = createRef()\n const currentStep = this.getFirstStep(steps, props.formData)\n this.state = {\n currentStep,\n steps,\n previousStepIds: [],\n formData: props.formData,\n doShowErrors: false,\n doShowHelp: true,\n hasUnsavedChanges: false,\n isSubmitted: props.isSubmitted,\n isLoadingSaved: !this.isNewForm(this.props.formData),\n }\n }\n\n onUnload = (ev: any) => {\n {\n if (this.state.hasUnsavedChanges) {\n ev.preventDefault()\n return (ev.returnValue = this.unsavedDataWarning)\n }\n return\n }\n }\n // Setup the `beforeunload` event listener\n setupBeforeUnloadListener = () => {\n window.addEventListener('beforeunload', this.onUnload)\n }\n\n componentWillUnmount() {\n window.removeEventListener('beforeunload', this.onUnload)\n }\n\n componentDidUpdate(prevProps: SynapseFormProps) {\n const shouldUpdate = this.props.callbackStatus !== prevProps.callbackStatus\n const isSuccess =\n this.props.callbackStatus === StatusEnum.SAVE_SUCCESS ||\n this.props.callbackStatus === StatusEnum.SUBMIT_SUCCESS\n if (shouldUpdate && isSuccess) {\n this.setState({ hasUnsavedChanges: false })\n if (this.props.callbackStatus === StatusEnum.SUBMIT_SUCCESS) {\n this.setState({ isSubmitted: true })\n window.history.back()\n }\n }\n }\n\n _setIncludedPropInFormDataNonWizard = (\n currentState: SynapseFormState,\n schemaScreens: any,\n ): IFormData => {\n const result = {}\n const currentStateFormData = currentState.formData\n //if there is a top level 'included' property in schema - update the form.\n Object.keys(schemaScreens).forEach((key: string) => {\n if (get(schemaScreens[key], `properties.included`)) {\n set(result, `${key}.included`, true)\n }\n })\n return { ...currentStateFormData, ...result }\n }\n\n _setIncludedPropInFormDataWizard = (\n currentState: SynapseFormState,\n ): IFormData => {\n const firstStepId = currentState.currentStep.id\n const newStateData = cloneDeep(currentState.formData)\n set(newStateData, `${firstStepId}.included`, true)\n return newStateData\n }\n\n componentDidMount() {\n this.setupBeforeUnloadListener()\n const isNewForm = this.isNewForm(this.state.formData)\n if (!isNewForm) {\n //when loading saved form - validate to see the steps status\n this.triggerAction(NavActionEnum.VALIDATE)\n } else {\n // for validation of optional forms. Validation is enforced only if included property is set.\n this.setState(prevState => {\n const newFormData = this.props.isWizardMode\n ? this._setIncludedPropInFormDataWizard(prevState)\n : this._setIncludedPropInFormDataNonWizard(\n prevState,\n this.props.schema,\n )\n return {\n formData: newFormData,\n }\n })\n }\n }\n\n // get the schema slice for the current screen/step\n getSchema = ({ id, final }: Step): FormSchema => {\n if (final) {\n return this.props.schema\n }\n //only get schema for current step. Only the portion of entire form is shown\n\n const currentStepSlice = pick(this.props.schema, [\n 'title',\n 'type',\n `properties.${id}`,\n ])\n return currentStepSlice\n }\n\n // find the next step\n getNextStepId = async (\n currentStep: Step,\n formData: any,\n nextStepId?: string,\n ): Promise<string> => {\n if (nextStepId) {\n return nextStepId\n }\n if (!currentStep.rules || currentStep.rules.length === 0) {\n return currentStep.default\n }\n\n // if there are rules - run the engine and go to the first next step\n const engine = new Engine(currentStep.rules)\n\n try {\n const result: EngineResult = await engine.run(formData)\n if (result.events.length > 0) {\n return (result.events[0] as IRulesNavigationEvent).params.next\n } else {\n return currentStep.default\n }\n } catch (error) {\n return currentStep.default\n }\n }\n\n // called when going next, previous or a given step\n moveStep = async (\n formData: any,\n nextStepId: string | undefined,\n isError: boolean,\n previousStack = [...this.state.previousStepIds],\n ) => {\n const currentStep = this.state.currentStep\n let currentStepState: StepStateEnum\n //we don't wnat to display errors on the page - this will be done explicitly in validation\n if (this.formRef?.current) {\n this.formRef.current.setState({ errorSchema: {} })\n }\n //in wizard mode we can only move forwards (don't know next step yet) or backwards (do know next step)\n const isMoveForwardInWizardMode = this.props.isWizardMode && !nextStepId\n\n //previousStack is used for 'back' navigation is wizard mode.\n //only need to do it if moving forward i.e. nextStepId is undefined\n if (isMoveForwardInWizardMode) {\n previousStack.push(currentStep.id)\n }\n\n if (!isError) {\n currentStepState = StepStateEnum.COMPLETED\n\n if (!isMoveForwardInWizardMode && this.props.isWizardMode) {\n currentStepState = StepStateEnum.TODO\n }\n } else {\n currentStepState = StepStateEnum.ERROR\n }\n // determine next step\n nextStepId = await this.getNextStepId(currentStep, formData, nextStepId)\n\n const steps = this.state.steps.map(step => {\n if (step.id === currentStep.id) {\n return {\n ...step,\n ...{ state: currentStepState, inProgress: false },\n }\n } else if (step.id === nextStepId) {\n return { ...step, ...{ inProgress: true } }\n }\n return step\n })\n //if we are in wizard mode we want to make sure that we include the step we are about to go to\n if (isMoveForwardInWizardMode) {\n set(formData, `${nextStepId}.included`, true)\n }\n\n //at this point the form is valid and submitted and the data reflects the latest\n const nextStep = this.state.steps.find(step => step.id === nextStepId)!\n // clean up unused screens in wizard before getting to submit\n if (this.props.isWizardMode && nextStep.final) {\n Object.keys(formData).forEach(key => {\n if (formData[key].included === undefined) {\n formData[key] = {}\n }\n })\n }\n\n this.saveStepState(previousStack, steps, nextStep, formData)\n }\n\n //save the state of the current screen\n saveStepState = (\n previousStepIds: string[],\n steps: Step[],\n currentStep: Step,\n formData: any,\n ) => {\n this.setState({\n previousStepIds,\n steps,\n currentStep,\n formData,\n hasValidated: false,\n doShowErrors: false,\n })\n }\n\n //--------- fns to support navigation --------------------//\n goPrevious = async (formData: any, isError: boolean) => {\n let previousStepId: string | undefined\n const previousStack: string[] = [...this.state.previousStepIds]\n // in wizard mode we go to the previously visited screen.\n // In regular mode go to the screen with previous index\n if (this.props.isWizardMode) {\n previousStepId = previousStack.pop()\n if (!this.isSubmitScreen()) {\n //since we don't know if we'll get back to that step again - exclude it. We will include it again if we\n // get to it.\n set(formData, `${this.state.currentStep.id}.included`, undefined)\n }\n } else {\n const currentIndex = findIndex(this.state.steps, {\n id: this.state.currentStep.id,\n })\n if (currentIndex > 0) {\n previousStepId = this.state.steps[currentIndex - 1].id\n }\n }\n if (!isUndefined(previousStepId)) {\n return this.moveStep(formData, previousStepId, isError, previousStack)\n }\n }\n\n triggerAction = async (navAction: NavActionEnum) => {\n // we don't need to validate on save so bypassing submit\n if (navAction === NavActionEnum.SAVE) {\n return this.props.onSave(this.state.formData)\n } else {\n this.navAction = navAction\n // first run whatever custom validaton we have\n this.extraErrors = await this.runCustomValidation(\n this.state.formData,\n this.state.currentStep,\n this.state.steps,\n )\n if (this.submitButtonRef.current) {\n this.submitButtonRef.current.click()\n }\n }\n }\n\n // triggered when we click on the step name in left nav (doesn't happen in wizard mode)\n triggerStepChange = (step: Step) => {\n this.nextStep = step\n this.triggerAction(NavActionEnum.GO_TO_STEP)\n }\n\n onError = (args: any) => {\n this.setState({\n doShowErrors: true,\n hasValidated: false,\n })\n if (this.navAction === NavActionEnum.VALIDATE) {\n const modifiedSteps = this.setStepStatusForFailedValidation(\n args.props,\n this.state.steps,\n !!this.props.isWizardMode,\n this.state.formData,\n this.getSchema(this.state.currentStep).properties ||\n this.getSchema(this.state.currentStep),\n )\n this.setState({ steps: modifiedSteps })\n this.formDivRef.current.scrollTo(0, 0)\n if (this.state.isLoadingSaved) {\n this.moveStep(this.state.formData, modifiedSteps[0].id, true)\n this.setState({ isLoadingSaved: false })\n }\n }\n }\n\n setStepStatusForFailedValidation = (\n errors: RJSFValidationError[],\n steps: Step[],\n isWizard: boolean,\n formData: IFormData,\n currentSchemaProperties: any,\n ): Step[] => {\n //error property is in the format: step.somevalue.etc .welcome.submission_name example\n //find all the steps where there is an error\n const stepsWithError = errors.map(\n error => trimStart(error.property, '.').split('.')[0],\n )\n //find all steps in current schema\n const stepsInCurrentSchema = Object.keys(currentSchemaProperties)\n const updatedSteps: Step[] = steps.map(step => {\n //if there is an error in this step\n if (stepsWithError.indexOf(step.id) > -1) {\n return {\n ...step,\n state: StepStateEnum.ERROR,\n }\n //if no error and included in schema\n } else if (stepsInCurrentSchema.indexOf(step.id) > -1) {\n let state = StepStateEnum.COMPLETED\n //if we are in wizard and possibly have not visited this step\n if (isWizard && !get(formData[step.id], 'included')) {\n state = step.state\n }\n\n return {\n ...step,\n state: state,\n }\n } else {\n return step\n }\n })\n return updatedSteps\n }\n\n //we are constantly saving form data. Needed to overwrite on-error behavior\n handleOnChange({ formData }: any) {\n //this is just for form updates. submit screen goes different route\n if (!this.isSubmitScreen() && !this.state.currentStep.excluded) {\n const hasUnsavedChanges = !isEqual(this.state.formData, formData)\n this.setState({ formData, hasUnsavedChanges })\n }\n }\n\n performAction(navAction: NavActionEnum, hasError: boolean) {\n const formData = this.state.formData\n\n switch (navAction) {\n case NavActionEnum.NEXT: {\n return this.moveStep(formData, undefined, hasError)\n }\n case NavActionEnum.PREVIOUS: {\n return this.goPrevious(formData, hasError)\n }\n case NavActionEnum.GO_TO_STEP: {\n //nextStep is returned when clicked on the Steps left nav\n if (!this.nextStep) {\n return\n }\n return this.moveStep(formData, this.nextStep.id, hasError)\n }\n\n case NavActionEnum.SUBMIT: {\n this.props.onSubmit(formData)\n return\n }\n case NavActionEnum.VALIDATE: {\n //we get here is we clicked validate and the data is valid.\n // if it's not valid we handle it in onError fn\n const steps = this.setStepStatusForFailedValidation(\n [],\n this.state.steps,\n !!this.props.isWizardMode,\n this.state.formData,\n this.getSchema(this.state.currentStep).properties ||\n this.getSchema(this.state.currentStep),\n )\n const currentStep = {\n ...this.state.currentStep,\n state: StepStateEnum.COMPLETED,\n }\n\n this.setState({ hasValidated: true, currentStep, steps })\n if (this.state.isLoadingSaved) {\n this.moveStep(this.state.formData, steps[0].id, false)\n this.setState({ isLoadingSaved: false })\n }\n return\n }\n default:\n return\n }\n }\n\n //we need to route things through submit - otherwise validation does not kick in\n // it triggers internal library validation and calls the performAction with the params for action\n onSubmit: () => any = () => {\n this.performAction(\n this.navAction,\n this.state.currentStep.state === StepStateEnum.ERROR,\n )\n }\n\n isSubmitScreen = (): boolean => {\n return this.state.currentStep.final === true && !this.state.isLoadingSaved\n }\n\n showExcludeStateWarningDialog = (\n stepId: string,\n isUpdateFlattenedData: boolean = false,\n ): void => {\n this.setState({\n modalContext: {\n action: this.toggleExcludeStep,\n arguments: [stepId, true, isUpdateFlattenedData],\n },\n })\n }\n\n toggleExcludeStep = (stepId: string, isExclude: boolean): void => {\n this.setState((prevState, props) => {\n const steps = prevState.steps.map(stp => {\n if (stp.id === stepId) {\n return { ...stp, ...{ excluded: isExclude } }\n }\n return stp\n })\n\n const formDataUpdated = cloneDeep(prevState.formData)\n const currentStep = cloneDeep(prevState.currentStep)\n //we need this because you can exclude on the ifnal screen so the currentStep.id\n //is not always the one we need to exclude\n if (currentStep.id === stepId) {\n currentStep.excluded = isExclude\n }\n //if exluding - blow away the data for the step\n if (isExclude) {\n formDataUpdated[stepId] = {}\n //set(formDataUpdated, `${stepId}.included`, false);\n } else {\n set(formDataUpdated, `${stepId}.included`, true)\n }\n return {\n steps,\n formData: formDataUpdated,\n modalContext: undefined,\n currentStep,\n }\n })\n }\n\n private renderNotification = (status?: StatusEnum) => {\n if (status === StatusEnum.SAVE_SUCCESS) {\n return <div className=\"notification-area\"> Successfully saved </div>\n }\n if (status === StatusEnum.SUBMIT_SUCCESS) {\n return <div className=\"notification-area\"> Successfully submitted </div>\n }\n if (status === StatusEnum.PROGRESS) {\n return <div className=\"notification-area\"> working on it ....</div>\n }\n return <></>\n }\n\n // displays the text for screens that don't have any form data\n private renderTextForStaticScreen = () => {\n if (!this.state.currentStep.copy) {\n return <></>\n }\n const copy = this.state.currentStep.copy\n return (\n <div\n className=\"static-screen\"\n dangerouslySetInnerHTML={{ __html: copy }}\n />\n )\n }\n\n //displays subheader for forms that can be excluded\n renderOptionalFormSubheader = (isWizard: boolean = false) => {\n if (isWizard) {\n return <></>\n }\n const currentStep = this.state.currentStep\n\n if (currentStep.excluded === true) {\n return (\n <div className=\"step-exclude-directions\">\n This form is currently not included in the submission.\n <button\n className=\"btn btn-link\"\n onClick={() => this.toggleExcludeStep(currentStep.id, false)}\n >\n Include\n </button>\n </div>\n )\n } else if (currentStep.excluded === false) {\n return (\n <div className=\"step-exclude-directions\">\n This form is currently included in the submission. Enter some data if\n you have it, or click "Skip".\n <button\n className=\"btn btn-link\"\n onClick={() =>\n this.showExcludeStateWarningDialog(this.state.currentStep.id)\n }\n >\n Skip\n </button>\n </div>\n )\n }\n return <></>\n }\n\n renderHelpToggle = (\n currentStep: Step,\n showHelp: boolean,\n callbackFn: () => void,\n ) => {\n if (currentStep.static || currentStep.final) {\n return <></>\n }\n return (\n <>\n <label className=\"pull-right toggle-help-label\">\n <span>Hide help</span>\n <Switch\n checkedIcon={false}\n uncheckedIcon={false}\n height={20}\n width={45}\n className=\"toggle-help\"\n offColor=\"#ccc\"\n onChange={() => callbackFn()}\n checked={showHelp}\n />\n <span>Show help</span>\n </label>\n </>\n )\n }\n\n runCustomValidation = async (\n formData: IFormData,\n currentStep: Step,\n allSteps: Step[],\n ): Promise<RJSFValidationError[]> => {\n const errors: RJSFValidationError[] = []\n\n //default - running on current step\n let rules = currentStep.validationRules || []\n let data = {\n [currentStep.id]: formData[currentStep.id],\n }\n\n // for final step -- concatenate all rules and run on all data\n if (currentStep.final) {\n rules = allSteps.reduce((acc: any, value: Step) => {\n return value.validationRules && value.validationRules.length > 0\n ? acc.concat(value.validationRules)\n : acc\n }, [])\n data = cloneDeep(formData)\n }\n\n if (rules.length === 0) {\n return []\n }\n\n //this is a workaround for inability to define a rule to run on all members of the data array\n // we define the generic rule with path e.g.\"path\": \".experiments[*].dose_range.dose_range_min\",\n const allRules: any[] = []\n rules.forEach(rule => {\n //take a rule\n const paramProp = rule.event.params.property\n // if it's just a normal rule - add it\n if (paramProp.indexOf('[*]') === -1) {\n allRules.push(rule)\n } else {\n const path = paramProp.split('[*]')[0].substring(1)\n const data = get(formData, path)\n // generate a rule for each item in the data array by substituting [*] w/ appropriate index\n if (Array.isArray(data) && typeof data !== 'string') {\n for (let i = 0; i < data.length; i++) {\n const newRule = JSON.parse(\n JSON.stringify(rule).replace(/\\[\\*\\]/g, `[${i}]`),\n )\n allRules.push(newRule)\n }\n } else {\n allRules.push(rule)\n }\n }\n })\n // no we run all the rules through the engine\n const engine = new Engine(allRules, {\n allowUndefinedFacts: true,\n })\n\n try {\n const result: EngineResult = await engine.run(data)\n const validationEvents = result.events as IRulesValidationEvent[]\n validationEvents.forEach(event => {\n const err: RJSFValidationError = {\n ...event.params,\n ...{\n params: {},\n stack: `${event.params.property} ${event.params.message}`,\n },\n }\n errors.push(err)\n })\n } catch (error) {\n console.log(error)\n }\n\n return errors\n }\n\n transformErrors = (errors: RJSFValidationError[]): RJSFValidationError[] => {\n // if we are not in wizard mode and not trying to submit or validate we just want to skip\n // over the errors and just set the step status\n // https://github.com/rjsf-team/react-jsonschema-form/issues/1263\n this.extraErrors.forEach(extraError => {\n if (!errors.find(error => error.stack === extraError.stack)) {\n errors.push(extraError)\n }\n })\n\n if (\n this.navAction !== NavActionEnum.SUBMIT &&\n this.navAction !== NavActionEnum.VALIDATE &&\n (!this.props.isWizardMode || this.state.currentStep.final)\n ) {\n const currentStep = {\n ...this.state.currentStep,\n }\n if (errors.length > 0) {\n currentStep.state = StepStateEnum.ERROR\n } else {\n currentStep.state = StepStateEnum.COMPLETED\n }\n\n this.setState({ currentStep })\n\n return []\n }\n\n // there is an odd behavior in the lib that in cases when we have additional fields depending on enum\n // value if it's required and not entered we get 3 error: enum, required, and oneOf\n // so if there is an error Oneof on a parent - ignore it and enum on a child. and just output 'required'\n // if there is an enum error and there is required with the same prefix remove it\n\n const reqErrors = errors.filter(error => error.name === 'required')\n reqErrors.forEach(error => {\n if (error.property) {\n const parentPath = error.property.substring(\n 0,\n error.property.lastIndexOf('.'),\n )\n remove(errors, (error: RJSFValidationError) => {\n return (\n (error.property || '').indexOf(parentPath) > -1 &&\n (error.name === 'enum' || error.name === 'oneOf')\n )\n })\n }\n })\n\n return errors.map(error => {\n if (error.message) {\n error.message = error.message.replace('property', 'field')\n }\n return error\n })\n }\n\n renderErrorListTemplate = (props: ErrorListProps) => {\n const { errors } = props\n const currentLis = errors\n .map((error, i) => {\n return renderTransformedErrorObject(\n this.state.steps,\n error,\n this.uiSchema,\n i,\n this.props.schema,\n )\n })\n .sort((a, b) => a.order - b.order)\n .map(li => li.element)\n\n return (\n <div className=\"form-error-summary\">\n <ul className=\"error-detail\">{currentLis}</ul>\n </div>\n )\n }\n\n render() {\n return (\n <div className=\"outter-wrap\">\n <Blocker\n shouldBlock={({ currentLocation, nextLocation }) =>\n this.state.hasUnsavedChanges &&\n currentLocation.pathname !== nextLocation.pathname\n }\n >\n {blocker => (\n <ConfirmationDialog\n open={blocker.state == 'blocked'}\n title=\"Unsaved Changes\"\n content={this.unsavedDataWarning}\n onConfirm={() => {\n if (blocker.proceed) {\n blocker.proceed()\n }\n }}\n onCancel={() => {\n if (blocker.reset) {\n blocker.reset()\n }\n }}\n />\n )}\n </Blocker>\n <Header\n isSubmitted={this.state.isSubmitted}\n bodyText={this.state.currentStep.description}\n title={this.props.formTitle}\n ></Header>\n <div>\n <div className=\"inner-wrap\">\n <StepsSideNav\n stepList={this.state.steps}\n isWizardMode={this.props.isWizardMode}\n onStepChange={this.triggerStepChange}\n ></StepsSideNav>\n {this.state.isLoadingSaved && (\n <div className=\"text-center\">\n <span className={'spinner'} />\n </div>\n )}\n <div className=\"form-wrap\">\n <div className=\"form-title\">{this.state.currentStep.title}</div>\n {this.renderNotification(this.props.callbackStatus)}\n <div\n className={`right-top-actions ${\n this.state.isSubmitted ? 'hide' : ''\n }`}\n >\n {!this.state.currentStep.static && (\n <button\n type=\"button\"\n className=\"btn btn-action save pull-right\"\n onClick={() => {\n this.triggerAction(NavActionEnum.VALIDATE)\n }}\n >\n VALIDATE\n </button>\n )}\n {this.renderHelpToggle(\n this.state.currentStep,\n this.state.doShowHelp,\n () =>\n this.setState({\n doShowHelp: !this.state.doShowHelp,\n }),\n )}\n {this.isSubmitScreen() && (\n <button\n type=\"button\"\n className=\"btn btn-action save pull-right\"\n disabled={this.state.isSubmitted}\n onClick={() => {\n this.triggerAction(NavActionEnum.SUBMIT)\n }}\n >\n SUBMIT\n </button>\n )}\n </div>\n {this.renderOptionalFormSubheader(this.props.isWizardMode)}\n <div\n className={\n this.isSubmitScreen() || this.state.currentStep.static\n ? 'hide-form-only'\n : 'wrap'\n }\n >\n {this.state.hasValidated && (\n <div className=\"notification-area\">\n Great! All required data on this form has been entered.\n </div>\n )}\n <div\n ref={this.formDivRef}\n className={`scroll-area ${\n this.state.currentStep.excluded ? 'disabled' : ' '\n } `}\n >\n <Form\n validator={validator}\n noHtml5Validate\n className={\n this.state.doShowHelp\n ? 'submissionInputForm'\n : 'submissionInputForm no-help'\n }\n liveValidate={false}\n formData={this.state.formData}\n schema={this.getSchema(this.state.currentStep)}\n uiSchema={this.uiSchema}\n onSubmit={this.onSubmit}\n onChange={args => this.handleOnChange(args)}\n onError={args =>\n this.onError({\n props: args,\n form: this.formRef,\n })\n }\n showErrorList={\n this.state.doShowErrors || this.props.isWizardMode\n ? 'top'\n : false\n }\n templates={{\n ErrorListTemplate: this.renderErrorListTemplate,\n }}\n transformErrors={this.transformErrors}\n ref={this.formRef}\n disabled={\n this.state.currentStep.excluded || this.state.isSubmitted\n }\n widgets={{\n CheckboxWidget: SynapseFormCheckboxWidget,\n CheckboxesWidget: SynapseFormCheckboxesWidget,\n RadioWidget: SynapseFormRadioWidget,\n }}\n >\n <div style={{ display: 'none' }}>\n <button type=\"submit\" ref={this.submitButtonRef}></button>\n </div>\n </Form>\n {this.renderTextForStaticScreen()}\n {!this.props.isWizardMode && (\n <NextStepLink\n steps={this.state.steps}\n nextStepId={this.state.currentStep.default}\n onNavAction={(step: Step) => this.triggerStepChange(step)}\n ></NextStepLink>\n )}\n </div>\n </div>\n\n {this.isSubmitScreen() && (\n <SummaryTable\n formData={this.state.formData}\n steps={this.state.steps}\n callbackFn={(screenId: string) =>\n this.showExcludeStateWarningDialog(screenId, true)\n }\n uiSchema={this.props.uiSchema}\n schema={this.props.schema}\n ></SummaryTable>\n )}\n\n <NavButtons\n currentStep={this.state.currentStep}\n steps={this.state.steps}\n previousStepIds={this.state.previousStepIds}\n isFormSubmitted={this.state.isSubmitted}\n onNavAction={(e: NavActionEnum) => {\n this.triggerAction(e)\n }}\n ></NavButtons>\n </div>\n </div>\n </div>\n {this.state.modalContext && (\n <WarningDialog\n open={true}\n title={this.excludeWarningHeader}\n content={this.excludeWarningText}\n className={`theme-${this.props.formClass}`}\n onConfirmCallbackArgs={this.state.modalContext.arguments}\n onCancel={() => this.setState({ modalContext: undefined })}\n onConfirm={(stepId: string, isExclude: boolean) =>\n this.toggleExcludeStep(stepId, isExclude)\n }\n />\n )}\n <DataDebug formData={this.state.formData} hidden={true}></DataDebug>\n </div>\n )\n }\n}\n\n// takes in a single validation error and and displays it in more readable manner\n// used by renderErrorListTemplate\nfunction renderTransformedErrorObject(\n steps: Step[],\n error: RJSFValidationError,\n uiSchema: UiSchema,\n i: number,\n schema: any,\n): { order: number; element: ReactNode } {\n const propPath = trimStart(error.property, '.')\n const propArr = propPath.split('.')\n\n // some things require labels in schema (e.g. checkboxes) so this is preferred\n const labelFromSchema = `${propArr.join('.properties.')}.title`\n //can be overriden by label in UI\n const labelFromUi = `${propPath}.ui:title`\n //for array fields we need to change the property e.g.\n // ld50.experiments[0].species_other should look like 'ld50.experiments.items.species_other'\n const arrayLabelFromSchema = labelFromSchema.replace(/\\[.*?\\]/, '.items')\n const arrayLabelFromUI = labelFromUi.replace(/\\[.*?\\]/, '.items')\n const indexMatch = labelFromSchema.match(/\\[.*?\\]/)\n\n let index = first(indexMatch)\n\n if (index) {\n index = index.substring(1, index.length - 1)\n index = !isNaN(parseInt(index)) ? ` [${parseInt(index) + 1}]` : ''\n }\n\n const label =\n get(uiSchema, labelFromUi) ||\n get(schema.properties, labelFromSchema) ||\n get(uiSchema, arrayLabelFromUI) ||\n get(schema.properties, arrayLabelFromSchema) ||\n error.property\n\n const screen = find(steps, { id: propArr[0] }) || {\n title: propArr[0],\n order: 0,\n }\n const element = (\n <li key={i} className=\"\">\n <span>\n <strong>\n {screen.title}\n {index}:\n </strong>\n {label} {error.message}\n </span>\n </li>\n )\n return { order: screen.order, element }\n}\n\n//recursively sets property value to dangerouslySetInnerHTML of that value\nfunction stringToElementForProp(srcObject: any, key: string): object {\n keys(srcObject).some(k => {\n if (k === key) {\n const value = srcObject[k]\n srcObject[k] = <span dangerouslySetInnerHTML={{ __html: value }}></span>\n\n return srcObject\n }\n if (srcObject[k] && typeof srcObject[k] === 'object') {\n stringToElementForProp(srcObject[k], key)\n }\n })\n return srcObject\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SynapseForm.js","names":[],"sources":["../../../src/components/SynapseForm/SynapseForm.tsx"],"sourcesContent":["import Blocker from '@/components/utils/Blocker'\nimport Form from '@rjsf/core'\nimport { ErrorListProps, RJSFValidationError, UiSchema } from '@rjsf/utils'\nimport validator from '@rjsf/validator-ajv8'\nimport { Engine, EngineResult } from 'json-rules-engine'\nimport cloneDeep from 'lodash-es/cloneDeep'\nimport find from 'lodash-es/find'\nimport findIndex from 'lodash-es/findIndex'\nimport first from 'lodash-es/first'\nimport get from 'lodash-es/get'\nimport isEqual from 'lodash-es/isEqual'\nimport isUndefined from 'lodash-es/isUndefined'\nimport keys from 'lodash-es/keys'\nimport pick from 'lodash-es/pick'\nimport remove from 'lodash-es/remove'\nimport set from 'lodash-es/set'\nimport trimStart from 'lodash-es/trimStart'\nimport { Component, createRef, ReactNode, RefObject } from 'react'\nimport Switch from 'react-switch'\nimport { ConfirmationDialog } from '../ConfirmationDialog/ConfirmationDialog'\nimport DataDebug from './DataDebug'\nimport Header from './Header'\nimport { NavButtons, NextStepLink } from './NavButtons'\nimport StepsSideNav from './StepsSideNav'\nimport SummaryTable from './SummaryTable'\nimport SynapseFormCheckboxesWidget from './SynapseFormCheckboxesWidget'\nimport SynapseFormCheckboxWidget from './SynapseFormCheckboxWidget'\nimport SynapseFormRadioWidget from './SynapseFormRadioWidget'\nimport {\n FormSchema,\n IRulesNavigationEvent,\n IRulesValidationEvent,\n NavActionEnum,\n StatusEnum,\n Step,\n StepStateEnum,\n} from './types'\nimport WarningDialog from './WarningDialog'\n\nexport interface IFormData {\n [key: string]: {\n included?: boolean\n [key: string]: any\n }\n}\n\nexport type SynapseFormProps = {\n schema: FormSchema\n uiSchema: UiSchema\n navSchema: {\n steps: any[]\n }\n formData: IFormData\n onSubmit: (formData: IFormData) => void\n onSave: (formData: IFormData) => void\n formTitle: string\n formClass?: string\n isWizardMode?: boolean\n callbackStatus?: StatusEnum\n isSubmitted?: boolean\n}\n\ntype SynapseFormState = {\n formData: IFormData // form data that prepopulates the form\n currentStep: Step\n nextStep?: Step\n steps: Step[]\n previousStepIds: string[]\n hasValidated?: boolean //validation has been called and it passed\n doShowErrors: boolean //if we should show error summary at the top of the page\n doShowHelp: boolean\n modalContext?: { action: (...args: any[]) => void; arguments: any[] }\n hasUnsavedChanges: boolean\n isSubmitted?: boolean\n isLoadingSaved: boolean\n}\n\nexport interface SummaryFormat {\n label: string\n value: string\n}\n\nexport default class SynapseForm extends Component<\n SynapseFormProps,\n SynapseFormState\n> {\n excludeWarningText = (\n <div>\n <p>\n This action will clear any entered data on this page and remove this\n form from your submission. You can include it again at anytime. Only\n this page will be affected.\n </p>\n <p>Are you sure you want to skip this step and clear any entered data?</p>\n </div>\n )\n excludeWarningHeader = 'Skip This Step?'\n unsavedDataWarning = `You might have some unsaved data. Are you sure you want to leave?`\n formRef: RefObject<Form<IFormData> | null> //ref to form for submission\n submitButtonRef: RefObject<HTMLButtonElement | null>\n formDivRef: any // ref to the div containing form (for scrolling on validation failure)\n navAction: NavActionEnum = NavActionEnum.NONE\n uiSchema: UiSchema\n nextStep: Step | undefined\n extraErrors: RJSFValidationError[] = []\n\n isNewForm = (formData: IFormData): boolean => {\n return (\n (Object.keys(formData).length == 1 &&\n Object.keys(formData)[0] === 'metadata') ||\n Object.keys(formData).length == 0\n )\n }\n\n getFirstStep = (steps: Step[], formData: IFormData): Step => {\n if (!this.isNewForm(formData)) {\n return steps.find(step => step.final === true) || steps[0]\n } else {\n return steps[0]\n }\n }\n\n constructor(props: SynapseFormProps) {\n super(props)\n\n //will modify the ui:help to render html vs text\n this.uiSchema = stringToElementForProp(\n cloneDeep(props.uiSchema),\n 'ui:help',\n ) as UiSchema\n //create steps array from the navSchema\n const steps = props.navSchema.steps\n .map((step, i) => {\n return {\n ...step,\n inProgress: i === 0 ? true : false,\n }\n })\n .sort((a, b) => a.order - b.order)\n\n this.formRef = createRef()\n this.formDivRef = createRef()\n this.submitButtonRef = createRef()\n const currentStep = this.getFirstStep(steps, props.formData)\n this.state = {\n currentStep,\n steps,\n previousStepIds: [],\n formData: props.formData,\n doShowErrors: false,\n doShowHelp: true,\n hasUnsavedChanges: false,\n isSubmitted: props.isSubmitted,\n isLoadingSaved: !this.isNewForm(this.props.formData),\n }\n }\n\n onUnload = (ev: any) => {\n {\n if (this.state.hasUnsavedChanges) {\n ev.preventDefault()\n return (ev.returnValue = this.unsavedDataWarning)\n }\n return\n }\n }\n // Setup the `beforeunload` event listener\n setupBeforeUnloadListener = () => {\n window.addEventListener('beforeunload', this.onUnload)\n }\n\n componentWillUnmount() {\n window.removeEventListener('beforeunload', this.onUnload)\n }\n\n componentDidUpdate(prevProps: SynapseFormProps) {\n const shouldUpdate = this.props.callbackStatus !== prevProps.callbackStatus\n const isSuccess =\n this.props.callbackStatus === StatusEnum.SAVE_SUCCESS ||\n this.props.callbackStatus === StatusEnum.SUBMIT_SUCCESS\n if (shouldUpdate && isSuccess) {\n this.setState({ hasUnsavedChanges: false })\n if (this.props.callbackStatus === StatusEnum.SUBMIT_SUCCESS) {\n this.setState({ isSubmitted: true })\n window.history.back()\n }\n }\n }\n\n _setIncludedPropInFormDataNonWizard = (\n currentState: SynapseFormState,\n schemaScreens: any,\n ): IFormData => {\n const result = {}\n const currentStateFormData = currentState.formData\n //if there is a top level 'included' property in schema - update the form.\n Object.keys(schemaScreens).forEach((key: string) => {\n if (get(schemaScreens[key], `properties.included`)) {\n set(result, `${key}.included`, true)\n }\n })\n return { ...currentStateFormData, ...result }\n }\n\n _setIncludedPropInFormDataWizard = (\n currentState: SynapseFormState,\n ): IFormData => {\n const firstStepId = currentState.currentStep.id\n const newStateData = cloneDeep(currentState.formData)\n set(newStateData, `${firstStepId}.included`, true)\n return newStateData\n }\n\n componentDidMount() {\n this.setupBeforeUnloadListener()\n const isNewForm = this.isNewForm(this.state.formData)\n if (!isNewForm) {\n //when loading saved form - validate to see the steps status\n this.triggerAction(NavActionEnum.VALIDATE)\n } else {\n // for validation of optional forms. Validation is enforced only if included property is set.\n this.setState(prevState => {\n const newFormData = this.props.isWizardMode\n ? this._setIncludedPropInFormDataWizard(prevState)\n : this._setIncludedPropInFormDataNonWizard(\n prevState,\n this.props.schema,\n )\n return {\n formData: newFormData,\n }\n })\n }\n }\n\n // get the schema slice for the current screen/step\n getSchema = ({ id, final }: Step): FormSchema => {\n if (final) {\n return this.props.schema\n }\n //only get schema for current step. Only the portion of entire form is shown\n\n const currentStepSlice = pick(this.props.schema, [\n 'title',\n 'type',\n `properties.${id}`,\n ])\n return currentStepSlice\n }\n\n // find the next step\n getNextStepId = async (\n currentStep: Step,\n formData: any,\n nextStepId?: string,\n ): Promise<string> => {\n if (nextStepId) {\n return nextStepId\n }\n if (!currentStep.rules || currentStep.rules.length === 0) {\n return currentStep.default\n }\n\n // if there are rules - run the engine and go to the first next step\n const engine = new Engine(currentStep.rules)\n\n try {\n const result: EngineResult = await engine.run(formData)\n if (result.events.length > 0) {\n return (result.events[0] as IRulesNavigationEvent).params.next\n } else {\n return currentStep.default\n }\n } catch (error) {\n return currentStep.default\n }\n }\n\n // called when going next, previous or a given step\n moveStep = async (\n formData: any,\n nextStepId: string | undefined,\n isError: boolean,\n previousStack = [...this.state.previousStepIds],\n ) => {\n const currentStep = this.state.currentStep\n let currentStepState: StepStateEnum\n //we don't wnat to display errors on the page - this will be done explicitly in validation\n if (this.formRef?.current) {\n this.formRef.current.setState({ errorSchema: {} })\n }\n //in wizard mode we can only move forwards (don't know next step yet) or backwards (do know next step)\n const isMoveForwardInWizardMode = this.props.isWizardMode && !nextStepId\n\n //previousStack is used for 'back' navigation is wizard mode.\n //only need to do it if moving forward i.e. nextStepId is undefined\n if (isMoveForwardInWizardMode) {\n previousStack.push(currentStep.id)\n }\n\n if (!isError) {\n currentStepState = StepStateEnum.COMPLETED\n\n if (!isMoveForwardInWizardMode && this.props.isWizardMode) {\n currentStepState = StepStateEnum.TODO\n }\n } else {\n currentStepState = StepStateEnum.ERROR\n }\n // determine next step\n nextStepId = await this.getNextStepId(currentStep, formData, nextStepId)\n\n const steps = this.state.steps.map(step => {\n if (step.id === currentStep.id) {\n return {\n ...step,\n ...{ state: currentStepState, inProgress: false },\n }\n } else if (step.id === nextStepId) {\n return { ...step, ...{ inProgress: true } }\n }\n return step\n })\n //if we are in wizard mode we want to make sure that we include the step we are about to go to\n if (isMoveForwardInWizardMode) {\n set(formData, `${nextStepId}.included`, true)\n }\n\n //at this point the form is valid and submitted and the data reflects the latest\n const nextStep = this.state.steps.find(step => step.id === nextStepId)!\n // clean up unused screens in wizard before getting to submit\n if (this.props.isWizardMode && nextStep.final) {\n Object.keys(formData).forEach(key => {\n if (formData[key].included === undefined) {\n formData[key] = {}\n }\n })\n }\n\n this.saveStepState(previousStack, steps, nextStep, formData)\n }\n\n //save the state of the current screen\n saveStepState = (\n previousStepIds: string[],\n steps: Step[],\n currentStep: Step,\n formData: any,\n ) => {\n this.setState({\n previousStepIds,\n steps,\n currentStep,\n formData,\n hasValidated: false,\n doShowErrors: false,\n })\n }\n\n //--------- fns to support navigation --------------------//\n goPrevious = async (formData: any, isError: boolean) => {\n let previousStepId: string | undefined\n const previousStack: string[] = [...this.state.previousStepIds]\n // in wizard mode we go to the previously visited screen.\n // In regular mode go to the screen with previous index\n if (this.props.isWizardMode) {\n previousStepId = previousStack.pop()\n if (!this.isSubmitScreen()) {\n //since we don't know if we'll get back to that step again - exclude it. We will include it again if we\n // get to it.\n set(formData, `${this.state.currentStep.id}.included`, undefined)\n }\n } else {\n const currentIndex = findIndex(this.state.steps, {\n id: this.state.currentStep.id,\n })\n if (currentIndex > 0) {\n previousStepId = this.state.steps[currentIndex - 1].id\n }\n }\n if (!isUndefined(previousStepId)) {\n return this.moveStep(formData, previousStepId, isError, previousStack)\n }\n }\n\n triggerAction = async (navAction: NavActionEnum) => {\n // we don't need to validate on save so bypassing submit\n if (navAction === NavActionEnum.SAVE) {\n return this.props.onSave(this.state.formData)\n } else {\n this.navAction = navAction\n // first run whatever custom validaton we have\n this.extraErrors = await this.runCustomValidation(\n this.state.formData,\n this.state.currentStep,\n this.state.steps,\n )\n if (this.submitButtonRef.current) {\n this.submitButtonRef.current.click()\n }\n }\n }\n\n // triggered when we click on the step name in left nav (doesn't happen in wizard mode)\n triggerStepChange = (step: Step) => {\n this.nextStep = step\n this.triggerAction(NavActionEnum.GO_TO_STEP)\n }\n\n onError = (args: any) => {\n this.setState({\n doShowErrors: true,\n hasValidated: false,\n })\n if (this.navAction === NavActionEnum.VALIDATE) {\n const modifiedSteps = this.setStepStatusForFailedValidation(\n args.props,\n this.state.steps,\n !!this.props.isWizardMode,\n this.state.formData,\n this.getSchema(this.state.currentStep).properties ||\n this.getSchema(this.state.currentStep),\n )\n this.setState({ steps: modifiedSteps })\n this.formDivRef.current.scrollTo(0, 0)\n if (this.state.isLoadingSaved) {\n this.moveStep(this.state.formData, modifiedSteps[0].id, true)\n this.setState({ isLoadingSaved: false })\n }\n }\n }\n\n setStepStatusForFailedValidation = (\n errors: RJSFValidationError[],\n steps: Step[],\n isWizard: boolean,\n formData: IFormData,\n currentSchemaProperties: any,\n ): Step[] => {\n //error property is in the format: step.somevalue.etc .welcome.submission_name example\n //find all the steps where there is an error\n const stepsWithError = errors.map(\n error => trimStart(error.property, '.').split('.')[0],\n )\n //find all steps in current schema\n const stepsInCurrentSchema = Object.keys(currentSchemaProperties)\n const updatedSteps: Step[] = steps.map(step => {\n //if there is an error in this step\n if (stepsWithError.indexOf(step.id) > -1) {\n return {\n ...step,\n state: StepStateEnum.ERROR,\n }\n //if no error and included in schema\n } else if (stepsInCurrentSchema.indexOf(step.id) > -1) {\n let state = StepStateEnum.COMPLETED\n //if we are in wizard and possibly have not visited this step\n if (isWizard && !get(formData[step.id], 'included')) {\n state = step.state\n }\n\n return {\n ...step,\n state: state,\n }\n } else {\n return step\n }\n })\n return updatedSteps\n }\n\n //we are constantly saving form data. Needed to overwrite on-error behavior\n handleOnChange({ formData }: any) {\n //this is just for form updates. submit screen goes different route\n if (!this.isSubmitScreen() && !this.state.currentStep.excluded) {\n const hasUnsavedChanges = !isEqual(this.state.formData, formData)\n this.setState({ formData, hasUnsavedChanges })\n }\n }\n\n performAction(navAction: NavActionEnum, hasError: boolean) {\n const formData = this.state.formData\n\n switch (navAction) {\n case NavActionEnum.NEXT: {\n return this.moveStep(formData, undefined, hasError)\n }\n case NavActionEnum.PREVIOUS: {\n return this.goPrevious(formData, hasError)\n }\n case NavActionEnum.GO_TO_STEP: {\n //nextStep is returned when clicked on the Steps left nav\n if (!this.nextStep) {\n return\n }\n return this.moveStep(formData, this.nextStep.id, hasError)\n }\n\n case NavActionEnum.SUBMIT: {\n this.props.onSubmit(formData)\n return\n }\n case NavActionEnum.VALIDATE: {\n //we get here is we clicked validate and the data is valid.\n // if it's not valid we handle it in onError fn\n const steps = this.setStepStatusForFailedValidation(\n [],\n this.state.steps,\n !!this.props.isWizardMode,\n this.state.formData,\n this.getSchema(this.state.currentStep).properties ||\n this.getSchema(this.state.currentStep),\n )\n const currentStep = {\n ...this.state.currentStep,\n state: StepStateEnum.COMPLETED,\n }\n\n this.setState({ hasValidated: true, currentStep, steps })\n if (this.state.isLoadingSaved) {\n this.moveStep(this.state.formData, steps[0].id, false)\n this.setState({ isLoadingSaved: false })\n }\n return\n }\n default:\n return\n }\n }\n\n //we need to route things through submit - otherwise validation does not kick in\n // it triggers internal library validation and calls the performAction with the params for action\n onSubmit: () => any = () => {\n this.performAction(\n this.navAction,\n this.state.currentStep.state === StepStateEnum.ERROR,\n )\n }\n\n isSubmitScreen = (): boolean => {\n return this.state.currentStep.final === true && !this.state.isLoadingSaved\n }\n\n showExcludeStateWarningDialog = (\n stepId: string,\n isUpdateFlattenedData: boolean = false,\n ): void => {\n this.setState({\n modalContext: {\n action: this.toggleExcludeStep,\n arguments: [stepId, true, isUpdateFlattenedData],\n },\n })\n }\n\n toggleExcludeStep = (stepId: string, isExclude: boolean): void => {\n this.setState((prevState, props) => {\n const steps = prevState.steps.map(stp => {\n if (stp.id === stepId) {\n return { ...stp, ...{ excluded: isExclude } }\n }\n return stp\n })\n\n const formDataUpdated = cloneDeep(prevState.formData)\n const currentStep = cloneDeep(prevState.currentStep)\n //we need this because you can exclude on the ifnal screen so the currentStep.id\n //is not always the one we need to exclude\n if (currentStep.id === stepId) {\n currentStep.excluded = isExclude\n }\n //if exluding - blow away the data for the step\n if (isExclude) {\n formDataUpdated[stepId] = {}\n //set(formDataUpdated, `${stepId}.included`, false);\n } else {\n set(formDataUpdated, `${stepId}.included`, true)\n }\n return {\n steps,\n formData: formDataUpdated,\n modalContext: undefined,\n currentStep,\n }\n })\n }\n\n private renderNotification = (status?: StatusEnum) => {\n if (status === StatusEnum.SAVE_SUCCESS) {\n return <div className=\"notification-area\"> Successfully saved </div>\n }\n if (status === StatusEnum.SUBMIT_SUCCESS) {\n return <div className=\"notification-area\"> Successfully submitted </div>\n }\n if (status === StatusEnum.PROGRESS) {\n return <div className=\"notification-area\"> working on it ....</div>\n }\n return <></>\n }\n\n // displays the text for screens that don't have any form data\n private renderTextForStaticScreen = () => {\n if (!this.state.currentStep.copy) {\n return <></>\n }\n const copy = this.state.currentStep.copy\n return (\n <div\n className=\"static-screen\"\n dangerouslySetInnerHTML={{ __html: copy }}\n />\n )\n }\n\n //displays subheader for forms that can be excluded\n renderOptionalFormSubheader = (isWizard: boolean = false) => {\n if (isWizard) {\n return <></>\n }\n const currentStep = this.state.currentStep\n\n if (currentStep.excluded === true) {\n return (\n <div className=\"step-exclude-directions\">\n This form is currently not included in the submission.\n <button\n className=\"btn btn-link\"\n onClick={() => this.toggleExcludeStep(currentStep.id, false)}\n >\n Include\n </button>\n </div>\n )\n } else if (currentStep.excluded === false) {\n return (\n <div className=\"step-exclude-directions\">\n This form is currently included in the submission. Enter some data if\n you have it, or click "Skip".\n <button\n className=\"btn btn-link\"\n onClick={() =>\n this.showExcludeStateWarningDialog(this.state.currentStep.id)\n }\n >\n Skip\n </button>\n </div>\n )\n }\n return <></>\n }\n\n renderHelpToggle = (\n currentStep: Step,\n showHelp: boolean,\n callbackFn: () => void,\n ) => {\n if (currentStep.static || currentStep.final) {\n return <></>\n }\n return (\n <>\n <label className=\"pull-right toggle-help-label\">\n <span>Hide help</span>\n <Switch\n checkedIcon={false}\n uncheckedIcon={false}\n height={20}\n width={45}\n className=\"toggle-help\"\n offColor=\"#ccc\"\n onChange={() => callbackFn()}\n checked={showHelp}\n />\n <span>Show help</span>\n </label>\n </>\n )\n }\n\n runCustomValidation = async (\n formData: IFormData,\n currentStep: Step,\n allSteps: Step[],\n ): Promise<RJSFValidationError[]> => {\n const errors: RJSFValidationError[] = []\n\n //default - running on current step\n let rules = currentStep.validationRules || []\n let data = {\n [currentStep.id]: formData[currentStep.id],\n }\n\n // for final step -- concatenate all rules and run on all data\n if (currentStep.final) {\n rules = allSteps.reduce((acc: any, value: Step) => {\n return value.validationRules && value.validationRules.length > 0\n ? acc.concat(value.validationRules)\n : acc\n }, [])\n data = cloneDeep(formData)\n }\n\n if (rules.length === 0) {\n return []\n }\n\n //this is a workaround for inability to define a rule to run on all members of the data array\n // we define the generic rule with path e.g.\"path\": \".experiments[*].dose_range.dose_range_min\",\n const allRules: any[] = []\n rules.forEach(rule => {\n //take a rule\n const paramProp = rule.event.params.property\n // if it's just a normal rule - add it\n if (paramProp.indexOf('[*]') === -1) {\n allRules.push(rule)\n } else {\n const path = paramProp.split('[*]')[0].substring(1)\n const data = get(formData, path)\n // generate a rule for each item in the data array by substituting [*] w/ appropriate index\n if (Array.isArray(data) && typeof data !== 'string') {\n for (let i = 0; i < data.length; i++) {\n const newRule = JSON.parse(\n JSON.stringify(rule).replace(/\\[\\*\\]/g, `[${i}]`),\n )\n allRules.push(newRule)\n }\n } else {\n allRules.push(rule)\n }\n }\n })\n // no we run all the rules through the engine\n const engine = new Engine(allRules, {\n allowUndefinedFacts: true,\n })\n\n try {\n const result: EngineResult = await engine.run(data)\n const validationEvents = result.events as IRulesValidationEvent[]\n validationEvents.forEach(event => {\n const err: RJSFValidationError = {\n ...event.params,\n ...{\n params: {},\n stack: `${event.params.property} ${event.params.message}`,\n },\n }\n errors.push(err)\n })\n } catch (error) {\n console.log(error)\n }\n\n return errors\n }\n\n transformErrors = (errors: RJSFValidationError[]): RJSFValidationError[] => {\n // if we are not in wizard mode and not trying to submit or validate we just want to skip\n // over the errors and just set the step status\n // https://github.com/rjsf-team/react-jsonschema-form/issues/1263\n this.extraErrors.forEach(extraError => {\n if (!errors.find(error => error.stack === extraError.stack)) {\n errors.push(extraError)\n }\n })\n\n if (\n this.navAction !== NavActionEnum.SUBMIT &&\n this.navAction !== NavActionEnum.VALIDATE &&\n (!this.props.isWizardMode || this.state.currentStep.final)\n ) {\n const currentStep = {\n ...this.state.currentStep,\n }\n if (errors.length > 0) {\n currentStep.state = StepStateEnum.ERROR\n } else {\n currentStep.state = StepStateEnum.COMPLETED\n }\n\n this.setState({ currentStep })\n\n return []\n }\n\n // there is an odd behavior in the lib that in cases when we have additional fields depending on enum\n // value if it's required and not entered we get 3 error: enum, required, and oneOf\n // so if there is an error Oneof on a parent - ignore it and enum on a child. and just output 'required'\n // if there is an enum error and there is required with the same prefix remove it\n\n const reqErrors = errors.filter(error => error.name === 'required')\n reqErrors.forEach(error => {\n if (error.property) {\n const parentPath = error.property.substring(\n 0,\n error.property.lastIndexOf('.'),\n )\n remove(errors, (error: RJSFValidationError) => {\n return (\n (error.property || '').indexOf(parentPath) > -1 &&\n (error.name === 'enum' || error.name === 'oneOf')\n )\n })\n }\n })\n\n return errors.map(error => {\n if (error.message) {\n error.message = error.message.replace('property', 'field')\n }\n return error\n })\n }\n\n renderErrorListTemplate = (props: ErrorListProps) => {\n const { errors } = props\n const currentLis = errors\n .map((error, i) => {\n return renderTransformedErrorObject(\n this.state.steps,\n error,\n this.uiSchema,\n i,\n this.props.schema,\n )\n })\n .sort((a, b) => a.order - b.order)\n .map(li => li.element)\n\n return (\n <div className=\"form-error-summary\">\n <ul className=\"error-detail\">{currentLis}</ul>\n </div>\n )\n }\n\n render() {\n return (\n <div className=\"outter-wrap\">\n <Blocker\n shouldBlock={({ currentLocation, nextLocation }) =>\n this.state.hasUnsavedChanges &&\n currentLocation.pathname !== nextLocation.pathname\n }\n >\n {blocker => (\n <ConfirmationDialog\n open={blocker.state == 'blocked'}\n title=\"Unsaved Changes\"\n content={this.unsavedDataWarning}\n onConfirm={() => {\n if (blocker.proceed) {\n blocker.proceed()\n }\n }}\n onCancel={() => {\n if (blocker.reset) {\n blocker.reset()\n }\n }}\n />\n )}\n </Blocker>\n <Header\n isSubmitted={this.state.isSubmitted}\n bodyText={this.state.currentStep.description}\n title={this.props.formTitle}\n ></Header>\n <div>\n <div className=\"inner-wrap\">\n <StepsSideNav\n stepList={this.state.steps}\n isWizardMode={this.props.isWizardMode}\n onStepChange={this.triggerStepChange}\n ></StepsSideNav>\n {this.state.isLoadingSaved && (\n <div className=\"text-center\">\n <span className={'spinner'} />\n </div>\n )}\n <div className=\"form-wrap\">\n <div className=\"form-title\">{this.state.currentStep.title}</div>\n {this.renderNotification(this.props.callbackStatus)}\n <div\n className={`right-top-actions ${\n this.state.isSubmitted ? 'hide' : ''\n }`}\n >\n {!this.state.currentStep.static && (\n <button\n type=\"button\"\n className=\"btn btn-action save pull-right\"\n onClick={() => {\n this.triggerAction(NavActionEnum.VALIDATE)\n }}\n >\n VALIDATE\n </button>\n )}\n {this.renderHelpToggle(\n this.state.currentStep,\n this.state.doShowHelp,\n () =>\n this.setState({\n doShowHelp: !this.state.doShowHelp,\n }),\n )}\n {this.isSubmitScreen() && (\n <button\n type=\"button\"\n className=\"btn btn-action save pull-right\"\n disabled={this.state.isSubmitted}\n onClick={() => {\n this.triggerAction(NavActionEnum.SUBMIT)\n }}\n >\n SUBMIT\n </button>\n )}\n </div>\n {this.renderOptionalFormSubheader(this.props.isWizardMode)}\n <div\n className={\n this.isSubmitScreen() || this.state.currentStep.static\n ? 'hide-form-only'\n : 'wrap'\n }\n >\n {this.state.hasValidated && (\n <div className=\"notification-area\">\n Great! All required data on this form has been entered.\n </div>\n )}\n <div\n ref={this.formDivRef}\n className={`scroll-area ${\n this.state.currentStep.excluded ? 'disabled' : ' '\n } `}\n >\n <Form\n validator={validator}\n noHtml5Validate\n className={\n this.state.doShowHelp\n ? 'submissionInputForm'\n : 'submissionInputForm no-help'\n }\n liveValidate={false}\n formData={this.state.formData}\n schema={this.getSchema(this.state.currentStep)}\n uiSchema={this.uiSchema}\n onSubmit={this.onSubmit}\n onChange={args => this.handleOnChange(args)}\n onError={args =>\n this.onError({\n props: args,\n form: this.formRef,\n })\n }\n showErrorList={\n this.state.doShowErrors || this.props.isWizardMode\n ? 'top'\n : false\n }\n templates={{\n ErrorListTemplate: this.renderErrorListTemplate,\n }}\n transformErrors={this.transformErrors}\n ref={this.formRef}\n disabled={\n this.state.currentStep.excluded || this.state.isSubmitted\n }\n widgets={{\n CheckboxWidget: SynapseFormCheckboxWidget,\n CheckboxesWidget: SynapseFormCheckboxesWidget,\n RadioWidget: SynapseFormRadioWidget,\n }}\n >\n <div style={{ display: 'none' }}>\n <button type=\"submit\" ref={this.submitButtonRef}></button>\n </div>\n </Form>\n {this.renderTextForStaticScreen()}\n {!this.props.isWizardMode && (\n <NextStepLink\n steps={this.state.steps}\n nextStepId={this.state.currentStep.default}\n onNavAction={(step: Step) => this.triggerStepChange(step)}\n ></NextStepLink>\n )}\n </div>\n </div>\n\n {this.isSubmitScreen() && (\n <SummaryTable\n formData={this.state.formData}\n steps={this.state.steps}\n callbackFn={(screenId: string) =>\n this.showExcludeStateWarningDialog(screenId, true)\n }\n uiSchema={this.props.uiSchema}\n schema={this.props.schema}\n ></SummaryTable>\n )}\n\n <NavButtons\n currentStep={this.state.currentStep}\n steps={this.state.steps}\n previousStepIds={this.state.previousStepIds}\n isFormSubmitted={this.state.isSubmitted}\n onNavAction={(e: NavActionEnum) => {\n this.triggerAction(e)\n }}\n ></NavButtons>\n </div>\n </div>\n </div>\n {this.state.modalContext && (\n <WarningDialog\n open={true}\n title={this.excludeWarningHeader}\n content={this.excludeWarningText}\n className={`theme-${this.props.formClass}`}\n onConfirmCallbackArgs={this.state.modalContext.arguments}\n onCancel={() => this.setState({ modalContext: undefined })}\n onConfirm={(stepId: string, isExclude: boolean) =>\n this.toggleExcludeStep(stepId, isExclude)\n }\n />\n )}\n <DataDebug formData={this.state.formData} hidden={true}></DataDebug>\n </div>\n )\n }\n}\n\n// takes in a single validation error and and displays it in more readable manner\n// used by renderErrorListTemplate\nfunction renderTransformedErrorObject(\n steps: Step[],\n error: RJSFValidationError,\n uiSchema: UiSchema,\n i: number,\n schema: any,\n): { order: number; element: ReactNode } {\n const propPath = trimStart(error.property, '.')\n const propArr = propPath.split('.')\n\n // some things require labels in schema (e.g. checkboxes) so this is preferred\n const labelFromSchema = `${propArr.join('.properties.')}.title`\n //can be overriden by label in UI\n const labelFromUi = `${propPath}.ui:title`\n //for array fields we need to change the property e.g.\n // ld50.experiments[0].species_other should look like 'ld50.experiments.items.species_other'\n const arrayLabelFromSchema = labelFromSchema.replace(/\\[.*?\\]/, '.items')\n const arrayLabelFromUI = labelFromUi.replace(/\\[.*?\\]/, '.items')\n const indexMatch = labelFromSchema.match(/\\[.*?\\]/)\n\n let index = first(indexMatch)\n\n if (index) {\n index = index.substring(1, index.length - 1)\n index = !isNaN(parseInt(index)) ? ` [${parseInt(index) + 1}]` : ''\n }\n\n const label =\n get(uiSchema, labelFromUi) ||\n get(schema.properties, labelFromSchema) ||\n get(uiSchema, arrayLabelFromUI) ||\n get(schema.properties, arrayLabelFromSchema) ||\n error.property\n\n const screen = find(steps, { id: propArr[0] }) || {\n title: propArr[0],\n order: 0,\n }\n const element = (\n <li key={i} className=\"\">\n <span>\n <strong>\n {screen.title}\n {index}:\n </strong>\n {label} {error.message}\n </span>\n </li>\n )\n return { order: screen.order, element }\n}\n\n//recursively sets property value to dangerouslySetInnerHTML of that value\nfunction stringToElementForProp(srcObject: any, key: string): object {\n keys(srcObject).some(k => {\n if (k === key) {\n const value = srcObject[k]\n srcObject[k] = <span dangerouslySetInnerHTML={{ __html: value }}></span>\n\n return srcObject\n }\n if (srcObject[k] && typeof srcObject[k] === 'object') {\n stringToElementForProp(srcObject[k], key)\n }\n })\n return srcObject\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkFA,IAAqB,IAArB,cAAyC,EAGvC;CACA,qBACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD,EAAA,UAAG,yKAIC,CAAA,EACJ,kBAAC,KAAD,EAAA,UAAG,uEAAuE,CAAA,CACtE,EAAA,CAAA;CAER,uBAAuB;CACvB,qBAAqB;CACrB;CACA;CACA;CACA,YAA2B,EAAc;CACzC;CACA;CACA,cAAqC,EAAE;CAEvC,aAAa,MAER,OAAO,KAAK,EAAS,CAAC,UAAU,KAC/B,OAAO,KAAK,EAAS,CAAC,OAAO,cAC/B,OAAO,KAAK,EAAS,CAAC,UAAU;CAIpC,gBAAgB,GAAe,MACxB,KAAK,UAAU,EAAS,GAGpB,EAAM,KAFN,EAAM,MAAK,MAAQ,EAAK,UAAU,GAAK,IAAI,EAAM;CAM5D,YAAY,GAAyB;AAInC,EAHA,MAAM,EAAM,EAGZ,KAAK,WAAW,EACd,EAAU,EAAM,SAAS,EACzB,UACD;EAED,IAAM,IAAQ,EAAM,UAAU,MAC3B,KAAK,GAAM,OACH;GACL,GAAG;GACH,YAAY,MAAM;GACnB,EACD,CACD,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,MAAM;AAIpC,EAFA,KAAK,UAAU,GAAW,EAC1B,KAAK,aAAa,GAAW,EAC7B,KAAK,kBAAkB,GAAW;EAClC,IAAM,IAAc,KAAK,aAAa,GAAO,EAAM,SAAS;AAC5D,OAAK,QAAQ;GACX;GACA;GACA,iBAAiB,EAAE;GACnB,UAAU,EAAM;GAChB,cAAc;GACd,YAAY;GACZ,mBAAmB;GACnB,aAAa,EAAM;GACnB,gBAAgB,CAAC,KAAK,UAAU,KAAK,MAAM,SAAS;GACrD;;CAGH,YAAY,MAAY;AAEpB,MAAI,KAAK,MAAM,kBAEb,QADA,EAAG,gBAAgB,EACX,EAAG,cAAc,KAAK;;CAMpC,kCAAkC;AAChC,SAAO,iBAAiB,gBAAgB,KAAK,SAAS;;CAGxD,uBAAuB;AACrB,SAAO,oBAAoB,gBAAgB,KAAK,SAAS;;CAG3D,mBAAmB,GAA6B;EAC9C,IAAM,IAAe,KAAK,MAAM,mBAAmB,EAAU,gBACvD,IACJ,KAAK,MAAM,mBAAmB,EAAW,gBACzC,KAAK,MAAM,mBAAmB,EAAW;AAC3C,EAAI,KAAgB,MAClB,KAAK,SAAS,EAAE,mBAAmB,IAAO,CAAC,EACvC,KAAK,MAAM,mBAAmB,EAAW,mBAC3C,KAAK,SAAS,EAAE,aAAa,IAAM,CAAC,EACpC,OAAO,QAAQ,MAAM;;CAK3B,uCACE,GACA,MACc;EACd,IAAM,IAAS,EAAE,EACX,IAAuB,EAAa;AAO1C,SALA,OAAO,KAAK,EAAc,CAAC,SAAS,MAAgB;AAClD,GAAI,EAAI,EAAc,IAAM,sBAAsB,IAChD,EAAI,GAAQ,GAAG,EAAI,YAAY,GAAK;IAEtC,EACK;GAAE,GAAG;GAAsB,GAAG;GAAQ;;CAG/C,oCACE,MACc;EACd,IAAM,IAAc,EAAa,YAAY,IACvC,IAAe,EAAU,EAAa,SAAS;AAErD,SADA,EAAI,GAAc,GAAG,EAAY,YAAY,GAAK,EAC3C;;CAGT,oBAAoB;AAGlB,EAFA,KAAK,2BAA2B,EACd,KAAK,UAAU,KAAK,MAAM,SACvC,GAKH,KAAK,UAAS,OAOL,EACL,UAPkB,KAAK,MAAM,eAC3B,KAAK,iCAAiC,EAAU,GAChD,KAAK,oCACH,GACA,KAAK,MAAM,OACZ,EAGJ,EACD,GAbF,KAAK,cAAc,EAAc,SAAS;;CAkB9C,aAAa,EAAE,OAAI,eACb,IACK,KAAK,MAAM,SAIK,EAAK,KAAK,MAAM,QAAQ;EAC/C;EACA;EACA,cAAc;EACf,CACM;CAIT,gBAAgB,OACd,GACA,GACA,MACoB;AACpB,MAAI,EACF,QAAO;AAET,MAAI,CAAC,EAAY,SAAS,EAAY,MAAM,WAAW,EACrD,QAAO,EAAY;EAIrB,IAAM,IAAS,IAAI,EAAO,EAAY,MAAM;AAE5C,MAAI;GACF,IAAM,IAAuB,MAAM,EAAO,IAAI,EAAS;AAIrD,UAHE,EAAO,OAAO,SAAS,IACjB,EAAO,OAAO,GAA6B,OAAO,OAEnD,EAAY;UAEP;AACd,UAAO,EAAY;;;CAKvB,WAAW,OACT,GACA,GACA,GACA,IAAgB,CAAC,GAAG,KAAK,MAAM,gBAAgB,KAC5C;EACH,IAAM,IAAc,KAAK,MAAM,aAC3B;AAEJ,EAAI,KAAK,SAAS,WAChB,KAAK,QAAQ,QAAQ,SAAS,EAAE,aAAa,EAAE,EAAE,CAAC;EAGpD,IAAM,IAA4B,KAAK,MAAM,gBAAgB,CAAC;AAkB9D,EAdI,KACF,EAAc,KAAK,EAAY,GAAG,EAG/B,IAOH,IAAmB,EAAc,SANjC,IAAmB,EAAc,WAE7B,CAAC,KAA6B,KAAK,MAAM,iBAC3C,IAAmB,EAAc,QAMrC,IAAa,MAAM,KAAK,cAAc,GAAa,GAAU,EAAW;EAExE,IAAM,IAAQ,KAAK,MAAM,MAAM,KAAI,MAC7B,EAAK,OAAO,EAAY,KACnB;GACL,GAAG;GACE,OAAO;GAAkB,YAAY;GAC3C,GACQ,EAAK,OAAO,IACd;GAAE,GAAG;GAAW,YAAY;GAAQ,GAEtC,EACP;AAEF,EAAI,KACF,EAAI,GAAU,GAAG,EAAW,YAAY,GAAK;EAI/C,IAAM,IAAW,KAAK,MAAM,MAAM,MAAK,MAAQ,EAAK,OAAO,EAAW;AAUtE,EARI,KAAK,MAAM,gBAAgB,EAAS,SACtC,OAAO,KAAK,EAAS,CAAC,SAAQ,MAAO;AACnC,GAAI,EAAS,GAAK,aAAa,KAAA,MAC7B,EAAS,KAAO,EAAE;IAEpB,EAGJ,KAAK,cAAc,GAAe,GAAO,GAAU,EAAS;;CAI9D,iBACE,GACA,GACA,GACA,MACG;AACH,OAAK,SAAS;GACZ;GACA;GACA;GACA;GACA,cAAc;GACd,cAAc;GACf,CAAC;;CAIJ,aAAa,OAAO,GAAe,MAAqB;EACtD,IAAI,GACE,IAA0B,CAAC,GAAG,KAAK,MAAM,gBAAgB;AAG/D,MAAI,KAAK,MAAM,aAEb,CADA,IAAiB,EAAc,KAAK,EAC/B,KAAK,gBAAgB,IAGxB,EAAI,GAAU,GAAG,KAAK,MAAM,YAAY,GAAG,YAAY,KAAA,EAAU;OAE9D;GACL,IAAM,IAAe,EAAU,KAAK,MAAM,OAAO,EAC/C,IAAI,KAAK,MAAM,YAAY,IAC5B,CAAC;AACF,GAAI,IAAe,MACjB,IAAiB,KAAK,MAAM,MAAM,IAAe,GAAG;;AAGxD,MAAI,CAAC,EAAY,EAAe,CAC9B,QAAO,KAAK,SAAS,GAAU,GAAgB,GAAS,EAAc;;CAI1E,gBAAgB,OAAO,MAA6B;AAElD,MAAI,MAAc,EAAc,KAC9B,QAAO,KAAK,MAAM,OAAO,KAAK,MAAM,SAAS;AAS7C,EAPA,KAAK,YAAY,GAEjB,KAAK,cAAc,MAAM,KAAK,oBAC5B,KAAK,MAAM,UACX,KAAK,MAAM,aACX,KAAK,MAAM,MACZ,EACG,KAAK,gBAAgB,WACvB,KAAK,gBAAgB,QAAQ,OAAO;;CAM1C,qBAAqB,MAAe;AAElC,EADA,KAAK,WAAW,GAChB,KAAK,cAAc,EAAc,WAAW;;CAG9C,WAAW,MAAc;AAKvB,MAJA,KAAK,SAAS;GACZ,cAAc;GACd,cAAc;GACf,CAAC,EACE,KAAK,cAAc,EAAc,UAAU;GAC7C,IAAM,IAAgB,KAAK,iCACzB,EAAK,OACL,KAAK,MAAM,OACX,CAAC,CAAC,KAAK,MAAM,cACb,KAAK,MAAM,UACX,KAAK,UAAU,KAAK,MAAM,YAAY,CAAC,cACrC,KAAK,UAAU,KAAK,MAAM,YAAY,CACzC;AAGD,GAFA,KAAK,SAAS,EAAE,OAAO,GAAe,CAAC,EACvC,KAAK,WAAW,QAAQ,SAAS,GAAG,EAAE,EAClC,KAAK,MAAM,mBACb,KAAK,SAAS,KAAK,MAAM,UAAU,EAAc,GAAG,IAAI,GAAK,EAC7D,KAAK,SAAS,EAAE,gBAAgB,IAAO,CAAC;;;CAK9C,oCACE,GACA,GACA,GACA,GACA,MACW;EAGX,IAAM,IAAiB,EAAO,KAC5B,MAAS,EAAU,EAAM,UAAU,IAAI,CAAC,MAAM,IAAI,CAAC,GACpD,EAEK,IAAuB,OAAO,KAAK,EAAwB;AAwBjE,SAvB6B,EAAM,KAAI,MAAQ;AAE7C,OAAI,EAAe,QAAQ,EAAK,GAAG,GAAG,GACpC,QAAO;IACL,GAAG;IACH,OAAO,EAAc;IACtB;OAEQ,EAAqB,QAAQ,EAAK,GAAG,GAAG,IAAI;IACrD,IAAI,IAAQ,EAAc;AAM1B,WAJI,KAAY,CAAC,EAAI,EAAS,EAAK,KAAK,WAAW,KACjD,IAAQ,EAAK,QAGR;KACL,GAAG;KACI;KACR;SAED,QAAO;IAGJ;;CAIT,eAAe,EAAE,eAAiB;AAEhC,MAAI,CAAC,KAAK,gBAAgB,IAAI,CAAC,KAAK,MAAM,YAAY,UAAU;GAC9D,IAAM,IAAoB,CAAC,EAAQ,KAAK,MAAM,UAAU,EAAS;AACjE,QAAK,SAAS;IAAE;IAAU;IAAmB,CAAC;;;CAIlD,cAAc,GAA0B,GAAmB;EACzD,IAAM,IAAW,KAAK,MAAM;AAE5B,UAAQ,GAAR;GACE,KAAK,EAAc,KACjB,QAAO,KAAK,SAAS,GAAU,KAAA,GAAW,EAAS;GAErD,KAAK,EAAc,SACjB,QAAO,KAAK,WAAW,GAAU,EAAS;GAE5C,KAAK,EAAc,WAKjB,QAHK,KAAK,WAGH,KAAK,SAAS,GAAU,KAAK,SAAS,IAAI,EAAS,GAFxD;GAKJ,KAAK,EAAc;AACjB,SAAK,MAAM,SAAS,EAAS;AAC7B;GAEF,KAAK,EAAc,UAAU;IAG3B,IAAM,IAAQ,KAAK,iCACjB,EAAE,EACF,KAAK,MAAM,OACX,CAAC,CAAC,KAAK,MAAM,cACb,KAAK,MAAM,UACX,KAAK,UAAU,KAAK,MAAM,YAAY,CAAC,cACrC,KAAK,UAAU,KAAK,MAAM,YAAY,CACzC,EACK,IAAc;KAClB,GAAG,KAAK,MAAM;KACd,OAAO,EAAc;KACtB;AAGD,IADA,KAAK,SAAS;KAAE,cAAc;KAAM;KAAa;KAAO,CAAC,EACrD,KAAK,MAAM,mBACb,KAAK,SAAS,KAAK,MAAM,UAAU,EAAM,GAAG,IAAI,GAAM,EACtD,KAAK,SAAS,EAAE,gBAAgB,IAAO,CAAC;AAE1C;;GAEF,QACE;;;CAMN,iBAA4B;AAC1B,OAAK,cACH,KAAK,WACL,KAAK,MAAM,YAAY,UAAU,EAAc,MAChD;;CAGH,uBACS,KAAK,MAAM,YAAY,UAAU,MAAQ,CAAC,KAAK,MAAM;CAG9D,iCACE,GACA,IAAiC,OACxB;AACT,OAAK,SAAS,EACZ,cAAc;GACZ,QAAQ,KAAK;GACb,WAAW;IAAC;IAAQ;IAAM;IAAsB;GACjD,EACF,CAAC;;CAGJ,qBAAqB,GAAgB,MAA6B;AAChE,OAAK,UAAU,GAAW,MAAU;GAClC,IAAM,IAAQ,EAAU,MAAM,KAAI,MAC5B,EAAI,OAAO,IACN;IAAE,GAAG;IAAU,UAAU;IAAa,GAExC,EACP,EAEI,IAAkB,EAAU,EAAU,SAAS,EAC/C,IAAc,EAAU,EAAU,YAAY;AAapD,UAVI,EAAY,OAAO,MACrB,EAAY,WAAW,IAGrB,IACF,EAAgB,KAAU,EAAE,GAG5B,EAAI,GAAiB,GAAG,EAAO,YAAY,GAAK,EAE3C;IACL;IACA,UAAU;IACV,cAAc,KAAA;IACd;IACD;IACD;;CAGJ,sBAA8B,MACxB,MAAW,EAAW,eACjB,kBAAC,OAAD;EAAK,WAAU;YAAoB;EAA0B,CAAA,GAElE,MAAW,EAAW,iBACjB,kBAAC,OAAD;EAAK,WAAU;YAAoB;EAA8B,CAAA,GAEtE,MAAW,EAAW,WACjB,kBAAC,OAAD;EAAK,WAAU;YAAoB;EAAyB,CAAA,GAE9D,kBAAA,GAAA,EAAK,CAAA;CAId,kCAA0C;AACxC,MAAI,CAAC,KAAK,MAAM,YAAY,KAC1B,QAAO,kBAAA,GAAA,EAAK,CAAA;EAEd,IAAM,IAAO,KAAK,MAAM,YAAY;AACpC,SACE,kBAAC,OAAD;GACE,WAAU;GACV,yBAAyB,EAAE,QAAQ,GAAM;GACzC,CAAA;;CAKN,+BAA+B,IAAoB,OAAU;AAC3D,MAAI,EACF,QAAO,kBAAA,GAAA,EAAK,CAAA;EAEd,IAAM,IAAc,KAAK,MAAM;AA8B/B,SA5BI,EAAY,aAAa,KAEzB,kBAAC,OAAD;GAAK,WAAU;aAAf,CAAyC,0DAEvC,kBAAC,UAAD;IACE,WAAU;IACV,eAAe,KAAK,kBAAkB,EAAY,IAAI,GAAM;cAC7D;IAEQ,CAAA,CACL;OAEC,EAAY,aAAa,KAEhC,kBAAC,OAAD;GAAK,WAAU;aAAf,CAAyC,yGAGvC,kBAAC,UAAD;IACE,WAAU;IACV,eACE,KAAK,8BAA8B,KAAK,MAAM,YAAY,GAAG;cAEhE;IAEQ,CAAA,CACL;OAGH,kBAAA,GAAA,EAAK,CAAA;;CAGd,oBACE,GACA,GACA,MAEI,EAAY,UAAU,EAAY,QAC7B,kBAAA,GAAA,EAAK,CAAA,GAGZ,kBAAA,GAAA,EAAA,UACE,kBAAC,SAAD;EAAO,WAAU;YAAjB;GACE,kBAAC,QAAD,EAAA,UAAM,aAAgB,CAAA;GACtB,kBAAC,GAAD;IACE,aAAa;IACb,eAAe;IACf,QAAQ;IACR,OAAO;IACP,WAAU;IACV,UAAS;IACT,gBAAgB,GAAY;IAC5B,SAAS;IACT,CAAA;GACF,kBAAC,QAAD,EAAA,UAAM,aAAgB,CAAA;GAChB;KACP,CAAA;CAIP,sBAAsB,OACpB,GACA,GACA,MACmC;EACnC,IAAM,IAAgC,EAAE,EAGpC,IAAQ,EAAY,mBAAmB,EAAE,EACzC,IAAO,GACR,EAAY,KAAK,EAAS,EAAY,KACxC;AAYD,MATI,EAAY,UACd,IAAQ,EAAS,QAAQ,GAAU,MAC1B,EAAM,mBAAmB,EAAM,gBAAgB,SAAS,IAC3D,EAAI,OAAO,EAAM,gBAAgB,GACjC,GACH,EAAE,CAAC,EACN,IAAO,EAAU,EAAS,GAGxB,EAAM,WAAW,EACnB,QAAO,EAAE;EAKX,IAAM,IAAkB,EAAE;AAC1B,IAAM,SAAQ,MAAQ;GAEpB,IAAM,IAAY,EAAK,MAAM,OAAO;AAEpC,OAAI,EAAU,QAAQ,MAAM,KAAK,GAC/B,GAAS,KAAK,EAAK;QACd;IAEL,IAAM,IAAO,EAAI,GADJ,EAAU,MAAM,MAAM,CAAC,GAAG,UAAU,EACtB,CAAK;AAEhC,QAAI,MAAM,QAAQ,EAAK,IAAI,OAAO,KAAS,SACzC,MAAK,IAAI,IAAI,GAAG,IAAI,EAAK,QAAQ,KAAK;KACpC,IAAM,IAAU,KAAK,MACnB,KAAK,UAAU,EAAK,CAAC,QAAQ,WAAW,IAAI,EAAE,GAAG,CAClD;AACD,OAAS,KAAK,EAAQ;;QAGxB,GAAS,KAAK,EAAK;;IAGvB;EAEF,IAAM,IAAS,IAAI,EAAO,GAAU,EAClC,qBAAqB,IACtB,CAAC;AAEF,MAAI;AAGF,IADyB,MADU,EAAO,IAAI,EAAK,EACnB,OACf,SAAQ,MAAS;IAChC,IAAM,IAA2B;KAC/B,GAAG,EAAM;KAEP,QAAQ,EAAE;KACV,OAAO,GAAG,EAAM,OAAO,SAAS,GAAG,EAAM,OAAO;KAEnD;AACD,MAAO,KAAK,EAAI;KAChB;WACK,GAAO;AACd,WAAQ,IAAI,EAAM;;AAGpB,SAAO;;CAGT,mBAAmB,MAAyD;AAU1E,MANA,KAAK,YAAY,SAAQ,MAAc;AACrC,GAAK,EAAO,MAAK,MAAS,EAAM,UAAU,EAAW,MAAM,IACzD,EAAO,KAAK,EAAW;IAEzB,EAGA,KAAK,cAAc,EAAc,UACjC,KAAK,cAAc,EAAc,aAChC,CAAC,KAAK,MAAM,gBAAgB,KAAK,MAAM,YAAY,QACpD;GACA,IAAM,IAAc,EAClB,GAAG,KAAK,MAAM,aACf;AASD,UARI,EAAO,SAAS,IAClB,EAAY,QAAQ,EAAc,QAElC,EAAY,QAAQ,EAAc,WAGpC,KAAK,SAAS,EAAE,gBAAa,CAAC,EAEvB,EAAE;;AAwBX,SAhBkB,EAAO,QAAO,MAAS,EAAM,SAAS,WACxD,CAAU,SAAQ,MAAS;AACzB,OAAI,EAAM,UAAU;IAClB,IAAM,IAAa,EAAM,SAAS,UAChC,GACA,EAAM,SAAS,YAAY,IAAI,CAChC;AACD,MAAO,IAAS,OAEX,EAAM,YAAY,IAAI,QAAQ,EAAW,GAAG,OAC5C,EAAM,SAAS,UAAU,EAAM,SAAS,SAE3C;;IAEJ,EAEK,EAAO,KAAI,OAChB,AACE,EAAM,YAAU,EAAM,QAAQ,QAAQ,YAAY,QAAQ,EAErD,GACP;;CAGJ,2BAA2B,MAA0B;EACnD,IAAM,EAAE,cAAW;AAcnB,SACE,kBAAC,OAAD;GAAK,WAAU;aACb,kBAAC,MAAD;IAAI,WAAU;cAfC,EAChB,KAAK,GAAO,MACJ,EACL,KAAK,MAAM,OACX,GACA,KAAK,UACL,GACA,KAAK,MAAM,OACZ,CACD,CACD,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,MAAM,CACjC,KAAI,MAAM,EAAG,QAIkB;IAAgB,CAAA;GAC1C,CAAA;;CAIV,SAAS;AACP,SACE,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,GAAD;KACE,cAAc,EAAE,oBAAiB,sBAC/B,KAAK,MAAM,qBACX,EAAgB,aAAa,EAAa;gBAG3C,MACC,kBAAC,GAAD;MACE,MAAM,EAAQ,SAAS;MACvB,OAAM;MACN,SAAS,KAAK;MACd,iBAAiB;AACf,OAAI,EAAQ,WACV,EAAQ,SAAS;;MAGrB,gBAAgB;AACd,OAAI,EAAQ,SACV,EAAQ,OAAO;;MAGnB,CAAA;KAEI,CAAA;IACV,kBAAC,GAAD;KACE,aAAa,KAAK,MAAM;KACxB,UAAU,KAAK,MAAM,YAAY;KACjC,OAAO,KAAK,MAAM;KACV,CAAA;IACV,kBAAC,OAAD,EAAA,UACE,kBAAC,OAAD;KAAK,WAAU;eAAf;MACE,kBAAC,GAAD;OACE,UAAU,KAAK,MAAM;OACrB,cAAc,KAAK,MAAM;OACzB,cAAc,KAAK;OACL,CAAA;MACf,KAAK,MAAM,kBACV,kBAAC,OAAD;OAAK,WAAU;iBACb,kBAAC,QAAD,EAAM,WAAW,WAAa,CAAA;OAC1B,CAAA;MAER,kBAAC,OAAD;OAAK,WAAU;iBAAf;QACE,kBAAC,OAAD;SAAK,WAAU;mBAAc,KAAK,MAAM,YAAY;SAAY,CAAA;QAC/D,KAAK,mBAAmB,KAAK,MAAM,eAAe;QACnD,kBAAC,OAAD;SACE,WAAW,qBACT,KAAK,MAAM,cAAc,SAAS;mBAFtC;UAKG,CAAC,KAAK,MAAM,YAAY,UACvB,kBAAC,UAAD;WACE,MAAK;WACL,WAAU;WACV,eAAe;AACb,iBAAK,cAAc,EAAc,SAAS;;qBAE7C;WAEQ,CAAA;UAEV,KAAK,iBACJ,KAAK,MAAM,aACX,KAAK,MAAM,kBAET,KAAK,SAAS,EACZ,YAAY,CAAC,KAAK,MAAM,YACzB,CAAC,CACL;UACA,KAAK,gBAAgB,IACpB,kBAAC,UAAD;WACE,MAAK;WACL,WAAU;WACV,UAAU,KAAK,MAAM;WACrB,eAAe;AACb,iBAAK,cAAc,EAAc,OAAO;;qBAE3C;WAEQ,CAAA;UAEP;;QACL,KAAK,4BAA4B,KAAK,MAAM,aAAa;QAC1D,kBAAC,OAAD;SACE,WACE,KAAK,gBAAgB,IAAI,KAAK,MAAM,YAAY,SAC5C,mBACA;mBAJR,CAOG,KAAK,MAAM,gBACV,kBAAC,OAAD;UAAK,WAAU;oBAAoB;UAE7B,CAAA,EAER,kBAAC,OAAD;UACE,KAAK,KAAK;UACV,WAAW,eACT,KAAK,MAAM,YAAY,WAAW,aAAa,IAChD;oBAJH;WAME,kBAAC,GAAD;YACa;YACX,iBAAA;YACA,WACE,KAAK,MAAM,aACP,wBACA;YAEN,cAAc;YACd,UAAU,KAAK,MAAM;YACrB,QAAQ,KAAK,UAAU,KAAK,MAAM,YAAY;YAC9C,UAAU,KAAK;YACf,UAAU,KAAK;YACf,WAAU,MAAQ,KAAK,eAAe,EAAK;YAC3C,UAAS,MACP,KAAK,QAAQ;aACX,OAAO;aACP,MAAM,KAAK;aACZ,CAAC;YAEJ,eACE,KAAK,MAAM,gBAAgB,KAAK,MAAM,eAClC,QACA;YAEN,WAAW,EACT,mBAAmB,KAAK,yBACzB;YACD,iBAAiB,KAAK;YACtB,KAAK,KAAK;YACV,UACE,KAAK,MAAM,YAAY,YAAY,KAAK,MAAM;YAEhD,SAAS;aACP,gBAAgB;aAChB,kBAAkB;aAClB,aAAa;aACd;sBAED,kBAAC,OAAD;aAAK,OAAO,EAAE,SAAS,QAAQ;uBAC7B,kBAAC,UAAD;cAAQ,MAAK;cAAS,KAAK,KAAK;cAA0B,CAAA;aACtD,CAAA;YACD,CAAA;WACN,KAAK,2BAA2B;WAChC,CAAC,KAAK,MAAM,gBACX,kBAAC,GAAD;YACE,OAAO,KAAK,MAAM;YAClB,YAAY,KAAK,MAAM,YAAY;YACnC,cAAc,MAAe,KAAK,kBAAkB,EAAK;YAC3C,CAAA;WAEd;YACF;;QAEL,KAAK,gBAAgB,IACpB,kBAAC,GAAD;SACE,UAAU,KAAK,MAAM;SACrB,OAAO,KAAK,MAAM;SAClB,aAAa,MACX,KAAK,8BAA8B,GAAU,GAAK;SAEpD,UAAU,KAAK,MAAM;SACrB,QAAQ,KAAK,MAAM;SACL,CAAA;QAGlB,kBAAC,GAAD;SACE,aAAa,KAAK,MAAM;SACxB,OAAO,KAAK,MAAM;SAClB,iBAAiB,KAAK,MAAM;SAC5B,iBAAiB,KAAK,MAAM;SAC5B,cAAc,MAAqB;AACjC,eAAK,cAAc,EAAE;;SAEX,CAAA;QACV;;MACF;QACF,CAAA;IACL,KAAK,MAAM,gBACV,kBAAC,GAAD;KACE,MAAM;KACN,OAAO,KAAK;KACZ,SAAS,KAAK;KACd,WAAW,SAAS,KAAK,MAAM;KAC/B,uBAAuB,KAAK,MAAM,aAAa;KAC/C,gBAAgB,KAAK,SAAS,EAAE,cAAc,KAAA,GAAW,CAAC;KAC1D,YAAY,GAAgB,MAC1B,KAAK,kBAAkB,GAAQ,EAAU;KAE3C,CAAA;IAEJ,kBAAC,GAAD;KAAW,UAAU,KAAK,MAAM;KAAU,QAAQ;KAAkB,CAAA;IAChE;;;;AAOZ,SAAS,EACP,GACA,GACA,GACA,GACA,GACuC;CACvC,IAAM,IAAW,EAAU,EAAM,UAAU,IAAI,EACzC,IAAU,EAAS,MAAM,IAAI,EAG7B,IAAkB,GAAG,EAAQ,KAAK,eAAe,CAAC,SAElD,IAAc,GAAG,EAAS,YAG1B,IAAuB,EAAgB,QAAQ,WAAW,SAAS,EACnE,IAAmB,EAAY,QAAQ,WAAW,SAAS,EAG7D,IAAQ,EAFO,EAAgB,MAAM,UAEvB,CAAW;AAE7B,CAEE,OADA,IAAQ,EAAM,UAAU,GAAG,EAAM,SAAS,EAAE,EACnC,MAAM,SAAS,EAAM,CAAC,GAAiC,KAA9B,KAAK,SAAS,EAAM,GAAG,EAAE;CAG7D,IAAM,IACJ,EAAI,GAAU,EAAY,IAC1B,EAAI,EAAO,YAAY,EAAgB,IACvC,EAAI,GAAU,EAAiB,IAC/B,EAAI,EAAO,YAAY,EAAqB,IAC5C,EAAM,UAEF,IAAS,EAAK,GAAO,EAAE,IAAI,EAAQ,IAAI,CAAC,IAAI;EAChD,OAAO,EAAQ;EACf,OAAO;EACR,EACK,IACJ,kBAAC,MAAD;EAAY,WAAU;YACpB,kBAAC,QAAD,EAAA,UAAA;GACE,kBAAC,UAAD,EAAA,UAAA;IACG,EAAO;IACP;IAAM;IACA,EAAA,CAAA;GACR;GAAM;GAAQ,EAAM;GAChB,EAAA,CAAA;EACJ,EARI,EAQJ;AAEP,QAAO;EAAE,OAAO,EAAO;EAAO;EAAS;;AAIzC,SAAS,EAAuB,GAAgB,GAAqB;AAYnE,QAXA,EAAK,EAAU,CAAC,MAAK,MAAK;AACxB,MAAI,MAAM,GAAK;GACb,IAAM,IAAQ,EAAU;AAGxB,UAFA,EAAU,KAAK,kBAAC,QAAD,EAAM,yBAAyB,EAAE,QAAQ,GAAO,EAAS,CAAA,EAEjE;;AAET,EAAI,EAAU,MAAM,OAAO,EAAU,MAAO,YAC1C,EAAuB,EAAU,IAAI,EAAI;GAE3C,EACK"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SynapseFormWrapper.js","names":[],"sources":["../../../src/components/SynapseForm/SynapseFormWrapper.tsx"],"sourcesContent":["import SynapseClient from '@/synapse-client'\nimport { useSynapseContext } from '@/utils'\nimport { SRC_SIGN_IN_CLASS } from '@/utils/SynapseConstants'\nimport $RefParser from '@apidevtools/json-schema-ref-parser'\nimport { Button } from '@mui/material'\nimport { UiSchema } from '@rjsf/utils'\nimport { FormData } from '@sage-bionetworks/synapse-types'\nimport { get, includes } from 'lodash-es'\nimport { Component } from 'react'\nimport FullWidthAlert from '../FullWidthAlert'\nimport SynapseForm from './SynapseForm'\nimport { getFileEntityData } from './SynapseFormUtils'\nimport { StatusEnum } from './types'\n\n/**\n * TODO: SWC-5612 - Replace token prop with SynapseContext.accessToken\n *\n * This wasn't done because Enzyme's shallow renderer is not currently\n * compatible with the `contextType` field in the React 16+ context API.\n *\n * This can be fixed by rewriting tests to not rely on the shallow renderer.\n *\n * See here: https://github.com/enzymejs/enzyme/issues/1553\n */\n\nexport type SynapseFormWrapperProps = {\n // Provide the parent container (folder/project), that should contain a folder (named <user_id>) that this user can write to.\n formSchemaEntityId: string // Synapse file that contains the form schema.\n formUiSchemaEntityId: string // Synapse file that contains the form ui schema.\n formNavSchemaEntityId: string //Synapse file that consists screen nav schema\n token?: string // user's access token\n isWizardMode?: boolean // if we are displaying the form in wizard mode\n fileNamePath: string // path in data to specify the name of saved file\n formTitle: string //for UI customization\n formClass?: string // to support potential theming\n\n formDataId?: string //formDataId for user data form data\n dataFileHandleId?: string //fileHandle to get userData\n submitted?: boolean // if the file has been submitted\n formGroupId: string\n}\n\ntype SynapseFormWrapperState = {\n notification?: Notification\n isLoading?: boolean\n formDataId?: string // file holding user form data\n formData?: any // form data that prepopulates the form\n formSchema?: any // schema that drives the form\n formUiSchema?: UiSchema // ui schema that directs how to render the form elements\n formNavSchema?: any // drives the steps left panel\n\n status?: StatusEnum\n}\n\ntype Error = {\n name?: string\n message?: string\n}\n\ninterface Notification extends Error {\n type: StatusEnum\n}\n\nclass _SynapseFormWrapper extends Component<\n SynapseFormWrapperProps,\n SynapseFormWrapperState\n> {\n constructor(props: SynapseFormWrapperProps) {\n super(props)\n this.state = {\n isLoading: true,\n formDataId: this.props?.formDataId,\n }\n }\n\n componentDidMount() {\n this.getData(this.props.token)\n }\n\n componentDidUpdate(prevProps: SynapseFormWrapperProps) {\n const shouldUpdate = this.props.token !== prevProps.token\n if (shouldUpdate) {\n this.getData(this.props.token)\n }\n }\n\n //same as above but also uses $RefParser to convert json $refs to regular json\n getFileEntityDataDereferenced = async (\n token: string,\n entityId: string,\n versionNumber?: string,\n ): Promise<{ version?: number; content: JSON }> => {\n const { version, content } = await getFileEntityData(\n token,\n entityId,\n versionNumber,\n this.onError,\n )\n const derefContent = await $RefParser.dereference<JSON>(content)\n return {\n version: version,\n content: derefContent,\n }\n }\n\n getData = async (token?: string): Promise<void> => {\n if (!token) {\n return\n }\n try {\n let formData: Record<string, any> = {}\n const dataFileHandleId = this.props.dataFileHandleId\n const submitted = this.props.submitted\n let formSchemaVersion = undefined\n let uiSchemaVersion = undefined\n let navSchemaVersion = undefined\n\n //for not new form we need to get the data\n //and if it is submitted form we need to pull appropriate schema versions\n //for new form (no dataFileHandleId) we need to populate schema versions\n\n if (dataFileHandleId) {\n const fileData = await SynapseClient.getFileHandleContentFromID(\n dataFileHandleId,\n token,\n )\n formData = JSON.parse(fileData)\n if (submitted && formData && formData['metadata']) {\n ;({ formSchemaVersion, uiSchemaVersion, navSchemaVersion } =\n formData['metadata'])\n }\n }\n\n const promises = [\n this.getFileEntityDataDereferenced(\n token,\n this.props.formSchemaEntityId,\n formSchemaVersion,\n ),\n getFileEntityData(\n token,\n this.props.formUiSchemaEntityId,\n uiSchemaVersion,\n this.onError,\n ),\n getFileEntityData(\n token,\n this.props.formNavSchemaEntityId,\n navSchemaVersion,\n this.onError,\n ),\n ]\n const configData = await Promise.all(promises)\n\n if (!dataFileHandleId) {\n //if we are creating a new file - store the versions\n formData = {\n metadata: {\n formSchemaVersion: configData[0].version,\n uiSchemaVersion: configData[1].version,\n navSchemaVersion: configData[2].version,\n },\n }\n }\n this.setState({\n formData: formData,\n formSchema: configData[0].content,\n formUiSchema: configData[1].content as unknown as UiSchema,\n formNavSchema: configData[2].content,\n isLoading: false,\n })\n } catch (error) {\n this.onError({ message: error })\n } finally {\n this.setState({\n isLoading: false,\n })\n }\n }\n\n finishedProcessing = (status: StatusEnum, message?: string) => {\n this.setState({\n isLoading: false,\n notification: { type: status, message: message },\n status: status,\n })\n //this will show the update message for 7 seconds\n setTimeout(() => {\n this.setState({ status: undefined })\n }, 7000)\n }\n\n onError = (error: Error) => {\n this.setState({\n notification: {\n type: StatusEnum.ERROR,\n message: error.message,\n name: error.name,\n },\n status: StatusEnum.ERROR,\n isLoading: false,\n })\n }\n\n submitForm = async (formData: any) => {\n await this.saveToFile(formData)\n\n this.setState({\n isLoading: true,\n })\n\n await SynapseClient.submitFormData(this.state.formDataId!, this.props.token)\n this.finishedProcessing(StatusEnum.SUBMIT_SUCCESS, 'File Submitted')\n }\n\n createOrUpdateFormDataFile = async (\n fileName: string,\n fileContentsBlob: Blob,\n ): Promise<FormData> => {\n fileName = `${fileName}.json`\n const fileUploadComplete = await SynapseClient.uploadFile(\n this.props.token,\n fileName,\n fileContentsBlob,\n )\n const formGroupId = this.props.formGroupId\n if (!formGroupId) {\n console.error('formGroupId must be defined')\n throw new Error('formGroupId must be defined')\n }\n try {\n // do we need to create a new file entity, or update an existing file entity?\n const newFileHandleId = fileUploadComplete.fileHandleId\n\n let formData\n if (this.state.formDataId) {\n formData = await SynapseClient.updateFormData(\n this.state.formDataId,\n fileName,\n newFileHandleId,\n this.props.token!,\n )\n } else {\n formData = await SynapseClient.createFormData(\n formGroupId,\n fileName,\n newFileHandleId,\n this.props.token!,\n )\n }\n\n return formData\n } catch (error) {\n this.onError(error)\n throw error\n }\n }\n\n saveToFile = async (data: any) => {\n const fileName = get(data, this.props.fileNamePath)\n this.setState({\n status: StatusEnum.PROGRESS,\n notification: { type: StatusEnum.PROGRESS, message: 'Progress' },\n isLoading: true,\n })\n\n if (!fileName) {\n // try to find corresponding property. By convention it should be first level property\n // and follow pattern screen.prop\n let errorTitle = 'File Name'\n try {\n // get it to the schema format\n const searchString = `${this.props.fileNamePath.replace(\n '.',\n '.properties.',\n )}.title`\n errorTitle = get(\n this.state.formSchema.properties,\n searchString,\n errorTitle,\n )\n } finally {\n const error = new Error(\n `Please Provide the ${errorTitle} before saving`,\n )\n this.onError(error)\n }\n return\n }\n\n try {\n const fileContent: Blob = new Blob([JSON.stringify(data)], {\n type: 'text/json',\n })\n\n const formData = await this.createOrUpdateFormDataFile(\n fileName,\n fileContent,\n )\n this.setState({\n formDataId: formData.formDataId,\n })\n\n this.finishedProcessing(StatusEnum.SAVE_SUCCESS, 'File Saved')\n } catch (error) {\n this.onError(error)\n }\n }\n\n isReadyToDisplayForm = (state: SynapseFormWrapperState): boolean => {\n return (\n this.state.status !== StatusEnum.ERROR_CRITICAL &&\n state.formSchema &&\n state.formUiSchema &&\n state.formNavSchema &&\n state.formData\n )\n }\n\n renderLoader = (\n state: SynapseFormWrapperState,\n props: SynapseFormWrapperProps,\n ) => {\n if (\n includes([StatusEnum.ERROR, StatusEnum.ERROR_CRITICAL], state.status) &&\n props.token &&\n state.isLoading\n ) {\n return (\n <div className=\"text-center\">\n <span className={'spinner'} />\n </div>\n )\n } else {\n return <></>\n }\n }\n\n renderNotification = (notification?: Notification) => {\n if (!notification) {\n return <></>\n }\n if (notification.type === StatusEnum.ERROR) {\n return (\n <FullWidthAlert\n variant=\"danger\"\n title=\"Error\"\n isGlobal={false}\n description={\n <>\n {notification.name} {notification.message}\n </>\n }\n onClose={() => this.setState({ status: undefined })}\n />\n )\n }\n\n return <></>\n }\n\n renderUnauthenticatedView = (token: string | undefined) => {\n if (token) {\n return <></>\n } else {\n return (\n <div className=\"panel padding-full unauthenticated text-center\">\n Please\n <Button\n variant=\"text\"\n color=\"primary\"\n sx={{\n mx: 1,\n fontSize: '1.4rem',\n verticalAlign: 'baseline',\n textTransform: 'none',\n }}\n className={`${SRC_SIGN_IN_CLASS}`}\n >\n sign in\n </Button>\n to initiate or continue your submission\n </div>\n )\n }\n }\n\n render() {\n return (\n <div className={`theme-${this.props.formClass}`}>\n <div className=\"SRC-ReactJsonForm\">\n {this.renderNotification(this.state.notification)}\n {this.renderLoader(this.state, this.props)}\n {this.renderUnauthenticatedView(this.props.token)}\n\n {this.isReadyToDisplayForm(this.state) && (\n <div>\n <SynapseForm\n schema={this.state.formSchema}\n uiSchema={this.state.formUiSchema!}\n formData={this.state.formData}\n navSchema={this.state.formNavSchema}\n isWizardMode={this.props.isWizardMode}\n formTitle={this.props.formTitle}\n formClass={this.props.formClass}\n callbackStatus={this.state.status}\n onSave={(data: any) => {\n this.saveToFile(data)\n }}\n onSubmit={(data: any) => {\n this.submitForm(data)\n }}\n isSubmitted={this.props.submitted}\n />\n </div>\n )}\n </div>\n </div>\n )\n }\n}\n\nexport function SynapseFormWrapper(props: SynapseFormWrapperProps) {\n const synapseContext = useSynapseContext()\n\n return <_SynapseFormWrapper {...props} token={synapseContext.accessToken} />\n}\n\nexport default SynapseFormWrapper\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SynapseFormWrapper.js","names":[],"sources":["../../../src/components/SynapseForm/SynapseFormWrapper.tsx"],"sourcesContent":["import SynapseClient from '@/synapse-client'\nimport { useSynapseContext } from '@/utils'\nimport { SRC_SIGN_IN_CLASS } from '@/utils/SynapseConstants'\nimport $RefParser from '@apidevtools/json-schema-ref-parser'\nimport { Button } from '@mui/material'\nimport { UiSchema } from '@rjsf/utils'\nimport { FormData } from '@sage-bionetworks/synapse-types'\nimport { get, includes } from 'lodash-es'\nimport { Component } from 'react'\nimport FullWidthAlert from '../FullWidthAlert'\nimport SynapseForm from './SynapseForm'\nimport { getFileEntityData } from './SynapseFormUtils'\nimport { StatusEnum } from './types'\n\n/**\n * TODO: SWC-5612 - Replace token prop with SynapseContext.accessToken\n *\n * This wasn't done because Enzyme's shallow renderer is not currently\n * compatible with the `contextType` field in the React 16+ context API.\n *\n * This can be fixed by rewriting tests to not rely on the shallow renderer.\n *\n * See here: https://github.com/enzymejs/enzyme/issues/1553\n */\n\nexport type SynapseFormWrapperProps = {\n // Provide the parent container (folder/project), that should contain a folder (named <user_id>) that this user can write to.\n formSchemaEntityId: string // Synapse file that contains the form schema.\n formUiSchemaEntityId: string // Synapse file that contains the form ui schema.\n formNavSchemaEntityId: string //Synapse file that consists screen nav schema\n token?: string // user's access token\n isWizardMode?: boolean // if we are displaying the form in wizard mode\n fileNamePath: string // path in data to specify the name of saved file\n formTitle: string //for UI customization\n formClass?: string // to support potential theming\n\n formDataId?: string //formDataId for user data form data\n dataFileHandleId?: string //fileHandle to get userData\n submitted?: boolean // if the file has been submitted\n formGroupId: string\n}\n\ntype SynapseFormWrapperState = {\n notification?: Notification\n isLoading?: boolean\n formDataId?: string // file holding user form data\n formData?: any // form data that prepopulates the form\n formSchema?: any // schema that drives the form\n formUiSchema?: UiSchema // ui schema that directs how to render the form elements\n formNavSchema?: any // drives the steps left panel\n\n status?: StatusEnum\n}\n\ntype Error = {\n name?: string\n message?: string\n}\n\ninterface Notification extends Error {\n type: StatusEnum\n}\n\nclass _SynapseFormWrapper extends Component<\n SynapseFormWrapperProps,\n SynapseFormWrapperState\n> {\n constructor(props: SynapseFormWrapperProps) {\n super(props)\n this.state = {\n isLoading: true,\n formDataId: this.props?.formDataId,\n }\n }\n\n componentDidMount() {\n this.getData(this.props.token)\n }\n\n componentDidUpdate(prevProps: SynapseFormWrapperProps) {\n const shouldUpdate = this.props.token !== prevProps.token\n if (shouldUpdate) {\n this.getData(this.props.token)\n }\n }\n\n //same as above but also uses $RefParser to convert json $refs to regular json\n getFileEntityDataDereferenced = async (\n token: string,\n entityId: string,\n versionNumber?: string,\n ): Promise<{ version?: number; content: JSON }> => {\n const { version, content } = await getFileEntityData(\n token,\n entityId,\n versionNumber,\n this.onError,\n )\n const derefContent = await $RefParser.dereference<JSON>(content)\n return {\n version: version,\n content: derefContent,\n }\n }\n\n getData = async (token?: string): Promise<void> => {\n if (!token) {\n return\n }\n try {\n let formData: Record<string, any> = {}\n const dataFileHandleId = this.props.dataFileHandleId\n const submitted = this.props.submitted\n let formSchemaVersion = undefined\n let uiSchemaVersion = undefined\n let navSchemaVersion = undefined\n\n //for not new form we need to get the data\n //and if it is submitted form we need to pull appropriate schema versions\n //for new form (no dataFileHandleId) we need to populate schema versions\n\n if (dataFileHandleId) {\n const fileData = await SynapseClient.getFileHandleContentFromID(\n dataFileHandleId,\n token,\n )\n formData = JSON.parse(fileData)\n if (submitted && formData && formData['metadata']) {\n ;({ formSchemaVersion, uiSchemaVersion, navSchemaVersion } =\n formData['metadata'])\n }\n }\n\n const promises = [\n this.getFileEntityDataDereferenced(\n token,\n this.props.formSchemaEntityId,\n formSchemaVersion,\n ),\n getFileEntityData(\n token,\n this.props.formUiSchemaEntityId,\n uiSchemaVersion,\n this.onError,\n ),\n getFileEntityData(\n token,\n this.props.formNavSchemaEntityId,\n navSchemaVersion,\n this.onError,\n ),\n ]\n const configData = await Promise.all(promises)\n\n if (!dataFileHandleId) {\n //if we are creating a new file - store the versions\n formData = {\n metadata: {\n formSchemaVersion: configData[0].version,\n uiSchemaVersion: configData[1].version,\n navSchemaVersion: configData[2].version,\n },\n }\n }\n this.setState({\n formData: formData,\n formSchema: configData[0].content,\n formUiSchema: configData[1].content as unknown as UiSchema,\n formNavSchema: configData[2].content,\n isLoading: false,\n })\n } catch (error) {\n this.onError({ message: error })\n } finally {\n this.setState({\n isLoading: false,\n })\n }\n }\n\n finishedProcessing = (status: StatusEnum, message?: string) => {\n this.setState({\n isLoading: false,\n notification: { type: status, message: message },\n status: status,\n })\n //this will show the update message for 7 seconds\n setTimeout(() => {\n this.setState({ status: undefined })\n }, 7000)\n }\n\n onError = (error: Error) => {\n this.setState({\n notification: {\n type: StatusEnum.ERROR,\n message: error.message,\n name: error.name,\n },\n status: StatusEnum.ERROR,\n isLoading: false,\n })\n }\n\n submitForm = async (formData: any) => {\n await this.saveToFile(formData)\n\n this.setState({\n isLoading: true,\n })\n\n await SynapseClient.submitFormData(this.state.formDataId!, this.props.token)\n this.finishedProcessing(StatusEnum.SUBMIT_SUCCESS, 'File Submitted')\n }\n\n createOrUpdateFormDataFile = async (\n fileName: string,\n fileContentsBlob: Blob,\n ): Promise<FormData> => {\n fileName = `${fileName}.json`\n const fileUploadComplete = await SynapseClient.uploadFile(\n this.props.token,\n fileName,\n fileContentsBlob,\n )\n const formGroupId = this.props.formGroupId\n if (!formGroupId) {\n console.error('formGroupId must be defined')\n throw new Error('formGroupId must be defined')\n }\n try {\n // do we need to create a new file entity, or update an existing file entity?\n const newFileHandleId = fileUploadComplete.fileHandleId\n\n let formData\n if (this.state.formDataId) {\n formData = await SynapseClient.updateFormData(\n this.state.formDataId,\n fileName,\n newFileHandleId,\n this.props.token!,\n )\n } else {\n formData = await SynapseClient.createFormData(\n formGroupId,\n fileName,\n newFileHandleId,\n this.props.token!,\n )\n }\n\n return formData\n } catch (error) {\n this.onError(error)\n throw error\n }\n }\n\n saveToFile = async (data: any) => {\n const fileName = get(data, this.props.fileNamePath)\n this.setState({\n status: StatusEnum.PROGRESS,\n notification: { type: StatusEnum.PROGRESS, message: 'Progress' },\n isLoading: true,\n })\n\n if (!fileName) {\n // try to find corresponding property. By convention it should be first level property\n // and follow pattern screen.prop\n let errorTitle = 'File Name'\n try {\n // get it to the schema format\n const searchString = `${this.props.fileNamePath.replace(\n '.',\n '.properties.',\n )}.title`\n errorTitle = get(\n this.state.formSchema.properties,\n searchString,\n errorTitle,\n )\n } finally {\n const error = new Error(\n `Please Provide the ${errorTitle} before saving`,\n )\n this.onError(error)\n }\n return\n }\n\n try {\n const fileContent: Blob = new Blob([JSON.stringify(data)], {\n type: 'text/json',\n })\n\n const formData = await this.createOrUpdateFormDataFile(\n fileName,\n fileContent,\n )\n this.setState({\n formDataId: formData.formDataId,\n })\n\n this.finishedProcessing(StatusEnum.SAVE_SUCCESS, 'File Saved')\n } catch (error) {\n this.onError(error)\n }\n }\n\n isReadyToDisplayForm = (state: SynapseFormWrapperState): boolean => {\n return (\n this.state.status !== StatusEnum.ERROR_CRITICAL &&\n state.formSchema &&\n state.formUiSchema &&\n state.formNavSchema &&\n state.formData\n )\n }\n\n renderLoader = (\n state: SynapseFormWrapperState,\n props: SynapseFormWrapperProps,\n ) => {\n if (\n includes([StatusEnum.ERROR, StatusEnum.ERROR_CRITICAL], state.status) &&\n props.token &&\n state.isLoading\n ) {\n return (\n <div className=\"text-center\">\n <span className={'spinner'} />\n </div>\n )\n } else {\n return <></>\n }\n }\n\n renderNotification = (notification?: Notification) => {\n if (!notification) {\n return <></>\n }\n if (notification.type === StatusEnum.ERROR) {\n return (\n <FullWidthAlert\n variant=\"danger\"\n title=\"Error\"\n isGlobal={false}\n description={\n <>\n {notification.name} {notification.message}\n </>\n }\n onClose={() => this.setState({ status: undefined })}\n />\n )\n }\n\n return <></>\n }\n\n renderUnauthenticatedView = (token: string | undefined) => {\n if (token) {\n return <></>\n } else {\n return (\n <div className=\"panel padding-full unauthenticated text-center\">\n Please\n <Button\n variant=\"text\"\n color=\"primary\"\n sx={{\n mx: 1,\n fontSize: '1.4rem',\n verticalAlign: 'baseline',\n textTransform: 'none',\n }}\n className={`${SRC_SIGN_IN_CLASS}`}\n >\n sign in\n </Button>\n to initiate or continue your submission\n </div>\n )\n }\n }\n\n render() {\n return (\n <div className={`theme-${this.props.formClass}`}>\n <div className=\"SRC-ReactJsonForm\">\n {this.renderNotification(this.state.notification)}\n {this.renderLoader(this.state, this.props)}\n {this.renderUnauthenticatedView(this.props.token)}\n\n {this.isReadyToDisplayForm(this.state) && (\n <div>\n <SynapseForm\n schema={this.state.formSchema}\n uiSchema={this.state.formUiSchema!}\n formData={this.state.formData}\n navSchema={this.state.formNavSchema}\n isWizardMode={this.props.isWizardMode}\n formTitle={this.props.formTitle}\n formClass={this.props.formClass}\n callbackStatus={this.state.status}\n onSave={(data: any) => {\n this.saveToFile(data)\n }}\n onSubmit={(data: any) => {\n this.submitForm(data)\n }}\n isSubmitted={this.props.submitted}\n />\n </div>\n )}\n </div>\n </div>\n )\n }\n}\n\nexport function SynapseFormWrapper(props: SynapseFormWrapperProps) {\n const synapseContext = useSynapseContext()\n\n return <_SynapseFormWrapper {...props} token={synapseContext.accessToken} />\n}\n\nexport default SynapseFormWrapper\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SynapseByTheNumbersItem.js","names":[],"sources":["../../../src/components/SynapseHomepageV2/SynapseByTheNumbersItem.tsx"],"sourcesContent":["import { Box, Typography } from '@mui/material'\nimport { Row } from '@sage-bionetworks/synapse-types'\nimport Plotly, { Datum } from 'plotly.js-basic-dist'\nimport Plot from '../Plot/Plot'\n\nexport type SynapseByTheNumbersItemProps = {\n title: string\n description: string\n rows: Row[]\n plotXColIndex: number\n plotYColIndex: number\n}\n\nexport function SynapseByTheNumbersItem({\n title,\n description,\n rows,\n plotXColIndex,\n plotYColIndex,\n}: SynapseByTheNumbersItemProps) {\n if (rows.length == 0) {\n return <></>\n }\n const xArray: Datum[] = []\n const yArray: Datum[] = []\n for (const row of rows) {\n for (let j = 1; j < row.values.length; j += 1) {\n // create pairs of data\n const rowValues = row.values\n xArray.push(rowValues[plotXColIndex])\n yArray.push(rowValues[plotYColIndex])\n }\n }\n //convert table data into numbers\n const yArrayNumbers = yArray.map(v => parseFloat(v!.toString()))\n\n const plotData: Partial<Plotly.PlotData>[] = [\n {\n type: 'scatter',\n mode: 'lines',\n fill: 'tozeroy',\n fillcolor: '#336663',\n line: {\n color: '#6ba89d',\n shape: 'spline', //smooth line, will need to do a more complex cubic spline interpolation (introducing new values between the data points) if we want to really smooth this out\n smoothing: 1.3,\n },\n x: xArray,\n y: yArrayNumbers,\n hoverinfo: 'skip', //hide hover over tool tips\n },\n ]\n\n // calculate the y axis range to show off the trend\n const maxY = Math.max(...yArrayNumbers)\n const minY = Math.min(...yArrayNumbers)\n // we're showing a trend, so set the y-axis range minimum to 5% below the minimum point\n const rangeMinYValue = minY - minY * 0.05\n const layout: Partial<Plotly.Layout> = {\n showlegend: false,\n xaxis: {\n visible: false, // Hide x-axis\n showgrid: false, // Hide x-axis grid\n },\n yaxis: {\n visible: false, // Hide y-axis\n showgrid: false, // Hide y-axis grid\n range: [rangeMinYValue, maxY], // Set the range from half of minY to maxY\n },\n paper_bgcolor: 'rgba(0,0,0,0)', // Transparent background\n plot_bgcolor: 'rgba(0,0,0,0)', // Transparent plot area\n width: 170,\n height: 100,\n margin: {\n l: 0,\n r: 0,\n t: 0,\n b: 0,\n pad: 0,\n },\n }\n const config: Partial<Plotly.Config> = {\n displayModeBar: false, // Hide Plotly controls\n staticPlot: true, //disable all interactivity\n }\n return (\n <Box\n sx={{\n display: 'flex',\n alignItems: 'center',\n gap: '15px',\n }}\n >\n <Box>\n <Typography\n variant=\"body1\"\n sx={{\n fontWeight: 600,\n fontSize: '32px',\n lineHeight: '40px',\n color: 'white',\n }}\n >\n {title}\n </Typography>\n <Typography\n variant=\"body1\"\n sx={{\n fontWeight: 300,\n fontSize: '16px',\n lineHeight: '24px',\n color: 'grey.600',\n maxWidth: '150px',\n }}\n >\n {description}\n </Typography>\n </Box>\n <Box\n sx={{\n //add a linear gradient (fades out near the bottom)\n maskImage:\n 'linear-gradient(to bottom, rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, 0) 100%)',\n }}\n >\n <Plot layout={layout} data={plotData} config={config} />\n </Box>\n </Box>\n )\n}\n"],"mappings":";;;;AAaA,SAAgB,EAAwB,EACtC,UACA,gBACA,SACA,kBACA,oBAC+B;AAC/B,KAAI,EAAK,UAAU,EACjB,QAAO,kBAAA,GAAA,EAAK,CAAA;CAEd,IAAM,IAAkB,EAAE,EACpB,IAAkB,EAAE;AAC1B,MAAK,IAAM,KAAO,EAChB,MAAK,IAAI,IAAI,GAAG,IAAI,EAAI,OAAO,QAAQ,KAAK,GAAG;EAE7C,IAAM,IAAY,EAAI;AAEtB,EADA,EAAO,KAAK,EAAU,GAAe,EACrC,EAAO,KAAK,EAAU,GAAe;;CAIzC,IAAM,IAAgB,EAAO,KAAI,MAAK,WAAW,EAAG,UAAU,CAAC,CAAC,EAE1D,IAAuC,CAC3C;EACE,MAAM;EACN,MAAM;EACN,MAAM;EACN,WAAW;EACX,MAAM;GACJ,OAAO;GACP,OAAO;GACP,WAAW;GACZ;EACD,GAAG;EACH,GAAG;EACH,WAAW;EACZ,CACF,EAGK,IAAO,KAAK,IAAI,GAAG,EAAc,EACjC,IAAO,KAAK,IAAI,GAAG,EAAc,EAGjC,IAAiC;EACrC,YAAY;EACZ,OAAO;GACL,SAAS;GACT,UAAU;GACX;EACD,OAAO;GACL,SAAS;GACT,UAAU;GACV,OAAO,CAVY,IAAO,IAAO,KAUT,EAAK;GAC9B;EACD,eAAe;EACf,cAAc;EACd,OAAO;EACP,QAAQ;EACR,QAAQ;GACN,GAAG;GACH,GAAG;GACH,GAAG;GACH,GAAG;GACH,KAAK;GACN;EACF;AAKD,QACE,kBAAC,GAAD;EACE,IAAI;GACF,SAAS;GACT,YAAY;GACZ,KAAK;GACN;YALH,CAOE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;GACE,SAAQ;GACR,IAAI;IACF,YAAY;IACZ,UAAU;IACV,YAAY;IACZ,OAAO;IACR;aAEA;GACU,CAAA,EACb,kBAAC,GAAD;GACE,SAAQ;GACR,IAAI;IACF,YAAY;IACZ,UAAU;IACV,YAAY;IACZ,OAAO;IACP,UAAU;IACX;aAEA;GACU,CAAA,CACT,EAAA,CAAA,EACN,kBAAC,GAAD;GACE,IAAI,EAEF,WACE,0EACH;aAED,kBAAC,GAAD;IAAc;IAAQ,MAAM;IAAkB,
|
|
1
|
+
{"version":3,"file":"SynapseByTheNumbersItem.js","names":[],"sources":["../../../src/components/SynapseHomepageV2/SynapseByTheNumbersItem.tsx"],"sourcesContent":["import { Box, Typography } from '@mui/material'\nimport { Row } from '@sage-bionetworks/synapse-types'\nimport Plotly, { Datum } from 'plotly.js-basic-dist'\nimport Plot from '../Plot/Plot'\n\nexport type SynapseByTheNumbersItemProps = {\n title: string\n description: string\n rows: Row[]\n plotXColIndex: number\n plotYColIndex: number\n}\n\nexport function SynapseByTheNumbersItem({\n title,\n description,\n rows,\n plotXColIndex,\n plotYColIndex,\n}: SynapseByTheNumbersItemProps) {\n if (rows.length == 0) {\n return <></>\n }\n const xArray: Datum[] = []\n const yArray: Datum[] = []\n for (const row of rows) {\n for (let j = 1; j < row.values.length; j += 1) {\n // create pairs of data\n const rowValues = row.values\n xArray.push(rowValues[plotXColIndex])\n yArray.push(rowValues[plotYColIndex])\n }\n }\n //convert table data into numbers\n const yArrayNumbers = yArray.map(v => parseFloat(v!.toString()))\n\n const plotData: Partial<Plotly.PlotData>[] = [\n {\n type: 'scatter',\n mode: 'lines',\n fill: 'tozeroy',\n fillcolor: '#336663',\n line: {\n color: '#6ba89d',\n shape: 'spline', //smooth line, will need to do a more complex cubic spline interpolation (introducing new values between the data points) if we want to really smooth this out\n smoothing: 1.3,\n },\n x: xArray,\n y: yArrayNumbers,\n hoverinfo: 'skip', //hide hover over tool tips\n },\n ]\n\n // calculate the y axis range to show off the trend\n const maxY = Math.max(...yArrayNumbers)\n const minY = Math.min(...yArrayNumbers)\n // we're showing a trend, so set the y-axis range minimum to 5% below the minimum point\n const rangeMinYValue = minY - minY * 0.05\n const layout: Partial<Plotly.Layout> = {\n showlegend: false,\n xaxis: {\n visible: false, // Hide x-axis\n showgrid: false, // Hide x-axis grid\n },\n yaxis: {\n visible: false, // Hide y-axis\n showgrid: false, // Hide y-axis grid\n range: [rangeMinYValue, maxY], // Set the range from half of minY to maxY\n },\n paper_bgcolor: 'rgba(0,0,0,0)', // Transparent background\n plot_bgcolor: 'rgba(0,0,0,0)', // Transparent plot area\n width: 170,\n height: 100,\n margin: {\n l: 0,\n r: 0,\n t: 0,\n b: 0,\n pad: 0,\n },\n }\n const config: Partial<Plotly.Config> = {\n displayModeBar: false, // Hide Plotly controls\n staticPlot: true, //disable all interactivity\n }\n return (\n <Box\n sx={{\n display: 'flex',\n alignItems: 'center',\n gap: '15px',\n }}\n >\n <Box>\n <Typography\n variant=\"body1\"\n sx={{\n fontWeight: 600,\n fontSize: '32px',\n lineHeight: '40px',\n color: 'white',\n }}\n >\n {title}\n </Typography>\n <Typography\n variant=\"body1\"\n sx={{\n fontWeight: 300,\n fontSize: '16px',\n lineHeight: '24px',\n color: 'grey.600',\n maxWidth: '150px',\n }}\n >\n {description}\n </Typography>\n </Box>\n <Box\n sx={{\n //add a linear gradient (fades out near the bottom)\n maskImage:\n 'linear-gradient(to bottom, rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, 0) 100%)',\n }}\n >\n <Plot layout={layout} data={plotData} config={config} />\n </Box>\n </Box>\n )\n}\n"],"mappings":";;;;AAaA,SAAgB,EAAwB,EACtC,UACA,gBACA,SACA,kBACA,oBAC+B;AAC/B,KAAI,EAAK,UAAU,EACjB,QAAO,kBAAA,GAAA,EAAK,CAAA;CAEd,IAAM,IAAkB,EAAE,EACpB,IAAkB,EAAE;AAC1B,MAAK,IAAM,KAAO,EAChB,MAAK,IAAI,IAAI,GAAG,IAAI,EAAI,OAAO,QAAQ,KAAK,GAAG;EAE7C,IAAM,IAAY,EAAI;AAEtB,EADA,EAAO,KAAK,EAAU,GAAe,EACrC,EAAO,KAAK,EAAU,GAAe;;CAIzC,IAAM,IAAgB,EAAO,KAAI,MAAK,WAAW,EAAG,UAAU,CAAC,CAAC,EAE1D,IAAuC,CAC3C;EACE,MAAM;EACN,MAAM;EACN,MAAM;EACN,WAAW;EACX,MAAM;GACJ,OAAO;GACP,OAAO;GACP,WAAW;GACZ;EACD,GAAG;EACH,GAAG;EACH,WAAW;EACZ,CACF,EAGK,IAAO,KAAK,IAAI,GAAG,EAAc,EACjC,IAAO,KAAK,IAAI,GAAG,EAAc,EAGjC,IAAiC;EACrC,YAAY;EACZ,OAAO;GACL,SAAS;GACT,UAAU;GACX;EACD,OAAO;GACL,SAAS;GACT,UAAU;GACV,OAAO,CAVY,IAAO,IAAO,KAUT,EAAK;GAC9B;EACD,eAAe;EACf,cAAc;EACd,OAAO;EACP,QAAQ;EACR,QAAQ;GACN,GAAG;GACH,GAAG;GACH,GAAG;GACH,GAAG;GACH,KAAK;GACN;EACF;AAKD,QACE,kBAAC,GAAD;EACE,IAAI;GACF,SAAS;GACT,YAAY;GACZ,KAAK;GACN;YALH,CAOE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;GACE,SAAQ;GACR,IAAI;IACF,YAAY;IACZ,UAAU;IACV,YAAY;IACZ,OAAO;IACR;aAEA;GACU,CAAA,EACb,kBAAC,GAAD;GACE,SAAQ;GACR,IAAI;IACF,YAAY;IACZ,UAAU;IACV,YAAY;IACZ,OAAO;IACP,UAAU;IACX;aAEA;GACU,CAAA,CACT,EAAA,CAAA,EACN,kBAAC,GAAD;GACE,IAAI,EAEF,WACE,0EACH;aAED,kBAAC,GAAD;IAAc;IAAQ,MAAM;IAAkB,QAAA;KA3ClD,gBAAgB;KAChB,YAAY;KA0CsC;IAAU,CAAA;GACpD,CAAA,CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SynapseFeatureItem.js","names":[],"sources":["../../../src/components/SynapseHomepageV2/SynapseFeatureItem.tsx"],"sourcesContent":["import { useMediaQuery, useTheme } from '@mui/material'\nimport { Box, Button, Typography } from '@mui/material'\nimport { ReactElement } from 'react'\n\nexport type SynapseFeatureItemProps = {\n title: string\n subtitle: string\n description: string\n featureName: string\n link: string\n icons?: ReactElement[]\n image: ReactElement\n}\n\nexport function SynapseFeatureItem({\n title,\n subtitle,\n description,\n featureName,\n link,\n icons,\n image,\n}: SynapseFeatureItemProps) {\n const theme = useTheme()\n const isSmallView = useMediaQuery(theme.breakpoints.down('md'))\n return isSmallView ? (\n <Box\n sx={{\n display: 'flex',\n flexDirection: 'column',\n rowGap: '20px',\n p: '50px 15px',\n }}\n >\n <Typography\n variant=\"headline3\"\n sx={{\n color: 'primary.100',\n fontSize: '36px',\n lineHeight: '36px',\n fontWeight: 400,\n textAlign: 'center',\n }}\n >\n {title}\n </Typography>\n <Typography\n variant=\"headline3\"\n sx={{\n color: 'primary.100',\n fontSize: '24px',\n fontWeight: 700,\n lineHeight: '28px',\n textAlign: 'center',\n }}\n >\n {subtitle}\n </Typography>\n <Box\n sx={{\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n columnGap: '20px',\n }}\n >\n {icons && icons.map((icon, index) => <Box key={index}>{icon}</Box>)}\n </Box>\n <Box sx={{ svg: { width: '100%', height: 'auto' } }}>{image}</Box>\n <Typography\n variant=\"body1\"\n sx={{\n color: 'primary.100',\n fontSize: '16px',\n mb: '25px',\n }}\n >\n {description}\n </Typography>\n <Button\n variant=\"contained\"\n color=\"lightPrimary\"\n href={link}\n target=\"_blank\"\n fullWidth\n >\n About {featureName}\n </Button>\n </Box>\n ) : (\n <Box\n sx={{\n display: 'grid',\n gridTemplateColumns: '450px auto',\n columnGap: {\n xs: '40px',\n lg: '120px',\n },\n pb: '120px',\n }}\n >\n <Box sx={{ mb: '50px', width: '437px' }}>\n <Typography\n variant=\"headline3\"\n sx={{\n color: 'primary.100',\n fontSize: '36px',\n lineHeight: '24px',\n mb: '30px',\n fontWeight: 400,\n }}\n >\n {title}\n </Typography>\n <Typography\n variant=\"headline3\"\n sx={{\n color: 'primary.100',\n fontSize: '24px',\n lineHeight: '32px',\n mb: '20px',\n fontWeight: 700,\n }}\n >\n {subtitle}\n </Typography>\n <Typography\n variant=\"body1\"\n sx={{\n color: 'primary.100',\n mb: '30px',\n }}\n >\n {description}\n </Typography>\n <Box\n sx={{\n display: 'flex',\n gap: '10px',\n alignItems: 'center',\n mb: '25px',\n }}\n >\n {icons && icons.map((icon, index) => <Box key={index}>{icon}</Box>)}\n </Box>\n <Button\n variant=\"contained\"\n size=\"large\"\n color=\"lightPrimary\"\n href={link}\n target=\"_blank\"\n >\n About {featureName}\n </Button>\n </Box>\n <Box sx={{ mr: '25px', svg: { width: '100%' } }}>{image}</Box>\n </Box>\n )\n}\n"],"mappings":";;;AAcA,SAAgB,EAAmB,EACjC,UACA,aACA,gBACA,gBACA,SACA,UACA,YAC0B;AAG1B,QADoB,EADN,
|
|
1
|
+
{"version":3,"file":"SynapseFeatureItem.js","names":[],"sources":["../../../src/components/SynapseHomepageV2/SynapseFeatureItem.tsx"],"sourcesContent":["import { useMediaQuery, useTheme } from '@mui/material'\nimport { Box, Button, Typography } from '@mui/material'\nimport { ReactElement } from 'react'\n\nexport type SynapseFeatureItemProps = {\n title: string\n subtitle: string\n description: string\n featureName: string\n link: string\n icons?: ReactElement[]\n image: ReactElement\n}\n\nexport function SynapseFeatureItem({\n title,\n subtitle,\n description,\n featureName,\n link,\n icons,\n image,\n}: SynapseFeatureItemProps) {\n const theme = useTheme()\n const isSmallView = useMediaQuery(theme.breakpoints.down('md'))\n return isSmallView ? (\n <Box\n sx={{\n display: 'flex',\n flexDirection: 'column',\n rowGap: '20px',\n p: '50px 15px',\n }}\n >\n <Typography\n variant=\"headline3\"\n sx={{\n color: 'primary.100',\n fontSize: '36px',\n lineHeight: '36px',\n fontWeight: 400,\n textAlign: 'center',\n }}\n >\n {title}\n </Typography>\n <Typography\n variant=\"headline3\"\n sx={{\n color: 'primary.100',\n fontSize: '24px',\n fontWeight: 700,\n lineHeight: '28px',\n textAlign: 'center',\n }}\n >\n {subtitle}\n </Typography>\n <Box\n sx={{\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n columnGap: '20px',\n }}\n >\n {icons && icons.map((icon, index) => <Box key={index}>{icon}</Box>)}\n </Box>\n <Box sx={{ svg: { width: '100%', height: 'auto' } }}>{image}</Box>\n <Typography\n variant=\"body1\"\n sx={{\n color: 'primary.100',\n fontSize: '16px',\n mb: '25px',\n }}\n >\n {description}\n </Typography>\n <Button\n variant=\"contained\"\n color=\"lightPrimary\"\n href={link}\n target=\"_blank\"\n fullWidth\n >\n About {featureName}\n </Button>\n </Box>\n ) : (\n <Box\n sx={{\n display: 'grid',\n gridTemplateColumns: '450px auto',\n columnGap: {\n xs: '40px',\n lg: '120px',\n },\n pb: '120px',\n }}\n >\n <Box sx={{ mb: '50px', width: '437px' }}>\n <Typography\n variant=\"headline3\"\n sx={{\n color: 'primary.100',\n fontSize: '36px',\n lineHeight: '24px',\n mb: '30px',\n fontWeight: 400,\n }}\n >\n {title}\n </Typography>\n <Typography\n variant=\"headline3\"\n sx={{\n color: 'primary.100',\n fontSize: '24px',\n lineHeight: '32px',\n mb: '20px',\n fontWeight: 700,\n }}\n >\n {subtitle}\n </Typography>\n <Typography\n variant=\"body1\"\n sx={{\n color: 'primary.100',\n mb: '30px',\n }}\n >\n {description}\n </Typography>\n <Box\n sx={{\n display: 'flex',\n gap: '10px',\n alignItems: 'center',\n mb: '25px',\n }}\n >\n {icons && icons.map((icon, index) => <Box key={index}>{icon}</Box>)}\n </Box>\n <Button\n variant=\"contained\"\n size=\"large\"\n color=\"lightPrimary\"\n href={link}\n target=\"_blank\"\n >\n About {featureName}\n </Button>\n </Box>\n <Box sx={{ mr: '25px', svg: { width: '100%' } }}>{image}</Box>\n </Box>\n )\n}\n"],"mappings":";;;AAcA,SAAgB,EAAmB,EACjC,UACA,aACA,gBACA,gBACA,SACA,UACA,YAC0B;AAG1B,QADoB,EADN,GACoB,CAAM,YAAY,KAAK,KAAK,CACvD,GACL,kBAAC,GAAD;EACE,IAAI;GACF,SAAS;GACT,eAAe;GACf,QAAQ;GACR,GAAG;GACJ;YANH;GAQE,kBAAC,GAAD;IACE,SAAQ;IACR,IAAI;KACF,OAAO;KACP,UAAU;KACV,YAAY;KACZ,YAAY;KACZ,WAAW;KACZ;cAEA;IACU,CAAA;GACb,kBAAC,GAAD;IACE,SAAQ;IACR,IAAI;KACF,OAAO;KACP,UAAU;KACV,YAAY;KACZ,YAAY;KACZ,WAAW;KACZ;cAEA;IACU,CAAA;GACb,kBAAC,GAAD;IACE,IAAI;KACF,SAAS;KACT,gBAAgB;KAChB,YAAY;KACZ,WAAW;KACZ;cAEA,KAAS,EAAM,KAAK,GAAM,MAAU,kBAAC,GAAD,EAAA,UAAkB,GAAW,EAAnB,EAAmB,CAAC;IAC/D,CAAA;GACN,kBAAC,GAAD;IAAK,IAAI,EAAE,KAAK;KAAE,OAAO;KAAQ,QAAQ;KAAQ,EAAE;cAAG;IAAY,CAAA;GAClE,kBAAC,GAAD;IACE,SAAQ;IACR,IAAI;KACF,OAAO;KACP,UAAU;KACV,IAAI;KACL;cAEA;IACU,CAAA;GACb,kBAAC,GAAD;IACE,SAAQ;IACR,OAAM;IACN,MAAM;IACN,QAAO;IACP,WAAA;cALF,CAMC,UACQ,EACA;;GACL;MAEN,kBAAC,GAAD;EACE,IAAI;GACF,SAAS;GACT,qBAAqB;GACrB,WAAW;IACT,IAAI;IACJ,IAAI;IACL;GACD,IAAI;GACL;YATH,CAWE,kBAAC,GAAD;GAAK,IAAI;IAAE,IAAI;IAAQ,OAAO;IAAS;aAAvC;IACE,kBAAC,GAAD;KACE,SAAQ;KACR,IAAI;MACF,OAAO;MACP,UAAU;MACV,YAAY;MACZ,IAAI;MACJ,YAAY;MACb;eAEA;KACU,CAAA;IACb,kBAAC,GAAD;KACE,SAAQ;KACR,IAAI;MACF,OAAO;MACP,UAAU;MACV,YAAY;MACZ,IAAI;MACJ,YAAY;MACb;eAEA;KACU,CAAA;IACb,kBAAC,GAAD;KACE,SAAQ;KACR,IAAI;MACF,OAAO;MACP,IAAI;MACL;eAEA;KACU,CAAA;IACb,kBAAC,GAAD;KACE,IAAI;MACF,SAAS;MACT,KAAK;MACL,YAAY;MACZ,IAAI;MACL;eAEA,KAAS,EAAM,KAAK,GAAM,MAAU,kBAAC,GAAD,EAAA,UAAkB,GAAW,EAAnB,EAAmB,CAAC;KAC/D,CAAA;IACN,kBAAC,GAAD;KACE,SAAQ;KACR,MAAK;KACL,OAAM;KACN,MAAM;KACN,QAAO;eALT,CAMC,UACQ,EACA;;IACL;MACN,kBAAC,GAAD;GAAK,IAAI;IAAE,IAAI;IAAQ,KAAK,EAAE,OAAO,QAAQ;IAAE;aAAG;GAAY,CAAA,CAC1D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SynapseHomepageChatSearch.js","names":[],"sources":["../../../src/components/SynapseHomepageV2/SynapseHomepageChatSearch.tsx"],"sourcesContent":["import {\n Box,\n FormControl,\n InputAdornment,\n MenuItem,\n OutlinedInput,\n Select,\n useTheme,\n} from '@mui/material'\nimport { Color } from '@mui/material/styles'\nimport { FormEventHandler, KeyboardEventHandler, useState } from 'react'\nimport { getSearchToken } from '../SynapseNavDrawer/SynapseNavDrawer'\nimport { parseSynId } from '@/utils/functions/RegularExpressions'\n\nexport type SynapseHomepageChatSearchProps = {\n gotoPlace: (href: string) => void\n}\nenum SearchMode {\n SEARCH = 0,\n CHAT = 1,\n}\n\n/**\n * Synapse Homepage Search component with a dropdown \"autocomplete\" menu of options.\n * SWC-7005: Not used in the current implementation of the Home Page, but there are plans to utilize it later.\n * @returns\n */\nexport function SynapseHomepageChatSearch({\n gotoPlace,\n}: SynapseHomepageChatSearchProps) {\n const theme = useTheme()\n const [searchValue, setSearchValue] = useState('')\n const [chatValue, setChatValue] = useState('')\n const [mode, setMode] = useState(SearchMode.SEARCH)\n\n const executeSearch = () => {\n if (mode == SearchMode.SEARCH) {\n const searchValueCleaned = searchValue.toLowerCase().trim()\n\n // Check if the input is a valid Synapse ID with version\n const parsedSynId = parseSynId(searchValueCleaned)\n if (parsedSynId && parsedSynId.targetVersionNumber) {\n const synIdWithVersion = `${parsedSynId.targetId}.${parsedSynId.targetVersionNumber}`\n gotoPlace(`/Synapse:${synIdWithVersion}`)\n return\n }\n gotoPlace(\n `/SearchV2:default?query=${getSearchToken(\n searchValueCleaned.split(/[ ,]+/),\n )}`,\n )\n } else {\n gotoPlace(`/Chat:initialMessage=${encodeURIComponent(chatValue)}`)\n }\n }\n const handleSubmit: FormEventHandler<HTMLFormElement> = event => {\n event.preventDefault()\n executeSearch()\n }\n const handleKeyDown: KeyboardEventHandler<\n HTMLTextAreaElement | HTMLInputElement\n > = event => {\n if (event.key === 'Enter') {\n event.preventDefault()\n executeSearch()\n }\n }\n\n return (\n <Box component=\"form\" onSubmit={handleSubmit}>\n <FormControl fullWidth sx={{ m: 1 }}>\n <OutlinedInput\n value={mode == SearchMode.SEARCH ? searchValue : chatValue}\n startAdornment={\n <InputAdornment\n position=\"start\"\n sx={{ p: '0px', ml: '7px', mr: '13px' }}\n >\n <Select\n value={mode}\n sx={{\n fontSize: '24px',\n fontWeight: 400,\n minWidth: '125px',\n color: (theme.palette.secondary as unknown as Color)[600],\n '& div[role=\"combobox\"]': {\n p: '14px 12px',\n },\n }}\n onChange={v => {\n setMode(v.target.value as SearchMode)\n //restore search or chat value\n }}\n >\n <MenuItem value={SearchMode.SEARCH}>Search</MenuItem>\n <MenuItem value={SearchMode.CHAT}>Chat</MenuItem>\n </Select>\n </InputAdornment>\n }\n placeholder={\n mode == SearchMode.SEARCH ? 'Search Synapse' : 'Ask a question'\n }\n sx={{ fontSize: '24px', borderRadius: 96.6 }}\n onChange={event => {\n if (mode == SearchMode.SEARCH) {\n setSearchValue(event.target.value)\n } else {\n setChatValue(event.target.value)\n }\n }}\n onKeyDown={handleKeyDown}\n />\n </FormControl>\n </Box>\n )\n}\n"],"mappings":";;;;;;AAiBA,IAAK,IAAL,yBAAA,GAAA;QACE,EAAA,EAAA,
|
|
1
|
+
{"version":3,"file":"SynapseHomepageChatSearch.js","names":[],"sources":["../../../src/components/SynapseHomepageV2/SynapseHomepageChatSearch.tsx"],"sourcesContent":["import {\n Box,\n FormControl,\n InputAdornment,\n MenuItem,\n OutlinedInput,\n Select,\n useTheme,\n} from '@mui/material'\nimport { Color } from '@mui/material/styles'\nimport { FormEventHandler, KeyboardEventHandler, useState } from 'react'\nimport { getSearchToken } from '../SynapseNavDrawer/SynapseNavDrawer'\nimport { parseSynId } from '@/utils/functions/RegularExpressions'\n\nexport type SynapseHomepageChatSearchProps = {\n gotoPlace: (href: string) => void\n}\nenum SearchMode {\n SEARCH = 0,\n CHAT = 1,\n}\n\n/**\n * Synapse Homepage Search component with a dropdown \"autocomplete\" menu of options.\n * SWC-7005: Not used in the current implementation of the Home Page, but there are plans to utilize it later.\n * @returns\n */\nexport function SynapseHomepageChatSearch({\n gotoPlace,\n}: SynapseHomepageChatSearchProps) {\n const theme = useTheme()\n const [searchValue, setSearchValue] = useState('')\n const [chatValue, setChatValue] = useState('')\n const [mode, setMode] = useState(SearchMode.SEARCH)\n\n const executeSearch = () => {\n if (mode == SearchMode.SEARCH) {\n const searchValueCleaned = searchValue.toLowerCase().trim()\n\n // Check if the input is a valid Synapse ID with version\n const parsedSynId = parseSynId(searchValueCleaned)\n if (parsedSynId && parsedSynId.targetVersionNumber) {\n const synIdWithVersion = `${parsedSynId.targetId}.${parsedSynId.targetVersionNumber}`\n gotoPlace(`/Synapse:${synIdWithVersion}`)\n return\n }\n gotoPlace(\n `/SearchV2:default?query=${getSearchToken(\n searchValueCleaned.split(/[ ,]+/),\n )}`,\n )\n } else {\n gotoPlace(`/Chat:initialMessage=${encodeURIComponent(chatValue)}`)\n }\n }\n const handleSubmit: FormEventHandler<HTMLFormElement> = event => {\n event.preventDefault()\n executeSearch()\n }\n const handleKeyDown: KeyboardEventHandler<\n HTMLTextAreaElement | HTMLInputElement\n > = event => {\n if (event.key === 'Enter') {\n event.preventDefault()\n executeSearch()\n }\n }\n\n return (\n <Box component=\"form\" onSubmit={handleSubmit}>\n <FormControl fullWidth sx={{ m: 1 }}>\n <OutlinedInput\n value={mode == SearchMode.SEARCH ? searchValue : chatValue}\n startAdornment={\n <InputAdornment\n position=\"start\"\n sx={{ p: '0px', ml: '7px', mr: '13px' }}\n >\n <Select\n value={mode}\n sx={{\n fontSize: '24px',\n fontWeight: 400,\n minWidth: '125px',\n color: (theme.palette.secondary as unknown as Color)[600],\n '& div[role=\"combobox\"]': {\n p: '14px 12px',\n },\n }}\n onChange={v => {\n setMode(v.target.value as SearchMode)\n //restore search or chat value\n }}\n >\n <MenuItem value={SearchMode.SEARCH}>Search</MenuItem>\n <MenuItem value={SearchMode.CHAT}>Chat</MenuItem>\n </Select>\n </InputAdornment>\n }\n placeholder={\n mode == SearchMode.SEARCH ? 'Search Synapse' : 'Ask a question'\n }\n sx={{ fontSize: '24px', borderRadius: 96.6 }}\n onChange={event => {\n if (mode == SearchMode.SEARCH) {\n setSearchValue(event.target.value)\n } else {\n setChatValue(event.target.value)\n }\n }}\n onKeyDown={handleKeyDown}\n />\n </FormControl>\n </Box>\n )\n}\n"],"mappings":";;;;;;AAiBA,IAAK,IAAL,yBAAA,GAAA;QACE,EAAA,EAAA,SAAS,KAAA,UACT,EAAA,EAAA,OAAO,KAAA;EAFJ,KAAA,EAAA,CAGJ;AAOD,SAAgB,EAA0B,EACxC,gBACiC;CACjC,IAAM,IAAQ,GAAU,EAClB,CAAC,GAAa,KAAkB,EAAS,GAAG,EAC5C,CAAC,GAAW,KAAgB,EAAS,GAAG,EACxC,CAAC,GAAM,KAAW,EAAS,EAAW,OAAO,EAE7C,UAAsB;AAC1B,MAAI,KAAQ,EAAW,QAAQ;GAC7B,IAAM,IAAqB,EAAY,aAAa,CAAC,MAAM,EAGrD,IAAc,EAAW,EAAmB;AAClD,OAAI,KAAe,EAAY,qBAAqB;AAElD,MAAU,YAAY,GADM,EAAY,SAAS,GAAG,EAAY,wBACvB;AACzC;;AAEF,KACE,2BAA2B,EACzB,EAAmB,MAAM,QAAQ,CAClC,GACF;QAED,GAAU,wBAAwB,mBAAmB,EAAU,GAAG;;AAgBtE,QACE,kBAAC,GAAD;EAAK,WAAU;EAAO,WAdgC,MAAS;AAE/D,GADA,EAAM,gBAAgB,EACtB,GAAe;;YAab,kBAAC,GAAD;GAAa,WAAA;GAAU,IAAI,EAAE,GAAG,GAAG;aACjC,kBAAC,GAAD;IACE,OAAO,KAAQ,EAAW,SAAS,IAAc;IACjD,gBACE,kBAAC,GAAD;KACE,UAAS;KACT,IAAI;MAAE,GAAG;MAAO,IAAI;MAAO,IAAI;MAAQ;eAEvC,kBAAC,GAAD;MACE,OAAO;MACP,IAAI;OACF,UAAU;OACV,YAAY;OACZ,UAAU;OACV,OAAQ,EAAM,QAAQ,UAA+B;OACrD,4BAA0B,EACxB,GAAG,aACJ;OACF;MACD,WAAU,MAAK;AACb,SAAQ,EAAE,OAAO,MAAoB;;gBAZzC,CAgBE,kBAAC,GAAD;OAAU,OAAO,EAAW;iBAAQ;OAAiB,CAAA,EACrD,kBAAC,GAAD;OAAU,OAAO,EAAW;iBAAM;OAAe,CAAA,CAC1C;;KACM,CAAA;IAEnB,aACE,KAAQ,EAAW,SAAS,mBAAmB;IAEjD,IAAI;KAAE,UAAU;KAAQ,cAAc;KAAM;IAC5C,WAAU,MAAS;AACjB,KAAI,KAAQ,EAAW,SACrB,EAAe,EAAM,OAAO,MAAM,GAElC,EAAa,EAAM,OAAO,MAAM;;IAGpC,YAjDJ,MAAS;AACX,KAAI,EAAM,QAAQ,YAChB,EAAM,gBAAgB,EACtB,GAAe;;IA+CX,CAAA;GACU,CAAA;EACV,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SynapseHomepageSearch.js","names":[],"sources":["../../../src/components/SynapseHomepageV2/SynapseHomepageSearch.tsx"],"sourcesContent":["import React from 'react'\nimport { Search } from '@/assets/themed_icons'\nimport { useGetQueryResultBundleWithAsyncStatus } from '@/synapse-queries'\nimport { SynapseConstants } from '@/utils'\nimport {\n Autocomplete,\n Box,\n Color,\n FormControl,\n InputAdornment,\n Popper,\n PopperProps,\n styled,\n TextField,\n useTheme,\n} from '@mui/material'\nimport { QueryBundleRequest } from '@sage-bionetworks/synapse-types'\nimport { useState } from 'react'\n\nexport type SynapseHomepageSearchProps = {\n sourceTable: string\n gotoPlace: (href: string) => void\n}\n\nconst boxShadow =\n '0px 4px 4px 0px rgba(0, 0, 0, 0.05), 0px 1px 1px 0px rgba(0, 0, 0, 0.05)'\nconst StyledPopper = styled(Popper)(() => ({\n '& .MuiAutocomplete-paper': {\n borderRadius: '0px 0px 40px 40px',\n p: '0px 20px 20px 20px',\n boxShadow,\n },\n}))\n\nconst PopperAlwaysPlacedBelow = (props: PopperProps): React.ReactNode => {\n // Modifier necessary to force placement to remain on the bottom of the anchor element, despite not having enough space to render\n return (\n <StyledPopper\n {...props}\n placement=\"bottom\"\n modifiers={[{ name: 'flip', enabled: false }]}\n />\n )\n}\n\n/**\n * Synapse Homepage Search component with a dropdown \"autocomplete\" menu of options.\n * SWC-7005: Not used in the current implementation of the Home Page, but there are plans to utilize it later.\n * @returns\n */\nexport function SynapseHomepageSearch({\n sourceTable,\n gotoPlace,\n}: SynapseHomepageSearchProps) {\n const [isPopperOpen, setIsPopperOpen] = useState(false)\n const theme = useTheme()\n const partMask = SynapseConstants.BUNDLE_MASK_QUERY_RESULTS\n const request: QueryBundleRequest = {\n partMask,\n concreteType: 'org.sagebionetworks.repo.model.table.QueryBundleRequest',\n entityId: sourceTable,\n query: {\n sql: `SELECT * FROM ${sourceTable}`,\n limit: 10,\n },\n }\n const { data: queryResultResponse, isLoading } =\n useGetQueryResultBundleWithAsyncStatus(request)\n\n const rowSet = queryResultResponse?.responseBody?.queryResult?.queryResults\n const headers = rowSet?.headers\n const topSearchedColIndex = headers?.findIndex(\n selectColumn => selectColumn.name == 'top_searched',\n )!\n return (\n <FormControl fullWidth sx={{ m: 1 }}>\n <Autocomplete\n freeSolo\n disableClearable\n // disable filtering\n filterOptions={options => options}\n options={\n rowSet && !isLoading\n ? rowSet.rows.map(row => row.values[topSearchedColIndex] ?? '')\n : ['...']\n }\n onChange={(_event, newValue: string | null) => {\n if (newValue) {\n gotoPlace(`/SearchV2:default?query=${encodeURIComponent(newValue)}`)\n }\n }}\n slots={{\n popper: PopperAlwaysPlacedBelow,\n }}\n onOpen={() => setIsPopperOpen(true)}\n onClose={() => setIsPopperOpen(false)}\n groupBy={() => 'Most popular searches'}\n renderInput={params => (\n <TextField\n {...params}\n variant=\"outlined\"\n placeholder=\"Search Synapse\"\n slotProps={{\n input: {\n sx: {\n fontSize: '24px',\n borderRadius: isPopperOpen ? '40px 40px 0px 0px' : '40px',\n backgroundColor: 'white',\n boxShadow,\n },\n startAdornment: (\n <InputAdornment position=\"start\">\n <Box\n sx={{\n ml: '15px',\n display: 'flex',\n alignItems: 'center',\n }}\n >\n <Search\n size={32}\n fill={\n (theme.palette.secondary as unknown as Color)[600]\n }\n />\n </Box>\n </InputAdornment>\n ),\n },\n }}\n />\n )}\n />\n </FormControl>\n )\n}\n"],"mappings":";;;;;;;;;;AAwBA,IAAM,IACJ,4EACI,IAAe,EAAO,EAAO,QAAQ,EACzC,4BAA4B;CAC1B,cAAc;CACd,GAAG;CACH;CACD,EACF,EAAE,EAEG,KAA2B,MAG7B,kBAAC,GAAD;CACE,GAAI;CACJ,WAAU;CACV,WAAW,CAAC;EAAE,MAAM;EAAQ,SAAS;EAAO,CAAC;CAC7C,CAAA;AASN,SAAgB,EAAsB,EACpC,gBACA,gBAC6B;CAC7B,IAAM,CAAC,GAAc,KAAmB,EAAS,GAAM,EACjD,IAAQ,GAAU,EAWlB,EAAE,MAAM,GAAqB,iBACjC,
|
|
1
|
+
{"version":3,"file":"SynapseHomepageSearch.js","names":[],"sources":["../../../src/components/SynapseHomepageV2/SynapseHomepageSearch.tsx"],"sourcesContent":["import React from 'react'\nimport { Search } from '@/assets/themed_icons'\nimport { useGetQueryResultBundleWithAsyncStatus } from '@/synapse-queries'\nimport { SynapseConstants } from '@/utils'\nimport {\n Autocomplete,\n Box,\n Color,\n FormControl,\n InputAdornment,\n Popper,\n PopperProps,\n styled,\n TextField,\n useTheme,\n} from '@mui/material'\nimport { QueryBundleRequest } from '@sage-bionetworks/synapse-types'\nimport { useState } from 'react'\n\nexport type SynapseHomepageSearchProps = {\n sourceTable: string\n gotoPlace: (href: string) => void\n}\n\nconst boxShadow =\n '0px 4px 4px 0px rgba(0, 0, 0, 0.05), 0px 1px 1px 0px rgba(0, 0, 0, 0.05)'\nconst StyledPopper = styled(Popper)(() => ({\n '& .MuiAutocomplete-paper': {\n borderRadius: '0px 0px 40px 40px',\n p: '0px 20px 20px 20px',\n boxShadow,\n },\n}))\n\nconst PopperAlwaysPlacedBelow = (props: PopperProps): React.ReactNode => {\n // Modifier necessary to force placement to remain on the bottom of the anchor element, despite not having enough space to render\n return (\n <StyledPopper\n {...props}\n placement=\"bottom\"\n modifiers={[{ name: 'flip', enabled: false }]}\n />\n )\n}\n\n/**\n * Synapse Homepage Search component with a dropdown \"autocomplete\" menu of options.\n * SWC-7005: Not used in the current implementation of the Home Page, but there are plans to utilize it later.\n * @returns\n */\nexport function SynapseHomepageSearch({\n sourceTable,\n gotoPlace,\n}: SynapseHomepageSearchProps) {\n const [isPopperOpen, setIsPopperOpen] = useState(false)\n const theme = useTheme()\n const partMask = SynapseConstants.BUNDLE_MASK_QUERY_RESULTS\n const request: QueryBundleRequest = {\n partMask,\n concreteType: 'org.sagebionetworks.repo.model.table.QueryBundleRequest',\n entityId: sourceTable,\n query: {\n sql: `SELECT * FROM ${sourceTable}`,\n limit: 10,\n },\n }\n const { data: queryResultResponse, isLoading } =\n useGetQueryResultBundleWithAsyncStatus(request)\n\n const rowSet = queryResultResponse?.responseBody?.queryResult?.queryResults\n const headers = rowSet?.headers\n const topSearchedColIndex = headers?.findIndex(\n selectColumn => selectColumn.name == 'top_searched',\n )!\n return (\n <FormControl fullWidth sx={{ m: 1 }}>\n <Autocomplete\n freeSolo\n disableClearable\n // disable filtering\n filterOptions={options => options}\n options={\n rowSet && !isLoading\n ? rowSet.rows.map(row => row.values[topSearchedColIndex] ?? '')\n : ['...']\n }\n onChange={(_event, newValue: string | null) => {\n if (newValue) {\n gotoPlace(`/SearchV2:default?query=${encodeURIComponent(newValue)}`)\n }\n }}\n slots={{\n popper: PopperAlwaysPlacedBelow,\n }}\n onOpen={() => setIsPopperOpen(true)}\n onClose={() => setIsPopperOpen(false)}\n groupBy={() => 'Most popular searches'}\n renderInput={params => (\n <TextField\n {...params}\n variant=\"outlined\"\n placeholder=\"Search Synapse\"\n slotProps={{\n input: {\n sx: {\n fontSize: '24px',\n borderRadius: isPopperOpen ? '40px 40px 0px 0px' : '40px',\n backgroundColor: 'white',\n boxShadow,\n },\n startAdornment: (\n <InputAdornment position=\"start\">\n <Box\n sx={{\n ml: '15px',\n display: 'flex',\n alignItems: 'center',\n }}\n >\n <Search\n size={32}\n fill={\n (theme.palette.secondary as unknown as Color)[600]\n }\n />\n </Box>\n </InputAdornment>\n ),\n },\n }}\n />\n )}\n />\n </FormControl>\n )\n}\n"],"mappings":";;;;;;;;;;AAwBA,IAAM,IACJ,4EACI,IAAe,EAAO,EAAO,QAAQ,EACzC,4BAA4B;CAC1B,cAAc;CACd,GAAG;CACH;CACD,EACF,EAAE,EAEG,KAA2B,MAG7B,kBAAC,GAAD;CACE,GAAI;CACJ,WAAU;CACV,WAAW,CAAC;EAAE,MAAM;EAAQ,SAAS;EAAO,CAAC;CAC7C,CAAA;AASN,SAAgB,EAAsB,EACpC,gBACA,gBAC6B;CAC7B,IAAM,CAAC,GAAc,KAAmB,EAAS,GAAM,EACjD,IAAQ,GAAU,EAWlB,EAAE,MAAM,GAAqB,iBACjC,EAAuC;EATvC,UAAA;EACA,cAAc;EACd,UAAU;EACV,OAAO;GACL,KAAK,iBAAiB;GACtB,OAAO;GACR;EAGsC,CAAQ,EAE3C,IAAS,GAAqB,cAAc,aAAa,cAEzD,KADU,GAAQ,UACa,WACnC,MAAgB,EAAa,QAAQ,eACtC;AACD,QACE,kBAAC,GAAD;EAAa,WAAA;EAAU,IAAI,EAAE,GAAG,GAAG;YACjC,kBAAC,GAAD;GACE,UAAA;GACA,kBAAA;GAEA,gBAAe,MAAW;GAC1B,SACE,KAAU,CAAC,IACP,EAAO,KAAK,KAAI,MAAO,EAAI,OAAO,MAAwB,GAAG,GAC7D,CAAC,MAAM;GAEb,WAAW,GAAQ,MAA4B;AAC7C,IAAI,KACF,EAAU,2BAA2B,mBAAmB,EAAS,GAAG;;GAGxE,OAAO,EACL,QAAQ,GACT;GACD,cAAc,EAAgB,GAAK;GACnC,eAAe,EAAgB,GAAM;GACrC,eAAe;GACf,cAAa,MACX,kBAAC,GAAD;IACE,GAAI;IACJ,SAAQ;IACR,aAAY;IACZ,WAAW,EACT,OAAO;KACL,IAAI;MACF,UAAU;MACV,cAAc,IAAe,sBAAsB;MACnD,iBAAiB;MACjB;MACD;KACD,gBACE,kBAAC,GAAD;MAAgB,UAAS;gBACvB,kBAAC,GAAD;OACE,IAAI;QACF,IAAI;QACJ,SAAS;QACT,YAAY;QACb;iBAED,kBAAC,GAAD;QACE,MAAM;QACN,MACG,EAAM,QAAQ,UAA+B;QAEhD,CAAA;OACE,CAAA;MACS,CAAA;KAEpB,EACF;IACD,CAAA;GAEJ,CAAA;EACU,CAAA"}
|