Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
b148921
include audit section displaying audit messages
PhilBastian Mar 6, 2025
105cc68
show status icons
PhilBastian Mar 10, 2025
337fdef
Merge branch 'master' into si_integration
PhilBastian Mar 11, 2025
dd2cd69
add feature flag
PhilBastian Mar 11, 2025
36d7815
format message type as per SI
PhilBastian Mar 11, 2025
b281cf3
change name from audit to all messages and include message view route
PhilBastian Mar 11, 2025
f706a7f
display time_sent and processing_time values
PhilBastian Mar 11, 2025
db87e15
fix the body of the popup message in retry dialog
soujay Mar 13, 2025
ef84c78
Revert "fix the body of the popup message in retry dialog"
soujay Mar 13, 2025
2616724
enable auto refresh to be paused and to be configured after creation
PhilBastian Mar 13, 2025
0065abb
manual/auto refresh control
PhilBastian Mar 13, 2025
6933c0f
Merge branch 'si_integration' of https://github.com/Particular/Servic…
PhilBastian Mar 13, 2025
10ae9af
stripe results grid
PhilBastian Mar 13, 2025
0a510d0
change to use emits
PhilBastian Mar 13, 2025
ba62324
remove commented code
PhilBastian Mar 14, 2025
60e4bfa
add paging
PhilBastian Mar 14, 2025
322f801
implement server side sorting
PhilBastian Mar 14, 2025
9cf0ac4
scroll on list instead of view, allowing the table headers to always …
PhilBastian Mar 14, 2025
338d370
Merge branch 'master' into si_integration
PhilBastian Mar 16, 2025
3b206eb
change to use messages routing
PhilBastian Mar 16, 2025
9e77b04
increase default page size
PhilBastian Mar 16, 2025
be36fd2
add failedmessage redirect and remove unused message components
PhilBastian Mar 17, 2025
c2f286e
start converting conversation model from SI
PhilBastian Mar 18, 2025
83592dc
order messages
PhilBastian Mar 18, 2025
0a07896
Merge branch 'master' into sequence_diagram
PhilBastian Mar 19, 2025
6a3fdab
add endpoint host versions
PhilBastian Mar 19, 2025
b2e1204
convert handleritem logic from SI
PhilBastian Mar 19, 2025
72df26f
convert routedMessages (arrows) from SI
PhilBastian Mar 19, 2025
a89730a
display endpoints
PhilBastian Apr 1, 2025
90a0052
timeline
PhilBastian Apr 1, 2025
eb5ffa5
handlers
PhilBastian Apr 2, 2025
7350293
arrow (left to right)
PhilBastian Apr 2, 2025
19171da
expand SVG to fit larger diagrams
PhilBastian Apr 2, 2025
f24f540
fix handler map
PhilBastian Apr 3, 2025
a9b6488
fix messagetype text side
PhilBastian Apr 3, 2025
5108f2a
replace props and emits with a store
PhilBastian Apr 3, 2025
39929c2
highlight on handlers
PhilBastian Apr 3, 2025
29f435a
implement route highlight
PhilBastian Apr 3, 2025
2de64d6
hide sequence diagram behind feature flag
PhilBastian Apr 3, 2025
c926f54
Merge branch 'master' into sequence_diagram
PhilBastian Apr 3, 2025
9303f63
support local and response message flow
PhilBastian Apr 4, 2025
ff1666f
handle long message names being pushed off the svg surface
PhilBastian Apr 4, 2025
35e4232
handle handler messagetext offset less than 0 (buggy)
PhilBastian Apr 4, 2025
b32a4fd
display event as dashed line
PhilBastian Apr 4, 2025
9645d4a
handle events in SequenceDiagram
PhilBastian Apr 4, 2025
0b0f590
address comments from review
PhilBastian Apr 7, 2025
c62f833
Merge branch 'sequence_diagram' into reverse_local_events_timeout
PhilBastian Apr 7, 2025
821947e
add comment for clarity
PhilBastian Apr 7, 2025
799eebb
Merge branch 'master' into reverse_local_events_timeout
PhilBastian Apr 7, 2025
20f3a71
fix merge issue
PhilBastian Apr 7, 2025
ec1a5b7
simplify name uniqueness
PhilBastian Apr 7, 2025
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
@@ -1,14 +1,14 @@
<script setup lang="ts">
import { Endpoint } from "@/resources/SequenceDiagram/Endpoint";
import { EndpointCentrePoint, useSequenceDiagramStore } from "@/stores/SequenceDiagramStore";
import { Endpoint_Width, EndpointCentrePoint, useSequenceDiagramStore } from "@/stores/SequenceDiagramStore";
import { storeToRefs } from "pinia";
import { computed, ref, watch } from "vue";

interface EndpointWithLocation extends Endpoint {
width: number;
textWidth: number;
x?: number;
surround: EndpointSurround;
surround?: EndpointSurround;
}

interface EndpointSurround {
Expand All @@ -22,12 +22,11 @@ interface EndpointSurround {
stroke: string;
}

const Endpoint_Width = 260;
const Endpoint_Gap = 30;
const Endpoint_Image_Width = 20;

const store = useSequenceDiagramStore();
const { endpoints } = storeToRefs(store);
const { startX, endpoints } = storeToRefs(store);

const epRefs = ref<SVGTextElement[]>([]);
const endpointItems = computed(() =>
Expand All @@ -39,7 +38,7 @@ const endpointItems = computed(() =>
const previousEndpoint = index > 0 ? endpointItems.value[index - 1] : undefined;
endpoint.width = Math.max(Endpoint_Width, bounds.width);
endpoint.textWidth = bounds.width;
endpoint.x = (previousEndpoint?.x ?? Endpoint_Width / 2) + (previousEndpoint?.width ?? 0) + Endpoint_Gap;
endpoint.x = (previousEndpoint?.x ?? startX.value) + (previousEndpoint?.width ?? 0) + Endpoint_Gap;

if (!endpoint.surround && el.isConnected) {
const style = getComputedStyle(el);
Expand Down Expand Up @@ -69,6 +68,11 @@ watch(endpointItems, () => {
store.setMaxWidth((lastEndpoint.x ?? 0) + lastEndpoint.width);
});

watch(startX, () => {
epRefs.value = [];
endpoints.value.forEach((endpoint) => ((endpoint as EndpointWithLocation).surround = undefined));
});

function setEndpointRef(el: SVGTextElement, index: number) {
if (el) epRefs.value[index] = el;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,15 @@ const handlerItems = computed(() => {
return 0;
})();

//determine which side of the handler to render the messageType on. If it's the left side (for a right arrow) then we apply a negative offset
const messageTypeOffset = handler.direction === Direction.Right ? ((messageTypeElement?.getBBox().width ?? 0) + 24) * -1 : 20;
if (messageTypeOffset < 0) {
store.setStartX(-1 * messageTypeOffset);
}

return {
id: handler.id,
endpointName: handler.endpoint.name,
incomingId: handler.route?.name,
left: (endpoint?.centre ?? 0) - Handler_Width / 2,
right: (endpoint?.centre ?? 0) + Handler_Width / 2,
Expand All @@ -52,13 +59,13 @@ const handlerItems = computed(() => {
icon,
iconSize,
messageType: handler.name,
messageTypeOffset: handler.direction === Direction.Right ? ((messageTypeElement?.getBBox().width ?? 0) + 24) * -1 : 20,
messageTypeOffset,
messageTypeHighlight: handler.route?.name === highlightId.value,
};
});

store.setMaxHeight(nextY);
store.setHandlerLocations(result.map((handler) => ({ id: handler.id, left: handler.left, right: handler.right, y: handler.y, height: handler.height })));
store.setHandlerLocations(result.map((handler) => ({ id: handler.id, endpointName: handler.endpointName, left: handler.left, right: handler.right, y: handler.y, height: handler.height })));

return result;
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { computed, ref } from "vue";
import { useSequenceDiagramStore } from "@/stores/SequenceDiagramStore";
import { storeToRefs } from "pinia";

const Arrow_Head_Width = 4;
const Arrow_Head_Width = 10;
const Message_Type_Margin = 4;

const store = useSequenceDiagramStore();
Expand All @@ -17,37 +17,39 @@ const arrows = computed(() =>
if (!route.name) return;
const fromHandler = route.fromRoutedMessage?.fromHandler;
if (!fromHandler) return;
const fromHandlerLocation = handlerLocations.value.find((hl) => hl.id === fromHandler.id);
const fromHandlerLocation = handlerLocations.value.find((hl) => hl.id === fromHandler.id && hl.endpointName === fromHandler.endpoint.name);
if (!fromHandlerLocation) return;
const toHandlerLocation = handlerLocations.value.find((hl) => hl.id === route.fromRoutedMessage?.toHandler?.id);
const toHandlerLocation = handlerLocations.value.find((hl) => hl.id === route.fromRoutedMessage?.toHandler?.id && hl.endpointName === route.fromRoutedMessage?.receiving.name);
if (!toHandlerLocation) return;

//TODO: is messageId enough to uniquely identify?
const arrowIndex = fromHandler.outMessages.findIndex((out) => route.fromRoutedMessage?.messageId === out.messageId) + 1;
const messageTypeElement = messageTypeRefs.value[index];
const messageTypeElementBounds = messageTypeElement?.getBBox();
const arrowIndex = fromHandler.outMessages.findIndex((out) => route.fromRoutedMessage?.messageId === out.messageId && route.fromRoutedMessage?.receiving.name === out.receiving.name) + 1;
const y = fromHandlerLocation.y + (fromHandlerLocation.height / (fromHandler.outMessages.length + 1)) * arrowIndex; //TODO work out the reason - 15 is applied in WPF;

const [direction, width, fromX] = (() => {
if (fromHandlerLocation.id === toHandlerLocation.id) return [Direction.Right, 15 + Arrow_Head_Width, fromHandlerLocation.right];
if (handlerLocations.value.indexOf(fromHandlerLocation) < handlerLocations.value.indexOf(toHandlerLocation)) return [Direction.Right, toHandlerLocation.left - fromHandlerLocation.right - Arrow_Head_Width, fromHandlerLocation.right];
return [Direction.Left, toHandlerLocation.left - fromHandlerLocation.right - Arrow_Head_Width, toHandlerLocation.left];
const toHandlerCentre = toHandlerLocation.left + (toHandlerLocation.right - toHandlerLocation.left) / 2;
const [direction, width, fromX, messageTypeOffset] = (() => {
if (fromHandlerLocation.left === toHandlerLocation.left) return [Direction.Right, 15 + Arrow_Head_Width, fromHandlerLocation.right, toHandlerCentre + 45];
if (fromHandlerLocation.left < toHandlerLocation.left) return [Direction.Right, toHandlerCentre - fromHandlerLocation.right - Arrow_Head_Width - 1, fromHandlerLocation.right, toHandlerCentre + 3];
return [Direction.Left, toHandlerCentre - fromHandlerLocation.left + Arrow_Head_Width + 1, fromHandlerLocation.left, toHandlerCentre - ((messageTypeElementBounds?.width ?? 0) + 15 + Message_Type_Margin * 3 + 3)];
})();
route.fromRoutedMessage.direction = direction;

const toX = toHandlerLocation.left + (toHandlerLocation.right - toHandlerLocation.left) / 2;
const messageTypeElement = messageTypeRefs.value[index];
const messageTypeElementBounds = messageTypeElement?.getBBox();
if (messageTypeOffset < 0) {
store.setStartX(-1 * messageTypeOffset);
}

return {
id: route.name,
fromX,
y,
direction,
width,
toX,
toHandlerCentre,
height: Math.abs(y - toHandlerLocation.y),
type: route.fromRoutedMessage.type,
messageType: route.fromRoutedMessage.name,
messageTypeOffset: toX + 3, //TODO: apply using messageTypeRef if arrow is left
messageTypeOffset,
highlight: highlightId.value === route.name,
highlightTextWidth: messageTypeElementBounds?.width,
highlightTextHeight: messageTypeElementBounds?.height,
Expand All @@ -65,12 +67,12 @@ function setMessageTypeRef(el: SVGTextElement, index: number) {
<g v-if="arrow != null">
<!--Main Arrow-->
<g>
<path :d="`M${arrow.fromX} ${arrow.y} h${arrow.width}`" stroke-width="4" stroke="black" />
<path :d="`M${arrow.fromX} ${arrow.y} h${arrow.width}`" stroke-width="3.5" stroke="black" :stroke-dasharray="arrow.type === RoutedMessageType.Event ? '12 8' : undefined" />
<path v-if="arrow.direction === Direction.Right" :d="`M${arrow.fromX + arrow.width} ${arrow.y - 7.5} l10 7.5 -10,7.5z`" fill="black" />
<path v-if="arrow.direction === Direction.Left" :d="`M${arrow.fromX - Arrow_Head_Width} ${arrow.y} l10,-7.5 0,15z`" fill="black" />
<path v-if="arrow.direction === Direction.Left" :d="`M${arrow.toHandlerCentre + 1} ${arrow.y} l10,-7.5 0,15z`" fill="black" />
</g>
<!--Highlight Arrow-->
<g v-if="arrow.highlight" :transform="`translate(${arrow.toX},${arrow.y})`" stroke="var(--highlight)" fill="var(--highlight)">
<g v-if="arrow.highlight" :transform="`translate(${arrow.toHandlerCentre},${arrow.y})`" stroke="var(--highlight)" fill="var(--highlight)">
<path :d="`M0 0 v${arrow.height - 6}`" stroke-width="2" />
<path :d="`M0 ${arrow.height} l-3,-6 6,0z`" />
</g>
Expand All @@ -96,10 +98,10 @@ function setMessageTypeRef(el: SVGTextElement, index: number) {
/>
<path
v-else-if="arrow.type === RoutedMessageType.Event"
d="M 0,0 M 32,32 M 0,16 A 6,6 0 1 1 12,16 A 6,6 0 1 1 0,16 M 14,13 v6 h10 v2 L32,16 L24,11 v2 M13.78,19.54 L9.54,23.78 L16.61,30.85 L15.19,32.26 L24.38,34.38 L22.26,25.19 L20.85,26.61 M9.54,8.22 L13.78,12.46 L20.85,5.39 L22.26,6.81 L24.38,-2.38 L15.19,-0.26 L16.61,1.15"
d="M 0 2 M 27.8 29.8 M 0 15.9 A 5.2 5.2 90 1 1 10.4 15.9 A 5.2 5.2 90 1 1 0 15.9 M 12.1 13.3 v 5.2 h 8.7 v 1.8 L 27.8 15.9 L 20.8 11.6 v 1.8 M 11.9 19 L 8.3 22.6 L 14.3 28.8 L 13.1 30 L 21.2 31.9 L 19.3 23.9 L 18.1 25.1 M 8.3 9.1 L 11.9 12.9 L 18.1 6.7 L 19.3 7.9 L 21.2 0 L 13.1 1.9 L 14.3 3.1"
/>
<path v-else-if="arrow.type === RoutedMessageType.Command" d="M 0,0 M 32,32 M 0,16 A 6,6 0 1 1 12,16 A 6,6 0 1 1 0,16 M 14,13 v6 h10 v2 L32,16 L24,11 v2 z" />
<path v-else-if="arrow.type === RoutedMessageType.Local" d="M17-1h-7v2h5v7H9V5.8L3,9l6,3.2V10h8V-1z M9,0.1C9,1.7,7.7,3,6,3S3,1.7,3,0.1S4.3-3,6-3S9-1.6,9,0.1z" />
<path v-else-if="arrow.type === RoutedMessageType.Local" d="M 32 6 h -14 v 4 h 10 v 14 H 16 V 19.6 L 4 26 l 12 6.4 V 28 h 16 V 6 z M 16 8.2 C 16 11.4 13.4 14 10 14 S 4 11.4 4 8.2 S 6.6 2 10 2 S 16 4.8 16 8 z" />
</svg>
<text :x="15 + Message_Type_Margin + Message_Type_Margin" :y="Message_Type_Margin" alignment-baseline="before-edge" :ref="(el) => setMessageTypeRef(el as SVGTextElement, i)">{{ arrow.messageType }}</text>
</g>
Expand Down
7 changes: 6 additions & 1 deletion src/Frontend/src/resources/SequenceDiagram/RoutedMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Handler } from "./Handler";
import { friendlyTypeName } from "./SequenceModel";

export interface RoutedMessage {
id: string;
name: string;
readonly selectedMessage: Message;
fromHandler?: Handler;
Expand Down Expand Up @@ -66,7 +67,7 @@ class MessageProcessingRouteItem implements MessageProcessingRoute {
this.processingHandler = processingHandler;

if (routedMessage && this.processingHandler) {
this.name = `${processingHandler?.name}(${routedMessage.messageId})`;
this.name = `${processingHandler?.name}(${routedMessage.id})`;
}

if (routedMessage) routedMessage.route = this;
Expand All @@ -92,6 +93,10 @@ class RoutedMessageItem implements RoutedMessage {
this.name = friendlyTypeName(message.message_type) ?? "";
}

get id() {
return this.selectedMessage.id;
}

get receiving() {
return this.selectedMessage.receiving_endpoint;
}
Expand Down
16 changes: 16 additions & 0 deletions src/Frontend/src/stores/SequenceDiagramStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,19 @@ export interface EndpointCentrePoint {

export interface HandlerLocation {
id: string;
endpointName: string;
left: number;
right: number;
y: number;
height: number;
}

export const Endpoint_Width = 260;

export const useSequenceDiagramStore = defineStore("SequenceDiagramStore", () => {
const conversationId = ref<string>();

const startX = ref(Endpoint_Width / 2);
const endpoints = ref<Endpoint[]>([]);
const handlers = ref<Handler[]>([]);
const routes = ref<MessageProcessingRoute[]>([]);
Expand All @@ -47,9 +51,19 @@ export const useSequenceDiagramStore = defineStore("SequenceDiagramStore", () =>
});

function setConversationId(id: string) {
endpoints.value = [];
handlers.value = [];
routes.value = [];
startX.value = Endpoint_Width / 2;
conversationId.value = id;
}

function setStartX(offset: number) {
const newValue = Math.max(offset + Endpoint_Width / 2, startX.value);
if (newValue === startX.value) return;
startX.value = newValue;
}

function setMaxWidth(width: number) {
maxWidth.value = width;
}
Expand All @@ -72,6 +86,7 @@ export const useSequenceDiagramStore = defineStore("SequenceDiagramStore", () =>

return {
setConversationId,
startX,
endpoints,
handlers,
routes,
Expand All @@ -80,6 +95,7 @@ export const useSequenceDiagramStore = defineStore("SequenceDiagramStore", () =>
maxHeight,
handlerLocations,
highlightId,
setStartX,
setMaxWidth,
setMaxHeight,
setEndpointCentrePoints,
Expand Down