@open-mercato/core 0.6.5-develop.5337.1.534b781eac → 0.6.5

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 (350) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/AGENTS.md +1 -1
  3. package/dist/bootstrap.js +46 -6
  4. package/dist/bootstrap.js.map +2 -2
  5. package/dist/generated/entities/organization/index.js +2 -0
  6. package/dist/generated/entities/organization/index.js.map +2 -2
  7. package/dist/generated/entity-fields-registry.js +1 -0
  8. package/dist/generated/entity-fields-registry.js.map +2 -2
  9. package/dist/helpers/integration/crmFixtures.js +4 -0
  10. package/dist/helpers/integration/crmFixtures.js.map +2 -2
  11. package/dist/modules/attachments/api/library/route.js +2 -2
  12. package/dist/modules/attachments/api/library/route.js.map +2 -2
  13. package/dist/modules/attachments/api/route.js +2 -0
  14. package/dist/modules/attachments/api/route.js.map +2 -2
  15. package/dist/modules/attachments/components/AttachmentContentPreview.js +9 -5
  16. package/dist/modules/attachments/components/AttachmentContentPreview.js.map +2 -2
  17. package/dist/modules/attachments/lib/access.js +18 -0
  18. package/dist/modules/attachments/lib/access.js.map +2 -2
  19. package/dist/modules/audit_logs/api/audit-logs/actions/redo/route.js +3 -2
  20. package/dist/modules/audit_logs/api/audit-logs/actions/redo/route.js.map +2 -2
  21. package/dist/modules/audit_logs/data/entities.js +2 -1
  22. package/dist/modules/audit_logs/data/entities.js.map +2 -2
  23. package/dist/modules/audit_logs/migrations/Migration20260611104500.js +13 -0
  24. package/dist/modules/audit_logs/migrations/Migration20260611104500.js.map +7 -0
  25. package/dist/modules/audit_logs/services/accessLogService.js +10 -0
  26. package/dist/modules/audit_logs/services/accessLogService.js.map +2 -2
  27. package/dist/modules/auth/api/admin/nav.js +9 -0
  28. package/dist/modules/auth/api/admin/nav.js.map +2 -2
  29. package/dist/modules/auth/api/login.js +4 -13
  30. package/dist/modules/auth/api/login.js.map +2 -2
  31. package/dist/modules/auth/commands/users.js +20 -14
  32. package/dist/modules/auth/commands/users.js.map +2 -2
  33. package/dist/modules/auth/data/entities.js +4 -2
  34. package/dist/modules/auth/data/entities.js.map +2 -2
  35. package/dist/modules/auth/lib/backendChrome.js +35 -2
  36. package/dist/modules/auth/lib/backendChrome.js.map +2 -2
  37. package/dist/modules/auth/lib/consentIntegrity.js +3 -3
  38. package/dist/modules/auth/lib/consentIntegrity.js.map +2 -2
  39. package/dist/modules/auth/migrations/Migration20260610120000.js +30 -0
  40. package/dist/modules/auth/migrations/Migration20260610120000.js.map +7 -0
  41. package/dist/modules/auth/migrations/Migration20260611103000.js +15 -0
  42. package/dist/modules/auth/migrations/Migration20260611103000.js.map +7 -0
  43. package/dist/modules/auth/services/authService.js +5 -3
  44. package/dist/modules/auth/services/authService.js.map +2 -2
  45. package/dist/modules/auth/services/rbacService.js +3 -2
  46. package/dist/modules/auth/services/rbacService.js.map +2 -2
  47. package/dist/modules/catalog/ai-tools/configuration-pack.js.map +1 -1
  48. package/dist/modules/catalog/ai-tools/prices-offers-pack.js.map +1 -1
  49. package/dist/modules/catalog/ai-tools/products-pack.js.map +1 -1
  50. package/dist/modules/catalog/ai-tools/variants-pack.js.map +1 -1
  51. package/dist/modules/communication_channels/data/entities.js.map +1 -1
  52. package/dist/modules/communication_channels/encryption.js.map +1 -1
  53. package/dist/modules/communication_channels/lib/thread-matcher.js.map +1 -1
  54. package/dist/modules/communication_channels/lib/thread-token.js.map +1 -1
  55. package/dist/modules/currencies/api/currencies/route.js +4 -3
  56. package/dist/modules/currencies/api/currencies/route.js.map +2 -2
  57. package/dist/modules/customer_accounts/api/admin/roles.js +2 -1
  58. package/dist/modules/customer_accounts/api/admin/roles.js.map +2 -2
  59. package/dist/modules/customer_accounts/backend/customer_accounts/settings/domain/components/Diagnostics.js +0 -3
  60. package/dist/modules/customer_accounts/backend/customer_accounts/settings/domain/components/Diagnostics.js.map +2 -2
  61. package/dist/modules/customer_accounts/events.js +1 -1
  62. package/dist/modules/customer_accounts/events.js.map +1 -1
  63. package/dist/modules/customer_accounts/lib/resolveTenantContext.js.map +1 -1
  64. package/dist/modules/customers/acl.js +1 -1
  65. package/dist/modules/customers/acl.js.map +1 -1
  66. package/dist/modules/customers/ai-tools/companies-pack.js.map +1 -1
  67. package/dist/modules/customers/ai-tools/deals-pack.js.map +1 -1
  68. package/dist/modules/customers/ai-tools/people-pack.js.map +1 -1
  69. package/dist/modules/customers/api/companies/route.js +4 -4
  70. package/dist/modules/customers/api/companies/route.js.map +2 -2
  71. package/dist/modules/customers/api/deals/route.js +43 -2
  72. package/dist/modules/customers/api/deals/route.js.map +2 -2
  73. package/dist/modules/customers/api/deals/summary/route.js +402 -0
  74. package/dist/modules/customers/api/deals/summary/route.js.map +7 -0
  75. package/dist/modules/customers/api/people/route.js +4 -4
  76. package/dist/modules/customers/api/people/route.js.map +2 -2
  77. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealActivities.js +16 -5
  78. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealActivities.js.map +2 -2
  79. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealData.js +22 -5
  80. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealData.js.map +2 -2
  81. package/dist/modules/customers/backend/customers/deals/[id]/page.js +12 -2
  82. package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +2 -2
  83. package/dist/modules/customers/backend/customers/deals/page.js +221 -56
  84. package/dist/modules/customers/backend/customers/deals/page.js.map +3 -3
  85. package/dist/modules/customers/backend/customers/deals/pipeline/page.js +1 -1
  86. package/dist/modules/customers/backend/customers/deals/pipeline/page.js.map +2 -2
  87. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js +18 -0
  88. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js.map +2 -2
  89. package/dist/modules/customers/cli.js +15 -9
  90. package/dist/modules/customers/cli.js.map +2 -2
  91. package/dist/modules/customers/commands/addresses.js +5 -5
  92. package/dist/modules/customers/commands/addresses.js.map +2 -2
  93. package/dist/modules/customers/commands/comments.js +5 -5
  94. package/dist/modules/customers/commands/comments.js.map +2 -2
  95. package/dist/modules/customers/commands/deals.js +2 -2
  96. package/dist/modules/customers/commands/deals.js.map +2 -2
  97. package/dist/modules/customers/commands/entity-roles.js +2 -1
  98. package/dist/modules/customers/commands/entity-roles.js.map +2 -2
  99. package/dist/modules/customers/commands/interactions.js +8 -5
  100. package/dist/modules/customers/commands/interactions.js.map +2 -2
  101. package/dist/modules/customers/commands/shared.js +21 -6
  102. package/dist/modules/customers/commands/shared.js.map +2 -2
  103. package/dist/modules/customers/commands/tags.js +3 -3
  104. package/dist/modules/customers/commands/tags.js.map +2 -2
  105. package/dist/modules/customers/components/DealsKpiStrip.js +282 -0
  106. package/dist/modules/customers/components/DealsKpiStrip.js.map +7 -0
  107. package/dist/modules/customers/components/detail/ConfirmDealLostDialog.js +0 -1
  108. package/dist/modules/customers/components/detail/ConfirmDealLostDialog.js.map +2 -2
  109. package/dist/modules/customers/components/detail/DealForm.js +100 -17
  110. package/dist/modules/customers/components/detail/DealForm.js.map +2 -2
  111. package/dist/modules/customers/components/detail/PersonDetailTabs.js +11 -3
  112. package/dist/modules/customers/components/detail/PersonDetailTabs.js.map +2 -2
  113. package/dist/modules/customers/components/detail/ScheduleActivityDialog.js +1 -2
  114. package/dist/modules/customers/components/detail/ScheduleActivityDialog.js.map +2 -2
  115. package/dist/modules/customers/components/detail/assignableStaff.js +21 -8
  116. package/dist/modules/customers/components/detail/assignableStaff.js.map +2 -2
  117. package/dist/modules/customers/components/kpi/PipelineStageBar.js +63 -0
  118. package/dist/modules/customers/components/kpi/PipelineStageBar.js.map +7 -0
  119. package/dist/modules/customers/lib/dealsMetrics.js +82 -0
  120. package/dist/modules/customers/lib/dealsMetrics.js.map +7 -0
  121. package/dist/modules/customers/migrations/Migration20260519120000_pipeline_stage_color_tones.js.map +1 -1
  122. package/dist/modules/data_sync/api/run.js +1 -1
  123. package/dist/modules/data_sync/api/run.js.map +2 -2
  124. package/dist/modules/directory/api/organization-branding/route.js +214 -0
  125. package/dist/modules/directory/api/organization-branding/route.js.map +7 -0
  126. package/dist/modules/directory/api/organizations/route.js +7 -0
  127. package/dist/modules/directory/api/organizations/route.js.map +3 -3
  128. package/dist/modules/directory/backend/directory/branding/page.js +214 -0
  129. package/dist/modules/directory/backend/directory/branding/page.js.map +7 -0
  130. package/dist/modules/directory/backend/directory/branding/page.meta.js +26 -0
  131. package/dist/modules/directory/backend/directory/branding/page.meta.js.map +7 -0
  132. package/dist/modules/directory/commands/organizations.js +8 -1
  133. package/dist/modules/directory/commands/organizations.js.map +2 -2
  134. package/dist/modules/directory/data/entities.js +3 -0
  135. package/dist/modules/directory/data/entities.js.map +2 -2
  136. package/dist/modules/directory/data/validators.js +9 -0
  137. package/dist/modules/directory/data/validators.js.map +2 -2
  138. package/dist/modules/directory/migrations/Migration20260607222259_directory.js +13 -0
  139. package/dist/modules/directory/migrations/Migration20260607222259_directory.js.map +7 -0
  140. package/dist/modules/directory/subscribers/invalidateOrgScopeCache.js +2 -1
  141. package/dist/modules/directory/subscribers/invalidateOrgScopeCache.js.map +2 -2
  142. package/dist/modules/directory/utils/organizationScope.js +59 -27
  143. package/dist/modules/directory/utils/organizationScope.js.map +2 -2
  144. package/dist/modules/entities/api/definitions.batch.js +2 -1
  145. package/dist/modules/entities/api/definitions.batch.js.map +2 -2
  146. package/dist/modules/entities/api/entities.js +7 -0
  147. package/dist/modules/entities/api/entities.js.map +2 -2
  148. package/dist/modules/entities/api/records.js +26 -15
  149. package/dist/modules/entities/api/records.js.map +2 -2
  150. package/dist/modules/entities/backend/entities/user/[entityId]/records/[recordId]/page.js +14 -0
  151. package/dist/modules/entities/backend/entities/user/[entityId]/records/[recordId]/page.js.map +2 -2
  152. package/dist/modules/entities/backend/entities/user/[entityId]/records/create/page.js +14 -0
  153. package/dist/modules/entities/backend/entities/user/[entityId]/records/create/page.js.map +2 -2
  154. package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js +12 -0
  155. package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js.map +2 -2
  156. package/dist/modules/entities/components/useRecordsEntityGuard.js +30 -0
  157. package/dist/modules/entities/components/useRecordsEntityGuard.js.map +7 -0
  158. package/dist/modules/payment_gateways/api/transactions/route.js +2 -4
  159. package/dist/modules/payment_gateways/api/transactions/route.js.map +2 -2
  160. package/dist/modules/progress/api/jobs/[id]/route.js +7 -2
  161. package/dist/modules/progress/api/jobs/[id]/route.js.map +2 -2
  162. package/dist/modules/progress/api/jobs/route.js +1 -1
  163. package/dist/modules/progress/api/jobs/route.js.map +2 -2
  164. package/dist/modules/progress/lib/progressServiceImpl.js +8 -2
  165. package/dist/modules/progress/lib/progressServiceImpl.js.map +2 -2
  166. package/dist/modules/query_index/data/entities.js +2 -1
  167. package/dist/modules/query_index/data/entities.js.map +2 -2
  168. package/dist/modules/query_index/lib/engine.js +4 -2
  169. package/dist/modules/query_index/lib/engine.js.map +2 -2
  170. package/dist/modules/query_index/migrations/Migration20260611103000_query_index.js +16 -0
  171. package/dist/modules/query_index/migrations/Migration20260611103000_query_index.js.map +7 -0
  172. package/dist/modules/resources/api/resources.js +2 -3
  173. package/dist/modules/resources/api/resources.js.map +2 -2
  174. package/dist/modules/sales/api/documents/factory.js +2 -2
  175. package/dist/modules/sales/api/documents/factory.js.map +2 -2
  176. package/dist/modules/sales/commands/documents.js +7 -5
  177. package/dist/modules/sales/commands/documents.js.map +2 -2
  178. package/dist/modules/sales/components/documents/SalesDocumentsTable.js +2 -1
  179. package/dist/modules/sales/components/documents/SalesDocumentsTable.js.map +2 -2
  180. package/dist/modules/sales/components/documents/salesDocumentsColumns.js +10 -0
  181. package/dist/modules/sales/components/documents/salesDocumentsColumns.js.map +7 -0
  182. package/dist/modules/staff/api/team-members.js +9 -2
  183. package/dist/modules/staff/api/team-members.js.map +2 -2
  184. package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.js +24 -1
  185. package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.js.map +2 -2
  186. package/dist/modules/staff/backend/staff/team-members/[id]/page.js +11 -6
  187. package/dist/modules/staff/backend/staff/team-members/[id]/page.js.map +2 -2
  188. package/dist/modules/staff/commands/team-members.js +1 -1
  189. package/dist/modules/staff/commands/team-members.js.map +2 -2
  190. package/dist/modules/staff/components/TeamMemberForm.js +1 -1
  191. package/dist/modules/staff/components/TeamMemberForm.js.map +2 -2
  192. package/dist/modules/staff/lib/scheduleSwitch.js +23 -0
  193. package/dist/modules/staff/lib/scheduleSwitch.js.map +7 -0
  194. package/dist/modules/sync_excel/api/import/route.js +1 -1
  195. package/dist/modules/sync_excel/api/import/route.js.map +2 -2
  196. package/dist/modules/workflows/api/definitions/route.js +3 -2
  197. package/dist/modules/workflows/api/definitions/route.js.map +2 -2
  198. package/dist/modules/workflows/backend/definitions/create/page.js +1 -2
  199. package/dist/modules/workflows/backend/definitions/create/page.js.map +2 -2
  200. package/dist/modules/workflows/backend/definitions/visual-editor/page.js +1 -2
  201. package/dist/modules/workflows/backend/definitions/visual-editor/page.js.map +2 -2
  202. package/dist/modules/workflows/components/DefinitionTriggersEditor.js +1 -2
  203. package/dist/modules/workflows/components/DefinitionTriggersEditor.js.map +2 -2
  204. package/dist/modules/workflows/components/NodeEditDialog.js +4 -13
  205. package/dist/modules/workflows/components/NodeEditDialog.js.map +2 -2
  206. package/dist/modules/workflows/components/NodeEditDialogCrudForm.js +4 -13
  207. package/dist/modules/workflows/components/NodeEditDialogCrudForm.js.map +2 -2
  208. package/dist/modules/workflows/components/WorkflowGraphImpl.js +1 -4
  209. package/dist/modules/workflows/components/WorkflowGraphImpl.js.map +2 -2
  210. package/dist/modules/workflows/components/fields/FormFieldArrayEditor.js +2 -5
  211. package/dist/modules/workflows/components/fields/FormFieldArrayEditor.js.map +2 -2
  212. package/generated/entities/organization/index.ts +1 -0
  213. package/generated/entity-fields-registry.ts +1 -0
  214. package/package.json +11 -12
  215. package/src/bootstrap.ts +65 -7
  216. package/src/helpers/integration/crmFixtures.ts +21 -1
  217. package/src/modules/attachments/AGENTS.md +79 -0
  218. package/src/modules/attachments/api/library/route.ts +2 -2
  219. package/src/modules/attachments/api/route.ts +2 -0
  220. package/src/modules/attachments/components/AttachmentContentPreview.tsx +6 -6
  221. package/src/modules/attachments/lib/access.ts +36 -0
  222. package/src/modules/audit_logs/api/audit-logs/actions/redo/route.ts +14 -2
  223. package/src/modules/audit_logs/data/entities.ts +1 -0
  224. package/src/modules/audit_logs/migrations/.snapshot-open-mercato.json +10 -0
  225. package/src/modules/audit_logs/migrations/Migration20260611104500.ts +13 -0
  226. package/src/modules/audit_logs/services/accessLogService.ts +15 -0
  227. package/src/modules/auth/api/admin/nav.ts +9 -0
  228. package/src/modules/auth/api/login.ts +13 -13
  229. package/src/modules/auth/commands/users.ts +32 -15
  230. package/src/modules/auth/data/entities.ts +13 -1
  231. package/src/modules/auth/i18n/de.json +0 -1
  232. package/src/modules/auth/i18n/en.json +0 -1
  233. package/src/modules/auth/i18n/es.json +0 -1
  234. package/src/modules/auth/i18n/pl.json +0 -1
  235. package/src/modules/auth/lib/backendChrome.tsx +37 -1
  236. package/src/modules/auth/lib/consentIntegrity.ts +6 -3
  237. package/src/modules/auth/migrations/.snapshot-open-mercato.json +20 -10
  238. package/src/modules/auth/migrations/Migration20260610120000.ts +53 -0
  239. package/src/modules/auth/migrations/Migration20260611103000.ts +21 -0
  240. package/src/modules/auth/services/authService.ts +24 -4
  241. package/src/modules/auth/services/rbacService.ts +11 -2
  242. package/src/modules/catalog/ai-tools/configuration-pack.ts +1 -1
  243. package/src/modules/catalog/ai-tools/prices-offers-pack.ts +1 -1
  244. package/src/modules/catalog/ai-tools/products-pack.ts +1 -1
  245. package/src/modules/catalog/ai-tools/variants-pack.ts +1 -1
  246. package/src/modules/communication_channels/data/entities.ts +2 -2
  247. package/src/modules/communication_channels/encryption.ts +1 -1
  248. package/src/modules/communication_channels/lib/adapter.ts +1 -1
  249. package/src/modules/communication_channels/lib/thread-matcher.ts +1 -1
  250. package/src/modules/communication_channels/lib/thread-token.ts +1 -1
  251. package/src/modules/currencies/api/currencies/route.ts +4 -3
  252. package/src/modules/customer_accounts/api/admin/roles.ts +2 -1
  253. package/src/modules/customer_accounts/backend/customer_accounts/settings/domain/components/Diagnostics.tsx +0 -3
  254. package/src/modules/customer_accounts/events.ts +1 -1
  255. package/src/modules/customer_accounts/lib/resolveTenantContext.ts +2 -2
  256. package/src/modules/customers/acl.ts +1 -1
  257. package/src/modules/customers/ai-tools/companies-pack.ts +1 -1
  258. package/src/modules/customers/ai-tools/deals-pack.ts +1 -1
  259. package/src/modules/customers/ai-tools/people-pack.ts +1 -1
  260. package/src/modules/customers/api/companies/route.ts +4 -4
  261. package/src/modules/customers/api/deals/route.ts +51 -2
  262. package/src/modules/customers/api/deals/summary/route.ts +496 -0
  263. package/src/modules/customers/api/people/route.ts +4 -4
  264. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealActivities.ts +28 -6
  265. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealData.ts +33 -6
  266. package/src/modules/customers/backend/customers/deals/[id]/page.tsx +17 -2
  267. package/src/modules/customers/backend/customers/deals/page.tsx +254 -66
  268. package/src/modules/customers/backend/customers/deals/pipeline/page.tsx +1 -2
  269. package/src/modules/customers/backend/customers/people-v2/[id]/page.tsx +18 -0
  270. package/src/modules/customers/cli.ts +15 -15
  271. package/src/modules/customers/commands/addresses.ts +5 -5
  272. package/src/modules/customers/commands/comments.ts +5 -5
  273. package/src/modules/customers/commands/deals.ts +2 -2
  274. package/src/modules/customers/commands/entity-roles.ts +2 -1
  275. package/src/modules/customers/commands/interactions.ts +8 -5
  276. package/src/modules/customers/commands/shared.ts +26 -4
  277. package/src/modules/customers/commands/tags.ts +3 -3
  278. package/src/modules/customers/components/DealsKpiStrip.tsx +389 -0
  279. package/src/modules/customers/components/detail/ConfirmDealLostDialog.tsx +0 -1
  280. package/src/modules/customers/components/detail/DealForm.tsx +121 -19
  281. package/src/modules/customers/components/detail/PersonDetailTabs.tsx +12 -2
  282. package/src/modules/customers/components/detail/ScheduleActivityDialog.tsx +1 -2
  283. package/src/modules/customers/components/detail/assignableStaff.ts +32 -8
  284. package/src/modules/customers/components/kpi/PipelineStageBar.tsx +77 -0
  285. package/src/modules/customers/i18n/de.json +43 -0
  286. package/src/modules/customers/i18n/en.json +43 -0
  287. package/src/modules/customers/i18n/es.json +43 -0
  288. package/src/modules/customers/i18n/pl.json +43 -0
  289. package/src/modules/customers/lib/dealsMetrics.ts +159 -0
  290. package/src/modules/customers/migrations/Migration20260519120000_pipeline_stage_color_tones.ts +1 -1
  291. package/src/modules/data_sync/api/run.ts +1 -1
  292. package/src/modules/directory/api/organization-branding/route.ts +238 -0
  293. package/src/modules/directory/api/organizations/route.ts +7 -0
  294. package/src/modules/directory/backend/directory/branding/page.meta.ts +24 -0
  295. package/src/modules/directory/backend/directory/branding/page.tsx +248 -0
  296. package/src/modules/directory/commands/organizations.ts +9 -1
  297. package/src/modules/directory/data/entities.ts +3 -0
  298. package/src/modules/directory/data/validators.ts +12 -0
  299. package/src/modules/directory/i18n/de.json +21 -0
  300. package/src/modules/directory/i18n/en.json +21 -0
  301. package/src/modules/directory/i18n/es.json +21 -0
  302. package/src/modules/directory/i18n/pl.json +21 -0
  303. package/src/modules/directory/migrations/.snapshot-open-mercato.json +40 -0
  304. package/src/modules/directory/migrations/Migration20260607222259_directory.ts +13 -0
  305. package/src/modules/directory/subscribers/invalidateOrgScopeCache.ts +3 -1
  306. package/src/modules/directory/utils/organizationScope.ts +85 -30
  307. package/src/modules/entities/api/definitions.batch.ts +11 -7
  308. package/src/modules/entities/api/entities.ts +11 -0
  309. package/src/modules/entities/api/records.ts +46 -25
  310. package/src/modules/entities/backend/entities/user/[entityId]/records/[recordId]/page.tsx +15 -0
  311. package/src/modules/entities/backend/entities/user/[entityId]/records/create/page.tsx +15 -0
  312. package/src/modules/entities/backend/entities/user/[entityId]/records/page.tsx +23 -0
  313. package/src/modules/entities/components/useRecordsEntityGuard.ts +41 -0
  314. package/src/modules/entities/i18n/de.json +1 -0
  315. package/src/modules/entities/i18n/en.json +1 -0
  316. package/src/modules/entities/i18n/es.json +1 -0
  317. package/src/modules/entities/i18n/pl.json +1 -0
  318. package/src/modules/payment_gateways/api/transactions/route.ts +2 -5
  319. package/src/modules/progress/api/jobs/[id]/route.ts +6 -1
  320. package/src/modules/progress/api/jobs/route.ts +1 -1
  321. package/src/modules/progress/lib/progressServiceImpl.ts +7 -1
  322. package/src/modules/query_index/data/entities.ts +1 -0
  323. package/src/modules/query_index/lib/engine.ts +11 -5
  324. package/src/modules/query_index/migrations/.snapshot-open-mercato.json +11 -0
  325. package/src/modules/query_index/migrations/Migration20260611103000_query_index.ts +29 -0
  326. package/src/modules/resources/api/resources.ts +2 -3
  327. package/src/modules/sales/api/documents/factory.ts +2 -2
  328. package/src/modules/sales/commands/documents.ts +7 -5
  329. package/src/modules/sales/components/documents/SalesDocumentsTable.tsx +2 -1
  330. package/src/modules/sales/components/documents/salesDocumentsColumns.ts +6 -0
  331. package/src/modules/staff/AGENTS.md +1 -1
  332. package/src/modules/staff/api/team-members.ts +9 -2
  333. package/src/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.ts +31 -1
  334. package/src/modules/staff/backend/staff/team-members/[id]/page.tsx +18 -8
  335. package/src/modules/staff/commands/team-members.ts +5 -2
  336. package/src/modules/staff/components/TeamMemberForm.tsx +4 -1
  337. package/src/modules/staff/i18n/de.json +1 -0
  338. package/src/modules/staff/i18n/en.json +1 -0
  339. package/src/modules/staff/i18n/es.json +1 -0
  340. package/src/modules/staff/i18n/pl.json +1 -0
  341. package/src/modules/staff/lib/scheduleSwitch.ts +46 -0
  342. package/src/modules/sync_excel/api/import/route.ts +1 -1
  343. package/src/modules/workflows/api/definitions/route.ts +3 -2
  344. package/src/modules/workflows/backend/definitions/create/page.tsx +1 -2
  345. package/src/modules/workflows/backend/definitions/visual-editor/page.tsx +1 -2
  346. package/src/modules/workflows/components/DefinitionTriggersEditor.tsx +1 -2
  347. package/src/modules/workflows/components/NodeEditDialog.tsx +1 -4
  348. package/src/modules/workflows/components/NodeEditDialogCrudForm.tsx +4 -7
  349. package/src/modules/workflows/components/WorkflowGraphImpl.tsx +1 -2
  350. package/src/modules/workflows/components/fields/FormFieldArrayEditor.tsx +2 -3
@@ -5,7 +5,7 @@ import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } f
5
5
  import { Badge } from "@open-mercato/ui/primitives/badge";
6
6
  import { Alert, AlertDescription } from "@open-mercato/ui/primitives/alert";
7
7
  import { Button } from "@open-mercato/ui/primitives/button";
8
- import { Info, Trash2 } from "lucide-react";
8
+ import { Trash2 } from "lucide-react";
9
9
  import { CrudForm } from "@open-mercato/ui/backend/CrudForm";
10
10
  import { JsonBuilder } from "@open-mercato/ui/backend/JsonBuilder";
11
11
  import { FormFieldArrayEditor } from "./fields/FormFieldArrayEditor.js";
@@ -70,10 +70,7 @@ function NodeEditDialogCrudForm({ node, isOpen, onClose, onSave, onDelete }) {
70
70
  id: "info",
71
71
  column: 1,
72
72
  bare: true,
73
- component: () => /* @__PURE__ */ jsxs(Alert, { variant: "default", className: "border-blue-200 bg-blue-50", children: [
74
- /* @__PURE__ */ jsx(Info, { className: "size-4" }),
75
- /* @__PURE__ */ jsx(AlertDescription, { children: "End nodes cannot be edited. They mark the completion of the workflow." })
76
- ] })
73
+ component: () => /* @__PURE__ */ jsx(Alert, { variant: "info", children: /* @__PURE__ */ jsx(AlertDescription, { children: "End nodes cannot be edited. They mark the completion of the workflow." }) })
77
74
  }
78
75
  ];
79
76
  }
@@ -83,10 +80,7 @@ function NodeEditDialogCrudForm({ node, isOpen, onClose, onSave, onDelete }) {
83
80
  id: "info",
84
81
  column: 1,
85
82
  bare: true,
86
- component: () => /* @__PURE__ */ jsxs(Alert, { variant: "default", className: "border-blue-200 bg-blue-50 mb-4", children: [
87
- /* @__PURE__ */ jsx(Info, { className: "size-4" }),
88
- /* @__PURE__ */ jsx(AlertDescription, { children: "Start nodes mark the beginning of the workflow. You can define pre-conditions that must pass before the workflow can be started." })
89
- ] })
83
+ component: () => /* @__PURE__ */ jsx(Alert, { variant: "info", className: "mb-4", children: /* @__PURE__ */ jsx(AlertDescription, { children: "Start nodes mark the beginning of the workflow. You can define pre-conditions that must pass before the workflow can be started." }) })
90
84
  },
91
85
  {
92
86
  id: "preConditions",
@@ -395,10 +389,7 @@ function NodeEditDialogCrudForm({ node, isOpen, onClose, onSave, onDelete }) {
395
389
  ] })
396
390
  ] }),
397
391
  /* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto min-h-0 px-6", children: [
398
- showJsonSchemaWarning && /* @__PURE__ */ jsxs(Alert, { variant: "default", className: "border-blue-200 bg-blue-50 mb-4", children: [
399
- /* @__PURE__ */ jsx(Info, { className: "size-4" }),
400
- /* @__PURE__ */ jsx(AlertDescription, { className: "text-xs", children: 'This form uses JSON Schema format. Fields have been converted for visual editing. When you save, it will be converted to the simplified format. To preserve the original JSON Schema, edit it in the "Advanced Configuration (JSON)" section.' })
401
- ] }),
392
+ showJsonSchemaWarning && /* @__PURE__ */ jsx(Alert, { variant: "info", className: "mb-4", children: /* @__PURE__ */ jsx(AlertDescription, { className: "text-xs", children: 'This form uses JSON Schema format. Fields have been converted for visual editing. When you save, it will be converted to the simplified format. To preserve the original JSON Schema, edit it in the "Advanced Configuration (JSON)" section.' }) }),
402
393
  /* @__PURE__ */ jsx(
403
394
  CrudForm,
404
395
  {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/workflows/components/NodeEditDialogCrudForm.tsx"],
4
- "sourcesContent": ["'use client'\n\nimport { Node } from '@xyflow/react'\nimport { useState, useEffect, useCallback, useMemo } from 'react'\nimport { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from '@open-mercato/ui/primitives/dialog'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { Alert, AlertDescription } from '@open-mercato/ui/primitives/alert'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Info, Trash2 } from 'lucide-react'\nimport { CrudForm, type CrudFormGroup, type CrudField, type CrudCustomFieldRenderProps } from '@open-mercato/ui/backend/CrudForm'\nimport { JsonBuilder } from '@open-mercato/ui/backend/JsonBuilder'\nimport { FormFieldArrayEditor } from './fields/FormFieldArrayEditor'\nimport { ActivityArrayEditor } from './fields/ActivityArrayEditor'\nimport { MappingArrayEditor } from './fields/MappingArrayEditor'\nimport { WorkflowSelectorField } from './fields/WorkflowSelectorField'\nimport { StartPreConditionsEditor } from './fields/StartPreConditionsEditor'\nimport { nodeToFormValues, formValuesToNodeUpdates, isJsonSchemaFormat, type NodeFormValues } from '../lib/nodeFormTransforms'\nimport { sanitizeId } from '../lib/graph-utils'\n\n/**\n * JsonConfigEditor - Custom field wrapper for JsonBuilder\n */\nfunction JsonConfigEditor({ value, setValue, disabled }: CrudCustomFieldRenderProps) {\n return (\n <JsonBuilder\n value={value || {}}\n onChange={setValue}\n disabled={disabled}\n />\n )\n}\n\nexport interface NodeEditDialogCrudFormProps {\n node: Node | null\n isOpen: boolean\n onClose: () => void\n onSave: (nodeId: string, updates: Partial<Node['data']>) => void\n onDelete?: (nodeId: string) => void\n}\n\n/**\n * NodeEditDialogCrudForm - CrudForm-based modal dialog for editing step properties\n *\n * Migrated from NodeEditDialog to use CrudForm for:\n * - UI coherence with other admin forms\n * - Custom fields support (future enhancement)\n * - Standardized validation and error handling\n * - Consistent keyboard shortcuts\n *\n * Handles 7 node types with dynamic groups:\n * - start: Non-editable (alert only)\n * - end: Non-editable (alert only)\n * - userTask: Assignment fields + form builder\n * - automated: Activity type + activities array\n * - subWorkflow: Workflow selector + input/output mappings\n * - waitForSignal: Signal name + timeout\n * - decision: Basic fields only\n */\nexport function NodeEditDialogCrudForm({ node, isOpen, onClose, onSave, onDelete }: NodeEditDialogCrudFormProps) {\n const [initialValues, setInitialValues] = useState<Partial<NodeFormValues>>({})\n const [showJsonSchemaWarning, setShowJsonSchemaWarning] = useState(false)\n\n // Load node data when dialog opens\n useEffect(() => {\n if (node && isOpen) {\n const values = nodeToFormValues(node)\n setInitialValues(values)\n setShowJsonSchemaWarning(isJsonSchemaFormat(node))\n }\n }, [node, isOpen])\n\n const handleSubmit = useCallback(async (values: Record<string, unknown>) => {\n if (!node) return\n\n // Validate and sanitize step ID\n const sanitizedId = sanitizeId(node.id)\n if (sanitizedId !== node.id) {\n if (typeof window !== 'undefined') {\n window.alert(\n `\u26A0\uFE0F Step ID was sanitized from \"${node.id}\" to \"${sanitizedId}\" to match schema requirements (lowercase letters, numbers, hyphens, and underscores only).`\n )\n }\n }\n\n try {\n const updates = formValuesToNodeUpdates(values as unknown as NodeFormValues, node)\n onSave(node.id, updates)\n onClose()\n } catch (error) {\n // Error will be displayed in form (e.g., invalid JSON)\n throw error\n }\n }, [node, onSave, onClose])\n\n const handleDelete = useCallback(() => {\n if (!node || !onDelete) return\n onDelete(node.id)\n }, [node, onDelete])\n\n const handleKeyDown = useCallback((e: React.KeyboardEvent) => {\n if (e.key === 'Escape') {\n onClose()\n }\n }, [onClose])\n\n // Dynamic groups based on node type\n const groups: CrudFormGroup[] = useMemo(() => {\n if (!node) return []\n\n // End nodes are non-editable\n if (node.type === 'end') {\n return [\n {\n id: 'info',\n column: 1,\n bare: true,\n component: () => (\n <Alert variant=\"default\" className=\"border-blue-200 bg-blue-50\">\n <Info className=\"size-4\" />\n <AlertDescription>\n End nodes cannot be edited. They mark the completion of the workflow.\n </AlertDescription>\n </Alert>\n ),\n },\n ]\n }\n\n // Start nodes: allow editing pre-conditions\n if (node.type === 'start') {\n return [\n {\n id: 'info',\n column: 1,\n bare: true,\n component: () => (\n <Alert variant=\"default\" className=\"border-blue-200 bg-blue-50 mb-4\">\n <Info className=\"size-4\" />\n <AlertDescription>\n Start nodes mark the beginning of the workflow. You can define pre-conditions that must pass before the workflow can be started.\n </AlertDescription>\n </Alert>\n ),\n },\n {\n id: 'preConditions',\n title: 'Pre-Conditions',\n column: 1,\n description: 'Business rules that must pass before the workflow can start',\n fields: ['preConditions'],\n },\n ]\n }\n\n const baseGroups: CrudFormGroup[] = [\n {\n id: 'basic',\n title: 'Basic Information',\n column: 1,\n fields: ['stepName', 'description', 'timeout'],\n },\n ]\n\n // UserTask specific groups\n if (node.type === 'userTask') {\n return [\n ...baseGroups,\n {\n id: 'userTask',\n title: 'User Task Configuration',\n column: 1,\n fields: ['assignedTo', 'assignedToRoles', 'formKey'],\n },\n {\n id: 'formFields',\n title: 'Form Fields',\n column: 1,\n description: 'Define the form structure for this user task',\n fields: ['formFields'],\n },\n {\n id: 'advanced',\n title: 'Advanced Configuration',\n column: 1,\n description: 'Additional JSON configuration (userTaskConfig, retryPolicy, etc.)',\n fields: ['advancedConfig'],\n },\n ]\n }\n\n // Automated specific groups\n if (node.type === 'automated') {\n return [\n ...baseGroups,\n {\n id: 'automated',\n title: 'Automated Task Configuration',\n column: 1,\n fields: ['activityType', 'activityId'],\n },\n {\n id: 'stepActivities',\n title: 'Step Activities',\n column: 1,\n description: 'Activities executed as part of this automated step',\n fields: ['stepActivities'],\n },\n {\n id: 'advanced',\n title: 'Advanced Configuration',\n column: 1,\n description: 'Additional JSON configuration (retryPolicy, etc.)',\n fields: ['advancedConfig'],\n },\n ]\n }\n\n // SubWorkflow specific groups\n if (node.type === 'subWorkflow') {\n return [\n ...baseGroups,\n {\n id: 'subWorkflow',\n title: 'Sub-Workflow Configuration',\n column: 1,\n fields: ['subWorkflowId', 'subWorkflowVersion'],\n },\n {\n id: 'mappings',\n title: 'Data Mappings',\n column: 1,\n description: 'Map data between parent and sub-workflow',\n fields: ['inputMappings', 'outputMappings'],\n },\n {\n id: 'advanced',\n title: 'Advanced Configuration',\n column: 1,\n description: 'Additional JSON configuration',\n fields: ['advancedConfig'],\n },\n ]\n }\n\n // WaitForSignal specific groups\n if (node.type === 'waitForSignal') {\n return [\n ...baseGroups,\n {\n id: 'signal',\n title: 'Signal Configuration',\n column: 1,\n fields: ['signalName', 'signalTimeout'],\n },\n {\n id: 'advanced',\n title: 'Advanced Configuration',\n column: 1,\n description: 'Additional JSON configuration',\n fields: ['advancedConfig'],\n },\n ]\n }\n\n // Decision and other types: just basic fields + advanced\n return [\n ...baseGroups,\n {\n id: 'advanced',\n title: 'Advanced Configuration',\n column: 1,\n description: 'Additional JSON configuration',\n fields: ['advancedConfig'],\n },\n ]\n }, [node])\n\n // Define all possible form fields (only relevant ones are used based on groups)\n const fields: CrudField[] = useMemo(() => [\n // Basic fields\n {\n id: 'stepName',\n label: 'Step Name',\n type: 'text',\n placeholder: 'Enter step name',\n required: true,\n description: 'Display name for this step',\n },\n {\n id: 'description',\n label: 'Description',\n type: 'textarea',\n placeholder: 'Enter step description',\n description: 'Optional description of what this step does',\n },\n {\n id: 'timeout',\n label: 'Timeout',\n type: 'text',\n placeholder: 'PT30S or 30000',\n description: 'ISO 8601 duration (e.g., PT30S) or milliseconds',\n },\n\n // UserTask fields\n {\n id: 'assignedTo',\n label: 'Assigned To',\n type: 'text',\n placeholder: 'user@example.com or userId',\n description: 'User email or ID to assign this task to',\n },\n {\n id: 'assignedToRoles',\n label: 'Assigned To Roles',\n type: 'text',\n placeholder: 'admin, manager',\n description: 'Comma-separated list of roles that can claim this task',\n },\n {\n id: 'formKey',\n label: 'Form Key',\n type: 'text',\n placeholder: 'approval_form',\n description: 'Optional form key for external form rendering',\n },\n {\n id: 'formFields',\n label: 'Form Fields',\n type: 'custom',\n component: (props) => (\n <FormFieldArrayEditor\n {...props}\n value={props.value as any}\n isJsonSchemaFormat={showJsonSchemaWarning}\n />\n ),\n },\n\n // Automated fields\n {\n id: 'activityType',\n label: 'Activity Type',\n type: 'select',\n options: [\n { value: 'SEND_EMAIL', label: 'Send Email' },\n { value: 'CALL_API', label: 'Call API' },\n { value: 'UPDATE_ENTITY', label: 'Update Entity' },\n { value: 'EMIT_EVENT', label: 'Emit Event' },\n { value: 'CALL_WEBHOOK', label: 'Call Webhook' },\n { value: 'EXECUTE_FUNCTION', label: 'Execute Function' },\n { value: 'WAIT', label: 'Wait' },\n ],\n description: 'Type of activity to execute',\n },\n {\n id: 'activityId',\n label: 'Activity ID',\n type: 'text',\n placeholder: 'send_welcome_email',\n description: 'Unique identifier for this activity',\n },\n {\n id: 'stepActivities',\n label: 'Step Activities',\n type: 'custom',\n component: (props) => <ActivityArrayEditor {...props} value={props.value as any} />,\n },\n\n // SubWorkflow fields\n {\n id: 'subWorkflowId',\n label: 'Sub-Workflow',\n type: 'custom',\n component: (props) => <WorkflowSelectorField {...props} value={props.value as any} />,\n },\n {\n id: 'subWorkflowVersion',\n label: 'Version',\n type: 'number',\n placeholder: '1',\n description: 'Specific version of the sub-workflow to invoke',\n },\n {\n id: 'inputMappings',\n label: 'Input Mappings',\n type: 'custom',\n component: (props) => (\n <MappingArrayEditor\n {...props}\n value={props.value as any}\n label=\"Input Mappings\"\n description=\"Map parent workflow data to sub-workflow input\"\n />\n ),\n },\n {\n id: 'outputMappings',\n label: 'Output Mappings',\n type: 'custom',\n component: (props) => (\n <MappingArrayEditor\n {...props}\n value={props.value as any}\n label=\"Output Mappings\"\n description=\"Map sub-workflow output back to parent workflow\"\n />\n ),\n },\n\n // WaitForSignal fields\n {\n id: 'signalName',\n label: 'Signal Name',\n type: 'text',\n placeholder: 'approval_received',\n description: 'Name of the signal to wait for',\n },\n {\n id: 'signalTimeout',\n label: 'Signal Timeout',\n type: 'text',\n placeholder: 'PT5M',\n description: 'How long to wait for the signal (ISO 8601 duration)',\n },\n\n // Advanced configuration\n {\n id: 'advancedConfig',\n label: 'Advanced Configuration (JSON)',\n type: 'custom',\n description: 'Additional JSON configuration merged with the step data',\n component: (props) => <JsonConfigEditor {...props} />,\n },\n\n // Start node pre-conditions\n {\n id: 'preConditions',\n label: 'Pre-Conditions',\n type: 'custom',\n description: 'Business rules that must pass before the workflow can start',\n component: (props) => <StartPreConditionsEditor {...props} value={props.value as any} />,\n },\n ], [showJsonSchemaWarning])\n\n if (!isOpen || !node) return null\n\n const nodeType = node.type || 'unknown'\n const nodeTypeLabel = nodeType.charAt(0).toUpperCase() + nodeType.slice(1).replace(/([A-Z])/g, ' $1')\n\n const canDelete = !!onDelete\n\n return (\n <Dialog open={isOpen} onOpenChange={onClose}>\n <DialogContent\n className=\"sm:max-w-7xl max-h-[90vh] overflow-hidden flex flex-col !p-0 [&_.grid]:!grid-cols-1\"\n onKeyDown={handleKeyDown}\n >\n <DialogHeader className=\"flex-shrink-0 p-6 pb-4 border-b border-border/70\">\n <div className=\"flex items-center gap-2 mb-2\">\n <DialogTitle>Edit Step</DialogTitle>\n <Badge variant=\"secondary\" className=\"text-xs\">\n {nodeTypeLabel}\n </Badge>\n </div>\n <div className=\"space-y-1\">\n <DialogDescription>\n Configure step properties and behavior\n </DialogDescription>\n <div className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <span className=\"font-medium\">ID:</span>\n <code className=\"px-1.5 py-0.5 rounded bg-muted font-mono\">{node.id}</code>\n </div>\n </div>\n </DialogHeader>\n\n <div className=\"flex-1 overflow-y-auto min-h-0 px-6\">\n {/* JSON Schema Conversion Warning */}\n {showJsonSchemaWarning && (\n <Alert variant=\"default\" className=\"border-blue-200 bg-blue-50 mb-4\">\n <Info className=\"size-4\" />\n <AlertDescription className=\"text-xs\">\n This form uses JSON Schema format. Fields have been converted for visual editing.\n When you save, it will be converted to the simplified format. To preserve the original JSON Schema,\n edit it in the &#34;Advanced Configuration (JSON)&#34; section.\n </AlertDescription>\n </Alert>\n )}\n\n <CrudForm\n fields={fields}\n groups={groups}\n initialValues={initialValues}\n onSubmit={handleSubmit}\n embedded={true}\n submitLabel=\"Save Step\"\n extraActions={\n canDelete ? (\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={handleDelete}\n className=\"text-red-600 border-red-200 hover:bg-red-50\"\n >\n <Trash2 className=\"size-4 mr-2\" />\n Delete Step\n </Button>\n ) : undefined\n }\n />\n </div>\n </DialogContent>\n </Dialog>\n )\n}\n"],
5
- "mappings": ";AAwBI,cA6FQ,YA7FR;AArBJ,SAAS,UAAU,WAAW,aAAa,eAAe;AAC1D,SAAS,QAAQ,eAAe,cAAc,aAAa,yBAAyB;AACpF,SAAS,aAAa;AACtB,SAAS,OAAO,wBAAwB;AACxC,SAAS,cAAc;AACvB,SAAS,MAAM,cAAc;AAC7B,SAAS,gBAAqF;AAC9F,SAAS,mBAAmB;AAC5B,SAAS,4BAA4B;AACrC,SAAS,2BAA2B;AACpC,SAAS,0BAA0B;AACnC,SAAS,6BAA6B;AACtC,SAAS,gCAAgC;AACzC,SAAS,kBAAkB,yBAAyB,0BAA+C;AACnG,SAAS,kBAAkB;AAK3B,SAAS,iBAAiB,EAAE,OAAO,UAAU,SAAS,GAA+B;AACnF,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO,SAAS,CAAC;AAAA,MACjB,UAAU;AAAA,MACV;AAAA;AAAA,EACF;AAEJ;AA4BO,SAAS,uBAAuB,EAAE,MAAM,QAAQ,SAAS,QAAQ,SAAS,GAAgC;AAC/G,QAAM,CAAC,eAAe,gBAAgB,IAAI,SAAkC,CAAC,CAAC;AAC9E,QAAM,CAAC,uBAAuB,wBAAwB,IAAI,SAAS,KAAK;AAGxE,YAAU,MAAM;AACd,QAAI,QAAQ,QAAQ;AAClB,YAAM,SAAS,iBAAiB,IAAI;AACpC,uBAAiB,MAAM;AACvB,+BAAyB,mBAAmB,IAAI,CAAC;AAAA,IACnD;AAAA,EACF,GAAG,CAAC,MAAM,MAAM,CAAC;AAEjB,QAAM,eAAe,YAAY,OAAO,WAAoC;AAC1E,QAAI,CAAC,KAAM;AAGX,UAAM,cAAc,WAAW,KAAK,EAAE;AACtC,QAAI,gBAAgB,KAAK,IAAI;AAC3B,UAAI,OAAO,WAAW,aAAa;AACjC,eAAO;AAAA,UACL,4CAAkC,KAAK,EAAE,SAAS,WAAW;AAAA,QAC/D;AAAA,MACF;AAAA,IACF;AAEA,QAAI;AACF,YAAM,UAAU,wBAAwB,QAAqC,IAAI;AACjF,aAAO,KAAK,IAAI,OAAO;AACvB,cAAQ;AAAA,IACV,SAAS,OAAO;AAEd,YAAM;AAAA,IACR;AAAA,EACF,GAAG,CAAC,MAAM,QAAQ,OAAO,CAAC;AAE1B,QAAM,eAAe,YAAY,MAAM;AACrC,QAAI,CAAC,QAAQ,CAAC,SAAU;AACxB,aAAS,KAAK,EAAE;AAAA,EAClB,GAAG,CAAC,MAAM,QAAQ,CAAC;AAEnB,QAAM,gBAAgB,YAAY,CAAC,MAA2B;AAC5D,QAAI,EAAE,QAAQ,UAAU;AACtB,cAAQ;AAAA,IACV;AAAA,EACF,GAAG,CAAC,OAAO,CAAC;AAGZ,QAAM,SAA0B,QAAQ,MAAM;AAC5C,QAAI,CAAC,KAAM,QAAO,CAAC;AAGnB,QAAI,KAAK,SAAS,OAAO;AACvB,aAAO;AAAA,QACL;AAAA,UACE,IAAI;AAAA,UACJ,QAAQ;AAAA,UACR,MAAM;AAAA,UACN,WAAW,MACT,qBAAC,SAAM,SAAQ,WAAU,WAAU,8BACjC;AAAA,gCAAC,QAAK,WAAU,UAAS;AAAA,YACzB,oBAAC,oBAAiB,mFAElB;AAAA,aACF;AAAA,QAEJ;AAAA,MACF;AAAA,IACF;AAGA,QAAI,KAAK,SAAS,SAAS;AACzB,aAAO;AAAA,QACL;AAAA,UACE,IAAI;AAAA,UACJ,QAAQ;AAAA,UACR,MAAM;AAAA,UACN,WAAW,MACT,qBAAC,SAAM,SAAQ,WAAU,WAAU,mCACjC;AAAA,gCAAC,QAAK,WAAU,UAAS;AAAA,YACzB,oBAAC,oBAAiB,8IAElB;AAAA,aACF;AAAA,QAEJ;AAAA,QACA;AAAA,UACE,IAAI;AAAA,UACJ,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,QAAQ,CAAC,eAAe;AAAA,QAC1B;AAAA,MACF;AAAA,IACF;AAEA,UAAM,aAA8B;AAAA,MAClC;AAAA,QACE,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,QAAQ,CAAC,YAAY,eAAe,SAAS;AAAA,MAC/C;AAAA,IACF;AAGA,QAAI,KAAK,SAAS,YAAY;AAC5B,aAAO;AAAA,QACL,GAAG;AAAA,QACH;AAAA,UACE,IAAI;AAAA,UACJ,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,QAAQ,CAAC,cAAc,mBAAmB,SAAS;AAAA,QACrD;AAAA,QACA;AAAA,UACE,IAAI;AAAA,UACJ,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,QAAQ,CAAC,YAAY;AAAA,QACvB;AAAA,QACA;AAAA,UACE,IAAI;AAAA,UACJ,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,QAAQ,CAAC,gBAAgB;AAAA,QAC3B;AAAA,MACF;AAAA,IACF;AAGA,QAAI,KAAK,SAAS,aAAa;AAC7B,aAAO;AAAA,QACL,GAAG;AAAA,QACH;AAAA,UACE,IAAI;AAAA,UACJ,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,QAAQ,CAAC,gBAAgB,YAAY;AAAA,QACvC;AAAA,QACA;AAAA,UACE,IAAI;AAAA,UACJ,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,QAAQ,CAAC,gBAAgB;AAAA,QAC3B;AAAA,QACA;AAAA,UACE,IAAI;AAAA,UACJ,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,QAAQ,CAAC,gBAAgB;AAAA,QAC3B;AAAA,MACF;AAAA,IACF;AAGA,QAAI,KAAK,SAAS,eAAe;AAC/B,aAAO;AAAA,QACL,GAAG;AAAA,QACH;AAAA,UACE,IAAI;AAAA,UACJ,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,QAAQ,CAAC,iBAAiB,oBAAoB;AAAA,QAChD;AAAA,QACA;AAAA,UACE,IAAI;AAAA,UACJ,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,QAAQ,CAAC,iBAAiB,gBAAgB;AAAA,QAC5C;AAAA,QACA;AAAA,UACE,IAAI;AAAA,UACJ,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,QAAQ,CAAC,gBAAgB;AAAA,QAC3B;AAAA,MACF;AAAA,IACF;AAGA,QAAI,KAAK,SAAS,iBAAiB;AACjC,aAAO;AAAA,QACL,GAAG;AAAA,QACH;AAAA,UACE,IAAI;AAAA,UACJ,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,QAAQ,CAAC,cAAc,eAAe;AAAA,QACxC;AAAA,QACA;AAAA,UACE,IAAI;AAAA,UACJ,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,QAAQ,CAAC,gBAAgB;AAAA,QAC3B;AAAA,MACF;AAAA,IACF;AAGA,WAAO;AAAA,MACL,GAAG;AAAA,MACH;AAAA,QACE,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,aAAa;AAAA,QACb,QAAQ,CAAC,gBAAgB;AAAA,MAC3B;AAAA,IACF;AAAA,EACF,GAAG,CAAC,IAAI,CAAC;AAGT,QAAM,SAAsB,QAAQ,MAAM;AAAA;AAAA,IAExC;AAAA,MACE,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,MACV,aAAa;AAAA,IACf;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,aAAa;AAAA,IACf;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,aAAa;AAAA,IACf;AAAA;AAAA,IAGA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,aAAa;AAAA,IACf;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,aAAa;AAAA,IACf;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,aAAa;AAAA,IACf;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,WAAW,CAAC,UACV;AAAA,QAAC;AAAA;AAAA,UACE,GAAG;AAAA,UACJ,OAAO,MAAM;AAAA,UACb,oBAAoB;AAAA;AAAA,MACtB;AAAA,IAEJ;AAAA;AAAA,IAGA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,QACP,EAAE,OAAO,cAAc,OAAO,aAAa;AAAA,QAC3C,EAAE,OAAO,YAAY,OAAO,WAAW;AAAA,QACvC,EAAE,OAAO,iBAAiB,OAAO,gBAAgB;AAAA,QACjD,EAAE,OAAO,cAAc,OAAO,aAAa;AAAA,QAC3C,EAAE,OAAO,gBAAgB,OAAO,eAAe;AAAA,QAC/C,EAAE,OAAO,oBAAoB,OAAO,mBAAmB;AAAA,QACvD,EAAE,OAAO,QAAQ,OAAO,OAAO;AAAA,MACjC;AAAA,MACA,aAAa;AAAA,IACf;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,aAAa;AAAA,IACf;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,WAAW,CAAC,UAAU,oBAAC,uBAAqB,GAAG,OAAO,OAAO,MAAM,OAAc;AAAA,IACnF;AAAA;AAAA,IAGA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,WAAW,CAAC,UAAU,oBAAC,yBAAuB,GAAG,OAAO,OAAO,MAAM,OAAc;AAAA,IACrF;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,aAAa;AAAA,IACf;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,WAAW,CAAC,UACV;AAAA,QAAC;AAAA;AAAA,UACE,GAAG;AAAA,UACJ,OAAO,MAAM;AAAA,UACb,OAAM;AAAA,UACN,aAAY;AAAA;AAAA,MACd;AAAA,IAEJ;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,WAAW,CAAC,UACV;AAAA,QAAC;AAAA;AAAA,UACE,GAAG;AAAA,UACJ,OAAO,MAAM;AAAA,UACb,OAAM;AAAA,UACN,aAAY;AAAA;AAAA,MACd;AAAA,IAEJ;AAAA;AAAA,IAGA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,aAAa;AAAA,IACf;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,aAAa;AAAA,IACf;AAAA;AAAA,IAGA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,WAAW,CAAC,UAAU,oBAAC,oBAAkB,GAAG,OAAO;AAAA,IACrD;AAAA;AAAA,IAGA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,WAAW,CAAC,UAAU,oBAAC,4BAA0B,GAAG,OAAO,OAAO,MAAM,OAAc;AAAA,IACxF;AAAA,EACF,GAAG,CAAC,qBAAqB,CAAC;AAE1B,MAAI,CAAC,UAAU,CAAC,KAAM,QAAO;AAE7B,QAAM,WAAW,KAAK,QAAQ;AAC9B,QAAM,gBAAgB,SAAS,OAAO,CAAC,EAAE,YAAY,IAAI,SAAS,MAAM,CAAC,EAAE,QAAQ,YAAY,KAAK;AAEpG,QAAM,YAAY,CAAC,CAAC;AAEpB,SACE,oBAAC,UAAO,MAAM,QAAQ,cAAc,SAClC;AAAA,IAAC;AAAA;AAAA,MACC,WAAU;AAAA,MACV,WAAW;AAAA,MAEX;AAAA,6BAAC,gBAAa,WAAU,oDACtB;AAAA,+BAAC,SAAI,WAAU,gCACb;AAAA,gCAAC,eAAY,uBAAS;AAAA,YACtB,oBAAC,SAAM,SAAQ,aAAY,WAAU,WAClC,yBACH;AAAA,aACF;AAAA,UACA,qBAAC,SAAI,WAAU,aACb;AAAA,gCAAC,qBAAkB,oDAEnB;AAAA,YACA,qBAAC,SAAI,WAAU,yDACb;AAAA,kCAAC,UAAK,WAAU,eAAc,iBAAG;AAAA,cACjC,oBAAC,UAAK,WAAU,4CAA4C,eAAK,IAAG;AAAA,eACtE;AAAA,aACF;AAAA,WACF;AAAA,QAEA,qBAAC,SAAI,WAAU,uCAEZ;AAAA,mCACC,qBAAC,SAAM,SAAQ,WAAU,WAAU,mCACjC;AAAA,gCAAC,QAAK,WAAU,UAAS;AAAA,YACzB,oBAAC,oBAAiB,WAAU,WAAU,2PAItC;AAAA,aACF;AAAA,UAGF;AAAA,YAAC;AAAA;AAAA,cACC;AAAA,cACA;AAAA,cACA;AAAA,cACA,UAAU;AAAA,cACV,UAAU;AAAA,cACV,aAAY;AAAA,cACZ,cACE,YACE;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAK;AAAA,kBACL,SAAQ;AAAA,kBACR,SAAS;AAAA,kBACT,WAAU;AAAA,kBAEV;AAAA,wCAAC,UAAO,WAAU,eAAc;AAAA,oBAAE;AAAA;AAAA;AAAA,cAEpC,IACE;AAAA;AAAA,UAER;AAAA,WACF;AAAA;AAAA;AAAA,EACF,GACF;AAEJ;",
4
+ "sourcesContent": ["'use client'\n\nimport { Node } from '@xyflow/react'\nimport { useState, useEffect, useCallback, useMemo } from 'react'\nimport { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from '@open-mercato/ui/primitives/dialog'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { Alert, AlertDescription } from '@open-mercato/ui/primitives/alert'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Trash2 } from 'lucide-react'\nimport { CrudForm, type CrudFormGroup, type CrudField, type CrudCustomFieldRenderProps } from '@open-mercato/ui/backend/CrudForm'\nimport { JsonBuilder } from '@open-mercato/ui/backend/JsonBuilder'\nimport { FormFieldArrayEditor } from './fields/FormFieldArrayEditor'\nimport { ActivityArrayEditor } from './fields/ActivityArrayEditor'\nimport { MappingArrayEditor } from './fields/MappingArrayEditor'\nimport { WorkflowSelectorField } from './fields/WorkflowSelectorField'\nimport { StartPreConditionsEditor } from './fields/StartPreConditionsEditor'\nimport { nodeToFormValues, formValuesToNodeUpdates, isJsonSchemaFormat, type NodeFormValues } from '../lib/nodeFormTransforms'\nimport { sanitizeId } from '../lib/graph-utils'\n\n/**\n * JsonConfigEditor - Custom field wrapper for JsonBuilder\n */\nfunction JsonConfigEditor({ value, setValue, disabled }: CrudCustomFieldRenderProps) {\n return (\n <JsonBuilder\n value={value || {}}\n onChange={setValue}\n disabled={disabled}\n />\n )\n}\n\nexport interface NodeEditDialogCrudFormProps {\n node: Node | null\n isOpen: boolean\n onClose: () => void\n onSave: (nodeId: string, updates: Partial<Node['data']>) => void\n onDelete?: (nodeId: string) => void\n}\n\n/**\n * NodeEditDialogCrudForm - CrudForm-based modal dialog for editing step properties\n *\n * Migrated from NodeEditDialog to use CrudForm for:\n * - UI coherence with other admin forms\n * - Custom fields support (future enhancement)\n * - Standardized validation and error handling\n * - Consistent keyboard shortcuts\n *\n * Handles 7 node types with dynamic groups:\n * - start: Non-editable (alert only)\n * - end: Non-editable (alert only)\n * - userTask: Assignment fields + form builder\n * - automated: Activity type + activities array\n * - subWorkflow: Workflow selector + input/output mappings\n * - waitForSignal: Signal name + timeout\n * - decision: Basic fields only\n */\nexport function NodeEditDialogCrudForm({ node, isOpen, onClose, onSave, onDelete }: NodeEditDialogCrudFormProps) {\n const [initialValues, setInitialValues] = useState<Partial<NodeFormValues>>({})\n const [showJsonSchemaWarning, setShowJsonSchemaWarning] = useState(false)\n\n // Load node data when dialog opens\n useEffect(() => {\n if (node && isOpen) {\n const values = nodeToFormValues(node)\n setInitialValues(values)\n setShowJsonSchemaWarning(isJsonSchemaFormat(node))\n }\n }, [node, isOpen])\n\n const handleSubmit = useCallback(async (values: Record<string, unknown>) => {\n if (!node) return\n\n // Validate and sanitize step ID\n const sanitizedId = sanitizeId(node.id)\n if (sanitizedId !== node.id) {\n if (typeof window !== 'undefined') {\n window.alert(\n `\u26A0\uFE0F Step ID was sanitized from \"${node.id}\" to \"${sanitizedId}\" to match schema requirements (lowercase letters, numbers, hyphens, and underscores only).`\n )\n }\n }\n\n try {\n const updates = formValuesToNodeUpdates(values as unknown as NodeFormValues, node)\n onSave(node.id, updates)\n onClose()\n } catch (error) {\n // Error will be displayed in form (e.g., invalid JSON)\n throw error\n }\n }, [node, onSave, onClose])\n\n const handleDelete = useCallback(() => {\n if (!node || !onDelete) return\n onDelete(node.id)\n }, [node, onDelete])\n\n const handleKeyDown = useCallback((e: React.KeyboardEvent) => {\n if (e.key === 'Escape') {\n onClose()\n }\n }, [onClose])\n\n // Dynamic groups based on node type\n const groups: CrudFormGroup[] = useMemo(() => {\n if (!node) return []\n\n // End nodes are non-editable\n if (node.type === 'end') {\n return [\n {\n id: 'info',\n column: 1,\n bare: true,\n component: () => (\n <Alert variant=\"info\">\n <AlertDescription>\n End nodes cannot be edited. They mark the completion of the workflow.\n </AlertDescription>\n </Alert>\n ),\n },\n ]\n }\n\n // Start nodes: allow editing pre-conditions\n if (node.type === 'start') {\n return [\n {\n id: 'info',\n column: 1,\n bare: true,\n component: () => (\n <Alert variant=\"info\" className=\"mb-4\">\n <AlertDescription>\n Start nodes mark the beginning of the workflow. You can define pre-conditions that must pass before the workflow can be started.\n </AlertDescription>\n </Alert>\n ),\n },\n {\n id: 'preConditions',\n title: 'Pre-Conditions',\n column: 1,\n description: 'Business rules that must pass before the workflow can start',\n fields: ['preConditions'],\n },\n ]\n }\n\n const baseGroups: CrudFormGroup[] = [\n {\n id: 'basic',\n title: 'Basic Information',\n column: 1,\n fields: ['stepName', 'description', 'timeout'],\n },\n ]\n\n // UserTask specific groups\n if (node.type === 'userTask') {\n return [\n ...baseGroups,\n {\n id: 'userTask',\n title: 'User Task Configuration',\n column: 1,\n fields: ['assignedTo', 'assignedToRoles', 'formKey'],\n },\n {\n id: 'formFields',\n title: 'Form Fields',\n column: 1,\n description: 'Define the form structure for this user task',\n fields: ['formFields'],\n },\n {\n id: 'advanced',\n title: 'Advanced Configuration',\n column: 1,\n description: 'Additional JSON configuration (userTaskConfig, retryPolicy, etc.)',\n fields: ['advancedConfig'],\n },\n ]\n }\n\n // Automated specific groups\n if (node.type === 'automated') {\n return [\n ...baseGroups,\n {\n id: 'automated',\n title: 'Automated Task Configuration',\n column: 1,\n fields: ['activityType', 'activityId'],\n },\n {\n id: 'stepActivities',\n title: 'Step Activities',\n column: 1,\n description: 'Activities executed as part of this automated step',\n fields: ['stepActivities'],\n },\n {\n id: 'advanced',\n title: 'Advanced Configuration',\n column: 1,\n description: 'Additional JSON configuration (retryPolicy, etc.)',\n fields: ['advancedConfig'],\n },\n ]\n }\n\n // SubWorkflow specific groups\n if (node.type === 'subWorkflow') {\n return [\n ...baseGroups,\n {\n id: 'subWorkflow',\n title: 'Sub-Workflow Configuration',\n column: 1,\n fields: ['subWorkflowId', 'subWorkflowVersion'],\n },\n {\n id: 'mappings',\n title: 'Data Mappings',\n column: 1,\n description: 'Map data between parent and sub-workflow',\n fields: ['inputMappings', 'outputMappings'],\n },\n {\n id: 'advanced',\n title: 'Advanced Configuration',\n column: 1,\n description: 'Additional JSON configuration',\n fields: ['advancedConfig'],\n },\n ]\n }\n\n // WaitForSignal specific groups\n if (node.type === 'waitForSignal') {\n return [\n ...baseGroups,\n {\n id: 'signal',\n title: 'Signal Configuration',\n column: 1,\n fields: ['signalName', 'signalTimeout'],\n },\n {\n id: 'advanced',\n title: 'Advanced Configuration',\n column: 1,\n description: 'Additional JSON configuration',\n fields: ['advancedConfig'],\n },\n ]\n }\n\n // Decision and other types: just basic fields + advanced\n return [\n ...baseGroups,\n {\n id: 'advanced',\n title: 'Advanced Configuration',\n column: 1,\n description: 'Additional JSON configuration',\n fields: ['advancedConfig'],\n },\n ]\n }, [node])\n\n // Define all possible form fields (only relevant ones are used based on groups)\n const fields: CrudField[] = useMemo(() => [\n // Basic fields\n {\n id: 'stepName',\n label: 'Step Name',\n type: 'text',\n placeholder: 'Enter step name',\n required: true,\n description: 'Display name for this step',\n },\n {\n id: 'description',\n label: 'Description',\n type: 'textarea',\n placeholder: 'Enter step description',\n description: 'Optional description of what this step does',\n },\n {\n id: 'timeout',\n label: 'Timeout',\n type: 'text',\n placeholder: 'PT30S or 30000',\n description: 'ISO 8601 duration (e.g., PT30S) or milliseconds',\n },\n\n // UserTask fields\n {\n id: 'assignedTo',\n label: 'Assigned To',\n type: 'text',\n placeholder: 'user@example.com or userId',\n description: 'User email or ID to assign this task to',\n },\n {\n id: 'assignedToRoles',\n label: 'Assigned To Roles',\n type: 'text',\n placeholder: 'admin, manager',\n description: 'Comma-separated list of roles that can claim this task',\n },\n {\n id: 'formKey',\n label: 'Form Key',\n type: 'text',\n placeholder: 'approval_form',\n description: 'Optional form key for external form rendering',\n },\n {\n id: 'formFields',\n label: 'Form Fields',\n type: 'custom',\n component: (props) => (\n <FormFieldArrayEditor\n {...props}\n value={props.value as any}\n isJsonSchemaFormat={showJsonSchemaWarning}\n />\n ),\n },\n\n // Automated fields\n {\n id: 'activityType',\n label: 'Activity Type',\n type: 'select',\n options: [\n { value: 'SEND_EMAIL', label: 'Send Email' },\n { value: 'CALL_API', label: 'Call API' },\n { value: 'UPDATE_ENTITY', label: 'Update Entity' },\n { value: 'EMIT_EVENT', label: 'Emit Event' },\n { value: 'CALL_WEBHOOK', label: 'Call Webhook' },\n { value: 'EXECUTE_FUNCTION', label: 'Execute Function' },\n { value: 'WAIT', label: 'Wait' },\n ],\n description: 'Type of activity to execute',\n },\n {\n id: 'activityId',\n label: 'Activity ID',\n type: 'text',\n placeholder: 'send_welcome_email',\n description: 'Unique identifier for this activity',\n },\n {\n id: 'stepActivities',\n label: 'Step Activities',\n type: 'custom',\n component: (props) => <ActivityArrayEditor {...props} value={props.value as any} />,\n },\n\n // SubWorkflow fields\n {\n id: 'subWorkflowId',\n label: 'Sub-Workflow',\n type: 'custom',\n component: (props) => <WorkflowSelectorField {...props} value={props.value as any} />,\n },\n {\n id: 'subWorkflowVersion',\n label: 'Version',\n type: 'number',\n placeholder: '1',\n description: 'Specific version of the sub-workflow to invoke',\n },\n {\n id: 'inputMappings',\n label: 'Input Mappings',\n type: 'custom',\n component: (props) => (\n <MappingArrayEditor\n {...props}\n value={props.value as any}\n label=\"Input Mappings\"\n description=\"Map parent workflow data to sub-workflow input\"\n />\n ),\n },\n {\n id: 'outputMappings',\n label: 'Output Mappings',\n type: 'custom',\n component: (props) => (\n <MappingArrayEditor\n {...props}\n value={props.value as any}\n label=\"Output Mappings\"\n description=\"Map sub-workflow output back to parent workflow\"\n />\n ),\n },\n\n // WaitForSignal fields\n {\n id: 'signalName',\n label: 'Signal Name',\n type: 'text',\n placeholder: 'approval_received',\n description: 'Name of the signal to wait for',\n },\n {\n id: 'signalTimeout',\n label: 'Signal Timeout',\n type: 'text',\n placeholder: 'PT5M',\n description: 'How long to wait for the signal (ISO 8601 duration)',\n },\n\n // Advanced configuration\n {\n id: 'advancedConfig',\n label: 'Advanced Configuration (JSON)',\n type: 'custom',\n description: 'Additional JSON configuration merged with the step data',\n component: (props) => <JsonConfigEditor {...props} />,\n },\n\n // Start node pre-conditions\n {\n id: 'preConditions',\n label: 'Pre-Conditions',\n type: 'custom',\n description: 'Business rules that must pass before the workflow can start',\n component: (props) => <StartPreConditionsEditor {...props} value={props.value as any} />,\n },\n ], [showJsonSchemaWarning])\n\n if (!isOpen || !node) return null\n\n const nodeType = node.type || 'unknown'\n const nodeTypeLabel = nodeType.charAt(0).toUpperCase() + nodeType.slice(1).replace(/([A-Z])/g, ' $1')\n\n const canDelete = !!onDelete\n\n return (\n <Dialog open={isOpen} onOpenChange={onClose}>\n <DialogContent\n className=\"sm:max-w-7xl max-h-[90vh] overflow-hidden flex flex-col !p-0 [&_.grid]:!grid-cols-1\"\n onKeyDown={handleKeyDown}\n >\n <DialogHeader className=\"flex-shrink-0 p-6 pb-4 border-b border-border/70\">\n <div className=\"flex items-center gap-2 mb-2\">\n <DialogTitle>Edit Step</DialogTitle>\n <Badge variant=\"secondary\" className=\"text-xs\">\n {nodeTypeLabel}\n </Badge>\n </div>\n <div className=\"space-y-1\">\n <DialogDescription>\n Configure step properties and behavior\n </DialogDescription>\n <div className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <span className=\"font-medium\">ID:</span>\n <code className=\"px-1.5 py-0.5 rounded bg-muted font-mono\">{node.id}</code>\n </div>\n </div>\n </DialogHeader>\n\n <div className=\"flex-1 overflow-y-auto min-h-0 px-6\">\n {/* JSON Schema Conversion Warning */}\n {showJsonSchemaWarning && (\n <Alert variant=\"info\" className=\"mb-4\">\n <AlertDescription className=\"text-xs\">\n This form uses JSON Schema format. Fields have been converted for visual editing.\n When you save, it will be converted to the simplified format. To preserve the original JSON Schema,\n edit it in the &#34;Advanced Configuration (JSON)&#34; section.\n </AlertDescription>\n </Alert>\n )}\n\n <CrudForm\n fields={fields}\n groups={groups}\n initialValues={initialValues}\n onSubmit={handleSubmit}\n embedded={true}\n submitLabel=\"Save Step\"\n extraActions={\n canDelete ? (\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={handleDelete}\n className=\"text-red-600 border-red-200 hover:bg-red-50\"\n >\n <Trash2 className=\"size-4 mr-2\" />\n Delete Step\n </Button>\n ) : undefined\n }\n />\n </div>\n </DialogContent>\n </Dialog>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -184,10 +184,7 @@ function WorkflowGraphImpl({
184
184
  }
185
185
  ),
186
186
  !editable && !isCompactViewport && /* @__PURE__ */ jsx(Panel, { position: "top-left", style: { margin: 10 }, children: /* @__PURE__ */ jsx("div", { className: "bg-card rounded-lg shadow-sm border border-border px-4 py-2", children: /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground font-medium", children: t("workflows.graph.visualization") }) }) }),
187
- editable && !isCompactViewport && /* @__PURE__ */ jsx(Panel, { position: "top-left", style: { margin: 10 }, children: /* @__PURE__ */ jsxs(Alert, { variant: "info", className: "max-w-sm", children: [
188
- /* @__PURE__ */ jsx(Edit3, { className: "size-4" }),
189
- /* @__PURE__ */ jsx(AlertDescription, { className: "font-medium", children: t("workflows.graph.editModeInfo") })
190
- ] }) })
187
+ editable && !isCompactViewport && /* @__PURE__ */ jsx(Panel, { position: "top-left", style: { margin: 10 }, children: /* @__PURE__ */ jsx(Alert, { variant: "info", icon: /* @__PURE__ */ jsx(Edit3, { "aria-hidden": "true" }), className: "max-w-sm", children: /* @__PURE__ */ jsx(AlertDescription, { className: "font-medium", children: t("workflows.graph.editModeInfo") }) }) })
191
188
  ]
192
189
  }
193
190
  ) });
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/workflows/components/WorkflowGraphImpl.tsx"],
4
- "sourcesContent": ["'use client'\n\nimport '@xyflow/react/dist/style.css'\n\nimport { useCallback, useMemo, useEffect, useState } from 'react'\nimport {\n ReactFlow,\n Node,\n Edge,\n Controls,\n Background,\n BackgroundVariant,\n MiniMap,\n Panel,\n useNodesState,\n useEdgesState,\n addEdge,\n Connection,\n ConnectionMode,\n MarkerType,\n} from '@xyflow/react'\nimport {StartNode, EndNode, UserTaskNode, AutomatedNode, SubWorkflowNode, WaitForSignalNode, WaitForTimerNode, ParallelForkNode, ParallelJoinNode} from './nodes'\nimport { WorkflowTransitionEdge } from './WorkflowTransitionEdge'\nimport { STATUS_COLORS } from '../lib/status-colors'\nimport { Alert, AlertDescription } from '@open-mercato/ui/primitives/alert'\nimport { Edit3 } from 'lucide-react'\nimport { useTheme } from '@open-mercato/ui/theme'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\n\nexport interface WorkflowGraphImplProps {\n initialNodes?: Node[]\n initialEdges?: Edge[]\n onNodesChange?: (changes: any[]) => void\n onEdgesChange?: (changes: any[]) => void\n onNodeClick?: (event: React.MouseEvent, node: Node) => void\n onEdgeClick?: (event: React.MouseEvent, edge: Edge) => void\n onConnect?: (connection: Connection) => void\n editable?: boolean\n className?: string\n height?: string\n}\n\nexport default function WorkflowGraphImpl({\n initialNodes = [],\n initialEdges = [],\n onNodesChange: onNodesChangeProp,\n onEdgesChange: onEdgesChangeProp,\n onNodeClick: onNodeClickProp,\n onEdgeClick: onEdgeClickProp,\n onConnect: onConnectProp,\n editable = false,\n className = '',\n height = '600px',\n}: WorkflowGraphImplProps) {\n const t = useT()\n const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes)\n const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges)\n\n const { resolvedTheme } = useTheme()\n const isDark = resolvedTheme === 'dark'\n const backgroundDotColor = isDark ? '#374151' : '#e5e7eb'\n const [isCompactViewport, setIsCompactViewport] = useState(false)\n\n useEffect(() => {\n if (typeof window === 'undefined') return\n const mediaQuery = window.matchMedia('(max-width: 1279px)')\n const updateViewportMode = () => setIsCompactViewport(mediaQuery.matches)\n\n updateViewportMode()\n mediaQuery.addEventListener('change', updateViewportMode)\n\n return () => {\n mediaQuery.removeEventListener('change', updateViewportMode)\n }\n }, [])\n\n useEffect(() => {\n setNodes(initialNodes)\n }, [initialNodes, setNodes])\n\n useEffect(() => {\n setEdges(initialEdges)\n }, [initialEdges, setEdges])\n\n const onConnect = useCallback(\n (connection: Connection) => {\n if (onConnectProp) {\n onConnectProp(connection)\n } else {\n const newEdge = {\n ...connection,\n type: 'workflowTransition',\n animated: false,\n markerEnd: {\n type: MarkerType.ArrowClosed,\n width: 16,\n height: 16,\n color: '#9ca3af',\n },\n }\n setEdges((eds) => addEdge(newEdge, eds))\n }\n },\n [setEdges, onConnectProp]\n )\n\n const handleNodesChange = useCallback(\n (changes: any) => {\n onNodesChange(changes)\n if (onNodesChangeProp) {\n onNodesChangeProp(changes)\n }\n },\n [onNodesChange, onNodesChangeProp]\n )\n\n const handleEdgesChange = useCallback(\n (changes: any) => {\n onEdgesChange(changes)\n if (onEdgesChangeProp) {\n onEdgesChangeProp(changes)\n }\n },\n [onEdgesChange, onEdgesChangeProp]\n )\n\n const nodeTypes = useMemo(\n () => ({\n start: StartNode,\n end: EndNode,\n userTask: UserTaskNode,\n automated: AutomatedNode,\n subWorkflow: SubWorkflowNode,\n waitForSignal: WaitForSignalNode,\n waitForTimer: WaitForTimerNode,\n parallelFork: ParallelForkNode,\n parallelJoin: ParallelJoinNode,\n }),\n []\n )\n\n const edgeTypes = useMemo(\n () => ({\n workflowTransition: WorkflowTransitionEdge,\n }),\n []\n )\n\n return (\n <div className={`workflow-graph-container ${className}`} style={{ height }}>\n <ReactFlow\n nodes={nodes}\n edges={edges}\n nodeTypes={nodeTypes}\n edgeTypes={edgeTypes}\n onNodesChange={handleNodesChange}\n onEdgesChange={handleEdgesChange}\n onConnect={editable ? onConnect : undefined}\n onNodeClick={onNodeClickProp}\n onEdgeClick={onEdgeClickProp}\n connectionMode={ConnectionMode.Loose}\n fitView\n fitViewOptions={{\n padding: 0.2,\n maxZoom: isCompactViewport ? 0.9 : 1,\n }}\n minZoom={0.1}\n maxZoom={2}\n defaultEdgeOptions={{\n type: 'workflowTransition',\n animated: false,\n markerEnd: {\n type: MarkerType.ArrowClosed,\n width: 16,\n height: 16,\n color: '#9ca3af',\n },\n }}\n nodesDraggable={editable}\n nodesConnectable={editable}\n elementsSelectable={editable}\n proOptions={{ hideAttribution: true }}\n >\n <Background\n variant={BackgroundVariant.Dots}\n gap={16}\n size={1}\n color={backgroundDotColor}\n />\n\n <Controls\n showZoom={true}\n showFitView={true}\n showInteractive={false}\n position={isCompactViewport ? 'bottom-right' : 'top-right'}\n className={`!bg-card !border-border !shadow-md [&>button]:!bg-card [&>button]:!border-border [&>button]:!fill-foreground [&>button:hover]:!bg-muted ${isCompactViewport ? 'scale-90 origin-bottom-right' : ''}`}\n />\n\n {!isCompactViewport && (\n <MiniMap\n nodeStrokeWidth={3}\n nodeColor={(node) => {\n const status = (node.data?.status || 'not_started') as keyof typeof STATUS_COLORS\n return STATUS_COLORS[status]?.hex || STATUS_COLORS.not_started.hex\n }}\n maskColor=\"rgba(0, 0, 0, 0.1)\"\n position=\"bottom-left\"\n className=\"!bg-card !border !border-border !rounded-lg\"\n />\n )}\n\n {!editable && !isCompactViewport && (\n <Panel position=\"top-left\" style={{ margin: 10 }}>\n <div className=\"bg-card rounded-lg shadow-sm border border-border px-4 py-2\">\n <p className=\"text-sm text-muted-foreground font-medium\">\n {t('workflows.graph.visualization')}\n </p>\n </div>\n </Panel>\n )}\n\n {editable && !isCompactViewport && (\n <Panel position=\"top-left\" style={{ margin: 10 }}>\n <Alert variant=\"info\" className=\"max-w-sm\">\n <Edit3 className=\"size-4\" />\n <AlertDescription className=\"font-medium\">\n {t('workflows.graph.editModeInfo')}\n </AlertDescription>\n </Alert>\n </Panel>\n )}\n </ReactFlow>\n </div>\n )\n}\n"],
5
- "mappings": ";AAuLQ,cAwCI,YAxCJ;AArLR,OAAO;AAEP,SAAS,aAAa,SAAS,WAAW,gBAAgB;AAC1D;AAAA,EACE;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,OACK;AACP,SAAQ,WAAW,SAAS,cAAc,eAAe,iBAAiB,mBAAmB,kBAAkB,kBAAkB,wBAAuB;AACxJ,SAAS,8BAA8B;AACvC,SAAS,qBAAqB;AAC9B,SAAS,OAAO,wBAAwB;AACxC,SAAS,aAAa;AACtB,SAAS,gBAAgB;AACzB,SAAS,YAAY;AAeN,SAAR,kBAAmC;AAAA,EACxC,eAAe,CAAC;AAAA,EAChB,eAAe,CAAC;AAAA,EAChB,eAAe;AAAA,EACf,eAAe;AAAA,EACf,aAAa;AAAA,EACb,aAAa;AAAA,EACb,WAAW;AAAA,EACX,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,SAAS;AACX,GAA2B;AACzB,QAAM,IAAI,KAAK;AACf,QAAM,CAAC,OAAO,UAAU,aAAa,IAAI,cAAc,YAAY;AACnE,QAAM,CAAC,OAAO,UAAU,aAAa,IAAI,cAAc,YAAY;AAEnE,QAAM,EAAE,cAAc,IAAI,SAAS;AACnC,QAAM,SAAS,kBAAkB;AACjC,QAAM,qBAAqB,SAAS,YAAY;AAChD,QAAM,CAAC,mBAAmB,oBAAoB,IAAI,SAAS,KAAK;AAEhE,YAAU,MAAM;AACd,QAAI,OAAO,WAAW,YAAa;AACnC,UAAM,aAAa,OAAO,WAAW,qBAAqB;AAC1D,UAAM,qBAAqB,MAAM,qBAAqB,WAAW,OAAO;AAExE,uBAAmB;AACnB,eAAW,iBAAiB,UAAU,kBAAkB;AAExD,WAAO,MAAM;AACX,iBAAW,oBAAoB,UAAU,kBAAkB;AAAA,IAC7D;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,YAAU,MAAM;AACd,aAAS,YAAY;AAAA,EACvB,GAAG,CAAC,cAAc,QAAQ,CAAC;AAE3B,YAAU,MAAM;AACd,aAAS,YAAY;AAAA,EACvB,GAAG,CAAC,cAAc,QAAQ,CAAC;AAE3B,QAAM,YAAY;AAAA,IAChB,CAAC,eAA2B;AAC1B,UAAI,eAAe;AACjB,sBAAc,UAAU;AAAA,MAC1B,OAAO;AACL,cAAM,UAAU;AAAA,UACd,GAAG;AAAA,UACH,MAAM;AAAA,UACN,UAAU;AAAA,UACV,WAAW;AAAA,YACT,MAAM,WAAW;AAAA,YACjB,OAAO;AAAA,YACP,QAAQ;AAAA,YACR,OAAO;AAAA,UACT;AAAA,QACF;AACA,iBAAS,CAAC,QAAQ,QAAQ,SAAS,GAAG,CAAC;AAAA,MACzC;AAAA,IACF;AAAA,IACA,CAAC,UAAU,aAAa;AAAA,EAC1B;AAEA,QAAM,oBAAoB;AAAA,IACxB,CAAC,YAAiB;AAChB,oBAAc,OAAO;AACrB,UAAI,mBAAmB;AACrB,0BAAkB,OAAO;AAAA,MAC3B;AAAA,IACF;AAAA,IACA,CAAC,eAAe,iBAAiB;AAAA,EACnC;AAEA,QAAM,oBAAoB;AAAA,IACxB,CAAC,YAAiB;AAChB,oBAAc,OAAO;AACrB,UAAI,mBAAmB;AACrB,0BAAkB,OAAO;AAAA,MAC3B;AAAA,IACF;AAAA,IACA,CAAC,eAAe,iBAAiB;AAAA,EACnC;AAEA,QAAM,YAAY;AAAA,IAChB,OAAO;AAAA,MACL,OAAO;AAAA,MACP,KAAK;AAAA,MACL,UAAU;AAAA,MACV,WAAW;AAAA,MACX,aAAa;AAAA,MACb,eAAe;AAAA,MACf,cAAc;AAAA,MACd,cAAc;AAAA,MACd,cAAc;AAAA,IAChB;AAAA,IACA,CAAC;AAAA,EACH;AAEA,QAAM,YAAY;AAAA,IAChB,OAAO;AAAA,MACL,oBAAoB;AAAA,IACtB;AAAA,IACA,CAAC;AAAA,EACH;AAEA,SACE,oBAAC,SAAI,WAAW,4BAA4B,SAAS,IAAI,OAAO,EAAE,OAAO,GACvE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,eAAe;AAAA,MACf,eAAe;AAAA,MACf,WAAW,WAAW,YAAY;AAAA,MAClC,aAAa;AAAA,MACb,aAAa;AAAA,MACb,gBAAgB,eAAe;AAAA,MAC/B,SAAO;AAAA,MACP,gBAAgB;AAAA,QACd,SAAS;AAAA,QACT,SAAS,oBAAoB,MAAM;AAAA,MACrC;AAAA,MACA,SAAS;AAAA,MACT,SAAS;AAAA,MACT,oBAAoB;AAAA,QAClB,MAAM;AAAA,QACN,UAAU;AAAA,QACV,WAAW;AAAA,UACT,MAAM,WAAW;AAAA,UACjB,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,OAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA,gBAAgB;AAAA,MAChB,kBAAkB;AAAA,MAClB,oBAAoB;AAAA,MACpB,YAAY,EAAE,iBAAiB,KAAK;AAAA,MAEpC;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,SAAS,kBAAkB;AAAA,YAC3B,KAAK;AAAA,YACL,MAAM;AAAA,YACN,OAAO;AAAA;AAAA,QACT;AAAA,QAEA;AAAA,UAAC;AAAA;AAAA,YACC,UAAU;AAAA,YACV,aAAa;AAAA,YACb,iBAAiB;AAAA,YACjB,UAAU,oBAAoB,iBAAiB;AAAA,YAC/C,WAAW,2IAA2I,oBAAoB,iCAAiC,EAAE;AAAA;AAAA,QAC/M;AAAA,QAEC,CAAC,qBACA;AAAA,UAAC;AAAA;AAAA,YACC,iBAAiB;AAAA,YACjB,WAAW,CAAC,SAAS;AACnB,oBAAM,SAAU,KAAK,MAAM,UAAU;AACrC,qBAAO,cAAc,MAAM,GAAG,OAAO,cAAc,YAAY;AAAA,YACjE;AAAA,YACA,WAAU;AAAA,YACV,UAAS;AAAA,YACT,WAAU;AAAA;AAAA,QACZ;AAAA,QAGD,CAAC,YAAY,CAAC,qBACb,oBAAC,SAAM,UAAS,YAAW,OAAO,EAAE,QAAQ,GAAG,GAC7C,8BAAC,SAAI,WAAU,+DACb,8BAAC,OAAE,WAAU,6CACV,YAAE,+BAA+B,GACpC,GACF,GACF;AAAA,QAGD,YAAY,CAAC,qBACZ,oBAAC,SAAM,UAAS,YAAW,OAAO,EAAE,QAAQ,GAAG,GAC7C,+BAAC,SAAM,SAAQ,QAAO,WAAU,YAC9B;AAAA,8BAAC,SAAM,WAAU,UAAS;AAAA,UAC1B,oBAAC,oBAAiB,WAAU,eACzB,YAAE,8BAA8B,GACnC;AAAA,WACF,GACF;AAAA;AAAA;AAAA,EAEJ,GACF;AAEJ;",
4
+ "sourcesContent": ["'use client'\n\nimport '@xyflow/react/dist/style.css'\n\nimport { useCallback, useMemo, useEffect, useState } from 'react'\nimport {\n ReactFlow,\n Node,\n Edge,\n Controls,\n Background,\n BackgroundVariant,\n MiniMap,\n Panel,\n useNodesState,\n useEdgesState,\n addEdge,\n Connection,\n ConnectionMode,\n MarkerType,\n} from '@xyflow/react'\nimport {StartNode, EndNode, UserTaskNode, AutomatedNode, SubWorkflowNode, WaitForSignalNode, WaitForTimerNode, ParallelForkNode, ParallelJoinNode} from './nodes'\nimport { WorkflowTransitionEdge } from './WorkflowTransitionEdge'\nimport { STATUS_COLORS } from '../lib/status-colors'\nimport { Alert, AlertDescription } from '@open-mercato/ui/primitives/alert'\nimport { Edit3 } from 'lucide-react'\nimport { useTheme } from '@open-mercato/ui/theme'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\n\nexport interface WorkflowGraphImplProps {\n initialNodes?: Node[]\n initialEdges?: Edge[]\n onNodesChange?: (changes: any[]) => void\n onEdgesChange?: (changes: any[]) => void\n onNodeClick?: (event: React.MouseEvent, node: Node) => void\n onEdgeClick?: (event: React.MouseEvent, edge: Edge) => void\n onConnect?: (connection: Connection) => void\n editable?: boolean\n className?: string\n height?: string\n}\n\nexport default function WorkflowGraphImpl({\n initialNodes = [],\n initialEdges = [],\n onNodesChange: onNodesChangeProp,\n onEdgesChange: onEdgesChangeProp,\n onNodeClick: onNodeClickProp,\n onEdgeClick: onEdgeClickProp,\n onConnect: onConnectProp,\n editable = false,\n className = '',\n height = '600px',\n}: WorkflowGraphImplProps) {\n const t = useT()\n const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes)\n const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges)\n\n const { resolvedTheme } = useTheme()\n const isDark = resolvedTheme === 'dark'\n const backgroundDotColor = isDark ? '#374151' : '#e5e7eb'\n const [isCompactViewport, setIsCompactViewport] = useState(false)\n\n useEffect(() => {\n if (typeof window === 'undefined') return\n const mediaQuery = window.matchMedia('(max-width: 1279px)')\n const updateViewportMode = () => setIsCompactViewport(mediaQuery.matches)\n\n updateViewportMode()\n mediaQuery.addEventListener('change', updateViewportMode)\n\n return () => {\n mediaQuery.removeEventListener('change', updateViewportMode)\n }\n }, [])\n\n useEffect(() => {\n setNodes(initialNodes)\n }, [initialNodes, setNodes])\n\n useEffect(() => {\n setEdges(initialEdges)\n }, [initialEdges, setEdges])\n\n const onConnect = useCallback(\n (connection: Connection) => {\n if (onConnectProp) {\n onConnectProp(connection)\n } else {\n const newEdge = {\n ...connection,\n type: 'workflowTransition',\n animated: false,\n markerEnd: {\n type: MarkerType.ArrowClosed,\n width: 16,\n height: 16,\n color: '#9ca3af',\n },\n }\n setEdges((eds) => addEdge(newEdge, eds))\n }\n },\n [setEdges, onConnectProp]\n )\n\n const handleNodesChange = useCallback(\n (changes: any) => {\n onNodesChange(changes)\n if (onNodesChangeProp) {\n onNodesChangeProp(changes)\n }\n },\n [onNodesChange, onNodesChangeProp]\n )\n\n const handleEdgesChange = useCallback(\n (changes: any) => {\n onEdgesChange(changes)\n if (onEdgesChangeProp) {\n onEdgesChangeProp(changes)\n }\n },\n [onEdgesChange, onEdgesChangeProp]\n )\n\n const nodeTypes = useMemo(\n () => ({\n start: StartNode,\n end: EndNode,\n userTask: UserTaskNode,\n automated: AutomatedNode,\n subWorkflow: SubWorkflowNode,\n waitForSignal: WaitForSignalNode,\n waitForTimer: WaitForTimerNode,\n parallelFork: ParallelForkNode,\n parallelJoin: ParallelJoinNode,\n }),\n []\n )\n\n const edgeTypes = useMemo(\n () => ({\n workflowTransition: WorkflowTransitionEdge,\n }),\n []\n )\n\n return (\n <div className={`workflow-graph-container ${className}`} style={{ height }}>\n <ReactFlow\n nodes={nodes}\n edges={edges}\n nodeTypes={nodeTypes}\n edgeTypes={edgeTypes}\n onNodesChange={handleNodesChange}\n onEdgesChange={handleEdgesChange}\n onConnect={editable ? onConnect : undefined}\n onNodeClick={onNodeClickProp}\n onEdgeClick={onEdgeClickProp}\n connectionMode={ConnectionMode.Loose}\n fitView\n fitViewOptions={{\n padding: 0.2,\n maxZoom: isCompactViewport ? 0.9 : 1,\n }}\n minZoom={0.1}\n maxZoom={2}\n defaultEdgeOptions={{\n type: 'workflowTransition',\n animated: false,\n markerEnd: {\n type: MarkerType.ArrowClosed,\n width: 16,\n height: 16,\n color: '#9ca3af',\n },\n }}\n nodesDraggable={editable}\n nodesConnectable={editable}\n elementsSelectable={editable}\n proOptions={{ hideAttribution: true }}\n >\n <Background\n variant={BackgroundVariant.Dots}\n gap={16}\n size={1}\n color={backgroundDotColor}\n />\n\n <Controls\n showZoom={true}\n showFitView={true}\n showInteractive={false}\n position={isCompactViewport ? 'bottom-right' : 'top-right'}\n className={`!bg-card !border-border !shadow-md [&>button]:!bg-card [&>button]:!border-border [&>button]:!fill-foreground [&>button:hover]:!bg-muted ${isCompactViewport ? 'scale-90 origin-bottom-right' : ''}`}\n />\n\n {!isCompactViewport && (\n <MiniMap\n nodeStrokeWidth={3}\n nodeColor={(node) => {\n const status = (node.data?.status || 'not_started') as keyof typeof STATUS_COLORS\n return STATUS_COLORS[status]?.hex || STATUS_COLORS.not_started.hex\n }}\n maskColor=\"rgba(0, 0, 0, 0.1)\"\n position=\"bottom-left\"\n className=\"!bg-card !border !border-border !rounded-lg\"\n />\n )}\n\n {!editable && !isCompactViewport && (\n <Panel position=\"top-left\" style={{ margin: 10 }}>\n <div className=\"bg-card rounded-lg shadow-sm border border-border px-4 py-2\">\n <p className=\"text-sm text-muted-foreground font-medium\">\n {t('workflows.graph.visualization')}\n </p>\n </div>\n </Panel>\n )}\n\n {editable && !isCompactViewport && (\n <Panel position=\"top-left\" style={{ margin: 10 }}>\n <Alert variant=\"info\" icon={<Edit3 aria-hidden=\"true\" />} className=\"max-w-sm\">\n <AlertDescription className=\"font-medium\">\n {t('workflows.graph.editModeInfo')}\n </AlertDescription>\n </Alert>\n </Panel>\n )}\n </ReactFlow>\n </div>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -15,7 +15,7 @@ import {
15
15
  SelectValue
16
16
  } from "@open-mercato/ui/primitives/select";
17
17
  import { Alert, AlertDescription } from "@open-mercato/ui/primitives/alert";
18
- import { ChevronDown, Plus, Trash2, Info } from "lucide-react";
18
+ import { ChevronDown, Plus, Trash2 } from "lucide-react";
19
19
  function FormFieldArrayEditor({
20
20
  id,
21
21
  value = [],
@@ -96,10 +96,7 @@ function FormFieldArrayEditor({
96
96
  }
97
97
  )
98
98
  ] }),
99
- isJsonSchemaFormat && /* @__PURE__ */ jsxs(Alert, { variant: "default", className: "border-blue-200 bg-blue-50", children: [
100
- /* @__PURE__ */ jsx(Info, { className: "size-4" }),
101
- /* @__PURE__ */ jsx(AlertDescription, { className: "text-xs", children: t("workflows.fieldEditors.formFields.jsonSchemaNotice") })
102
- ] }),
99
+ isJsonSchemaFormat && /* @__PURE__ */ jsx(Alert, { variant: "info", children: /* @__PURE__ */ jsx(AlertDescription, { className: "text-xs", children: t("workflows.fieldEditors.formFields.jsonSchemaNotice") }) }),
103
100
  formFields.length === 0 ? /* @__PURE__ */ jsx("div", { className: "p-4 text-center text-sm text-muted-foreground bg-muted rounded-lg border", children: t("workflows.fieldEditors.formFields.emptyState") }) : /* @__PURE__ */ jsx("div", { className: "space-y-2", children: formFields.map((field, index) => {
104
101
  const isExpanded = expandedIndices.has(index);
105
102
  return /* @__PURE__ */ jsxs("div", { className: "border border-gray-200 rounded-lg bg-gray-50", children: [
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/workflows/components/fields/FormFieldArrayEditor.tsx"],
4
- "sourcesContent": ["'use client'\n\nimport { useState } from 'react'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport { Label } from '@open-mercato/ui/primitives/label'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@open-mercato/ui/primitives/select'\nimport { Alert, AlertDescription } from '@open-mercato/ui/primitives/alert'\nimport { ChevronDown, Plus, Trash2, Info } from 'lucide-react'\nimport type { CrudCustomFieldRenderProps } from '@open-mercato/ui/backend/CrudForm'\n\n/**\n * Form field definition structure\n */\nexport interface FormField {\n name: string\n type: string\n label: string\n required: boolean\n placeholder?: string\n options?: string[]\n defaultValue?: string\n}\n\ninterface FormFieldArrayEditorProps extends CrudCustomFieldRenderProps {\n value: FormField[]\n isJsonSchemaFormat?: boolean\n}\n\n/**\n * FormFieldArrayEditor - Custom field component for managing UserTask form fields\n *\n * Provides an interface to add, edit, and remove form field definitions for user tasks.\n * Supports 12 field types with conditional options for select/radio types.\n *\n * Displays a warning banner if the form was converted from JSON Schema format.\n *\n * Used by NodeEditDialog (UserTask type only)\n */\nexport function FormFieldArrayEditor({\n id,\n value = [],\n error,\n setValue,\n disabled,\n isJsonSchemaFormat = false,\n}: FormFieldArrayEditorProps) {\n const t = useT()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const [expandedIndices, setExpandedIndices] = useState<Set<number>>(new Set())\n\n const formFields = Array.isArray(value) ? value : []\n\n const toggleExpanded = (index: number) => {\n const newExpanded = new Set(expandedIndices)\n if (newExpanded.has(index)) {\n newExpanded.delete(index)\n } else {\n newExpanded.add(index)\n }\n setExpandedIndices(newExpanded)\n }\n\n const addFormField = () => {\n const newField: FormField = {\n name: `field_${Date.now()}`,\n type: 'text',\n label: t('workflows.form.newField'),\n required: false,\n placeholder: '',\n }\n const newFields = [...formFields, newField]\n setValue(newFields)\n\n // Auto-expand the newly added field\n const newExpanded = new Set(expandedIndices)\n newExpanded.add(formFields.length)\n setExpandedIndices(newExpanded)\n }\n\n const removeFormField = async (index: number) => {\n const confirmed = await confirm({\n title: t('workflows.fieldEditors.formFields.removeField'),\n text: t('workflows.fieldEditors.formFields.confirmRemove'),\n variant: 'destructive',\n })\n if (!confirmed) return\n\n const newFields = formFields.filter((_, i) => i !== index)\n setValue(newFields)\n\n // Remove from expanded set\n const newExpanded = new Set(expandedIndices)\n newExpanded.delete(index)\n setExpandedIndices(newExpanded)\n }\n\n const updateFormField = (index: number, fieldKey: keyof FormField, fieldValue: any) => {\n const updated = [...formFields]\n updated[index] = { ...updated[index], [fieldKey]: fieldValue }\n setValue(updated)\n }\n\n return (\n <div className=\"space-y-3\">\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n <div>\n <Label className=\"text-sm font-semibold\">{t('workflows.fieldEditors.formFields.title')} ({formFields.length})</Label>\n <p className=\"text-xs text-muted-foreground mt-0.5\">\n {t('workflows.fieldEditors.formFields.description')}\n </p>\n {error && <p className=\"text-xs text-red-600 mt-1\">{error}</p>}\n </div>\n <Button\n type=\"button\"\n size=\"sm\"\n onClick={addFormField}\n disabled={disabled}\n className=\"w-full sm:w-auto\"\n >\n <Plus className=\"size-3 mr-1\" />\n {t('workflows.fieldEditors.formFields.addField')}\n </Button>\n </div>\n\n {/* JSON Schema Format Notice */}\n {isJsonSchemaFormat && (\n <Alert variant=\"default\" className=\"border-blue-200 bg-blue-50\">\n <Info className=\"size-4\" />\n <AlertDescription className=\"text-xs\">\n {t('workflows.fieldEditors.formFields.jsonSchemaNotice')}\n </AlertDescription>\n </Alert>\n )}\n\n {formFields.length === 0 ? (\n <div className=\"p-4 text-center text-sm text-muted-foreground bg-muted rounded-lg border\">\n {t('workflows.fieldEditors.formFields.emptyState')}\n </div>\n ) : (\n <div className=\"space-y-2\">\n {formFields.map((field, index) => {\n const isExpanded = expandedIndices.has(index)\n return (\n <div key={index} className=\"border border-gray-200 rounded-lg bg-gray-50\">\n {/* Collapsed Header */}\n <button\n type=\"button\"\n onClick={() => toggleExpanded(index)}\n disabled={disabled}\n className=\"w-full px-4 py-3 text-left flex items-center justify-between hover:bg-gray-100 transition-colors rounded-t-lg disabled:opacity-50\"\n >\n <div className=\"flex-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"text-sm font-semibold text-gray-900\">\n {field.label || field.name}\n </span>\n <Badge variant=\"secondary\" className=\"text-xs\">\n {field.type}\n </Badge>\n {field.required && (\n <Badge variant=\"destructive\" className=\"text-xs text-white\">\n {t('workflows.form.required')}\n </Badge>\n )}\n </div>\n <p className=\"text-xs text-gray-600 mt-1\">\n Field name: <code className=\"bg-white px-1 rounded\">{field.name}</code>\n </p>\n </div>\n <ChevronDown\n className={`w-5 h-5 text-gray-400 transition-transform ${isExpanded ? 'rotate-180' : ''}`}\n />\n </button>\n\n {/* Expanded Content */}\n {isExpanded && (\n <div className=\"px-4 pb-4 space-y-3 border-t border-gray-200 bg-white\">\n {/* Field Name */}\n <div className=\"pt-3\">\n <Label htmlFor={`${id}-${index}-name`} className=\"text-xs font-medium mb-1\">\n {t('workflows.fieldEditors.formFields.fieldName')} *\n </Label>\n <Input\n id={`${id}-${index}-name`}\n type=\"text\"\n value={field.name}\n onChange={(e) => updateFormField(index, 'name', e.target.value)}\n placeholder={t('workflows.fieldEditors.formFields.fieldNamePlaceholder')}\n className=\"text-xs\"\n disabled={disabled}\n />\n <p className=\"text-xs text-muted-foreground mt-0.5\">{t('workflows.fieldEditors.formFields.fieldNameHint')}</p>\n </div>\n\n {/* Field Label */}\n <div>\n <Label htmlFor={`${id}-${index}-label`} className=\"text-xs font-medium mb-1\">\n {t('workflows.fieldEditors.formFields.fieldLabel')} *\n </Label>\n <Input\n id={`${id}-${index}-label`}\n type=\"text\"\n value={field.label}\n onChange={(e) => updateFormField(index, 'label', e.target.value)}\n placeholder={t('workflows.fieldEditors.formFields.fieldLabelPlaceholder')}\n className=\"text-xs\"\n disabled={disabled}\n />\n <p className=\"text-xs text-muted-foreground mt-0.5\">{t('workflows.fieldEditors.formFields.fieldLabelHint')}</p>\n </div>\n\n {/* Field Type */}\n <div>\n <Label htmlFor={`${id}-${index}-type`} className=\"text-xs font-medium mb-1\">\n {t('workflows.fieldEditors.formFields.fieldType')} *\n </Label>\n <Select\n value={field.type}\n onValueChange={(value) => updateFormField(index, 'type', value)}\n disabled={disabled}\n >\n <SelectTrigger id={`${id}-${index}-type`}>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"text\">{t('workflows.form.fieldTypes.text')}</SelectItem>\n <SelectItem value=\"number\">{t('workflows.form.fieldTypes.number')}</SelectItem>\n <SelectItem value=\"email\">{t('workflows.form.fieldTypes.email')}</SelectItem>\n <SelectItem value=\"tel\">{t('workflows.form.fieldTypes.tel')}</SelectItem>\n <SelectItem value=\"url\">{t('workflows.form.fieldTypes.url')}</SelectItem>\n <SelectItem value=\"textarea\">{t('workflows.form.fieldTypes.textarea')}</SelectItem>\n <SelectItem value=\"select\">{t('workflows.form.fieldTypes.select')}</SelectItem>\n <SelectItem value=\"radio\">{t('workflows.form.fieldTypes.radio')}</SelectItem>\n <SelectItem value=\"checkbox\">{t('workflows.form.fieldTypes.checkbox')}</SelectItem>\n <SelectItem value=\"date\">{t('workflows.form.fieldTypes.date')}</SelectItem>\n <SelectItem value=\"time\">{t('workflows.form.fieldTypes.time')}</SelectItem>\n <SelectItem value=\"datetime-local\">{t('workflows.form.fieldTypes.datetime-local')}</SelectItem>\n </SelectContent>\n </Select>\n </div>\n\n {/* Placeholder */}\n <div>\n <Label htmlFor={`${id}-${index}-placeholder`} className=\"text-xs font-medium mb-1\">\n {t('workflows.fieldEditors.formFields.placeholder')}\n </Label>\n <Input\n id={`${id}-${index}-placeholder`}\n type=\"text\"\n value={field.placeholder || ''}\n onChange={(e) => updateFormField(index, 'placeholder', e.target.value)}\n placeholder={t('workflows.fieldEditors.formFields.placeholderPlaceholder')}\n className=\"text-xs\"\n disabled={disabled}\n />\n </div>\n\n {/* Default Value */}\n <div>\n <Label htmlFor={`${id}-${index}-defaultValue`} className=\"text-xs font-medium mb-1\">\n {t('workflows.fieldEditors.formFields.defaultValue')}\n </Label>\n <Input\n id={`${id}-${index}-defaultValue`}\n type=\"text\"\n value={field.defaultValue || ''}\n onChange={(e) => updateFormField(index, 'defaultValue', e.target.value)}\n placeholder={t('workflows.fieldEditors.formFields.defaultValuePlaceholder')}\n className=\"text-xs\"\n disabled={disabled}\n />\n </div>\n\n {/* Options (for select/radio) */}\n {(field.type === 'select' || field.type === 'radio') && (\n <div>\n <Label htmlFor={`${id}-${index}-options`} className=\"text-xs font-medium mb-1\">\n {t('workflows.fieldEditors.formFields.options')}\n </Label>\n <Input\n id={`${id}-${index}-options`}\n type=\"text\"\n value={field.options?.join(', ') || ''}\n onChange={(e) =>\n updateFormField(\n index,\n 'options',\n e.target.value\n .split(',')\n .map((o) => o.trim())\n .filter(Boolean)\n )\n }\n placeholder={t('workflows.fieldEditors.formFields.optionsPlaceholder')}\n className=\"text-xs\"\n disabled={disabled}\n />\n <p className=\"text-xs text-muted-foreground mt-0.5\">{t('workflows.fieldEditors.formFields.optionsHint')}</p>\n </div>\n )}\n\n {/* Required Checkbox */}\n <div>\n <div className=\"flex items-center gap-2\">\n <input\n type=\"checkbox\"\n id={`${id}-${index}-required`}\n checked={field.required}\n onChange={(e) => updateFormField(index, 'required', e.target.checked)}\n className=\"h-4 w-4 rounded border-gray-300 text-blue-600 focus-visible:ring-ring\"\n disabled={disabled}\n />\n <Label htmlFor={`${id}-${index}-required`} className=\"text-xs font-medium cursor-pointer\">\n {t('workflows.fieldEditors.formFields.requiredField')}\n </Label>\n </div>\n </div>\n\n {/* Delete Button */}\n <div className=\"border-t border-gray-200 pt-3\">\n <Button\n type=\"button\"\n variant=\"destructive\"\n size=\"sm\"\n onClick={() => removeFormField(index)}\n disabled={disabled}\n >\n <Trash2 className=\"size-4 mr-1\" />\n {t('workflows.fieldEditors.formFields.removeField')}\n </Button>\n </div>\n </div>\n )}\n </div>\n )\n })}\n </div>\n )}\n {ConfirmDialogElement}\n </div>\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["'use client'\n\nimport { useState } from 'react'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport { Label } from '@open-mercato/ui/primitives/label'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@open-mercato/ui/primitives/select'\nimport { Alert, AlertDescription } from '@open-mercato/ui/primitives/alert'\nimport { ChevronDown, Plus, Trash2 } from 'lucide-react'\nimport type { CrudCustomFieldRenderProps } from '@open-mercato/ui/backend/CrudForm'\n\n/**\n * Form field definition structure\n */\nexport interface FormField {\n name: string\n type: string\n label: string\n required: boolean\n placeholder?: string\n options?: string[]\n defaultValue?: string\n}\n\ninterface FormFieldArrayEditorProps extends CrudCustomFieldRenderProps {\n value: FormField[]\n isJsonSchemaFormat?: boolean\n}\n\n/**\n * FormFieldArrayEditor - Custom field component for managing UserTask form fields\n *\n * Provides an interface to add, edit, and remove form field definitions for user tasks.\n * Supports 12 field types with conditional options for select/radio types.\n *\n * Displays a warning banner if the form was converted from JSON Schema format.\n *\n * Used by NodeEditDialog (UserTask type only)\n */\nexport function FormFieldArrayEditor({\n id,\n value = [],\n error,\n setValue,\n disabled,\n isJsonSchemaFormat = false,\n}: FormFieldArrayEditorProps) {\n const t = useT()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const [expandedIndices, setExpandedIndices] = useState<Set<number>>(new Set())\n\n const formFields = Array.isArray(value) ? value : []\n\n const toggleExpanded = (index: number) => {\n const newExpanded = new Set(expandedIndices)\n if (newExpanded.has(index)) {\n newExpanded.delete(index)\n } else {\n newExpanded.add(index)\n }\n setExpandedIndices(newExpanded)\n }\n\n const addFormField = () => {\n const newField: FormField = {\n name: `field_${Date.now()}`,\n type: 'text',\n label: t('workflows.form.newField'),\n required: false,\n placeholder: '',\n }\n const newFields = [...formFields, newField]\n setValue(newFields)\n\n // Auto-expand the newly added field\n const newExpanded = new Set(expandedIndices)\n newExpanded.add(formFields.length)\n setExpandedIndices(newExpanded)\n }\n\n const removeFormField = async (index: number) => {\n const confirmed = await confirm({\n title: t('workflows.fieldEditors.formFields.removeField'),\n text: t('workflows.fieldEditors.formFields.confirmRemove'),\n variant: 'destructive',\n })\n if (!confirmed) return\n\n const newFields = formFields.filter((_, i) => i !== index)\n setValue(newFields)\n\n // Remove from expanded set\n const newExpanded = new Set(expandedIndices)\n newExpanded.delete(index)\n setExpandedIndices(newExpanded)\n }\n\n const updateFormField = (index: number, fieldKey: keyof FormField, fieldValue: any) => {\n const updated = [...formFields]\n updated[index] = { ...updated[index], [fieldKey]: fieldValue }\n setValue(updated)\n }\n\n return (\n <div className=\"space-y-3\">\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n <div>\n <Label className=\"text-sm font-semibold\">{t('workflows.fieldEditors.formFields.title')} ({formFields.length})</Label>\n <p className=\"text-xs text-muted-foreground mt-0.5\">\n {t('workflows.fieldEditors.formFields.description')}\n </p>\n {error && <p className=\"text-xs text-red-600 mt-1\">{error}</p>}\n </div>\n <Button\n type=\"button\"\n size=\"sm\"\n onClick={addFormField}\n disabled={disabled}\n className=\"w-full sm:w-auto\"\n >\n <Plus className=\"size-3 mr-1\" />\n {t('workflows.fieldEditors.formFields.addField')}\n </Button>\n </div>\n\n {/* JSON Schema Format Notice */}\n {isJsonSchemaFormat && (\n <Alert variant=\"info\">\n <AlertDescription className=\"text-xs\">\n {t('workflows.fieldEditors.formFields.jsonSchemaNotice')}\n </AlertDescription>\n </Alert>\n )}\n\n {formFields.length === 0 ? (\n <div className=\"p-4 text-center text-sm text-muted-foreground bg-muted rounded-lg border\">\n {t('workflows.fieldEditors.formFields.emptyState')}\n </div>\n ) : (\n <div className=\"space-y-2\">\n {formFields.map((field, index) => {\n const isExpanded = expandedIndices.has(index)\n return (\n <div key={index} className=\"border border-gray-200 rounded-lg bg-gray-50\">\n {/* Collapsed Header */}\n <button\n type=\"button\"\n onClick={() => toggleExpanded(index)}\n disabled={disabled}\n className=\"w-full px-4 py-3 text-left flex items-center justify-between hover:bg-gray-100 transition-colors rounded-t-lg disabled:opacity-50\"\n >\n <div className=\"flex-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"text-sm font-semibold text-gray-900\">\n {field.label || field.name}\n </span>\n <Badge variant=\"secondary\" className=\"text-xs\">\n {field.type}\n </Badge>\n {field.required && (\n <Badge variant=\"destructive\" className=\"text-xs text-white\">\n {t('workflows.form.required')}\n </Badge>\n )}\n </div>\n <p className=\"text-xs text-gray-600 mt-1\">\n Field name: <code className=\"bg-white px-1 rounded\">{field.name}</code>\n </p>\n </div>\n <ChevronDown\n className={`w-5 h-5 text-gray-400 transition-transform ${isExpanded ? 'rotate-180' : ''}`}\n />\n </button>\n\n {/* Expanded Content */}\n {isExpanded && (\n <div className=\"px-4 pb-4 space-y-3 border-t border-gray-200 bg-white\">\n {/* Field Name */}\n <div className=\"pt-3\">\n <Label htmlFor={`${id}-${index}-name`} className=\"text-xs font-medium mb-1\">\n {t('workflows.fieldEditors.formFields.fieldName')} *\n </Label>\n <Input\n id={`${id}-${index}-name`}\n type=\"text\"\n value={field.name}\n onChange={(e) => updateFormField(index, 'name', e.target.value)}\n placeholder={t('workflows.fieldEditors.formFields.fieldNamePlaceholder')}\n className=\"text-xs\"\n disabled={disabled}\n />\n <p className=\"text-xs text-muted-foreground mt-0.5\">{t('workflows.fieldEditors.formFields.fieldNameHint')}</p>\n </div>\n\n {/* Field Label */}\n <div>\n <Label htmlFor={`${id}-${index}-label`} className=\"text-xs font-medium mb-1\">\n {t('workflows.fieldEditors.formFields.fieldLabel')} *\n </Label>\n <Input\n id={`${id}-${index}-label`}\n type=\"text\"\n value={field.label}\n onChange={(e) => updateFormField(index, 'label', e.target.value)}\n placeholder={t('workflows.fieldEditors.formFields.fieldLabelPlaceholder')}\n className=\"text-xs\"\n disabled={disabled}\n />\n <p className=\"text-xs text-muted-foreground mt-0.5\">{t('workflows.fieldEditors.formFields.fieldLabelHint')}</p>\n </div>\n\n {/* Field Type */}\n <div>\n <Label htmlFor={`${id}-${index}-type`} className=\"text-xs font-medium mb-1\">\n {t('workflows.fieldEditors.formFields.fieldType')} *\n </Label>\n <Select\n value={field.type}\n onValueChange={(value) => updateFormField(index, 'type', value)}\n disabled={disabled}\n >\n <SelectTrigger id={`${id}-${index}-type`}>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"text\">{t('workflows.form.fieldTypes.text')}</SelectItem>\n <SelectItem value=\"number\">{t('workflows.form.fieldTypes.number')}</SelectItem>\n <SelectItem value=\"email\">{t('workflows.form.fieldTypes.email')}</SelectItem>\n <SelectItem value=\"tel\">{t('workflows.form.fieldTypes.tel')}</SelectItem>\n <SelectItem value=\"url\">{t('workflows.form.fieldTypes.url')}</SelectItem>\n <SelectItem value=\"textarea\">{t('workflows.form.fieldTypes.textarea')}</SelectItem>\n <SelectItem value=\"select\">{t('workflows.form.fieldTypes.select')}</SelectItem>\n <SelectItem value=\"radio\">{t('workflows.form.fieldTypes.radio')}</SelectItem>\n <SelectItem value=\"checkbox\">{t('workflows.form.fieldTypes.checkbox')}</SelectItem>\n <SelectItem value=\"date\">{t('workflows.form.fieldTypes.date')}</SelectItem>\n <SelectItem value=\"time\">{t('workflows.form.fieldTypes.time')}</SelectItem>\n <SelectItem value=\"datetime-local\">{t('workflows.form.fieldTypes.datetime-local')}</SelectItem>\n </SelectContent>\n </Select>\n </div>\n\n {/* Placeholder */}\n <div>\n <Label htmlFor={`${id}-${index}-placeholder`} className=\"text-xs font-medium mb-1\">\n {t('workflows.fieldEditors.formFields.placeholder')}\n </Label>\n <Input\n id={`${id}-${index}-placeholder`}\n type=\"text\"\n value={field.placeholder || ''}\n onChange={(e) => updateFormField(index, 'placeholder', e.target.value)}\n placeholder={t('workflows.fieldEditors.formFields.placeholderPlaceholder')}\n className=\"text-xs\"\n disabled={disabled}\n />\n </div>\n\n {/* Default Value */}\n <div>\n <Label htmlFor={`${id}-${index}-defaultValue`} className=\"text-xs font-medium mb-1\">\n {t('workflows.fieldEditors.formFields.defaultValue')}\n </Label>\n <Input\n id={`${id}-${index}-defaultValue`}\n type=\"text\"\n value={field.defaultValue || ''}\n onChange={(e) => updateFormField(index, 'defaultValue', e.target.value)}\n placeholder={t('workflows.fieldEditors.formFields.defaultValuePlaceholder')}\n className=\"text-xs\"\n disabled={disabled}\n />\n </div>\n\n {/* Options (for select/radio) */}\n {(field.type === 'select' || field.type === 'radio') && (\n <div>\n <Label htmlFor={`${id}-${index}-options`} className=\"text-xs font-medium mb-1\">\n {t('workflows.fieldEditors.formFields.options')}\n </Label>\n <Input\n id={`${id}-${index}-options`}\n type=\"text\"\n value={field.options?.join(', ') || ''}\n onChange={(e) =>\n updateFormField(\n index,\n 'options',\n e.target.value\n .split(',')\n .map((o) => o.trim())\n .filter(Boolean)\n )\n }\n placeholder={t('workflows.fieldEditors.formFields.optionsPlaceholder')}\n className=\"text-xs\"\n disabled={disabled}\n />\n <p className=\"text-xs text-muted-foreground mt-0.5\">{t('workflows.fieldEditors.formFields.optionsHint')}</p>\n </div>\n )}\n\n {/* Required Checkbox */}\n <div>\n <div className=\"flex items-center gap-2\">\n <input\n type=\"checkbox\"\n id={`${id}-${index}-required`}\n checked={field.required}\n onChange={(e) => updateFormField(index, 'required', e.target.checked)}\n className=\"h-4 w-4 rounded border-gray-300 text-blue-600 focus-visible:ring-ring\"\n disabled={disabled}\n />\n <Label htmlFor={`${id}-${index}-required`} className=\"text-xs font-medium cursor-pointer\">\n {t('workflows.fieldEditors.formFields.requiredField')}\n </Label>\n </div>\n </div>\n\n {/* Delete Button */}\n <div className=\"border-t border-gray-200 pt-3\">\n <Button\n type=\"button\"\n variant=\"destructive\"\n size=\"sm\"\n onClick={() => removeFormField(index)}\n disabled={disabled}\n >\n <Trash2 className=\"size-4 mr-1\" />\n {t('workflows.fieldEditors.formFields.removeField')}\n </Button>\n </div>\n </div>\n )}\n </div>\n )\n })}\n </div>\n )}\n {ConfirmDialogElement}\n </div>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["value"]
7
7
  }
@@ -2,6 +2,7 @@ export const id = "id";
2
2
  export const tenant = "tenant";
3
3
  export const name = "name";
4
4
  export const slug = "slug";
5
+ export const logo_url = "logo_url";
5
6
  export const is_active = "is_active";
6
7
  export const parent_id = "parent_id";
7
8
  export const root_id = "root_id";
@@ -1537,6 +1537,7 @@ export const entityFieldsRegistry: Record<string, Record<string, string>> = {
1537
1537
  "tenant": "tenant",
1538
1538
  "name": "name",
1539
1539
  "slug": "slug",
1540
+ "logo_url": "logo_url",
1540
1541
  "is_active": "is_active",
1541
1542
  "parent_id": "parent_id",
1542
1543
  "root_id": "root_id",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-mercato/core",
3
- "version": "0.6.5-develop.5337.1.534b781eac",
3
+ "version": "0.6.5",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "scripts": {
@@ -231,30 +231,30 @@
231
231
  "@mikro-orm/decorators": "^7.1.4",
232
232
  "@mikro-orm/postgresql": "^7.1.4",
233
233
  "@xyflow/react": "^12.11.0",
234
- "ai": "^6.0.198",
234
+ "ai": "^6.0.205",
235
235
  "date-fns": "4.4.0",
236
236
  "date-fns-tz": "^3.2.0",
237
237
  "html-to-text": "^10.0.0",
238
238
  "mammoth": "^1.9.0",
239
239
  "pdfjs-dist": "^6.0.227",
240
240
  "resend": "^6.12.4",
241
- "sanitize-html": "^2.13.0",
242
- "semver": "^7.8.3",
241
+ "sanitize-html": "^2.17.5",
242
+ "semver": "^7.8.4",
243
243
  "svix": "^1.95.2",
244
244
  "ts-pattern": "^5.0.0",
245
245
  "zod": "^4.4.3"
246
246
  },
247
247
  "peerDependencies": {
248
- "@open-mercato/ai-assistant": "0.6.5-develop.5337.1.534b781eac",
249
- "@open-mercato/shared": "0.6.5-develop.5337.1.534b781eac",
250
- "@open-mercato/ui": "0.6.5-develop.5337.1.534b781eac",
248
+ "@open-mercato/ai-assistant": "0.6.5",
249
+ "@open-mercato/shared": "0.6.5",
250
+ "@open-mercato/ui": "0.6.5",
251
251
  "react": "^19.0.0",
252
252
  "react-dom": "^19.0.0"
253
253
  },
254
254
  "devDependencies": {
255
- "@open-mercato/ai-assistant": "0.6.5-develop.5337.1.534b781eac",
256
- "@open-mercato/shared": "0.6.5-develop.5337.1.534b781eac",
257
- "@open-mercato/ui": "0.6.5-develop.5337.1.534b781eac",
255
+ "@open-mercato/ai-assistant": "0.6.5",
256
+ "@open-mercato/shared": "0.6.5",
257
+ "@open-mercato/ui": "0.6.5",
258
258
  "@testing-library/dom": "^10.4.1",
259
259
  "@testing-library/jest-dom": "^6.9.1",
260
260
  "@testing-library/react": "^16.3.1",
@@ -279,6 +279,5 @@
279
279
  "type": "git",
280
280
  "url": "https://github.com/open-mercato/open-mercato",
281
281
  "directory": "packages/core"
282
- },
283
- "stableVersion": "0.6.4"
282
+ }
284
283
  }
package/src/bootstrap.ts CHANGED
@@ -3,6 +3,7 @@ import { asValue } from 'awilix'
3
3
  import { createEventBus } from '@open-mercato/events/index'
4
4
  import { setGlobalEventBus } from '@open-mercato/shared/modules/events'
5
5
  import { createCacheService } from '@open-mercato/cache'
6
+ import type { CacheStrategy } from '@open-mercato/cache'
6
7
  import { createKmsService } from '@open-mercato/shared/lib/encryption/kms'
7
8
  import { TenantDataEncryptionService } from '@open-mercato/shared/lib/encryption/tenantDataEncryptionService'
8
9
  import { registerTenantEncryptionSubscriber } from '@open-mercato/shared/lib/encryption/subscriber'
@@ -21,6 +22,59 @@ import type { EntityManager } from '@mikro-orm/postgresql'
21
22
  const RL_GLOBAL_KEY = '__openMercatoRateLimiterService__'
22
23
  const RL_SHUTDOWN_KEY = '__openMercatoRateLimiterShutdown__'
23
24
 
25
+ const CACHE_GLOBAL_KEY = '__openMercatoCacheService__'
26
+ const CACHE_SHUTDOWN_KEY = '__openMercatoCacheShutdown__'
27
+
28
+ // Escape hatch: set OM_CACHE_SINGLETON=off to fall back to the legacy
29
+ // per-request cache instance (e.g. to isolate a regression). Default ON.
30
+ function isCacheSingletonEnabled(): boolean {
31
+ const raw = process.env.OM_CACHE_SINGLETON
32
+ if (raw === undefined) return true
33
+ const normalized = raw.trim().toLowerCase()
34
+ if (!normalized.length) return true
35
+ return !(normalized === '0' || normalized === 'off' || normalized === 'false' || normalized === 'no')
36
+ }
37
+
38
+ /**
39
+ * Process-wide cache service singleton, mirroring getCachedRateLimiterService.
40
+ *
41
+ * bootstrap() previously built a fresh cache per request container, so under
42
+ * the default memory strategy every cross-request cache was a no-op (each
43
+ * instance is process-local) and under sqlite each request leaked a native
44
+ * handle. Reusing one instance is safe by construction: tenant scope resolves
45
+ * per-call via AsyncLocalStorage (packages/cache/src/tenantContext.ts), so the
46
+ * service holds no request-bound state.
47
+ *
48
+ * Returns null when disabled via the escape hatch or when creation fails, so
49
+ * the caller falls back to a per-request instance.
50
+ */
51
+ export function getCachedCacheService(): CacheStrategy | null {
52
+ if (!isCacheSingletonEnabled()) return null
53
+ let service = (globalThis as any)[CACHE_GLOBAL_KEY] as CacheStrategy | null ?? null
54
+ if (!service) {
55
+ try {
56
+ try {
57
+ service = createCacheService()
58
+ } catch (err) {
59
+ console.warn('Cache service initialization failed; falling back to memory strategy:', (err as Error)?.message || err)
60
+ service = createCacheService({ strategy: 'memory' })
61
+ }
62
+ ;(globalThis as any)[CACHE_GLOBAL_KEY] = service
63
+
64
+ // Register shutdown hook once to close persistent handles (sqlite/redis) on process exit
65
+ if (!(globalThis as any)[CACHE_SHUTDOWN_KEY]) {
66
+ const shutdown = () => { service?.close?.().catch(() => {}) }
67
+ process.once('SIGTERM', shutdown)
68
+ process.once('SIGINT', shutdown)
69
+ ;(globalThis as any)[CACHE_SHUTDOWN_KEY] = true
70
+ }
71
+ } catch (err) {
72
+ console.warn('[cache] Failed to create cache service:', (err as Error)?.message || err)
73
+ }
74
+ }
75
+ return service
76
+ }
77
+
24
78
  export function getCachedRateLimiterService(): RateLimiterService | null {
25
79
  let service = (globalThis as any)[RL_GLOBAL_KEY] as RateLimiterService | null ?? null
26
80
  if (!service) {
@@ -50,13 +104,17 @@ export function getCachedRateLimiterService(): RateLimiterService | null {
50
104
  }
51
105
 
52
106
  export async function bootstrap(container: AwilixContainer) {
53
- // Create and register the cache service
54
- let cache: any
55
- try {
56
- cache = createCacheService()
57
- } catch (err: any) {
58
- console.warn('Cache service initialization failed; falling back to memory strategy:', err?.message || err)
59
- cache = createCacheService({ strategy: 'memory' })
107
+ // Register the cache service. Prefer the process-wide singleton so caches
108
+ // survive across request containers; fall back to a per-request instance
109
+ // when the singleton is disabled or fails to build.
110
+ let cache: any = getCachedCacheService()
111
+ if (!cache) {
112
+ try {
113
+ cache = createCacheService()
114
+ } catch (err: any) {
115
+ console.warn('Cache service initialization failed; falling back to memory strategy:', err?.message || err)
116
+ cache = createCacheService({ strategy: 'memory' })
117
+ }
60
118
  }
61
119
  container.register({ cache: asValue(cache) })
62
120
 
@@ -71,7 +71,23 @@ export async function createPersonFixture(
71
71
  export async function createDealFixture(
72
72
  request: APIRequestContext,
73
73
  token: string,
74
- input: { title: string; companyIds?: string[]; personIds?: string[]; pipelineId?: string; pipelineStageId?: string; valueAmount?: number; valueCurrency?: string },
74
+ input: {
75
+ title: string;
76
+ companyIds?: string[];
77
+ personIds?: string[];
78
+ pipelineId?: string;
79
+ pipelineStageId?: string;
80
+ valueAmount?: number;
81
+ valueCurrency?: string;
82
+ // Optional deal lifecycle fields — all valid on `dealCreateSchema`. Forwarded so KPI/summary
83
+ // tests can seed won/lost/overdue/owned deals across quarters (see TC-CRM-082). `status` is a
84
+ // free-form dictionary value (e.g. 'open', 'in_progress', 'win', 'loose'); `expectedCloseAt`
85
+ // accepts an ISO string (the schema coerces it to a Date); `closureOutcome` is 'won' | 'lost'.
86
+ status?: string;
87
+ expectedCloseAt?: string;
88
+ ownerUserId?: string;
89
+ closureOutcome?: 'won' | 'lost';
90
+ },
75
91
  ): Promise<string> {
76
92
  const data: Record<string, unknown> = { title: input.title };
77
93
  if (input.companyIds?.length) data.companyIds = input.companyIds;
@@ -80,6 +96,10 @@ export async function createDealFixture(
80
96
  if (input.pipelineStageId) data.pipelineStageId = input.pipelineStageId;
81
97
  if (input.valueAmount !== undefined) data.valueAmount = input.valueAmount;
82
98
  if (input.valueCurrency) data.valueCurrency = input.valueCurrency;
99
+ if (input.status) data.status = input.status;
100
+ if (input.expectedCloseAt) data.expectedCloseAt = input.expectedCloseAt;
101
+ if (input.ownerUserId) data.ownerUserId = input.ownerUserId;
102
+ if (input.closureOutcome) data.closureOutcome = input.closureOutcome;
83
103
  return createEntity(request, token, '/api/customers/deals', data, ['dealId', 'id', 'entityId']);
84
104
  }
85
105