@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,3127 @@
1
+ import React from 'react';
2
+ import {
3
+ createStateFromTypeAndSubscribe,
4
+ DefinitionEntityState,
5
+ DataTypeParentChildRelation,
6
+ DataTypeState,
7
+ EntityType,
8
+ IDataTypeTransfer,
9
+ ILiteralValueTransfer,
10
+ PrimitiveTypes,
11
+ LiteralValueState,
12
+ resolveEntityName,
13
+ ChangeSet,
14
+ ChangeSetEntityChangeType,
15
+ resolveDataTypeLabel,
16
+ UserManagedEntityState,
17
+ BUILT_IN_BASE_ENTITY_IDS,
18
+ PrimitiveEntityState,
19
+ IPrimitiveEntityTransfer,
20
+ VALUE_READING_TYPES,
21
+ UserManagedDataTypeParentEntityState,
22
+ checkIsNullable,
23
+ DataTypeStateEntityOption,
24
+ getParentCanvasEntity,
25
+ definitionEntityValidation,
26
+ findNextAvailableName,
27
+ checkIsOnlyNull,
28
+ toSentenceCase,
29
+ recursivelySelectDataTypeOption,
30
+ flattenDataTypesInOrGroup,
31
+ } from '@elyx-code/project-logic-tree';
32
+ import WarningIcon from '../../assets/warning-sign-24px.png';
33
+ import {
34
+ Autocomplete,
35
+ Box,
36
+ Checkbox,
37
+ FormControlLabel,
38
+ FormGroup,
39
+ IconButton,
40
+ TextField,
41
+ Tooltip as MuiTooltip,
42
+ Chip,
43
+ } from '@mui/material';
44
+ import DropdownMenuPopup from '../../lib/dropdown/DropdownMenuPopup';
45
+ import Tooltip from '../../lib/tooltip/Tooltip';
46
+ import DataTypeIcon, {
47
+ ExplicitDataTypeIcon,
48
+ } from '../draggable-entity-card/DataTypeIcon';
49
+ import { DateTimePicker } from '@mui/x-date-pickers';
50
+ import dayjs from 'dayjs';
51
+ import { EditorService } from '../../services/editor';
52
+ import DefinitionEntityIcon from '../draggable-entity-card/definition-entity/DefinitionEntityIcon';
53
+ import {
54
+ calculateCardSize,
55
+ CANVAS_VERTICAL_BUFFER_BETWEEN_CARDS,
56
+ getCanvasEntityDraggableContainerDOMId,
57
+ resolveCardSubheader,
58
+ } from '../../services/editor/ui';
59
+ import './data-type-builder.css';
60
+ import {
61
+ DataTypeBuilderOption,
62
+ getAllDataTypeBuilderOptions,
63
+ } from '../../services/editor/utils';
64
+ import { popupNotification } from '../../popup-notification';
65
+ import Button from '../../lib/button/Button';
66
+
67
+ export interface ILiteralValueOption {
68
+ type: 'literal-value-option';
69
+ name: PrimitiveTypes;
70
+ }
71
+
72
+ export function fromLiteralValueTypeToHTMLInputType(
73
+ name: PrimitiveTypes,
74
+ ): 'text' | 'number' | 'date' {
75
+ switch (name) {
76
+ case PrimitiveTypes.String:
77
+ return 'text';
78
+ case PrimitiveTypes.Number:
79
+ return 'number';
80
+ case PrimitiveTypes.Date:
81
+ return 'date';
82
+ default:
83
+ return 'text';
84
+ }
85
+ }
86
+
87
+ export function fromLiteralValueTypeToReadableLabel(name: PrimitiveTypes): string {
88
+ switch (name) {
89
+ case PrimitiveTypes.String:
90
+ return 'Text';
91
+ case PrimitiveTypes.Number:
92
+ return 'Number';
93
+ case PrimitiveTypes.Date:
94
+ return 'Date';
95
+ case PrimitiveTypes.Boolean:
96
+ return 'Boolean';
97
+ case PrimitiveTypes.Null:
98
+ return 'Null';
99
+ case PrimitiveTypes.Untyped:
100
+ return 'Any type';
101
+ case PrimitiveTypes.Void:
102
+ return 'Void';
103
+ default:
104
+ return !!name ? toSentenceCase(name) : 'Unknown';
105
+ }
106
+ }
107
+
108
+ export const fromLiteralValueTypeToExplicitIconName = (
109
+ name: PrimitiveTypes,
110
+ ): PrimitiveTypes | 'list' | EntityType.DefinitionEntity | 'unknown' => {
111
+ switch (name) {
112
+ case PrimitiveTypes.String:
113
+ return PrimitiveTypes.String;
114
+ case PrimitiveTypes.Number:
115
+ return PrimitiveTypes.Number;
116
+ case PrimitiveTypes.Date:
117
+ return PrimitiveTypes.Date;
118
+ case PrimitiveTypes.Boolean:
119
+ return PrimitiveTypes.Boolean;
120
+ case PrimitiveTypes.Null:
121
+ return PrimitiveTypes.Null;
122
+ default:
123
+ return name;
124
+ }
125
+ };
126
+
127
+ export const fromLiteralValueTypeToFontColor = (name: PrimitiveTypes): string => {
128
+ switch (name) {
129
+ case PrimitiveTypes.String:
130
+ return 'var(--color-string--value)';
131
+ case PrimitiveTypes.Number:
132
+ return 'var(--color-number--value)';
133
+ case PrimitiveTypes.Date:
134
+ return 'var(--color-string--value)';
135
+ case PrimitiveTypes.Boolean:
136
+ return 'var(--color-boolean--value)';
137
+ case PrimitiveTypes.Null:
138
+ return 'var(--color-support-primary)';
139
+ case PrimitiveTypes.Untyped:
140
+ return 'rgba(0,0,0,0.6)';
141
+ default:
142
+ return 'black';
143
+ }
144
+ };
145
+
146
+ export const resolveLiteralValueSubheader = (
147
+ primitiveVame: PrimitiveTypes,
148
+ ): string => {
149
+ if (primitiveVame === PrimitiveTypes.Null) {
150
+ return 'An explicit empty value';
151
+ }
152
+
153
+ if (primitiveVame === PrimitiveTypes.Untyped) {
154
+ return 'Allows any type of value';
155
+ }
156
+
157
+ if (primitiveVame === PrimitiveTypes.Void) {
158
+ return 'When actions don\'t output any value';
159
+ }
160
+
161
+ return 'A literal inputted value';
162
+ };
163
+
164
+ export const resolveLiteralValueLabel = (
165
+ value: LiteralValueState | ILiteralValueOption,
166
+ ): string => {
167
+ if (value.name === PrimitiveTypes.Untyped) {
168
+ return 'Any type allowed';
169
+ }
170
+
171
+ return fromLiteralValueTypeToReadableLabel(value.name) + ' value';
172
+ };
173
+
174
+ export enum AllowedDataTypeListTypes {
175
+ None = 'none',
176
+ All = 'all',
177
+ Flat = 'flat',
178
+ }
179
+
180
+ const LiteralValueField = ({
181
+ value,
182
+ disabled,
183
+ onChange,
184
+ onChangeSet,
185
+ }: {
186
+ value: LiteralValueState;
187
+ disabled?: boolean;
188
+ onChange: (value: LiteralValueState, changeSet: ChangeSet | null) => void;
189
+ onChangeSet?: () => ChangeSet | null;
190
+ }) => {
191
+ const [localValue, setLocalValue] = React.useState<number | string | Date>(
192
+ value?.value as number | string | Date,
193
+ );
194
+
195
+ // Based on the value type, we render a different input field
196
+ if (value.name === PrimitiveTypes.Boolean) {
197
+ return (
198
+ <FormGroup>
199
+ <FormControlLabel
200
+ control={
201
+ <Checkbox
202
+ disabled={disabled}
203
+ className='data-type-builder--checkbox'
204
+ checked={value.value as boolean}
205
+ onChange={(e) => {
206
+ const changeSet = onChangeSet?.() || null;
207
+
208
+ value.metaSync(
209
+ {
210
+ value: e.target.checked,
211
+ },
212
+ changeSet,
213
+ );
214
+
215
+ onChange(value, changeSet);
216
+ }}
217
+ />
218
+ }
219
+ label={value.value ? 'True' : 'False'}
220
+ />
221
+ </FormGroup>
222
+ );
223
+ } else if (value.name === PrimitiveTypes.Date) {
224
+ return (
225
+ <DateTimePicker
226
+ disabled={disabled}
227
+ defaultValue={value.value ? dayjs(value.value as Date) : undefined}
228
+ slotProps={{
229
+ field: {
230
+ // @ts-ignore
231
+ size: 'small',
232
+ sx: {
233
+ width: 200,
234
+ },
235
+ },
236
+ }}
237
+ onChange={(newValue) => {
238
+ setLocalValue(newValue.toDate());
239
+ }}
240
+ onBlur={() => {
241
+ const changeSet = onChangeSet?.() || null;
242
+
243
+ value.metaSync(
244
+ {
245
+ value: localValue,
246
+ },
247
+ changeSet,
248
+ );
249
+
250
+ onChange(value, changeSet);
251
+ }}
252
+ />
253
+ );
254
+ }
255
+
256
+ return (
257
+ <TextField
258
+ size='small'
259
+ label='Value'
260
+ disabled={disabled}
261
+ type={fromLiteralValueTypeToHTMLInputType(value.name)}
262
+ value={localValue}
263
+ onChange={(e) => {
264
+ setLocalValue(e.target.value);
265
+ }}
266
+ onBlur={() => {
267
+ const changeSet = onChangeSet?.() || null;
268
+
269
+ value.metaSync(
270
+ {
271
+ value: localValue,
272
+ },
273
+ changeSet,
274
+ );
275
+
276
+ onChange(value, changeSet);
277
+ }}
278
+ />
279
+ );
280
+ };
281
+
282
+ const DataTypeSelectorValue = ({
283
+ value,
284
+ project,
285
+ }: {
286
+ value: DataTypeBuilderOption | ILiteralValueOption;
287
+ project: EditorService;
288
+ }) => {
289
+ if (
290
+ value?.type === EntityType.PrimitiveEntity &&
291
+ (value.id ===
292
+ BUILT_IN_BASE_ENTITY_IDS[EntityType.PrimitiveEntity].null.id ||
293
+ value.id ===
294
+ BUILT_IN_BASE_ENTITY_IDS[EntityType.PrimitiveEntity].untyped.id)
295
+ ) {
296
+ return (
297
+ <span
298
+ style={{
299
+ display: 'flex',
300
+ flexDirection: 'column',
301
+ }}
302
+ >
303
+ <span
304
+ style={{
305
+ display: 'flex',
306
+ alignItems: 'center',
307
+ gap: 8,
308
+ color: fromLiteralValueTypeToFontColor(value.name),
309
+ }}
310
+ >
311
+ <ExplicitDataTypeIcon
312
+ icon={fromLiteralValueTypeToExplicitIconName(value.name)}
313
+ size='small'
314
+ id={value.id}
315
+ />
316
+ {fromLiteralValueTypeToReadableLabel(value.name) + ' value'}
317
+ </span>
318
+ <p
319
+ style={{
320
+ margin: 0,
321
+ marginLeft: 20,
322
+ fontSize: 10,
323
+ color: 'rgba(0,0,0,0.54)',
324
+ }}
325
+ >
326
+ {resolveLiteralValueSubheader(value.name)}
327
+ </p>
328
+ </span>
329
+ );
330
+ } else if (
331
+ [
332
+ EntityType.ActionDescriptor,
333
+ EntityType.DefinitionEntity,
334
+ EntityType.PrimitiveEntity,
335
+ EntityType.BuiltInBaseEntity,
336
+ ].includes(value?.type as EntityType)
337
+ ) {
338
+ return (
339
+ <span
340
+ style={{
341
+ display: 'flex',
342
+ flexDirection: 'column',
343
+ }}
344
+ >
345
+ <span
346
+ style={{
347
+ display: 'flex',
348
+ alignItems: 'center',
349
+ gap: 8,
350
+ }}
351
+ >
352
+ <DefinitionEntityIcon
353
+ entity={value as DefinitionEntityState}
354
+ size='small'
355
+ />
356
+ {resolveEntityName(value as DataTypeBuilderOption, project.logic) ||
357
+ '-'}
358
+ </span>
359
+ <p
360
+ style={{
361
+ margin: 0,
362
+ marginLeft: 20,
363
+ fontSize: 10,
364
+ color: 'rgba(0,0,0,0.54)',
365
+ }}
366
+ >
367
+ {resolveCardSubheader(value as DefinitionEntityState)}
368
+ </p>
369
+ </span>
370
+ );
371
+ } else if (
372
+ value?.type === EntityType.LiteralValue ||
373
+ value?.type === 'literal-value-option'
374
+ ) {
375
+ return (
376
+ <span
377
+ style={{
378
+ display: 'flex',
379
+ flexDirection: 'column',
380
+ }}
381
+ >
382
+ <span
383
+ style={{
384
+ display: 'flex',
385
+ alignItems: 'center',
386
+ gap: 8,
387
+ color: fromLiteralValueTypeToFontColor(value.name),
388
+ }}
389
+ >
390
+ <ExplicitDataTypeIcon
391
+ icon={fromLiteralValueTypeToExplicitIconName(value.name)}
392
+ size='small'
393
+ id={'data-type-builder-value-option--' + value.name}
394
+ />
395
+ {resolveLiteralValueLabel(value)}
396
+ </span>
397
+ <p
398
+ style={{
399
+ margin: 0,
400
+ marginLeft: 20,
401
+ fontSize: 10,
402
+ color: 'rgba(0,0,0,0.54)',
403
+ }}
404
+ >
405
+ {resolveLiteralValueSubheader(value.name)}
406
+ </p>
407
+ </span>
408
+ );
409
+ } else if (EntityType.Property === value?.type) {
410
+ const foreignEntityName = resolveEntityName(value, project.logic);
411
+ const foreignKeyParentName = resolveEntityName(value.parent, project.logic);
412
+
413
+ const subLabel = (
414
+ <>
415
+ Reference to <b>{foreignEntityName}</b> from{' '}
416
+ <b>{foreignKeyParentName}</b>
417
+ </>
418
+ );
419
+
420
+ return (
421
+ <span
422
+ style={{
423
+ display: 'flex',
424
+ flexDirection: 'column',
425
+ }}
426
+ >
427
+ <span
428
+ style={{
429
+ display: 'flex',
430
+ alignItems: 'center',
431
+ gap: 8,
432
+ }}
433
+ >
434
+ <DataTypeIcon entity={value} size='small' project={project} />
435
+ {resolveEntityName(value, project.logic) || '-'}
436
+ </span>
437
+ <p
438
+ style={{
439
+ margin: 0,
440
+ marginLeft: 20,
441
+ fontSize: 10,
442
+ color: 'rgba(0,0,0,0.54)',
443
+ }}
444
+ >
445
+ {subLabel}
446
+ </p>
447
+ </span>
448
+ );
449
+ }
450
+
451
+ return null;
452
+ };
453
+
454
+ export enum DataTypeValueDisabledReason {
455
+ External = 'external',
456
+ IncompatibleSiblingsCrossSection = 'incompatible-siblings-cross-section',
457
+ IncompatibleWithImplementation = 'incompatible-with-implementation',
458
+ }
459
+
460
+ export function calculateOptionDisabledReasons(
461
+ option: DataTypeBuilderOption | ILiteralValueOption,
462
+ getOptionDisabled?: (
463
+ option: DataTypeBuilderOption | ILiteralValueOption,
464
+ ) => boolean,
465
+ baseDataTypes?: DataTypeState[],
466
+ topBaseDataTypes?: DataTypeState[],
467
+ ): DataTypeValueDisabledReason[] {
468
+ const reasons: DataTypeValueDisabledReason[] = [];
469
+
470
+ const externalCheck: boolean = getOptionDisabled?.(option);
471
+ if (externalCheck) {
472
+ reasons.push(DataTypeValueDisabledReason.External);
473
+ }
474
+
475
+ if (
476
+ (option.type === 'literal-value-option' &&
477
+ option.name === PrimitiveTypes.Null) ||
478
+ ([EntityType.PrimitiveEntity, EntityType.LiteralValue].includes(
479
+ option.type as EntityType,
480
+ ) &&
481
+ option.name === PrimitiveTypes.Null)
482
+ ) {
483
+ if (!topBaseDataTypes?.length) {
484
+ return [];
485
+ }
486
+
487
+ const everyTopBaseDataTypeIsNullable = (topBaseDataTypes || []).every(
488
+ (baseDt) => {
489
+ const topParentIsOnlyNull = checkIsOnlyNull(baseDt);
490
+
491
+ return topParentIsOnlyNull;
492
+ },
493
+ );
494
+
495
+ if (!everyTopBaseDataTypeIsNullable) {
496
+ return [DataTypeValueDisabledReason.IncompatibleWithImplementation];
497
+ }
498
+
499
+ return [];
500
+ }
501
+
502
+ if (
503
+ baseDataTypes &&
504
+ !!baseDataTypes.length // &&
505
+ // !!(baseDataTypes || []).some((dt) => dt.implementationChooseOne)
506
+ ) {
507
+ let isCompatible: boolean = false;
508
+
509
+ const allAllowedBaseDataTypes: DataTypeState[] = baseDataTypes.flatMap(
510
+ (dt) => flattenDataTypesInOrGroup(dt),
511
+ );
512
+
513
+ // Disable options that are not present in the children of the baseDataTypes
514
+ for (const child of allAllowedBaseDataTypes) {
515
+ if (
516
+ (option.type === 'literal-value-option' &&
517
+ option.name === child.entity?.name &&
518
+ child.entity?.type === EntityType.LiteralValue) ||
519
+ (option.type !== 'literal-value-option' &&
520
+ option.id === child.entity?.id &&
521
+ child.entity?.type !== EntityType.LiteralValue)
522
+ ) {
523
+ isCompatible = true;
524
+ break;
525
+ }
526
+
527
+ if (child.foreignKeyAllowed && option.type === EntityType.Property) {
528
+ isCompatible = true;
529
+ break;
530
+ }
531
+
532
+ if (
533
+ option.type !== 'literal-value-option' &&
534
+ option.id === child.entity?.id
535
+ ) {
536
+ isCompatible = true;
537
+ break;
538
+ }
539
+ }
540
+
541
+ if (!isCompatible) {
542
+ reasons.push(DataTypeValueDisabledReason.IncompatibleWithImplementation);
543
+ }
544
+ } else {
545
+ }
546
+
547
+ return reasons;
548
+ }
549
+
550
+ export interface IDataTypeBuilderOption {
551
+ value: DataTypeBuilderOption | ILiteralValueOption;
552
+ disabledReasons: DataTypeValueDisabledReason[];
553
+ }
554
+
555
+ const DataTypeValueSelector = ({
556
+ dataType,
557
+ parentBaseDataTypes: _parentBaseDataTypes,
558
+ topParent: _topParent,
559
+ topBaseDataTypes,
560
+ baseDataTypes,
561
+ value,
562
+ onChange,
563
+ options,
564
+ project,
565
+ getOptionDisabled,
566
+ getOptionTooltip,
567
+ onChangeSet,
568
+ }: {
569
+ dataType: DataTypeState;
570
+ baseDataTypes?: DataTypeState[];
571
+ parentBaseDataTypes?: DataTypeState[];
572
+ topParent?: UserManagedEntityState;
573
+ topBaseDataTypes?: DataTypeState[];
574
+ value: DataTypeBuilderOption;
575
+ onChange: (value: DataTypeState, changeSet: ChangeSet | null) => void;
576
+ options: DataTypeBuilderOption[];
577
+ project: EditorService;
578
+ getOptionDisabled?: (
579
+ option: DataTypeBuilderOption | ILiteralValueOption,
580
+ ) => boolean;
581
+ getOptionTooltip?: (
582
+ option: DataTypeBuilderOption | ILiteralValueOption,
583
+ ) => React.ReactNode;
584
+ onChangeSet?: () => ChangeSet | null;
585
+ }) => {
586
+ const [updateKey, setUpdateKey] = React.useState<number>(0);
587
+
588
+ const resolveLocalValueFromExternalValue = (
589
+ value: DataTypeBuilderOption,
590
+ ): IDataTypeBuilderOption => {
591
+ if (value?.type === EntityType.LiteralValue) {
592
+ return {
593
+ value: {
594
+ type: 'literal-value-option',
595
+ name: value.name,
596
+ },
597
+ disabledReasons: [],
598
+ // calculateOptionDisabledReasons(
599
+ // value,
600
+ // getOptionDisabled,
601
+ // baseDataTypes,
602
+ // topBaseDataTypes
603
+ // ),
604
+ };
605
+ }
606
+
607
+ return {
608
+ value,
609
+ disabledReasons: [],
610
+ // calculateOptionDisabledReasons(
611
+ // value,
612
+ // getOptionDisabled,
613
+ // baseDataTypes,
614
+ // topBaseDataTypes
615
+ // ),
616
+ };
617
+ };
618
+
619
+ const [localValue, setLocalValue] = React.useState<IDataTypeBuilderOption>(
620
+ resolveLocalValueFromExternalValue(value),
621
+ );
622
+ const [localEnumOptionsValue, setLocalEnumOptionsValue] = React.useState<
623
+ null | string[]
624
+ >(dataType?.options || []);
625
+
626
+ const aggregateOptions: (DataTypeBuilderOption | ILiteralValueOption)[] = [
627
+ ...options.filter((opt) => opt.type === EntityType.PrimitiveEntity),
628
+ {
629
+ type: 'literal-value-option',
630
+ name: PrimitiveTypes.Untyped,
631
+ },
632
+ {
633
+ type: 'literal-value-option',
634
+ name: PrimitiveTypes.String,
635
+ },
636
+ {
637
+ type: 'literal-value-option',
638
+ name: PrimitiveTypes.Number,
639
+ },
640
+ {
641
+ type: 'literal-value-option',
642
+ name: PrimitiveTypes.Boolean,
643
+ },
644
+ // {
645
+ // type: 'literal-value-option',
646
+ // name: PrimitiveTypes.Null,
647
+ // },
648
+ ...options.filter((opt) => opt.type !== EntityType.PrimitiveEntity),
649
+
650
+ // Put disabled options at the end
651
+ ];
652
+
653
+ const sanitizedOptions: IDataTypeBuilderOption[] = aggregateOptions
654
+ .map((opt) => {
655
+ const disabledReasons = calculateOptionDisabledReasons(
656
+ opt,
657
+ getOptionDisabled,
658
+ baseDataTypes,
659
+ topBaseDataTypes,
660
+ );
661
+
662
+ return {
663
+ value: opt,
664
+ disabledReasons,
665
+ };
666
+ })
667
+ .sort((a, b) => {
668
+ if (a.disabledReasons.length && !b.disabledReasons.length) {
669
+ return 1;
670
+ }
671
+
672
+ if (!a.disabledReasons.length && b.disabledReasons.length) {
673
+ return -1;
674
+ }
675
+
676
+ return 0;
677
+ }) as IDataTypeBuilderOption[];
678
+
679
+ const showEnumBuilderField: boolean =
680
+ !!localValue &&
681
+ localValue?.value?.type === EntityType.PrimitiveEntity &&
682
+ localValue?.value.name === PrimitiveTypes.Enum;
683
+
684
+ const showLiteralValueField: boolean =
685
+ !showEnumBuilderField &&
686
+ !!localValue &&
687
+ localValue?.value?.type === 'literal-value-option' &&
688
+ ![PrimitiveTypes.Null, PrimitiveTypes.Untyped].includes(
689
+ localValue?.value?.name,
690
+ );
691
+
692
+ return (
693
+ <span
694
+ key={updateKey}
695
+ style={{
696
+ display: 'flex',
697
+ gap: 8,
698
+ alignItems: 'center',
699
+ }}
700
+ >
701
+ <Autocomplete
702
+ disablePortal
703
+ // disabled={
704
+ // !!baseDataTypes?.length &&
705
+ // !(baseDataTypes || []).some((dt) => dt.implementationChooseOne)
706
+ // }
707
+ options={sanitizedOptions}
708
+ sx={{
709
+ width: 200,
710
+ }}
711
+ value={localValue}
712
+ getOptionLabel={(option) => {
713
+ if (option.value?.type === 'literal-value-option') {
714
+ return resolveLiteralValueLabel(option.value);
715
+ } else if (!!option.value) {
716
+ return resolveEntityName(option.value, project.logic) || '-';
717
+ }
718
+
719
+ return '-';
720
+ }}
721
+ getOptionDisabled={(option) => {
722
+ return option.disabledReasons.length > 0;
723
+ }}
724
+ onChange={(_, newValue) => {
725
+ const changeSet = onChangeSet?.() || null;
726
+
727
+ let resolvedNewValue: DataTypeBuilderOption;
728
+
729
+ const oldEntityValue = dataType.entity;
730
+
731
+ if (
732
+ newValue?.value?.type === 'literal-value-option' &&
733
+ newValue?.value.name !== PrimitiveTypes.Untyped &&
734
+ newValue?.value.name !== PrimitiveTypes.Null
735
+ ) {
736
+ const newLiteralValueTransfer: ILiteralValueTransfer =
737
+ LiteralValueState.new(changeSet);
738
+
739
+ newLiteralValueTransfer.name = newValue?.value.name;
740
+ newLiteralValueTransfer.parent = dataType.toReference();
741
+
742
+ resolvedNewValue = createStateFromTypeAndSubscribe(
743
+ newLiteralValueTransfer,
744
+ project.logic,
745
+ ) as LiteralValueState;
746
+
747
+ changeSet?.add(resolvedNewValue, ChangeSetEntityChangeType.Added);
748
+
749
+ resolvedNewValue.initChildren(changeSet);
750
+
751
+ resolvedNewValue.metaSync(
752
+ {
753
+ name: newValue?.value.name,
754
+ },
755
+ changeSet,
756
+ );
757
+ } else if (
758
+ newValue?.value?.type === 'literal-value-option' &&
759
+ newValue?.value.name === PrimitiveTypes.Untyped
760
+ ) {
761
+ resolvedNewValue = project.logic.getBuiltIn(
762
+ BUILT_IN_BASE_ENTITY_IDS['primitive-entity'].untyped.id,
763
+ ) as PrimitiveEntityState;
764
+ } else if (
765
+ newValue?.value?.type === 'literal-value-option' &&
766
+ newValue?.value.name === PrimitiveTypes.Null
767
+ ) {
768
+ resolvedNewValue = project.logic.getBuiltIn(
769
+ BUILT_IN_BASE_ENTITY_IDS['primitive-entity'].null.id,
770
+ ) as PrimitiveEntityState;
771
+ } else {
772
+ resolvedNewValue =
773
+ (newValue?.value as DataTypeBuilderOption) || null;
774
+ }
775
+
776
+ if (resolvedNewValue?.type === EntityType.Property) {
777
+ dataType.setForeignKeyRef(resolvedNewValue, changeSet);
778
+ dataType.setEntity(null, changeSet);
779
+ } else {
780
+ // Send a new literal value as well, but with the value property being empty,
781
+ // when the component is updated, the local value will be set
782
+ dataType.setEntity(resolvedNewValue, changeSet);
783
+ dataType.setForeignKeyRef(null, changeSet);
784
+ }
785
+
786
+ dataType.orChildrenGroup?.forEach((child) => {
787
+ child.remove({ ignoreUpstream: true }, changeSet);
788
+ });
789
+ dataType.andChildrenGroup?.forEach((child) => {
790
+ child.remove({ ignoreUpstream: true }, changeSet);
791
+ });
792
+ dataType.orChildrenGroup = null;
793
+ dataType.andChildrenGroup = null;
794
+
795
+ changeSet?.add(dataType, ChangeSetEntityChangeType.Updated);
796
+
797
+ if (resolvedNewValue?.type === EntityType.LiteralValue) {
798
+ dataType.metaSync(
799
+ {
800
+ asType: false,
801
+ like: false,
802
+ },
803
+ changeSet,
804
+ );
805
+
806
+ resolvedNewValue.setParent(dataType, changeSet);
807
+ }
808
+
809
+ if (newValue?.value.name !== PrimitiveTypes.Enum) {
810
+ dataType.metaSync(
811
+ {
812
+ options: null,
813
+ },
814
+ changeSet,
815
+ );
816
+
817
+ setLocalEnumOptionsValue([]);
818
+ }
819
+
820
+ if (
821
+ !!oldEntityValue &&
822
+ (oldEntityValue as DefinitionEntityState).parent?.id ===
823
+ dataType.id &&
824
+ resolvedNewValue?.id !== oldEntityValue.id
825
+ ) {
826
+ (oldEntityValue as DefinitionEntityState).remove(
827
+ { ignoreUpstream: true },
828
+ changeSet,
829
+ );
830
+ }
831
+
832
+ dataType.metaSync(
833
+ {
834
+ inferred: false,
835
+ },
836
+ changeSet,
837
+ );
838
+
839
+ onChange(dataType, changeSet);
840
+ setLocalValue(resolveLocalValueFromExternalValue(resolvedNewValue));
841
+
842
+ setUpdateKey(updateKey + 1);
843
+ }}
844
+ renderOption={(props, option) => {
845
+ const { key, ...optionProps } = props;
846
+ return (
847
+ <MuiTooltip
848
+ key={key}
849
+ title={getOptionTooltip?.(option.value)}
850
+ placement='right'
851
+ arrow
852
+ enterDelay={!!option.disabledReasons.length ? 100 : 400}
853
+ leaveDelay={200}
854
+ >
855
+ <Box
856
+ component='li'
857
+ sx={{ '& > img': { mr: 2, flexShrink: 0 } }}
858
+ {...optionProps}
859
+ >
860
+ <DataTypeSelectorValue value={option.value} project={project} />
861
+ </Box>
862
+ </MuiTooltip>
863
+ );
864
+ }}
865
+ renderInput={(params) => (
866
+ <span
867
+ style={{ position: 'relative', display: 'block', height: '100%' }}
868
+ >
869
+ <span
870
+ id={
871
+ 'data-type-builder--' +
872
+ (value?.id || 'unknown') +
873
+ `--input-selected-value`
874
+ }
875
+ style={{
876
+ position: 'absolute',
877
+ top: 8,
878
+ left: 0,
879
+ width: '100%',
880
+ height: '100%',
881
+ maxHeight: 30,
882
+ overflowY: 'hidden',
883
+ // To match start of text field text
884
+ paddingLeft: 14,
885
+ display: 'flex',
886
+ flexDirection: 'column',
887
+ }}
888
+ >
889
+ <DataTypeSelectorValue value={value} project={project} />
890
+ </span>
891
+
892
+ <TextField
893
+ {...params}
894
+ size='small'
895
+ label={`Select value`}
896
+ className={`data-type-builder__input`}
897
+ slotProps={{
898
+ htmlInput: {
899
+ ...params.inputProps,
900
+ id:
901
+ 'data-type-builder--' +
902
+ (value?.id || 'unknown') +
903
+ `--input`,
904
+ style: {
905
+ opacity: 0,
906
+ },
907
+ },
908
+ }}
909
+ onFocus={(e) => {
910
+ e.target.style.opacity = '1';
911
+
912
+ const selectedValueElement = document.getElementById(
913
+ 'data-type-builder--' +
914
+ (value?.id || 'unknown') +
915
+ `--input-selected-value`,
916
+ );
917
+
918
+ if (!!selectedValueElement) {
919
+ selectedValueElement.style.visibility = 'hidden';
920
+ }
921
+ }}
922
+ onBlur={(e) => {
923
+ e.target.style.opacity = '0';
924
+
925
+ const selectedValueElement = document.getElementById(
926
+ 'data-type-builder--' +
927
+ (value?.id || 'unknown') +
928
+ `--input-selected-value`,
929
+ );
930
+
931
+ if (!!selectedValueElement) {
932
+ selectedValueElement.style.visibility = 'visible';
933
+ }
934
+ }}
935
+ />
936
+ </span>
937
+ )}
938
+ />
939
+ {showEnumBuilderField && (
940
+ <Autocomplete
941
+ sx={{
942
+ minWidth: 200,
943
+ }}
944
+ disabled={(() => {
945
+ if (!(baseDataTypes || []).length) {
946
+ return false;
947
+ }
948
+
949
+ if (
950
+ (baseDataTypes || []).some((dt) => dt.implementationChooseOne)
951
+ ) {
952
+ if (
953
+ (baseDataTypes || []).every((dt) => {
954
+ return (dt.orChildrenGroup || []).some(
955
+ (child) =>
956
+ child.entity?.type === EntityType.PrimitiveEntity &&
957
+ (child.entity as PrimitiveEntityState).name ===
958
+ PrimitiveTypes.Enum,
959
+ );
960
+ })
961
+ ) {
962
+ return false;
963
+ }
964
+
965
+ return true;
966
+ }
967
+
968
+ return false;
969
+ })()}
970
+ multiple
971
+ freeSolo
972
+ size='small'
973
+ id={`data-type-builder--enum-builder--${dataType?.id}`}
974
+ options={[]}
975
+ disableClearable
976
+ value={localEnumOptionsValue}
977
+ renderOption={(optionProps, option, state, ownerState) => {
978
+ return (
979
+ <Box
980
+ component='li'
981
+ sx={{ '& > img': { mr: 2, flexShrink: 0 } }}
982
+ {...optionProps}
983
+ onClick={(e) => {
984
+ if (option.startsWith('Add "')) {
985
+ const newOption = option.slice(5, -1);
986
+
987
+ if (!newOption) {
988
+ return;
989
+ }
990
+ if (localEnumOptionsValue.includes(newOption)) {
991
+ return;
992
+ }
993
+
994
+ const newValue = [...localEnumOptionsValue, newOption];
995
+ setLocalEnumOptionsValue(newValue);
996
+
997
+ // Add new value to the list
998
+ const changeSet = onChangeSet?.() || null;
999
+
1000
+ dataType.metaSync(
1001
+ {
1002
+ options: newValue,
1003
+ },
1004
+ changeSet,
1005
+ );
1006
+
1007
+ onChange(dataType, changeSet);
1008
+ } else {
1009
+ optionProps.onClick(e);
1010
+ }
1011
+ }}
1012
+ >
1013
+ {option}
1014
+ </Box>
1015
+ );
1016
+ }}
1017
+ filterOptions={(options, params) => {
1018
+ const filtered: string[] = [];
1019
+
1020
+ const { inputValue } = params;
1021
+
1022
+ if (inputValue !== '') {
1023
+ return [`Add "${inputValue}"`];
1024
+ }
1025
+
1026
+ return filtered;
1027
+ }}
1028
+ defaultValue={dataType.options || []}
1029
+ open
1030
+ noOptionsText={"Press 'Enter' to add a new value"}
1031
+ onChange={(_, newValue) => {
1032
+ const changeSet = onChangeSet?.() || null;
1033
+
1034
+ const sanitizedNewValue = (newValue || [])
1035
+ // Sanitize the 'Add "value"' option
1036
+ .map((value) => {
1037
+ if (value.startsWith('Add "')) {
1038
+ const newOption = value.slice(5, -1);
1039
+
1040
+ if (!newOption) {
1041
+ return;
1042
+ }
1043
+ if (localEnumOptionsValue.includes(newOption)) {
1044
+ return;
1045
+ }
1046
+
1047
+ return newOption;
1048
+ }
1049
+
1050
+ return value;
1051
+ })
1052
+ .filter(
1053
+ // Filter duplicates
1054
+ (value, index, self) =>
1055
+ self.indexOf(value) === index && !!value,
1056
+ );
1057
+
1058
+ setLocalEnumOptionsValue(sanitizedNewValue);
1059
+
1060
+ dataType.metaSync(
1061
+ {
1062
+ options: sanitizedNewValue as string[],
1063
+ },
1064
+ changeSet,
1065
+ );
1066
+
1067
+ onChange(dataType, changeSet);
1068
+
1069
+ setUpdateKey(updateKey + 1);
1070
+ }}
1071
+ renderTags={(value, getTagProps) => {
1072
+ return value.map((option, index) => (
1073
+ <Chip
1074
+ variant='outlined'
1075
+ size='small'
1076
+ label={option}
1077
+ deleteIcon={!!baseDataTypes?.length ? <></> : undefined}
1078
+ {...getTagProps({ index })}
1079
+ disabled={false}
1080
+ />
1081
+ ));
1082
+ }}
1083
+ renderInput={(params) => (
1084
+ <TextField
1085
+ {...params}
1086
+ id={`data-type-builder--enum-builder--${dataType?.id}--input`}
1087
+ variant='outlined'
1088
+ label={'Allowed values'}
1089
+ placeholder='New value'
1090
+ />
1091
+ )}
1092
+ />
1093
+ )}
1094
+ {showLiteralValueField && (
1095
+ <LiteralValueField
1096
+ disabled={!!baseDataTypes?.length}
1097
+ value={value as LiteralValueState}
1098
+ onChangeSet={onChangeSet}
1099
+ onChange={(newValue, changeSet) => {
1100
+ dataType.setEntity(newValue, changeSet);
1101
+
1102
+ changeSet?.add(dataType, ChangeSetEntityChangeType.Updated);
1103
+
1104
+ if (newValue?.type === EntityType.LiteralValue) {
1105
+ dataType.metaSync(
1106
+ {
1107
+ asType: false,
1108
+ like: false,
1109
+ },
1110
+ changeSet,
1111
+ );
1112
+
1113
+ newValue.setParent(dataType, changeSet);
1114
+ }
1115
+
1116
+ onChange(dataType, changeSet);
1117
+ setLocalValue(resolveLocalValueFromExternalValue(newValue));
1118
+
1119
+ setUpdateKey(updateKey + 1);
1120
+ }}
1121
+ />
1122
+ )}
1123
+ </span>
1124
+ );
1125
+ };
1126
+
1127
+ const DataTypeBuilderRow = ({
1128
+ index,
1129
+ dataType: _dataType,
1130
+ parent,
1131
+ parentBaseDataTypes,
1132
+ topParent,
1133
+ topBaseDataTypes,
1134
+ baseDataTypes,
1135
+ onChange,
1136
+ options,
1137
+ project,
1138
+ getOptionDisabled,
1139
+ getOptionTooltip,
1140
+ lists: _lists,
1141
+ getListDisabledTooltip,
1142
+ disallowAsType,
1143
+ getAsTypeDisabledTooltip,
1144
+ disallowLike,
1145
+ getLikeDisabledTooltip,
1146
+ onChangeSet,
1147
+ }: {
1148
+ index: number;
1149
+ onChange: (value: DataTypeState, changeSet: ChangeSet | null) => void;
1150
+ options: DataTypeBuilderOption[];
1151
+ dataType?: DataTypeState;
1152
+ parent: UserManagedDataTypeParentEntityState;
1153
+ parentBaseDataTypes?: DataTypeState[];
1154
+ baseDataTypes?: DataTypeState[];
1155
+ topBaseDataTypes?: DataTypeState[];
1156
+ topParent?: UserManagedDataTypeParentEntityState;
1157
+ project: EditorService;
1158
+ getOptionDisabled?: (
1159
+ option: DataTypeBuilderOption | ILiteralValueOption,
1160
+ ) => boolean;
1161
+ getOptionTooltip?: (
1162
+ option: DataTypeBuilderOption | ILiteralValueOption,
1163
+ ) => React.ReactNode;
1164
+ lists?: AllowedDataTypeListTypes;
1165
+ getListDisabledTooltip?: (dataType: DataTypeState) => React.ReactNode;
1166
+ disallowAsType?: boolean;
1167
+ getAsTypeDisabledTooltip?: (dataType: DataTypeState) => React.ReactNode;
1168
+ disallowLike?: boolean;
1169
+ getLikeDisabledTooltip?: (dataType: DataTypeState) => React.ReactNode;
1170
+ onChangeSet?: () => ChangeSet | null;
1171
+ }) => {
1172
+ const [isMenuOpen, setIsMenuOpen] = React.useState(false);
1173
+
1174
+ const lists = _lists || AllowedDataTypeListTypes.All;
1175
+
1176
+ const isListCheckboxDisabled: boolean =
1177
+ lists === AllowedDataTypeListTypes.None ||
1178
+ (lists === AllowedDataTypeListTypes.Flat &&
1179
+ _dataType?.parent?.type === EntityType.DataType);
1180
+
1181
+ let initChangeSet: ChangeSet | null = null;
1182
+ let dataType: DataTypeState = _dataType;
1183
+
1184
+ if (!dataType) {
1185
+ initChangeSet = onChangeSet?.() || null;
1186
+
1187
+ const newDataTypeTransfer: IDataTypeTransfer =
1188
+ DataTypeState.new(initChangeSet);
1189
+ newDataTypeTransfer.parent = parent.toReference();
1190
+
1191
+ dataType = createStateFromTypeAndSubscribe(
1192
+ newDataTypeTransfer,
1193
+ project.logic,
1194
+ ) as DataTypeState;
1195
+
1196
+ dataType.hydrateAncestors();
1197
+ dataType.addSelfToProject(initChangeSet);
1198
+ initChangeSet?.add(dataType, ChangeSetEntityChangeType.Added);
1199
+ dataType.initChildren(initChangeSet);
1200
+ }
1201
+
1202
+ if (dataType && dataType.isList && isListCheckboxDisabled) {
1203
+ if (!initChangeSet) {
1204
+ initChangeSet = onChangeSet?.() || null;
1205
+ }
1206
+
1207
+ dataType.metaSync(
1208
+ {
1209
+ isList: false,
1210
+ },
1211
+ initChangeSet,
1212
+ );
1213
+ }
1214
+
1215
+ if (!!initChangeSet) {
1216
+ onChange(dataType, initChangeSet);
1217
+ }
1218
+
1219
+ const canDelete = true; // ((): boolean => {
1220
+ // if (!dataType || !dataType.isResolved) {
1221
+ // return true;
1222
+ // }
1223
+
1224
+ // if (!baseDataTypes || baseDataTypes.length === 0) {
1225
+ // return true;
1226
+ // }
1227
+
1228
+ // const parentDataType = parentBaseDataTypes[0];
1229
+
1230
+ // if (
1231
+ // dataType.parent?.type === EntityType.DataType &&
1232
+ // !!dataType.parent.implementationChooseOne &&
1233
+ // !!dataType.parent.orChildrenGroup?.length &&
1234
+ // dataType.parent.orChildrenGroup.length > 1 &&
1235
+ // !!dataType.parent.orChildrenGroup.find((dt) => dt.id === dataType.id)
1236
+ // ) {
1237
+ // return true;
1238
+ // }
1239
+
1240
+ // return false;
1241
+ // })();
1242
+
1243
+ return (
1244
+ <>
1245
+ <div
1246
+ style={{
1247
+ display: 'flex',
1248
+ gap: 12,
1249
+ alignItems: 'center',
1250
+ width: 'max-content',
1251
+ }}
1252
+ >
1253
+ {/* node like box */}
1254
+ <span
1255
+ style={{
1256
+ display: 'flex',
1257
+ flexDirection: 'column',
1258
+ }}
1259
+ >
1260
+ {/* vertical centered line */}
1261
+ {index === 0 ? (
1262
+ // No line, but a placeholder block
1263
+ <div
1264
+ style={{
1265
+ width: 1,
1266
+ height: 15.5,
1267
+ backgroundColor: 'transparent',
1268
+ marginLeft: 5,
1269
+ }}
1270
+ />
1271
+ ) : (
1272
+ <div
1273
+ style={{
1274
+ width: 1,
1275
+ height: 15.5,
1276
+ backgroundColor: 'rgba(0,0,0,0.54)',
1277
+ marginLeft: 5,
1278
+ }}
1279
+ />
1280
+ )}
1281
+
1282
+ <span
1283
+ style={{
1284
+ display: 'flex',
1285
+ alignItems: 'center',
1286
+ }}
1287
+ >
1288
+ {!!dataType?.parentRelationType && (
1289
+ <span
1290
+ id='data-type-builder__row__horizontal-line-before-node'
1291
+ style={{
1292
+ width: 2,
1293
+ height: 1,
1294
+ backgroundColor: 'rgba(0,0,0,0.54)',
1295
+ }}
1296
+ />
1297
+ )}
1298
+ <div
1299
+ style={{
1300
+ width: 7,
1301
+ height: 7,
1302
+ borderRadius: 1,
1303
+ backgroundColor: 'rgba(0,0,0,0.54)',
1304
+ marginLeft: !!dataType?.parentRelationType ? 0 : 2,
1305
+ }}
1306
+ />
1307
+ </span>
1308
+
1309
+ {/* vertical centered line */}
1310
+ {dataType?.isResolved ? (
1311
+ <div
1312
+ style={{
1313
+ width: 1,
1314
+ height: 16.5,
1315
+ backgroundColor: 'rgba(0,0,0,0.54)',
1316
+ marginLeft: 5,
1317
+ }}
1318
+ />
1319
+ ) : (
1320
+ <div
1321
+ style={{
1322
+ width: 1,
1323
+ height: 16.5,
1324
+ backgroundColor: 'transparent',
1325
+ marginLeft: 5,
1326
+ }}
1327
+ />
1328
+ )}
1329
+ </span>
1330
+
1331
+ <div
1332
+ style={{
1333
+ display: 'flex',
1334
+ gap: 12,
1335
+ alignItems: 'center',
1336
+ }}
1337
+ >
1338
+ <DataTypeValueSelector
1339
+ dataType={dataType}
1340
+ baseDataTypes={baseDataTypes}
1341
+ value={dataType?.entity || dataType?.foreignKeyRef}
1342
+ parentBaseDataTypes={parentBaseDataTypes}
1343
+ topBaseDataTypes={topBaseDataTypes}
1344
+ topParent={topParent}
1345
+ project={project}
1346
+ onChangeSet={onChangeSet}
1347
+ onChange={(_, changeSet) => {
1348
+ onChange(dataType, changeSet);
1349
+ }}
1350
+ options={options}
1351
+ getOptionDisabled={getOptionDisabled}
1352
+ getOptionTooltip={getOptionTooltip}
1353
+ />
1354
+
1355
+ <MuiTooltip
1356
+ title={
1357
+ !!baseDataTypes?.length
1358
+ ? 'Current data-type must match the base implementation'
1359
+ : isListCheckboxDisabled
1360
+ ? getListDisabledTooltip?.(dataType)
1361
+ : ''
1362
+ }
1363
+ placement='bottom'
1364
+ enterDelay={isListCheckboxDisabled ? 100 : 400}
1365
+ leaveDelay={200}
1366
+ >
1367
+ <FormGroup>
1368
+ <FormControlLabel
1369
+ control={
1370
+ <Checkbox
1371
+ disabled={!!baseDataTypes?.length || isListCheckboxDisabled}
1372
+ className='data-type-builder--checkbox'
1373
+ checked={dataType?.isList as boolean}
1374
+ onChange={(e) => {
1375
+ const changeSet = onChangeSet?.() || null;
1376
+
1377
+ dataType.metaSync(
1378
+ {
1379
+ isList: e.target.checked,
1380
+ },
1381
+ changeSet,
1382
+ );
1383
+
1384
+ onChange(dataType, changeSet);
1385
+ }}
1386
+ />
1387
+ }
1388
+ label={dataType?.isList ? 'List value' : 'Individual value'}
1389
+ />
1390
+ </FormGroup>
1391
+ </MuiTooltip>
1392
+
1393
+ <MuiTooltip
1394
+ title={
1395
+ !!baseDataTypes?.length
1396
+ ? 'Current data-type must match the base implementation'
1397
+ : disallowAsType
1398
+ ? getAsTypeDisabledTooltip?.(dataType)
1399
+ : ''
1400
+ }
1401
+ placement='bottom'
1402
+ enterDelay={disallowAsType ? 100 : 400}
1403
+ leaveDelay={200}
1404
+ >
1405
+ <FormGroup>
1406
+ <FormControlLabel
1407
+ control={
1408
+ <Checkbox
1409
+ disabled={!!baseDataTypes?.length || disallowAsType}
1410
+ className='data-type-builder--checkbox'
1411
+ checked={dataType?.asType as boolean}
1412
+ onChange={(e) => {
1413
+ const changeSet = onChangeSet?.() || null;
1414
+
1415
+ dataType.metaSync(
1416
+ {
1417
+ asType: e.target.checked,
1418
+ },
1419
+ changeSet,
1420
+ );
1421
+
1422
+ onChange(dataType, changeSet);
1423
+ }}
1424
+ />
1425
+ }
1426
+ label={
1427
+ dataType?.asType ? 'As template type' : 'As instance value'
1428
+ }
1429
+ />
1430
+ </FormGroup>
1431
+ </MuiTooltip>
1432
+
1433
+ <MuiTooltip
1434
+ title={
1435
+ !!baseDataTypes?.length
1436
+ ? 'Current data-type must match the base implementation'
1437
+ : getLikeDisabledTooltip?.(dataType)
1438
+ }
1439
+ placement='bottom'
1440
+ enterDelay={disallowLike ? 100 : 400}
1441
+ leaveDelay={200}
1442
+ >
1443
+ <FormGroup>
1444
+ <FormControlLabel
1445
+ control={
1446
+ <Checkbox
1447
+ disabled={!!baseDataTypes?.length || disallowLike}
1448
+ className='data-type-builder--checkbox'
1449
+ checked={dataType?.like as boolean}
1450
+ onChange={(e) => {
1451
+ const changeSet = onChangeSet?.() || null;
1452
+
1453
+ dataType.metaSync(
1454
+ {
1455
+ like: e.target.checked,
1456
+ },
1457
+ changeSet,
1458
+ );
1459
+
1460
+ onChange(dataType, changeSet);
1461
+ }}
1462
+ />
1463
+ }
1464
+ label={
1465
+ dataType?.like
1466
+ ? 'Allow equivalent type'
1467
+ : 'Exact entity match'
1468
+ }
1469
+ />
1470
+ </FormGroup>
1471
+ </MuiTooltip>
1472
+
1473
+ <IconButton
1474
+ id={'data-type-builder--' + dataType?.id + '--menu-button'}
1475
+ disabled={!canDelete}
1476
+ size='small'
1477
+ style={{
1478
+ width: 22,
1479
+ height: 22,
1480
+ }}
1481
+ onClick={() => {
1482
+ setIsMenuOpen(!isMenuOpen);
1483
+ }}
1484
+ >
1485
+ <i className='fas fa-ellipsis-v' />
1486
+ </IconButton>
1487
+
1488
+ {/* Warning error icon */}
1489
+ {!dataType?.isResolved && (
1490
+ <>
1491
+ <img
1492
+ className='search-statement__error-icon'
1493
+ id={`data-type-builder--${dataType?.id}--error-icon`}
1494
+ src={WarningIcon}
1495
+ />
1496
+ <Tooltip
1497
+ anchorQuerySelector={`#data-type-builder--${dataType?.id}--error-icon`}
1498
+ placement='bottom'
1499
+ openDelay={300}
1500
+ >
1501
+ This data type is not fully resolved.
1502
+ <br />
1503
+ Please make sure to select a value for the entity field
1504
+ </Tooltip>
1505
+ </>
1506
+ )}
1507
+ </div>
1508
+ </div>
1509
+
1510
+ <DropdownMenuPopup
1511
+ popupOptions={{
1512
+ anchorQuerySelector: `#data-type-builder--${dataType?.id}--menu-button`,
1513
+ placement: 'right',
1514
+ open: isMenuOpen,
1515
+ }}
1516
+ options={[
1517
+ {
1518
+ onClick: async () => {
1519
+ const changeSet = onChangeSet?.() || null;
1520
+
1521
+ // If the is the last child of the parent, then delete the parent
1522
+ // If this is the parent only has 2 children, then transfer the content
1523
+ // of the remaining child to the parent so it isn't a group but a single entity then
1524
+ // delete the remaining child as well
1525
+ if (
1526
+ [
1527
+ ...((dataType.parent as DataTypeState).andChildrenGroup ||
1528
+ []),
1529
+ ...((dataType.parent as DataTypeState).orChildrenGroup || []),
1530
+ ].length === 2
1531
+ ) {
1532
+ const parent = dataType.parent as DataTypeState;
1533
+
1534
+ dataType.remove({ ignoreUpstream: false }, changeSet);
1535
+
1536
+ const remainingChild = [
1537
+ ...(parent.andChildrenGroup || []),
1538
+ ...(parent.orChildrenGroup || []),
1539
+ ][0];
1540
+
1541
+ parent.setEntity(remainingChild.entity, changeSet);
1542
+
1543
+ // Check if the entity's parent is the og data type and set the parent to the new parent
1544
+ if (
1545
+ !!remainingChild.entity &&
1546
+ (remainingChild.entity as DefinitionEntityState).parent
1547
+ ?.id === dataType.id
1548
+ ) {
1549
+ (remainingChild.entity as DefinitionEntityState).setParent(
1550
+ parent,
1551
+ changeSet,
1552
+ );
1553
+
1554
+ changeSet.add(
1555
+ remainingChild.entity as UserManagedEntityState,
1556
+ ChangeSetEntityChangeType.Updated,
1557
+ );
1558
+ }
1559
+
1560
+ parent.metaSync(
1561
+ {
1562
+ asType: remainingChild.asType,
1563
+ like: remainingChild.like,
1564
+ isList: remainingChild.isList,
1565
+ },
1566
+ changeSet,
1567
+ );
1568
+
1569
+ parent.andChildrenGroup = remainingChild.andChildrenGroup;
1570
+ parent.orChildrenGroup = remainingChild.orChildrenGroup;
1571
+
1572
+ changeSet.add(parent, ChangeSetEntityChangeType.Updated);
1573
+
1574
+ remainingChild.remove({ ignoreUpstream: false }, changeSet);
1575
+
1576
+ if (isListCheckboxDisabled && !!parent) {
1577
+ parent.metaSync(
1578
+ {
1579
+ isList: false,
1580
+ },
1581
+ changeSet,
1582
+ );
1583
+ }
1584
+
1585
+ onChange(null, changeSet);
1586
+ } else if (
1587
+ [
1588
+ ...((dataType.parent as DataTypeState).andChildrenGroup ||
1589
+ []),
1590
+ ...((dataType.parent as DataTypeState).orChildrenGroup || []),
1591
+ ].length === 1
1592
+ ) {
1593
+ const parent = dataType.parent as DataTypeState;
1594
+
1595
+ parent.remove({ ignoreUpstream: false }, changeSet);
1596
+
1597
+ onChange(null, changeSet);
1598
+ } else {
1599
+ dataType.remove({ ignoreUpstream: false }, changeSet);
1600
+
1601
+ onChange(null, changeSet);
1602
+ }
1603
+ },
1604
+ disabled: !canDelete,
1605
+ label: 'Delete',
1606
+ color: 'error',
1607
+ iconEnd: 'fa-solid fa-trash-can',
1608
+ tooltip: !canDelete
1609
+ ? 'Current data-type must match the base implementation'
1610
+ : 'Click to delete this part of the statement',
1611
+ // tooltip: 'Click to delete this part of the statement',
1612
+ },
1613
+ {
1614
+ onClick: async () => {
1615
+ const changeSet = onChangeSet?.() || null;
1616
+
1617
+ dataType.afterAllChildrenInitialized(changeSet);
1618
+
1619
+ await project.renderAndCloseChangeSet(changeSet);
1620
+
1621
+ // For now, to achieve a refresh of the data-type builder
1622
+ setIsMenuOpen(false);
1623
+ },
1624
+ label: 'Recalculate',
1625
+ color: 'warning',
1626
+ iconEnd: 'fa-solid fa-bug',
1627
+ tooltip: 'Recalculate the state of this data-type entry',
1628
+ },
1629
+ ...(dataType?.entity?.type === EntityType.DefinitionEntity &&
1630
+ dataType?.entity?.parent?.id === dataType.id
1631
+ ? [
1632
+ {
1633
+ onClick: async () => {
1634
+ if (
1635
+ dataType?.entity?.type !== EntityType.DefinitionEntity ||
1636
+ dataType?.entity?.parent?.id !== dataType.id
1637
+ ) {
1638
+ return;
1639
+ }
1640
+
1641
+ const changeSet = onChangeSet?.() || null;
1642
+
1643
+ dataType?.entity.setParent(project.logic, changeSet);
1644
+
1645
+ changeSet?.add(
1646
+ dataType?.entity as UserManagedEntityState,
1647
+ ChangeSetEntityChangeType.Updated,
1648
+ );
1649
+
1650
+ const currentCanvasParent = getParentCanvasEntity(dataType);
1651
+
1652
+ if (!currentCanvasParent) {
1653
+ popupNotification({
1654
+ color: 'error',
1655
+ text: 'Cannot add definition to canvas: no parent canvas found',
1656
+ });
1657
+ return;
1658
+ }
1659
+
1660
+ const newX = currentCanvasParent.x;
1661
+ const newY =
1662
+ currentCanvasParent.y -
1663
+ calculateCardSize(dataType?.entity).height -
1664
+ CANVAS_VERTICAL_BUFFER_BETWEEN_CARDS;
1665
+
1666
+ // const validationResult =
1667
+ // definitionEntityValidation.validateDefinitionEntityName(
1668
+ // dataType?.entity,
1669
+ // 'Definition',
1670
+ // );
1671
+
1672
+ const name = findNextAvailableName(
1673
+ 'Definition',
1674
+ project.logic.entities,
1675
+ );
1676
+
1677
+ // if (!validationResult.length) {
1678
+ // debouncedOnChangeName(e.target.value);
1679
+ // }
1680
+
1681
+ // setEntityNameErrors(validationResult);
1682
+
1683
+ dataType?.entity.metaSync(
1684
+ {
1685
+ x: newX,
1686
+ y: newY,
1687
+ name: name,
1688
+ },
1689
+ changeSet,
1690
+ );
1691
+
1692
+ await project.renderAndCloseChangeSet(changeSet);
1693
+
1694
+ // Navigate to canvas and scroll to the new definition
1695
+ EditorService.navigate(project.editorBasePath);
1696
+
1697
+ const objectId = getCanvasEntityDraggableContainerDOMId(
1698
+ dataType?.entity,
1699
+ );
1700
+
1701
+ project.canvas?.scrollToObjectById(objectId);
1702
+
1703
+ // For now, to achieve a refresh of the data-type builder
1704
+ setIsMenuOpen(false);
1705
+ },
1706
+ label: 'Add definition to canvas',
1707
+ iconEnd: 'fa-solid fa-plus',
1708
+ tooltip:
1709
+ 'The current definition is inlined. Click to add it to the canvas',
1710
+ },
1711
+ ]
1712
+ : []),
1713
+ ]}
1714
+ />
1715
+ </>
1716
+ );
1717
+ };
1718
+
1719
+ const DataTypeBuilderGroup = ({
1720
+ dataType,
1721
+ parent,
1722
+ baseDataTypes,
1723
+ parentBaseDataTypes,
1724
+ topBaseDataTypes,
1725
+ topParent,
1726
+ project,
1727
+ onChange,
1728
+ options,
1729
+ getOptionDisabled,
1730
+ getOptionTooltip,
1731
+ lists,
1732
+ getListDisabledTooltip,
1733
+ disallowAsType,
1734
+ getAsTypeDisabledTooltip,
1735
+ disallowLike,
1736
+ getLikeDisabledTooltip,
1737
+ onChangeSet,
1738
+ }: {
1739
+ dataType?: DataTypeState;
1740
+ parent: UserManagedDataTypeParentEntityState;
1741
+ parentBaseDataTypes?: DataTypeState[];
1742
+ baseDataTypes?: DataTypeState[];
1743
+ topBaseDataTypes?: DataTypeState[];
1744
+ topParent?: UserManagedDataTypeParentEntityState;
1745
+ project: EditorService;
1746
+ onChange: (value: DataTypeState, changeSet: ChangeSet | null) => void;
1747
+ options: DataTypeBuilderOption[];
1748
+ getOptionDisabled?: (
1749
+ option: DataTypeBuilderOption | ILiteralValueOption,
1750
+ ) => boolean;
1751
+ getOptionTooltip?: (
1752
+ option: DataTypeBuilderOption | ILiteralValueOption,
1753
+ ) => React.ReactNode;
1754
+ lists?: AllowedDataTypeListTypes;
1755
+ getListDisabledTooltip?: (dataType: DataTypeState) => React.ReactNode;
1756
+ disallowAsType?: boolean;
1757
+ getAsTypeDisabledTooltip?: (dataType: DataTypeState) => React.ReactNode;
1758
+ disallowLike?: boolean;
1759
+ getLikeDisabledTooltip?: (dataType: DataTypeState) => React.ReactNode;
1760
+ onChangeSet?: () => ChangeSet | null;
1761
+ }) => {
1762
+ const nestedDataTypeGroups: {
1763
+ operator: 'and' | 'or';
1764
+ dataType: DataTypeState;
1765
+ baseDataTypes?: DataTypeState[];
1766
+ }[] = (() => {
1767
+ if (!dataType) {
1768
+ return [];
1769
+ }
1770
+
1771
+ if (!!(baseDataTypes || []).some((dt) => dt.implementationChooseOne)) {
1772
+ return [];
1773
+ }
1774
+
1775
+ return [
1776
+ ...(dataType.andChildrenGroup || []).map((c, i) => ({
1777
+ operator: 'and' as 'and' | 'or',
1778
+ dataType: c,
1779
+ baseDataTypes:
1780
+ (baseDataTypes || []).flatMap((dt) => dt.andChildrenGroup || []) ||
1781
+ [],
1782
+ })),
1783
+ ...(dataType.orChildrenGroup || []).map((c, i) => ({
1784
+ operator: 'or' as 'and' | 'or',
1785
+ dataType: c,
1786
+ baseDataTypes:
1787
+ (baseDataTypes || []).flatMap((dt) => dt.orChildrenGroup || []) || [],
1788
+ })),
1789
+ ];
1790
+ })();
1791
+
1792
+ const canAddANDAfterSelf: boolean =
1793
+ dataType?.parentRelationType ===
1794
+ DataTypeParentChildRelation.AndDataTypeGroup ||
1795
+ !!(
1796
+ dataType?.parent?.type === EntityType.DataType &&
1797
+ (!(dataType?.parent as DataTypeState)?.andChildrenGroup ||
1798
+ !((dataType?.parent as DataTypeState)?.andChildrenGroup || []).length)
1799
+ ) ||
1800
+ dataType?.parent?.type !== EntityType.DataType;
1801
+
1802
+ const isListCheckboxDisabled: boolean =
1803
+ !!baseDataTypes?.length ||
1804
+ lists === AllowedDataTypeListTypes.None ||
1805
+ (lists === AllowedDataTypeListTypes.Flat &&
1806
+ dataType?.parent?.type === EntityType.DataType);
1807
+
1808
+ if (dataType && dataType.isList && isListCheckboxDisabled) {
1809
+ const changeSet = onChangeSet?.() || null;
1810
+
1811
+ dataType.metaSync(
1812
+ {
1813
+ isList: false,
1814
+ },
1815
+ changeSet,
1816
+ );
1817
+
1818
+ onChange(dataType, changeSet);
1819
+ }
1820
+
1821
+ const currentIsNullable: boolean = checkIsNullable(dataType);
1822
+
1823
+ const canAddNewItemToGroup: boolean = (() => {
1824
+ let baseTypesNotFullfilled: boolean = false;
1825
+
1826
+ (baseDataTypes || []).forEach((baseDataType) => {
1827
+ const baseIsNullable = checkIsNullable(baseDataType);
1828
+
1829
+ if (baseIsNullable && !currentIsNullable) {
1830
+ baseTypesNotFullfilled = true;
1831
+ }
1832
+ });
1833
+
1834
+ if (baseTypesNotFullfilled) {
1835
+ return true;
1836
+ }
1837
+
1838
+ // if (!!baseDataTypes?.length) {
1839
+ // return false;
1840
+ // }
1841
+
1842
+ return true;
1843
+ })();
1844
+
1845
+ const canAddNewAndItemToGroup: boolean = (() => {
1846
+ // The goal is to avoid a "never true" situation
1847
+ // If the current 'entity' or items in the group are primitive types,
1848
+ // we can't add a new AND item
1849
+ if (!dataType) {
1850
+ return true;
1851
+ }
1852
+
1853
+ const allEntities: (DataTypeStateEntityOption | null)[] = [
1854
+ dataType.entity,
1855
+ ...(dataType.andChildrenGroup || []).map((dt) => dt.entity),
1856
+ ...(dataType.orChildrenGroup || []).map((dt) => dt.entity),
1857
+ ];
1858
+
1859
+ const hasPrimitiveType = allEntities.some((entity) => {
1860
+ if (!entity) {
1861
+ return false;
1862
+ }
1863
+
1864
+ if (
1865
+ entity.type === EntityType.PrimitiveEntity ||
1866
+ entity.type === EntityType.LiteralValue
1867
+ ) {
1868
+ return true;
1869
+ }
1870
+
1871
+ return false;
1872
+ });
1873
+
1874
+ return !hasPrimitiveType;
1875
+ })();
1876
+
1877
+ const isRootLevel =
1878
+ !dataType?.parent || dataType?.parent?.type !== EntityType.DataType;
1879
+
1880
+ return (
1881
+ <div
1882
+ style={{
1883
+ display: 'flex',
1884
+ flexDirection: 'column',
1885
+ width: 'max-content',
1886
+ }}
1887
+ >
1888
+ {((!!dataType &&
1889
+ !(dataType.andChildrenGroup || []).length &&
1890
+ !(dataType.orChildrenGroup || []).length) ||
1891
+ (baseDataTypes || []).some((dt) => dt.implementationChooseOne)) && (
1892
+ <>
1893
+ <DataTypeBuilderRow
1894
+ options={options}
1895
+ index={0}
1896
+ dataType={dataType}
1897
+ parent={parent}
1898
+ parentBaseDataTypes={parentBaseDataTypes}
1899
+ baseDataTypes={baseDataTypes}
1900
+ topBaseDataTypes={topBaseDataTypes}
1901
+ topParent={topParent}
1902
+ project={project}
1903
+ onChangeSet={onChangeSet}
1904
+ onChange={(updatedDataType, changeSet) => {
1905
+ if (isListCheckboxDisabled && !!updatedDataType) {
1906
+ updatedDataType.metaSync(
1907
+ {
1908
+ isList: false,
1909
+ },
1910
+ changeSet,
1911
+ );
1912
+ }
1913
+
1914
+ onChange(updatedDataType, changeSet);
1915
+ }}
1916
+ getOptionDisabled={getOptionDisabled}
1917
+ getOptionTooltip={getOptionTooltip}
1918
+ lists={lists}
1919
+ getListDisabledTooltip={getListDisabledTooltip}
1920
+ disallowAsType={disallowAsType}
1921
+ getAsTypeDisabledTooltip={getAsTypeDisabledTooltip}
1922
+ disallowLike={disallowLike}
1923
+ getLikeDisabledTooltip={getLikeDisabledTooltip}
1924
+ />
1925
+
1926
+ {dataType?.isResolved && (
1927
+ <>
1928
+ {/* vertical centered line */}
1929
+ {!!dataType?.parentRelationType && (
1930
+ <div
1931
+ id='data-type-builder__vertical-line-after-root-data-type'
1932
+ style={{
1933
+ width: 1,
1934
+ height: 4,
1935
+ backgroundColor: 'rgba(0,0,0,0.54)',
1936
+ marginLeft: 5,
1937
+ }}
1938
+ />
1939
+ )}
1940
+
1941
+ <span
1942
+ className='data-type-builder__add-data-type-between__container'
1943
+ style={{
1944
+ display: 'flex',
1945
+ gap: 6,
1946
+ alignItems: 'center',
1947
+ }}
1948
+ >
1949
+ <button
1950
+ id={`data-type-builder--${dataType?.id}--add-first-nested-data-type`}
1951
+ className='data-type-builder__add-data-type-between__button'
1952
+ disabled={!canAddNewItemToGroup}
1953
+ style={{
1954
+ width: 11,
1955
+ height: 11,
1956
+ }}
1957
+ >
1958
+ <i className='fas fa-plus' />
1959
+ </button>
1960
+
1961
+ <hr
1962
+ className='data-type-builder__add-data-type-between__line'
1963
+ style={{
1964
+ width: 630,
1965
+ backgroundColor: 'var(--color-main-primary)',
1966
+ color: 'var(--color-main-primary)',
1967
+ borderTop: '2px solid var(--color-main-primary)',
1968
+ maxWidth: '100%',
1969
+ margin: 0,
1970
+ }}
1971
+ />
1972
+ </span>
1973
+
1974
+ <DropdownMenuPopup
1975
+ popupOptions={{
1976
+ anchorQuerySelector: `#data-type-builder--${dataType?.id}--add-first-nested-data-type`,
1977
+ placement: 'bottom',
1978
+ }}
1979
+ options={[
1980
+ {
1981
+ onClick: async () => {
1982
+ const changeSet = onChangeSet?.() || null;
1983
+
1984
+ const newSiblingDataTypeTransfer: IDataTypeTransfer =
1985
+ DataTypeState.new(changeSet);
1986
+ newSiblingDataTypeTransfer.parent =
1987
+ dataType.toReference();
1988
+ newSiblingDataTypeTransfer.entity = (
1989
+ project.logic.getBuiltIn(
1990
+ BUILT_IN_BASE_ENTITY_IDS['primitive-entity'].untyped
1991
+ .id,
1992
+ ) as PrimitiveEntityState
1993
+ )?.toJSON() as IPrimitiveEntityTransfer;
1994
+
1995
+ const newSiblingDataType =
1996
+ createStateFromTypeAndSubscribe(
1997
+ newSiblingDataTypeTransfer,
1998
+ project.logic,
1999
+ ) as DataTypeState;
2000
+
2001
+ newSiblingDataType.hydrateAncestors();
2002
+ newSiblingDataType.setParent(dataType, changeSet);
2003
+
2004
+ changeSet?.add(
2005
+ newSiblingDataType,
2006
+ ChangeSetEntityChangeType.Added,
2007
+ );
2008
+
2009
+ newSiblingDataType.initChildren(changeSet);
2010
+
2011
+ if (isListCheckboxDisabled && !!dataType) {
2012
+ dataType.metaSync(
2013
+ {
2014
+ isList: false,
2015
+ },
2016
+ changeSet,
2017
+ );
2018
+ }
2019
+
2020
+ const existingEntity = dataType.entity;
2021
+
2022
+ dataType.setEntity(null, changeSet);
2023
+
2024
+ const oldSelfClone = dataType.clone(changeSet);
2025
+
2026
+ oldSelfClone.setParent(dataType, changeSet);
2027
+ oldSelfClone.setEntity(existingEntity, changeSet);
2028
+
2029
+ if (
2030
+ !!existingEntity &&
2031
+ (existingEntity as DefinitionEntityState).parent?.id ===
2032
+ dataType.id
2033
+ ) {
2034
+ (existingEntity as DefinitionEntityState).setParent(
2035
+ oldSelfClone,
2036
+ changeSet,
2037
+ );
2038
+
2039
+ changeSet?.add(
2040
+ existingEntity as UserManagedEntityState,
2041
+ ChangeSetEntityChangeType.Updated,
2042
+ );
2043
+ }
2044
+
2045
+ oldSelfClone.metaSync(
2046
+ {
2047
+ parentRelationType:
2048
+ DataTypeParentChildRelation.AndDataTypeGroup,
2049
+ },
2050
+ changeSet,
2051
+ );
2052
+ newSiblingDataType.metaSync(
2053
+ {
2054
+ parentRelationType:
2055
+ DataTypeParentChildRelation.AndDataTypeGroup,
2056
+ },
2057
+ changeSet,
2058
+ );
2059
+
2060
+ dataType.andChildrenGroup = [
2061
+ ...(dataType.andChildrenGroup || []),
2062
+ oldSelfClone,
2063
+ newSiblingDataType,
2064
+ ];
2065
+
2066
+ // Ideally, only if there were actual changes we should manually set the entity to the change set as updated
2067
+ changeSet?.add(
2068
+ dataType,
2069
+ ChangeSetEntityChangeType.Updated,
2070
+ );
2071
+
2072
+ dataType.metaSync(
2073
+ {
2074
+ entity: null,
2075
+ asType: false,
2076
+ like: false,
2077
+ },
2078
+ changeSet,
2079
+ );
2080
+
2081
+ onChange?.(dataType, changeSet);
2082
+ },
2083
+ label: `Add 'AND' data type`,
2084
+ color: 'primary',
2085
+ iconEnd: 'fa-solid fa-plus',
2086
+ tooltip: !canAddNewItemToGroup
2087
+ ? 'Current data-type must match the base implementation'
2088
+ : canAddANDAfterSelf
2089
+ ? canAddNewAndItemToGroup
2090
+ ? 'Click to add'
2091
+ : 'Cannot add new "AND" item when primitive types are present'
2092
+ : 'Group the "AND" statements together',
2093
+ disabled:
2094
+ !canAddNewItemToGroup ||
2095
+ !canAddANDAfterSelf ||
2096
+ !canAddNewAndItemToGroup,
2097
+ },
2098
+ {
2099
+ onClick: async () => {
2100
+ const changeSet = onChangeSet?.() || null;
2101
+
2102
+ if (isListCheckboxDisabled && !!dataType) {
2103
+ dataType.metaSync(
2104
+ {
2105
+ isList: false,
2106
+ },
2107
+ changeSet,
2108
+ );
2109
+ }
2110
+
2111
+ const existingEntity = dataType.entity;
2112
+
2113
+ let autoResolvedNextEntity: DataTypeStateEntityOption;
2114
+
2115
+ const sameLevelSiblings = [];
2116
+
2117
+ if (parent.type === EntityType.DataType) {
2118
+ sameLevelSiblings.push(
2119
+ ...(parent.andChildrenGroup || []),
2120
+ ...(parent.orChildrenGroup || []),
2121
+ );
2122
+ }
2123
+
2124
+ if (baseDataTypes && baseDataTypes.length === 1) {
2125
+ const baseIsNullable = checkIsNullable(
2126
+ baseDataTypes[0],
2127
+ );
2128
+ const selectedNonNullableBaseDataType =
2129
+ recursivelySelectDataTypeOption(
2130
+ baseDataTypes[0],
2131
+ sameLevelSiblings,
2132
+ )?.selectedDataType;
2133
+
2134
+ if (
2135
+ selectedNonNullableBaseDataType?.entity?.id !==
2136
+ existingEntity?.id
2137
+ ) {
2138
+ autoResolvedNextEntity =
2139
+ selectedNonNullableBaseDataType?.entity;
2140
+ } else if (
2141
+ baseIsNullable &&
2142
+ selectedNonNullableBaseDataType?.entity?.id !==
2143
+ existingEntity?.id
2144
+ ) {
2145
+ autoResolvedNextEntity = project.logic.getBuiltIn(
2146
+ BUILT_IN_BASE_ENTITY_IDS['primitive-entity'].null
2147
+ .id,
2148
+ ) as PrimitiveEntityState;
2149
+ } else {
2150
+ autoResolvedNextEntity = baseDataTypes[0].entity;
2151
+ }
2152
+ } else if (baseDataTypes && baseDataTypes.length > 1) {
2153
+ const filteredBaseDataTypes = (
2154
+ baseDataTypes || []
2155
+ ).filter((dt) => dt.entity?.id !== existingEntity?.id);
2156
+
2157
+ if (filteredBaseDataTypes.length > 0) {
2158
+ autoResolvedNextEntity =
2159
+ filteredBaseDataTypes[0].entity;
2160
+ }
2161
+ } else if (!baseDataTypes || baseDataTypes.length === 0) {
2162
+ const existingPrimitiveNames: PrimitiveTypes[] = [];
2163
+
2164
+ if (parent.type === EntityType.DataType) {
2165
+ sameLevelSiblings.forEach((dt) => {
2166
+ if (
2167
+ dt.entity?.type === EntityType.PrimitiveEntity ||
2168
+ dt.entity?.type === EntityType.LiteralValue
2169
+ ) {
2170
+ existingPrimitiveNames.push(
2171
+ (dt.entity as PrimitiveEntityState)
2172
+ .name as PrimitiveTypes,
2173
+ );
2174
+ }
2175
+ });
2176
+ } else if (
2177
+ parent.type !== EntityType.DefinitionEntity
2178
+ ) {
2179
+ const parentDT = parent.getDataType(null);
2180
+
2181
+ if (
2182
+ parentDT?.entity?.type ===
2183
+ EntityType.PrimitiveEntity ||
2184
+ parentDT?.entity?.type === EntityType.LiteralValue
2185
+ ) {
2186
+ existingPrimitiveNames.push(
2187
+ (parentDT?.entity as PrimitiveEntityState)
2188
+ .name as PrimitiveTypes,
2189
+ );
2190
+ }
2191
+ }
2192
+
2193
+ const availablePrimitiveNames = Object.values(
2194
+ PrimitiveTypes,
2195
+ ).filter(
2196
+ (pn) =>
2197
+ ![
2198
+ ...existingPrimitiveNames,
2199
+ PrimitiveTypes.ActionDescriptor,
2200
+ PrimitiveTypes.EntityTemplate,
2201
+ ].includes(pn),
2202
+ );
2203
+ const builtInId =
2204
+ BUILT_IN_BASE_ENTITY_IDS['primitive-entity'][
2205
+ (availablePrimitiveNames[0] as PrimitiveTypes.Boolean) ||
2206
+ PrimitiveTypes.Boolean
2207
+ ]?.id;
2208
+
2209
+ if (!!availablePrimitiveNames && !!builtInId) {
2210
+ autoResolvedNextEntity = project.logic.getBuiltIn(
2211
+ builtInId,
2212
+ ) as PrimitiveEntityState;
2213
+ }
2214
+ }
2215
+
2216
+ if (!autoResolvedNextEntity) {
2217
+ autoResolvedNextEntity = project.logic.getBuiltIn(
2218
+ BUILT_IN_BASE_ENTITY_IDS['primitive-entity'].untyped
2219
+ .id,
2220
+ ) as PrimitiveEntityState;
2221
+ }
2222
+
2223
+ const newSiblingDataTypeTransfer: IDataTypeTransfer =
2224
+ DataTypeState.new(changeSet);
2225
+ newSiblingDataTypeTransfer.parentRelationType =
2226
+ DataTypeParentChildRelation.OrDataTypeGroup;
2227
+ newSiblingDataTypeTransfer.parent =
2228
+ dataType.toReference();
2229
+ newSiblingDataTypeTransfer.entity =
2230
+ autoResolvedNextEntity?.toJSON() as IPrimitiveEntityTransfer;
2231
+
2232
+ const newSiblingDataType =
2233
+ createStateFromTypeAndSubscribe(
2234
+ newSiblingDataTypeTransfer,
2235
+ project.logic,
2236
+ ) as DataTypeState;
2237
+
2238
+ newSiblingDataType.hydrateAncestors();
2239
+
2240
+ changeSet?.add(
2241
+ newSiblingDataType,
2242
+ ChangeSetEntityChangeType.Added,
2243
+ );
2244
+ newSiblingDataType.setParent(dataType, changeSet);
2245
+
2246
+ newSiblingDataType.initChildren(changeSet);
2247
+
2248
+ const oldSelfCloneTransfer: IDataTypeTransfer =
2249
+ DataTypeState.new(changeSet);
2250
+ oldSelfCloneTransfer.parentRelationType =
2251
+ DataTypeParentChildRelation.OrDataTypeGroup;
2252
+ oldSelfCloneTransfer.parent = dataType.toReference();
2253
+
2254
+ const oldSelfClone = createStateFromTypeAndSubscribe(
2255
+ oldSelfCloneTransfer,
2256
+ project.logic,
2257
+ ) as DataTypeState;
2258
+
2259
+ oldSelfClone.hydrateAncestors();
2260
+
2261
+ changeSet?.add(
2262
+ oldSelfClone,
2263
+ ChangeSetEntityChangeType.Added,
2264
+ );
2265
+ oldSelfClone.setParent(dataType, changeSet);
2266
+
2267
+ oldSelfClone.initChildren(changeSet);
2268
+
2269
+ oldSelfClone.merge(dataType, changeSet);
2270
+
2271
+ if (
2272
+ !!existingEntity &&
2273
+ (existingEntity as DefinitionEntityState).parent?.id ===
2274
+ dataType.id
2275
+ ) {
2276
+ (existingEntity as DefinitionEntityState).setParent(
2277
+ oldSelfClone,
2278
+ changeSet,
2279
+ );
2280
+
2281
+ changeSet?.add(
2282
+ existingEntity as UserManagedEntityState,
2283
+ ChangeSetEntityChangeType.Updated,
2284
+ );
2285
+ }
2286
+
2287
+ dataType.setEntity(null, changeSet);
2288
+ dataType.setForeignKeyRef(null, changeSet);
2289
+
2290
+ oldSelfClone.metaSync(
2291
+ {
2292
+ parentRelationType:
2293
+ DataTypeParentChildRelation.OrDataTypeGroup,
2294
+ },
2295
+ changeSet,
2296
+ );
2297
+ newSiblingDataType.metaSync(
2298
+ {
2299
+ parentRelationType:
2300
+ DataTypeParentChildRelation.OrDataTypeGroup,
2301
+ },
2302
+ changeSet,
2303
+ );
2304
+
2305
+ dataType.addToOrGroup(oldSelfClone, changeSet);
2306
+ dataType.addToOrGroup(newSiblingDataType, changeSet);
2307
+
2308
+ // Ideally, only if there were actual changes we should manually set the entity to the change set as updated
2309
+ changeSet?.add(
2310
+ dataType,
2311
+ ChangeSetEntityChangeType.Updated,
2312
+ );
2313
+
2314
+ dataType.metaSync(
2315
+ {
2316
+ asType: false,
2317
+ like: false,
2318
+ },
2319
+ changeSet,
2320
+ );
2321
+
2322
+ onChange?.(dataType, changeSet);
2323
+ },
2324
+ label: `Add 'OR' data type`,
2325
+ color: 'primary',
2326
+ disabled: !canAddNewItemToGroup,
2327
+ iconEnd: 'fa-solid fa-plus',
2328
+ tooltip: !canAddNewItemToGroup
2329
+ ? 'Current data-type must match the base implementation'
2330
+ : 'Click to add',
2331
+ },
2332
+ ]}
2333
+ />
2334
+ </>
2335
+ )}
2336
+ </>
2337
+ )}
2338
+
2339
+ {nestedDataTypeGroups.length > 1 &&
2340
+ !(baseDataTypes || []).some((dt) => dt.implementationChooseOne) && (
2341
+ // Have a node representing the whole group of children,
2342
+ // Here the user can choose whether the children should be a list as a whole
2343
+ <span
2344
+ style={{
2345
+ display: 'flex',
2346
+ flexDirection: 'column',
2347
+ }}
2348
+ >
2349
+ <span
2350
+ style={{
2351
+ display: 'flex',
2352
+ alignItems: 'center',
2353
+ }}
2354
+ >
2355
+ {!!dataType.parentRelationType && (
2356
+ <span
2357
+ id='data-type-builder__builder-group__horizontal-line-before-node'
2358
+ style={{
2359
+ width: 2,
2360
+ height: 1,
2361
+ backgroundColor: 'rgba(0,0,0,0.54)',
2362
+ }}
2363
+ />
2364
+ )}
2365
+ <span
2366
+ style={{
2367
+ display: 'flex',
2368
+ flexDirection: 'column',
2369
+ }}
2370
+ >
2371
+ <div
2372
+ style={{
2373
+ width: 1,
2374
+ height: 15.5,
2375
+ backgroundColor: 'transparent',
2376
+ marginLeft: 5,
2377
+ }}
2378
+ />
2379
+
2380
+ <div
2381
+ style={{
2382
+ width: 7,
2383
+ height: 7,
2384
+ borderRadius: 1,
2385
+ backgroundColor: 'transparent',
2386
+ border: '1px solid rgba(0,0,0,0.54)',
2387
+ marginLeft: !!dataType.parentRelationType ? 0 : 2,
2388
+ }}
2389
+ />
2390
+
2391
+ <div
2392
+ style={{
2393
+ width: 1,
2394
+ height: 16.5,
2395
+ backgroundColor: 'rgba(0,0,0,0.54)',
2396
+ marginLeft: !!dataType.parentRelationType ? 3 : 5,
2397
+ // flexGrow: 1,
2398
+ }}
2399
+ />
2400
+ </span>
2401
+ <span
2402
+ id='data-type-builder__builder-group__horizontal-line-after-node'
2403
+ style={{
2404
+ width: 14,
2405
+ height: 1,
2406
+ backgroundColor: 'rgba(0,0,0,0.54)',
2407
+ }}
2408
+ />
2409
+
2410
+ <p
2411
+ style={{
2412
+ textTransform: 'uppercase',
2413
+ fontSize: 8,
2414
+ color: 'rgba(0,0,0,0.54)',
2415
+ margin: 0,
2416
+ marginLeft: 2,
2417
+ }}
2418
+ >
2419
+ Group
2420
+ </p>
2421
+
2422
+ {/* Fields */}
2423
+ <div
2424
+ style={{
2425
+ display: 'flex',
2426
+ gap: 8,
2427
+ alignItems: 'center',
2428
+ marginLeft: 16,
2429
+ }}
2430
+ >
2431
+ <MuiTooltip
2432
+ title={
2433
+ !!baseDataTypes?.length
2434
+ ? 'Current data-type must match the base implementation'
2435
+ : isListCheckboxDisabled
2436
+ ? getListDisabledTooltip?.(dataType)
2437
+ : ''
2438
+ }
2439
+ placement='bottom'
2440
+ enterDelay={isListCheckboxDisabled ? 100 : 400}
2441
+ leaveDelay={200}
2442
+ >
2443
+ <FormGroup>
2444
+ <FormControlLabel
2445
+ control={
2446
+ <Checkbox
2447
+ disabled={
2448
+ !!baseDataTypes?.length || isListCheckboxDisabled
2449
+ }
2450
+ className='data-type-builder--checkbox'
2451
+ checked={dataType.isList as boolean}
2452
+ onChange={(e) => {
2453
+ const changeSet = onChangeSet?.() || null;
2454
+
2455
+ dataType.metaSync(
2456
+ {
2457
+ isList: e.target.checked,
2458
+ },
2459
+ changeSet,
2460
+ );
2461
+
2462
+ onChange(dataType, changeSet);
2463
+ }}
2464
+ />
2465
+ }
2466
+ label={
2467
+ dataType.isList
2468
+ ? 'Group is list value'
2469
+ : 'Group is idividual value'
2470
+ }
2471
+ />
2472
+ </FormGroup>
2473
+ </MuiTooltip>
2474
+ </div>
2475
+ </span>
2476
+
2477
+ {/* vertical centered line */}
2478
+ <div
2479
+ style={{
2480
+ width: 1,
2481
+ height: 6,
2482
+ backgroundColor: 'rgba(0,0,0,0.54)',
2483
+ marginLeft: 5,
2484
+ }}
2485
+ />
2486
+ </span>
2487
+ )}
2488
+
2489
+ {nestedDataTypeGroups.map((nestedDataTypeItem, index) => {
2490
+ const canAddANDAfterThisNode: boolean =
2491
+ nestedDataTypeItem.operator === 'and' ||
2492
+ !dataType.andChildrenGroup ||
2493
+ !(dataType.andChildrenGroup || []).length;
2494
+
2495
+ return (
2496
+ <>
2497
+ <span
2498
+ style={{
2499
+ display: 'flex',
2500
+ }}
2501
+ >
2502
+ <span
2503
+ key={index}
2504
+ style={{
2505
+ display: 'flex',
2506
+ flexDirection: 'column',
2507
+ }}
2508
+ >
2509
+ {index === 0 && nestedDataTypeGroups.length <= 1 ? (
2510
+ <div
2511
+ id={`data-type-builder__vertical-line-before-operator-keyword--${index}`}
2512
+ style={{
2513
+ width: 1,
2514
+ height: index !== 0 ? 15 : 16,
2515
+ backgroundColor: 'transparent',
2516
+ marginLeft: 5,
2517
+ }}
2518
+ />
2519
+ ) : (
2520
+ <div
2521
+ id={`data-type-builder__vertical-line-before-operator-keyword--${index}`}
2522
+ style={{
2523
+ width: 1,
2524
+ height: index !== 0 ? 15 : 16,
2525
+ backgroundColor: 'rgba(0,0,0,0.54)',
2526
+ marginLeft: 5,
2527
+ }}
2528
+ />
2529
+ )}
2530
+
2531
+ <span
2532
+ style={{
2533
+ display: 'flex',
2534
+ alignItems: 'center',
2535
+ }}
2536
+ >
2537
+ {index !== 0 ? (
2538
+ <p
2539
+ style={{
2540
+ textTransform: 'uppercase',
2541
+ fontSize: 8,
2542
+ color: 'rgba(0,0,0,0.54)',
2543
+ margin: 0,
2544
+ }}
2545
+ >
2546
+ {nestedDataTypeItem.operator?.toUpperCase()}
2547
+ </p>
2548
+ ) : (
2549
+ <span
2550
+ style={{
2551
+ display: 'flex',
2552
+ alignItems: 'center',
2553
+ }}
2554
+ >
2555
+ {!!dataType.parentRelationType &&
2556
+ nestedDataTypeGroups.length <= 1 && (
2557
+ <span
2558
+ id='data-type-builder__builder__horizontal-line-before-node'
2559
+ style={{
2560
+ width: 2,
2561
+ height: 1,
2562
+ backgroundColor: 'rgba(0,0,0,0.54)',
2563
+ }}
2564
+ />
2565
+ )}
2566
+ <div
2567
+ style={{
2568
+ width: 7,
2569
+ height: 7,
2570
+ borderRadius: 1,
2571
+ backgroundColor: 'rgba(0,0,0,0.54)',
2572
+ marginLeft:
2573
+ !!dataType.parentRelationType &&
2574
+ nestedDataTypeGroups.length <= 1
2575
+ ? 0
2576
+ : 2,
2577
+ }}
2578
+ />
2579
+ </span>
2580
+ )}
2581
+
2582
+ {/* Horizontal line to connect to the nested dataType builder */}
2583
+ <span
2584
+ style={{
2585
+ width:
2586
+ index !== 0
2587
+ ? nestedDataTypeItem.operator?.toUpperCase() === 'AND'
2588
+ ? 8
2589
+ : 12
2590
+ : 18,
2591
+ height: 1,
2592
+ backgroundColor: 'rgba(0,0,0,0.54)',
2593
+ flexGrow: 1,
2594
+ marginLeft: index !== 0 ? 2 : 0,
2595
+ }}
2596
+ />
2597
+ </span>
2598
+ <div
2599
+ id={`data-type-builder__vertical-line-after-operator-keyword--${index}`}
2600
+ style={{
2601
+ width: 1,
2602
+ backgroundColor: 'rgba(0,0,0,0.54)',
2603
+ flexGrow: 1,
2604
+ marginLeft: 5,
2605
+ }}
2606
+ />
2607
+ </span>
2608
+
2609
+ <DataTypeBuilderGroup
2610
+ dataType={nestedDataTypeItem.dataType}
2611
+ baseDataTypes={nestedDataTypeItem.baseDataTypes}
2612
+ parentBaseDataTypes={baseDataTypes}
2613
+ topBaseDataTypes={topBaseDataTypes}
2614
+ topParent={topParent}
2615
+ parent={dataType}
2616
+ options={options}
2617
+ project={project}
2618
+ lists={lists}
2619
+ getListDisabledTooltip={getListDisabledTooltip}
2620
+ disallowAsType={disallowAsType}
2621
+ getOptionDisabled={getOptionDisabled}
2622
+ getOptionTooltip={getOptionTooltip}
2623
+ getAsTypeDisabledTooltip={getAsTypeDisabledTooltip}
2624
+ disallowLike={disallowLike}
2625
+ getLikeDisabledTooltip={getLikeDisabledTooltip}
2626
+ onChangeSet={onChangeSet}
2627
+ onChange={(_, changeSet) => {
2628
+ if (isListCheckboxDisabled && !!dataType) {
2629
+ dataType.metaSync(
2630
+ {
2631
+ isList: false,
2632
+ },
2633
+ changeSet,
2634
+ );
2635
+ }
2636
+
2637
+ // Trigger update on top dataType
2638
+ onChange(dataType, changeSet);
2639
+ }}
2640
+ />
2641
+ </span>
2642
+
2643
+ {!!dataType.parentRelationType && (
2644
+ <div
2645
+ id='data-type-builder__vertical-line-after-child-builder'
2646
+ style={{
2647
+ width: 1,
2648
+ height: 4,
2649
+ backgroundColor: 'rgba(0,0,0,0.54)',
2650
+ marginLeft: 5,
2651
+ }}
2652
+ />
2653
+ )}
2654
+
2655
+ {dataType.isResolved && (
2656
+ <>
2657
+ <span
2658
+ className='data-type-builder__add-data-type-between__container'
2659
+ style={{
2660
+ display: 'flex',
2661
+ gap: 6,
2662
+ alignItems: 'center',
2663
+ }}
2664
+ >
2665
+ <button
2666
+ id={`data-type-builder--${nestedDataTypeItem.dataType?.id}--add-nested-data-type--between--in-group`}
2667
+ className='data-type-builder__add-data-type-between__button'
2668
+ disabled={!!baseDataTypes?.length}
2669
+ style={{
2670
+ width: 11,
2671
+ height: 11,
2672
+ }}
2673
+ >
2674
+ <i className='fas fa-plus' />
2675
+ </button>
2676
+
2677
+ <hr
2678
+ className='data-type-builder__add-data-type-between__line'
2679
+ style={{
2680
+ width: 630,
2681
+ backgroundColor: 'var(--color-main-primary)',
2682
+ color: 'var(--color-main-primary)',
2683
+ borderTop: '2px solid var(--color-main-primary)',
2684
+ maxWidth: '100%',
2685
+ margin: 0,
2686
+ }}
2687
+ />
2688
+ </span>
2689
+
2690
+ <DropdownMenuPopup
2691
+ popupOptions={{
2692
+ anchorQuerySelector: `#data-type-builder--${nestedDataTypeItem.dataType?.id}--add-nested-data-type--between--in-group`,
2693
+ placement: 'bottom',
2694
+ }}
2695
+ options={[
2696
+ {
2697
+ onClick: async () => {
2698
+ const changeSet = onChangeSet?.() || null;
2699
+
2700
+ const newSiblingDataTypeTransfer: IDataTypeTransfer =
2701
+ DataTypeState.new(changeSet);
2702
+ newSiblingDataTypeTransfer.parent =
2703
+ dataType.toReference();
2704
+ newSiblingDataTypeTransfer.entity = (
2705
+ project.logic.getBuiltIn(
2706
+ BUILT_IN_BASE_ENTITY_IDS['primitive-entity'].untyped
2707
+ .id,
2708
+ ) as PrimitiveEntityState
2709
+ )?.toJSON() as IPrimitiveEntityTransfer;
2710
+
2711
+ const newSiblingDataType =
2712
+ createStateFromTypeAndSubscribe(
2713
+ newSiblingDataTypeTransfer,
2714
+ project.logic,
2715
+ ) as DataTypeState;
2716
+
2717
+ newSiblingDataType.hydrateAncestors();
2718
+ newSiblingDataType.setParent(dataType, changeSet);
2719
+
2720
+ changeSet?.add(
2721
+ newSiblingDataType,
2722
+ ChangeSetEntityChangeType.Added,
2723
+ );
2724
+
2725
+ newSiblingDataType.initChildren(changeSet);
2726
+
2727
+ newSiblingDataType.metaSync(
2728
+ {
2729
+ parentRelationType:
2730
+ DataTypeParentChildRelation.AndDataTypeGroup,
2731
+ },
2732
+ changeSet,
2733
+ );
2734
+
2735
+ dataType.addToAndGroup(newSiblingDataType, changeSet);
2736
+ dataType.setEntity(null, changeSet);
2737
+
2738
+ changeSet?.add(
2739
+ dataType,
2740
+ ChangeSetEntityChangeType.Updated,
2741
+ );
2742
+
2743
+ if (isListCheckboxDisabled && !!dataType) {
2744
+ dataType.metaSync(
2745
+ {
2746
+ isList: false,
2747
+ },
2748
+ changeSet,
2749
+ );
2750
+ }
2751
+
2752
+ onChange?.(dataType, changeSet);
2753
+ },
2754
+ label: `Add 'AND' dataType`,
2755
+ color: 'primary',
2756
+ iconEnd: 'fa-solid fa-plus',
2757
+ tooltip: !!baseDataTypes?.length
2758
+ ? 'Current data-type must match the base implementation'
2759
+ : canAddANDAfterThisNode
2760
+ ? 'Click to add'
2761
+ : 'Group the "AND" statements together',
2762
+ disabled:
2763
+ !!baseDataTypes?.length || !canAddANDAfterThisNode,
2764
+ },
2765
+ {
2766
+ onClick: async () => {
2767
+ const changeSet = onChangeSet?.() || null;
2768
+
2769
+ const newSiblingDataTypeTransfer: IDataTypeTransfer =
2770
+ DataTypeState.new(changeSet);
2771
+ newSiblingDataTypeTransfer.parent =
2772
+ dataType.toReference();
2773
+ newSiblingDataTypeTransfer.entity = (
2774
+ project.logic.getBuiltIn(
2775
+ BUILT_IN_BASE_ENTITY_IDS['primitive-entity'].untyped
2776
+ .id,
2777
+ ) as PrimitiveEntityState
2778
+ )?.toJSON() as IPrimitiveEntityTransfer;
2779
+
2780
+ const newSiblingDataType =
2781
+ createStateFromTypeAndSubscribe(
2782
+ newSiblingDataTypeTransfer,
2783
+ project.logic,
2784
+ ) as DataTypeState;
2785
+
2786
+ newSiblingDataType.hydrateAncestors();
2787
+ newSiblingDataType.setParent(dataType, changeSet);
2788
+
2789
+ changeSet?.add(
2790
+ newSiblingDataType,
2791
+ ChangeSetEntityChangeType.Added,
2792
+ );
2793
+
2794
+ newSiblingDataType.initChildren(changeSet);
2795
+
2796
+ newSiblingDataType.metaSync(
2797
+ {
2798
+ parentRelationType:
2799
+ DataTypeParentChildRelation.OrDataTypeGroup,
2800
+ },
2801
+ changeSet,
2802
+ );
2803
+
2804
+ dataType.addToOrGroup(newSiblingDataType, changeSet);
2805
+ dataType.setEntity(null, changeSet);
2806
+
2807
+ changeSet?.add(
2808
+ dataType,
2809
+ ChangeSetEntityChangeType.Updated,
2810
+ );
2811
+
2812
+ if (isListCheckboxDisabled && !!dataType) {
2813
+ dataType.metaSync(
2814
+ {
2815
+ isList: false,
2816
+ },
2817
+ changeSet,
2818
+ );
2819
+ }
2820
+
2821
+ onChange?.(dataType, changeSet);
2822
+ },
2823
+ label: `Add 'OR' dataType`,
2824
+ color: 'primary',
2825
+ iconEnd: 'fa-solid fa-plus',
2826
+ tooltip: !!baseDataTypes?.length
2827
+ ? 'Current data-type must match the base implementation'
2828
+ : 'Click to add',
2829
+ disabled: !!baseDataTypes?.length,
2830
+ },
2831
+ ]}
2832
+ />
2833
+ </>
2834
+ )}
2835
+ </>
2836
+ );
2837
+ })}
2838
+
2839
+ {!dataType && (
2840
+ <>
2841
+ <div
2842
+ style={{
2843
+ display: 'flex',
2844
+ alignItems: 'center',
2845
+ gap: 8,
2846
+ }}
2847
+ >
2848
+ {isRootLevel ? (
2849
+ <Button
2850
+ style={{
2851
+ marginTop: 8,
2852
+ }}
2853
+ id={`data-type-builder--${dataType?.id}--add-root-data-type`}
2854
+ // variant='outlined'
2855
+ color='primary'
2856
+ disabled={!!baseDataTypes?.length}
2857
+ onClick={() => {
2858
+ const changeSet = onChangeSet?.() || null;
2859
+
2860
+ if (!dataType) {
2861
+ const newDataTypeTransfer: IDataTypeTransfer =
2862
+ DataTypeState.new(changeSet);
2863
+
2864
+ const newDataType = createStateFromTypeAndSubscribe(
2865
+ newDataTypeTransfer,
2866
+ project.logic,
2867
+ ) as DataTypeState;
2868
+
2869
+ changeSet?.add(
2870
+ newDataType,
2871
+ ChangeSetEntityChangeType.Added,
2872
+ );
2873
+
2874
+ if (isListCheckboxDisabled && !!newDataType) {
2875
+ newDataType.metaSync(
2876
+ {
2877
+ isList: false,
2878
+ },
2879
+ changeSet,
2880
+ );
2881
+ }
2882
+
2883
+ onChange?.(newDataType, changeSet);
2884
+ } else {
2885
+ if (isListCheckboxDisabled && !!dataType) {
2886
+ dataType.metaSync(
2887
+ {
2888
+ isList: false,
2889
+ },
2890
+ changeSet,
2891
+ );
2892
+ }
2893
+
2894
+ onChange?.(dataType, changeSet);
2895
+ }
2896
+ }}
2897
+ >
2898
+ Add data type
2899
+ </Button>
2900
+ ) : (
2901
+ <>
2902
+ <button
2903
+ id={`data-type-builder--${dataType?.id}--add-root-data-type`}
2904
+ className='data-type-builder__add-data-type-between__button'
2905
+ disabled={!!baseDataTypes?.length}
2906
+ onClick={() => {
2907
+ const changeSet = onChangeSet?.() || null;
2908
+
2909
+ if (!dataType) {
2910
+ const newDataTypeTransfer: IDataTypeTransfer =
2911
+ DataTypeState.new(changeSet);
2912
+
2913
+ const newDataType = createStateFromTypeAndSubscribe(
2914
+ newDataTypeTransfer,
2915
+ project.logic,
2916
+ ) as DataTypeState;
2917
+
2918
+ changeSet?.add(
2919
+ newDataType,
2920
+ ChangeSetEntityChangeType.Added,
2921
+ );
2922
+
2923
+ if (isListCheckboxDisabled && !!newDataType) {
2924
+ newDataType.metaSync(
2925
+ {
2926
+ isList: false,
2927
+ },
2928
+ changeSet,
2929
+ );
2930
+ }
2931
+
2932
+ onChange?.(newDataType, changeSet);
2933
+ } else {
2934
+ if (isListCheckboxDisabled && !!dataType) {
2935
+ dataType.metaSync(
2936
+ {
2937
+ isList: false,
2938
+ },
2939
+ changeSet,
2940
+ );
2941
+ }
2942
+
2943
+ onChange?.(dataType, changeSet);
2944
+ }
2945
+ }}
2946
+ style={{
2947
+ width: 11,
2948
+ height: 11,
2949
+ }}
2950
+ >
2951
+ <i className='fas fa-plus' />
2952
+ </button>
2953
+ <p
2954
+ style={{
2955
+ margin: 0,
2956
+ fontSize: 10,
2957
+ color: 'rgba(0,0,0,0.54)',
2958
+ }}
2959
+ >
2960
+ No data type
2961
+ </p>
2962
+ </>
2963
+ )}
2964
+ </div>
2965
+
2966
+ <Tooltip
2967
+ anchorQuerySelector={`#data-type-builder--${dataType?.id}--add-root-data-type`}
2968
+ placement='bottom'
2969
+ >
2970
+ {!!baseDataTypes?.length
2971
+ ? "Can't modify because current data-type must match the base implementation"
2972
+ : 'Click to add the first data type'}
2973
+ </Tooltip>
2974
+ </>
2975
+ )}
2976
+ </div>
2977
+ );
2978
+ };
2979
+
2980
+ export const DataTypeBuilder = ({
2981
+ dataType,
2982
+ baseDataTypes,
2983
+ topParent,
2984
+ project,
2985
+ onChange = () => {},
2986
+ options,
2987
+ getOptionDisabled,
2988
+ getOptionTooltip,
2989
+ lists: _lists,
2990
+ getListDisabledTooltip,
2991
+ disallowAsType,
2992
+ getAsTypeDisabledTooltip,
2993
+ disallowLike,
2994
+ getLikeDisabledTooltip,
2995
+ onChangeSet,
2996
+ readOnly,
2997
+ }: {
2998
+ dataType?: DataTypeState;
2999
+ baseDataTypes?: DataTypeState[];
3000
+ topParent: UserManagedDataTypeParentEntityState;
3001
+ project: EditorService;
3002
+ onChange?: (value: DataTypeState, changeSet: ChangeSet | null) => void;
3003
+ options?: DataTypeBuilderOption[];
3004
+ getOptionDisabled?: (
3005
+ option: DataTypeBuilderOption | ILiteralValueOption,
3006
+ ) => boolean;
3007
+ getOptionTooltip?: (
3008
+ option: DataTypeBuilderOption | ILiteralValueOption,
3009
+ ) => React.ReactNode;
3010
+ lists?: AllowedDataTypeListTypes;
3011
+ getListDisabledTooltip?: (dataType: DataTypeState) => React.ReactNode;
3012
+ disallowAsType?: boolean;
3013
+ getAsTypeDisabledTooltip?: (dataType: DataTypeState) => React.ReactNode;
3014
+ disallowLike?: boolean;
3015
+ getLikeDisabledTooltip?: (dataType: DataTypeState) => React.ReactNode;
3016
+ onChangeSet?: () => ChangeSet | null;
3017
+ readOnly?: boolean;
3018
+ }) => {
3019
+ const lists = _lists || AllowedDataTypeListTypes.All;
3020
+
3021
+ const optionsWithDefaults =
3022
+ options || getAllDataTypeBuilderOptions(project.logic, topParent);
3023
+
3024
+ const defaultGetListDisabledTooltip = (
3025
+ dataType: DataTypeState,
3026
+ ): React.ReactNode => {
3027
+ if (getListDisabledTooltip) {
3028
+ return getListDisabledTooltip(dataType);
3029
+ }
3030
+
3031
+ if (lists === AllowedDataTypeListTypes.None) {
3032
+ return 'Lists are not allowed in the context this data type is used';
3033
+ } else if (lists === AllowedDataTypeListTypes.Flat) {
3034
+ return "A single level of list is allowed in the context this data type is used. You can't nest lists";
3035
+ }
3036
+
3037
+ return '';
3038
+ };
3039
+
3040
+ const readOnlyTopLevelLabel = resolveDataTypeLabel(
3041
+ dataType || baseDataTypes?.[0],
3042
+ );
3043
+
3044
+ const canInferDataTypeFromValueWritter =
3045
+ !baseDataTypes &&
3046
+ !!dataType &&
3047
+ VALUE_READING_TYPES.includes(dataType.parent.type);
3048
+
3049
+ return (
3050
+ <div
3051
+ style={{
3052
+ width: '100%',
3053
+ overflowX: 'scroll',
3054
+ // paddingTop: 7,
3055
+ display: 'flex',
3056
+ flexDirection: 'column',
3057
+ gap: 8,
3058
+ }}
3059
+ >
3060
+ <div
3061
+ style={{
3062
+ display: 'flex',
3063
+ }}
3064
+ >
3065
+ <p
3066
+ style={{
3067
+ margin: 0,
3068
+ fontSize: 10,
3069
+ color: 'rgba(0,0,0,0.54)',
3070
+ }}
3071
+ >
3072
+ {readOnlyTopLevelLabel}
3073
+ </p>
3074
+ </div>
3075
+ {canInferDataTypeFromValueWritter && !readOnly && (
3076
+ // Checkbox to allow the user to infer the data type from the value writter
3077
+ <FormGroup>
3078
+ <FormControlLabel
3079
+ control={
3080
+ <Checkbox
3081
+ className='data-type-builder--inferred-checkbox'
3082
+ checked={dataType.inferred}
3083
+ onChange={(e) => {
3084
+ const changeSet = onChangeSet?.() || null;
3085
+
3086
+ dataType.metaSync(
3087
+ {
3088
+ inferred: e.target.checked,
3089
+ },
3090
+ changeSet,
3091
+ );
3092
+
3093
+ onChange(dataType, changeSet);
3094
+ }}
3095
+ />
3096
+ }
3097
+ label='Infer data type from value writter'
3098
+ />
3099
+ </FormGroup>
3100
+ )}
3101
+ {!readOnly && (
3102
+ <DataTypeBuilderGroup
3103
+ dataType={dataType}
3104
+ parentBaseDataTypes={[]}
3105
+ baseDataTypes={baseDataTypes}
3106
+ topParent={topParent}
3107
+ topBaseDataTypes={baseDataTypes}
3108
+ parent={topParent}
3109
+ project={project}
3110
+ onChange={onChange}
3111
+ onChangeSet={onChangeSet}
3112
+ options={optionsWithDefaults}
3113
+ getOptionDisabled={getOptionDisabled}
3114
+ getOptionTooltip={getOptionTooltip}
3115
+ lists={lists}
3116
+ getListDisabledTooltip={defaultGetListDisabledTooltip}
3117
+ disallowAsType={disallowAsType}
3118
+ getAsTypeDisabledTooltip={getAsTypeDisabledTooltip}
3119
+ disallowLike={disallowLike}
3120
+ getLikeDisabledTooltip={getLikeDisabledTooltip}
3121
+ />
3122
+ )}
3123
+ </div>
3124
+ );
3125
+ };
3126
+
3127
+ export default DataTypeBuilder;