synapse-react-client 4.0.45 → 4.0.46

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (319) hide show
  1. package/dist/SWC.index.js +1 -1
  2. package/dist/aridhia-queries/AridhiaKeyFactory.d.ts +1 -0
  3. package/dist/aridhia-queries/AridhiaKeyFactory.d.ts.map +1 -1
  4. package/dist/aridhia-queries/AridhiaKeyFactory.js +3 -0
  5. package/dist/aridhia-queries/AridhiaKeyFactory.js.map +1 -1
  6. package/dist/aridhia-queries/aridhiaTokenExchange.js +6 -6
  7. package/dist/aridhia-queries/index.d.ts +1 -0
  8. package/dist/aridhia-queries/index.d.ts.map +1 -1
  9. package/dist/aridhia-queries/index.js +11 -10
  10. package/dist/aridhia-queries/useGetAridhiaVocabularyTerm.d.ts +19 -0
  11. package/dist/aridhia-queries/useGetAridhiaVocabularyTerm.d.ts.map +1 -0
  12. package/dist/aridhia-queries/useGetAridhiaVocabularyTerm.js +14 -0
  13. package/dist/aridhia-queries/useGetAridhiaVocabularyTerm.js.map +1 -0
  14. package/dist/components/AccessRequirementList/AccessApprovalCheckMark.d.ts.map +1 -1
  15. package/dist/components/AccessRequirementList/AccessApprovalCheckMark.js +6 -4
  16. package/dist/components/AccessRequirementList/AccessApprovalCheckMark.js.map +1 -1
  17. package/dist/components/AccessRequirementList/AccessRequirementList.js.map +1 -1
  18. package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/AccessorRequirementHelpText.js +1 -1
  19. package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/AccessorRequirementHelpText.js.map +1 -1
  20. package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/ResearchProjectForm/ResearchProjectForm.js +1 -1
  21. package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/ResearchProjectForm/ResearchProjectForm.js.map +1 -1
  22. package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/ReviewCollaboratorsAndSigningOfficialAccordion.js +1 -1
  23. package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/ReviewCollaboratorsAndSigningOfficialAccordion.js.map +1 -1
  24. package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/SignatureStatusStep/SignatureStatusStep.d.ts.map +1 -1
  25. package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/SignatureStatusStep/SignatureStatusStep.js +11 -8
  26. package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/SignatureStatusStep/SignatureStatusStep.js.map +1 -1
  27. package/dist/components/AccessTokenPage/AccessTokenPage.js +1 -1
  28. package/dist/components/AccessTokenPage/AccessTokenPage.js.map +1 -1
  29. package/dist/components/AcknowledgementsPage/AcknowledgementsPage.js +1 -1
  30. package/dist/components/AcknowledgementsPage/AcknowledgementsPage.js.map +1 -1
  31. package/dist/components/Aridhia/DarWizard/DarSectionForm.d.ts.map +1 -1
  32. package/dist/components/Aridhia/DarWizard/DarSectionForm.js +17 -13
  33. package/dist/components/Aridhia/DarWizard/DarSectionForm.js.map +1 -1
  34. package/dist/components/Aridhia/DarWizard/DarSubmittedPanel.d.ts +3 -3
  35. package/dist/components/Aridhia/DarWizard/DarSubmittedPanel.d.ts.map +1 -1
  36. package/dist/components/Aridhia/DarWizard/DarSubmittedPanel.js +33 -34
  37. package/dist/components/Aridhia/DarWizard/DarSubmittedPanel.js.map +1 -1
  38. package/dist/components/Aridhia/fairFormToRjsf.js +1 -1
  39. package/dist/components/Aridhia/fairFormToRjsf.js.map +1 -1
  40. package/dist/components/Authentication/LastLoginInfo.js +1 -1
  41. package/dist/components/Authentication/LastLoginInfo.js.map +1 -1
  42. package/dist/components/CertificationQuiz/CertificationQuiz.js +1 -1
  43. package/dist/components/CertificationQuiz/CertificationQuiz.js.map +1 -1
  44. package/dist/components/ChallengeSubmission/AvailableEvaluationQueueList.js +1 -1
  45. package/dist/components/ChallengeSubmission/AvailableEvaluationQueueList.js.map +1 -1
  46. package/dist/components/ChallengeSubmission/EvaluationQueueCurrentRoundInfo.js +1 -1
  47. package/dist/components/ChallengeSubmission/EvaluationQueueCurrentRoundInfo.js.map +1 -1
  48. package/dist/components/ChallengeSubmission/SubmissionDirectoryList.js +6 -6
  49. package/dist/components/ChallengeSubmission/SubmissionDirectoryList.js.map +1 -1
  50. package/dist/components/ChallengeTeamWizard/ChallengeTeamTable.d.ts.map +1 -1
  51. package/dist/components/ChallengeTeamWizard/ChallengeTeamTable.js +4 -4
  52. package/dist/components/ChallengeTeamWizard/ChallengeTeamTable.js.map +1 -1
  53. package/dist/components/ChallengeTeamWizard/SelectChallengeTeam.js +4 -4
  54. package/dist/components/CitationPopover/CitationPopoverContent.js +4 -4
  55. package/dist/components/CitationPopover/CitationPopoverContent.js.map +1 -1
  56. package/dist/components/ComponentCollapse.d.ts.map +1 -1
  57. package/dist/components/ComponentCollapse.js +2 -1
  58. package/dist/components/ComponentCollapse.js.map +1 -1
  59. package/dist/components/DataGrid/SynapseGrid.d.ts.map +1 -1
  60. package/dist/components/DataGrid/SynapseGrid.js +231 -219
  61. package/dist/components/DataGrid/SynapseGrid.js.map +1 -1
  62. package/dist/components/DataGrid/SyncGridWithSourceButton.d.ts.map +1 -1
  63. package/dist/components/DataGrid/SyncGridWithSourceButton.js +5 -4
  64. package/dist/components/DataGrid/SyncGridWithSourceButton.js.map +1 -1
  65. package/dist/components/DataGrid/components/ColumnHeaderWithTooltip.d.ts.map +1 -1
  66. package/dist/components/DataGrid/components/ColumnHeaderWithTooltip.js +7 -5
  67. package/dist/components/DataGrid/components/ColumnHeaderWithTooltip.js.map +1 -1
  68. package/dist/components/DataGrid/components/ExportCsvFromGridButton.js +4 -4
  69. package/dist/components/DataGrid/components/ExportCsvFromGridButton.js.map +1 -1
  70. package/dist/components/DataGrid/components/ReorderColumnsButton.js +4 -4
  71. package/dist/components/DataGrid/components/ReorderColumnsButton.js.map +1 -1
  72. package/dist/components/DataGrid/components/ReorderColumnsDialog.d.ts.map +1 -1
  73. package/dist/components/DataGrid/components/ReorderColumnsDialog.js +12 -8
  74. package/dist/components/DataGrid/components/ReorderColumnsDialog.js.map +1 -1
  75. package/dist/components/DataGrid/components/UploadCsvToGridButton.js +1 -1
  76. package/dist/components/DataGrid/components/UploadCsvToGridButton.js.map +1 -1
  77. package/dist/components/DataGrid/hooks/useGridUndoRedo.js +5 -5
  78. package/dist/components/DataGrid/utils/applyModelChange.d.ts.map +1 -1
  79. package/dist/components/DataGrid/utils/applyModelChange.js +14 -14
  80. package/dist/components/DataGrid/utils/applyModelChange.js.map +1 -1
  81. package/dist/components/DataGrid/utils/columnFactory.js +1 -1
  82. package/dist/components/DataGrid/utils/columnFactory.js.map +1 -1
  83. package/dist/components/DataGrid/utils/splitPatch.d.ts.map +1 -1
  84. package/dist/components/DataGrid/utils/splitPatch.js +22 -13
  85. package/dist/components/DataGrid/utils/splitPatch.js.map +1 -1
  86. package/dist/components/DownloadCart/DownloadCartPage.js +1 -1
  87. package/dist/components/DownloadCart/DownloadCartPage.js.map +1 -1
  88. package/dist/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.d.ts.map +1 -1
  89. package/dist/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.js +2 -1
  90. package/dist/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.js.map +1 -1
  91. package/dist/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.module.js.map +1 -1
  92. package/dist/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.module.scss +1 -3
  93. package/dist/components/EntityBadgeIcons/EntityBadgeIcons.d.ts.map +1 -1
  94. package/dist/components/EntityBadgeIcons/EntityBadgeIcons.js +16 -10
  95. package/dist/components/EntityBadgeIcons/EntityBadgeIcons.js.map +1 -1
  96. package/dist/components/EntityDownloadButton/EntityDownloadButton.js +1 -1
  97. package/dist/components/EntityDownloadButton/EntityDownloadButton.js.map +1 -1
  98. package/dist/components/EntityFinder/EntityFinder.js +4 -4
  99. package/dist/components/EntityFinder/EntityIdTextField.js +1 -1
  100. package/dist/components/EntityFinder/EntityIdTextField.js.map +1 -1
  101. package/dist/components/EntityFinder/tree/VirtualizedTree.d.ts.map +1 -1
  102. package/dist/components/EntityFinder/tree/VirtualizedTree.js +5 -4
  103. package/dist/components/EntityFinder/tree/VirtualizedTree.js.map +1 -1
  104. package/dist/components/EntityHeaderTable/EntityHeaderTable.js +1 -1
  105. package/dist/components/EntityHeaderTable/EntityHeaderTable.js.map +1 -1
  106. package/dist/components/EntityTreeTable/components/EntityNameCell.d.ts.map +1 -1
  107. package/dist/components/EntityTreeTable/components/EntityNameCell.js +2 -1
  108. package/dist/components/EntityTreeTable/components/EntityNameCell.js.map +1 -1
  109. package/dist/components/EntityUpload/FileUploadProgress.d.ts.map +1 -1
  110. package/dist/components/EntityUpload/FileUploadProgress.js +11 -7
  111. package/dist/components/EntityUpload/FileUploadProgress.js.map +1 -1
  112. package/dist/components/Evaluation/round_limits/EvaluationRoundLimitOptionsList.d.ts.map +1 -1
  113. package/dist/components/Evaluation/round_limits/EvaluationRoundLimitOptionsList.js +4 -3
  114. package/dist/components/Evaluation/round_limits/EvaluationRoundLimitOptionsList.js.map +1 -1
  115. package/dist/components/ExperimentalMode/ExperimentalMode.js +1 -1
  116. package/dist/components/ExperimentalMode/ExperimentalMode.js.map +1 -1
  117. package/dist/components/ExternalFileHandleLink/ExternalFileHandleLink.js +1 -1
  118. package/dist/components/ExternalFileHandleLink/ExternalFileHandleLink.js.map +1 -1
  119. package/dist/components/FormTemplateEditor/ChoiceOptionsEditor.d.ts.map +1 -1
  120. package/dist/components/FormTemplateEditor/ChoiceOptionsEditor.js +2 -1
  121. package/dist/components/FormTemplateEditor/ChoiceOptionsEditor.js.map +1 -1
  122. package/dist/components/FormTemplateEditor/FieldDefinitionDrawer.d.ts.map +1 -1
  123. package/dist/components/FormTemplateEditor/FieldDefinitionDrawer.js +2 -1
  124. package/dist/components/FormTemplateEditor/FieldDefinitionDrawer.js.map +1 -1
  125. package/dist/components/FormTemplateEditor/FieldLibrary.d.ts.map +1 -1
  126. package/dist/components/FormTemplateEditor/FieldLibrary.js +2 -1
  127. package/dist/components/FormTemplateEditor/FieldLibrary.js.map +1 -1
  128. package/dist/components/FormTemplateEditor/FieldLibraryRow.js +4 -4
  129. package/dist/components/FormTemplateEditor/FieldLibraryRow.js.map +1 -1
  130. package/dist/components/FormTemplateEditor/FormStructurePanel.js +1 -1
  131. package/dist/components/FormTemplateEditor/FormStructurePanel.js.map +1 -1
  132. package/dist/components/FormTemplateEditor/FormTemplateEditorForm.js +1 -1
  133. package/dist/components/FormTemplateEditor/FormTemplateEditorForm.js.map +1 -1
  134. package/dist/components/FormTemplateEditor/StepCard.d.ts.map +1 -1
  135. package/dist/components/FormTemplateEditor/StepCard.js +15 -10
  136. package/dist/components/FormTemplateEditor/StepCard.js.map +1 -1
  137. package/dist/components/FormTemplateEditor/StepFieldRow.d.ts.map +1 -1
  138. package/dist/components/FormTemplateEditor/StepFieldRow.js +11 -6
  139. package/dist/components/FormTemplateEditor/StepFieldRow.js.map +1 -1
  140. package/dist/components/FormTemplateEditor/TemplateFileHandleField.d.ts.map +1 -1
  141. package/dist/components/FormTemplateEditor/TemplateFileHandleField.js +2 -1
  142. package/dist/components/FormTemplateEditor/TemplateFileHandleField.js.map +1 -1
  143. package/dist/components/GenericCard/DuoTermTags/DuoTermTags.js +45 -45
  144. package/dist/components/GenericCard/PortalDOI/PortalDOI.js +5 -5
  145. package/dist/components/GenericCard/PortalDOI/PortalDOI.js.map +1 -1
  146. package/dist/components/GenericCard/TableRowGenericCard.js +1 -1
  147. package/dist/components/GenericCard/TableRowGenericCard.js.map +1 -1
  148. package/dist/components/HelpPopover/HelpPopover.js +1 -1
  149. package/dist/components/HelpPopover/HelpPopover.js.map +1 -1
  150. package/dist/components/IconSvg/IconSvg.d.ts.map +1 -1
  151. package/dist/components/IconSvg/IconSvg.js +154 -47
  152. package/dist/components/IconSvg/IconSvg.js.map +1 -1
  153. package/dist/components/JsonSchemaForm/templates/ButtonTemplate.d.ts.map +1 -1
  154. package/dist/components/JsonSchemaForm/templates/ButtonTemplate.js +19 -16
  155. package/dist/components/JsonSchemaForm/templates/ButtonTemplate.js.map +1 -1
  156. package/dist/components/JsonSchemaForm/templates/RJSFInputLabel.d.ts.map +1 -1
  157. package/dist/components/JsonSchemaForm/templates/RJSFInputLabel.js +2 -1
  158. package/dist/components/JsonSchemaForm/templates/RJSFInputLabel.js.map +1 -1
  159. package/dist/components/JsonSchemaForm/widgets/PhoneWidget.d.ts +9 -0
  160. package/dist/components/JsonSchemaForm/widgets/PhoneWidget.d.ts.map +1 -0
  161. package/dist/components/JsonSchemaForm/widgets/PhoneWidget.js +21 -0
  162. package/dist/components/JsonSchemaForm/widgets/PhoneWidget.js.map +1 -0
  163. package/dist/components/Markdown/MarkdownCollapse.d.ts.map +1 -1
  164. package/dist/components/Markdown/MarkdownCollapse.js +3 -1
  165. package/dist/components/Markdown/MarkdownCollapse.js.map +1 -1
  166. package/dist/components/MissingQueryResultsWarning/MissingQueryResultsWarning.js +1 -1
  167. package/dist/components/MissingQueryResultsWarning/MissingQueryResultsWarning.js.map +1 -1
  168. package/dist/components/OAuthClientManagement/OAuthManagement.js +14 -13
  169. package/dist/components/OAuthClientManagement/OAuthManagement.js.map +1 -1
  170. package/dist/components/PortalList/PortalCard.d.ts.map +1 -1
  171. package/dist/components/PortalList/PortalCard.js +6 -5
  172. package/dist/components/PortalList/PortalCard.js.map +1 -1
  173. package/dist/components/PortalList/PortalList.js +4 -4
  174. package/dist/components/PortalList/PortalList.js.map +1 -1
  175. package/dist/components/ProjectVisibilityChip/ProjectVisibilityChip.js +6 -6
  176. package/dist/components/QueryBuilder/FilterConditionRow.js +4 -4
  177. package/dist/components/QueryCountButton/QueryCountButton.js +5 -5
  178. package/dist/components/QueryCountButton/QueryCountButton.js.map +1 -1
  179. package/dist/components/ReleaseCard/ReleaseCardLarge.js +5 -5
  180. package/dist/components/ReleaseCard/ReleaseCardLarge.js.map +1 -1
  181. package/dist/components/SetAccessRequirementCommonFields/SetAccessRequirementCommonFields.js +1 -1
  182. package/dist/components/SetAccessRequirementCommonFields/SetAccessRequirementCommonFields.js.map +1 -1
  183. package/dist/components/ShareThisPage/ShareThisPage.js +4 -4
  184. package/dist/components/ShareThisPage/ShareThisPage.js.map +1 -1
  185. package/dist/components/SustainabilityScorecard/DialLayout.js +1 -1
  186. package/dist/components/SustainabilityScorecard/DialLayout.js.map +1 -1
  187. package/dist/components/SustainabilityScorecard/SustainabilityScorecard.js +1 -1
  188. package/dist/components/SustainabilityScorecard/SustainabilityScorecard.js.map +1 -1
  189. package/dist/components/SynapseChat/SynapseChat.js +1 -1
  190. package/dist/components/SynapseChat/SynapseChat.js.map +1 -1
  191. package/dist/components/SynapseChat/SynapseChatInteraction.d.ts.map +1 -1
  192. package/dist/components/SynapseChat/SynapseChatInteraction.js +2 -1
  193. package/dist/components/SynapseChat/SynapseChatInteraction.js.map +1 -1
  194. package/dist/components/SynapseChat/components/ChatInputArea/ChatInputArea.js +1 -1
  195. package/dist/components/SynapseChat/components/ChatInputArea/ChatInputArea.js.map +1 -1
  196. package/dist/components/SynapseFooter/SynapseFooter.js +1 -1
  197. package/dist/components/SynapseFooter/SynapseFooter.js.map +1 -1
  198. package/dist/components/SynapseHomepageV2/SynapseFeaturedDatasetItem.js +1 -1
  199. package/dist/components/SynapseHomepageV2/SynapseFeaturedDatasetItem.js.map +1 -1
  200. package/dist/components/SynapseHomepageV2/SynapseHomepageNavBar.d.ts.map +1 -1
  201. package/dist/components/SynapseHomepageV2/SynapseHomepageNavBar.js +2 -1
  202. package/dist/components/SynapseHomepageV2/SynapseHomepageNavBar.js.map +1 -1
  203. package/dist/components/SynapseHomepageV2/SynapseInActionItem.js +4 -4
  204. package/dist/components/SynapseHomepageV2/SynapseInActionItem.js.map +1 -1
  205. package/dist/components/SynapseHomepageV2/SynapseTrendingProjectsItem.js +1 -1
  206. package/dist/components/SynapseHomepageV2/SynapseTrendingProjectsItem.js.map +1 -1
  207. package/dist/components/SynapseNavDrawer/SynapseNavDrawer.d.ts.map +1 -1
  208. package/dist/components/SynapseNavDrawer/SynapseNavDrawer.js +4 -1
  209. package/dist/components/SynapseNavDrawer/SynapseNavDrawer.js.map +1 -1
  210. package/dist/components/SynapsePortalBanners/SynapsePortalBanners.js +1 -1
  211. package/dist/components/SynapsePortalBanners/SynapsePortalBanners.js.map +1 -1
  212. package/dist/components/SynapseSearchPageResults/SynapseSearchPageResults.js +1 -1
  213. package/dist/components/SynapseSearchPageResults/SynapseSearchPageResults.js.map +1 -1
  214. package/dist/components/SynapseSearchPageResults/SynapseSearchResultsCard.d.ts.map +1 -1
  215. package/dist/components/SynapseSearchPageResults/SynapseSearchResultsCard.js +12 -9
  216. package/dist/components/SynapseSearchPageResults/SynapseSearchResultsCard.js.map +1 -1
  217. package/dist/components/SynapseTable/RowSelection/RowSelectionControls.js +4 -4
  218. package/dist/components/SynapseTable/RowSelection/RowSelectionControls.js.map +1 -1
  219. package/dist/components/SynapseTable/datasets/DatasetItemsEditor.js +140 -140
  220. package/dist/components/SynapseTable/datasets/DatasetItemsEditor.js.map +1 -1
  221. package/dist/components/TableColumnSchemaEditor/ColumnModelForm.js +1 -1
  222. package/dist/components/TableColumnSchemaEditor/ColumnModelForm.js.map +1 -1
  223. package/dist/components/TableColumnSchemaEditor/ImportTableColumnsButton.js +1 -1
  224. package/dist/components/TableColumnSchemaEditor/ImportTableColumnsButton.js.map +1 -1
  225. package/dist/components/TableColumnSchemaEditor/TableColumnSchemaEditorUtils.d.ts.map +1 -1
  226. package/dist/components/TableColumnSchemaEditor/TableColumnSchemaEditorUtils.js.map +1 -1
  227. package/dist/components/TableColumnSchemaEditor/TableColumnSchemaForm.js +9 -9
  228. package/dist/components/TableColumnSchemaEditor/TableColumnSchemaForm.js.map +1 -1
  229. package/dist/components/TableColumnSchemaEditor/TableColumnSchemaFormActions.d.ts.map +1 -1
  230. package/dist/components/TableColumnSchemaEditor/TableColumnSchemaFormActions.js +6 -4
  231. package/dist/components/TableColumnSchemaEditor/TableColumnSchemaFormActions.js.map +1 -1
  232. package/dist/components/TanStackTable/ColumnHeader.js +1 -1
  233. package/dist/components/TanStackTable/ColumnHeader.js.map +1 -1
  234. package/dist/components/TeamSubjectsSelector/TeamBadgeOrError.js +1 -1
  235. package/dist/components/TeamSubjectsSelector/TeamBadgeOrError.js.map +1 -1
  236. package/dist/components/TeamSubjectsSelector/TeamSubjectsSelector.d.ts.map +1 -1
  237. package/dist/components/TeamSubjectsSelector/TeamSubjectsSelector.js +4 -3
  238. package/dist/components/TeamSubjectsSelector/TeamSubjectsSelector.js.map +1 -1
  239. package/dist/components/Webhook/WebhookDashboard.js +1 -1
  240. package/dist/components/Webhook/WebhookDashboard.js.map +1 -1
  241. package/dist/components/dataaccess/AccessRequirementDashboard.js +4 -4
  242. package/dist/components/dataaccess/AccessRequirementDashboard.js.map +1 -1
  243. package/dist/components/dataaccess/AccessRequirementTable.js +1 -1
  244. package/dist/components/dataaccess/AccessRequirementTable.js.map +1 -1
  245. package/dist/components/dataaccess/EDucTemplateTable.d.ts.map +1 -1
  246. package/dist/components/dataaccess/EDucTemplateTable.js +13 -11
  247. package/dist/components/dataaccess/EDucTemplateTable.js.map +1 -1
  248. package/dist/components/dataaccess/FormTemplateTable.js +6 -6
  249. package/dist/components/dataaccess/FormTemplateTable.js.map +1 -1
  250. package/dist/components/dataaccess/ReviewerDashboard.js +17 -17
  251. package/dist/components/dataaccess/ReviewerDashboard.js.map +1 -1
  252. package/dist/components/dataaccess/SubmissionPage/SubmissionPage.js +4 -4
  253. package/dist/components/doi/CreateOrUpdateDoiModal.js +1 -1
  254. package/dist/components/doi/CreateOrUpdateDoiModal.js.map +1 -1
  255. package/dist/components/download_list/DownloadDetails.d.ts.map +1 -1
  256. package/dist/components/download_list/DownloadDetails.js +12 -10
  257. package/dist/components/download_list/DownloadDetails.js.map +1 -1
  258. package/dist/components/entity/metadata/AnnotationsTable.js +1 -1
  259. package/dist/components/entity/metadata/AnnotationsTable.js.map +1 -1
  260. package/dist/components/entity/page/CreatedByModifiedBy.js +1 -1
  261. package/dist/components/entity/page/CreatedByModifiedBy.js.map +1 -1
  262. package/dist/components/entity/page/action_menu/EntityActionMenu.d.ts.map +1 -1
  263. package/dist/components/entity/page/action_menu/EntityActionMenu.js.map +1 -1
  264. package/dist/components/entity/page/title_bar/useGetEntityTitleBarProperties.js +1 -1
  265. package/dist/components/entity/page/title_bar/useGetEntityTitleBarProperties.js.map +1 -1
  266. package/dist/components/error/ErrorChip.d.ts.map +1 -1
  267. package/dist/components/error/ErrorChip.js +2 -1
  268. package/dist/components/error/ErrorChip.js.map +1 -1
  269. package/dist/components/table/CsvPreview/CreateTableFromCsvDialog.js +14 -14
  270. package/dist/components/table/CsvPreview/CsvPreviewWithOptions.js +4 -4
  271. package/dist/components/table/CsvPreview/CsvPreviewWithOptions.js.map +1 -1
  272. package/dist/components/widgets/facet-nav/FacetNavPanel.js +1 -1
  273. package/dist/components/widgets/facet-nav/FacetNavPanel.js.map +1 -1
  274. package/dist/features/curator/dashboard/components/NextStepButton.d.ts.map +1 -1
  275. package/dist/features/curator/dashboard/components/NextStepButton.js +7 -6
  276. package/dist/features/curator/dashboard/components/NextStepButton.js.map +1 -1
  277. package/dist/features/entity/metadata-task/components/CreateOrUpdateCurationTaskDialog.js +8 -8
  278. package/dist/features/entity/metadata-task/components/CreateOrUpdateCurationTaskDialog.js.map +1 -1
  279. package/dist/features/entity/metadata-task/components/MetadataTaskTableActionCell.js +4 -4
  280. package/dist/features/entity/metadata-task/components/MetadataTaskTableActionCell.js.map +1 -1
  281. package/dist/features/entity/metadata-task/components/MetadataTasksPage.js +4 -4
  282. package/dist/features/entity/metadata-task/components/MetadataTasksPage.js.map +1 -1
  283. package/dist/features/entity/metadata-task/components/MetadataTasksTableAssigneeCell.js +1 -1
  284. package/dist/features/entity/metadata-task/components/MetadataTasksTableAssigneeCell.js.map +1 -1
  285. package/dist/features/entity/metadata-task/create-task/CurateTaskForm.js +4 -4
  286. package/dist/features/entity/metadata-task/create-task/CurateTaskForm.js.map +1 -1
  287. package/dist/features/entity/metadata-task/create-task/TaskCategoryCard.js +1 -1
  288. package/dist/features/entity/metadata-task/create-task/TaskCategoryCard.js.map +1 -1
  289. package/dist/features/entity/metadata-task/create-task/TaskFormHeader.js +1 -1
  290. package/dist/features/entity/metadata-task/create-task/TaskFormHeader.js.map +1 -1
  291. package/dist/features/entity/metadata-task/create-task/curationTaskFlowRoutes.js +10 -10
  292. package/dist/features/entity/metadata-task/create-task/curationTaskFlowRoutes.js.map +1 -1
  293. package/dist/features/team/invitation/components/OpenInvitationsToUserCard.js +1 -1
  294. package/dist/features/team/invitation/components/OpenInvitationsToUserCard.js.map +1 -1
  295. package/dist/mocks/msw/handlers/aridhiaHandlers.d.ts +8 -0
  296. package/dist/mocks/msw/handlers/aridhiaHandlers.d.ts.map +1 -1
  297. package/dist/mocks/msw/handlers/aridhiaHandlers.js +52 -41
  298. package/dist/mocks/msw/handlers/aridhiaHandlers.js.map +1 -1
  299. package/dist/mocks/msw/handlers/entityHandlers.d.ts.map +1 -1
  300. package/dist/mocks/msw/handlers/entityHandlers.js +70 -67
  301. package/dist/mocks/msw/handlers/entityHandlers.js.map +1 -1
  302. package/dist/mocks/msw/handlers/gridHandlers.js +2 -2
  303. package/dist/mocks/msw/handlers/gridHandlers.js.map +1 -1
  304. package/dist/mocks/msw/server.d.ts.map +1 -1
  305. package/dist/mocks/msw/server.js +4 -2
  306. package/dist/mocks/msw/server.js.map +1 -1
  307. package/dist/synapse-queries/user/useGetUserChallenges.d.ts.map +1 -1
  308. package/dist/synapse-queries/user/useGetUserChallenges.js.map +1 -1
  309. package/dist/theme/DefaultTheme.d.ts.map +1 -1
  310. package/dist/theme/DefaultTheme.js +4 -1
  311. package/dist/theme/DefaultTheme.js.map +1 -1
  312. package/dist/tsconfig.build.tsbuildinfo +1 -1
  313. package/dist/utils/APIConstants.d.ts.map +1 -1
  314. package/dist/utils/APIConstants.js.map +1 -1
  315. package/dist/utils/AppUtils/AppUtils.js +1 -1
  316. package/dist/utils/AppUtils/AppUtils.js.map +1 -1
  317. package/dist/utils/functions/EntityTypeUtils.d.ts.map +1 -1
  318. package/dist/utils/functions/EntityTypeUtils.js.map +1 -1
  319. package/package.json +7 -6
@@ -1 +1 @@
1
- {"version":3,"file":"QueryCountButton.js","names":[],"sources":["../../../src/components/QueryCountButton/QueryCountButton.tsx"],"sourcesContent":["import useGetQueryResultBundle from '@/synapse-queries/entity/useGetQueryResultBundle'\nimport { BUNDLE_MASK_QUERY_COUNT } from '@/utils/SynapseConstants'\nimport { parseEntityIdFromSqlStatement } from '@/utils/functions/SqlFunctions'\nimport { QueryBundleRequest } from '@sage-bionetworks/synapse-types'\nimport { Box, Button, ButtonProps } from '@mui/material'\nimport { NavigateNext } from '@mui/icons-material'\nimport React from 'react'\nimport { Link as RouterLink, useInRouterContext } from 'react-router'\n\nexport type QueryCountButtonProps = {\n /**\n * The SQL query to execute to get the count\n */\n sql: string\n /**\n * The target URL when the button is clicked\n */\n href: string\n /**\n * Text to display before the count (e.g., \"Explore\")\n */\n prefixText?: string\n /**\n * Text to display after the count (e.g., \"files\")\n */\n suffixText?: string\n /**\n * Additional MUI Button props\n */\n} & Omit<ButtonProps, 'children'>\n\n/**\n * A button component that displays text with an inline count.\n * The count is fetched by executing a SQL query against a Synapse table.\n * Example: \"Explore 42 files\"\n */\nexport function QueryCountButton(props: QueryCountButtonProps) {\n const { sql, href, prefixText = '', suffixText = '', ...buttonProps } = props\n const entityId = parseEntityIdFromSqlStatement(sql)\n const inRouterContext = useInRouterContext()\n\n const request: QueryBundleRequest = {\n concreteType: 'org.sagebionetworks.repo.model.table.QueryBundleRequest',\n query: { sql },\n entityId,\n partMask: BUNDLE_MASK_QUERY_COUNT,\n }\n\n const { data: queryResult, isLoading } = useGetQueryResultBundle(request)\n\n const count = queryResult?.queryCount\n\n const isExternalLink =\n href?.startsWith('http://') || href?.startsWith('https://')\n\n // Determine the appropriate link props based on context\n let linkProps: Partial<ButtonProps> & { target?: string; to?: string } = {}\n\n if (isExternalLink) {\n linkProps = {\n href,\n target: '_blank',\n rel: 'noopener noreferrer',\n component: 'a',\n }\n } else if (inRouterContext) {\n // For internal links, if we are in a react-router context, use RouterLink\n linkProps = {\n to: href,\n component: RouterLink,\n }\n } else {\n linkProps = {\n href,\n component: 'a',\n }\n }\n\n // Build the button text: \"prefixText count suffixText\"\n const buttonText = React.useMemo(() => {\n const parts: string[] = []\n\n if (prefixText) {\n parts.push(prefixText)\n }\n\n if (!isLoading && count !== undefined) {\n parts.push(count.toLocaleString())\n }\n\n if (suffixText) {\n parts.push(suffixText)\n }\n\n return parts.join(' ')\n }, [prefixText, count, suffixText, isLoading])\n\n // Icon with theme-aware circular background\n const endIcon = (\n <Box\n sx={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n backgroundColor: 'background.paper',\n borderRadius: '50%',\n width: 24,\n height: 24,\n }}\n >\n <NavigateNext sx={{ color: 'primary.main', fontSize: 20 }} />\n </Box>\n )\n\n return (\n <Button\n {...buttonProps}\n {...linkProps}\n endIcon={endIcon}\n loading={isLoading}\n >\n {buttonText}\n </Button>\n )\n}\n\nexport default QueryCountButton\n"],"mappings":";;;;;;;;;AAoCA,SAAgB,EAAiB,GAA8B;CAC7D,IAAM,EAAE,QAAK,SAAM,gBAAa,IAAI,gBAAa,IAAI,GAAG,MAAgB,GAClE,IAAW,EAA8B,CAAG,GAC5C,IAAkB,EAAmB,GASrC,EAAE,MAAM,GAAa,iBAAc,EAAwB;EAN/D,cAAc;EACd,OAAO,EAAE,OAAI;EACb;EACA,UAAA;CAG+D,CAAO,GAElE,IAAQ,GAAa,YAErB,IACJ,GAAM,WAAW,SAAS,KAAK,GAAM,WAAW,UAAU,GAGxD,IAAqE,CAAC;CAE1E,AAcE,IAdE,IACU;EACV;EACA,QAAQ;EACR,KAAK;EACL,WAAW;CACb,IACS,IAEG;EACV,IAAI;EACJ,WAAW;CACb,IAEY;EACV;EACA,WAAW;CACb;CAIF,IAAM,IAAa,EAAM,cAAc;EACrC,IAAM,IAAkB,CAAC;EAczB,OAZI,KACF,EAAM,KAAK,CAAU,GAGnB,CAAC,KAAa,MAAU,KAAA,KAC1B,EAAM,KAAK,EAAM,eAAe,CAAC,GAG/B,KACF,EAAM,KAAK,CAAU,GAGhB,EAAM,KAAK,GAAG;CACvB,GAAG;EAAC;EAAY;EAAO;EAAY;CAAS,CAAC,GAGvC,IACJ,kBAAC,GAAD;EACE,IAAI;GACF,SAAS;GACT,YAAY;GACZ,gBAAgB;GAChB,iBAAiB;GACjB,cAAc;GACd,OAAO;GACP,QAAQ;EACV;YAEA,kBAAC,GAAD,EAAc,IAAI;GAAE,OAAO;GAAgB,UAAU;EAAG,EAAI,CAAA;CACzD,CAAA;CAGP,OACE,kBAAC,GAAD;EACE,GAAI;EACJ,GAAI;EACK;EACT,SAAS;YAER;CACK,CAAA;AAEZ"}
1
+ {"version":3,"file":"QueryCountButton.js","names":[],"sources":["../../../src/components/QueryCountButton/QueryCountButton.tsx"],"sourcesContent":["import useGetQueryResultBundle from '@/synapse-queries/entity/useGetQueryResultBundle'\nimport { BUNDLE_MASK_QUERY_COUNT } from '@/utils/SynapseConstants'\nimport { parseEntityIdFromSqlStatement } from '@/utils/functions/SqlFunctions'\nimport { QueryBundleRequest } from '@sage-bionetworks/synapse-types'\nimport { Box, Button, ButtonProps } from '@mui/material'\nimport NavigateNext from '@mui/icons-material/NavigateNext'\nimport React from 'react'\nimport { Link as RouterLink, useInRouterContext } from 'react-router'\n\nexport type QueryCountButtonProps = {\n /**\n * The SQL query to execute to get the count\n */\n sql: string\n /**\n * The target URL when the button is clicked\n */\n href: string\n /**\n * Text to display before the count (e.g., \"Explore\")\n */\n prefixText?: string\n /**\n * Text to display after the count (e.g., \"files\")\n */\n suffixText?: string\n /**\n * Additional MUI Button props\n */\n} & Omit<ButtonProps, 'children'>\n\n/**\n * A button component that displays text with an inline count.\n * The count is fetched by executing a SQL query against a Synapse table.\n * Example: \"Explore 42 files\"\n */\nexport function QueryCountButton(props: QueryCountButtonProps) {\n const { sql, href, prefixText = '', suffixText = '', ...buttonProps } = props\n const entityId = parseEntityIdFromSqlStatement(sql)\n const inRouterContext = useInRouterContext()\n\n const request: QueryBundleRequest = {\n concreteType: 'org.sagebionetworks.repo.model.table.QueryBundleRequest',\n query: { sql },\n entityId,\n partMask: BUNDLE_MASK_QUERY_COUNT,\n }\n\n const { data: queryResult, isLoading } = useGetQueryResultBundle(request)\n\n const count = queryResult?.queryCount\n\n const isExternalLink =\n href?.startsWith('http://') || href?.startsWith('https://')\n\n // Determine the appropriate link props based on context\n let linkProps: Partial<ButtonProps> & { target?: string; to?: string } = {}\n\n if (isExternalLink) {\n linkProps = {\n href,\n target: '_blank',\n rel: 'noopener noreferrer',\n component: 'a',\n }\n } else if (inRouterContext) {\n // For internal links, if we are in a react-router context, use RouterLink\n linkProps = {\n to: href,\n component: RouterLink,\n }\n } else {\n linkProps = {\n href,\n component: 'a',\n }\n }\n\n // Build the button text: \"prefixText count suffixText\"\n const buttonText = React.useMemo(() => {\n const parts: string[] = []\n\n if (prefixText) {\n parts.push(prefixText)\n }\n\n if (!isLoading && count !== undefined) {\n parts.push(count.toLocaleString())\n }\n\n if (suffixText) {\n parts.push(suffixText)\n }\n\n return parts.join(' ')\n }, [prefixText, count, suffixText, isLoading])\n\n // Icon with theme-aware circular background\n const endIcon = (\n <Box\n sx={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n backgroundColor: 'background.paper',\n borderRadius: '50%',\n width: 24,\n height: 24,\n }}\n >\n <NavigateNext sx={{ color: 'primary.main', fontSize: 20 }} />\n </Box>\n )\n\n return (\n <Button\n {...buttonProps}\n {...linkProps}\n endIcon={endIcon}\n loading={isLoading}\n >\n {buttonText}\n </Button>\n )\n}\n\nexport default QueryCountButton\n"],"mappings":";;;;;;;;;AAoCA,SAAgB,EAAiB,GAA8B;CAC7D,IAAM,EAAE,QAAK,SAAM,gBAAa,IAAI,gBAAa,IAAI,GAAG,MAAgB,GAClE,IAAW,EAA8B,CAAG,GAC5C,IAAkB,EAAmB,GASrC,EAAE,MAAM,GAAa,iBAAc,EAAwB;EAN/D,cAAc;EACd,OAAO,EAAE,OAAI;EACb;EACA,UAAA;CAG+D,CAAO,GAElE,IAAQ,GAAa,YAErB,IACJ,GAAM,WAAW,SAAS,KAAK,GAAM,WAAW,UAAU,GAGxD,IAAqE,CAAC;CAE1E,AAcE,IAdE,IACU;EACV;EACA,QAAQ;EACR,KAAK;EACL,WAAW;CACb,IACS,IAEG;EACV,IAAI;EACJ,WAAW;CACb,IAEY;EACV;EACA,WAAW;CACb;CAIF,IAAM,IAAa,EAAM,cAAc;EACrC,IAAM,IAAkB,CAAC;EAczB,OAZI,KACF,EAAM,KAAK,CAAU,GAGnB,CAAC,KAAa,MAAU,KAAA,KAC1B,EAAM,KAAK,EAAM,eAAe,CAAC,GAG/B,KACF,EAAM,KAAK,CAAU,GAGhB,EAAM,KAAK,GAAG;CACvB,GAAG;EAAC;EAAY;EAAO;EAAY;CAAS,CAAC,GAGvC,IACJ,kBAAC,GAAD;EACE,IAAI;GACF,SAAS;GACT,YAAY;GACZ,gBAAgB;GAChB,iBAAiB;GACjB,cAAc;GACd,OAAO;GACP,QAAQ;EACV;YAEA,kBAAC,GAAD,EAAc,IAAI;GAAE,OAAO;GAAgB,UAAU;EAAG,EAAI,CAAA;CACzD,CAAA;CAGP,OACE,kBAAC,GAAD;EACE,GAAI;EACJ,GAAI;EACK;EACT,SAAS;YAER;CACK,CAAA;AAEZ"}
@@ -2,8 +2,8 @@ import { formatExplorePagePathAndQueryString as e, formatReleaseCardData as t }
2
2
  import { Fragment as n, useEffect as r, useState as i } from "react";
3
3
  import { Box as a, Button as o, Divider as s, Stack as c, Typography as l } from "@mui/material";
4
4
  import { Fragment as u, jsx as d, jsxs as f } from "react/jsx-runtime";
5
- import { CalendarTodayTwoTone as p } from "@mui/icons-material";
6
- import { Link as m } from "react-router";
5
+ import { Link as p } from "react-router";
6
+ import m from "@mui/icons-material/CalendarTodayTwoTone";
7
7
  //#region src/components/ReleaseCard/ReleaseCardLarge.tsx
8
8
  function h({ value: e, label: t }) {
9
9
  return /* @__PURE__ */ f(c, {
@@ -65,7 +65,7 @@ function g({ data: g, schema: _, includePortalCardClass: v = !0, releaseCardConf
65
65
  alignItems: "center",
66
66
  gap: "10px"
67
67
  },
68
- children: [/* @__PURE__ */ d(p, { sx: { color: "grey.700" } }), /* @__PURE__ */ f(l, {
68
+ children: [/* @__PURE__ */ d(m, { sx: { color: "grey.700" } }), /* @__PURE__ */ f(l, {
69
69
  variant: "headline1",
70
70
  children: [y.prependRelease && "Release ", b]
71
71
  })]
@@ -82,13 +82,13 @@ function g({ data: g, schema: _, includePortalCardClass: v = !0, releaseCardConf
82
82
  gap: "20px"
83
83
  },
84
84
  children: [C && T && /* @__PURE__ */ d(o, {
85
- component: m,
85
+ component: p,
86
86
  variant: "contained",
87
87
  color: "primary",
88
88
  to: T,
89
89
  children: C.label
90
90
  }), w && D && /* @__PURE__ */ d(o, {
91
- component: m,
91
+ component: p,
92
92
  to: D,
93
93
  children: w.label
94
94
  })]
@@ -1 +1 @@
1
- {"version":3,"file":"ReleaseCardLarge.js","names":[],"sources":["../../../src/components/ReleaseCard/ReleaseCardLarge.tsx"],"sourcesContent":["import { CalendarTodayTwoTone } from '@mui/icons-material'\nimport { Box, Button, Divider, Stack, Typography } from '@mui/material'\nimport { Fragment, useEffect, useState } from 'react'\nimport { Link as ReactRouterLink } from 'react-router'\nimport { ReleaseCardProps } from './ReleaseCard'\nimport { ReleaseCardLargeConfig, ReleaseCardStat } from './ReleaseCardTypes'\nimport {\n formatExplorePagePathAndQueryString,\n formatReleaseCardData,\n} from './ReleaseCardUtils'\n\nfunction StatFlex({ value, label }: ReleaseCardStat) {\n return (\n <Stack\n direction=\"column\"\n sx={{\n alignItems: 'center',\n padding: { xs: '20px 10px', md: '20px 40px' },\n gap: '10px',\n // ensure that stats are aligned when multiple cards are stacked vertically\n width: { xs: 'unset', lg: '200px' },\n }}\n >\n <Typography variant=\"headline1\">{value}</Typography>\n <Typography\n variant=\"body1\"\n sx={{\n lineHeight: '20px',\n color: 'grey.700',\n }}\n >\n {label}\n </Typography>\n </Stack>\n )\n}\n\nexport type ReleaseCardLargeProps = Omit<\n ReleaseCardProps,\n 'releaseCardConfig'\n> & { releaseCardConfig: ReleaseCardLargeConfig }\n\nexport function ReleaseCardLarge({\n data,\n schema,\n includePortalCardClass = true,\n releaseCardConfig,\n}: ReleaseCardLargeProps) {\n const { releaseName, releaseDate, stats } = formatReleaseCardData(\n schema,\n data,\n releaseCardConfig.releaseMetadataConfig,\n releaseCardConfig.statsConfig,\n )\n const { primaryBtnConfig, secondaryBtnConfig } = releaseCardConfig\n\n const [primaryBtnPathAndQuery, setPrimaryBtnPathAndQuery] = useState<\n string | null\n >(null)\n const [secondaryBtnPathAndQuery, setSecondaryBtnPathAndQuery] = useState<\n string | null\n >(null)\n\n useEffect(() => {\n formatExplorePagePathAndQueryString(schema, data, primaryBtnConfig).then(\n setPrimaryBtnPathAndQuery,\n )\n\n formatExplorePagePathAndQueryString(schema, data, secondaryBtnConfig).then(\n setSecondaryBtnPathAndQuery,\n )\n }, [schema, data, primaryBtnConfig, secondaryBtnConfig])\n\n if (releaseName === null) return <></>\n\n return (\n <Box\n className={`ReleaseCard ${\n includePortalCardClass ? 'SRC-portalCard' : ''\n }`}\n sx={{\n minWidth: '200px',\n }}\n >\n <Stack\n direction={{ xs: 'column', lg: 'row' }}\n sx={{\n justifyContent: 'space-between',\n gap: '20px',\n padding: '20px',\n }}\n >\n <Stack\n direction=\"column\"\n sx={{\n gap: '20px',\n }}\n >\n <Stack\n direction=\"row\"\n sx={{\n alignItems: 'center',\n gap: '10px',\n }}\n >\n <CalendarTodayTwoTone sx={{ color: 'grey.700' }} />\n <Typography variant=\"headline1\">\n {releaseCardConfig.prependRelease && 'Release '}\n {releaseName}\n </Typography>\n </Stack>\n <Stack\n direction={{ xs: 'column', sm: 'row' }}\n sx={{\n alignItems: { xs: 'flex-start', sm: 'center' },\n gap: '20px',\n }}\n >\n {primaryBtnConfig && primaryBtnPathAndQuery && (\n <Button\n component={ReactRouterLink}\n variant=\"contained\"\n color=\"primary\"\n to={primaryBtnPathAndQuery}\n >\n {primaryBtnConfig.label}\n </Button>\n )}\n {secondaryBtnConfig && secondaryBtnPathAndQuery && (\n <Button component={ReactRouterLink} to={secondaryBtnPathAndQuery}>\n {secondaryBtnConfig.label}\n </Button>\n )}\n </Stack>\n </Stack>\n <Divider /> {/* divides stacks when page is narrow */}\n <Stack\n direction=\"row\"\n sx={{\n gap: { xs: 0, lg: '10px' },\n alignItems: 'center',\n justifyContent: { xs: 'space-evenly', lg: 'unset' },\n flexWrap: { xs: 'wrap', lg: 'nowrap' },\n }}\n >\n <StatFlex {...releaseDate} />\n {stats.map(stat => {\n return (\n <Fragment key={stat.label}>\n <Divider orientation=\"vertical\" flexItem />\n <StatFlex {...stat} />\n </Fragment>\n )\n })}\n </Stack>\n </Stack>\n </Box>\n )\n}\n"],"mappings":";;;;;;;AAWA,SAAS,EAAS,EAAE,UAAO,YAA0B;CACnD,OACE,kBAAC,GAAD;EACE,WAAU;EACV,IAAI;GACF,YAAY;GACZ,SAAS;IAAE,IAAI;IAAa,IAAI;GAAY;GAC5C,KAAK;GAEL,OAAO;IAAE,IAAI;IAAS,IAAI;GAAQ;EACpC;YARF,CAUE,kBAAC,GAAD;GAAY,SAAQ;aAAa;EAAkB,CAAA,GACnD,kBAAC,GAAD;GACE,SAAQ;GACR,IAAI;IACF,YAAY;IACZ,OAAO;GACT;aAEC;EACS,CAAA,CACP;;AAEX;AAOA,SAAgB,EAAiB,EAC/B,SACA,WACA,4BAAyB,IACzB,wBACwB;CACxB,IAAM,EAAE,gBAAa,gBAAa,aAAU,EAC1C,GACA,GACA,EAAkB,uBAClB,EAAkB,WACpB,GACM,EAAE,qBAAkB,0BAAuB,GAE3C,CAAC,GAAwB,KAA6B,EAE1D,IAAI,GACA,CAAC,GAA0B,KAA+B,EAE9D,IAAI;CAcN,OAZA,QAAgB;EAKd,AAJA,EAAoC,GAAQ,GAAM,CAAgB,EAAE,KAClE,CACF,GAEA,EAAoC,GAAQ,GAAM,CAAkB,EAAE,KACpE,CACF;CACF,GAAG;EAAC;EAAQ;EAAM;EAAkB;CAAkB,CAAC,GAEnD,MAAgB,OAAa,kBAAA,GAAA,CAAI,CAAA,IAGnC,kBAAC,GAAD;EACE,WAAW,eACT,IAAyB,mBAAmB;EAE9C,IAAI,EACF,UAAU,QACZ;YAEA,kBAAC,GAAD;GACE,WAAW;IAAE,IAAI;IAAU,IAAI;GAAM;GACrC,IAAI;IACF,gBAAgB;IAChB,KAAK;IACL,SAAS;GACX;aANF;IAQE,kBAAC,GAAD;KACE,WAAU;KACV,IAAI,EACF,KAAK,OACP;eAJF,CAME,kBAAC,GAAD;MACE,WAAU;MACV,IAAI;OACF,YAAY;OACZ,KAAK;MACP;gBALF,CAOE,kBAAC,GAAD,EAAsB,IAAI,EAAE,OAAO,WAAW,EAAI,CAAA,GAClD,kBAAC,GAAD;OAAY,SAAQ;iBAApB,CACG,EAAkB,kBAAkB,YACpC,CACS;QACP;SACP,kBAAC,GAAD;MACE,WAAW;OAAE,IAAI;OAAU,IAAI;MAAM;MACrC,IAAI;OACF,YAAY;QAAE,IAAI;QAAc,IAAI;OAAS;OAC7C,KAAK;MACP;gBALF,CAOG,KAAoB,KACnB,kBAAC,GAAD;OACE,WAAW;OACX,SAAQ;OACR,OAAM;OACN,IAAI;iBAEH,EAAiB;MACZ,CAAA,GAET,KAAsB,KACrB,kBAAC,GAAD;OAAQ,WAAW;OAAiB,IAAI;iBACrC,EAAmB;MACd,CAAA,CAEL;OACF;;IACP,kBAAC,GAAD,CAAU,CAAA;IAAC;IACX,kBAAC,GAAD;KACE,WAAU;KACV,IAAI;MACF,KAAK;OAAE,IAAI;OAAG,IAAI;MAAO;MACzB,YAAY;MACZ,gBAAgB;OAAE,IAAI;OAAgB,IAAI;MAAQ;MAClD,UAAU;OAAE,IAAI;OAAQ,IAAI;MAAS;KACvC;eAPF,CASE,kBAAC,GAAD,EAAU,GAAI,EAAc,CAAA,GAC3B,EAAM,KAAI,MAEP,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;MAAS,aAAY;MAAW,UAAA;KAAU,CAAA,GAC1C,kBAAC,GAAD,EAAU,GAAI,EAAO,CAAA,CACb,EAAA,GAHK,EAAK,KAGV,CAEb,CACI;;GACF;;CACJ,CAAA;AAET"}
1
+ {"version":3,"file":"ReleaseCardLarge.js","names":[],"sources":["../../../src/components/ReleaseCard/ReleaseCardLarge.tsx"],"sourcesContent":["import CalendarTodayTwoTone from '@mui/icons-material/CalendarTodayTwoTone'\nimport { Box, Button, Divider, Stack, Typography } from '@mui/material'\nimport { Fragment, useEffect, useState } from 'react'\nimport { Link as ReactRouterLink } from 'react-router'\nimport { ReleaseCardProps } from './ReleaseCard'\nimport { ReleaseCardLargeConfig, ReleaseCardStat } from './ReleaseCardTypes'\nimport {\n formatExplorePagePathAndQueryString,\n formatReleaseCardData,\n} from './ReleaseCardUtils'\n\nfunction StatFlex({ value, label }: ReleaseCardStat) {\n return (\n <Stack\n direction=\"column\"\n sx={{\n alignItems: 'center',\n padding: { xs: '20px 10px', md: '20px 40px' },\n gap: '10px',\n // ensure that stats are aligned when multiple cards are stacked vertically\n width: { xs: 'unset', lg: '200px' },\n }}\n >\n <Typography variant=\"headline1\">{value}</Typography>\n <Typography\n variant=\"body1\"\n sx={{\n lineHeight: '20px',\n color: 'grey.700',\n }}\n >\n {label}\n </Typography>\n </Stack>\n )\n}\n\nexport type ReleaseCardLargeProps = Omit<\n ReleaseCardProps,\n 'releaseCardConfig'\n> & { releaseCardConfig: ReleaseCardLargeConfig }\n\nexport function ReleaseCardLarge({\n data,\n schema,\n includePortalCardClass = true,\n releaseCardConfig,\n}: ReleaseCardLargeProps) {\n const { releaseName, releaseDate, stats } = formatReleaseCardData(\n schema,\n data,\n releaseCardConfig.releaseMetadataConfig,\n releaseCardConfig.statsConfig,\n )\n const { primaryBtnConfig, secondaryBtnConfig } = releaseCardConfig\n\n const [primaryBtnPathAndQuery, setPrimaryBtnPathAndQuery] = useState<\n string | null\n >(null)\n const [secondaryBtnPathAndQuery, setSecondaryBtnPathAndQuery] = useState<\n string | null\n >(null)\n\n useEffect(() => {\n formatExplorePagePathAndQueryString(schema, data, primaryBtnConfig).then(\n setPrimaryBtnPathAndQuery,\n )\n\n formatExplorePagePathAndQueryString(schema, data, secondaryBtnConfig).then(\n setSecondaryBtnPathAndQuery,\n )\n }, [schema, data, primaryBtnConfig, secondaryBtnConfig])\n\n if (releaseName === null) return <></>\n\n return (\n <Box\n className={`ReleaseCard ${\n includePortalCardClass ? 'SRC-portalCard' : ''\n }`}\n sx={{\n minWidth: '200px',\n }}\n >\n <Stack\n direction={{ xs: 'column', lg: 'row' }}\n sx={{\n justifyContent: 'space-between',\n gap: '20px',\n padding: '20px',\n }}\n >\n <Stack\n direction=\"column\"\n sx={{\n gap: '20px',\n }}\n >\n <Stack\n direction=\"row\"\n sx={{\n alignItems: 'center',\n gap: '10px',\n }}\n >\n <CalendarTodayTwoTone sx={{ color: 'grey.700' }} />\n <Typography variant=\"headline1\">\n {releaseCardConfig.prependRelease && 'Release '}\n {releaseName}\n </Typography>\n </Stack>\n <Stack\n direction={{ xs: 'column', sm: 'row' }}\n sx={{\n alignItems: { xs: 'flex-start', sm: 'center' },\n gap: '20px',\n }}\n >\n {primaryBtnConfig && primaryBtnPathAndQuery && (\n <Button\n component={ReactRouterLink}\n variant=\"contained\"\n color=\"primary\"\n to={primaryBtnPathAndQuery}\n >\n {primaryBtnConfig.label}\n </Button>\n )}\n {secondaryBtnConfig && secondaryBtnPathAndQuery && (\n <Button component={ReactRouterLink} to={secondaryBtnPathAndQuery}>\n {secondaryBtnConfig.label}\n </Button>\n )}\n </Stack>\n </Stack>\n <Divider /> {/* divides stacks when page is narrow */}\n <Stack\n direction=\"row\"\n sx={{\n gap: { xs: 0, lg: '10px' },\n alignItems: 'center',\n justifyContent: { xs: 'space-evenly', lg: 'unset' },\n flexWrap: { xs: 'wrap', lg: 'nowrap' },\n }}\n >\n <StatFlex {...releaseDate} />\n {stats.map(stat => {\n return (\n <Fragment key={stat.label}>\n <Divider orientation=\"vertical\" flexItem />\n <StatFlex {...stat} />\n </Fragment>\n )\n })}\n </Stack>\n </Stack>\n </Box>\n )\n}\n"],"mappings":";;;;;;;AAWA,SAAS,EAAS,EAAE,UAAO,YAA0B;CACnD,OACE,kBAAC,GAAD;EACE,WAAU;EACV,IAAI;GACF,YAAY;GACZ,SAAS;IAAE,IAAI;IAAa,IAAI;GAAY;GAC5C,KAAK;GAEL,OAAO;IAAE,IAAI;IAAS,IAAI;GAAQ;EACpC;YARF,CAUE,kBAAC,GAAD;GAAY,SAAQ;aAAa;EAAkB,CAAA,GACnD,kBAAC,GAAD;GACE,SAAQ;GACR,IAAI;IACF,YAAY;IACZ,OAAO;GACT;aAEC;EACS,CAAA,CACP;;AAEX;AAOA,SAAgB,EAAiB,EAC/B,SACA,WACA,4BAAyB,IACzB,wBACwB;CACxB,IAAM,EAAE,gBAAa,gBAAa,aAAU,EAC1C,GACA,GACA,EAAkB,uBAClB,EAAkB,WACpB,GACM,EAAE,qBAAkB,0BAAuB,GAE3C,CAAC,GAAwB,KAA6B,EAE1D,IAAI,GACA,CAAC,GAA0B,KAA+B,EAE9D,IAAI;CAcN,OAZA,QAAgB;EAKd,AAJA,EAAoC,GAAQ,GAAM,CAAgB,EAAE,KAClE,CACF,GAEA,EAAoC,GAAQ,GAAM,CAAkB,EAAE,KACpE,CACF;CACF,GAAG;EAAC;EAAQ;EAAM;EAAkB;CAAkB,CAAC,GAEnD,MAAgB,OAAa,kBAAA,GAAA,CAAI,CAAA,IAGnC,kBAAC,GAAD;EACE,WAAW,eACT,IAAyB,mBAAmB;EAE9C,IAAI,EACF,UAAU,QACZ;YAEA,kBAAC,GAAD;GACE,WAAW;IAAE,IAAI;IAAU,IAAI;GAAM;GACrC,IAAI;IACF,gBAAgB;IAChB,KAAK;IACL,SAAS;GACX;aANF;IAQE,kBAAC,GAAD;KACE,WAAU;KACV,IAAI,EACF,KAAK,OACP;eAJF,CAME,kBAAC,GAAD;MACE,WAAU;MACV,IAAI;OACF,YAAY;OACZ,KAAK;MACP;gBALF,CAOE,kBAAC,GAAD,EAAsB,IAAI,EAAE,OAAO,WAAW,EAAI,CAAA,GAClD,kBAAC,GAAD;OAAY,SAAQ;iBAApB,CACG,EAAkB,kBAAkB,YACpC,CACS;QACP;SACP,kBAAC,GAAD;MACE,WAAW;OAAE,IAAI;OAAU,IAAI;MAAM;MACrC,IAAI;OACF,YAAY;QAAE,IAAI;QAAc,IAAI;OAAS;OAC7C,KAAK;MACP;gBALF,CAOG,KAAoB,KACnB,kBAAC,GAAD;OACE,WAAW;OACX,SAAQ;OACR,OAAM;OACN,IAAI;iBAEH,EAAiB;MACZ,CAAA,GAET,KAAsB,KACrB,kBAAC,GAAD;OAAQ,WAAW;OAAiB,IAAI;iBACrC,EAAmB;MACd,CAAA,CAEL;OACF;;IACP,kBAAC,GAAD,CAAU,CAAA;IAAC;IACX,kBAAC,GAAD;KACE,WAAU;KACV,IAAI;MACF,KAAK;OAAE,IAAI;OAAG,IAAI;MAAO;MACzB,YAAY;MACZ,gBAAgB;OAAE,IAAI;OAAgB,IAAI;MAAQ;MAClD,UAAU;OAAE,IAAI;OAAQ,IAAI;MAAS;KACvC;eAPF,CASE,kBAAC,GAAD,EAAU,GAAI,EAAc,CAAA,GAC3B,EAAM,KAAI,MAEP,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;MAAS,aAAY;MAAW,UAAA;KAAU,CAAA,GAC1C,kBAAC,GAAD,EAAU,GAAI,EAAO,CAAA,CACb,EAAA,GAHK,EAAK,KAGV,CAEb,CACI;;GACF;;CACJ,CAAA;AAET"}
@@ -12,7 +12,7 @@ import { forwardRef as r, useEffect as ce, useImperativeHandle as le, useMemo as
12
12
  import { Alert as o, Box as ue, Checkbox as de, FormControlLabel as s, Radio as c, RadioGroup as fe, Skeleton as l, Stack as pe, TextField as u, Tooltip as me, Typography as d } from "@mui/material";
13
13
  import { Fragment as f, jsx as p, jsxs as m } from "react/jsx-runtime";
14
14
  import { ACCESS_TYPE as h, JSON_SCHEMA_ACCESS_REQUIREMENT_CONCRETE_TYPE_VALUE as g, MANAGED_ACT_ACCESS_REQUIREMENT_CONCRETE_TYPE_VALUE as _, RestrictableObjectType as v, SELF_SIGN_ACCESS_REQUIREMENT_CONCRETE_TYPE_VALUE as y } from "@sage-bionetworks/synapse-types";
15
- import { HelpOutlineTwoTone as b } from "@mui/icons-material";
15
+ import b from "@mui/icons-material/HelpOutlineTwoTone";
16
16
  import x from "pluralize";
17
17
  //#region src/components/SetAccessRequirementCommonFields/SetAccessRequirementCommonFields.tsx
18
18
  var S = "Please select at least one resource for this Access Requirement to be associated with.", C = (e) => {
@@ -1 +1 @@
1
- {"version":3,"file":"SetAccessRequirementCommonFields.js","names":[],"sources":["../../../src/components/SetAccessRequirementCommonFields/SetAccessRequirementCommonFields.tsx"],"sourcesContent":["import {\n useCreateAccessRequirement,\n useGetAccessRequirements,\n useUpdateAccessRequirement,\n} from '@/synapse-queries'\nimport { spreadSx } from '@/theme/spreadSx'\nimport { HelpOutlineTwoTone } from '@mui/icons-material'\nimport {\n Alert,\n Box,\n Checkbox,\n FormControlLabel,\n Radio,\n RadioGroup,\n Skeleton,\n Stack,\n TextField,\n Tooltip,\n Typography,\n TypographyProps,\n} from '@mui/material'\nimport { SynapseClientError } from '@sage-bionetworks/synapse-client/util/SynapseClientError'\nimport {\n ACCESS_REQUIREMENT_CONCRETE_TYPE,\n ACCESS_TYPE,\n AccessRequirement,\n JSON_SCHEMA_ACCESS_REQUIREMENT_CONCRETE_TYPE_VALUE,\n MANAGED_ACT_ACCESS_REQUIREMENT_CONCRETE_TYPE_VALUE,\n RestrictableObjectDescriptor,\n RestrictableObjectType,\n SELF_SIGN_ACCESS_REQUIREMENT_CONCRETE_TYPE_VALUE,\n} from '@sage-bionetworks/synapse-types'\nimport pluralize from 'pluralize'\nimport { FormTemplateReference } from '@sage-bionetworks/synapse-client'\nimport { useGetFeatureFlag } from '@/synapse-queries/featureflags/useGetFeatureFlag'\nimport { FeatureFlagEnum } from '@/utils/featureflag/FeatureFlags'\nimport {\n FormTemplateReferenceField,\n useFormTemplateReferenceError,\n} from '../FormTemplateReferenceField/FormTemplateReferenceField'\nimport {\n ForwardedRef,\n forwardRef,\n useEffect,\n useImperativeHandle,\n useMemo,\n useState,\n} from 'react'\nimport EntitySubjectsSelector from '../EntitySubjectsSelector'\nimport { SynapseErrorBoundary } from '../error'\nimport TeamSubjectsSelector from '../TeamSubjectsSelector'\n\nexport const EMPTY_SUBJECT_LIST_ERROR_MESSAGE =\n 'Please select at least one resource for this Access Requirement to be associated with.'\nexport const UNSAVED_SUBJECTS_ERROR_MESSAGE = (\n subjectsType: RestrictableObjectType,\n) => {\n const idsText =\n subjectsType === RestrictableObjectType.ENTITY ? 'Synapse' : 'Team'\n const typeText =\n subjectsType[0].toUpperCase() + subjectsType.slice(1).toLowerCase()\n return `${idsText} IDs were specified but not added to the subjects list. Please either clear out the Add ${idsText} IDs textbox or click the Add ${pluralize(\n typeText,\n )} button.`\n}\nconst NAME_HELP_TEXT =\n \"Enter access requirement name. This will also be used when sending notifications for expiring or revoked approval. For example, 'The approval for the name access requirement was revoked...'\"\n\nconst headerProps: Partial<TypographyProps> = {\n variant: 'body1',\n fontWeight: 700,\n}\n\nfunction getAccessType(subjectType: RestrictableObjectType) {\n switch (subjectType) {\n case RestrictableObjectType.ENTITY:\n return ACCESS_TYPE.DOWNLOAD\n case RestrictableObjectType.TEAM:\n return ACCESS_TYPE.PARTICIPATE\n default:\n throw new Error(\n `RestrictableObjectType ${subjectType} does not have an access type specified.`,\n )\n }\n}\n\nexport type SetAccessRequirementCommonFieldsHandle = {\n /* Allow the parent component to trigger saving the AR, so this may be embedded in an arbitrary modal. */\n save: () => void\n}\n\nexport type SetAccessRequirementCommonFieldsProps = {\n /* Provided when creating a new AR */\n subject?: RestrictableObjectDescriptor\n /* Provided when editing an existing AR */\n accessRequirementId?: string\n /* Called when AR has been saved successfully */\n onSave: (\n accessRequirementId: string,\n accessRequirementConreteType: ACCESS_REQUIREMENT_CONCRETE_TYPE,\n ) => void\n /* Called when error saving AR */\n onError: () => void\n}\n\nexport const SetAccessRequirementCommonFields = forwardRef(\n function SetAccessRequirementCommonFields(\n props: SetAccessRequirementCommonFieldsProps,\n ref: ForwardedRef<SetAccessRequirementCommonFieldsHandle>,\n ) {\n const { subject, accessRequirementId, onSave, onError } = props\n\n const isEditing = !subject\n\n const [subjects, setSubjects] = useState<RestrictableObjectDescriptor[]>(\n subject ? [subject] : [],\n )\n const [hasPendingSubjects, setHasPendingSubjects] = useState<boolean>(false)\n const [subjectsError, setSubjectsError] = useState<string | null>(null)\n const [name, setName] = useState<string>('')\n const [subjectsDefinedByAnnotations, setSubjectsDefinedByAnnotations] =\n useState<boolean>(false)\n const [arType, setArType] = useState<ACCESS_REQUIREMENT_CONCRETE_TYPE>(\n subject?.type === RestrictableObjectType.TEAM\n ? SELF_SIGN_ACCESS_REQUIREMENT_CONCRETE_TYPE_VALUE\n : MANAGED_ACT_ACCESS_REQUIREMENT_CONCRETE_TYPE_VALUE,\n )\n const [clientError, setClientError] = useState<string | null>(null)\n const isSchemaDrivenEnabled = useGetFeatureFlag(\n FeatureFlagEnum.ACT_DASHBOARD_FORM_TEMPLATES,\n )\n const [formTemplateRef, setFormTemplateRef] = useState<\n FormTemplateReference | undefined\n >(undefined)\n const [showFormTemplateError, setShowFormTemplateError] =\n useState<boolean>(false)\n const isSchemaDrivenTypeSelected =\n isSchemaDrivenEnabled &&\n arType === JSON_SCHEMA_ACCESS_REQUIREMENT_CONCRETE_TYPE_VALUE\n const formTemplateReferenceError = useFormTemplateReferenceError(\n isSchemaDrivenTypeSelected ? formTemplateRef : undefined,\n )\n\n const onMutationSuccess = (ar: AccessRequirement) => {\n setClientError(null)\n onSave(ar.id.toString(), ar.concreteType)\n }\n\n const onMutationError = (error: SynapseClientError) => {\n setClientError(error.reason)\n onError()\n }\n\n const { mutate: createAccessRequirement } = useCreateAccessRequirement({\n onSuccess: newAr => onMutationSuccess(newAr),\n onError: error => onMutationError(error),\n })\n\n const { mutate: updateAccessRequirement } = useUpdateAccessRequirement({\n onSuccess: updatedAr => onMutationSuccess(updatedAr),\n onError: error => onMutationError(error),\n })\n\n const {\n data: accessRequirement,\n isLoading: isLoadingAr,\n error: getArError,\n } = useGetAccessRequirements(accessRequirementId!, {\n enabled: Boolean(accessRequirementId),\n })\n\n useEffect(() => {\n if (accessRequirement) {\n setArType(accessRequirement.concreteType)\n if (\n accessRequirement.concreteType ===\n JSON_SCHEMA_ACCESS_REQUIREMENT_CONCRETE_TYPE_VALUE\n ) {\n setFormTemplateRef(accessRequirement.formTemplateRef)\n }\n setName(accessRequirement.name)\n setSubjects(accessRequirement.subjectIds)\n setSubjectsDefinedByAnnotations(\n accessRequirement.subjectsDefinedByAnnotations,\n )\n }\n }, [accessRequirement])\n\n const subjectsType = useMemo(() => {\n if (subject) {\n return subject.type\n }\n if (accessRequirement) {\n const initialSubjects = accessRequirement.subjectIds\n if (initialSubjects.length > 0) {\n return initialSubjects[0].type\n }\n }\n if (subjectsDefinedByAnnotations) {\n return RestrictableObjectType.ENTITY\n }\n return null\n }, [subject, accessRequirement, subjectsDefinedByAnnotations])\n\n const selectorContent = useMemo(() => {\n if (!subjectsType) return <></>\n\n function onUpdate(subjects: RestrictableObjectDescriptor[]) {\n setSubjectsError(null)\n setSubjects(subjects)\n }\n\n function onUpdateIdsTextbox(value: string) {\n setSubjectsError(null)\n setHasPendingSubjects(value.trim() !== '')\n }\n\n if (subjectsDefinedByAnnotations) {\n return <></>\n }\n switch (subjectsType) {\n case RestrictableObjectType.TEAM:\n return (\n <TeamSubjectsSelector\n subjects={subjects}\n onUpdate={subjects => onUpdate(subjects)}\n onUpdateTeamIDsTextbox={value => onUpdateIdsTextbox(value)}\n />\n )\n case RestrictableObjectType.ENTITY:\n return (\n <EntitySubjectsSelector\n subjects={subjects}\n onUpdate={subjects => onUpdate(subjects)}\n onUpdateEntityIDsTextbox={value => onUpdateIdsTextbox(value)}\n />\n )\n default:\n console.error(\n `RestrictableObjectType ${subjectsType} does not have a selector implemented.`,\n )\n return <></>\n }\n }, [subjectsType, subjects, subjectsDefinedByAnnotations])\n\n useImperativeHandle(ref, () => {\n return {\n save() {\n const isStillLoading =\n (isEditing && !accessRequirement) || !subjectsType\n const hasSubjectsError =\n !subjectsDefinedByAnnotations &&\n (hasPendingSubjects || subjects.length === 0)\n if (isStillLoading || hasSubjectsError) {\n if (hasSubjectsError && !isStillLoading) {\n if (hasPendingSubjects) {\n setSubjectsError(UNSAVED_SUBJECTS_ERROR_MESSAGE(subjectsType))\n } else if (subjects.length === 0) {\n setSubjectsError(EMPTY_SUBJECT_LIST_ERROR_MESSAGE)\n }\n }\n\n onError()\n return\n }\n\n if (isSchemaDrivenTypeSelected && formTemplateReferenceError) {\n setShowFormTemplateError(true)\n onError()\n return\n }\n\n const newAccessType = getAccessType(subjectsType)\n if (!isEditing) {\n const newAr: Partial<AccessRequirement> = {\n concreteType: arType,\n subjectIds: subjects,\n name: name,\n accessType: newAccessType,\n subjectsDefinedByAnnotations: subjectsDefinedByAnnotations,\n ...(isSchemaDrivenTypeSelected ? { formTemplateRef } : {}),\n }\n createAccessRequirement(newAr)\n }\n\n if (isEditing && accessRequirement) {\n updateAccessRequirement({\n ...accessRequirement,\n subjectIds: subjects,\n name: name,\n accessType: newAccessType,\n subjectsDefinedByAnnotations: subjectsDefinedByAnnotations,\n ...(isSchemaDrivenTypeSelected ? { formTemplateRef } : {}),\n })\n }\n },\n }\n }, [\n hasPendingSubjects,\n subjectsType,\n subjects,\n name,\n arType,\n accessRequirement,\n isEditing,\n onError,\n createAccessRequirement,\n updateAccessRequirement,\n subjectsDefinedByAnnotations,\n isSchemaDrivenTypeSelected,\n formTemplateRef,\n formTemplateReferenceError,\n ])\n\n if (isLoadingAr || !subjectsType) {\n return (\n <>\n <Skeleton width={100} height={30} />\n <Skeleton width={125} height={30} />\n <Skeleton width=\"100%\">\n <TextField />\n </Skeleton>\n <Skeleton width={100} height={30} />\n <Skeleton width=\"100%\">\n <TextField />\n </Skeleton>\n </>\n )\n }\n\n if (getArError) {\n return <Alert severity=\"error\">{getArError.reason}</Alert>\n }\n\n return (\n <>\n <Typography {...headerProps}>Resources</Typography>\n {subjectsType !== RestrictableObjectType.TEAM && (\n <FormControlLabel\n control={<Checkbox />}\n label=\"Associated entities should be defined by annotations (DUO)\"\n checked={subjectsDefinedByAnnotations}\n onChange={() => {\n setSubjectsError(null)\n // if we are switching from DUO to manually defining the subjects (and the AR has been retrieved), then\n // reset to the AR subject IDs or the original subject ID. Otherwise, clear out the subjects.\n let newSubjectIds: RestrictableObjectDescriptor[] = []\n if (subjectsDefinedByAnnotations) {\n if (accessRequirement) {\n newSubjectIds = accessRequirement.subjectIds\n } else if (subject) {\n newSubjectIds = [subject]\n }\n }\n setSubjects(newSubjectIds)\n setSubjectsDefinedByAnnotations(!subjectsDefinedByAnnotations)\n }}\n />\n )}\n <SynapseErrorBoundary>{selectorContent}</SynapseErrorBoundary>\n {subjectsError && <Alert severity=\"error\">{subjectsError}</Alert>}\n <Stack\n direction=\"row\"\n sx={{\n gap: 1,\n alignItems: 'center',\n mb: 1,\n mt: 2,\n }}\n >\n <Typography component=\"label\" htmlFor=\"arName\" {...headerProps}>\n Name\n </Typography>\n <Tooltip title={NAME_HELP_TEXT} placement=\"right\">\n <HelpOutlineTwoTone sx={{ color: 'grey.600' }} />\n </Tooltip>\n </Stack>\n <TextField\n id=\"arName\"\n name=\"arName\"\n value={name}\n placeholder=\"Access requirement name\"\n fullWidth\n onChange={event => setName(event.target.value)}\n />\n {!isEditing && subjectsType !== RestrictableObjectType.TEAM && (\n <>\n <Typography\n {...headerProps}\n sx={spreadSx(\n {\n mt: 2,\n },\n headerProps.sx,\n )}\n >\n Access requirement type\n </Typography>\n <RadioGroup\n value={arType}\n onChange={(_event, value) =>\n setArType(value as ACCESS_REQUIREMENT_CONCRETE_TYPE)\n }\n >\n <FormControlLabel\n value={MANAGED_ACT_ACCESS_REQUIREMENT_CONCRETE_TYPE_VALUE}\n control={<Radio />}\n label=\"Controlled - requests are in Synapse\"\n />\n <FormControlLabel\n value={SELF_SIGN_ACCESS_REQUIREMENT_CONCRETE_TYPE_VALUE}\n control={<Radio />}\n label=\"Click wrap\"\n />\n {isSchemaDrivenEnabled && (\n <FormControlLabel\n value={JSON_SCHEMA_ACCESS_REQUIREMENT_CONCRETE_TYPE_VALUE}\n control={<Radio />}\n label=\"Schema-driven - requests are in Synapse, using a form template\"\n />\n )}\n </RadioGroup>\n </>\n )}\n {isSchemaDrivenTypeSelected && (\n <Box sx={{ mt: 2 }}>\n <Typography\n {...headerProps}\n sx={spreadSx({ mb: 1 }, headerProps.sx)}\n >\n Form presented to requesters\n </Typography>\n <FormTemplateReferenceField\n value={formTemplateRef}\n onChange={reference => {\n setShowFormTemplateError(false)\n setFormTemplateRef(reference)\n }}\n error={showFormTemplateError ? formTemplateReferenceError : null}\n />\n </Box>\n )}\n {clientError && (\n <Alert severity=\"error\" sx={{ marginTop: 2 }}>\n {clientError}\n </Alert>\n )}\n </>\n )\n },\n)\n"],"mappings":"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"}
1
+ {"version":3,"file":"SetAccessRequirementCommonFields.js","names":[],"sources":["../../../src/components/SetAccessRequirementCommonFields/SetAccessRequirementCommonFields.tsx"],"sourcesContent":["import {\n useCreateAccessRequirement,\n useGetAccessRequirements,\n useUpdateAccessRequirement,\n} from '@/synapse-queries'\nimport { spreadSx } from '@/theme/spreadSx'\nimport HelpOutlineTwoTone from '@mui/icons-material/HelpOutlineTwoTone'\nimport {\n Alert,\n Box,\n Checkbox,\n FormControlLabel,\n Radio,\n RadioGroup,\n Skeleton,\n Stack,\n TextField,\n Tooltip,\n Typography,\n TypographyProps,\n} from '@mui/material'\nimport { SynapseClientError } from '@sage-bionetworks/synapse-client/util/SynapseClientError'\nimport {\n ACCESS_REQUIREMENT_CONCRETE_TYPE,\n ACCESS_TYPE,\n AccessRequirement,\n JSON_SCHEMA_ACCESS_REQUIREMENT_CONCRETE_TYPE_VALUE,\n MANAGED_ACT_ACCESS_REQUIREMENT_CONCRETE_TYPE_VALUE,\n RestrictableObjectDescriptor,\n RestrictableObjectType,\n SELF_SIGN_ACCESS_REQUIREMENT_CONCRETE_TYPE_VALUE,\n} from '@sage-bionetworks/synapse-types'\nimport pluralize from 'pluralize'\nimport { FormTemplateReference } from '@sage-bionetworks/synapse-client'\nimport { useGetFeatureFlag } from '@/synapse-queries/featureflags/useGetFeatureFlag'\nimport { FeatureFlagEnum } from '@/utils/featureflag/FeatureFlags'\nimport {\n FormTemplateReferenceField,\n useFormTemplateReferenceError,\n} from '../FormTemplateReferenceField/FormTemplateReferenceField'\nimport {\n ForwardedRef,\n forwardRef,\n useEffect,\n useImperativeHandle,\n useMemo,\n useState,\n} from 'react'\nimport EntitySubjectsSelector from '../EntitySubjectsSelector'\nimport { SynapseErrorBoundary } from '../error'\nimport TeamSubjectsSelector from '../TeamSubjectsSelector'\n\nexport const EMPTY_SUBJECT_LIST_ERROR_MESSAGE =\n 'Please select at least one resource for this Access Requirement to be associated with.'\nexport const UNSAVED_SUBJECTS_ERROR_MESSAGE = (\n subjectsType: RestrictableObjectType,\n) => {\n const idsText =\n subjectsType === RestrictableObjectType.ENTITY ? 'Synapse' : 'Team'\n const typeText =\n subjectsType[0].toUpperCase() + subjectsType.slice(1).toLowerCase()\n return `${idsText} IDs were specified but not added to the subjects list. Please either clear out the Add ${idsText} IDs textbox or click the Add ${pluralize(\n typeText,\n )} button.`\n}\nconst NAME_HELP_TEXT =\n \"Enter access requirement name. This will also be used when sending notifications for expiring or revoked approval. For example, 'The approval for the name access requirement was revoked...'\"\n\nconst headerProps: Partial<TypographyProps> = {\n variant: 'body1',\n fontWeight: 700,\n}\n\nfunction getAccessType(subjectType: RestrictableObjectType) {\n switch (subjectType) {\n case RestrictableObjectType.ENTITY:\n return ACCESS_TYPE.DOWNLOAD\n case RestrictableObjectType.TEAM:\n return ACCESS_TYPE.PARTICIPATE\n default:\n throw new Error(\n `RestrictableObjectType ${subjectType} does not have an access type specified.`,\n )\n }\n}\n\nexport type SetAccessRequirementCommonFieldsHandle = {\n /* Allow the parent component to trigger saving the AR, so this may be embedded in an arbitrary modal. */\n save: () => void\n}\n\nexport type SetAccessRequirementCommonFieldsProps = {\n /* Provided when creating a new AR */\n subject?: RestrictableObjectDescriptor\n /* Provided when editing an existing AR */\n accessRequirementId?: string\n /* Called when AR has been saved successfully */\n onSave: (\n accessRequirementId: string,\n accessRequirementConreteType: ACCESS_REQUIREMENT_CONCRETE_TYPE,\n ) => void\n /* Called when error saving AR */\n onError: () => void\n}\n\nexport const SetAccessRequirementCommonFields = forwardRef(\n function SetAccessRequirementCommonFields(\n props: SetAccessRequirementCommonFieldsProps,\n ref: ForwardedRef<SetAccessRequirementCommonFieldsHandle>,\n ) {\n const { subject, accessRequirementId, onSave, onError } = props\n\n const isEditing = !subject\n\n const [subjects, setSubjects] = useState<RestrictableObjectDescriptor[]>(\n subject ? [subject] : [],\n )\n const [hasPendingSubjects, setHasPendingSubjects] = useState<boolean>(false)\n const [subjectsError, setSubjectsError] = useState<string | null>(null)\n const [name, setName] = useState<string>('')\n const [subjectsDefinedByAnnotations, setSubjectsDefinedByAnnotations] =\n useState<boolean>(false)\n const [arType, setArType] = useState<ACCESS_REQUIREMENT_CONCRETE_TYPE>(\n subject?.type === RestrictableObjectType.TEAM\n ? SELF_SIGN_ACCESS_REQUIREMENT_CONCRETE_TYPE_VALUE\n : MANAGED_ACT_ACCESS_REQUIREMENT_CONCRETE_TYPE_VALUE,\n )\n const [clientError, setClientError] = useState<string | null>(null)\n const isSchemaDrivenEnabled = useGetFeatureFlag(\n FeatureFlagEnum.ACT_DASHBOARD_FORM_TEMPLATES,\n )\n const [formTemplateRef, setFormTemplateRef] = useState<\n FormTemplateReference | undefined\n >(undefined)\n const [showFormTemplateError, setShowFormTemplateError] =\n useState<boolean>(false)\n const isSchemaDrivenTypeSelected =\n isSchemaDrivenEnabled &&\n arType === JSON_SCHEMA_ACCESS_REQUIREMENT_CONCRETE_TYPE_VALUE\n const formTemplateReferenceError = useFormTemplateReferenceError(\n isSchemaDrivenTypeSelected ? formTemplateRef : undefined,\n )\n\n const onMutationSuccess = (ar: AccessRequirement) => {\n setClientError(null)\n onSave(ar.id.toString(), ar.concreteType)\n }\n\n const onMutationError = (error: SynapseClientError) => {\n setClientError(error.reason)\n onError()\n }\n\n const { mutate: createAccessRequirement } = useCreateAccessRequirement({\n onSuccess: newAr => onMutationSuccess(newAr),\n onError: error => onMutationError(error),\n })\n\n const { mutate: updateAccessRequirement } = useUpdateAccessRequirement({\n onSuccess: updatedAr => onMutationSuccess(updatedAr),\n onError: error => onMutationError(error),\n })\n\n const {\n data: accessRequirement,\n isLoading: isLoadingAr,\n error: getArError,\n } = useGetAccessRequirements(accessRequirementId!, {\n enabled: Boolean(accessRequirementId),\n })\n\n useEffect(() => {\n if (accessRequirement) {\n setArType(accessRequirement.concreteType)\n if (\n accessRequirement.concreteType ===\n JSON_SCHEMA_ACCESS_REQUIREMENT_CONCRETE_TYPE_VALUE\n ) {\n setFormTemplateRef(accessRequirement.formTemplateRef)\n }\n setName(accessRequirement.name)\n setSubjects(accessRequirement.subjectIds)\n setSubjectsDefinedByAnnotations(\n accessRequirement.subjectsDefinedByAnnotations,\n )\n }\n }, [accessRequirement])\n\n const subjectsType = useMemo(() => {\n if (subject) {\n return subject.type\n }\n if (accessRequirement) {\n const initialSubjects = accessRequirement.subjectIds\n if (initialSubjects.length > 0) {\n return initialSubjects[0].type\n }\n }\n if (subjectsDefinedByAnnotations) {\n return RestrictableObjectType.ENTITY\n }\n return null\n }, [subject, accessRequirement, subjectsDefinedByAnnotations])\n\n const selectorContent = useMemo(() => {\n if (!subjectsType) return <></>\n\n function onUpdate(subjects: RestrictableObjectDescriptor[]) {\n setSubjectsError(null)\n setSubjects(subjects)\n }\n\n function onUpdateIdsTextbox(value: string) {\n setSubjectsError(null)\n setHasPendingSubjects(value.trim() !== '')\n }\n\n if (subjectsDefinedByAnnotations) {\n return <></>\n }\n switch (subjectsType) {\n case RestrictableObjectType.TEAM:\n return (\n <TeamSubjectsSelector\n subjects={subjects}\n onUpdate={subjects => onUpdate(subjects)}\n onUpdateTeamIDsTextbox={value => onUpdateIdsTextbox(value)}\n />\n )\n case RestrictableObjectType.ENTITY:\n return (\n <EntitySubjectsSelector\n subjects={subjects}\n onUpdate={subjects => onUpdate(subjects)}\n onUpdateEntityIDsTextbox={value => onUpdateIdsTextbox(value)}\n />\n )\n default:\n console.error(\n `RestrictableObjectType ${subjectsType} does not have a selector implemented.`,\n )\n return <></>\n }\n }, [subjectsType, subjects, subjectsDefinedByAnnotations])\n\n useImperativeHandle(ref, () => {\n return {\n save() {\n const isStillLoading =\n (isEditing && !accessRequirement) || !subjectsType\n const hasSubjectsError =\n !subjectsDefinedByAnnotations &&\n (hasPendingSubjects || subjects.length === 0)\n if (isStillLoading || hasSubjectsError) {\n if (hasSubjectsError && !isStillLoading) {\n if (hasPendingSubjects) {\n setSubjectsError(UNSAVED_SUBJECTS_ERROR_MESSAGE(subjectsType))\n } else if (subjects.length === 0) {\n setSubjectsError(EMPTY_SUBJECT_LIST_ERROR_MESSAGE)\n }\n }\n\n onError()\n return\n }\n\n if (isSchemaDrivenTypeSelected && formTemplateReferenceError) {\n setShowFormTemplateError(true)\n onError()\n return\n }\n\n const newAccessType = getAccessType(subjectsType)\n if (!isEditing) {\n const newAr: Partial<AccessRequirement> = {\n concreteType: arType,\n subjectIds: subjects,\n name: name,\n accessType: newAccessType,\n subjectsDefinedByAnnotations: subjectsDefinedByAnnotations,\n ...(isSchemaDrivenTypeSelected ? { formTemplateRef } : {}),\n }\n createAccessRequirement(newAr)\n }\n\n if (isEditing && accessRequirement) {\n updateAccessRequirement({\n ...accessRequirement,\n subjectIds: subjects,\n name: name,\n accessType: newAccessType,\n subjectsDefinedByAnnotations: subjectsDefinedByAnnotations,\n ...(isSchemaDrivenTypeSelected ? { formTemplateRef } : {}),\n })\n }\n },\n }\n }, [\n hasPendingSubjects,\n subjectsType,\n subjects,\n name,\n arType,\n accessRequirement,\n isEditing,\n onError,\n createAccessRequirement,\n updateAccessRequirement,\n subjectsDefinedByAnnotations,\n isSchemaDrivenTypeSelected,\n formTemplateRef,\n formTemplateReferenceError,\n ])\n\n if (isLoadingAr || !subjectsType) {\n return (\n <>\n <Skeleton width={100} height={30} />\n <Skeleton width={125} height={30} />\n <Skeleton width=\"100%\">\n <TextField />\n </Skeleton>\n <Skeleton width={100} height={30} />\n <Skeleton width=\"100%\">\n <TextField />\n </Skeleton>\n </>\n )\n }\n\n if (getArError) {\n return <Alert severity=\"error\">{getArError.reason}</Alert>\n }\n\n return (\n <>\n <Typography {...headerProps}>Resources</Typography>\n {subjectsType !== RestrictableObjectType.TEAM && (\n <FormControlLabel\n control={<Checkbox />}\n label=\"Associated entities should be defined by annotations (DUO)\"\n checked={subjectsDefinedByAnnotations}\n onChange={() => {\n setSubjectsError(null)\n // if we are switching from DUO to manually defining the subjects (and the AR has been retrieved), then\n // reset to the AR subject IDs or the original subject ID. Otherwise, clear out the subjects.\n let newSubjectIds: RestrictableObjectDescriptor[] = []\n if (subjectsDefinedByAnnotations) {\n if (accessRequirement) {\n newSubjectIds = accessRequirement.subjectIds\n } else if (subject) {\n newSubjectIds = [subject]\n }\n }\n setSubjects(newSubjectIds)\n setSubjectsDefinedByAnnotations(!subjectsDefinedByAnnotations)\n }}\n />\n )}\n <SynapseErrorBoundary>{selectorContent}</SynapseErrorBoundary>\n {subjectsError && <Alert severity=\"error\">{subjectsError}</Alert>}\n <Stack\n direction=\"row\"\n sx={{\n gap: 1,\n alignItems: 'center',\n mb: 1,\n mt: 2,\n }}\n >\n <Typography component=\"label\" htmlFor=\"arName\" {...headerProps}>\n Name\n </Typography>\n <Tooltip title={NAME_HELP_TEXT} placement=\"right\">\n <HelpOutlineTwoTone sx={{ color: 'grey.600' }} />\n </Tooltip>\n </Stack>\n <TextField\n id=\"arName\"\n name=\"arName\"\n value={name}\n placeholder=\"Access requirement name\"\n fullWidth\n onChange={event => setName(event.target.value)}\n />\n {!isEditing && subjectsType !== RestrictableObjectType.TEAM && (\n <>\n <Typography\n {...headerProps}\n sx={spreadSx(\n {\n mt: 2,\n },\n headerProps.sx,\n )}\n >\n Access requirement type\n </Typography>\n <RadioGroup\n value={arType}\n onChange={(_event, value) =>\n setArType(value as ACCESS_REQUIREMENT_CONCRETE_TYPE)\n }\n >\n <FormControlLabel\n value={MANAGED_ACT_ACCESS_REQUIREMENT_CONCRETE_TYPE_VALUE}\n control={<Radio />}\n label=\"Controlled - requests are in Synapse\"\n />\n <FormControlLabel\n value={SELF_SIGN_ACCESS_REQUIREMENT_CONCRETE_TYPE_VALUE}\n control={<Radio />}\n label=\"Click wrap\"\n />\n {isSchemaDrivenEnabled && (\n <FormControlLabel\n value={JSON_SCHEMA_ACCESS_REQUIREMENT_CONCRETE_TYPE_VALUE}\n control={<Radio />}\n label=\"Schema-driven - requests are in Synapse, using a form template\"\n />\n )}\n </RadioGroup>\n </>\n )}\n {isSchemaDrivenTypeSelected && (\n <Box sx={{ mt: 2 }}>\n <Typography\n {...headerProps}\n sx={spreadSx({ mb: 1 }, headerProps.sx)}\n >\n Form presented to requesters\n </Typography>\n <FormTemplateReferenceField\n value={formTemplateRef}\n onChange={reference => {\n setShowFormTemplateError(false)\n setFormTemplateRef(reference)\n }}\n error={showFormTemplateError ? formTemplateReferenceError : null}\n />\n </Box>\n )}\n {clientError && (\n <Alert severity=\"error\" sx={{ marginTop: 2 }}>\n {clientError}\n </Alert>\n )}\n </>\n )\n },\n)\n"],"mappings":"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"}
@@ -5,8 +5,8 @@ import { useCreateShortUrl as r } from "../../utils/hooks/useCreateShortUrl.js";
5
5
  import { useEffect as i, useState as a } from "react";
6
6
  import { Box as o, Dialog as s, DialogContent as c, DialogTitle as l, IconButton as u, Input as d, Typography as f } from "@mui/material";
7
7
  import { jsx as p, jsxs as m } from "react/jsx-runtime";
8
- import { ShareTwoTone as h } from "@mui/icons-material";
9
- import g from "@mui/icons-material/Close";
8
+ import h from "@mui/icons-material/Close";
9
+ import g from "@mui/icons-material/ShareTwoTone";
10
10
  import { BlueskyIcon as _, BlueskyShareButton as v, LinkedinIcon as y, LinkedinShareButton as b, TwitterShareButton as x, XIcon as S } from "react-share";
11
11
  //#region src/components/ShareThisPage/ShareThisPage.tsx
12
12
  var C = ({ shortIoPublicApiKey: C, domain: w = "sageb.io", renderAs: T = "button", open: E, onClose: D }) => {
@@ -28,7 +28,7 @@ var C = ({ shortIoPublicApiKey: C, domain: w = "sageb.io", renderAs: T = "button
28
28
  N && I();
29
29
  }, [N, I]), /* @__PURE__ */ m("div", { children: [T === "button" && /* @__PURE__ */ p(e, {
30
30
  variant: "outlined",
31
- startIcon: /* @__PURE__ */ p(h, { className: n.shareIcon }),
31
+ startIcon: /* @__PURE__ */ p(g, { className: n.shareIcon }),
32
32
  onClick: P,
33
33
  children: "Share"
34
34
  }), /* @__PURE__ */ m(s, {
@@ -41,7 +41,7 @@ var C = ({ shortIoPublicApiKey: C, domain: w = "sageb.io", renderAs: T = "button
41
41
  children: ["Share this page", /* @__PURE__ */ p(u, {
42
42
  onClick: F,
43
43
  size: "small",
44
- children: /* @__PURE__ */ p(g, { className: n.closeIcon })
44
+ children: /* @__PURE__ */ p(h, { className: n.closeIcon })
45
45
  })]
46
46
  }), /* @__PURE__ */ p(c, {
47
47
  className: n.dialogContent,
@@ -1 +1 @@
1
- {"version":3,"file":"ShareThisPage.js","names":[],"sources":["../../../src/components/ShareThisPage/ShareThisPage.tsx"],"sourcesContent":["import {\n Dialog,\n DialogTitle,\n DialogContent,\n IconButton,\n Typography,\n Input,\n Box,\n} from '@mui/material'\nimport GenericCardActionButton from '../GenericCard/GenericCardActionButton'\nimport React from 'react'\nimport { useEffect, useState } from 'react'\nimport CloseIcon from '@mui/icons-material/Close'\nimport CopyToClipboardIcon from '../CopyToClipboardIcon'\nimport {\n LinkedinShareButton,\n LinkedinIcon,\n TwitterShareButton,\n BlueskyShareButton,\n BlueskyIcon,\n XIcon,\n} from 'react-share'\nimport styles from './ShareThisPage.module.scss'\nimport { ShareTwoTone } from '@mui/icons-material'\nimport { useCreateShortUrl } from '../../utils/hooks/useCreateShortUrl'\n\nexport type ShareThisPageProps = {\n shortIoPublicApiKey?: string\n domain?: string\n renderAs?: 'button' | 'icon'\n open?: boolean\n onClose?: () => void\n}\n\nconst ShareThisPage = ({\n shortIoPublicApiKey,\n domain = 'sageb.io',\n renderAs = 'button',\n open: externalOpen,\n onClose: externalOnClose,\n}: ShareThisPageProps): React.ReactNode => {\n const [url, setUrl] = useState('')\n const [internalOpen, setInternalOpen] = useState(false)\n\n // Use internal state if externalOpen is undefined\n // Otherwise, the open state is controlled externally by externalOpen\n const isControlled = externalOpen === undefined\n const open = isControlled ? internalOpen : externalOpen\n\n const handleOpen = () => {\n if (isControlled) {\n setInternalOpen(true)\n }\n }\n\n const handleClose = () => {\n if (isControlled) {\n setInternalOpen(false)\n }\n if (externalOnClose) {\n externalOnClose()\n }\n }\n\n const { mutate: createShortUrl, isPending } = useCreateShortUrl({\n shortIoPublicApiKey,\n domain,\n onSuccess: data => {\n setUrl(data)\n },\n onError: error => {\n console.error(error)\n setUrl(window.location.href)\n },\n })\n\n useEffect(() => {\n if (open) {\n createShortUrl()\n }\n }, [open, createShortUrl])\n\n return (\n <div>\n {renderAs === 'button' && (\n <GenericCardActionButton\n variant=\"outlined\"\n startIcon={<ShareTwoTone className={styles.shareIcon} />}\n onClick={handleOpen}\n >\n Share\n </GenericCardActionButton>\n )}\n\n <Dialog\n open={open}\n onClose={handleClose}\n maxWidth=\"xs\"\n className={styles.dialogPaper}\n >\n <DialogTitle className={styles.dialogTitle}>\n Share this page\n <IconButton onClick={handleClose} size=\"small\">\n <CloseIcon className={styles.closeIcon} />\n </IconButton>\n </DialogTitle>\n\n <DialogContent className={styles.dialogContent}>\n <Box className={styles.contentStack}>\n <div className={styles.shareButtonsContainer}>\n <LinkedinShareButton url={url} aria-label=\"Share on LinkedIn\">\n <div className={styles.shareItem}>\n <LinkedinIcon size={48} round />\n <Typography variant=\"body1\" className={styles.shareItemLabel}>\n LinkedIn\n </Typography>\n </div>\n </LinkedinShareButton>\n\n <TwitterShareButton url={url} aria-label=\"Share on X\">\n <div className={styles.shareItem}>\n <XIcon size={48} round />\n <Typography variant=\"body1\" className={styles.shareItemLabel}>\n X\n </Typography>\n </div>\n </TwitterShareButton>\n\n <BlueskyShareButton url={url} aria-label=\"Share on Bluesky\">\n <div className={styles.shareItem}>\n <BlueskyIcon size={48} round />\n <Typography variant=\"body1\" className={styles.shareItemLabel}>\n Bluesky\n </Typography>\n </div>\n </BlueskyShareButton>\n </div>\n\n <div className={styles.copySection}>\n <Typography className={styles.copyLabel}>Page Link</Typography>\n <div className={styles.copyRow}>\n <Input\n className={styles.urlInput}\n value={url}\n readOnly\n aria-label=\"Page URL\"\n placeholder={isPending ? 'Generating link...' : ''}\n />\n <CopyToClipboardIcon\n value={url}\n sizePx={24}\n className={styles.copyButton}\n />\n </div>\n </div>\n </Box>\n </DialogContent>\n </Dialog>\n </div>\n )\n}\n\nexport default ShareThisPage\n"],"mappings":";;;;;;;;;;;AAkCA,IAAM,KAAiB,EACrB,wBACA,YAAS,YACT,cAAW,UACX,MAAM,GACN,SAAS,QACgC;CACzC,IAAM,CAAC,GAAK,KAAU,EAAS,EAAE,GAC3B,CAAC,GAAc,KAAmB,EAAS,EAAK,GAIhD,IAAe,MAAiB,KAAA,GAChC,IAAO,IAAe,IAAe,GAErC,UAAmB;EACvB,AAAI,KACF,EAAgB,EAAI;CAExB,GAEM,UAAoB;EAIxB,AAHI,KACF,EAAgB,EAAK,GAEnB,KACF,EAAgB;CAEpB,GAEM,EAAE,QAAQ,GAAgB,iBAAc,EAAkB;EAC9D;EACA;EACA,YAAW,MAAQ;GACjB,EAAO,CAAI;EACb;EACA,UAAS,MAAS;GAEhB,AADA,QAAQ,MAAM,CAAK,GACnB,EAAO,OAAO,SAAS,IAAI;EAC7B;CACF,CAAC;CAQD,OANA,QAAgB;EACd,AAAI,KACF,EAAe;CAEnB,GAAG,CAAC,GAAM,CAAc,CAAC,GAGvB,kBAAC,OAAD,EAAA,UAAA,CACG,MAAa,YACZ,kBAAC,GAAD;EACE,SAAQ;EACR,WAAW,kBAAC,GAAD,EAAc,WAAW,EAAO,UAAY,CAAA;EACvD,SAAS;YACV;CAEwB,CAAA,GAG3B,kBAAC,GAAD;EACQ;EACN,SAAS;EACT,UAAS;EACT,WAAW,EAAO;YAJpB,CAME,kBAAC,GAAD;GAAa,WAAW,EAAO;aAA/B,CAA4C,mBAE1C,kBAAC,GAAD;IAAY,SAAS;IAAa,MAAK;cACrC,kBAAC,GAAD,EAAW,WAAW,EAAO,UAAY,CAAA;GAC/B,CAAA,CACD;MAEb,kBAAC,GAAD;GAAe,WAAW,EAAO;aAC/B,kBAAC,GAAD;IAAK,WAAW,EAAO;cAAvB,CACE,kBAAC,OAAD;KAAK,WAAW,EAAO;eAAvB;MACE,kBAAC,GAAD;OAA0B;OAAK,cAAW;iBACxC,kBAAC,OAAD;QAAK,WAAW,EAAO;kBAAvB,CACE,kBAAC,GAAD;SAAc,MAAM;SAAI,OAAA;QAAO,CAAA,GAC/B,kBAAC,GAAD;SAAY,SAAQ;SAAQ,WAAW,EAAO;mBAAgB;QAElD,CAAA,CACT;;MACc,CAAA;MAErB,kBAAC,GAAD;OAAyB;OAAK,cAAW;iBACvC,kBAAC,OAAD;QAAK,WAAW,EAAO;kBAAvB,CACE,kBAAC,GAAD;SAAO,MAAM;SAAI,OAAA;QAAO,CAAA,GACxB,kBAAC,GAAD;SAAY,SAAQ;SAAQ,WAAW,EAAO;mBAAgB;QAElD,CAAA,CACT;;MACa,CAAA;MAEpB,kBAAC,GAAD;OAAyB;OAAK,cAAW;iBACvC,kBAAC,OAAD;QAAK,WAAW,EAAO;kBAAvB,CACE,kBAAC,GAAD;SAAa,MAAM;SAAI,OAAA;QAAO,CAAA,GAC9B,kBAAC,GAAD;SAAY,SAAQ;SAAQ,WAAW,EAAO;mBAAgB;QAElD,CAAA,CACT;;MACa,CAAA;KACjB;QAEL,kBAAC,OAAD;KAAK,WAAW,EAAO;eAAvB,CACE,kBAAC,GAAD;MAAY,WAAW,EAAO;gBAAW;KAAqB,CAAA,GAC9D,kBAAC,OAAD;MAAK,WAAW,EAAO;gBAAvB,CACE,kBAAC,GAAD;OACE,WAAW,EAAO;OAClB,OAAO;OACP,UAAA;OACA,cAAW;OACX,aAAa,IAAY,uBAAuB;MACjD,CAAA,GACD,kBAAC,GAAD;OACE,OAAO;OACP,QAAQ;OACR,WAAW,EAAO;MACnB,CAAA,CACE;OACF;MACF;;EACQ,CAAA,CACT;GACL,EAAA,CAAA;AAET"}
1
+ {"version":3,"file":"ShareThisPage.js","names":[],"sources":["../../../src/components/ShareThisPage/ShareThisPage.tsx"],"sourcesContent":["import {\n Dialog,\n DialogTitle,\n DialogContent,\n IconButton,\n Typography,\n Input,\n Box,\n} from '@mui/material'\nimport GenericCardActionButton from '../GenericCard/GenericCardActionButton'\nimport React from 'react'\nimport { useEffect, useState } from 'react'\nimport CloseIcon from '@mui/icons-material/Close'\nimport CopyToClipboardIcon from '../CopyToClipboardIcon'\nimport {\n LinkedinShareButton,\n LinkedinIcon,\n TwitterShareButton,\n BlueskyShareButton,\n BlueskyIcon,\n XIcon,\n} from 'react-share'\nimport styles from './ShareThisPage.module.scss'\nimport ShareTwoTone from '@mui/icons-material/ShareTwoTone'\nimport { useCreateShortUrl } from '../../utils/hooks/useCreateShortUrl'\n\nexport type ShareThisPageProps = {\n shortIoPublicApiKey?: string\n domain?: string\n renderAs?: 'button' | 'icon'\n open?: boolean\n onClose?: () => void\n}\n\nconst ShareThisPage = ({\n shortIoPublicApiKey,\n domain = 'sageb.io',\n renderAs = 'button',\n open: externalOpen,\n onClose: externalOnClose,\n}: ShareThisPageProps): React.ReactNode => {\n const [url, setUrl] = useState('')\n const [internalOpen, setInternalOpen] = useState(false)\n\n // Use internal state if externalOpen is undefined\n // Otherwise, the open state is controlled externally by externalOpen\n const isControlled = externalOpen === undefined\n const open = isControlled ? internalOpen : externalOpen\n\n const handleOpen = () => {\n if (isControlled) {\n setInternalOpen(true)\n }\n }\n\n const handleClose = () => {\n if (isControlled) {\n setInternalOpen(false)\n }\n if (externalOnClose) {\n externalOnClose()\n }\n }\n\n const { mutate: createShortUrl, isPending } = useCreateShortUrl({\n shortIoPublicApiKey,\n domain,\n onSuccess: data => {\n setUrl(data)\n },\n onError: error => {\n console.error(error)\n setUrl(window.location.href)\n },\n })\n\n useEffect(() => {\n if (open) {\n createShortUrl()\n }\n }, [open, createShortUrl])\n\n return (\n <div>\n {renderAs === 'button' && (\n <GenericCardActionButton\n variant=\"outlined\"\n startIcon={<ShareTwoTone className={styles.shareIcon} />}\n onClick={handleOpen}\n >\n Share\n </GenericCardActionButton>\n )}\n\n <Dialog\n open={open}\n onClose={handleClose}\n maxWidth=\"xs\"\n className={styles.dialogPaper}\n >\n <DialogTitle className={styles.dialogTitle}>\n Share this page\n <IconButton onClick={handleClose} size=\"small\">\n <CloseIcon className={styles.closeIcon} />\n </IconButton>\n </DialogTitle>\n\n <DialogContent className={styles.dialogContent}>\n <Box className={styles.contentStack}>\n <div className={styles.shareButtonsContainer}>\n <LinkedinShareButton url={url} aria-label=\"Share on LinkedIn\">\n <div className={styles.shareItem}>\n <LinkedinIcon size={48} round />\n <Typography variant=\"body1\" className={styles.shareItemLabel}>\n LinkedIn\n </Typography>\n </div>\n </LinkedinShareButton>\n\n <TwitterShareButton url={url} aria-label=\"Share on X\">\n <div className={styles.shareItem}>\n <XIcon size={48} round />\n <Typography variant=\"body1\" className={styles.shareItemLabel}>\n X\n </Typography>\n </div>\n </TwitterShareButton>\n\n <BlueskyShareButton url={url} aria-label=\"Share on Bluesky\">\n <div className={styles.shareItem}>\n <BlueskyIcon size={48} round />\n <Typography variant=\"body1\" className={styles.shareItemLabel}>\n Bluesky\n </Typography>\n </div>\n </BlueskyShareButton>\n </div>\n\n <div className={styles.copySection}>\n <Typography className={styles.copyLabel}>Page Link</Typography>\n <div className={styles.copyRow}>\n <Input\n className={styles.urlInput}\n value={url}\n readOnly\n aria-label=\"Page URL\"\n placeholder={isPending ? 'Generating link...' : ''}\n />\n <CopyToClipboardIcon\n value={url}\n sizePx={24}\n className={styles.copyButton}\n />\n </div>\n </div>\n </Box>\n </DialogContent>\n </Dialog>\n </div>\n )\n}\n\nexport default ShareThisPage\n"],"mappings":";;;;;;;;;;;AAkCA,IAAM,KAAiB,EACrB,wBACA,YAAS,YACT,cAAW,UACX,MAAM,GACN,SAAS,QACgC;CACzC,IAAM,CAAC,GAAK,KAAU,EAAS,EAAE,GAC3B,CAAC,GAAc,KAAmB,EAAS,EAAK,GAIhD,IAAe,MAAiB,KAAA,GAChC,IAAO,IAAe,IAAe,GAErC,UAAmB;EACvB,AAAI,KACF,EAAgB,EAAI;CAExB,GAEM,UAAoB;EAIxB,AAHI,KACF,EAAgB,EAAK,GAEnB,KACF,EAAgB;CAEpB,GAEM,EAAE,QAAQ,GAAgB,iBAAc,EAAkB;EAC9D;EACA;EACA,YAAW,MAAQ;GACjB,EAAO,CAAI;EACb;EACA,UAAS,MAAS;GAEhB,AADA,QAAQ,MAAM,CAAK,GACnB,EAAO,OAAO,SAAS,IAAI;EAC7B;CACF,CAAC;CAQD,OANA,QAAgB;EACd,AAAI,KACF,EAAe;CAEnB,GAAG,CAAC,GAAM,CAAc,CAAC,GAGvB,kBAAC,OAAD,EAAA,UAAA,CACG,MAAa,YACZ,kBAAC,GAAD;EACE,SAAQ;EACR,WAAW,kBAAC,GAAD,EAAc,WAAW,EAAO,UAAY,CAAA;EACvD,SAAS;YACV;CAEwB,CAAA,GAG3B,kBAAC,GAAD;EACQ;EACN,SAAS;EACT,UAAS;EACT,WAAW,EAAO;YAJpB,CAME,kBAAC,GAAD;GAAa,WAAW,EAAO;aAA/B,CAA4C,mBAE1C,kBAAC,GAAD;IAAY,SAAS;IAAa,MAAK;cACrC,kBAAC,GAAD,EAAW,WAAW,EAAO,UAAY,CAAA;GAC/B,CAAA,CACD;MAEb,kBAAC,GAAD;GAAe,WAAW,EAAO;aAC/B,kBAAC,GAAD;IAAK,WAAW,EAAO;cAAvB,CACE,kBAAC,OAAD;KAAK,WAAW,EAAO;eAAvB;MACE,kBAAC,GAAD;OAA0B;OAAK,cAAW;iBACxC,kBAAC,OAAD;QAAK,WAAW,EAAO;kBAAvB,CACE,kBAAC,GAAD;SAAc,MAAM;SAAI,OAAA;QAAO,CAAA,GAC/B,kBAAC,GAAD;SAAY,SAAQ;SAAQ,WAAW,EAAO;mBAAgB;QAElD,CAAA,CACT;;MACc,CAAA;MAErB,kBAAC,GAAD;OAAyB;OAAK,cAAW;iBACvC,kBAAC,OAAD;QAAK,WAAW,EAAO;kBAAvB,CACE,kBAAC,GAAD;SAAO,MAAM;SAAI,OAAA;QAAO,CAAA,GACxB,kBAAC,GAAD;SAAY,SAAQ;SAAQ,WAAW,EAAO;mBAAgB;QAElD,CAAA,CACT;;MACa,CAAA;MAEpB,kBAAC,GAAD;OAAyB;OAAK,cAAW;iBACvC,kBAAC,OAAD;QAAK,WAAW,EAAO;kBAAvB,CACE,kBAAC,GAAD;SAAa,MAAM;SAAI,OAAA;QAAO,CAAA,GAC9B,kBAAC,GAAD;SAAY,SAAQ;SAAQ,WAAW,EAAO;mBAAgB;QAElD,CAAA,CACT;;MACa,CAAA;KACjB;QAEL,kBAAC,OAAD;KAAK,WAAW,EAAO;eAAvB,CACE,kBAAC,GAAD;MAAY,WAAW,EAAO;gBAAW;KAAqB,CAAA,GAC9D,kBAAC,OAAD;MAAK,WAAW,EAAO;gBAAvB,CACE,kBAAC,GAAD;OACE,WAAW,EAAO;OAClB,OAAO;OACP,UAAA;OACA,cAAW;OACX,aAAa,IAAY,uBAAuB;MACjD,CAAA,GACD,kBAAC,GAAD;OACE,OAAO;OACP,QAAQ;OACR,WAAW,EAAO;MACnB,CAAA,CACE;OACF;MACF;;EACQ,CAAA,CACT;GACL,EAAA,CAAA;AAET"}
@@ -1,7 +1,7 @@
1
1
  import "react";
2
2
  import { Box as e, Stack as t, Tooltip as n, Typography as r } from "@mui/material";
3
3
  import { jsx as i, jsxs as a } from "react/jsx-runtime";
4
- import { InfoTwoTone as o } from "@mui/icons-material";
4
+ import o from "@mui/icons-material/InfoTwoTone";
5
5
  //#region src/components/SustainabilityScorecard/DialLayout.tsx
6
6
  var s = ({ dial: s, label: c, toolTipText: l }) => /* @__PURE__ */ a(t, {
7
7
  sx: {
@@ -1 +1 @@
1
- {"version":3,"file":"DialLayout.js","names":[],"sources":["../../../src/components/SustainabilityScorecard/DialLayout.tsx"],"sourcesContent":["import React from 'react'\nimport { Box, Stack, Tooltip, Typography } from '@mui/material'\nimport { InfoTwoTone } from '@mui/icons-material'\nimport { ReactElement } from 'react'\nimport { ScoreDescriptor } from './Dial'\n\nexport type DialLayoutProps = {\n dial: ReactElement\n label: ScoreDescriptor\n toolTipText?: string\n}\n\n// Displayed on entity header of details page\nconst DialLayout = ({\n dial,\n label,\n toolTipText,\n}: DialLayoutProps): React.ReactNode => {\n return (\n <Stack sx={{ alignItems: 'center', gap: '10px' }}>\n {dial}\n <Box sx={{ display: 'flex', alignItems: 'center', gap: '4px' }}>\n <Typography variant=\"smallText1\" sx={{ margin: '0 !important' }}>\n {label}\n </Typography>\n {toolTipText && (\n <Tooltip title={toolTipText}>\n <InfoTwoTone sx={{ width: '18px', height: '18px' }} />\n </Tooltip>\n )}\n </Box>\n </Stack>\n )\n}\n\nexport default DialLayout\n"],"mappings":";;;;;AAaA,IAAM,KAAc,EAClB,SACA,UACA,qBAGE,kBAAC,GAAD;CAAO,IAAI;EAAE,YAAY;EAAU,KAAK;CAAO;WAA/C,CACG,GACD,kBAAC,GAAD;EAAK,IAAI;GAAE,SAAS;GAAQ,YAAY;GAAU,KAAK;EAAM;YAA7D,CACE,kBAAC,GAAD;GAAY,SAAQ;GAAa,IAAI,EAAE,QAAQ,eAAe;aAC3D;EACS,CAAA,GACX,KACC,kBAAC,GAAD;GAAS,OAAO;aACd,kBAAC,GAAD,EAAa,IAAI;IAAE,OAAO;IAAQ,QAAQ;GAAO,EAAI,CAAA;EAC9C,CAAA,CAER;GACA"}
1
+ {"version":3,"file":"DialLayout.js","names":[],"sources":["../../../src/components/SustainabilityScorecard/DialLayout.tsx"],"sourcesContent":["import React from 'react'\nimport { Box, Stack, Tooltip, Typography } from '@mui/material'\nimport InfoTwoTone from '@mui/icons-material/InfoTwoTone'\nimport { ReactElement } from 'react'\nimport { ScoreDescriptor } from './Dial'\n\nexport type DialLayoutProps = {\n dial: ReactElement\n label: ScoreDescriptor\n toolTipText?: string\n}\n\n// Displayed on entity header of details page\nconst DialLayout = ({\n dial,\n label,\n toolTipText,\n}: DialLayoutProps): React.ReactNode => {\n return (\n <Stack sx={{ alignItems: 'center', gap: '10px' }}>\n {dial}\n <Box sx={{ display: 'flex', alignItems: 'center', gap: '4px' }}>\n <Typography variant=\"smallText1\" sx={{ margin: '0 !important' }}>\n {label}\n </Typography>\n {toolTipText && (\n <Tooltip title={toolTipText}>\n <InfoTwoTone sx={{ width: '18px', height: '18px' }} />\n </Tooltip>\n )}\n </Box>\n </Stack>\n )\n}\n\nexport default DialLayout\n"],"mappings":";;;;;AAaA,IAAM,KAAc,EAClB,SACA,UACA,qBAGE,kBAAC,GAAD;CAAO,IAAI;EAAE,YAAY;EAAU,KAAK;CAAO;WAA/C,CACG,GACD,kBAAC,GAAD;EAAK,IAAI;GAAE,SAAS;GAAQ,YAAY;GAAU,KAAK;EAAM;YAA7D,CACE,kBAAC,GAAD;GAAY,SAAQ;GAAa,IAAI,EAAE,QAAQ,eAAe;aAC3D;EACS,CAAA,GACX,KACC,kBAAC,GAAD;GAAS,OAAO;aACd,kBAAC,GAAD,EAAa,IAAI;IAAE,OAAO;IAAQ,QAAQ;GAAO,EAAI,CAAA;EAC9C,CAAA,CAER;GACA"}
@@ -7,7 +7,7 @@ import o from "./Dial.js";
7
7
  import "react";
8
8
  import { Box as s, Link as c, Skeleton as l, Stack as u, Tooltip as d, Typography as f } from "@mui/material";
9
9
  import { Fragment as p, jsx as m, jsxs as h } from "react/jsx-runtime";
10
- import { InfoTwoTone as g } from "@mui/icons-material";
10
+ import g from "@mui/icons-material/InfoTwoTone";
11
11
  import { Link as _, useLocation as v } from "react-router";
12
12
  import y from "@mui/icons-material/Close";
13
13
  //#region src/components/SustainabilityScorecard/SustainabilityScorecard.tsx
@@ -1 +1 @@
1
- {"version":3,"file":"SustainabilityScorecard.js","names":[],"sources":["../../../src/components/SustainabilityScorecard/SustainabilityScorecard.tsx"],"sourcesContent":["import {\n Box,\n Link as MuiLink,\n Skeleton,\n Stack,\n Tooltip,\n Typography,\n} from '@mui/material'\nimport React from 'react'\nimport CloseIcon from '@mui/icons-material/Close'\nimport useGetQueryResultBundle from '@/synapse-queries/entity/useGetQueryResultBundle'\nimport { getFieldIndex } from '@/utils/functions/queryUtils'\n\nimport { SxProps, Theme } from '@mui/material'\nimport {\n getMetricValues,\n SUSTAINABILITY_ICON_COLORS,\n SustainabilityScorecardBaseProps,\n} from './SustainabilityScorecardUtils'\nimport { InfoTwoTone } from '@mui/icons-material'\nimport { CheckIcon } from '@/assets/icons/terms/CheckIcon'\nimport NoContentAvailable from '../SynapseTable/NoContentAvailable'\nimport Dial from './Dial'\nimport { Link as RouterLink, useLocation } from 'react-router'\n\nexport type MetricsConfig = {\n /** Name of the metric column in the table */\n key: string\n /** Display label for the metric */\n label: string\n /** Shown as a tooltip in SustainabilityScorecard and as summary text in SustainabilityScorecardSummary */\n text?: string\n}\n\nexport type SustainabilityScorecardProps = SustainabilityScorecardBaseProps & {\n sx?: SxProps<Theme>\n sustainabilityReportLink?: string\n}\n\ntype MetricRowProps = {\n metricValues: string[]\n metricsConfig: MetricsConfig[]\n}\n\nconst MetricRow = ({\n metricValues,\n metricsConfig,\n}: MetricRowProps): React.ReactNode => {\n return (\n <>\n {metricsConfig.map((metric, index) => (\n <Box sx={{ display: 'flex', padding: '4px 20px' }} key={metric.key}>\n <Typography\n variant=\"smallText1\"\n sx={{ alignItems: 'center', display: 'flex', gap: '8px' }}\n >\n {metric.label}\n <Tooltip title={metric.text} placement=\"top\">\n <InfoTwoTone\n sx={{\n width: '18px',\n height: '18px',\n color: 'primary.contrastText',\n }}\n />\n </Tooltip>\n </Typography>\n {metricValues[index] === 'true' ? (\n <Box\n sx={{\n backgroundColor: SUSTAINABILITY_ICON_COLORS.check,\n borderRadius: '50%',\n width: 18,\n height: 18,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n marginLeft: 'auto',\n }}\n >\n <CheckIcon\n sx={{ color: 'primary.contrastText', fontSize: '11px' }}\n />\n </Box>\n ) : (\n <Box\n sx={{\n backgroundColor: SUSTAINABILITY_ICON_COLORS.close,\n borderRadius: '50%',\n width: 18,\n height: 18,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n marginLeft: 'auto',\n }}\n >\n <CloseIcon\n sx={{ color: 'primary.contrastText', fontSize: '14px' }}\n />\n </Box>\n )}\n </Box>\n ))}\n </>\n )\n}\n\n/* SustainabilityScorecard component displays sustainability metrics and a dial based on the sustainability score of the entity. */\nconst SustainabilityScorecard = ({\n metricsConfig,\n scoreDescriptorColumnName,\n queryRequest,\n sx,\n sustainabilityReportLink,\n}: SustainabilityScorecardProps): React.ReactNode => {\n const { data: queryResultBundle, isLoading } =\n useGetQueryResultBundle(queryRequest)\n const location = useLocation()\n const search = location.search\n\n if (isLoading) {\n return <Skeleton width={'100%'} height={'100%'} />\n }\n\n const data = queryResultBundle?.queryResult!.queryResults\n\n if (data?.rows?.length === 0) {\n return (\n <Stack sx={{ display: 'flex', padding: '20px', ...sx }}>\n <Typography sx={{ paddingBottom: '20px' }} variant=\"subsectionHeader\">\n Sustainability Index\n </Typography>\n <NoContentAvailable />\n </Stack>\n )\n }\n\n const scoreDescriptorColIndex = getFieldIndex(\n scoreDescriptorColumnName,\n queryResultBundle,\n )\n\n const scoreDescriptor = data?.rows[0].values[scoreDescriptorColIndex]\n\n const metricValues = getMetricValues(\n data?.rows[0],\n queryResultBundle,\n metricsConfig,\n )\n\n return (\n <Box\n sx={{\n display: 'flex',\n flexDirection: { xs: 'column', sm: 'row' },\n padding: '20px',\n gap: '20px',\n ...sx,\n }}\n >\n <Stack sx={{ display: 'flex', gap: '20px', alignItems: 'center' }}>\n <Typography variant=\"subsectionHeader\">Sustainability Index</Typography>\n <Dial scoreDescriptor={scoreDescriptor ?? ''} />\n </Stack>\n <Stack sx={{ flex: 1, gap: '2px' }}>\n <MetricRow metricValues={metricValues} metricsConfig={metricsConfig} />\n {sustainabilityReportLink && (\n <MuiLink\n component={RouterLink}\n to={{ pathname: sustainabilityReportLink, search }}\n sx={{ padding: '4px 20px', fontSize: '14px' }}\n >\n View this tool’s sustainability and reusability report\n </MuiLink>\n )}\n </Stack>\n </Box>\n )\n}\n\nexport default SustainabilityScorecard\n"],"mappings":";;;;;;;;;;;;;AA4CA,IAAM,KAAa,EACjB,iBACA,uBAGE,kBAAA,GAAA,EAAA,UACG,EAAc,KAAK,GAAQ,MAC1B,kBAAC,GAAD;CAAK,IAAI;EAAE,SAAS;EAAQ,SAAS;CAAW;WAAhD,CACE,kBAAC,GAAD;EACE,SAAQ;EACR,IAAI;GAAE,YAAY;GAAU,SAAS;GAAQ,KAAK;EAAM;YAF1D,CAIG,EAAO,OACR,kBAAC,GAAD;GAAS,OAAO,EAAO;GAAM,WAAU;aACrC,kBAAC,GAAD,EACE,IAAI;IACF,OAAO;IACP,QAAQ;IACR,OAAO;GACT,EACD,CAAA;EACM,CAAA,CACC;KACX,EAAa,OAAW,SACvB,kBAAC,GAAD;EACE,IAAI;GACF,iBAAiB,EAA2B;GAC5C,cAAc;GACd,OAAO;GACP,QAAQ;GACR,SAAS;GACT,YAAY;GACZ,gBAAgB;GAChB,YAAY;EACd;YAEA,kBAAC,GAAD,EACE,IAAI;GAAE,OAAO;GAAwB,UAAU;EAAO,EACvD,CAAA;CACE,CAAA,IAEL,kBAAC,GAAD;EACE,IAAI;GACF,iBAAiB,EAA2B;GAC5C,cAAc;GACd,OAAO;GACP,QAAQ;GACR,SAAS;GACT,YAAY;GACZ,gBAAgB;GAChB,YAAY;EACd;YAEA,kBAAC,GAAD,EACE,IAAI;GAAE,OAAO;GAAwB,UAAU;EAAO,EACvD,CAAA;CACE,CAAA,CAEJ;GAnDmD,EAAO,GAmD1D,CACN,EACD,CAAA,GAKA,KAA2B,EAC/B,kBACA,8BACA,iBACA,OACA,kCACmD;CACnD,IAAM,EAAE,MAAM,GAAmB,iBAC/B,EAAwB,CAAY,GAEhC,IADW,EACF,EAAS;CAExB,IAAI,GACF,OAAO,kBAAC,GAAD;EAAU,OAAO;EAAQ,QAAQ;CAAS,CAAA;CAGnD,IAAM,IAAO,GAAmB,YAAa;CAE7C,IAAI,GAAM,MAAM,WAAW,GACzB,OACE,kBAAC,GAAD;EAAO,IAAI;GAAE,SAAS;GAAQ,SAAS;GAAQ,GAAG;EAAG;YAArD,CACE,kBAAC,GAAD;GAAY,IAAI,EAAE,eAAe,OAAO;GAAG,SAAQ;aAAmB;EAE1D,CAAA,GACZ,kBAAC,GAAD,CAAqB,CAAA,CAChB;;CAIX,IAAM,IAA0B,EAC9B,GACA,CACF,GAEM,IAAkB,GAAM,KAAK,GAAG,OAAO,IAEvC,IAAe,EACnB,GAAM,KAAK,IACX,GACA,CACF;CAEA,OACE,kBAAC,GAAD;EACE,IAAI;GACF,SAAS;GACT,eAAe;IAAE,IAAI;IAAU,IAAI;GAAM;GACzC,SAAS;GACT,KAAK;GACL,GAAG;EACL;YAPF,CASE,kBAAC,GAAD;GAAO,IAAI;IAAE,SAAS;IAAQ,KAAK;IAAQ,YAAY;GAAS;aAAhE,CACE,kBAAC,GAAD;IAAY,SAAQ;cAAmB;GAAgC,CAAA,GACvE,kBAAC,GAAD,EAAM,iBAAiB,KAAmB,GAAK,CAAA,CAC1C;MACP,kBAAC,GAAD;GAAO,IAAI;IAAE,MAAM;IAAG,KAAK;GAAM;aAAjC,CACE,kBAAC,GAAD;IAAyB;IAA6B;GAAgB,CAAA,GACrE,KACC,kBAAC,GAAD;IACE,WAAW;IACX,IAAI;KAAE,UAAU;KAA0B;IAAO;IACjD,IAAI;KAAE,SAAS;KAAY,UAAU;IAAO;cAC7C;GAEQ,CAAA,CAEN;IACJ;;AAET"}
1
+ {"version":3,"file":"SustainabilityScorecard.js","names":[],"sources":["../../../src/components/SustainabilityScorecard/SustainabilityScorecard.tsx"],"sourcesContent":["import {\n Box,\n Link as MuiLink,\n Skeleton,\n Stack,\n Tooltip,\n Typography,\n} from '@mui/material'\nimport React from 'react'\nimport CloseIcon from '@mui/icons-material/Close'\nimport useGetQueryResultBundle from '@/synapse-queries/entity/useGetQueryResultBundle'\nimport { getFieldIndex } from '@/utils/functions/queryUtils'\n\nimport { SxProps, Theme } from '@mui/material'\nimport {\n getMetricValues,\n SUSTAINABILITY_ICON_COLORS,\n SustainabilityScorecardBaseProps,\n} from './SustainabilityScorecardUtils'\nimport InfoTwoTone from '@mui/icons-material/InfoTwoTone'\nimport { CheckIcon } from '@/assets/icons/terms/CheckIcon'\nimport NoContentAvailable from '../SynapseTable/NoContentAvailable'\nimport Dial from './Dial'\nimport { Link as RouterLink, useLocation } from 'react-router'\n\nexport type MetricsConfig = {\n /** Name of the metric column in the table */\n key: string\n /** Display label for the metric */\n label: string\n /** Shown as a tooltip in SustainabilityScorecard and as summary text in SustainabilityScorecardSummary */\n text?: string\n}\n\nexport type SustainabilityScorecardProps = SustainabilityScorecardBaseProps & {\n sx?: SxProps<Theme>\n sustainabilityReportLink?: string\n}\n\ntype MetricRowProps = {\n metricValues: string[]\n metricsConfig: MetricsConfig[]\n}\n\nconst MetricRow = ({\n metricValues,\n metricsConfig,\n}: MetricRowProps): React.ReactNode => {\n return (\n <>\n {metricsConfig.map((metric, index) => (\n <Box sx={{ display: 'flex', padding: '4px 20px' }} key={metric.key}>\n <Typography\n variant=\"smallText1\"\n sx={{ alignItems: 'center', display: 'flex', gap: '8px' }}\n >\n {metric.label}\n <Tooltip title={metric.text} placement=\"top\">\n <InfoTwoTone\n sx={{\n width: '18px',\n height: '18px',\n color: 'primary.contrastText',\n }}\n />\n </Tooltip>\n </Typography>\n {metricValues[index] === 'true' ? (\n <Box\n sx={{\n backgroundColor: SUSTAINABILITY_ICON_COLORS.check,\n borderRadius: '50%',\n width: 18,\n height: 18,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n marginLeft: 'auto',\n }}\n >\n <CheckIcon\n sx={{ color: 'primary.contrastText', fontSize: '11px' }}\n />\n </Box>\n ) : (\n <Box\n sx={{\n backgroundColor: SUSTAINABILITY_ICON_COLORS.close,\n borderRadius: '50%',\n width: 18,\n height: 18,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n marginLeft: 'auto',\n }}\n >\n <CloseIcon\n sx={{ color: 'primary.contrastText', fontSize: '14px' }}\n />\n </Box>\n )}\n </Box>\n ))}\n </>\n )\n}\n\n/* SustainabilityScorecard component displays sustainability metrics and a dial based on the sustainability score of the entity. */\nconst SustainabilityScorecard = ({\n metricsConfig,\n scoreDescriptorColumnName,\n queryRequest,\n sx,\n sustainabilityReportLink,\n}: SustainabilityScorecardProps): React.ReactNode => {\n const { data: queryResultBundle, isLoading } =\n useGetQueryResultBundle(queryRequest)\n const location = useLocation()\n const search = location.search\n\n if (isLoading) {\n return <Skeleton width={'100%'} height={'100%'} />\n }\n\n const data = queryResultBundle?.queryResult!.queryResults\n\n if (data?.rows?.length === 0) {\n return (\n <Stack sx={{ display: 'flex', padding: '20px', ...sx }}>\n <Typography sx={{ paddingBottom: '20px' }} variant=\"subsectionHeader\">\n Sustainability Index\n </Typography>\n <NoContentAvailable />\n </Stack>\n )\n }\n\n const scoreDescriptorColIndex = getFieldIndex(\n scoreDescriptorColumnName,\n queryResultBundle,\n )\n\n const scoreDescriptor = data?.rows[0].values[scoreDescriptorColIndex]\n\n const metricValues = getMetricValues(\n data?.rows[0],\n queryResultBundle,\n metricsConfig,\n )\n\n return (\n <Box\n sx={{\n display: 'flex',\n flexDirection: { xs: 'column', sm: 'row' },\n padding: '20px',\n gap: '20px',\n ...sx,\n }}\n >\n <Stack sx={{ display: 'flex', gap: '20px', alignItems: 'center' }}>\n <Typography variant=\"subsectionHeader\">Sustainability Index</Typography>\n <Dial scoreDescriptor={scoreDescriptor ?? ''} />\n </Stack>\n <Stack sx={{ flex: 1, gap: '2px' }}>\n <MetricRow metricValues={metricValues} metricsConfig={metricsConfig} />\n {sustainabilityReportLink && (\n <MuiLink\n component={RouterLink}\n to={{ pathname: sustainabilityReportLink, search }}\n sx={{ padding: '4px 20px', fontSize: '14px' }}\n >\n View this tool’s sustainability and reusability report\n </MuiLink>\n )}\n </Stack>\n </Box>\n )\n}\n\nexport default SustainabilityScorecard\n"],"mappings":";;;;;;;;;;;;;AA4CA,IAAM,KAAa,EACjB,iBACA,uBAGE,kBAAA,GAAA,EAAA,UACG,EAAc,KAAK,GAAQ,MAC1B,kBAAC,GAAD;CAAK,IAAI;EAAE,SAAS;EAAQ,SAAS;CAAW;WAAhD,CACE,kBAAC,GAAD;EACE,SAAQ;EACR,IAAI;GAAE,YAAY;GAAU,SAAS;GAAQ,KAAK;EAAM;YAF1D,CAIG,EAAO,OACR,kBAAC,GAAD;GAAS,OAAO,EAAO;GAAM,WAAU;aACrC,kBAAC,GAAD,EACE,IAAI;IACF,OAAO;IACP,QAAQ;IACR,OAAO;GACT,EACD,CAAA;EACM,CAAA,CACC;KACX,EAAa,OAAW,SACvB,kBAAC,GAAD;EACE,IAAI;GACF,iBAAiB,EAA2B;GAC5C,cAAc;GACd,OAAO;GACP,QAAQ;GACR,SAAS;GACT,YAAY;GACZ,gBAAgB;GAChB,YAAY;EACd;YAEA,kBAAC,GAAD,EACE,IAAI;GAAE,OAAO;GAAwB,UAAU;EAAO,EACvD,CAAA;CACE,CAAA,IAEL,kBAAC,GAAD;EACE,IAAI;GACF,iBAAiB,EAA2B;GAC5C,cAAc;GACd,OAAO;GACP,QAAQ;GACR,SAAS;GACT,YAAY;GACZ,gBAAgB;GAChB,YAAY;EACd;YAEA,kBAAC,GAAD,EACE,IAAI;GAAE,OAAO;GAAwB,UAAU;EAAO,EACvD,CAAA;CACE,CAAA,CAEJ;GAnDmD,EAAO,GAmD1D,CACN,EACD,CAAA,GAKA,KAA2B,EAC/B,kBACA,8BACA,iBACA,OACA,kCACmD;CACnD,IAAM,EAAE,MAAM,GAAmB,iBAC/B,EAAwB,CAAY,GAEhC,IADW,EACF,EAAS;CAExB,IAAI,GACF,OAAO,kBAAC,GAAD;EAAU,OAAO;EAAQ,QAAQ;CAAS,CAAA;CAGnD,IAAM,IAAO,GAAmB,YAAa;CAE7C,IAAI,GAAM,MAAM,WAAW,GACzB,OACE,kBAAC,GAAD;EAAO,IAAI;GAAE,SAAS;GAAQ,SAAS;GAAQ,GAAG;EAAG;YAArD,CACE,kBAAC,GAAD;GAAY,IAAI,EAAE,eAAe,OAAO;GAAG,SAAQ;aAAmB;EAE1D,CAAA,GACZ,kBAAC,GAAD,CAAqB,CAAA,CAChB;;CAIX,IAAM,IAA0B,EAC9B,GACA,CACF,GAEM,IAAkB,GAAM,KAAK,GAAG,OAAO,IAEvC,IAAe,EACnB,GAAM,KAAK,IACX,GACA,CACF;CAEA,OACE,kBAAC,GAAD;EACE,IAAI;GACF,SAAS;GACT,eAAe;IAAE,IAAI;IAAU,IAAI;GAAM;GACzC,SAAS;GACT,KAAK;GACL,GAAG;EACL;YAPF,CASE,kBAAC,GAAD;GAAO,IAAI;IAAE,SAAS;IAAQ,KAAK;IAAQ,YAAY;GAAS;aAAhE,CACE,kBAAC,GAAD;IAAY,SAAQ;cAAmB;GAAgC,CAAA,GACvE,kBAAC,GAAD,EAAM,iBAAiB,KAAmB,GAAK,CAAA,CAC1C;MACP,kBAAC,GAAD;GAAO,IAAI;IAAE,MAAM;IAAG,KAAK;GAAM;aAAjC,CACE,kBAAC,GAAD;IAAyB;IAA6B;GAAgB,CAAA,GACrE,KACC,kBAAC,GAAD;IACE,WAAW;IACX,IAAI;KAAE,UAAU;KAA0B;IAAO;IACjD,IAAI;KAAE,SAAS;KAAY,UAAU;IAAO;cAC7C;GAEQ,CAAA,CAEN;IACJ;;AAET"}
@@ -18,7 +18,7 @@ import { Alert as u, Box as d, Chip as f, List as p, ListItem as m, Stack as h,
18
18
  import { jsx as _, jsxs as v } from "react/jsx-runtime";
19
19
  import { AgentAccessLevel as y } from "@sage-bionetworks/synapse-types";
20
20
  import { FileHandleAssociateType as ae } from "@sage-bionetworks/synapse-client";
21
- import { SmartToyTwoTone as b } from "@mui/icons-material";
21
+ import b from "@mui/icons-material/SmartToyTwoTone";
22
22
  //#region src/components/SynapseChat/SynapseChat.tsx
23
23
  var oe = "Hi! How can I help you today?", se = {
24
24
  [y.PUBLICLY_ACCESSIBLE]: " and can only read public data.",
@@ -1 +1 @@
1
- {"version":3,"file":"SynapseChat.js","names":[],"sources":["../../../src/components/SynapseChat/SynapseChat.tsx"],"sourcesContent":["import { ChatState, useChatState } from '@/components/SynapseChat/useChatState'\nimport {\n useCreateAgentSession,\n useUpdateAgentSession,\n} from '@/synapse-queries/chat/useChat'\nimport { useSynapseContext } from '@/utils'\nimport {\n Alert,\n Box,\n Chip,\n List,\n ListItem,\n Stack,\n Typography,\n} from '@mui/material'\nimport {\n AgentSession,\n FileHandleAssociateType,\n GridAgentSessionContext,\n} from '@sage-bionetworks/synapse-client'\nimport { AgentAccessLevel } from '@sage-bionetworks/synapse-types'\nimport { useEffect, useRef, useState } from 'react'\nimport { SkeletonParagraph } from '../Skeleton'\nimport { displayToast } from '../ToastMessage'\nimport AccessLevelMenu from './AccessLevelMenu'\nimport { ChatAttachment } from './utils/types'\nimport { ChatInputArea } from './components/ChatInputArea/ChatInputArea'\nimport SynapseChatMessage from './SynapseChatMessage'\nimport { SmartToyTwoTone } from '@mui/icons-material'\nimport { UserCard } from '../UserCard/UserCard'\nimport { useApplicationSessionContext } from '@/utils/AppUtils'\nimport { ReactComponent as CurieAvatarHead } from '@/assets/illustrations/curie_avatar_head.svg'\n\nconst CURIE_GREETING = 'Hi! How can I help you today?'\n\nconst CURIE_ACCESS_LEVEL_SUFFIX: Record<AgentAccessLevel, string> = {\n [AgentAccessLevel.PUBLICLY_ACCESSIBLE]: ' and can only read public data.',\n [AgentAccessLevel.READ_YOUR_PRIVATE_DATA]:\n ' and can read your public and private data in Synapse on your behalf.',\n [AgentAccessLevel.WRITE_YOUR_PRIVATE_DATA]:\n ' and can read and write your public and private data in Synapse on your behalf.',\n}\n\nconst DEFAULT_AVATAR = (\n <Box\n sx={{\n p: '3px',\n borderRadius: '50%',\n borderStyle: 'solid',\n borderWidth: '1px',\n borderColor: 'grey.300',\n mt: '10px',\n height: '31px',\n }}\n >\n <SmartToyTwoTone sx={{ color: 'secondary.main' }} />\n </Box>\n)\n\nconst CURIE_AVATAR = (\n <Box\n sx={{\n mt: '10px',\n height: '30px',\n width: '30px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <CurieAvatarHead />\n </Box>\n)\n\nexport type SynapseChatProps = {\n initialMessage?: string //optional initial message\n agentRegistrationId?: string // if provided, use this agent\n chatbotName?: string // optional name of this chatbot agent\n variant?: 'default' | 'curie'\n hideTitle?: boolean\n textboxPositionOffset?: string // when embedded in a form, the textbox (form) stuck to the bottom may need to be offset due to container padding (dialog content for example!)\n /* optional session context for the agent session */\n sessionContext?: GridAgentSessionContext\n /* The current session, if state is lifted out of this component */\n externalSession?: AgentSession\n /* A callback invoked to bootstrap the current session, if state is to be lifted out of this component */\n setExternalSession?: (s: AgentSession | undefined) => void\n /* The current chat history, if state is lifted out of this component */\n externalChatState?: ChatState\n // default access level for the agent session.\n defaultAgentAccessLevel?: AgentAccessLevel\n // Whether to show the access level menu for the agent session.\n showAccessLevelMenu?: boolean\n /**\n * Optional callback invoked once when a chat response is received from the server.\n * Use this for side effects such as navigation based on the response content.\n * Called in the mutation onSuccess handler so it runs exactly once per response.\n */\n onChatResponse?: (responseText: string) => void\n /** Optional list of prompt suggestions shown as clickable pills above the text input */\n suggestedPrompts?: string[]\n /** Optional custom avatar for the chatbot agent */\n agentAvatar?: React.ReactNode\n /**\n * Whether to allow the user to attach local files to their chat message.\n * @default false\n */\n allowAttachments?: boolean\n /**\n * Invoked when creating the agent session fails because the current (anonymous) user is not\n * authorized to start a session with this agent. Callers should use this to prompt the user to\n * log in. When omitted, the session creation error is shown inline instead.\n */\n onSessionCreationUnauthenticated?: () => void\n}\n\nexport function SynapseChat({\n initialMessage,\n agentRegistrationId,\n chatbotName = 'SynapseChat',\n variant = 'default',\n agentAvatar,\n hideTitle = false,\n textboxPositionOffset = '0px',\n sessionContext,\n externalSession,\n setExternalSession,\n externalChatState,\n showAccessLevelMenu = true,\n onChatResponse,\n suggestedPrompts,\n allowAttachments = false,\n onSessionCreationUnauthenticated,\n}: SynapseChatProps) {\n const { accessToken, isAuthenticated } = useSynapseContext()\n const { userId } = useApplicationSessionContext()\n\n const baseDisclaimerText = chatbotName + ' can make mistakes'\n\n const resolvedAgentAvatar =\n agentAvatar ?? (variant === 'curie' ? CURIE_AVATAR : DEFAULT_AVATAR)\n\n const userAvatar = (\n <UserCard ownerId={userId} size=\"AVATAR\" avatarSize=\"MEDIUM\" />\n )\n const [localAgentSession, setLocalAgentSession] = useState<AgentSession>()\n const agentSession = externalSession ?? localAgentSession\n const setAgentSession = setExternalSession ?? setLocalAgentSession\n\n const { mutate: createAgentSession, error: createAgentSessionError } =\n useCreateAgentSession({\n onSuccess: newAgentSession => setAgentSession(newAgentSession),\n onError: err => {\n // A registration that the ACT has not opened to anonymous chat rejects an anonymous\n // session with a 401/403. Defer to the caller to prompt the user to log in.\n if (!isAuthenticated && (err.status === 401 || err.status === 403)) {\n onSessionCreationUnauthenticated?.()\n }\n },\n })\n\n const { mutate: updateAgentSession } = useUpdateAgentSession({\n onSuccess: updatedAgentSession => setAgentSession(updatedAgentSession),\n onError: err =>\n displayToast(\n `Unable to update the agent session: ${err.message}`,\n 'danger',\n ),\n })\n const [agentAccessLevel, setAgentAccessLevel] = useState<AgentAccessLevel>(\n sessionContext\n ? AgentAccessLevel.WRITE_YOUR_PRIVATE_DATA\n : AgentAccessLevel.PUBLICLY_ACCESSIBLE,\n )\n\n const internalChatState = useChatState(agentSession, onChatResponse)\n const chatState = externalChatState ?? internalChatState\n const { interactions, isAwaitingResponse, sendChat } = chatState\n\n const showGreeting = variant === 'curie' && interactions.length === 0\n\n const curieAccessLevelSuffix =\n variant === 'curie' ? CURIE_ACCESS_LEVEL_SUFFIX[agentAccessLevel] : ''\n const disclaimerText = baseDisclaimerText + curieAccessLevelSuffix\n\n // Only interactions added after this component instance mounted should play the entry\n // animation. Callers may lift state so history survives a `Dialog` closing, but the\n // `Dialog` unmounts its children, so every reopen would otherwise re-animate the whole\n // conversation.\n const presentAtMountRef = useRef<Set<string> | undefined>(undefined)\n if (presentAtMountRef.current === undefined) {\n presentAtMountRef.current = new Set(interactions.map(i => i.id))\n }\n const presentAtMount = presentAtMountRef.current\n\n // Keep track of the text that the user is currently typing into the textfield\n const [userChatTextfieldValue, setUserChatTextfieldValue] = useState('')\n const [initialMessageProcessed, setInitialMessageProcessed] = useState(false)\n\n // A copy of the attachments sent with the last interaction, so it can still show rich\n // (name/type) chips after ChatInputArea has cleared its own attachment state. This is passed to\n // the last interaction for its entire lifetime -- sent, then processing, then completed -- as a\n // fallback filename source, since the request body (FileHandleAssociation) never carries a\n // filename and the server-resolved filename (attachmentStatuses) only arrives once the job\n // completes. It's simply overwritten on the next send.\n const [lastSentAttachments, setLastSentAttachments] = useState<\n ChatAttachment[]\n >([])\n\n // Restore chat session history, if exists.\n // TODO: currently only a single page is restored. Add support for multiple pages (and detect the user scrolling up to restore the next page of results older)\n // const {\n // data: sessionHistoryInfiniteData,\n // } = //, hasNextPage: hasMoreSessionHistory, fetchNextPage: fetchNextSessionHistoryPage, isLoading: isSessionHistoryLoading } =\n // useGetAgentChatSessionHistoryInfinite(\n // {\n // sessionId: agentSession?.sessionId,\n // },\n // {\n // enabled: !!agentSession,\n // },\n // )\n\n // const sessionHistory = useMemo(\n // () =>\n // sessionHistoryInfiniteData?.pages\n // .flatMap(page => page.page)\n // /* Note: session history is ordered from most recent to least recent in each page, so reverse the order when restoring the chat interface */\n // .reverse() ?? [],\n // [sessionHistoryInfiniteData],\n // )\n\n useEffect(() => {\n // on mount, create a new agent session!\n if (createAgentSession && !agentSession) {\n createAgentSession({\n agentAccessLevel,\n agentRegistrationId,\n sessionContext,\n })\n }\n }, [\n createAgentSession,\n agentSession,\n accessToken,\n sessionContext,\n agentAccessLevel,\n agentRegistrationId,\n ])\n\n useEffect(() => {\n // on mount, resolve the initial message chat interaction (if set)\n if (agentSession && initialMessage && !initialMessageProcessed) {\n sendChat(initialMessage)\n setInitialMessageProcessed(true)\n }\n }, [agentSession, initialMessage, initialMessageProcessed, sendChat])\n\n const handleSend = (message: string, attachments: ChatAttachment[]) => {\n sendChat(\n message,\n attachments.length\n ? attachments.map(attachment => ({\n fileHandleId: attachment.fileHandleId,\n // The backend short-circuits the FileHandleAssociation auth check for a user's own\n // uploaded file handle, so associateObjectId/associateObjectType are not totally\n // accurate here. FileHandleAssociateType has no dedicated value for \"the uploader's\n // own bare file handle\", so this stubs associateObjectId to the fileHandleId itself\n // and the FileEntity associate type, which supports the short-circuit path.\n associateObjectId: attachment.fileHandleId,\n associateObjectType: FileHandleAssociateType.FileEntity,\n }))\n : undefined,\n )\n setUserChatTextfieldValue('')\n setLastSentAttachments(attachments)\n }\n\n if (createAgentSessionError) {\n // When an anonymous user can't start a session, the caller is redirecting them to log in, so\n // suppress the inline error in favor of that flow.\n const deferredToLogin =\n !isAuthenticated &&\n !!onSessionCreationUnauthenticated &&\n (createAgentSessionError.status === 401 ||\n createAgentSessionError.status === 403)\n if (!deferredToLogin) {\n return (\n <Alert severity={'error'} sx={{ my: 2 }}>\n {createAgentSessionError.reason}\n </Alert>\n )\n }\n }\n\n return (\n <Box\n sx={{\n display: 'flex',\n flexDirection: 'column',\n justifyContent: variant === 'curie' ? 'flex-start' : 'space-between',\n gap: variant === 'curie' ? '20px' : '0',\n maxWidth: '1100px',\n mx: 'auto',\n height: '100%',\n }}\n >\n {!hideTitle && (\n <Typography\n variant=\"headline1\"\n sx={{\n p: '20px',\n borderBottom: '1px solid',\n borderColor: 'grey.300',\n position: 'sticky',\n top: '0px',\n backgroundColor: 'white',\n zIndex: 1,\n }}\n >\n {chatbotName}\n </Typography>\n )}\n {showAccessLevelMenu && variant !== 'curie' && isAuthenticated && (\n <AccessLevelMenu\n initAccessLevel={agentAccessLevel}\n onChange={newAccessLevel => {\n setAgentAccessLevel(newAccessLevel)\n updateAgentSession({\n agentAccessLevel: newAccessLevel,\n sessionId: agentSession!.sessionId!,\n })\n }}\n />\n )}\n {!agentSession && <SkeletonParagraph numRows={10} />}\n {agentSession && (\n <Box\n sx={{\n flexGrow: 1,\n overflowY: 'auto',\n mb: variant === 'curie' ? 0 : 2,\n }}\n >\n <List\n sx={{\n flex: 1,\n overflowY: 'auto',\n pt: '20px',\n ...(variant === 'curie' && { pt: 0, pb: 0, gap: '20px' }),\n display: 'flex',\n flexDirection: 'column',\n ...(showGreeting && {\n minHeight: '100%',\n justifyContent: 'flex-end',\n }),\n }}\n >\n {/* {sessionHistory &&\n sessionHistory.map((interaction, index) => {\n return (\n <SynapseChatInteraction\n key={index}\n userMessage={interaction.usersRequestText}\n chatResponseText={interaction.agentResponseText}\n />\n )\n })} */}\n {showGreeting && (\n <ListItem\n sx={{\n display: 'grid',\n gridTemplateColumns: '50px auto',\n columnGap: '16px',\n justifyItems: 'start',\n alignItems: 'start',\n p: 0,\n }}\n >\n {resolvedAgentAvatar}\n <Typography sx={{ justifySelf: 'start', mt: '14px' }}>\n {CURIE_GREETING}\n </Typography>\n </ListItem>\n )}\n {interactions.map((interaction, index) => {\n const isLast = index === interactions.length - 1\n return (\n <SynapseChatMessage\n agentAvatar={resolvedAgentAvatar}\n userAvatar={userAvatar}\n key={interaction.id}\n userMessage={interaction.userMessage}\n chatJobId={interaction.jobId}\n showLoadingIcon={variant !== 'curie'}\n onSendChat={sendChat}\n scrollIntoView={isLast}\n animateEntry={!presentAtMount.has(interaction.id)}\n isAwaitingResponse={isAwaitingResponse}\n pendingAttachments={\n // Only one interaction can be in flight at a time (the composer is disabled\n // while isAwaitingResponse), so lastSentAttachments always corresponds to\n // whichever interaction is last.\n isLast ? lastSentAttachments : undefined\n }\n />\n )\n })}\n </List>\n </Box>\n )}\n <Box\n sx={{\n position: 'sticky',\n bottom: variant === 'curie' ? '0px' : textboxPositionOffset,\n backgroundColor: 'white',\n }}\n >\n {suggestedPrompts &&\n suggestedPrompts.length > 0 &&\n interactions.length === 0 && (\n <Stack\n direction=\"row\"\n spacing={1}\n sx={{ pt: '8px', flexWrap: 'wrap', gap: 1 }}\n >\n {suggestedPrompts.map(prompt => (\n <Chip\n key={prompt}\n label={prompt}\n variant=\"outlined\"\n onClick={() => setUserChatTextfieldValue(prompt)}\n disabled={!agentSession}\n sx={{ cursor: 'pointer' }}\n />\n ))}\n </Stack>\n )}\n <Box sx={{ mt: '5px' }}>\n <ChatInputArea\n value={userChatTextfieldValue}\n onValueChange={setUserChatTextfieldValue}\n onSend={handleSend}\n placeholder={\n variant === 'curie' ? 'Ask anything' : `Message ${chatbotName}`\n }\n disabled={!agentSession || isAwaitingResponse}\n allowAttachments={allowAttachments}\n />\n </Box>\n </Box>\n <Typography variant=\"smallText1\" sx={{ pt: '8px', textAlign: 'center' }}>\n {disclaimerText}\n </Typography>\n </Box>\n )\n}\n\nexport default SynapseChat\n"],"mappings":"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"}
1
+ {"version":3,"file":"SynapseChat.js","names":[],"sources":["../../../src/components/SynapseChat/SynapseChat.tsx"],"sourcesContent":["import { ChatState, useChatState } from '@/components/SynapseChat/useChatState'\nimport {\n useCreateAgentSession,\n useUpdateAgentSession,\n} from '@/synapse-queries/chat/useChat'\nimport { useSynapseContext } from '@/utils'\nimport {\n Alert,\n Box,\n Chip,\n List,\n ListItem,\n Stack,\n Typography,\n} from '@mui/material'\nimport {\n AgentSession,\n FileHandleAssociateType,\n GridAgentSessionContext,\n} from '@sage-bionetworks/synapse-client'\nimport { AgentAccessLevel } from '@sage-bionetworks/synapse-types'\nimport { useEffect, useRef, useState } from 'react'\nimport { SkeletonParagraph } from '../Skeleton'\nimport { displayToast } from '../ToastMessage'\nimport AccessLevelMenu from './AccessLevelMenu'\nimport { ChatAttachment } from './utils/types'\nimport { ChatInputArea } from './components/ChatInputArea/ChatInputArea'\nimport SynapseChatMessage from './SynapseChatMessage'\nimport SmartToyTwoTone from '@mui/icons-material/SmartToyTwoTone'\nimport { UserCard } from '../UserCard/UserCard'\nimport { useApplicationSessionContext } from '@/utils/AppUtils'\nimport { ReactComponent as CurieAvatarHead } from '@/assets/illustrations/curie_avatar_head.svg'\n\nconst CURIE_GREETING = 'Hi! How can I help you today?'\n\nconst CURIE_ACCESS_LEVEL_SUFFIX: Record<AgentAccessLevel, string> = {\n [AgentAccessLevel.PUBLICLY_ACCESSIBLE]: ' and can only read public data.',\n [AgentAccessLevel.READ_YOUR_PRIVATE_DATA]:\n ' and can read your public and private data in Synapse on your behalf.',\n [AgentAccessLevel.WRITE_YOUR_PRIVATE_DATA]:\n ' and can read and write your public and private data in Synapse on your behalf.',\n}\n\nconst DEFAULT_AVATAR = (\n <Box\n sx={{\n p: '3px',\n borderRadius: '50%',\n borderStyle: 'solid',\n borderWidth: '1px',\n borderColor: 'grey.300',\n mt: '10px',\n height: '31px',\n }}\n >\n <SmartToyTwoTone sx={{ color: 'secondary.main' }} />\n </Box>\n)\n\nconst CURIE_AVATAR = (\n <Box\n sx={{\n mt: '10px',\n height: '30px',\n width: '30px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <CurieAvatarHead />\n </Box>\n)\n\nexport type SynapseChatProps = {\n initialMessage?: string //optional initial message\n agentRegistrationId?: string // if provided, use this agent\n chatbotName?: string // optional name of this chatbot agent\n variant?: 'default' | 'curie'\n hideTitle?: boolean\n textboxPositionOffset?: string // when embedded in a form, the textbox (form) stuck to the bottom may need to be offset due to container padding (dialog content for example!)\n /* optional session context for the agent session */\n sessionContext?: GridAgentSessionContext\n /* The current session, if state is lifted out of this component */\n externalSession?: AgentSession\n /* A callback invoked to bootstrap the current session, if state is to be lifted out of this component */\n setExternalSession?: (s: AgentSession | undefined) => void\n /* The current chat history, if state is lifted out of this component */\n externalChatState?: ChatState\n // default access level for the agent session.\n defaultAgentAccessLevel?: AgentAccessLevel\n // Whether to show the access level menu for the agent session.\n showAccessLevelMenu?: boolean\n /**\n * Optional callback invoked once when a chat response is received from the server.\n * Use this for side effects such as navigation based on the response content.\n * Called in the mutation onSuccess handler so it runs exactly once per response.\n */\n onChatResponse?: (responseText: string) => void\n /** Optional list of prompt suggestions shown as clickable pills above the text input */\n suggestedPrompts?: string[]\n /** Optional custom avatar for the chatbot agent */\n agentAvatar?: React.ReactNode\n /**\n * Whether to allow the user to attach local files to their chat message.\n * @default false\n */\n allowAttachments?: boolean\n /**\n * Invoked when creating the agent session fails because the current (anonymous) user is not\n * authorized to start a session with this agent. Callers should use this to prompt the user to\n * log in. When omitted, the session creation error is shown inline instead.\n */\n onSessionCreationUnauthenticated?: () => void\n}\n\nexport function SynapseChat({\n initialMessage,\n agentRegistrationId,\n chatbotName = 'SynapseChat',\n variant = 'default',\n agentAvatar,\n hideTitle = false,\n textboxPositionOffset = '0px',\n sessionContext,\n externalSession,\n setExternalSession,\n externalChatState,\n showAccessLevelMenu = true,\n onChatResponse,\n suggestedPrompts,\n allowAttachments = false,\n onSessionCreationUnauthenticated,\n}: SynapseChatProps) {\n const { accessToken, isAuthenticated } = useSynapseContext()\n const { userId } = useApplicationSessionContext()\n\n const baseDisclaimerText = chatbotName + ' can make mistakes'\n\n const resolvedAgentAvatar =\n agentAvatar ?? (variant === 'curie' ? CURIE_AVATAR : DEFAULT_AVATAR)\n\n const userAvatar = (\n <UserCard ownerId={userId} size=\"AVATAR\" avatarSize=\"MEDIUM\" />\n )\n const [localAgentSession, setLocalAgentSession] = useState<AgentSession>()\n const agentSession = externalSession ?? localAgentSession\n const setAgentSession = setExternalSession ?? setLocalAgentSession\n\n const { mutate: createAgentSession, error: createAgentSessionError } =\n useCreateAgentSession({\n onSuccess: newAgentSession => setAgentSession(newAgentSession),\n onError: err => {\n // A registration that the ACT has not opened to anonymous chat rejects an anonymous\n // session with a 401/403. Defer to the caller to prompt the user to log in.\n if (!isAuthenticated && (err.status === 401 || err.status === 403)) {\n onSessionCreationUnauthenticated?.()\n }\n },\n })\n\n const { mutate: updateAgentSession } = useUpdateAgentSession({\n onSuccess: updatedAgentSession => setAgentSession(updatedAgentSession),\n onError: err =>\n displayToast(\n `Unable to update the agent session: ${err.message}`,\n 'danger',\n ),\n })\n const [agentAccessLevel, setAgentAccessLevel] = useState<AgentAccessLevel>(\n sessionContext\n ? AgentAccessLevel.WRITE_YOUR_PRIVATE_DATA\n : AgentAccessLevel.PUBLICLY_ACCESSIBLE,\n )\n\n const internalChatState = useChatState(agentSession, onChatResponse)\n const chatState = externalChatState ?? internalChatState\n const { interactions, isAwaitingResponse, sendChat } = chatState\n\n const showGreeting = variant === 'curie' && interactions.length === 0\n\n const curieAccessLevelSuffix =\n variant === 'curie' ? CURIE_ACCESS_LEVEL_SUFFIX[agentAccessLevel] : ''\n const disclaimerText = baseDisclaimerText + curieAccessLevelSuffix\n\n // Only interactions added after this component instance mounted should play the entry\n // animation. Callers may lift state so history survives a `Dialog` closing, but the\n // `Dialog` unmounts its children, so every reopen would otherwise re-animate the whole\n // conversation.\n const presentAtMountRef = useRef<Set<string> | undefined>(undefined)\n if (presentAtMountRef.current === undefined) {\n presentAtMountRef.current = new Set(interactions.map(i => i.id))\n }\n const presentAtMount = presentAtMountRef.current\n\n // Keep track of the text that the user is currently typing into the textfield\n const [userChatTextfieldValue, setUserChatTextfieldValue] = useState('')\n const [initialMessageProcessed, setInitialMessageProcessed] = useState(false)\n\n // A copy of the attachments sent with the last interaction, so it can still show rich\n // (name/type) chips after ChatInputArea has cleared its own attachment state. This is passed to\n // the last interaction for its entire lifetime -- sent, then processing, then completed -- as a\n // fallback filename source, since the request body (FileHandleAssociation) never carries a\n // filename and the server-resolved filename (attachmentStatuses) only arrives once the job\n // completes. It's simply overwritten on the next send.\n const [lastSentAttachments, setLastSentAttachments] = useState<\n ChatAttachment[]\n >([])\n\n // Restore chat session history, if exists.\n // TODO: currently only a single page is restored. Add support for multiple pages (and detect the user scrolling up to restore the next page of results older)\n // const {\n // data: sessionHistoryInfiniteData,\n // } = //, hasNextPage: hasMoreSessionHistory, fetchNextPage: fetchNextSessionHistoryPage, isLoading: isSessionHistoryLoading } =\n // useGetAgentChatSessionHistoryInfinite(\n // {\n // sessionId: agentSession?.sessionId,\n // },\n // {\n // enabled: !!agentSession,\n // },\n // )\n\n // const sessionHistory = useMemo(\n // () =>\n // sessionHistoryInfiniteData?.pages\n // .flatMap(page => page.page)\n // /* Note: session history is ordered from most recent to least recent in each page, so reverse the order when restoring the chat interface */\n // .reverse() ?? [],\n // [sessionHistoryInfiniteData],\n // )\n\n useEffect(() => {\n // on mount, create a new agent session!\n if (createAgentSession && !agentSession) {\n createAgentSession({\n agentAccessLevel,\n agentRegistrationId,\n sessionContext,\n })\n }\n }, [\n createAgentSession,\n agentSession,\n accessToken,\n sessionContext,\n agentAccessLevel,\n agentRegistrationId,\n ])\n\n useEffect(() => {\n // on mount, resolve the initial message chat interaction (if set)\n if (agentSession && initialMessage && !initialMessageProcessed) {\n sendChat(initialMessage)\n setInitialMessageProcessed(true)\n }\n }, [agentSession, initialMessage, initialMessageProcessed, sendChat])\n\n const handleSend = (message: string, attachments: ChatAttachment[]) => {\n sendChat(\n message,\n attachments.length\n ? attachments.map(attachment => ({\n fileHandleId: attachment.fileHandleId,\n // The backend short-circuits the FileHandleAssociation auth check for a user's own\n // uploaded file handle, so associateObjectId/associateObjectType are not totally\n // accurate here. FileHandleAssociateType has no dedicated value for \"the uploader's\n // own bare file handle\", so this stubs associateObjectId to the fileHandleId itself\n // and the FileEntity associate type, which supports the short-circuit path.\n associateObjectId: attachment.fileHandleId,\n associateObjectType: FileHandleAssociateType.FileEntity,\n }))\n : undefined,\n )\n setUserChatTextfieldValue('')\n setLastSentAttachments(attachments)\n }\n\n if (createAgentSessionError) {\n // When an anonymous user can't start a session, the caller is redirecting them to log in, so\n // suppress the inline error in favor of that flow.\n const deferredToLogin =\n !isAuthenticated &&\n !!onSessionCreationUnauthenticated &&\n (createAgentSessionError.status === 401 ||\n createAgentSessionError.status === 403)\n if (!deferredToLogin) {\n return (\n <Alert severity={'error'} sx={{ my: 2 }}>\n {createAgentSessionError.reason}\n </Alert>\n )\n }\n }\n\n return (\n <Box\n sx={{\n display: 'flex',\n flexDirection: 'column',\n justifyContent: variant === 'curie' ? 'flex-start' : 'space-between',\n gap: variant === 'curie' ? '20px' : '0',\n maxWidth: '1100px',\n mx: 'auto',\n height: '100%',\n }}\n >\n {!hideTitle && (\n <Typography\n variant=\"headline1\"\n sx={{\n p: '20px',\n borderBottom: '1px solid',\n borderColor: 'grey.300',\n position: 'sticky',\n top: '0px',\n backgroundColor: 'white',\n zIndex: 1,\n }}\n >\n {chatbotName}\n </Typography>\n )}\n {showAccessLevelMenu && variant !== 'curie' && isAuthenticated && (\n <AccessLevelMenu\n initAccessLevel={agentAccessLevel}\n onChange={newAccessLevel => {\n setAgentAccessLevel(newAccessLevel)\n updateAgentSession({\n agentAccessLevel: newAccessLevel,\n sessionId: agentSession!.sessionId!,\n })\n }}\n />\n )}\n {!agentSession && <SkeletonParagraph numRows={10} />}\n {agentSession && (\n <Box\n sx={{\n flexGrow: 1,\n overflowY: 'auto',\n mb: variant === 'curie' ? 0 : 2,\n }}\n >\n <List\n sx={{\n flex: 1,\n overflowY: 'auto',\n pt: '20px',\n ...(variant === 'curie' && { pt: 0, pb: 0, gap: '20px' }),\n display: 'flex',\n flexDirection: 'column',\n ...(showGreeting && {\n minHeight: '100%',\n justifyContent: 'flex-end',\n }),\n }}\n >\n {/* {sessionHistory &&\n sessionHistory.map((interaction, index) => {\n return (\n <SynapseChatInteraction\n key={index}\n userMessage={interaction.usersRequestText}\n chatResponseText={interaction.agentResponseText}\n />\n )\n })} */}\n {showGreeting && (\n <ListItem\n sx={{\n display: 'grid',\n gridTemplateColumns: '50px auto',\n columnGap: '16px',\n justifyItems: 'start',\n alignItems: 'start',\n p: 0,\n }}\n >\n {resolvedAgentAvatar}\n <Typography sx={{ justifySelf: 'start', mt: '14px' }}>\n {CURIE_GREETING}\n </Typography>\n </ListItem>\n )}\n {interactions.map((interaction, index) => {\n const isLast = index === interactions.length - 1\n return (\n <SynapseChatMessage\n agentAvatar={resolvedAgentAvatar}\n userAvatar={userAvatar}\n key={interaction.id}\n userMessage={interaction.userMessage}\n chatJobId={interaction.jobId}\n showLoadingIcon={variant !== 'curie'}\n onSendChat={sendChat}\n scrollIntoView={isLast}\n animateEntry={!presentAtMount.has(interaction.id)}\n isAwaitingResponse={isAwaitingResponse}\n pendingAttachments={\n // Only one interaction can be in flight at a time (the composer is disabled\n // while isAwaitingResponse), so lastSentAttachments always corresponds to\n // whichever interaction is last.\n isLast ? lastSentAttachments : undefined\n }\n />\n )\n })}\n </List>\n </Box>\n )}\n <Box\n sx={{\n position: 'sticky',\n bottom: variant === 'curie' ? '0px' : textboxPositionOffset,\n backgroundColor: 'white',\n }}\n >\n {suggestedPrompts &&\n suggestedPrompts.length > 0 &&\n interactions.length === 0 && (\n <Stack\n direction=\"row\"\n spacing={1}\n sx={{ pt: '8px', flexWrap: 'wrap', gap: 1 }}\n >\n {suggestedPrompts.map(prompt => (\n <Chip\n key={prompt}\n label={prompt}\n variant=\"outlined\"\n onClick={() => setUserChatTextfieldValue(prompt)}\n disabled={!agentSession}\n sx={{ cursor: 'pointer' }}\n />\n ))}\n </Stack>\n )}\n <Box sx={{ mt: '5px' }}>\n <ChatInputArea\n value={userChatTextfieldValue}\n onValueChange={setUserChatTextfieldValue}\n onSend={handleSend}\n placeholder={\n variant === 'curie' ? 'Ask anything' : `Message ${chatbotName}`\n }\n disabled={!agentSession || isAwaitingResponse}\n allowAttachments={allowAttachments}\n />\n </Box>\n </Box>\n <Typography variant=\"smallText1\" sx={{ pt: '8px', textAlign: 'center' }}>\n {disclaimerText}\n </Typography>\n </Box>\n )\n}\n\nexport default SynapseChat\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"SynapseChatInteraction.d.ts","sourceRoot":"","sources":["../../../src/components/SynapseChat/SynapseChatInteraction.tsx"],"names":[],"mappings":"AAiBA,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AAQ5D,OAAO,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAA;AAE5E;;;;;GAKG;AACH,MAAM,MAAM,gCAAgC,GAAG;IAC7C,YAAY,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,2BAA2B,GAAG;IACxC,WAAW,EAAE,MAAM,CAAA;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,iBAAiB,CAAC,EAAE,UAAU,EAAE,CAAA;IAChC,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IACtC,WAAW,EAAE,KAAK,CAAC,SAAS,CAAA;IAC5B,UAAU,EAAE,KAAK,CAAC,SAAS,CAAA;IAC3B,sFAAsF;IACtF,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,6GAA6G;IAC7G,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,2DAA2D;IAC3D,WAAW,CAAC,EAAE,gCAAgC,EAAE,CAAA;IAChD,sHAAsH;IACtH,kBAAkB,CAAC,EAAE,yBAAyB,EAAE,CAAA;IAChD,gFAAgF;IAChF,eAAe,CAAC,EAAE,OAAO,CAAA;CAC1B,CAAA;AAqBD,wBAAgB,sBAAsB,CAAC,EACrC,WAAW,EACX,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,cAAsB,EACtB,UAAU,EACV,WAAW,EACX,UAAU,EACV,YAAoB,EACpB,kBAA0B,EAC1B,WAAW,EACX,kBAAkB,EAClB,eAAsB,GACvB,EAAE,2BAA2B,2CAqP7B;AAED,eAAe,sBAAsB,CAAA"}
1
+ {"version":3,"file":"SynapseChatInteraction.d.ts","sourceRoot":"","sources":["../../../src/components/SynapseChat/SynapseChatInteraction.tsx"],"names":[],"mappings":"AAkBA,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AAQ5D,OAAO,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAA;AAE5E;;;;;GAKG;AACH,MAAM,MAAM,gCAAgC,GAAG;IAC7C,YAAY,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,2BAA2B,GAAG;IACxC,WAAW,EAAE,MAAM,CAAA;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,iBAAiB,CAAC,EAAE,UAAU,EAAE,CAAA;IAChC,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IACtC,WAAW,EAAE,KAAK,CAAC,SAAS,CAAA;IAC5B,UAAU,EAAE,KAAK,CAAC,SAAS,CAAA;IAC3B,sFAAsF;IACtF,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,6GAA6G;IAC7G,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,2DAA2D;IAC3D,WAAW,CAAC,EAAE,gCAAgC,EAAE,CAAA;IAChD,sHAAsH;IACtH,kBAAkB,CAAC,EAAE,yBAAyB,EAAE,CAAA;IAChD,gFAAgF;IAChF,eAAe,CAAC,EAAE,OAAO,CAAA;CAC1B,CAAA;AAqBD,wBAAgB,sBAAsB,CAAC,EACrC,WAAW,EACX,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,cAAsB,EACtB,UAAU,EACV,WAAW,EACX,UAAU,EACV,YAAoB,EACpB,kBAA0B,EAC1B,WAAW,EACX,kBAAkB,EAClB,eAAsB,GACvB,EAAE,2BAA2B,2CAqP7B;AAED,eAAe,sBAAsB,CAAA"}
@@ -6,7 +6,8 @@ import i from "./SynapseChatInteraction.module.js";
6
6
  import { useEffect as a, useMemo as o, useRef as s, useState as c } from "react";
7
7
  import { Alert as l, Box as u, Button as d, Chip as f, Collapse as p, ListItem as m, ListItemText as h, Stack as g, Tooltip as _, useTheme as v } from "@mui/material";
8
8
  import { Fragment as y, jsx as b, jsxs as x } from "react/jsx-runtime";
9
- import { KeyboardArrowDown as S, KeyboardArrowRight as C } from "@mui/icons-material";
9
+ import S from "@mui/icons-material/KeyboardArrowDown";
10
+ import C from "@mui/icons-material/KeyboardArrowRight";
10
11
  //#region src/components/SynapseChat/SynapseChatInteraction.tsx
11
12
  function w(e) {
12
13
  return "reasoningText" in e ? e.reasoningText : "";
@@ -1 +1 @@
1
- {"version":3,"file":"SynapseChatInteraction.js","names":[],"sources":["../../../src/components/SynapseChat/SynapseChatInteraction.tsx"],"sourcesContent":["import { SynapseSpinner } from '@/components/LoadingScreen/LoadingScreen'\nimport extractMessageFromTraceEvent, {\n TraceMessage,\n} from '@/components/SynapseChat/extractMessageFromTraceEvent'\nimport { KeyboardArrowDown, KeyboardArrowRight } from '@mui/icons-material'\nimport {\n Alert,\n Box,\n Button,\n Chip,\n Collapse,\n ListItem,\n ListItemText,\n Stack,\n Tooltip,\n useTheme,\n} from '@mui/material'\nimport { TraceEvent } from '@sage-bionetworks/synapse-types'\nimport { useEffect, useMemo, useRef, useState } from 'react'\nimport MarkdownSynapse from '../Markdown/MarkdownSynapse'\nimport styles from './SynapseChatInteraction.module.scss'\nimport {\n AttachmentStripItem,\n ChatAttachmentStrip,\n} from './components/ChatAttachmentStrip/ChatAttachmentStrip'\nimport { AgentChatAttachmentStatus } from '@sage-bionetworks/synapse-client'\n\n/**\n * A chat attachment to display on a sent/pending turn. Only `fileHandleId` is guaranteed --\n * `fileName`/`contentType` are omitted for a turn restored from history, where only the\n * fileHandleId that was sent to the server is known, with no in-session upload record to fall\n * back on (see SynapseChatMessage).\n */\nexport type SynapseChatInteractionAttachment = {\n fileHandleId: string\n fileName?: string\n contentType?: string\n}\n\nexport type SynapseChatInteractionProps = {\n userMessage: string\n chatResponseText?: string\n chatResponseTrace?: TraceEvent[]\n scrollIntoView?: boolean\n chatErrorReason?: string\n onSendChat?: (message: string) => void\n agentAvatar: React.ReactNode\n userAvatar: React.ReactNode\n /** Whether to play the fade/rise-in entry animation for this interaction on mount. */\n animateEntry?: boolean\n /** Whether a turn is currently in flight; gates the guide-prompt chips so they can't bypass the composer. */\n isAwaitingResponse?: boolean\n /** Attachments the user sent with this message, if any. */\n attachments?: SynapseChatInteractionAttachment[]\n /** Server-reported outcome of staging each attachment, if available (see AgentChatResponseWithAttachmentStatuses). */\n attachmentStatuses?: AgentChatAttachmentStatus[]\n /** Whether to show the loading spinner icon while the response is in flight. */\n showLoadingIcon?: boolean\n}\n\n// Show tool calls in the trace. Useful for development. We may want to show them to users in the future.\nconst SHOW_TOOL_USE = false\n\nfunction getMarkdownForTraceMessage(traceMessage: TraceMessage): string {\n if ('reasoningText' in traceMessage) {\n return traceMessage.reasoningText\n }\n if (SHOW_TOOL_USE && 'toolName' in traceMessage) {\n return `**Tool Used:** \\`${\n traceMessage.toolName\n }\\`\\n\\n**Tool Input:**\\n\\`\\`\\`json\\n${JSON.stringify(\n traceMessage.toolInput,\n null,\n 2,\n )}\\n\\`\\`\\`\\n`\n }\n return ''\n}\n\nexport function SynapseChatInteraction({\n userMessage,\n chatResponseText,\n chatErrorReason,\n chatResponseTrace,\n scrollIntoView = false,\n onSendChat,\n agentAvatar,\n userAvatar,\n animateEntry = false,\n isAwaitingResponse = false,\n attachments,\n attachmentStatuses,\n showLoadingIcon = true,\n}: SynapseChatInteractionProps) {\n const theme = useTheme()\n const userMessageRef = useRef<HTMLLIElement | null>(null)\n const responseRef = useRef<HTMLLIElement | null>(null)\n const [showTrace, setShowTrace] = useState(false)\n\n const isLoading = !chatResponseText && !chatErrorReason\n\n useEffect(() => {\n // on mount, scroll into view if instructed. This brings the \"Thinking...\" row to the top so\n // the answer's opening lines are usually visible as soon as it starts streaming in.\n if (scrollIntoView) {\n userMessageRef.current?.scrollIntoView({ behavior: 'smooth' })\n }\n }, [scrollIntoView])\n\n useEffect(() => {\n // once the response (or an error) arrives, scroll all the way to the bottom so the full\n // answer - which may be taller than the viewport - is brought into view.\n if (scrollIntoView && !isLoading) {\n responseRef.current?.scrollIntoView({ behavior: 'smooth', block: 'end' })\n }\n }, [scrollIntoView, isLoading])\n\n const traceMessages = useMemo(\n () =>\n (chatResponseTrace ?? [])\n .flatMap(traceEvent => extractMessageFromTraceEvent(traceEvent))\n ?.filter(trace => !!trace),\n [chatResponseTrace],\n )\n\n const hasTraceInfo = traceMessages.length > 0\n\n const lastReasoningMessage = useMemo(\n () => traceMessages.filter(trace => 'reasoningText' in trace).at(-1),\n [traceMessages],\n )\n\n const traceButtonLoadingText =\n lastReasoningMessage == null\n ? 'Thinking...'\n : lastReasoningMessage.reasoningText\n\n const traceButtonText = isLoading\n ? traceButtonLoadingText\n : `${showTrace ? 'Hide' : 'Show'} Trace`\n\n const { textContent, guidePrompts } = useMemo(() => {\n try {\n const parser = new DOMParser()\n const doc = parser.parseFromString(chatResponseText ?? '', 'text/html')\n\n // Remove tool_name and actions elements (AI XML tags not for display)\n doc\n .querySelectorAll('tool_name, actions')\n .forEach(element => element.remove())\n\n // Extract guideprompts before removing them\n const extractedGuidePrompts = Array.from(\n doc.querySelectorAll('guideprompt'),\n )\n .map(el => el.textContent?.trim())\n .filter((t): t is string => !!t)\n\n // Remove guideprompt elements\n doc.querySelectorAll('guideprompt').forEach(element => element.remove())\n\n // Extract text from <chat> element if present, otherwise use full body text\n const chatElement = doc.querySelector('chat')\n return {\n textContent: chatElement\n ? (chatElement.textContent ?? '')\n : (doc.body.textContent ?? ''),\n guidePrompts: extractedGuidePrompts,\n }\n } catch (e) {\n console.error(e)\n return { textContent: chatResponseText ?? '', guidePrompts: [] }\n }\n }, [chatResponseText])\n\n const attachmentItems: AttachmentStripItem[] = useMemo(\n () =>\n (attachments ?? []).map(attachment => {\n const status = attachmentStatuses?.find(\n s => s.fileHandleId === attachment.fileHandleId,\n )\n return {\n fileHandleId: attachment.fileHandleId,\n label: attachment.fileName ?? attachment.fileHandleId,\n contentType: attachment.contentType,\n status: status?.status === 'FAILED' ? 'failed' : 'default',\n errorMessage: status?.failureMessage,\n }\n }),\n [attachments, attachmentStatuses],\n )\n\n return (\n <>\n <ListItem\n ref={userMessageRef}\n sx={{\n alignSelf: 'flex-end',\n maxWidth: '82%',\n mb: '5px',\n wordWrap: 'break-word',\n width: 'auto',\n display: 'grid',\n gridTemplateColumns: 'auto auto',\n columnGap: '16px',\n alignItems: 'start',\n justifyItems: 'end',\n }}\n >\n <Box\n className={animateEntry ? styles.entryAnimation : undefined}\n sx={{\n p: '4px 14px',\n backgroundColor: '#F3F6F7',\n borderRadius: '8px',\n }}\n >\n <ListItemText primary={userMessage} />\n </Box>\n <Box sx={{ marginTop: '4px' }}>{userAvatar}</Box>\n </ListItem>\n {attachmentItems.length > 0 && (\n <ListItem sx={{ display: 'block', p: '0px', mb: '5px' }}>\n <ChatAttachmentStrip items={attachmentItems} wrap />\n </ListItem>\n )}\n <ListItem\n ref={responseRef}\n sx={{\n display: 'grid',\n gridTemplateColumns: '50px auto',\n columnGap: '16px',\n justifyItems: 'center',\n alignItems: 'start',\n p: '0px',\n padding: '10px',\n }}\n >\n {agentAvatar}\n <Box\n sx={{\n borderRadius: '10px',\n maxWidth: '100%',\n overflow: 'auto',\n }}\n >\n <Box\n component={'aside'}\n sx={{\n '.markdown': {\n fontStyle: 'italic',\n borderLeft: `4px solid ${theme.palette.grey[300]}`,\n marginLeft: '4px',\n paddingLeft: '8px',\n mt: 1,\n mb: 2,\n },\n }}\n >\n <Button\n variant={'outlined'}\n size={'small'}\n startIcon={\n isLoading ? (\n showLoadingIcon ? (\n <SynapseSpinner size={14} />\n ) : undefined\n ) : showTrace ? (\n <KeyboardArrowDown sx={{ width: '14px' }} />\n ) : (\n <KeyboardArrowRight sx={{ width: '14px' }} />\n )\n }\n disabled={!hasTraceInfo}\n onClick={() => {\n setShowTrace(v => !v)\n }}\n sx={{\n height: '20px',\n fontSize: '12px',\n fontWeight: 600,\n mb: 1,\n border: 'none !important',\n color: 'grey.700',\n justifyContent: 'flex-start',\n whiteSpace: 'nowrap',\n maxWidth: '325px',\n textTransform: 'none',\n pl: 0,\n '.MuiButton-startIcon': { mr: 0.5 },\n }}\n >\n <Box sx={{ overflow: 'hidden', textOverflow: 'ellipsis' }}>\n {traceButtonText}\n </Box>\n </Button>\n {chatResponseTrace && (\n <Collapse in={showTrace}>\n <MarkdownSynapse\n markdown={traceMessages\n .map(getMarkdownForTraceMessage)\n .filter(md => md.trim().length > 0)\n .join('<br/><br/>')}\n />\n </Collapse>\n )}\n </Box>\n {(textContent || (onSendChat && guidePrompts.length > 0)) && (\n <Box className={animateEntry ? styles.entryAnimation : undefined}>\n {textContent && <MarkdownSynapse markdown={textContent} />}\n {onSendChat && guidePrompts.length > 0 && (\n <Stack direction=\"row\" flexWrap=\"wrap\" gap={1} mt={1}>\n {guidePrompts.map(prompt => (\n <Tooltip key={prompt} title={prompt}>\n <Chip\n label={prompt}\n variant=\"outlined\"\n color=\"primary\"\n clickable\n disabled={isAwaitingResponse}\n onClick={() => onSendChat(prompt)}\n sx={{ maxWidth: 200 }}\n />\n </Tooltip>\n ))}\n </Stack>\n )}\n </Box>\n )}\n </Box>\n </ListItem>\n {chatErrorReason && (\n <Alert severity={'error'} sx={{ my: 2 }}>\n {chatErrorReason}\n </Alert>\n )}\n </>\n )\n}\n\nexport default SynapseChatInteraction\n"],"mappings":"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"}
1
+ {"version":3,"file":"SynapseChatInteraction.js","names":[],"sources":["../../../src/components/SynapseChat/SynapseChatInteraction.tsx"],"sourcesContent":["import { SynapseSpinner } from '@/components/LoadingScreen/LoadingScreen'\nimport extractMessageFromTraceEvent, {\n TraceMessage,\n} from '@/components/SynapseChat/extractMessageFromTraceEvent'\nimport KeyboardArrowDown from '@mui/icons-material/KeyboardArrowDown'\nimport KeyboardArrowRight from '@mui/icons-material/KeyboardArrowRight'\nimport {\n Alert,\n Box,\n Button,\n Chip,\n Collapse,\n ListItem,\n ListItemText,\n Stack,\n Tooltip,\n useTheme,\n} from '@mui/material'\nimport { TraceEvent } from '@sage-bionetworks/synapse-types'\nimport { useEffect, useMemo, useRef, useState } from 'react'\nimport MarkdownSynapse from '../Markdown/MarkdownSynapse'\nimport styles from './SynapseChatInteraction.module.scss'\nimport {\n AttachmentStripItem,\n ChatAttachmentStrip,\n} from './components/ChatAttachmentStrip/ChatAttachmentStrip'\nimport { AgentChatAttachmentStatus } from '@sage-bionetworks/synapse-client'\n\n/**\n * A chat attachment to display on a sent/pending turn. Only `fileHandleId` is guaranteed --\n * `fileName`/`contentType` are omitted for a turn restored from history, where only the\n * fileHandleId that was sent to the server is known, with no in-session upload record to fall\n * back on (see SynapseChatMessage).\n */\nexport type SynapseChatInteractionAttachment = {\n fileHandleId: string\n fileName?: string\n contentType?: string\n}\n\nexport type SynapseChatInteractionProps = {\n userMessage: string\n chatResponseText?: string\n chatResponseTrace?: TraceEvent[]\n scrollIntoView?: boolean\n chatErrorReason?: string\n onSendChat?: (message: string) => void\n agentAvatar: React.ReactNode\n userAvatar: React.ReactNode\n /** Whether to play the fade/rise-in entry animation for this interaction on mount. */\n animateEntry?: boolean\n /** Whether a turn is currently in flight; gates the guide-prompt chips so they can't bypass the composer. */\n isAwaitingResponse?: boolean\n /** Attachments the user sent with this message, if any. */\n attachments?: SynapseChatInteractionAttachment[]\n /** Server-reported outcome of staging each attachment, if available (see AgentChatResponseWithAttachmentStatuses). */\n attachmentStatuses?: AgentChatAttachmentStatus[]\n /** Whether to show the loading spinner icon while the response is in flight. */\n showLoadingIcon?: boolean\n}\n\n// Show tool calls in the trace. Useful for development. We may want to show them to users in the future.\nconst SHOW_TOOL_USE = false\n\nfunction getMarkdownForTraceMessage(traceMessage: TraceMessage): string {\n if ('reasoningText' in traceMessage) {\n return traceMessage.reasoningText\n }\n if (SHOW_TOOL_USE && 'toolName' in traceMessage) {\n return `**Tool Used:** \\`${\n traceMessage.toolName\n }\\`\\n\\n**Tool Input:**\\n\\`\\`\\`json\\n${JSON.stringify(\n traceMessage.toolInput,\n null,\n 2,\n )}\\n\\`\\`\\`\\n`\n }\n return ''\n}\n\nexport function SynapseChatInteraction({\n userMessage,\n chatResponseText,\n chatErrorReason,\n chatResponseTrace,\n scrollIntoView = false,\n onSendChat,\n agentAvatar,\n userAvatar,\n animateEntry = false,\n isAwaitingResponse = false,\n attachments,\n attachmentStatuses,\n showLoadingIcon = true,\n}: SynapseChatInteractionProps) {\n const theme = useTheme()\n const userMessageRef = useRef<HTMLLIElement | null>(null)\n const responseRef = useRef<HTMLLIElement | null>(null)\n const [showTrace, setShowTrace] = useState(false)\n\n const isLoading = !chatResponseText && !chatErrorReason\n\n useEffect(() => {\n // on mount, scroll into view if instructed. This brings the \"Thinking...\" row to the top so\n // the answer's opening lines are usually visible as soon as it starts streaming in.\n if (scrollIntoView) {\n userMessageRef.current?.scrollIntoView({ behavior: 'smooth' })\n }\n }, [scrollIntoView])\n\n useEffect(() => {\n // once the response (or an error) arrives, scroll all the way to the bottom so the full\n // answer - which may be taller than the viewport - is brought into view.\n if (scrollIntoView && !isLoading) {\n responseRef.current?.scrollIntoView({ behavior: 'smooth', block: 'end' })\n }\n }, [scrollIntoView, isLoading])\n\n const traceMessages = useMemo(\n () =>\n (chatResponseTrace ?? [])\n .flatMap(traceEvent => extractMessageFromTraceEvent(traceEvent))\n ?.filter(trace => !!trace),\n [chatResponseTrace],\n )\n\n const hasTraceInfo = traceMessages.length > 0\n\n const lastReasoningMessage = useMemo(\n () => traceMessages.filter(trace => 'reasoningText' in trace).at(-1),\n [traceMessages],\n )\n\n const traceButtonLoadingText =\n lastReasoningMessage == null\n ? 'Thinking...'\n : lastReasoningMessage.reasoningText\n\n const traceButtonText = isLoading\n ? traceButtonLoadingText\n : `${showTrace ? 'Hide' : 'Show'} Trace`\n\n const { textContent, guidePrompts } = useMemo(() => {\n try {\n const parser = new DOMParser()\n const doc = parser.parseFromString(chatResponseText ?? '', 'text/html')\n\n // Remove tool_name and actions elements (AI XML tags not for display)\n doc\n .querySelectorAll('tool_name, actions')\n .forEach(element => element.remove())\n\n // Extract guideprompts before removing them\n const extractedGuidePrompts = Array.from(\n doc.querySelectorAll('guideprompt'),\n )\n .map(el => el.textContent?.trim())\n .filter((t): t is string => !!t)\n\n // Remove guideprompt elements\n doc.querySelectorAll('guideprompt').forEach(element => element.remove())\n\n // Extract text from <chat> element if present, otherwise use full body text\n const chatElement = doc.querySelector('chat')\n return {\n textContent: chatElement\n ? (chatElement.textContent ?? '')\n : (doc.body.textContent ?? ''),\n guidePrompts: extractedGuidePrompts,\n }\n } catch (e) {\n console.error(e)\n return { textContent: chatResponseText ?? '', guidePrompts: [] }\n }\n }, [chatResponseText])\n\n const attachmentItems: AttachmentStripItem[] = useMemo(\n () =>\n (attachments ?? []).map(attachment => {\n const status = attachmentStatuses?.find(\n s => s.fileHandleId === attachment.fileHandleId,\n )\n return {\n fileHandleId: attachment.fileHandleId,\n label: attachment.fileName ?? attachment.fileHandleId,\n contentType: attachment.contentType,\n status: status?.status === 'FAILED' ? 'failed' : 'default',\n errorMessage: status?.failureMessage,\n }\n }),\n [attachments, attachmentStatuses],\n )\n\n return (\n <>\n <ListItem\n ref={userMessageRef}\n sx={{\n alignSelf: 'flex-end',\n maxWidth: '82%',\n mb: '5px',\n wordWrap: 'break-word',\n width: 'auto',\n display: 'grid',\n gridTemplateColumns: 'auto auto',\n columnGap: '16px',\n alignItems: 'start',\n justifyItems: 'end',\n }}\n >\n <Box\n className={animateEntry ? styles.entryAnimation : undefined}\n sx={{\n p: '4px 14px',\n backgroundColor: '#F3F6F7',\n borderRadius: '8px',\n }}\n >\n <ListItemText primary={userMessage} />\n </Box>\n <Box sx={{ marginTop: '4px' }}>{userAvatar}</Box>\n </ListItem>\n {attachmentItems.length > 0 && (\n <ListItem sx={{ display: 'block', p: '0px', mb: '5px' }}>\n <ChatAttachmentStrip items={attachmentItems} wrap />\n </ListItem>\n )}\n <ListItem\n ref={responseRef}\n sx={{\n display: 'grid',\n gridTemplateColumns: '50px auto',\n columnGap: '16px',\n justifyItems: 'center',\n alignItems: 'start',\n p: '0px',\n padding: '10px',\n }}\n >\n {agentAvatar}\n <Box\n sx={{\n borderRadius: '10px',\n maxWidth: '100%',\n overflow: 'auto',\n }}\n >\n <Box\n component={'aside'}\n sx={{\n '.markdown': {\n fontStyle: 'italic',\n borderLeft: `4px solid ${theme.palette.grey[300]}`,\n marginLeft: '4px',\n paddingLeft: '8px',\n mt: 1,\n mb: 2,\n },\n }}\n >\n <Button\n variant={'outlined'}\n size={'small'}\n startIcon={\n isLoading ? (\n showLoadingIcon ? (\n <SynapseSpinner size={14} />\n ) : undefined\n ) : showTrace ? (\n <KeyboardArrowDown sx={{ width: '14px' }} />\n ) : (\n <KeyboardArrowRight sx={{ width: '14px' }} />\n )\n }\n disabled={!hasTraceInfo}\n onClick={() => {\n setShowTrace(v => !v)\n }}\n sx={{\n height: '20px',\n fontSize: '12px',\n fontWeight: 600,\n mb: 1,\n border: 'none !important',\n color: 'grey.700',\n justifyContent: 'flex-start',\n whiteSpace: 'nowrap',\n maxWidth: '325px',\n textTransform: 'none',\n pl: 0,\n '.MuiButton-startIcon': { mr: 0.5 },\n }}\n >\n <Box sx={{ overflow: 'hidden', textOverflow: 'ellipsis' }}>\n {traceButtonText}\n </Box>\n </Button>\n {chatResponseTrace && (\n <Collapse in={showTrace}>\n <MarkdownSynapse\n markdown={traceMessages\n .map(getMarkdownForTraceMessage)\n .filter(md => md.trim().length > 0)\n .join('<br/><br/>')}\n />\n </Collapse>\n )}\n </Box>\n {(textContent || (onSendChat && guidePrompts.length > 0)) && (\n <Box className={animateEntry ? styles.entryAnimation : undefined}>\n {textContent && <MarkdownSynapse markdown={textContent} />}\n {onSendChat && guidePrompts.length > 0 && (\n <Stack direction=\"row\" flexWrap=\"wrap\" gap={1} mt={1}>\n {guidePrompts.map(prompt => (\n <Tooltip key={prompt} title={prompt}>\n <Chip\n label={prompt}\n variant=\"outlined\"\n color=\"primary\"\n clickable\n disabled={isAwaitingResponse}\n onClick={() => onSendChat(prompt)}\n sx={{ maxWidth: 200 }}\n />\n </Tooltip>\n ))}\n </Stack>\n )}\n </Box>\n )}\n </Box>\n </ListItem>\n {chatErrorReason && (\n <Alert severity={'error'} sx={{ my: 2 }}>\n {chatErrorReason}\n </Alert>\n )}\n </>\n )\n}\n\nexport default SynapseChatInteraction\n"],"mappings":"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"}