@open-mercato/core 0.6.3-develop.3876.1.d40fe4ec2d → 0.6.3-develop.3881.1.0b590ac4eb

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 (107) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/modules/attachments/api/file/[id]/route.js +7 -2
  3. package/dist/modules/attachments/api/file/[id]/route.js.map +2 -2
  4. package/dist/modules/attachments/api/image/[id]/[[...slug]]/route.js +7 -4
  5. package/dist/modules/attachments/api/image/[id]/[[...slug]]/route.js.map +2 -2
  6. package/dist/modules/audit_logs/services/accessLogService.js +127 -8
  7. package/dist/modules/audit_logs/services/accessLogService.js.map +2 -2
  8. package/dist/modules/auth/di.js +17 -3
  9. package/dist/modules/auth/di.js.map +2 -2
  10. package/dist/modules/auth/services/rbacDefaultCache.js +110 -0
  11. package/dist/modules/auth/services/rbacDefaultCache.js.map +7 -0
  12. package/dist/modules/currencies/api/currencies/route.js +3 -4
  13. package/dist/modules/currencies/api/currencies/route.js.map +2 -2
  14. package/dist/modules/currencies/api/exchange-rates/route.js +3 -4
  15. package/dist/modules/currencies/api/exchange-rates/route.js.map +2 -2
  16. package/dist/modules/customers/api/people/route.js +26 -24
  17. package/dist/modules/customers/api/people/route.js.map +2 -2
  18. package/dist/modules/directory/subscribers/invalidateOrgScopeCache.js +26 -0
  19. package/dist/modules/directory/subscribers/invalidateOrgScopeCache.js.map +7 -0
  20. package/dist/modules/directory/utils/organizationScope.js +85 -0
  21. package/dist/modules/directory/utils/organizationScope.js.map +2 -2
  22. package/dist/modules/workflows/backend/definitions/[id]/page.js +2 -1
  23. package/dist/modules/workflows/backend/definitions/[id]/page.js.map +2 -2
  24. package/dist/modules/workflows/backend/definitions/create/page.js +4 -2
  25. package/dist/modules/workflows/backend/definitions/create/page.js.map +2 -2
  26. package/dist/modules/workflows/backend/definitions/visual-editor/page.js +20 -3
  27. package/dist/modules/workflows/backend/definitions/visual-editor/page.js.map +2 -2
  28. package/dist/modules/workflows/components/ActivitiesEditor.js +34 -1
  29. package/dist/modules/workflows/components/ActivitiesEditor.js.map +2 -2
  30. package/dist/modules/workflows/components/NodeEditDialog.js +153 -17
  31. package/dist/modules/workflows/components/NodeEditDialog.js.map +2 -2
  32. package/dist/modules/workflows/components/StepsEditor.js +31 -0
  33. package/dist/modules/workflows/components/StepsEditor.js.map +2 -2
  34. package/dist/modules/workflows/components/WorkflowGraph.js +3 -2
  35. package/dist/modules/workflows/components/WorkflowGraph.js.map +2 -2
  36. package/dist/modules/workflows/components/nodes/WaitForTimerNode.js +54 -0
  37. package/dist/modules/workflows/components/nodes/WaitForTimerNode.js.map +7 -0
  38. package/dist/modules/workflows/components/nodes/index.js +3 -1
  39. package/dist/modules/workflows/components/nodes/index.js.map +2 -2
  40. package/dist/modules/workflows/data/validators.js +117 -0
  41. package/dist/modules/workflows/data/validators.js.map +2 -2
  42. package/dist/modules/workflows/di.js +5 -1
  43. package/dist/modules/workflows/di.js.map +2 -2
  44. package/dist/modules/workflows/lib/activity-executor.js +42 -1
  45. package/dist/modules/workflows/lib/activity-executor.js.map +2 -2
  46. package/dist/modules/workflows/lib/activity-queue-types.js.map +2 -2
  47. package/dist/modules/workflows/lib/activity-worker-handler.js +24 -0
  48. package/dist/modules/workflows/lib/activity-worker-handler.js.map +2 -2
  49. package/dist/modules/workflows/lib/duration.js +32 -0
  50. package/dist/modules/workflows/lib/duration.js.map +7 -0
  51. package/dist/modules/workflows/lib/event-logger.js +1 -0
  52. package/dist/modules/workflows/lib/event-logger.js.map +2 -2
  53. package/dist/modules/workflows/lib/format-validation-error.js +12 -0
  54. package/dist/modules/workflows/lib/format-validation-error.js.map +7 -0
  55. package/dist/modules/workflows/lib/graph-utils.js +6 -3
  56. package/dist/modules/workflows/lib/graph-utils.js.map +2 -2
  57. package/dist/modules/workflows/lib/node-type-icons.js +9 -5
  58. package/dist/modules/workflows/lib/node-type-icons.js.map +2 -2
  59. package/dist/modules/workflows/lib/signal-handler.js +55 -23
  60. package/dist/modules/workflows/lib/signal-handler.js.map +2 -2
  61. package/dist/modules/workflows/lib/step-handler.js +79 -29
  62. package/dist/modules/workflows/lib/step-handler.js.map +2 -2
  63. package/dist/modules/workflows/lib/timer-handler.js +159 -0
  64. package/dist/modules/workflows/lib/timer-handler.js.map +7 -0
  65. package/dist/modules/workflows/lib/workflow-executor.js +1 -1
  66. package/dist/modules/workflows/lib/workflow-executor.js.map +2 -2
  67. package/dist/modules/workflows/workers/workflow-activities.worker.js +20 -4
  68. package/dist/modules/workflows/workers/workflow-activities.worker.js.map +2 -2
  69. package/package.json +7 -7
  70. package/src/modules/attachments/api/file/[id]/route.ts +7 -2
  71. package/src/modules/attachments/api/image/[id]/[[...slug]]/route.ts +7 -4
  72. package/src/modules/audit_logs/services/accessLogService.ts +179 -15
  73. package/src/modules/auth/di.ts +26 -3
  74. package/src/modules/auth/services/rbacDefaultCache.ts +145 -0
  75. package/src/modules/currencies/api/currencies/route.ts +3 -4
  76. package/src/modules/currencies/api/exchange-rates/route.ts +3 -4
  77. package/src/modules/customers/api/people/route.ts +27 -25
  78. package/src/modules/directory/subscribers/invalidateOrgScopeCache.ts +39 -0
  79. package/src/modules/directory/utils/organizationScope.ts +121 -0
  80. package/src/modules/workflows/backend/definitions/[id]/page.tsx +3 -2
  81. package/src/modules/workflows/backend/definitions/create/page.tsx +4 -2
  82. package/src/modules/workflows/backend/definitions/visual-editor/page.tsx +18 -1
  83. package/src/modules/workflows/components/ActivitiesEditor.tsx +40 -0
  84. package/src/modules/workflows/components/NodeEditDialog.tsx +218 -30
  85. package/src/modules/workflows/components/StepsEditor.tsx +36 -0
  86. package/src/modules/workflows/components/WorkflowGraph.tsx +2 -1
  87. package/src/modules/workflows/components/nodes/WaitForTimerNode.tsx +70 -0
  88. package/src/modules/workflows/components/nodes/index.ts +3 -0
  89. package/src/modules/workflows/data/validators.ts +121 -0
  90. package/src/modules/workflows/di.ts +4 -0
  91. package/src/modules/workflows/i18n/de.json +10 -1
  92. package/src/modules/workflows/i18n/en.json +10 -1
  93. package/src/modules/workflows/i18n/es.json +10 -1
  94. package/src/modules/workflows/i18n/pl.json +10 -1
  95. package/src/modules/workflows/lib/activity-executor.ts +86 -2
  96. package/src/modules/workflows/lib/activity-queue-types.ts +18 -11
  97. package/src/modules/workflows/lib/activity-worker-handler.ts +29 -0
  98. package/src/modules/workflows/lib/duration.ts +51 -0
  99. package/src/modules/workflows/lib/event-logger.ts +1 -0
  100. package/src/modules/workflows/lib/format-validation-error.ts +30 -0
  101. package/src/modules/workflows/lib/graph-utils.ts +3 -0
  102. package/src/modules/workflows/lib/node-type-icons.ts +6 -2
  103. package/src/modules/workflows/lib/signal-handler.ts +62 -24
  104. package/src/modules/workflows/lib/step-handler.ts +107 -50
  105. package/src/modules/workflows/lib/timer-handler.ts +213 -0
  106. package/src/modules/workflows/lib/workflow-executor.ts +1 -1
  107. package/src/modules/workflows/workers/workflow-activities.worker.ts +33 -7
@@ -20,6 +20,7 @@ import { JsonBuilder } from "@open-mercato/ui/backend/JsonBuilder";
20
20
  import { StartPreConditionsEditor } from "./fields/StartPreConditionsEditor.js";
21
21
  import { useT } from "@open-mercato/shared/lib/i18n/context";
22
22
  import { useConfirmDialog } from "@open-mercato/ui/backend/confirm-dialog";
23
+ import { isFutureIsoDateString, isValidDurationString } from "../data/validators.js";
23
24
  function NodeEditDialog({ node, isOpen, onClose, onSave, onDelete }) {
24
25
  const t = useT();
25
26
  const { confirm: confirmDialog, ConfirmDialogElement } = useConfirmDialog();
@@ -46,9 +47,12 @@ function NodeEditDialog({ node, isOpen, onClose, onSave, onDelete }) {
46
47
  const [showWorkflowSelector, setShowWorkflowSelector] = useState(false);
47
48
  const [signalName, setSignalName] = useState("");
48
49
  const [signalTimeout, setSignalTimeout] = useState("");
50
+ const [timerDuration, setTimerDuration] = useState("");
51
+ const [timerUntil, setTimerUntil] = useState("");
49
52
  const [stepActivities, setStepActivities] = useState([]);
50
53
  const [expandedStepActivities, setExpandedStepActivities] = useState(/* @__PURE__ */ new Set());
51
54
  const [preConditions, setPreConditions] = useState([]);
55
+ const [fieldErrors, setFieldErrors] = useState({});
52
56
  const convertJsonSchemaToFields = (schema) => {
53
57
  if (!schema || !schema.properties) return [];
54
58
  const fields = [];
@@ -147,6 +151,13 @@ function NodeEditDialog({ node, isOpen, onClose, onSave, onDelete }) {
147
151
  setSignalName("");
148
152
  setSignalTimeout("");
149
153
  }
154
+ if (node.type === "waitForTimer") {
155
+ setTimerDuration(nodeData?.config?.duration || "");
156
+ setTimerUntil(nodeData?.config?.until || "");
157
+ } else {
158
+ setTimerDuration("");
159
+ setTimerUntil("");
160
+ }
150
161
  if (node.type === "automated" && nodeData?.activities) {
151
162
  setStepActivities(nodeData.activities);
152
163
  } else if (node.type === "automated") {
@@ -182,6 +193,7 @@ function NodeEditDialog({ node, isOpen, onClose, onSave, onDelete }) {
182
193
  }
183
194
  setAdvancedConfig(advancedFields);
184
195
  setExpandedFields(/* @__PURE__ */ new Set());
196
+ setFieldErrors({});
185
197
  }
186
198
  }, [node, isOpen]);
187
199
  const addFormField = () => {
@@ -230,6 +242,23 @@ function NodeEditDialog({ node, isOpen, onClose, onSave, onDelete }) {
230
242
  };
231
243
  const handleSave = () => {
232
244
  if (!node) return;
245
+ const errors = {};
246
+ if (node.type === "waitForTimer") {
247
+ if (timerDuration && !isValidDurationString(timerDuration)) {
248
+ errors.timerDuration = t("workflows.validation.invalidDuration");
249
+ }
250
+ if (timerUntil && !isFutureIsoDateString(timerUntil)) {
251
+ errors.timerUntil = t("workflows.validation.untilMustBeFuture");
252
+ }
253
+ }
254
+ if (node.type === "waitForSignal" && signalTimeout && !isValidDurationString(signalTimeout)) {
255
+ errors.signalTimeout = t("workflows.validation.invalidDuration");
256
+ }
257
+ if (Object.keys(errors).length > 0) {
258
+ setFieldErrors(errors);
259
+ return;
260
+ }
261
+ setFieldErrors({});
233
262
  const sanitizedId = sanitizeId(node.id);
234
263
  if (sanitizedId !== node.id) {
235
264
  alert(t("workflows.nodeEditor.stepIdSanitized", { from: node.id, to: sanitizedId }));
@@ -296,6 +325,15 @@ function NodeEditDialog({ node, isOpen, onClose, onSave, onDelete }) {
296
325
  updates.signalConfig = config;
297
326
  }
298
327
  }
328
+ if (node.type === "waitForTimer") {
329
+ const config = {};
330
+ if (timerDuration) {
331
+ config.duration = timerDuration;
332
+ } else if (timerUntil) {
333
+ config.until = timerUntil;
334
+ }
335
+ updates.config = Object.keys(config).length > 0 ? config : void 0;
336
+ }
299
337
  if (node.type === "automated" && stepActivities.length > 0) {
300
338
  updates.activities = stepActivities;
301
339
  }
@@ -326,7 +364,10 @@ function NodeEditDialog({ node, isOpen, onClose, onSave, onDelete }) {
326
364
  end: t("workflows.nodeTypes.end"),
327
365
  userTask: t("workflows.nodeTypes.userTask"),
328
366
  automated: t("workflows.nodeTypes.automated"),
329
- decision: t("workflows.nodeTypes.decision")
367
+ decision: t("workflows.nodeTypes.decision"),
368
+ waitForSignal: t("workflows.nodeTypes.waitForSignal"),
369
+ waitForTimer: t("workflows.nodeTypes.waitForTimer"),
370
+ subWorkflow: t("workflows.nodeTypes.subWorkflow")
330
371
  }[node.type || "automated"];
331
372
  const isEditable = node.type !== "end";
332
373
  const isStartNode = node.type === "start";
@@ -402,7 +443,7 @@ function NodeEditDialog({ node, isOpen, onClose, onSave, onDelete }) {
402
443
  ),
403
444
  /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500 mt-1", children: t("workflows.form.descriptions.description") })
404
445
  ] }),
405
- /* @__PURE__ */ jsxs("div", { children: [
446
+ node.type !== "waitForSignal" && node.type !== "waitForTimer" && /* @__PURE__ */ jsxs("div", { children: [
406
447
  /* @__PURE__ */ jsx("label", { className: "block text-sm font-medium text-gray-700 mb-1", children: t("workflows.form.timeout") }),
407
448
  /* @__PURE__ */ jsx(
408
449
  Input,
@@ -416,7 +457,7 @@ function NodeEditDialog({ node, isOpen, onClose, onSave, onDelete }) {
416
457
  /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500 mt-1", children: t("workflows.form.descriptions.timeout") })
417
458
  ] }),
418
459
  node.type === "userTask" && /* @__PURE__ */ jsxs(Fragment, { children: [
419
- /* @__PURE__ */ jsx("div", { className: "border-t border-gray-200 pt-4 mt-4", children: /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-gray-900 mb-3", children: t("workflows.nodeEditor.userTaskConfig") }) }),
460
+ /* @__PURE__ */ jsx("div", { className: "border-t border-gray-200 pt-4 mt-4", children: /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-foreground mb-3", children: t("workflows.nodeEditor.userTaskConfig") }) }),
420
461
  /* @__PURE__ */ jsxs("div", { children: [
421
462
  /* @__PURE__ */ jsx("label", { className: "block text-sm font-medium text-gray-700 mb-1", children: t("workflows.form.assignedTo") }),
422
463
  /* @__PURE__ */ jsx(
@@ -459,7 +500,7 @@ function NodeEditDialog({ node, isOpen, onClose, onSave, onDelete }) {
459
500
  /* @__PURE__ */ jsxs("div", { className: "border-t border-gray-200 pt-4 mt-4", children: [
460
501
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-3", children: [
461
502
  /* @__PURE__ */ jsxs("div", { children: [
462
- /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-gray-900", children: t("workflows.form.formFields", { count: formFields.length }) }),
503
+ /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-foreground", children: t("workflows.form.formFields", { count: formFields.length }) }),
463
504
  /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500 mt-0.5", children: t("workflows.form.descriptions.formFields") })
464
505
  ] }),
465
506
  /* @__PURE__ */ jsxs(
@@ -492,7 +533,7 @@ function NodeEditDialog({ node, isOpen, onClose, onSave, onDelete }) {
492
533
  children: [
493
534
  /* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
494
535
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
495
- /* @__PURE__ */ jsx("span", { className: "text-sm font-semibold text-gray-900", children: field.label || field.name }),
536
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-semibold text-foreground", children: field.label || field.name }),
496
537
  /* @__PURE__ */ jsx(Badge, { variant: "secondary", className: "text-xs", children: field.type }),
497
538
  field.required && /* @__PURE__ */ jsx(Badge, { variant: "destructive", className: "text-xs text-white", children: t("workflows.form.required") })
498
539
  ] }),
@@ -648,7 +689,7 @@ function NodeEditDialog({ node, isOpen, onClose, onSave, onDelete }) {
648
689
  node.type === "automated" && /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs("div", { className: "border-t border-gray-200 pt-4 mt-4", children: [
649
690
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-3", children: [
650
691
  /* @__PURE__ */ jsxs("div", { children: [
651
- /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-gray-900", children: t("workflows.form.stepActivities", { count: stepActivities.length }) }),
692
+ /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-foreground", children: t("workflows.form.stepActivities", { count: stepActivities.length }) }),
652
693
  /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500 mt-0.5", children: t("workflows.form.descriptions.activities") })
653
694
  ] }),
654
695
  /* @__PURE__ */ jsxs(
@@ -696,7 +737,7 @@ function NodeEditDialog({ node, isOpen, onClose, onSave, onDelete }) {
696
737
  children: [
697
738
  /* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
698
739
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
699
- /* @__PURE__ */ jsx("span", { className: "text-sm font-semibold text-gray-900", children: activity.activityName || activity.activityId || `Activity ${index + 1}` }),
740
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-semibold text-foreground", children: activity.activityName || activity.activityId || `Activity ${index + 1}` }),
700
741
  /* @__PURE__ */ jsx(Badge, { variant: "secondary", className: "text-xs", children: activity.activityType }),
701
742
  activity.async && /* @__PURE__ */ jsx(Badge, { variant: "outline", className: "text-xs", children: t("workflows.form.async") })
702
743
  ] }),
@@ -777,7 +818,8 @@ function NodeEditDialog({ node, isOpen, onClose, onSave, onDelete }) {
777
818
  /* @__PURE__ */ jsx(SelectItem, { value: "UPDATE_ENTITY", children: t("workflows.activities.types.UPDATE_ENTITY") }),
778
819
  /* @__PURE__ */ jsx(SelectItem, { value: "EMIT_EVENT", children: t("workflows.activities.types.EMIT_EVENT") }),
779
820
  /* @__PURE__ */ jsx(SelectItem, { value: "CALL_WEBHOOK", children: t("workflows.activities.types.CALL_WEBHOOK") }),
780
- /* @__PURE__ */ jsx(SelectItem, { value: "EXECUTE_FUNCTION", children: t("workflows.activities.types.EXECUTE_FUNCTION") })
821
+ /* @__PURE__ */ jsx(SelectItem, { value: "EXECUTE_FUNCTION", children: t("workflows.activities.types.EXECUTE_FUNCTION") }),
822
+ /* @__PURE__ */ jsx(SelectItem, { value: "WAIT", children: t("workflows.activities.types.WAIT") })
781
823
  ] })
782
824
  ]
783
825
  }
@@ -893,7 +935,45 @@ function NodeEditDialog({ node, isOpen, onClose, onSave, onDelete }) {
893
935
  ),
894
936
  /* @__PURE__ */ jsx("span", { className: "text-xs text-gray-700", children: t("workflows.form.executeAsync") })
895
937
  ] }) }),
896
- /* @__PURE__ */ jsxs("div", { children: [
938
+ activity.activityType === "WAIT" && /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
939
+ /* @__PURE__ */ jsxs("div", { children: [
940
+ /* @__PURE__ */ jsx("label", { className: "block text-xs font-medium text-gray-700 mb-1", children: t("workflows.activities.waitDuration") }),
941
+ /* @__PURE__ */ jsx(
942
+ Input,
943
+ {
944
+ size: "sm",
945
+ type: "text",
946
+ value: activity.config?.duration || "",
947
+ onChange: (e) => {
948
+ const updated = [...stepActivities];
949
+ updated[index].config = { ...updated[index].config, duration: e.target.value, until: void 0 };
950
+ setStepActivities(updated);
951
+ },
952
+ placeholder: t("workflows.activities.waitDurationPlaceholder")
953
+ }
954
+ ),
955
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-1", children: t("workflows.activities.waitDurationDescription") })
956
+ ] }),
957
+ /* @__PURE__ */ jsx("div", { className: "text-xs text-center text-muted-foreground", children: t("workflows.activities.waitOr") }),
958
+ /* @__PURE__ */ jsxs("div", { children: [
959
+ /* @__PURE__ */ jsx("label", { className: "block text-xs font-medium text-gray-700 mb-1", children: t("workflows.activities.waitUntil") }),
960
+ /* @__PURE__ */ jsx(
961
+ Input,
962
+ {
963
+ size: "sm",
964
+ type: "datetime-local",
965
+ value: activity.config?.until ? activity.config.until.slice(0, 16) : "",
966
+ onChange: (e) => {
967
+ const updated = [...stepActivities];
968
+ updated[index].config = { ...updated[index].config, until: e.target.value ? new Date(e.target.value).toISOString() : void 0, duration: void 0 };
969
+ setStepActivities(updated);
970
+ }
971
+ }
972
+ ),
973
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-1", children: t("workflows.activities.waitUntilDescription") })
974
+ ] })
975
+ ] }),
976
+ activity.activityType !== "WAIT" && /* @__PURE__ */ jsxs("div", { children: [
897
977
  /* @__PURE__ */ jsx("label", { className: "block text-xs font-medium text-gray-700 mb-1", children: t("workflows.form.configuration") }),
898
978
  /* @__PURE__ */ jsx(
899
979
  JsonBuilder,
@@ -931,7 +1011,7 @@ function NodeEditDialog({ node, isOpen, onClose, onSave, onDelete }) {
931
1011
  }) })
932
1012
  ] }) }),
933
1013
  node.type === "subWorkflow" && /* @__PURE__ */ jsxs(Fragment, { children: [
934
- /* @__PURE__ */ jsx("div", { className: "border-t border-gray-200 pt-4 mt-4", children: /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-gray-900 mb-3", children: t("workflows.form.subWorkflowConfig") }) }),
1014
+ /* @__PURE__ */ jsx("div", { className: "border-t border-gray-200 pt-4 mt-4", children: /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-foreground mb-3", children: t("workflows.form.subWorkflowConfig") }) }),
935
1015
  /* @__PURE__ */ jsxs("div", { children: [
936
1016
  /* @__PURE__ */ jsxs("label", { className: "block text-sm font-medium text-gray-700 mb-1", children: [
937
1017
  t("workflows.form.workflowToInvoke"),
@@ -977,7 +1057,7 @@ function NodeEditDialog({ node, isOpen, onClose, onSave, onDelete }) {
977
1057
  /* @__PURE__ */ jsxs("div", { className: "border-t border-gray-200 pt-4 mt-4", children: [
978
1058
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-3", children: [
979
1059
  /* @__PURE__ */ jsxs("div", { children: [
980
- /* @__PURE__ */ jsx("h4", { className: "text-sm font-semibold text-gray-900", children: t("workflows.form.inputMapping", { count: inputMappings.length }) }),
1060
+ /* @__PURE__ */ jsx("h4", { className: "text-sm font-semibold text-foreground", children: t("workflows.form.inputMapping", { count: inputMappings.length }) }),
981
1061
  /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500 mt-0.5", children: t("workflows.form.descriptions.inputMapping") })
982
1062
  ] }),
983
1063
  /* @__PURE__ */ jsxs(
@@ -1045,7 +1125,7 @@ function NodeEditDialog({ node, isOpen, onClose, onSave, onDelete }) {
1045
1125
  /* @__PURE__ */ jsxs("div", { className: "border-t border-gray-200 pt-4 mt-4", children: [
1046
1126
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-3", children: [
1047
1127
  /* @__PURE__ */ jsxs("div", { children: [
1048
- /* @__PURE__ */ jsx("h4", { className: "text-sm font-semibold text-gray-900", children: t("workflows.form.outputMapping", { count: outputMappings.length }) }),
1128
+ /* @__PURE__ */ jsx("h4", { className: "text-sm font-semibold text-foreground", children: t("workflows.form.outputMapping", { count: outputMappings.length }) }),
1049
1129
  /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500 mt-0.5", children: t("workflows.form.descriptions.outputMapping") })
1050
1130
  ] }),
1051
1131
  /* @__PURE__ */ jsxs(
@@ -1112,7 +1192,7 @@ function NodeEditDialog({ node, isOpen, onClose, onSave, onDelete }) {
1112
1192
  ] })
1113
1193
  ] }),
1114
1194
  node.type === "waitForSignal" && /* @__PURE__ */ jsxs(Fragment, { children: [
1115
- /* @__PURE__ */ jsx("div", { className: "border-t border-gray-200 pt-4 mt-4", children: /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-gray-900 mb-3", children: t("workflows.form.signalConfig") }) }),
1195
+ /* @__PURE__ */ jsx("div", { className: "border-t border-gray-200 pt-4 mt-4", children: /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-foreground mb-3", children: t("workflows.form.signalConfig") }) }),
1116
1196
  /* @__PURE__ */ jsxs("div", { children: [
1117
1197
  /* @__PURE__ */ jsxs("label", { className: "block text-sm font-medium text-gray-700 mb-1", children: [
1118
1198
  t("workflows.form.signalName"),
@@ -1136,11 +1216,67 @@ function NodeEditDialog({ node, isOpen, onClose, onSave, onDelete }) {
1136
1216
  {
1137
1217
  type: "text",
1138
1218
  value: signalTimeout,
1139
- onChange: (e) => setSignalTimeout(e.target.value),
1140
- placeholder: t("workflows.form.placeholders.signalTimeout")
1219
+ onChange: (e) => {
1220
+ setSignalTimeout(e.target.value);
1221
+ if (fieldErrors.signalTimeout) {
1222
+ const next = { ...fieldErrors };
1223
+ delete next.signalTimeout;
1224
+ setFieldErrors(next);
1225
+ }
1226
+ },
1227
+ placeholder: t("workflows.form.placeholders.signalTimeout"),
1228
+ "aria-invalid": fieldErrors.signalTimeout ? true : void 0
1229
+ }
1230
+ ),
1231
+ fieldErrors.signalTimeout ? /* @__PURE__ */ jsx("p", { className: "text-xs text-destructive mt-1", children: fieldErrors.signalTimeout }) : /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500 mt-1", children: t("workflows.form.descriptions.signalTimeout") })
1232
+ ] })
1233
+ ] }),
1234
+ node.type === "waitForTimer" && /* @__PURE__ */ jsxs(Fragment, { children: [
1235
+ /* @__PURE__ */ jsx("div", { className: "border-t border-gray-200 pt-4 mt-4", children: /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-foreground mb-3", children: t("workflows.steps.types.WAIT_FOR_TIMER") }) }),
1236
+ /* @__PURE__ */ jsxs("div", { children: [
1237
+ /* @__PURE__ */ jsx("label", { className: "block text-sm font-medium text-gray-700 mb-1", children: t("workflows.activities.waitDuration") }),
1238
+ /* @__PURE__ */ jsx(
1239
+ Input,
1240
+ {
1241
+ type: "text",
1242
+ value: timerDuration,
1243
+ onChange: (e) => {
1244
+ setTimerDuration(e.target.value);
1245
+ if (e.target.value) setTimerUntil("");
1246
+ if (fieldErrors.timerDuration) {
1247
+ const next = { ...fieldErrors };
1248
+ delete next.timerDuration;
1249
+ setFieldErrors(next);
1250
+ }
1251
+ },
1252
+ placeholder: t("workflows.activities.waitDurationPlaceholder"),
1253
+ "aria-invalid": fieldErrors.timerDuration ? true : void 0
1254
+ }
1255
+ ),
1256
+ fieldErrors.timerDuration ? /* @__PURE__ */ jsx("p", { className: "text-xs text-destructive mt-1", children: fieldErrors.timerDuration }) : /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500 mt-1", children: t("workflows.activities.waitDurationDescription") })
1257
+ ] }),
1258
+ /* @__PURE__ */ jsxs("div", { children: [
1259
+ /* @__PURE__ */ jsx("label", { className: "block text-sm font-medium text-gray-700 mb-1", children: t("workflows.activities.waitUntil") }),
1260
+ /* @__PURE__ */ jsx(
1261
+ Input,
1262
+ {
1263
+ type: "datetime-local",
1264
+ value: timerUntil ? timerUntil.slice(0, 16) : "",
1265
+ min: new Date(Date.now() - (/* @__PURE__ */ new Date()).getTimezoneOffset() * 6e4).toISOString().slice(0, 16),
1266
+ onChange: (e) => {
1267
+ const next = e.target.value ? new Date(e.target.value).toISOString() : "";
1268
+ setTimerUntil(next);
1269
+ if (next) setTimerDuration("");
1270
+ if (fieldErrors.timerUntil) {
1271
+ const nextErrors = { ...fieldErrors };
1272
+ delete nextErrors.timerUntil;
1273
+ setFieldErrors(nextErrors);
1274
+ }
1275
+ },
1276
+ "aria-invalid": fieldErrors.timerUntil ? true : void 0
1141
1277
  }
1142
1278
  ),
1143
- /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500 mt-1", children: t("workflows.form.descriptions.signalTimeout") })
1279
+ fieldErrors.timerUntil ? /* @__PURE__ */ jsx("p", { className: "text-xs text-destructive mt-1", children: fieldErrors.timerUntil }) : /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500 mt-1", children: t("workflows.activities.waitUntilDescription") })
1144
1280
  ] })
1145
1281
  ] }),
1146
1282
  /* @__PURE__ */ jsxs("div", { className: "border-t border-gray-200 pt-4 mt-4", children: [
@@ -1151,7 +1287,7 @@ function NodeEditDialog({ node, isOpen, onClose, onSave, onDelete }) {
1151
1287
  onClick: () => setShowAdvanced(!showAdvanced),
1152
1288
  className: "flex items-center justify-between w-full text-left",
1153
1289
  children: [
1154
- /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-gray-900", children: t("workflows.form.advancedConfiguration") }),
1290
+ /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-foreground", children: t("workflows.form.advancedConfiguration") }),
1155
1291
  /* @__PURE__ */ jsx(
1156
1292
  "svg",
1157
1293
  {