Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export interface InitiatingMessageViewModel {
}
export interface SagaTimeoutMessageViewModel extends SagaMessageViewModel {
TimeoutFriendly: string;
HasBeenProcessed: boolean;
}

export interface SagaUpdateViewModel {
Expand Down Expand Up @@ -88,19 +89,22 @@ export function parseSagaUpdates(sagaHistory: SagaHistory | null, messagesData:

const outgoingTimeoutMessages = outgoingMessages
.filter((msg) => msg.HasTimeout)
.map(
(msg) =>
({
...msg,
TimeoutFriendly: `${msg.TimeoutFriendly}`,
}) as SagaTimeoutMessageViewModel
);
.map((msg) => {
// Check if this timeout message has been processed by checking if there's an initiating message with matching ID
const hasBeenProcessed = sagaHistory.changes.some((update) => update.initiating_message?.message_id === msg.MessageId);

return {
...msg,
TimeoutFriendly: `${msg.TimeoutFriendly}`,
HasBeenProcessed: hasBeenProcessed,
} as SagaTimeoutMessageViewModel;
});

const regularMessages = outgoingMessages.filter((msg) => !msg.HasTimeout) as SagaMessageViewModel[];

const hasTimeout = outgoingTimeoutMessages.length > 0;

return {
return <SagaUpdateViewModel>{
MessageId: update.initiating_message?.message_id || "",
StartTime: startTime,
FinishTime: finishTime,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,29 @@ import { SagaTimeoutMessageViewModel } from "./SagaDiagramParser";
import MessageDataBox from "./MessageDataBox.vue";
import TimeoutIcon from "@/assets/TimeoutIcon.svg";
import SagaTimeoutIcon from "@/assets/SagaTimeoutIcon.svg";
import { useSagaDiagramStore } from "@/stores/SagaDiagramStore";

defineProps<{
const props = defineProps<{
message: SagaTimeoutMessageViewModel;
isLastMessage: boolean;
showMessageData?: boolean;
}>();

const store = useSagaDiagramStore();

const navigateToTimeout = () => {
// Set the selected message ID in the store
store.setSelectedMessageId(props.message.MessageId);
};
</script>

<template>
<div class="row row--right">
<div class="cell cell--center">
<div class="cell-inner cell-inner-line">
<img class="saga-icon saga-icon--center-cell saga-icon--overlap" :src="SagaTimeoutIcon" alt="" />
<a class="timeout-status" href="" aria-label="timeout requested">Timeout Requested = {{ message.TimeoutFriendly }}</a>
<a v-if="message.HasBeenProcessed" class="timeout-status" href="#" @click.prevent="navigateToTimeout" aria-label="timeout requested">Timeout Requested = {{ message.TimeoutFriendly }}</a>
<span v-else class="timeout-status" aria-label="timeout requested">Timeout Requested = {{ message.TimeoutFriendly }}</span>
</div>
</div>
<div class="cell cell--side"></div>
Expand Down
105 changes: 102 additions & 3 deletions src/Frontend/src/components/messages2/SagaDiagram/SagaUpdateNode.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,60 @@ import { SagaUpdateViewModel } from "./SagaDiagramParser";
import MessageDataBox from "./MessageDataBox.vue";
import SagaOutgoingTimeoutMessage from "./SagaOutgoingTimeoutMessage.vue";
import SagaOutgoingMessage from "./SagaOutgoingMessage.vue";
import { useSagaDiagramStore } from "@/stores/SagaDiagramStore";
import { ref, watch } from "vue";

// Import the images directly
import CommandIcon from "@/assets/command.svg";
import SagaInitiatedIcon from "@/assets/SagaInitiatedIcon.svg";
import SagaUpdatedIcon from "@/assets/SagaUpdatedIcon.svg";
import TimeoutIcon from "@/assets/timeout.svg";
import SagaTimeoutIcon from "@/assets/SagaTimeoutIcon.svg";
defineProps<{

const props = defineProps<{
update: SagaUpdateViewModel;
showMessageData?: boolean;
}>();

const store = useSagaDiagramStore();
const initiatingMessageRef = ref<HTMLElement | null>(null);
const isActive = ref(false);

// Watch for changes to selectedMessageId
watch(
() => store.selectedMessageId,
(newMessageId) => {
// Check if this node contains the selected message
const isSelected = props.update.InitiatingMessage.IsSagaTimeoutMessage && newMessageId === props.update.MessageId;

// Update active state
isActive.value = isSelected;

// If this is the selected message, scroll to it
if (isSelected && initiatingMessageRef.value) {
initiatingMessageRef.value.scrollIntoView({
behavior: "smooth",
block: "center",
});
}
}
);
</script>

<template>
<div class="block" role="row">
<!-- Initiating message and saga status header -->
<div class="row">
<div class="cell cell--side">
<div class="cell-inner cell-inner-side">
<div
ref="initiatingMessageRef"
:class="{
'cell-inner': true,
'cell-inner-side': true,
'cell-inner-side--active': isActive || (update.InitiatingMessage.IsSagaTimeoutMessage && update.MessageId === store.selectedMessageId),
}"
:data-message-id="update.InitiatingMessage.IsSagaTimeoutMessage ? update.MessageId : ''"
>
<img class="saga-icon saga-icon--side-cell" :src="update.InitiatingMessage.IsSagaTimeoutMessage ? TimeoutIcon : CommandIcon" alt="" />
<h2 class="message-title" aria-label="initiating message type">{{ update.InitiatingMessage.MessageType }}</h2>
<div class="timestamp" aria-label="initiating message timestamp">{{ update.InitiatingMessage.FormattedMessageTimestamp }}</div>
Expand Down Expand Up @@ -164,7 +199,11 @@ defineProps<{
}

.cell-inner-side--active {
border: solid 2px #000000;
border: solid 5px #00a3c4;
-webkit-animation: blink-border 1.8s ease-in-out;
-moz-animation: blink-border 1.8s ease-in-out;
-o-animation: blink-border 1.8s ease-in-out;
animation: blink-border 1.8s ease-in-out;
}

.cell-inner-right {
Expand Down Expand Up @@ -308,4 +347,64 @@ defineProps<{
font-weight: 900;
color: #00a3c4;
}

@-webkit-keyframes blink-border {
0%,
100% {
border-color: #000000;
}
20%,
60% {
border-color: #cccccc;
}
40%,
80% {
border-color: #000000;
}
}

@-moz-keyframes blink-border {
0%,
100% {
border-color: #000000;
}
20%,
60% {
border-color: #cccccc;
}
40%,
80% {
border-color: #000000;
}
}

@-o-keyframes blink-border {
0%,
100% {
border-color: #000000;
}
20%,
60% {
border-color: #cccccc;
}
40%,
80% {
border-color: #000000;
}
}

@keyframes blink-border {
0%,
100% {
border-color: #00a3c4;
}
20%,
60% {
border-color: #cccccc;
}
40%,
80% {
border-color: #00a3c4;
}
}
</style>
8 changes: 8 additions & 0 deletions src/Frontend/src/stores/SagaDiagramStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export const useSagaDiagramStore = defineStore("SagaDiagramStore", () => {
const showMessageData = ref(false);
const fetchedMessages = ref(new Set<string>());
const messagesData = ref<SagaMessageData[]>([]);
const selectedMessageId = ref<string | null>(null);
const MessageBodyEndpoint = "messages/{0}/body";

// Watch the sagaId and fetch saga history when it changes
Expand Down Expand Up @@ -188,6 +189,7 @@ export const useSagaDiagramStore = defineStore("SagaDiagramStore", () => {
error.value = null;
fetchedMessages.value.clear();
messagesData.value = [];
selectedMessageId.value = null;
}

function formatUrl(template: string, id: string): string {
Expand Down Expand Up @@ -248,6 +250,10 @@ export const useSagaDiagramStore = defineStore("SagaDiagramStore", () => {
}
}

function setSelectedMessageId(messageId: string | null) {
selectedMessageId.value = messageId;
}

return {
sagaHistory,
sagaId,
Expand All @@ -256,9 +262,11 @@ export const useSagaDiagramStore = defineStore("SagaDiagramStore", () => {
error,
showMessageData,
messagesData,
selectedMessageId,
setSagaId,
clearSagaHistory,
toggleMessageData,
setSelectedMessageId,
};
});

Expand Down