Skip to content

Commit 54d2cd8

Browse files
committed
Display message data
1 parent 290b765 commit 54d2cd8

File tree

7 files changed

+146
-53
lines changed

7 files changed

+146
-53
lines changed

src/Frontend/src/components/messages2/SagaDiagram/MessageDataBox.vue

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
<script setup lang="ts">
2+
import { SagaMessageDataItem } from "@/stores/SagaDiagramStore";
3+
24
defineProps<{
3-
propertyKey?: string;
4-
propertyValue?: string;
5-
title?: string;
5+
messageData: SagaMessageDataItem[];
66
}>();
77
</script>
88

99
<template>
10-
<div class="message-data-box">
11-
<b class="message-data-box-text">{{ propertyKey || "OrderId" }}</b>
10+
<div v-for="(item, index) in messageData" :key="index" class="message-data-box">
11+
<b class="message-data-box-text">{{ item.key }}</b>
1212
<span class="message-data-box-text">=</span>
13-
<span class="message-data-box-text--ellipsis" :title="title || propertyValue || 'Sample ID'">{{ propertyValue || "Sample ID" }}</span>
13+
<span class="message-data-box-text--ellipsis" :title="item.value">{{ item.value }}</span>
1414
</div>
1515
</template>
1616

src/Frontend/src/components/messages2/SagaDiagram/SagaTimeoutMessage.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,11 @@ defineProps<{
2828
<div class="cell-inner cell-inner-right"></div>
2929
<div class="cell-inner cell-inner-side cell-inner-side--active">
3030
<img class="saga-icon saga-icon--side-cell" :src="TimeoutIcon" alt="" />
31-
<h2 class="message-title" aria-label="timeout message type">FOURTH:{{ message.MessageFriendlyTypeName }}</h2>
31+
<h2 class="message-title" aria-label="timeout message type">FOURTH:{{ message.MessageFriendlyTypeName }}<br />{{ message.MessageId }}</h2>
3232
<div class="timestamp" aria-label="timeout message timestamp">{{ message.FormattedTimeSent }}</div>
3333
</div>
3434
<div v-if="showMessageData" class="message-data message-data--active">
35-
<MessageDataBox />
35+
<MessageDataBox :messageData="message.Data" />
3636
</div>
3737
</div>
3838
</div>

src/Frontend/src/components/messages2/SagaDiagram/SagaUpdateNode.vue

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,6 @@ const props = defineProps<{
1313
update: SagaUpdateViewModel;
1414
showMessageData?: boolean;
1515
}>();
16-
console.log("NonTimeoutMessages :");
17-
console.log(props.update.NonTimeoutMessages);
18-
console.log("TIMEOUT MESSAGES:");
19-
console.log(props.update.TimeoutMessages);
20-
console.log("Initaiteing MESSAGES:");
21-
console.log(props.update.InitiatingMessageData);
2216
</script>
2317

2418
<template>
@@ -28,14 +22,17 @@ console.log(props.update.InitiatingMessageData);
2822
<div class="cell cell--side">
2923
<div class="cell-inner cell-inner-side">
3024
<img class="saga-icon saga-icon--side-cell" :src="CommandIcon" alt="" />
31-
<h2 class="message-title" aria-label="initiating message type">FIRST:{{ update.InitiatingMessageType }}</h2>
25+
<h2 class="message-title" aria-label="initiating message type">
26+
FIRST:{{ update.InitiatingMessageType }}<br />
27+
{{ update.MessageId }}
28+
</h2>
3229
<div class="timestamp" aria-label="initiating message timestamp">{{ update.FormattedInitiatingMessageTimestamp }}</div>
3330
</div>
3431
</div>
3532
<div class="cell cell--center cell-flex">
3633
<div class="cell-inner cell-inner-center cell-inner--align-bottom">
3734
<img class="saga-icon saga-icon--center-cell" :src="update.IsFirstNode ? SagaInitiatedIcon : SagaUpdatedIcon" alt="" />
38-
<h2 class="saga-status-title saga-status-title--inline">SECOND:{{ update.StatusDisplay }}</h2>
35+
<h2 class="saga-status-title saga-status-title--inline">SECOND:{{ update.StatusDisplay }}<br />{{ update.MessageId }}</h2>
3936
<div class="timestamp timestamp--inline" aria-label="time stamp">{{ update.FormattedStartTime }}</div>
4037
</div>
4138
</div>
@@ -47,7 +44,7 @@ console.log(props.update.InitiatingMessageData);
4744
<div class="cell cell--side cell--left-border cell--aling-top">
4845
<div v-if="showMessageData" class="message-data message-data--active">
4946
<!-- Generic message data box -->
50-
<MessageDataBox v-if="update.InitiatingMessageType" />
47+
<MessageDataBox v-if="update.InitiatingMessageType" :messageData="update.InitiatingMessageData" />
5148
</div>
5249
</div>
5350

@@ -76,11 +73,11 @@ console.log(props.update.InitiatingMessageData);
7673
<template v-for="(msg, msgIndex) in update.NonTimeoutMessages" :key="msgIndex">
7774
<div class="cell-inner cell-inner-side">
7875
<img class="saga-icon saga-icon--side-cell" :src="msg.IsEventMessage ? EventIcon : CommandIcon" :alt="msg.IsEventMessage ? 'Event' : 'Command'" />
79-
<h2 class="message-title">THIRD:{{ msg.MessageFriendlyTypeName }}</h2>
76+
<h2 class="message-title">THIRD:{{ msg.MessageFriendlyTypeName }}<br />{{ msg.MessageId }}</h2>
8077
<div class="timestamp">{{ msg.FormattedTimeSent }}</div>
8178
</div>
8279
<div v-if="showMessageData" class="message-data message-data--active">
83-
<MessageDataBox />
80+
<MessageDataBox :messageData="msg.Data" />
8481
</div>
8582
</template>
8683
</div>

src/Frontend/src/components/messages2/SagaDiagram/useSagaDiagramParser.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { typeToName } from "@/composables/typeHumanizer";
33
import { SagaMessageData, SagaMessageDataItem } from "@/stores/SagaDiagramStore";
44

55
export interface SagaMessage {
6+
MessageId: string;
67
MessageFriendlyTypeName: string;
78
FormattedTimeSent: string;
89
Data: SagaMessageDataItem[];
@@ -15,6 +16,7 @@ export interface SagaTimeoutMessage extends SagaMessage {
1516
}
1617

1718
export interface SagaUpdateViewModel {
19+
MessageId: string;
1820
StartTime: Date;
1921
FinishTime: Date;
2022
FormattedStartTime: string;
@@ -95,6 +97,7 @@ export function parseSagaUpdates(sagaHistory: SagaHistory | null, messagesData:
9597
const hasTimeout = timeoutMessages.length > 0;
9698

9799
return {
100+
MessageId: update.initiating_message?.message_id || "",
98101
StartTime: startTime,
99102
FinishTime: finishTime,
100103
FormattedStartTime: `${startTime.toLocaleDateString()} ${startTime.toLocaleTimeString()}`,

src/Frontend/src/composables/serviceServiceControlUrls.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,15 @@ export function useIsMonitoringEnabled() {
4747
return !useIsMonitoringDisabled();
4848
}
4949

50-
export function useFetchFromServiceControl(suffix: string) {
51-
return fetch(serviceControlUrl.value + suffix);
50+
// export function useFetchFromServiceControl(suffix: string) {
51+
// return fetch(serviceControlUrl.value + suffix);
52+
// }
53+
export function useFetchFromServiceControl(suffix: string, headers?: HeadersInit) {
54+
const requestOptions: RequestInit = {
55+
headers,
56+
};
57+
return fetch(serviceControlUrl.value + suffix, requestOptions);
5258
}
53-
5459
export async function useTypedFetchFromServiceControl<T>(suffix: string): Promise<[Response, T]> {
5560
const response = await fetch(`${serviceControlUrl.value}${suffix}`);
5661
if (!response.ok) throw new Error(response.statusText ?? "No response");

src/Frontend/src/resources/SagaHistory.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ export interface SagaHistory {
77
changes: SagaStateChange[];
88
}
99

10-
11-
1210
export interface SagaStateChange {
1311
start_time: Date;
1412
finish_time: Date;

src/Frontend/src/stores/SagaDiagramStore.ts

Lines changed: 119 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import { acceptHMRUpdate, defineStore } from "pinia";
22
import { ref, watch } from "vue";
33
import { SagaHistory, SagaMessage } from "@/resources/SagaHistory";
44
import { useFetchFromServiceControl } from "@/composables/serviceServiceControlUrls";
5-
// import { MessageStatus } from "@/resources/Message";
6-
5+
import { MessageStatus } from "@/resources/Message";
6+
const StandardKeys = ["$type", "Id", "Originator", "OriginalMessageId"];
77
export interface SagaMessageDataItem {
88
key: string;
99
value: string;
@@ -21,7 +21,6 @@ export const useSagaDiagramStore = defineStore("sagaHistory", () => {
2121
const fetchedMessages = ref(new Set<string>());
2222
const messagesData = ref<SagaMessageData[]>([]);
2323
const MessageBodyEndpoint = "messages/{0}/body";
24-
2524
// Watch for changes to sagaId and fetch saga history data
2625
watch(sagaId, async (newSagaId) => {
2726
if (!newSagaId) {
@@ -48,10 +47,21 @@ export const useSagaDiagramStore = defineStore("sagaHistory", () => {
4847
if (change.outgoing_messages) {
4948
messages.push(...change.outgoing_messages.filter((msg) => !fetchedMessages.value.has(msg.message_id)));
5049
}
51-
5250
return messages;
5351
});
5452

53+
// Check if any messages need body_url
54+
const needsBodyUrl = messagesToFetch.every((msg) => !msg.body_url);
55+
if (needsBodyUrl && messagesToFetch.length > 0) {
56+
const auditMessages = await getAuditMessages(sagaId.value!);
57+
messagesToFetch.forEach((message) => {
58+
const auditMessage = auditMessages.find((x) => x.message_id === message.message_id);
59+
if (auditMessage) {
60+
message.body_url = auditMessage.body_url;
61+
}
62+
});
63+
}
64+
5565
// Fetch data for each unfetched message in parallel and store results
5666
const fetchPromises = messagesToFetch.map(async (message) => {
5767
const data = await fetchSagaMessageData(message);
@@ -86,7 +96,7 @@ export const useSagaDiagramStore = defineStore("sagaHistory", () => {
8696
error.value = "Failed to fetch saga history";
8797
} else {
8898
const data = await response.json();
89-
99+
console.log("Saga history data for sis" + id, data);
90100
sagaHistory.value = data;
91101
}
92102
} catch (e) {
@@ -96,51 +106,131 @@ export const useSagaDiagramStore = defineStore("sagaHistory", () => {
96106
loading.value = false;
97107
}
98108
}
99-
109+
function createEmptyMessageData(message_id: string): SagaMessageData {
110+
return {
111+
message_id,
112+
data: [
113+
{
114+
key: "Content",
115+
value: "EMPTY",
116+
},
117+
],
118+
};
119+
}
100120
async function fetchSagaMessageData(message: SagaMessage): Promise<SagaMessageData> {
101-
const bodyUrl = message.body_url ?? formatUrl(MessageBodyEndpoint, message.message_id);
121+
const bodyUrl = (message.body_url ?? formatUrl(MessageBodyEndpoint, message.message_id)).replace(/^\//, "");
102122
loading.value = true;
103123
error.value = null;
104124
// const headers = {
105-
// "Cache-Control": message.message_status === MessageStatus.Successful ? "no-cache" : "no-cache",
125+
// //"Cache-Control": message.message_status === MessageStatus.Successful ? "no-cache" : "no-cache",
126+
// "Cache-Control": "no-cache",
106127
// };
107128
try {
129+
console.log("MessageBodyEndpoint:", MessageBodyEndpoint);
130+
console.log("message.body_url:", message.body_url);
131+
console.log("message.message_id:", message.message_id);
132+
console.log("bodyUrl:", bodyUrl);
108133
const response = await useFetchFromServiceControl(bodyUrl);
109-
const body = response;
134+
if (!response.ok) {
135+
throw new Error(`HTTP error! status: ${response.status}`);
136+
}
137+
const body = await response.json();
110138

111139
if (!body) {
112-
return {
113-
message_id: message.message_id,
114-
data: [],
115-
};
140+
return createEmptyMessageData(message.message_id);
116141
}
117142

118-
// if (typeof body === "string" && body.trim().startsWith("<?xml")) {
119-
// // return getXmlData(body); // Implement XML parsing below
120-
// } else {
121-
// // return processJsonValues(body); // Implement JSON property extraction
122-
// }
123-
124-
// Return dummy data for now
143+
let data: SagaMessageDataItem[];
144+
if (typeof body === "string" && body.trim().startsWith("<?xml")) {
145+
data = getXmlData(body);
146+
} else {
147+
data = processJsonValues(body);
148+
}
149+
// Check if parsed data is empty
150+
if (!data || data.length === 0) {
151+
return createEmptyMessageData(message.message_id);
152+
}
125153
return {
126154
message_id: message.message_id,
127-
data: [
128-
{ key: "Property1", value: "Test Value 1" },
129-
{ key: "Property2", value: "Test Value 2" },
130-
{ key: "Timestamp", value: new Date().toISOString() },
131-
],
155+
data,
132156
};
133157
} catch (e) {
134158
error.value = e instanceof Error ? e.message : "Unknown error occurred";
135-
return {
136-
message_id: message.message_id,
137-
data: [],
138-
};
159+
console.log("InCATCH" + error.value);
160+
return createEmptyMessageData(message.message_id);
139161
} finally {
140162
loading.value = false;
141163
}
142164
}
143165

166+
async function getAuditMessages(sagaId: string) {
167+
try {
168+
const response = await useFetchFromServiceControl(`messages/search?q=${sagaId}`);
169+
if (!response.ok) {
170+
throw new Error(`HTTP error! status: ${response.status}`);
171+
}
172+
return await response.json();
173+
} catch (error) {
174+
console.error("Error fetching audit messages:", error);
175+
return { result: [] };
176+
}
177+
}
178+
179+
function getXmlData(xmlString: string): SagaMessageDataItem[] {
180+
try {
181+
const parser = new DOMParser();
182+
const xmlDoc = parser.parseFromString(xmlString, "application/xml");
183+
184+
// Get the root element
185+
const rootElement = xmlDoc.documentElement;
186+
if (!rootElement) {
187+
return [];
188+
}
189+
190+
// Handle both v5 and pre-v5 message formats
191+
const messageRoot = rootElement.nodeName === "Messages" ? Array.from(rootElement.children)[0] : rootElement;
192+
193+
if (!messageRoot) {
194+
return [];
195+
}
196+
197+
// Convert child elements to SagaMessageDataItems
198+
return Array.from(messageRoot.children).map((node) => ({
199+
key: node.nodeName,
200+
value: node.textContent?.trim() || "",
201+
}));
202+
} catch (error) {
203+
console.error("Error parsing message data:", error);
204+
return [];
205+
}
206+
}
207+
208+
// Replace or modify the existing processJsonValues function
209+
function processJsonValues(jsonBody: any): SagaMessageDataItem[] {
210+
if (typeof jsonBody === "string") {
211+
try {
212+
jsonBody = JSON.parse(jsonBody);
213+
} catch (e) {
214+
console.error("Error parsing JSON:", e);
215+
return [];
216+
}
217+
}
218+
219+
const items: SagaMessageDataItem[] = [];
220+
221+
// Filter out standard keys and convert to KeyValuePairs
222+
for (const key in jsonBody) {
223+
if (!StandardKeys.includes(key)) {
224+
items.push({
225+
key: key,
226+
value: String(jsonBody[key] ?? ""),
227+
});
228+
}
229+
}
230+
231+
return items;
232+
}
233+
144234
function clearSagaHistory() {
145235
sagaHistory.value = null;
146236
sagaId.value = null;

0 commit comments

Comments
 (0)