From f4398cdb3ed4b29d83b32e1aa7de9e1b17b3841f Mon Sep 17 00:00:00 2001 From: Mahdi Date: Sun, 11 Oct 2026 16:48:37 +0330 Subject: [PATCH] fix(web): mobile automation canvas/inspector, compact activity row, timestamped comments --- .../activities/ActivityCommentSheet.vue | 28 ++++++- .../automations/AutomationCanvas.vue | 73 ++++++++++++++++++- .../automations/AutomationInspector.vue | 5 ++ apps/web/src/views/ActivitiesView.vue | 7 +- apps/web/src/views/ActivityDetailView.vue | 8 +- 5 files changed, 116 insertions(+), 5 deletions(-) diff --git a/apps/web/src/components/activities/ActivityCommentSheet.vue b/apps/web/src/components/activities/ActivityCommentSheet.vue index 050a4f7..05cb6fa 100644 --- a/apps/web/src/components/activities/ActivityCommentSheet.vue +++ b/apps/web/src/components/activities/ActivityCommentSheet.vue @@ -55,6 +55,12 @@ const dueLabel = computed(() => { return `${formatJalaliDay(d)} ${clock}`; }); +const now = ref(new Date()); +let clockTimer: ReturnType | undefined; +const nowLabel = computed( + () => `${formatJalaliDay(now.value)} ساعت ${formatClockFa(now.value)}`, +); + const canSubmit = computed( () => comment.value.trim().length > 0 && !props.saving && !voiceBusy.value, ); @@ -115,6 +121,9 @@ function onKeydown(ev: KeyboardEvent) { onMounted(async () => { document.body.style.overflow = 'hidden'; window.addEventListener('keydown', onKeydown); + clockTimer = setInterval(() => { + now.value = new Date(); + }, 30_000); await nextTick(); textareaRef.value?.focus(); try { @@ -143,6 +152,7 @@ onMounted(async () => { onBeforeUnmount(() => { document.body.style.overflow = ''; window.removeEventListener('keydown', onKeydown); + clearInterval(clockTimer); }); @@ -182,11 +192,15 @@ onBeforeUnmount(() => { {{ activity.assignee?.fullName || 'بدون مسئول' }} - + - {{ dueLabel }} + موعد: {{ dueLabel }} +

+ + زمان ثبت نظر: {{ nowLabel }} +

@@ -396,6 +410,16 @@ onBeforeUnmount(() => { border-top: 1px solid #f1f5f9; } +.stamp { + display: flex; + align-items: center; + gap: 0.3rem; + margin: 0.55rem 0 0; + color: #0f766e; + font-size: 0.8rem; + font-weight: 600; +} + .meta i { width: 1px; height: 14px; diff --git a/apps/web/src/components/automations/AutomationCanvas.vue b/apps/web/src/components/automations/AutomationCanvas.vue index 1055790..a6e8b21 100644 --- a/apps/web/src/components/automations/AutomationCanvas.vue +++ b/apps/web/src/components/automations/AutomationCanvas.vue @@ -674,9 +674,80 @@ strong { font-size: 0.78rem; } +/* موبایل: چیدمان عمودی؛ هر شاخه یک کارت زیر کارت قبلی */ @media (max-width: 700px) { + .canvas { + min-height: 0; + padding: 1rem 0.75rem; + } + + .flow, + .flow:has(.branches) { + flex-direction: column; + align-items: center; + min-width: 0; + min-height: 0; + padding-bottom: 0; + } + .node.trigger { - width: 13rem; + width: min(100%, 15rem); + } + + .wire, + .wire.stub { + width: 2px; + height: 2.1rem; + } + + .wire::after { + inset-inline-end: auto; + top: auto; + bottom: -1px; + left: 50%; + transform: translateX(-50%); + border-block: 0; + border-inline: 5px solid transparent; + border-top: 7px solid #cbd5e1; + } + + .wire.end { + width: 2px; + height: 2.4rem; + background: repeating-linear-gradient(180deg, #cbd5e1 0 6px, transparent 6px 10px); + } + + .branches { + align-items: stretch; + width: 100%; + gap: 0.75rem; + } + + .branch { + flex-direction: column; + align-items: center; + padding: 1.9rem 0.5rem 0.5rem; + border: 1px dashed #fed7aa; + border-radius: var(--radius); + background: rgba(255, 255, 255, 0.55); + } + + .branch::before { + display: none; + } + + .branch-tag { + top: 0.45rem; + inset-inline-start: 0.6rem; + } + + .add-branch { + position: static; + align-self: center; + } + + .picker { + max-width: none; } } diff --git a/apps/web/src/components/automations/AutomationInspector.vue b/apps/web/src/components/automations/AutomationInspector.vue index 938a8f0..d956272 100644 --- a/apps/web/src/components/automations/AutomationInspector.vue +++ b/apps/web/src/components/automations/AutomationInspector.vue @@ -506,6 +506,7 @@ watch(