From 4b130a81fdf8a694b5775e2570c0ee2cf9ba38ae Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 7 May 2025 15:29:55 -0600 Subject: [PATCH 1/5] timeout bi-directional navigation v1 --- .../SagaDiagram/SagaDiagramParser.ts | 19 ++++++ .../SagaDiagram/SagaOutgoingMessage.vue | 46 +++++++++++--- .../SagaOutgoingTimeoutMessage.vue | 60 ++++++++++++++++++- .../messages2/SagaDiagram/SagaUpdateNode.vue | 46 ++++++++++---- src/Frontend/src/stores/SagaDiagramStore.ts | 21 +++++++ 5 files changed, 173 insertions(+), 19 deletions(-) diff --git a/src/Frontend/src/components/messages2/SagaDiagram/SagaDiagramParser.ts b/src/Frontend/src/components/messages2/SagaDiagram/SagaDiagramParser.ts index f1854f13e..910f30e9d 100644 --- a/src/Frontend/src/components/messages2/SagaDiagram/SagaDiagramParser.ts +++ b/src/Frontend/src/components/messages2/SagaDiagram/SagaDiagramParser.ts @@ -17,6 +17,8 @@ export interface InitiatingMessageViewModel { FormattedMessageTimestamp: string; IsEventMessage: boolean; MessageData: SagaMessageDataItem[]; + HasRelatedTimeoutRequest?: boolean; + MessageId: string; } export interface SagaTimeoutMessageViewModel extends SagaMessageViewModel { TimeoutFriendly: string; @@ -57,6 +59,18 @@ export interface SagaViewModel { export function parseSagaUpdates(sagaHistory: SagaHistory | null, messagesData: SagaMessageData[]): SagaUpdateViewModel[] { if (!sagaHistory || !sagaHistory.changes || !sagaHistory.changes.length) return []; + const timeoutMessageIds = new Set(); + sagaHistory.changes.forEach((update) => { + if (update.outgoing_messages) { + update.outgoing_messages.forEach((msg) => { + const delivery_delay = msg.delivery_delay || "00:00:00"; + if (delivery_delay && delivery_delay !== "00:00:00") { + timeoutMessageIds.add(msg.message_id); + } + }); + } + }); + const updates = sagaHistory.changes .map((update) => { const startTime = new Date(update.start_time); @@ -107,6 +121,9 @@ export function parseSagaUpdates(sagaHistory: SagaHistory | null, messagesData: const hasTimeout = outgoingTimeoutMessages.length > 0; + // Check if initiating message is a timeout and if so, if it has a corresponding request in the diagram + const hasRelatedTimeoutRequest = update.initiating_message?.is_saga_timeout_message && timeoutMessageIds.has(update.initiating_message?.message_id); + return { MessageId: update.initiating_message?.message_id || "", StartTime: startTime, @@ -115,11 +132,13 @@ export function parseSagaUpdates(sagaHistory: SagaHistory | null, messagesData: Status: update.status, StatusDisplay: update.status === "new" ? "Saga Initiated" : "Saga Updated", InitiatingMessage: { + MessageId: update.initiating_message?.message_id || "", MessageType: typeToName(update.initiating_message?.message_type || "Unknown Message") || "", FormattedMessageTimestamp: `${initiatingMessageTimestamp.toLocaleDateString()} ${initiatingMessageTimestamp.toLocaleTimeString()}`, MessageData: initiatingMessageData, IsEventMessage: update.initiating_message?.intent === "Publish", IsSagaTimeoutMessage: update.initiating_message?.is_saga_timeout_message || false, + HasRelatedTimeoutRequest: hasRelatedTimeoutRequest, }, HasTimeout: hasTimeout, IsFirstNode: update.status === "new", diff --git a/src/Frontend/src/components/messages2/SagaDiagram/SagaOutgoingMessage.vue b/src/Frontend/src/components/messages2/SagaDiagram/SagaOutgoingMessage.vue index 433a84d78..ac9fa61c6 100644 --- a/src/Frontend/src/components/messages2/SagaDiagram/SagaOutgoingMessage.vue +++ b/src/Frontend/src/components/messages2/SagaDiagram/SagaOutgoingMessage.vue @@ -3,15 +3,35 @@ import MessageDataBox from "./MessageDataBox.vue"; import CommandIcon from "@/assets/command.svg"; import EventIcon from "@/assets/event.svg"; import { SagaMessageViewModel } from "./SagaDiagramParser"; +import { useSagaDiagramStore } from "@/stores/SagaDiagramStore"; +import { ref, watch } from "vue"; +const isActive = ref(false); -defineProps<{ +const store = useSagaDiagramStore(); + +const props = defineProps<{ message: SagaMessageViewModel; showMessageData?: boolean; }>(); + +watch( + () => store.selectedMessageId, + (newMessageId) => { + // Check if this node contains the selected message + isActive.value = newMessageId === props.message.MessageId; + }, + { immediate: true } +);