Skip to content

Commit c710180

Browse files
committed
Saga Update properties
1 parent 0425236 commit c710180

File tree

2 files changed

+94
-16
lines changed

2 files changed

+94
-16
lines changed

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

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ export interface SagaUpdateViewModel {
3636
OutgoingTimeoutMessages: SagaTimeoutMessageViewModel[];
3737
HasOutgoingMessages: boolean;
3838
HasOutgoingTimeoutMessages: boolean;
39+
showUpdatedPropertiesOnly: boolean;
40+
stateAfterChange: Record<string, unknown>;
41+
previousStateAfterChange?: Record<string, unknown>;
3942
}
4043

4144
export interface SagaViewModel {
@@ -54,12 +57,20 @@ export interface SagaViewModel {
5457
export function parseSagaUpdates(sagaHistory: SagaHistory | null, messagesData: SagaMessageData[]): SagaUpdateViewModel[] {
5558
if (!sagaHistory || !sagaHistory.changes || !sagaHistory.changes.length) return [];
5659

57-
return sagaHistory.changes
60+
const updates = sagaHistory.changes
5861
.map((update) => {
5962
const startTime = new Date(update.start_time);
6063
const finishTime = new Date(update.finish_time);
6164
const initiatingMessageTimestamp = new Date(update.initiating_message?.time_sent || Date.now());
6265

66+
// Parse the state_after_change JSON
67+
let stateAfterChange: Record<string, unknown> = {};
68+
try {
69+
stateAfterChange = JSON.parse(update.state_after_change || "{}");
70+
} catch (e) {
71+
console.error("Error parsing state_after_change:", e);
72+
}
73+
6374
// Find message data for initiating message
6475
const initiatingMessageData = update.initiating_message ? messagesData.find((m) => m.message_id === update.initiating_message.message_id)?.data || [] : [];
6576

@@ -123,8 +134,17 @@ export function parseSagaUpdates(sagaHistory: SagaHistory | null, messagesData:
123134
OutgoingMessages: regularMessages,
124135
HasOutgoingMessages: regularMessages.length > 0,
125136
HasOutgoingTimeoutMessages: outgoingTimeoutMessages.length > 0,
137+
showUpdatedPropertiesOnly: true, // Default to showing only updated properties
138+
stateAfterChange: stateAfterChange,
126139
};
127140
})
128141
.sort((a, b) => a.StartTime.getTime() - b.StartTime.getTime())
129142
.sort((a, b) => a.FinishTime.getTime() - b.FinishTime.getTime());
143+
144+
// Add reference to previous state for each update except the first one
145+
for (let i = 1; i < updates.length; i++) {
146+
updates[i].previousStateAfterChange = updates[i - 1].stateAfterChange;
147+
}
148+
149+
return updates;
130150
}

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

Lines changed: 73 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import MessageDataBox from "./MessageDataBox.vue";
44
import SagaOutgoingTimeoutMessage from "./SagaOutgoingTimeoutMessage.vue";
55
import SagaOutgoingMessage from "./SagaOutgoingMessage.vue";
66
import { useSagaDiagramStore } from "@/stores/SagaDiagramStore";
7-
import { ref, watch } from "vue";
7+
import { ref, watch, computed } from "vue";
88
99
// Import the images directly
1010
import CommandIcon from "@/assets/command.svg";
@@ -21,6 +21,7 @@ const props = defineProps<{
2121
const store = useSagaDiagramStore();
2222
const initiatingMessageRef = ref<HTMLElement | null>(null);
2323
const isActive = ref(false);
24+
const showAllProperties = ref(!props.update.showUpdatedPropertiesOnly);
2425
2526
// Watch for changes to selectedMessageId
2627
watch(
@@ -41,6 +42,63 @@ watch(
4142
}
4243
}
4344
);
45+
46+
// Function to toggle between showing all properties and only updated properties
47+
const togglePropertyView = (event: Event, showAll: boolean) => {
48+
event.preventDefault();
49+
showAllProperties.value = showAll;
50+
// Instead of directly modifying the prop, we update our local view state
51+
// props.update.showUpdatedPropertiesOnly = !showAll;
52+
};
53+
54+
// Compute the properties to display based on the current state
55+
const displayProperties = computed(() => {
56+
const properties: { name: string; value: string; isNew: boolean }[] = [];
57+
const state = props.update.stateAfterChange;
58+
const previousState = props.update.previousStateAfterChange || {};
59+
const isFirstNode = props.update.IsFirstNode;
60+
61+
// Function to check if a property has changed
62+
const hasPropertyChanged = (key: string) => {
63+
if (isFirstNode) return true; // For the first node, all properties are "new"
64+
return JSON.stringify(state[key]) !== JSON.stringify(previousState[key]);
65+
};
66+
67+
// Function to format value differences
68+
const formatValue = (key: string) => {
69+
const currentValue = state[key];
70+
if (isFirstNode || !props.update.previousStateAfterChange) {
71+
return String(currentValue);
72+
}
73+
74+
const prevValue = previousState[key];
75+
if (JSON.stringify(currentValue) !== JSON.stringify(prevValue)) {
76+
return `${prevValue} → ${currentValue}`;
77+
}
78+
return String(currentValue);
79+
};
80+
81+
// Filter out standard keys like $type, Id, Originator, OriginalMessageId
82+
const standardKeys = ["$type", "Id", "Originator", "OriginalMessageId"];
83+
84+
// Add all properties that should be displayed
85+
for (const key in state) {
86+
if (standardKeys.includes(key)) continue;
87+
88+
const propertyChanged = hasPropertyChanged(key);
89+
90+
// Skip unchanged properties when showing only updated properties
91+
if (!showAllProperties.value && !propertyChanged && !isFirstNode) continue;
92+
93+
properties.push({
94+
name: isFirstNode ? `${key} (new)` : key, // Add "(new)" suffix for first node
95+
value: formatValue(key),
96+
isNew: isFirstNode || propertyChanged,
97+
});
98+
}
99+
100+
return properties;
101+
});
44102
</script>
45103

46104
<template>
@@ -90,18 +148,19 @@ watch(
90148
<div class="cell cell--center cell--center--border">
91149
<div :class="{ 'cell-inner': true, 'cell-inner-line': update.HasTimeout, 'cell-inner-center': !update.HasTimeout }">
92150
<div class="saga-properties">
93-
<a class="saga-properties-link" href="">All Properties</a> /
94-
<a class="saga-properties-link saga-properties-link--active" href="">Updated Properties</a>
151+
<a class="saga-properties-link" :class="{ 'saga-properties-link--active': showAllProperties }" href="" @click="(e) => togglePropertyView(e, true)">All Properties</a> /
152+
<a class="saga-properties-link" :class="{ 'saga-properties-link--active': !showAllProperties }" href="" @click="(e) => togglePropertyView(e, false)">Updated Properties</a>
95153
</div>
96154

97155
<!-- Display saga properties if available -->
98-
<ul class="saga-properties-list">
99-
<li class="saga-properties-list-item">
100-
<span class="saga-properties-list-text" title="Property (new)">Property (new)</span>
156+
<ul class="saga-properties-list" v-if="displayProperties.length > 0">
157+
<li class="saga-properties-list-item" v-for="(prop, index) in displayProperties" :key="index">
158+
<span class="saga-properties-list-text" :title="prop.name">{{ prop.name }}</span>
101159
<span class="saga-properties-list-text">=</span>
102-
<span class="saga-properties-list-text" title="Sample Value"> Sample Value</span>
160+
<span class="saga-properties-list-text" :title="prop.value">{{ prop.value }}</span>
103161
</li>
104162
</ul>
163+
<div v-else class="no-properties">No properties to display</div>
105164
</div>
106165
</div>
107166

@@ -118,10 +177,6 @@ watch(
118177
</template>
119178

120179
<style scoped>
121-
.block {
122-
/* block container style */
123-
}
124-
125180
.row {
126181
display: flex;
127182
}
@@ -164,10 +219,6 @@ watch(
164219
border-top: solid 2px #000000;
165220
}
166221
167-
.cell-inner {
168-
/* padding: 0.5rem; */
169-
}
170-
171222
.cell-inner-center {
172223
padding: 0.5rem;
173224
}
@@ -322,6 +373,13 @@ watch(
322373
display: block;
323374
}
324375
376+
.no-properties {
377+
padding: 0.25rem;
378+
font-style: italic;
379+
font-size: 0.8rem;
380+
color: #666;
381+
}
382+
325383
.saga-icon {
326384
display: block;
327385
float: left;

0 commit comments

Comments
 (0)