Skip to content

Commit 704e1eb

Browse files
committed
improved loading of the body - and formatted xml
Inspired by the one in MessageStore. Potential removal of duplication
1 parent c941809 commit 704e1eb

File tree

3 files changed

+52
-80
lines changed

3 files changed

+52
-80
lines changed

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

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@ import { storeToRefs } from "pinia";
44
import LoadingSpinner from "@/components/LoadingSpinner.vue";
55
import MaximizableCodeEditor from "@/components/MaximizableCodeEditor.vue";
66
import { computed } from "vue";
7-
import { CodeLanguage } from "@/components/codeEditorTypes";
8-
import { parse, stringify } from "lossless-json";
97
import { EditorView } from "@codemirror/view";
8+
import parseContentType from "@/composables/contentTypeParser";
109
1110
const messageDataBoxTheme = EditorView.baseTheme({
1211
".maximazable-code-editor--inline-instance .cm-editor": {
@@ -31,37 +30,29 @@ const modalTitle = computed(() => {
3130
const sagaDiagramStore = useSagaDiagramStore();
3231
const { messageDataLoading } = storeToRefs(sagaDiagramStore);
3332
34-
const formattedData = computed(() => {
35-
if (props.messageData.type === "json" && props.messageData.data) {
36-
try {
37-
// Parse and then stringify with indentation to ensure proper formatting
38-
const parsed = parse(props.messageData.data);
39-
return stringify(parsed, null, 2);
40-
} catch {
41-
return props.messageData.data;
42-
}
43-
}
44-
return props.messageData.data;
45-
});
33+
const contentType = computed(() => parseContentType(props.messageData.body.data.content_type));
4634
47-
const editorLanguage = computed<CodeLanguage>(() => {
48-
const type = props.messageData.type?.toLowerCase();
49-
return (type === "xml" ? "xml" : "json") as CodeLanguage;
50-
});
35+
const body = computed(() => props.messageData.body.data.value || "");
5136
</script>
5237

5338
<template>
5439
<div v-if="messageDataLoading" class="message-data-loading">
5540
<LoadingSpinner />
5641
</div>
57-
<div v-else-if="messageData.error" class="message-data-box message-data-box-error">
42+
<div v-else-if="messageData.body.failed_to_load" class="message-data-box message-data-box-error">
5843
<span class="message-data-box-text--error">An error occurred while retrieving the message data</span>
5944
</div>
60-
<div v-else-if="!messageDataLoading && messageData.data === ''" class="message-data-box">
45+
<div v-else-if="messageData.body.not_found" class="message-data-box message-data-box-error">
46+
<span class="message-data-box-text--error">Message body not found</span>
47+
</div>
48+
<div v-else-if="!messageDataLoading && !messageData.body.data.value" class="message-data-box">
6149
<span class="message-data-box-text--empty">Empty</span>
6250
</div>
63-
<div v-else class="message-data-box message-data-box-content">
64-
<MaximizableCodeEditor :model-value="formattedData || ''" :language="editorLanguage" :read-only="true" :show-gutter="false" :modalTitle="modalTitle" :extensions="[messageDataBoxTheme]" />
51+
<div v-else-if="contentType.isSupported" class="message-data-box message-data-box-content">
52+
<MaximizableCodeEditor :model-value="body" :language="contentType.language" :readOnly="true" :showGutter="false" :modalTitle="modalTitle" :extensions="[messageDataBoxTheme]" />
53+
</div>
54+
<div v-else class="message-data-box message-data-box-error">
55+
<div class="alert alert-warning">Message body cannot be displayed because content type "{{ messageData.body.data.content_type }}" is not supported.</div>
6556
</div>
6657
</template>
6758

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,11 @@ function findMessageData(messagesData: SagaMessageData[], messageId: string): Sa
152152
function createEmptyMessageData(): SagaMessageData {
153153
return {
154154
message_id: "",
155-
data: "",
156-
type: "json",
157-
error: false,
155+
body: {
156+
data: {},
157+
loading: false,
158+
failed_to_load: false,
159+
not_found: false,
160+
},
158161
};
159162
}

src/Frontend/src/stores/SagaDiagramStore.ts

Lines changed: 33 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,19 @@ import { ref, watch } from "vue";
33
import { SagaHistory, SagaMessage } from "@/resources/SagaHistory";
44
import { useFetchFromServiceControl } from "@/composables/serviceServiceControlUrls";
55
import Message from "@/resources/Message";
6+
import { parse, stringify } from "lossless-json";
7+
import xmlFormat from "xml-formatter";
8+
9+
interface DataContainer<T> {
10+
loading?: boolean;
11+
failed_to_load?: boolean;
12+
not_found?: boolean;
13+
data: T;
14+
}
615

716
export interface SagaMessageData {
817
message_id: string;
9-
data: string;
10-
type: "json" | "xml";
11-
error: boolean;
18+
body: DataContainer<{ value?: string; content_type?: string }>;
1219
}
1320
export const useSagaDiagramStore = defineStore("SagaDiagramStore", () => {
1421
const sagaHistory = ref<SagaHistory | null>(null);
@@ -71,67 +78,38 @@ export const useSagaDiagramStore = defineStore("SagaDiagramStore", () => {
7178

7279
async function fetchSagaMessageData(message: SagaMessage): Promise<SagaMessageData> {
7380
const bodyUrl = (message.body_url ?? formatUrl(MessageBodyEndpoint, message.message_id)).replace(/^\//, "");
81+
const result: SagaMessageData = {
82+
message_id: message.message_id,
83+
body: { data: {} },
84+
};
7485

75-
try {
76-
const response = await useFetchFromServiceControl(bodyUrl, { cache: "no-store" });
86+
result.body.loading = true;
87+
result.body.failed_to_load = false;
7788

78-
// Treat 404 as empty data, not as an error
89+
try {
90+
const response = await useFetchFromServiceControl(bodyUrl);
7991
if (response.status === 404) {
80-
return {
81-
message_id: message.message_id,
82-
data: "",
83-
type: "json",
84-
error: false,
85-
};
86-
}
87-
88-
// Handle other non-OK responses as errors
89-
if (!response.ok) {
90-
error.value = `HTTP error! status: ${response.status}`;
91-
return {
92-
message_id: message.message_id,
93-
data: "",
94-
type: "json",
95-
error: true,
96-
};
92+
result.body.not_found = true;
93+
return result;
9794
}
9895

99-
const body = await response.text();
96+
const contentType = response.headers.get("content-type");
97+
result.body.data.content_type = contentType ?? "text/plain";
98+
result.body.data.value = await response.text();
10099

101-
if (!body) {
102-
return {
103-
message_id: message.message_id,
104-
data: "",
105-
type: "json",
106-
error: false,
107-
};
100+
if (contentType === "application/json") {
101+
result.body.data.value = stringify(parse(result.body.data.value), null, 2) ?? result.body.data.value;
108102
}
109-
110-
// Determine the content type
111-
if (body.trim().startsWith("<?xml")) {
112-
return {
113-
message_id: message.message_id,
114-
data: body,
115-
type: "xml",
116-
error: false,
117-
};
118-
} else {
119-
return {
120-
message_id: message.message_id,
121-
data: body,
122-
type: "json",
123-
error: false,
124-
};
103+
if (contentType === "text/xml") {
104+
result.body.data.value = xmlFormat(result.body.data.value, { indentation: " ", collapseContent: true });
125105
}
126-
} catch (e) {
127-
error.value = e instanceof Error ? e.message : "Unknown error occurred";
128-
return {
129-
message_id: message.message_id,
130-
data: "",
131-
type: "json",
132-
error: true,
133-
};
106+
} catch {
107+
result.body.failed_to_load = true;
108+
} finally {
109+
result.body.loading = false;
134110
}
111+
112+
return result;
135113
}
136114

137115
async function getAuditMessages(sagaId: string) {

0 commit comments

Comments
 (0)