@elyx-code/editor-ui 0.0.2

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 (452) hide show
  1. package/README.md +2 -0
  2. package/package.json +109 -0
  3. package/src/App.tsx +31 -0
  4. package/src/Router.tsx +115 -0
  5. package/src/__mocks__/defaultModuleMock.ts +1 -0
  6. package/src/__mocks__/fileMock.ts +1 -0
  7. package/src/__mocks__/styleMock.ts +1 -0
  8. package/src/assets/Clock-11.1s-18px.svg +16 -0
  9. package/src/assets/Clock-11.1s-28px.svg +16 -0
  10. package/src/assets/authentication.svg +1 -0
  11. package/src/assets/canvas-backdrop-0.png +0 -0
  12. package/src/assets/canvas-backdrop-1.png +0 -0
  13. package/src/assets/canvas-backdrop-2.png +0 -0
  14. package/src/assets/canvas-backdrop-3.png +0 -0
  15. package/src/assets/canvas-backdrop-4.png +0 -0
  16. package/src/assets/canvas-backdrop-5.png +0 -0
  17. package/src/assets/canvas-backdrop.png +0 -0
  18. package/src/assets/checkmark-animation.gif +0 -0
  19. package/src/assets/checkmark-animation.mp4 +0 -0
  20. package/src/assets/code-formatting/format-black.svg +6 -0
  21. package/src/assets/code-formatting/format-dark-grey.svg +6 -0
  22. package/src/assets/code-formatting/format-light-grey.svg +6 -0
  23. package/src/assets/code-formatting/format-white.svg +6 -0
  24. package/src/assets/code-formatting/inline-black.svg +5 -0
  25. package/src/assets/code-formatting/inline-dark-grey.svg +5 -0
  26. package/src/assets/code-formatting/inline-light-grey.svg +5 -0
  27. package/src/assets/code-formatting/inline-white.svg +5 -0
  28. package/src/assets/contained-logo-full-word.png +0 -0
  29. package/src/assets/cron-job-color.png +0 -0
  30. package/src/assets/cron-job.png +0 -0
  31. package/src/assets/database-table-color.png +0 -0
  32. package/src/assets/database-table.png +0 -0
  33. package/src/assets/datatype-icons/black/any.svg +1 -0
  34. package/src/assets/datatype-icons/black/binary.svg +1 -0
  35. package/src/assets/datatype-icons/black/boolean.svg +3 -0
  36. package/src/assets/datatype-icons/black/date-time.svg +3 -0
  37. package/src/assets/datatype-icons/black/definition-entity.svg +6 -0
  38. package/src/assets/datatype-icons/black/key-file.svg +1 -0
  39. package/src/assets/datatype-icons/black/list.svg +3 -0
  40. package/src/assets/datatype-icons/black/null.svg +3 -0
  41. package/src/assets/datatype-icons/black/number.svg +13 -0
  42. package/src/assets/datatype-icons/black/project.svg +12 -0
  43. package/src/assets/datatype-icons/black/sql-program.svg +2 -0
  44. package/src/assets/datatype-icons/black/text.svg +3 -0
  45. package/src/assets/datatype-icons/black/unknown.svg +3 -0
  46. package/src/assets/datatype-icons/black/uuid.svg +4 -0
  47. package/src/assets/datatype-icons/black/void.svg +1 -0
  48. package/src/assets/datatype-icons/dark-grey/any.svg +1 -0
  49. package/src/assets/datatype-icons/dark-grey/boolean.svg +3 -0
  50. package/src/assets/datatype-icons/dark-grey/date-time.svg +3 -0
  51. package/src/assets/datatype-icons/dark-grey/definition-entity.svg +6 -0
  52. package/src/assets/datatype-icons/dark-grey/list.svg +3 -0
  53. package/src/assets/datatype-icons/dark-grey/null.svg +3 -0
  54. package/src/assets/datatype-icons/dark-grey/number.svg +13 -0
  55. package/src/assets/datatype-icons/dark-grey/project.svg +12 -0
  56. package/src/assets/datatype-icons/dark-grey/sql-program.svg +2 -0
  57. package/src/assets/datatype-icons/dark-grey/text.svg +3 -0
  58. package/src/assets/datatype-icons/dark-grey/unknown.svg +3 -0
  59. package/src/assets/datatype-icons/dark-grey/uuid.svg +4 -0
  60. package/src/assets/datatype-icons/dark-grey/void.svg +1 -0
  61. package/src/assets/datatype-icons/light-grey/any.svg +1 -0
  62. package/src/assets/datatype-icons/light-grey/boolean.svg +3 -0
  63. package/src/assets/datatype-icons/light-grey/date-time.svg +3 -0
  64. package/src/assets/datatype-icons/light-grey/definition-entity.svg +6 -0
  65. package/src/assets/datatype-icons/light-grey/list.svg +3 -0
  66. package/src/assets/datatype-icons/light-grey/null.svg +3 -0
  67. package/src/assets/datatype-icons/light-grey/number.svg +13 -0
  68. package/src/assets/datatype-icons/light-grey/project.svg +12 -0
  69. package/src/assets/datatype-icons/light-grey/sql-program.svg +2 -0
  70. package/src/assets/datatype-icons/light-grey/text.svg +3 -0
  71. package/src/assets/datatype-icons/light-grey/unknown.svg +3 -0
  72. package/src/assets/datatype-icons/light-grey/uuid.svg +4 -0
  73. package/src/assets/datatype-icons/light-grey/void.svg +1 -0
  74. package/src/assets/edit.png +0 -0
  75. package/src/assets/execution.svg +13 -0
  76. package/src/assets/favicon.svg +14 -0
  77. package/src/assets/file-search.svg +1 -0
  78. package/src/assets/http-endpoint.png +0 -0
  79. package/src/assets/image-input-placeholder.png +0 -0
  80. package/src/assets/logo-full-word-white.png +0 -0
  81. package/src/assets/logo-full-word.png +0 -0
  82. package/src/assets/password.svg +85 -0
  83. package/src/assets/pencil.png +0 -0
  84. package/src/assets/publish-project-rich-icon-2.svg +1 -0
  85. package/src/assets/publish-project-rich-icon.svg +1 -0
  86. package/src/assets/relational-database.png +0 -0
  87. package/src/assets/resources.svg +3 -0
  88. package/src/assets/resume-icon-14px.png +0 -0
  89. package/src/assets/server.png +0 -0
  90. package/src/assets/small-status/checkmark.svg +4 -0
  91. package/src/assets/small-status/error.svg +4 -0
  92. package/src/assets/small-status/loading.svg +4 -0
  93. package/src/assets/small-status/skipped.svg +11 -0
  94. package/src/assets/sql-connection-config.svg +1 -0
  95. package/src/assets/sql-row-transformer.svg +1 -0
  96. package/src/assets/ssl-certificate-config.svg +1 -0
  97. package/src/assets/sync.svg +1 -0
  98. package/src/assets/testing-logic-icon.svg +1 -0
  99. package/src/assets/versions.svg +25 -0
  100. package/src/assets/visual-programming-icon.svg +1 -0
  101. package/src/assets/warning-sign-24px.png +0 -0
  102. package/src/auth/index.ts +318 -0
  103. package/src/components/DialogLoader.tsx +94 -0
  104. package/src/components/EntityDialogHeader.tsx +110 -0
  105. package/src/components/EntityDialogSectionHeader.tsx +214 -0
  106. package/src/components/GalleryAddExternalIntegrationInfoDialog.tsx +87 -0
  107. package/src/components/GenerateProjectStartingLogicPromptDialog.tsx +281 -0
  108. package/src/components/LegacyRouteRedirector.tsx +55 -0
  109. package/src/components/ProPlanChip.tsx +23 -0
  110. package/src/components/ReportBugDialog.tsx +412 -0
  111. package/src/components/RequestIntegrationAccessDialog.tsx +261 -0
  112. package/src/components/UseTemplateProjectDialog.tsx +193 -0
  113. package/src/components/WorkspaceLayout.tsx +152 -0
  114. package/src/components/animated-svg/AnimatedCheckmark.tsx +41 -0
  115. package/src/components/animated-svg/AnimatedCrossmark.tsx +51 -0
  116. package/src/components/animated-svg/AnimatedEmailSending.tsx +38 -0
  117. package/src/components/animated-svg/AnimatedLoading.tsx +72 -0
  118. package/src/components/animated-svg/animated-svg.css +239 -0
  119. package/src/components/canvas/Canvas.tsx +16 -0
  120. package/src/components/canvas/CreateEntityMenu.tsx +2020 -0
  121. package/src/components/canvas/canvas.css +10 -0
  122. package/src/components/canvas/create-entity-menu.css +579 -0
  123. package/src/components/canvas-search/CanvasSearch.tsx +501 -0
  124. package/src/components/canvas-search/canvas-search.css +126 -0
  125. package/src/components/canvas-settings-menu/CanvasSettingsMenuButton.tsx +515 -0
  126. package/src/components/canvas-settings-menu/canvas-settings-menu.css +96 -0
  127. package/src/components/circular-image-upload/CircularImageUpload.tsx +113 -0
  128. package/src/components/circular-image-upload/circular-image-upload.css +69 -0
  129. package/src/components/costs/CostsDialog.tsx +459 -0
  130. package/src/components/data-type/DataTypeBuilder.tsx +3127 -0
  131. package/src/components/data-type/data-type-builder.css +45 -0
  132. package/src/components/dialogs/BetaAcknowledgeDialog.tsx +43 -0
  133. package/src/components/dialogs/ComplexDataDialog.tsx +458 -0
  134. package/src/components/dialogs/CronBuilderDialog.tsx +2145 -0
  135. package/src/components/dialogs/ExternalIntegrationConnections.tsx +565 -0
  136. package/src/components/dialogs/JsonEditorDialog.tsx +1392 -0
  137. package/src/components/dialogs/StringEditorDialog.tsx +268 -0
  138. package/src/components/dialogs/argument-declaration/ArgumentDeclaration.tsx +1167 -0
  139. package/src/components/dialogs/argument-declaration/ArgumentDeclarationDialogContent.tsx +128 -0
  140. package/src/components/dialogs/beta-dialog.css +165 -0
  141. package/src/components/dialogs/condition/Condition.tsx +431 -0
  142. package/src/components/dialogs/condition/ConditionDialogContent.tsx +126 -0
  143. package/src/components/dialogs/definition-entity/DefinitionEntityDialogContent.tsx +973 -0
  144. package/src/components/dialogs/function-call/FunctionCall.tsx +442 -0
  145. package/src/components/dialogs/function-call/FunctionCallDialogContent.tsx +126 -0
  146. package/src/components/dialogs/function-declaration/FunctionDeclaration.tsx +926 -0
  147. package/src/components/dialogs/function-declaration/FunctionDeclarationDialogContent.tsx +124 -0
  148. package/src/components/dialogs/generating-project-starting-logic-overlay/GeneratingProjectStartingLogicOverlay.tsx +176 -0
  149. package/src/components/dialogs/generating-project-starting-logic-overlay/generating-project-starting-logic-overlay.css +13 -0
  150. package/src/components/dialogs/global-event/GlobalEvent.tsx +475 -0
  151. package/src/components/dialogs/global-event/GlobalEventDialogContent.tsx +126 -0
  152. package/src/components/dialogs/help/HelpDialog.tsx +217 -0
  153. package/src/components/dialogs/help/HelpDilalogHomeContent.tsx +178 -0
  154. package/src/components/dialogs/help/help-dialog.css +116 -0
  155. package/src/components/dialogs/help/help-icon/HelpIconButton.tsx +41 -0
  156. package/src/components/dialogs/help/help-icon/help-icon.css +9 -0
  157. package/src/components/dialogs/input-map/InputMap.tsx +635 -0
  158. package/src/components/dialogs/input-map/InputMapDialogContent.tsx +126 -0
  159. package/src/components/dialogs/json-editor-dialog.css +4 -0
  160. package/src/components/dialogs/loop/Loop.tsx +650 -0
  161. package/src/components/dialogs/loop/LoopDialogContent.tsx +122 -0
  162. package/src/components/dialogs/operation/Operation.tsx +440 -0
  163. package/src/components/dialogs/operation/OperationDialogContent.tsx +126 -0
  164. package/src/components/dialogs/output-map/OutputMap.tsx +536 -0
  165. package/src/components/dialogs/output-map/OutputMapDialogContent.tsx +126 -0
  166. package/src/components/dialogs/property/Property.tsx +1490 -0
  167. package/src/components/dialogs/property/PropertyDialogContent.tsx +106 -0
  168. package/src/components/dialogs/search-statement/ColumnSelector.tsx +334 -0
  169. package/src/components/dialogs/search-statement/ConditionBuilder.tsx +750 -0
  170. package/src/components/dialogs/search-statement/DataAggregationSection.tsx +621 -0
  171. package/src/components/dialogs/search-statement/DataSourceSelection.tsx +734 -0
  172. package/src/components/dialogs/search-statement/EntityMetadataSection.tsx +135 -0
  173. package/src/components/dialogs/search-statement/FilterConditionsSection.tsx +151 -0
  174. package/src/components/dialogs/search-statement/InlineInputMap.tsx +153 -0
  175. package/src/components/dialogs/search-statement/LiteralValue.tsx +616 -0
  176. package/src/components/dialogs/search-statement/MainSourceAndInputsSection.tsx +271 -0
  177. package/src/components/dialogs/search-statement/NestedSearchStatementBuilder.tsx +170 -0
  178. package/src/components/dialogs/search-statement/OutputFormatSection.tsx +1779 -0
  179. package/src/components/dialogs/search-statement/ResultsSection.tsx +344 -0
  180. package/src/components/dialogs/search-statement/SearchStatementBuilder.tsx +251 -0
  181. package/src/components/dialogs/search-statement/SearchStatementDialogContent.tsx +398 -0
  182. package/src/components/dialogs/search-statement/ValueSelector.tsx +766 -0
  183. package/src/components/dialogs/search-statement/search-statement-context.tsx +1630 -0
  184. package/src/components/dialogs/search-statement/search-statement-dialog.css +56 -0
  185. package/src/components/dialogs/search-statement/test.sql +111 -0
  186. package/src/components/dialogs/value-descriptor/ValueDescriptor.tsx +824 -0
  187. package/src/components/dialogs/value-descriptor/ValueDescriptorDialogContent.tsx +124 -0
  188. package/src/components/dialogs/variable-declaration/VariableDeclaration.tsx +836 -0
  189. package/src/components/dialogs/variable-declaration/VariableDeclarationDialogContent.tsx +106 -0
  190. package/src/components/dialogs/variable-instance/VariableInstance.tsx +443 -0
  191. package/src/components/dialogs/variable-instance/VariableInstanceDialogContent.tsx +124 -0
  192. package/src/components/draggable-entity-card/ArgumentDeclaration.tsx +736 -0
  193. package/src/components/draggable-entity-card/CollapseEntityButton.tsx +170 -0
  194. package/src/components/draggable-entity-card/ConditionCard.tsx +1062 -0
  195. package/src/components/draggable-entity-card/ConnectionDeleteButton.tsx +309 -0
  196. package/src/components/draggable-entity-card/DataTypeIcon.tsx +624 -0
  197. package/src/components/draggable-entity-card/DraggableEntityCard.tsx +617 -0
  198. package/src/components/draggable-entity-card/ErrorMapProperty.tsx +464 -0
  199. package/src/components/draggable-entity-card/EventCard.tsx +700 -0
  200. package/src/components/draggable-entity-card/ExecutionInProgressValue.tsx +327 -0
  201. package/src/components/draggable-entity-card/FunctionDeclarationCard.tsx +819 -0
  202. package/src/components/draggable-entity-card/InputMapProperty.tsx +1067 -0
  203. package/src/components/draggable-entity-card/InternalCall.tsx +978 -0
  204. package/src/components/draggable-entity-card/InternalCallExecutionNode.tsx +643 -0
  205. package/src/components/draggable-entity-card/LogicScopeCallerNode.tsx +262 -0
  206. package/src/components/draggable-entity-card/LoopCard.tsx +791 -0
  207. package/src/components/draggable-entity-card/MainValueInput.tsx +523 -0
  208. package/src/components/draggable-entity-card/MainValueOutput.tsx +458 -0
  209. package/src/components/draggable-entity-card/MethodDeclaration.tsx +1088 -0
  210. package/src/components/draggable-entity-card/NestedCondition.tsx +1025 -0
  211. package/src/components/draggable-entity-card/OutputMapProperty.tsx +843 -0
  212. package/src/components/draggable-entity-card/PassthroughEntityCard.tsx +1247 -0
  213. package/src/components/draggable-entity-card/ReturnedError.tsx +549 -0
  214. package/src/components/draggable-entity-card/SmallSuccessFailureNodes.tsx +523 -0
  215. package/src/components/draggable-entity-card/SuccessFailureNodes.tsx +509 -0
  216. package/src/components/draggable-entity-card/TestEntityButton.tsx +946 -0
  217. package/src/components/draggable-entity-card/TestMenu.tsx +523 -0
  218. package/src/components/draggable-entity-card/TestMenuValidationDropdown.tsx +84 -0
  219. package/src/components/draggable-entity-card/UnreachableMarker.tsx +114 -0
  220. package/src/components/draggable-entity-card/VariableCard.tsx +1577 -0
  221. package/src/components/draggable-entity-card/VariableScopeMarker.tsx +117 -0
  222. package/src/components/draggable-entity-card/collapse-entity-button.css +44 -0
  223. package/src/components/draggable-entity-card/definition-entity/DefinitionEntityCard.tsx +1181 -0
  224. package/src/components/draggable-entity-card/definition-entity/DefinitionEntityIcon.tsx +36 -0
  225. package/src/components/draggable-entity-card/definition-entity/DefinitionEntityProperty.tsx +478 -0
  226. package/src/components/draggable-entity-card/definition-entity/DynamicFooterActions.tsx +112 -0
  227. package/src/components/draggable-entity-card/definition-entity/actions/external-integration-connection/ExportCredentialsFooterAction.tsx +461 -0
  228. package/src/components/draggable-entity-card/definition-entity/actions/external-integration-connection/RestablishConnectionFooterAction.tsx +199 -0
  229. package/src/components/draggable-entity-card/definition-entity/actions/external-integration-connection/restablish-connection-footer-action.css +85 -0
  230. package/src/components/draggable-entity-card/definition-entity/actions/google-drive/GoogleDriveFilePickerAPIFooterAction.tsx +277 -0
  231. package/src/components/draggable-entity-card/definition-entity/actions/google-drive/google-drive-file-picker-api-footer-action.css +107 -0
  232. package/src/components/draggable-entity-card/definition-entity/actions/persisted-entity/DatabaseFooterAction.tsx +452 -0
  233. package/src/components/draggable-entity-card/definition-entity/actions/persisted-entity/database-footer-action.css +86 -0
  234. package/src/components/draggable-entity-card/definition-entity/definition-entity-card.css +17 -0
  235. package/src/components/draggable-entity-card/draggable-entity-card.css +1140 -0
  236. package/src/components/draggable-entity-card/entity-locked-icon/EntityLockedIcon.tsx +133 -0
  237. package/src/components/draggable-entity-card/entity-locked-icon/entity-locked.css +8 -0
  238. package/src/components/draggable-entity-card/expand-properties-icon-button/ExpandPropertiesIconButton.tsx +84 -0
  239. package/src/components/draggable-entity-card/expand-properties-icon-button/expand-properties-icon-button.css +21 -0
  240. package/src/components/draggable-entity-card/implement-entity-icon/ImplementEntityIcon.tsx +74 -0
  241. package/src/components/draggable-entity-card/implement-entity-icon/implement-entity-icon.css +13 -0
  242. package/src/components/draggable-entity-card/logic-error/LogicErrorIconMenu.tsx +424 -0
  243. package/src/components/draggable-entity-card/logic-error/logic-error.css +23 -0
  244. package/src/components/draggable-entity-card/new-card-input-button/NewCardInputButton.tsx +193 -0
  245. package/src/components/draggable-entity-card/new-card-input-button/NewDynamicInputButton.tsx +214 -0
  246. package/src/components/draggable-entity-card/new-card-input-button/new-card-input-button.css +71 -0
  247. package/src/components/draggable-entity-card/new-card-output-button/NewCardOutputButton.tsx +192 -0
  248. package/src/components/draggable-entity-card/new-card-output-button/new-card-output-button.css +71 -0
  249. package/src/components/draggable-entity-card/termination-statement/TerminationStatementCard.tsx +1543 -0
  250. package/src/components/draggable-entity-card/termination-statement/termination-statement-card.css +17 -0
  251. package/src/components/draggable-entity-card/test-entity-button.css +55 -0
  252. package/src/components/draggable-entity-card/test-menu.css +181 -0
  253. package/src/components/draggable-entity-card/unreachable-marker.css +43 -0
  254. package/src/components/draggable-entity-card/variable-scope-marker.css +22 -0
  255. package/src/components/dynamic-value/DynamicValue.tsx +2395 -0
  256. package/src/components/dynamic-value/DynamicValueEntry.tsx +1957 -0
  257. package/src/components/dynamic-value/dynamic-value.css +230 -0
  258. package/src/components/editor/ElyxMonacoEditor.tsx +38 -0
  259. package/src/components/entity-error/EntityErrorListItem.tsx +47 -0
  260. package/src/components/entity-error/entity-error.css +198 -0
  261. package/src/components/entity-icon/EntityIcon.tsx +292 -0
  262. package/src/components/entity-icon/entity-icon.css +39 -0
  263. package/src/components/gallery-card/CreateNewProject.tsx +222 -0
  264. package/src/components/gallery-card/GalleryCard.tsx +171 -0
  265. package/src/components/gallery-card/MarketplaceCard.tsx +87 -0
  266. package/src/components/gallery-card/ProjectDuplicationCard.tsx +575 -0
  267. package/src/components/gallery-card/gallery-card.css +25 -0
  268. package/src/components/notifications/NotificationsIconButton.tsx +124 -0
  269. package/src/components/notifications/NotificationsPanel.tsx +385 -0
  270. package/src/components/notifications/notifications.css +189 -0
  271. package/src/components/online-users/LocalOnlineUsers.tsx +175 -0
  272. package/src/components/online-users/PageOnlineUsers.tsx +297 -0
  273. package/src/components/online-users/online-users.css +72 -0
  274. package/src/components/page-backdrop/PageBackdrop.tsx +8 -0
  275. package/src/components/page-backdrop/page-backdrop.css +7 -0
  276. package/src/components/project-configuration/DeleteProjectConfirmationDialog.tsx +134 -0
  277. package/src/components/project-configuration/ProjectConfigurationDialog.tsx +972 -0
  278. package/src/components/project-configuration/ProjectDataForm.tsx +121 -0
  279. package/src/components/project-configuration/UnpublishProjectConfirmationDialog.tsx +162 -0
  280. package/src/components/project-configuration/project-configuration-content.css +209 -0
  281. package/src/components/project-name/ProjectName.tsx +2025 -0
  282. package/src/components/project-name/project-name.css +599 -0
  283. package/src/components/publishing/Publication.tsx +133 -0
  284. package/src/components/publishing/history/PublicationHistoryContent.tsx +414 -0
  285. package/src/components/publishing/history/PublicationHistoryDialog.tsx +234 -0
  286. package/src/components/publishing/preview/PublicationPreviewDialog.tsx +1158 -0
  287. package/src/components/publishing/preview/PublishingPriceForecast.tsx +160 -0
  288. package/src/components/publishing/preview/PublishingResourcesDetails.tsx +91 -0
  289. package/src/components/publishing/publication-sequence/PublishingSequenceContent.tsx +375 -0
  290. package/src/components/publishing/publication-sequence/PublishingSequenceDialog.tsx +344 -0
  291. package/src/components/publishing/publishing-dialog.css +142 -0
  292. package/src/components/publishing/utils.ts +227 -0
  293. package/src/components/resources/ResourcesDialog.tsx +591 -0
  294. package/src/components/resources/UpgradeBanner.tsx +102 -0
  295. package/src/components/resources/codebase/CodebaseDetails.tsx +156 -0
  296. package/src/components/resources/cron-job/CronJobsList.tsx +532 -0
  297. package/src/components/resources/functions/FunctionsList.tsx +454 -0
  298. package/src/components/resources/http-api/HttpAPI.tsx +566 -0
  299. package/src/components/resources/http-api/HttpAPIClientModule.tsx +37 -0
  300. package/src/components/resources/logs/LogsViewer.tsx +768 -0
  301. package/src/components/resources/query.ts +74 -0
  302. package/src/components/resources/relational-database/DatabaseTable.tsx +905 -0
  303. package/src/components/resources/relational-database/RelationalDatabase.tsx +83 -0
  304. package/src/components/resources/relational-database/RelationalDatabaseSecrets.tsx +361 -0
  305. package/src/components/resources/resources-dialog.css +74 -0
  306. package/src/components/test-relational-database/DatabaseTable.tsx +913 -0
  307. package/src/components/test-relational-database/TestDatabaseDialogContent.tsx +670 -0
  308. package/src/components/test-relational-database/query.ts +74 -0
  309. package/src/components/toolbar/ToolBar.tsx +236 -0
  310. package/src/components/toolbar/toolbar.css +78 -0
  311. package/src/components/transaction-history/TransactionHistoryDialog.tsx +268 -0
  312. package/src/components/user/CurrentUserAvatar.tsx +65 -0
  313. package/src/components/user/UserChip.tsx +62 -0
  314. package/src/components/user/user.css +39 -0
  315. package/src/components/user-profile/ChangePasswordForm.tsx +67 -0
  316. package/src/components/user-profile/OwnUserProfileContent.tsx +665 -0
  317. package/src/components/user-profile/PublicUserProfileContent.tsx +99 -0
  318. package/src/components/user-profile/UserDataForm.tsx +75 -0
  319. package/src/components/user-profile/UserProfileDialog.tsx +110 -0
  320. package/src/components/user-profile/user-profile-content.css +25 -0
  321. package/src/config.ts +130 -0
  322. package/src/globals.d.ts +13 -0
  323. package/src/index.html +27 -0
  324. package/src/index.tsx +23 -0
  325. package/src/lib/badge/Badge.tsx +35 -0
  326. package/src/lib/badge/badge.css +32 -0
  327. package/src/lib/button/Button.tsx +129 -0
  328. package/src/lib/button/button.css +145 -0
  329. package/src/lib/canvas/canvas-undo-redo.ts +263 -0
  330. package/src/lib/canvas/defs.ts +170 -0
  331. package/src/lib/canvas/index.test.ts +189 -0
  332. package/src/lib/canvas/index.ts +6999 -0
  333. package/src/lib/canvas/utils.ts +59 -0
  334. package/src/lib/card/Card.tsx +62 -0
  335. package/src/lib/card/LoadingCard.tsx +82 -0
  336. package/src/lib/card/card.css +259 -0
  337. package/src/lib/chip/Chip.tsx +79 -0
  338. package/src/lib/chip/chip.css +0 -0
  339. package/src/lib/dialog/Dialog.tsx +122 -0
  340. package/src/lib/dialog/SmallDialog.tsx +61 -0
  341. package/src/lib/dialog/dialog.css +40 -0
  342. package/src/lib/display-data-structure/index.tsx +21 -0
  343. package/src/lib/dropdown/CanvasDropdownMenuCard.tsx +68 -0
  344. package/src/lib/dropdown/CanvasDropdownMenuCardOption.tsx +136 -0
  345. package/src/lib/dropdown/DropdownButton.tsx +104 -0
  346. package/src/lib/dropdown/DropdownMenuCard.tsx +324 -0
  347. package/src/lib/dropdown/DropdownMenuPopup.tsx +27 -0
  348. package/src/lib/dropdown/dropdown-button.css +76 -0
  349. package/src/lib/dropdown/dropdown-menu.css +151 -0
  350. package/src/lib/json-editor/RawJsonEditor.tsx +137 -0
  351. package/src/lib/json-editor/json-editor.css +35 -0
  352. package/src/lib/loader/Loader.tsx +120 -0
  353. package/src/lib/loader/loader.css +38 -0
  354. package/src/lib/pagination/Pagination.tsx +64 -0
  355. package/src/lib/popup/CanvasPopupBaseComponent.tsx +103 -0
  356. package/src/lib/popup/Popup.tsx +243 -0
  357. package/src/lib/popup/popup.css +16 -0
  358. package/src/lib/table/RowForm.tsx +301 -0
  359. package/src/lib/table/Table.tsx +1069 -0
  360. package/src/lib/table/table.css +249 -0
  361. package/src/lib/table/types.ts +108 -0
  362. package/src/lib/text-area/TextArea.tsx +183 -0
  363. package/src/lib/text-area/text-area.css +156 -0
  364. package/src/lib/text-field/TextField.tsx +218 -0
  365. package/src/lib/text-field/index.ts +8 -0
  366. package/src/lib/text-field/text-field.css +201 -0
  367. package/src/lib/tooltip/Tooltip.tsx +24 -0
  368. package/src/lib/tooltip/tooltip.css +17 -0
  369. package/src/localization/index.ts +47 -0
  370. package/src/main.css +343 -0
  371. package/src/pages/Auth.tsx +848 -0
  372. package/src/pages/Editor.tsx +883 -0
  373. package/src/pages/ErrorPage.tsx +179 -0
  374. package/src/pages/Gallery.tsx +1693 -0
  375. package/src/pages/NewPaymentMethodCallback.tsx +53 -0
  376. package/src/pages/NotFoundPage.tsx +126 -0
  377. package/src/pages/PricingPlans.tsx +155 -0
  378. package/src/pages/auth.css +304 -0
  379. package/src/pages/gallery.css +421 -0
  380. package/src/payments/index.ts +187 -0
  381. package/src/popup-notification/index.ts +90 -0
  382. package/src/services/database/index.ts +1 -0
  383. package/src/services/database/utils.ts +1301 -0
  384. package/src/services/editor/CanvasElement.tsx +2934 -0
  385. package/src/services/editor/CanvasElementConnectionDeleteButton.ts +204 -0
  386. package/src/services/editor/CanvasPopup.tsx +749 -0
  387. package/src/services/editor/EditorService.ts +8157 -0
  388. package/src/services/editor/area.ts +1312 -0
  389. package/src/services/editor/connections.ts +1019 -0
  390. package/src/services/editor/create/condition.ts +25 -0
  391. package/src/services/editor/create/definition-entity.ts +29 -0
  392. package/src/services/editor/create/function-call.ts +25 -0
  393. package/src/services/editor/create/global-event.ts +33 -0
  394. package/src/services/editor/create/loop.ts +25 -0
  395. package/src/services/editor/create/operation.ts +30 -0
  396. package/src/services/editor/create/utils.ts +140 -0
  397. package/src/services/editor/create/variable-declaration.ts +135 -0
  398. package/src/services/editor/create/variable-instance.ts +100 -0
  399. package/src/services/editor/editor-ui-extensions-context.ts +43 -0
  400. package/src/services/editor/entities-metadata.json +9310 -0
  401. package/src/services/editor/icons.ts +1093 -0
  402. package/src/services/editor/index.ts +1 -0
  403. package/src/services/editor/layout.ts +102 -0
  404. package/src/services/editor/modules/built-in-function-implementations/base.ts +14 -0
  405. package/src/services/editor/modules/built-in-function-implementations/create-persisted-entity/index.ts +56 -0
  406. package/src/services/editor/modules/built-in-function-implementations/delete-persisted-entity/index.ts +55 -0
  407. package/src/services/editor/modules/built-in-function-implementations/index.ts +4 -0
  408. package/src/services/editor/modules/built-in-function-implementations/update-persisted-entity/index.ts +56 -0
  409. package/src/services/editor/modules/operations-implementations/external-integrations/google-drive/get-files.ts +183 -0
  410. package/src/services/editor/modules/operations-implementations/external-integrations/google-drive/list-drives.ts +124 -0
  411. package/src/services/editor/modules/operations-implementations/external-integrations/google-drive/list-root-folders.ts +125 -0
  412. package/src/services/editor/modules/operations-implementations/external-integrations/google-drive/smart-fetch-document.ts +702 -0
  413. package/src/services/editor/modules/operations-implementations/external-integrations/google-drive/upload-document.ts +535 -0
  414. package/src/services/editor/modules/operations-implementations/external-integrations/google-gemini/generate-content.ts +193 -0
  415. package/src/services/editor/modules/operations-implementations/external-integrations/google-mail/get-emails.ts +586 -0
  416. package/src/services/editor/modules/operations-implementations/external-integrations/google-mail/send-email.ts +386 -0
  417. package/src/services/editor/modules/operations-implementations/external-integrations/index.ts +12 -0
  418. package/src/services/editor/modules/operations-implementations/external-integrations/slack/channels.ts +240 -0
  419. package/src/services/editor/modules/operations-implementations/external-integrations/slack/messages.ts +210 -0
  420. package/src/services/editor/modules/operations-implementations/external-integrations/slack/replies.ts +200 -0
  421. package/src/services/editor/modules/operations-implementations/external-integrations/slack/send-message.ts +177 -0
  422. package/src/services/editor/modules/operations-implementations/index.ts +1 -0
  423. package/src/services/editor/modules/search-node-implementation/index.ts +42 -0
  424. package/src/services/editor/modules/sql-migrations-generation.tsx +1054 -0
  425. package/src/services/editor/publication/publication.ts +578 -0
  426. package/src/services/editor/ui.ts +1348 -0
  427. package/src/services/editor/utils.ts +5868 -0
  428. package/src/services/editor/value-store.ts +619 -0
  429. package/src/services/execution/built-in-function-implementations.ts +422 -0
  430. package/src/services/execution/index.ts +4747 -0
  431. package/src/services/execution/logic.ts +121 -0
  432. package/src/services/execution/test-instance.tsx +2296 -0
  433. package/src/services/execution/utils.ts +33 -0
  434. package/src/services/execution/value-resolution.test.ts +424 -0
  435. package/src/services/execution/value-resolution.ts +4087 -0
  436. package/src/services/integrations/ExternalIntegrationsService.ts +439 -0
  437. package/src/services/integrations/api.ts +175 -0
  438. package/src/services/local-relational-database/idb_helper.ts +66 -0
  439. package/src/services/local-relational-database/index.ts +3308 -0
  440. package/src/services/local-relational-database/utils.ts +403 -0
  441. package/src/services/notifications/index.ts +525 -0
  442. package/src/services/user/index.ts +144 -0
  443. package/src/setupTests.ts +1 -0
  444. package/src/socket/socket.ts +248 -0
  445. package/src/socket/utils.ts +10 -0
  446. package/src/store/workspace.ts +12 -0
  447. package/src/theme.ts +19 -0
  448. package/src/utils/DOM.ts +39 -0
  449. package/src/utils/date.ts +169 -0
  450. package/src/utils/index.ts +158 -0
  451. package/src/utils/react.tsx +679 -0
  452. package/src/utils/testing.ts +103 -0
@@ -0,0 +1,1158 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import axios from 'axios';
3
+ import short from 'short-uuid';
4
+ import '../publishing-dialog.css';
5
+ import { getAccessToken, getCurrentUserOrLogoutRedirect } from '../../../auth';
6
+ import VersionsIcon from '../../../assets/versions.svg';
7
+ import Button from '../../../lib/button/Button';
8
+ import PublishingResourcesDetails from './PublishingResourcesDetails';
9
+ import PublishingPriceForecast from './PublishingPriceForecast';
10
+ import {
11
+ PUBLISHING_DISABLED_REASONS,
12
+ fromPublishingDisabledCodeToReadable,
13
+ } from '../utils';
14
+ import Tooltip from '../../../lib/tooltip/Tooltip';
15
+ import {
16
+ ADD_PAYMENT_METHOD_PROCESS,
17
+ startAddPaymentMethodSession,
18
+ } from '../../../payments';
19
+ import { EditorService } from '../../../services/editor';
20
+ import DialogLoader from '../../DialogLoader';
21
+ import {
22
+ AWS_SERVER_SIDE_PROJECT_DEPLOYMENT_SEQUENCE,
23
+ InfrastructureResourceType,
24
+ IUser,
25
+ PublicationStatus,
26
+ } from '@elyx-code/definitions';
27
+ import {
28
+ BaseEntityNames,
29
+ ChangeSet,
30
+ checkHasBaseEntity,
31
+ createOrUpdateRowTransformer,
32
+ DefinitionEntityState,
33
+ EntityError,
34
+ EntityErrorCode,
35
+ EntityErrorSeverity,
36
+ EntityType,
37
+ getParentCanvasEntity,
38
+ ISQLMigrationsDiffs,
39
+ ProjectState,
40
+ resolveSQLMigrationsDiffs,
41
+ StateMutationAction,
42
+ } from '@elyx-code/project-logic-tree';
43
+ import EntityErrorListItem from '../../entity-error/EntityErrorListItem';
44
+ import { getCanvasEntityDraggableContainerDOMId } from '../../../services/editor/ui';
45
+ import { Logger, YieldTracker } from '@elyx-code/common-ts-utils';
46
+ import { popupNotification } from '../../../popup-notification';
47
+ import {
48
+ Alert,
49
+ Box,
50
+ CircularProgress,
51
+ Typography,
52
+ Button as MUIButton,
53
+ } from '@mui/material';
54
+ import OpenInNewIcon from '@mui/icons-material/OpenInNew';
55
+ import { envConfig } from '../../../config';
56
+ import { getRelationalDBInstanceNameFromEntityId } from '../../../services/editor/publication/publication';
57
+
58
+ const translator = short();
59
+
60
+ export enum ProjectValidationErrorsEnum {
61
+ NO_LOGIC = 'NO_LOGIC',
62
+ NO_NAME = 'NO_NAME',
63
+ }
64
+
65
+ export type ProjectValidationErrors =
66
+ | ProjectValidationErrorsEnum
67
+ | EntityErrorCode;
68
+
69
+ // Returns diffs for every top-level persisted definition-entity that has
70
+ // changed since the last publication in a way that requires a row-transformer
71
+ // (either a brand-new one is needed, or an open one exists but is stale).
72
+ function resolveMissingRowTransformerDiffs(
73
+ project: EditorService,
74
+ ): ISQLMigrationsDiffs[] {
75
+ if (!project.lastPublishedProjectState) return [];
76
+
77
+ const persistedEntities = project.logic.entities.filter(
78
+ (entity): entity is DefinitionEntityState =>
79
+ entity.type === EntityType.DefinitionEntity &&
80
+ (entity as DefinitionEntityState).parent.type !== EntityType.DataType &&
81
+ checkHasBaseEntity(entity, BaseEntityNames.PERSISTED_ENTITY),
82
+ );
83
+
84
+ const diffs = persistedEntities
85
+ .map((entity) =>
86
+ resolveSQLMigrationsDiffs(
87
+ project.logic,
88
+ project.lastPublishedProjectState,
89
+ entity,
90
+ ),
91
+ )
92
+ .filter(
93
+ (diff) =>
94
+ diff.newRowTransformerNeeded ||
95
+ diff.isPreexistingRowTransformerUpToDate === false,
96
+ );
97
+
98
+ return diffs;
99
+ }
100
+
101
+ async function getOnlyRelevantErrorsForPublication(
102
+ projectState: ProjectState,
103
+ ): Promise<EntityError[]> {
104
+ const errors: EntityError[] = [];
105
+
106
+ if (
107
+ (!projectState.entities || !projectState.entities.length) &&
108
+ (!projectState.functions || !projectState.functions.length)
109
+ ) {
110
+ errors.push(
111
+ // @ts-ignore
112
+ new EntityError<ProjectValidationErrorsEnum>({
113
+ code: ProjectValidationErrorsEnum.NO_LOGIC,
114
+ id: projectState.id + '--' + ProjectValidationErrorsEnum.NO_LOGIC,
115
+ message: `Entity of type ${projectState.type} with id "${projectState.id}" must contain at least one entity or function to be published.`,
116
+ severity: EntityErrorSeverity.Error,
117
+ entity: projectState,
118
+ }),
119
+ );
120
+ }
121
+
122
+ if (!projectState.name) {
123
+ errors.push(
124
+ // @ts-ignore
125
+ new EntityError<ProjectValidationErrorsEnum>({
126
+ code: ProjectValidationErrorsEnum.NO_NAME,
127
+ id: projectState.id + '--' + ProjectValidationErrorsEnum.NO_NAME,
128
+ message: `Entity of type ${projectState.type} with id "${projectState.id}" must have a name to be published.`,
129
+ severity: EntityErrorSeverity.Error,
130
+ entity: projectState,
131
+ }),
132
+ );
133
+ }
134
+
135
+ const tracker = YieldTracker.from({ yieldEvery: 100 });
136
+
137
+ await projectState.validateAsync({ tracker });
138
+
139
+ const projectErrors = (await projectState.getErrorsAsync({ tracker })).filter(
140
+ (error) => EntityErrorSeverity.Error === error.severity,
141
+ );
142
+
143
+ return [...errors, ...projectErrors];
144
+ }
145
+
146
+ export interface IPublishingDialogProps {
147
+ onClose: (event: any) => void;
148
+ contentHeight?: boolean;
149
+ project: EditorService;
150
+ }
151
+
152
+ function assemblePreviewData(project: EditorService) {
153
+ // Here we loop over the routes integrations, looking for the serverless function belonging to the entities in the project payload
154
+ // Any function without an entity we count as deleted
155
+ // Any entity without a function we count as new
156
+ // All others we count as modified
157
+
158
+ let deletedFunctionsCount = 0;
159
+ let newFunctionsCount = 0;
160
+ let modifiedFunctionsCount = 0;
161
+
162
+ let deletedRelationsDatabasesCount = 0;
163
+ let newRelationsDatabasesCount = 0;
164
+ let modifiedRelationsDatabasesCount = 0;
165
+
166
+ // So we can assume that every new entity results in 3 routes and 3 functions
167
+ // +1 'options' method route for the http api which is always present
168
+ const callableEntities = project.logic.entities.filter(
169
+ (entity) =>
170
+ checkHasBaseEntity(entity, BaseEntityNames.CRON_JOB) ||
171
+ checkHasBaseEntity(entity, BaseEntityNames.HTTP_ENDPOINT),
172
+ );
173
+ const endpointEntities = project.logic.entities.filter((entity) =>
174
+ checkHasBaseEntity(entity, BaseEntityNames.HTTP_ENDPOINT),
175
+ );
176
+ const relationalDatabaseEntities = project.logic.entities.filter((entity) =>
177
+ checkHasBaseEntity(entity, BaseEntityNames.RELATIONAL_DATABASE),
178
+ );
179
+ const totalFunctionsCount = callableEntities.length;
180
+
181
+ const seenOfEndpointEntityIds = new Set<string>();
182
+ const seenOfRelationalDatabaseEntityIds = new Set<string>();
183
+
184
+ (project.liveResources || []).forEach((resource) => {
185
+ if (resource.resourceType === InfrastructureResourceType.HttpApi) {
186
+ resource.details?.routes.forEach((route) => {
187
+ // We skip the method http route because it is present by default in all apps
188
+ if (route.target.resource.resourceId?.endsWith('-options')) {
189
+ return;
190
+ }
191
+
192
+ const functionIdParts =
193
+ route.target.resource.resourceId?.split('fn_') || [];
194
+
195
+ const sanitizedFunctionEntityId = translator.toUUID(
196
+ functionIdParts[functionIdParts.length - 1],
197
+ );
198
+
199
+ const foundEntityForFunction = endpointEntities.find(
200
+ (entity) => entity.id === sanitizedFunctionEntityId,
201
+ );
202
+
203
+ if (!foundEntityForFunction) {
204
+ // This function has no entity, so we will never find it
205
+ if (
206
+ !route.target.resource.resourceId?.includes(
207
+ 'function:http-options-project-',
208
+ )
209
+ ) {
210
+ // Function exists but entity is missing, it was deleted
211
+ deletedFunctionsCount++;
212
+ }
213
+ } else {
214
+ // This entity has a function deployed, so it existed before and it has been modified
215
+ seenOfEndpointEntityIds.add(foundEntityForFunction.id);
216
+ modifiedFunctionsCount++;
217
+ }
218
+ });
219
+ } else if (
220
+ resource.resourceType === InfrastructureResourceType.RelationalDatabase
221
+ ) {
222
+ const foundEntityForDatabase = relationalDatabaseEntities.find(
223
+ (entity) =>
224
+ getRelationalDBInstanceNameFromEntityId(
225
+ entity.id,
226
+ project?.branchHead?.identifier,
227
+ ) === resource.resourceId,
228
+ );
229
+
230
+ if (!foundEntityForDatabase) {
231
+ // This function has no entity, so we will never find it
232
+ if (!resource.resourceId?.includes('function:http-options-project-')) {
233
+ // Function exists but entity is missing, it was deleted
234
+ deletedRelationsDatabasesCount++;
235
+ }
236
+ } else {
237
+ // This entity has a function deployed, so it existed before and it has been modified
238
+ seenOfRelationalDatabaseEntityIds.add(foundEntityForDatabase.id);
239
+ modifiedRelationsDatabasesCount++;
240
+ }
241
+ }
242
+ });
243
+
244
+ // Loop over project entities and check if we saw them in the previously deployed routes
245
+ // These entities don't have functions deployed, so they are new
246
+ const newEndpointsEntities = endpointEntities.filter(
247
+ (entity) => !seenOfEndpointEntityIds.has(entity.id),
248
+ );
249
+ const newRelationalDatabases = relationalDatabaseEntities.filter(
250
+ (entity) => !seenOfRelationalDatabaseEntityIds.has(entity.id),
251
+ );
252
+
253
+ // There is 3 http methods for each entity 'get', 'post', 'patch'
254
+ // So we can assume that every new entity results in 3 routes and 3 functions
255
+ newFunctionsCount = newEndpointsEntities.length;
256
+ newRelationsDatabasesCount = newRelationalDatabases.length;
257
+
258
+ const relationalDatabasesSummary = {
259
+ type: InfrastructureResourceType.RelationalDatabase,
260
+ items: {
261
+ total: {
262
+ count: newRelationsDatabasesCount + modifiedRelationsDatabasesCount,
263
+ },
264
+ new: {
265
+ count: newRelationsDatabasesCount,
266
+ },
267
+ modified: {
268
+ count: modifiedRelationsDatabasesCount,
269
+ },
270
+ deleted: {
271
+ count: deletedRelationsDatabasesCount,
272
+ },
273
+ },
274
+ };
275
+
276
+ const httpApiSummary = {
277
+ type: InfrastructureResourceType.HttpEndpoint,
278
+ items: {
279
+ total: {
280
+ count: newFunctionsCount + modifiedFunctionsCount,
281
+ },
282
+ new: {
283
+ count: newFunctionsCount,
284
+ },
285
+ modified: {
286
+ count: modifiedFunctionsCount,
287
+ },
288
+ deleted: {
289
+ count: deletedFunctionsCount,
290
+ },
291
+ },
292
+ };
293
+
294
+ const cloudHostedCodebaseSummary = {
295
+ type: InfrastructureResourceType.ServerlessFunction,
296
+ items: {
297
+ total: {
298
+ count: newFunctionsCount + modifiedFunctionsCount,
299
+ },
300
+ new: {
301
+ count: newFunctionsCount,
302
+ },
303
+ modified: {
304
+ count: modifiedFunctionsCount,
305
+ },
306
+ deleted: {
307
+ count: deletedFunctionsCount,
308
+ },
309
+ },
310
+ };
311
+
312
+ const resources = [
313
+ relationalDatabasesSummary,
314
+ httpApiSummary,
315
+ cloudHostedCodebaseSummary,
316
+ ];
317
+
318
+ const isUsersFirstPublishedProject = false;
319
+
320
+ const costItems = [
321
+ {
322
+ value: 27,
323
+ currency: 'EUR',
324
+ valueType: 'absolute',
325
+ type: 'cost',
326
+ amount: relationalDatabasesSummary.items.total.count,
327
+ name: InfrastructureResourceType.RelationalDatabase,
328
+ },
329
+ {
330
+ value: 0.5,
331
+ currency: 'EUR',
332
+ valueType: 'absolute',
333
+ type: 'cost',
334
+ amount: httpApiSummary.items.total.count,
335
+ name: InfrastructureResourceType.HttpApi,
336
+ },
337
+ {
338
+ value: 0.5,
339
+ currency: 'EUR',
340
+ valueType: 'absolute',
341
+ type: 'cost',
342
+ amount: cloudHostedCodebaseSummary.items.total.count,
343
+ name: InfrastructureResourceType.CloudHostedCodebase,
344
+ },
345
+ // If this is the first project published by the user, we add a discount of 28 EUR for the first month
346
+ // 28 EUR should cover for a basic web server application with near-zero traffic
347
+ ...(isUsersFirstPublishedProject
348
+ ? [
349
+ {
350
+ value: 28,
351
+ currency: 'EUR',
352
+ valueType: 'absolute',
353
+ type: 'discount',
354
+ amount: 1,
355
+ name: 'first-published-project-monthly-discount',
356
+ },
357
+ ]
358
+ : []),
359
+ ];
360
+
361
+ // Calculate the total price from the cost items
362
+ const totalCostValue = costItems.reduce((total, costItem) => {
363
+ if (costItem.type === 'discount') {
364
+ return total - costItem.value * costItem.amount;
365
+ }
366
+ return total + costItem.value * costItem.amount;
367
+ }, 0);
368
+
369
+ const totalCostSummary = {
370
+ value: totalCostValue,
371
+ currency: 'EUR',
372
+ valueType: 'absolute',
373
+ type: totalCostValue >= 0 ? 'cost' : 'discount',
374
+ amount: 1,
375
+ name: 'total',
376
+ };
377
+
378
+ const nextProjectAutoIncrementPublicationCount =
379
+ (project.livePublication?.projectAutoIncrementPublicationCount || 0) + 1;
380
+ const nextProjectPublishedSemanticVersion = `${nextProjectAutoIncrementPublicationCount}.0.0`;
381
+ const nextProjectVersion = project.logic.version;
382
+
383
+ const nextPublicationDetails = {
384
+ nextProjectAutoIncrementPublicationCount,
385
+ nextProjectPublishedSemanticVersion,
386
+ nextProjectVersion,
387
+ };
388
+
389
+ const data = {
390
+ resources,
391
+ monthlyCostForecast: {
392
+ items: costItems,
393
+ total: totalCostSummary,
394
+ },
395
+ nextPublicationDetails,
396
+ };
397
+
398
+ return data;
399
+ }
400
+
401
+ const calculateMockPublishingDetails = (project: ProjectState) => {
402
+ let deletedFunctionsCount = 0;
403
+ let newFunctionsCount = 0;
404
+ let modifiedFunctionsCount = 0;
405
+
406
+ // So we can assume that every new entity results in 3 routes and 3 functions
407
+ // +1 'options' method route for the http api which is always present
408
+ const totalFunctionsCount = project.entities.length * 3 + 1;
409
+
410
+ const costItems = [
411
+ {
412
+ value: 27,
413
+ currency: 'EUR',
414
+ valueType: 'absolute',
415
+ type: 'cost',
416
+ amount: 1,
417
+ name: InfrastructureResourceType.RelationalDatabase,
418
+ },
419
+ {
420
+ value: 0.5,
421
+ currency: 'EUR',
422
+ valueType: 'absolute',
423
+ type: 'cost',
424
+ amount: 1,
425
+ name: InfrastructureResourceType.HttpApi,
426
+ },
427
+ {
428
+ value: 0.5,
429
+ currency: 'EUR',
430
+ valueType: 'absolute',
431
+ type: 'cost',
432
+ amount: 1,
433
+ name: InfrastructureResourceType.CloudHostedCodebase,
434
+ },
435
+ // If this is the first project published by the user, we add a discount of 28 EUR for the first month
436
+ // 28 EUR should cover for a basic web server application with near-zero traffic
437
+ ...(true // Forcing true for now, to test
438
+ ? [
439
+ {
440
+ value: 28,
441
+ currency: 'EUR',
442
+ valueType: 'absolute',
443
+ type: 'discount',
444
+ amount: 1,
445
+ name: 'first-published-project-monthly-discount',
446
+ },
447
+ ]
448
+ : []),
449
+ ];
450
+
451
+ // Calculate the total price from the cost items
452
+ const totalCostValue = costItems.reduce((total, costItem) => {
453
+ if (costItem.type === 'discount') {
454
+ return total - costItem.value;
455
+ }
456
+ return total + costItem.value;
457
+ }, 0);
458
+
459
+ const totalCostSummary = {
460
+ value: totalCostValue,
461
+ currency: 'EUR',
462
+ valueType: 'absolute',
463
+ type: totalCostValue >= 0 ? 'cost' : 'discount',
464
+ amount: 1,
465
+ name: 'total',
466
+ };
467
+
468
+ const resources = [
469
+ {
470
+ type: InfrastructureResourceType.RelationalDatabase,
471
+ items: {
472
+ total: {
473
+ count: 1,
474
+ },
475
+ new: {
476
+ count: true ? 1 : 0,
477
+ },
478
+ modified: {
479
+ count: true ? 0 : 1,
480
+ },
481
+ deleted: {
482
+ count: 0,
483
+ },
484
+ },
485
+ },
486
+ {
487
+ type: InfrastructureResourceType.HttpEndpoint,
488
+ items: {
489
+ total: {
490
+ count: totalFunctionsCount,
491
+ },
492
+ new: {
493
+ count: true ? totalFunctionsCount : newFunctionsCount,
494
+ },
495
+ modified: {
496
+ count: modifiedFunctionsCount,
497
+ },
498
+ deleted: {
499
+ count: deletedFunctionsCount,
500
+ },
501
+ },
502
+ },
503
+ {
504
+ type: InfrastructureResourceType.ServerlessFunction,
505
+ items: {
506
+ total: {
507
+ count: totalFunctionsCount,
508
+ },
509
+ new: {
510
+ count: true ? totalFunctionsCount : newFunctionsCount,
511
+ },
512
+ modified: {
513
+ count: modifiedFunctionsCount,
514
+ },
515
+ deleted: {
516
+ count: deletedFunctionsCount,
517
+ },
518
+ },
519
+ },
520
+ ];
521
+
522
+ const data = {
523
+ resources,
524
+ publicationSequence: AWS_SERVER_SIDE_PROJECT_DEPLOYMENT_SEQUENCE,
525
+ monthlyCostForecast: {
526
+ items: costItems,
527
+ total: totalCostSummary,
528
+ },
529
+ };
530
+
531
+ return data;
532
+ };
533
+
534
+ const PublicationPreviewDialog: React.FC<IPublishingDialogProps> = ({
535
+ onClose,
536
+ project,
537
+ }) => {
538
+ if (!project || !project.logic || !project.ready) {
539
+ return (
540
+ <DialogLoader
541
+ title='Project publication'
542
+ subtitle='Publish your project to the cloud'
543
+ onClose={onClose}
544
+ />
545
+ );
546
+ }
547
+
548
+ const [publishingDetails, setPublishingDetails] = useState<any | null>(null);
549
+ const [user, setUser] = useState<IUser | null>(null);
550
+ const [publishingDisabledReason, setPublishingDisabledReason] =
551
+ useState<PUBLISHING_DISABLED_REASONS | null>(null);
552
+ const [isDownloadingCode, setIsDownloadingCode] = useState<boolean>(false);
553
+ const [paymentMethods, setPaymentMethods] = useState<any[] | null>(null);
554
+ const [isInitialisingPublication, setIsInitialisingPublication] =
555
+ useState<boolean>(false);
556
+ const [projectErrors, setProjectErrors] = useState<EntityError[]>([]);
557
+ const [missingMigrationDiffs, setMissingMigrationDiffs] = useState<
558
+ ISQLMigrationsDiffs[]
559
+ >([]);
560
+
561
+ // const fetchPublicationPreview = async () => {
562
+ // if (!project.projectId) return;
563
+
564
+ // try {
565
+ // // const response = await axios.get(
566
+ // // // `${envConfig.API_BASE_URL}/publishing-service/v1/publication-preview?projectId=${projectId}&targets=server`,
567
+ // // `${envConfig.API_BASE_URL}/publishing-service/v1/publication-preview?projectId=${project.projectId}&targets=server`,
568
+ // // {
569
+ // // headers: {
570
+ // // Authorization: `Bearer ${await getAccessToken()}`,
571
+ // // },
572
+ // // }
573
+ // // );
574
+ // // Logger.log('Publication preview response:', response);
575
+ // return assemblePreviewData(project);
576
+ // } catch (error) {
577
+ // Logger.error('Error fetching publication preview:', error);
578
+ // return calculateMockPublishingDetails(project.logic);
579
+ // }
580
+ // };
581
+
582
+ const fetchPaymentMethods = async () => {
583
+ try {
584
+ const response = await axios.get(
585
+ `${envConfig.API_BASE_URL}/pricing-service/v1/${project.activeWorkspace?.id}/payment-methods`,
586
+ {
587
+ headers: {
588
+ Authorization: `Bearer ${await getAccessToken()}`,
589
+ },
590
+ },
591
+ );
592
+
593
+ return response.data.items;
594
+ } catch (error) {
595
+ Logger.error('Error fetching payment methods:', error);
596
+ return [];
597
+ }
598
+ };
599
+
600
+ const loadPreview = async () => {
601
+ Logger.log('Fetching data...');
602
+ if (
603
+ (!project.logic.entities || !project.logic.entities.length) &&
604
+ (!project.logic.functions || !project.logic.functions.length) &&
605
+ (!project.logic.events || !project.logic.events.length)
606
+ ) {
607
+ Logger.log('No logic found in project');
608
+ setPublishingDisabledReason(PUBLISHING_DISABLED_REASONS.NO_LOGIC);
609
+ return;
610
+ }
611
+
612
+ if (!project.logic.name) {
613
+ Logger.log('No name found in project');
614
+ setPublishingDisabledReason(PUBLISHING_DISABLED_REASONS.NO_NAME);
615
+ return;
616
+ }
617
+
618
+ await project.validateProjectState();
619
+
620
+ // Row-transformer check takes priority over logic errors. If persisted
621
+ // data structures have drifted from the live database, the user must add
622
+ // row transformers before we let them publish — regardless of any other
623
+ // validation problems further down the tree.
624
+ const missingDiffs = resolveMissingRowTransformerDiffs(project);
625
+ if (missingDiffs.length) {
626
+ setMissingMigrationDiffs(missingDiffs);
627
+ setPublishingDisabledReason(
628
+ PUBLISHING_DISABLED_REASONS.MISSING_ROW_TRANSFORMERS,
629
+ );
630
+ return;
631
+ }
632
+
633
+ const projectErrors = (
634
+ await getOnlyRelevantErrorsForPublication(project.logic)
635
+ ).filter((error) => error.severity === EntityErrorSeverity.Error);
636
+
637
+ if (projectErrors.length) {
638
+ setProjectErrors(projectErrors);
639
+ setPublishingDisabledReason(PUBLISHING_DISABLED_REASONS.LOGIC_ERRORS);
640
+ return;
641
+ }
642
+
643
+ const publicationPreview = assemblePreviewData(project);
644
+ setPublishingDetails(publicationPreview);
645
+
646
+ const [paymentMethods, user] = await Promise.all([
647
+ // fetchPublicationPreview(),
648
+ fetchPaymentMethods(),
649
+ getCurrentUserOrLogoutRedirect(),
650
+ ]);
651
+
652
+ Logger.log('Fetched data:', {
653
+ // publicationPreview,
654
+ paymentMethods,
655
+ user,
656
+ });
657
+
658
+ setPaymentMethods(paymentMethods);
659
+ setUser(user);
660
+ };
661
+
662
+ const _startAddPaymentMethodSession = async () => {
663
+ return startAddPaymentMethodSession({
664
+ projectId: project.projectId,
665
+ process: ADD_PAYMENT_METHOD_PROCESS.PUBLISH_PROJECT,
666
+ workspaceId: project.activeWorkspace?.id,
667
+ workspaceSlug: project.activeWorkspace?.slug,
668
+ branchIdentifier: project.viewingBranch,
669
+ projectVersion: project.viewingVersion,
670
+ });
671
+ };
672
+
673
+ const onPublishClick = async () => {
674
+ Logger.log('onPublishClick');
675
+ setIsInitialisingPublication(true);
676
+
677
+ if (!paymentMethods?.length) {
678
+ _startAddPaymentMethodSession();
679
+ } else {
680
+ setIsInitialisingPublication(true);
681
+ Logger.log('Publishing project...');
682
+ await project.publish();
683
+ }
684
+ };
685
+
686
+ const onDownloadCodeClick = async () => {
687
+ setIsDownloadingCode(true);
688
+
689
+ try {
690
+ await project.downloadCode({
691
+ version: 'latest',
692
+ onProcessError(error) {
693
+ popupNotification({
694
+ text: 'Error preparing code download: ' + error.message,
695
+ color: 'error',
696
+ });
697
+ },
698
+ onDownloadError(error) {
699
+ popupNotification({
700
+ text: 'Error downloading code: ' + error.message,
701
+ color: 'error',
702
+ });
703
+ },
704
+ });
705
+
706
+ // ACK received → mark success locally
707
+ popupNotification({
708
+ text: 'Code downloaded',
709
+ });
710
+ } catch (error) {
711
+ console.log(
712
+ 'Error downloading latest version of the code error: ',
713
+ error,
714
+ );
715
+ }
716
+ setIsDownloadingCode(false);
717
+ };
718
+
719
+ useEffect(() => {
720
+ Logger.log('Publication dialog mounted...');
721
+ loadPreview();
722
+ }, [project?.liveResources]);
723
+
724
+ // Generate (or extend) the row transformers for every persisted entity whose
725
+ // diffs require one, then send the user back to the canvas focused on the
726
+ // first transformer we touched so they can review/customise it.
727
+ const onAddMissingRowTransformers = (event: any) => {
728
+ if (!missingMigrationDiffs.length) return;
729
+
730
+ const changeSet = project.logic.addChangeSet(
731
+ new ChangeSet(
732
+ project.logic,
733
+ ProjectState.sessionAuthor,
734
+ new Date().toISOString(),
735
+ project.logic,
736
+ false,
737
+ StateMutationAction.GenerateSQLMigrationOnPersistedEntityUpdate,
738
+ ),
739
+ );
740
+
741
+ let firstTransformer: DefinitionEntityState | null = null;
742
+
743
+ missingMigrationDiffs.forEach((diffs) => {
744
+ const { rowTransformer } = createOrUpdateRowTransformer(
745
+ project.logic,
746
+ diffs,
747
+ changeSet,
748
+ );
749
+ if (!firstTransformer) firstTransformer = rowTransformer;
750
+
751
+ diffs.extendedEntities.forEach((extDiffs, i) => {
752
+ createOrUpdateRowTransformer(project.logic, extDiffs, changeSet, {
753
+ x: (i + 1) * 600,
754
+ y: 800,
755
+ });
756
+ });
757
+ });
758
+
759
+ project.renderAndCloseChangeSet(changeSet);
760
+
761
+ onClose(event);
762
+
763
+ if (firstTransformer) {
764
+ if (project.canvas?.currentScale < 0.7) {
765
+ project.canvas?.zoomTo(0.7);
766
+ } else if (project.canvas?.currentScale > 1) {
767
+ project.canvas?.zoomTo(1);
768
+ }
769
+ project.canvas?.scrollToObjectById(
770
+ getCanvasEntityDraggableContainerDOMId(firstTransformer),
771
+ );
772
+ }
773
+ };
774
+
775
+ const dataIsLoading = !project || !user || paymentMethods === null;
776
+
777
+ return (
778
+ <div
779
+ style={{
780
+ display: 'flex',
781
+ flexDirection: 'column',
782
+ height: '100%',
783
+ gap: '4px',
784
+ padding: '40px',
785
+ overflowY: 'scroll',
786
+ }}
787
+ >
788
+ <div style={{ display: 'flex', alignItems: 'center', gap: '16px' }}>
789
+ <button className='dialog_back_button' onClick={onClose}>
790
+ <i className='fa-solid fa-arrow-left' />
791
+ </button>
792
+ <h1 style={{ margin: 0, fontWeight: 500, fontSize: '28px' }}>
793
+ Project publication
794
+ </h1>
795
+ </div>
796
+ <a
797
+ style={{
798
+ display: 'flex',
799
+ gap: '6px',
800
+ marginLeft: '42px',
801
+ textDecoration: 'none',
802
+ }}
803
+ href=''
804
+ onClick={(event) => {
805
+ event.preventDefault();
806
+ EditorService.navigate(
807
+ `${project?.editorBasePath}/publication/history`,
808
+ );
809
+ }}
810
+ >
811
+ <img src={VersionsIcon} alt='Versions' />
812
+ <p style={{ margin: 0, color: 'rgba(0,0,0,0.7)' }}>Publication history</p>
813
+ </a>
814
+
815
+ <div style={{ flex: 1, margin: '0 42px', marginTop: '30px' }}>
816
+ <div
817
+ style={{
818
+ display: 'flex',
819
+ flexDirection: 'column',
820
+ minHeight: '80%',
821
+ height: '100%',
822
+ }}
823
+ >
824
+ <div style={{ display: 'flex', alignItems: 'center' }}>
825
+ <h3
826
+ style={{
827
+ display: 'flex',
828
+ gap: '6px',
829
+ fontWeight: 'normal',
830
+ margin: 0,
831
+ }}
832
+ >
833
+ {!publishingDisabledReason && <span>New version</span>}
834
+ <span style={{ fontWeight: 'bold' }}>
835
+ {
836
+ publishingDetails?.nextPublicationDetails
837
+ ?.nextProjectPublishedSemanticVersion
838
+ }
839
+ </span>
840
+ </h3>
841
+ {publishingDetails && (
842
+ <>
843
+ <Button
844
+ variant='text'
845
+ iconStart='fa-solid fa-download'
846
+ size='small'
847
+ id='download-latest-code-version-button'
848
+ loading={isDownloadingCode}
849
+ onClick={onDownloadCodeClick}
850
+ >
851
+ Download code
852
+ </Button>
853
+ <Tooltip
854
+ anchorQuerySelector='#download-latest-code-version-button'
855
+ placement='bottom'
856
+ >
857
+ Download your latest code, immediately and for free
858
+ </Tooltip>
859
+ </>
860
+ )}
861
+ </div>
862
+ {publishingDetails && (
863
+ <p
864
+ style={{
865
+ margin: 0,
866
+ fontSize: '14px',
867
+ marginTop: '6px',
868
+ color: 'rgba(0,0,0,0.54)',
869
+ }}
870
+ >
871
+ The following cloud resources will be provisioned
872
+ </p>
873
+ )}
874
+ {publishingDetails && (
875
+ <div
876
+ style={{
877
+ marginTop: '30px',
878
+ marginBottom: '30px',
879
+ height: '100%',
880
+ display: 'flex',
881
+ flexDirection: 'column',
882
+ justifyContent: 'space-between',
883
+ gap: '50px',
884
+ }}
885
+ >
886
+ <PublishingResourcesDetails
887
+ project={project}
888
+ details={publishingDetails}
889
+ />
890
+ <PublishingPriceForecast
891
+ project={project}
892
+ details={publishingDetails}
893
+ paymentMethods={paymentMethods || []}
894
+ dataIsLoading={dataIsLoading}
895
+ />
896
+ </div>
897
+ )}
898
+ {publishingDisabledReason && (
899
+ <div
900
+ style={{
901
+ width: '100%',
902
+ display: 'flex',
903
+ justifyContent: 'center',
904
+ flexDirection: 'column',
905
+ alignItems: 'center',
906
+ height: '100%',
907
+ flex: 1,
908
+ }}
909
+ >
910
+ <h3 style={{ margin: 0, fontWeight: 'normal', marginTop: '6px' }}>
911
+ Publishing disabled
912
+ </h3>
913
+ <p
914
+ style={{
915
+ marginBottom: '24px',
916
+ fontSize: '16px',
917
+ marginTop: '10px',
918
+ color: 'rgba(0,0,0,0.54)',
919
+ }}
920
+ >
921
+ {fromPublishingDisabledCodeToReadable(publishingDisabledReason)}
922
+ </p>
923
+ {publishingDisabledReason ===
924
+ PUBLISHING_DISABLED_REASONS.NO_NAME && (
925
+ <Button
926
+ onClick={() => {
927
+ EditorService.navigate(
928
+ `${project?.editorBasePath}/project-configuration`,
929
+ );
930
+ }}
931
+ >
932
+ Add name
933
+ </Button>
934
+ )}
935
+ {publishingDisabledReason ===
936
+ PUBLISHING_DISABLED_REASONS.LOGIC_ERRORS && (
937
+ <ul
938
+ className='entity-error__results outline'
939
+ onScroll={(e: any) => {
940
+ e.stopPropagation();
941
+ document.body.style.overflow = 'hidden';
942
+ }}
943
+ >
944
+ {projectErrors.map((error) => (
945
+ <EntityErrorListItem
946
+ error={error}
947
+ onClick={(e) => {
948
+ onClose(e);
949
+
950
+ // If the zoom is too small, zoom in to the entity
951
+ if (project.canvas?.currentScale < 0.7) {
952
+ project.canvas?.zoomTo(0.7);
953
+ } else if (project.canvas?.currentScale > 1) {
954
+ project.canvas?.zoomTo(1);
955
+ }
956
+
957
+ const canvasEntity = getParentCanvasEntity(
958
+ error.entity,
959
+ );
960
+
961
+ project.canvas?.scrollToObjectById(
962
+ getCanvasEntityDraggableContainerDOMId(canvasEntity),
963
+ );
964
+ }}
965
+ />
966
+ ))}
967
+ </ul>
968
+ )}
969
+ {publishingDisabledReason ===
970
+ PUBLISHING_DISABLED_REASONS.MISSING_ROW_TRANSFORMERS && (
971
+ <div
972
+ style={{
973
+ width: '100%',
974
+ maxWidth: 640,
975
+ display: 'flex',
976
+ flexDirection: 'column',
977
+ gap: 12,
978
+ }}
979
+ >
980
+ <ul
981
+ style={{
982
+ listStyle: 'none',
983
+ padding: 0,
984
+ margin: 0,
985
+ display: 'flex',
986
+ flexDirection: 'column',
987
+ gap: 8,
988
+ }}
989
+ >
990
+ {missingMigrationDiffs.map((diffs) => {
991
+ const entity = diffs.updatedEntityVersion;
992
+ const needsNew = diffs.newRowTransformerNeeded;
993
+ const isStale =
994
+ diffs.isPreexistingRowTransformerUpToDate === false;
995
+
996
+ return (
997
+ <li
998
+ key={entity.id + '--missing-row-transformer'}
999
+ style={{
1000
+ display: 'flex',
1001
+ alignItems: 'center',
1002
+ gap: 12,
1003
+ padding: '12px 14px',
1004
+ border: '1px solid rgba(0,0,0,0.08)',
1005
+ borderRadius: 8,
1006
+ background: '#fff',
1007
+ }}
1008
+ >
1009
+ <i
1010
+ className='fa-solid fa-database'
1011
+ style={{ color: '#ED6C02' }}
1012
+ />
1013
+ <div
1014
+ style={{
1015
+ display: 'flex',
1016
+ flexDirection: 'column',
1017
+ gap: 2,
1018
+ flex: 1,
1019
+ textAlign: 'left',
1020
+ }}
1021
+ >
1022
+ <span style={{ fontSize: 14, fontWeight: 500 }}>
1023
+ {entity.name}
1024
+ </span>
1025
+ <span
1026
+ style={{
1027
+ fontSize: 12,
1028
+ color: 'rgba(0,0,0,0.54)',
1029
+ }}
1030
+ >
1031
+ {needsNew
1032
+ ? 'Needs a new row transformer'
1033
+ : isStale
1034
+ ? 'Open row transformer is out of date'
1035
+ : 'Needs a row transformer'}
1036
+ </span>
1037
+ </div>
1038
+ </li>
1039
+ );
1040
+ })}
1041
+ </ul>
1042
+ <Button
1043
+ onClick={onAddMissingRowTransformers}
1044
+ style={{ alignSelf: 'center' }}
1045
+ >
1046
+ {missingMigrationDiffs.some(
1047
+ (d) => !!d.newestOpenRowTransformer,
1048
+ )
1049
+ ? 'Add to existing row transformers'
1050
+ : 'Generate row transformers'}
1051
+ </Button>
1052
+ </div>
1053
+ )}
1054
+ </div>
1055
+ )}
1056
+ {!publishingDisabledReason && !publishingDetails && (
1057
+ <Box
1058
+ sx={{
1059
+ display: 'flex',
1060
+ // flexGrow: 1,
1061
+ flexDirection: 'column',
1062
+ gap: 6,
1063
+ alignItems: 'center',
1064
+ height: 'calc(100% - 130px)',
1065
+ width: '100%',
1066
+ justifyContent: 'center',
1067
+ }}
1068
+ >
1069
+ <CircularProgress size={120} thickness={2} />
1070
+
1071
+ <Typography variant='h6'>
1072
+ Preparing publication preview...
1073
+ </Typography>
1074
+ </Box>
1075
+ )}
1076
+ </div>
1077
+ </div>
1078
+ {
1079
+ /*
1080
+ Error banner if publication is already on-going
1081
+ */
1082
+ !!project.publication &&
1083
+ project.publication.status === PublicationStatus.Running && (
1084
+ <div
1085
+ style={{
1086
+ marginBottom: 20,
1087
+ marginRight: 42,
1088
+ marginLeft: 42,
1089
+ }}
1090
+ >
1091
+ <Alert
1092
+ severity='error'
1093
+ // 1. Center the main icon vertically with the content
1094
+ sx={{ alignItems: 'center' }}
1095
+ // 2. Put your button in the action prop, which forces it to the right
1096
+ action={
1097
+ <MUIButton
1098
+ color='inherit'
1099
+ size='small'
1100
+ endIcon={<OpenInNewIcon />}
1101
+ onClick={() => {
1102
+ EditorService.navigate(
1103
+ `${project?.editorBasePath}/publication/publication-sequence/${project.publication?.id}`,
1104
+ );
1105
+ }}
1106
+ >
1107
+ VIEW
1108
+ </MUIButton>
1109
+ }
1110
+ >
1111
+ <strong>Ongoing publication</strong> Another publication is
1112
+ currently running. Please wait for it to finish before starting
1113
+ a new one.
1114
+ </Alert>
1115
+ </div>
1116
+ )
1117
+ }
1118
+ <div
1119
+ style={{
1120
+ alignSelf: 'flex-start',
1121
+ display: 'flex',
1122
+ flexDirection: 'row',
1123
+ justifyContent: 'flex-end',
1124
+ width: '100%',
1125
+ gap: '16px',
1126
+ }}
1127
+ >
1128
+ <Button
1129
+ onClick={() => {
1130
+ EditorService.navigate(`${project?.editorBasePath}`);
1131
+ }}
1132
+ color='primary'
1133
+ variant='text'
1134
+ >
1135
+ Cancel
1136
+ </Button>
1137
+ <Button
1138
+ onClick={onPublishClick}
1139
+ disabled={
1140
+ !!publishingDisabledReason ||
1141
+ dataIsLoading ||
1142
+ (!!project.publication &&
1143
+ project.publication.status === PublicationStatus.Running)
1144
+ }
1145
+ loading={isInitialisingPublication}
1146
+ >
1147
+ Publish{' '}
1148
+ {
1149
+ publishingDetails?.nextPublicationDetails
1150
+ ?.nextProjectPublishedSemanticVersion
1151
+ }
1152
+ </Button>
1153
+ </div>
1154
+ </div>
1155
+ );
1156
+ };
1157
+
1158
+ export default PublicationPreviewDialog;