Skip to content

Commit 3803685

Browse files
authored
Merge pull request #2271 from Particular/john/message_view
Moved message display to be under /messages
2 parents c3af652 + 96ba77a commit 3803685

10 files changed

+95
-64
lines changed

src/Frontend/package-lock.json

+4-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Frontend/src/components/EventLogItem.vue

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script setup lang="ts">
2-
import { useRouter } from "vue-router";
2+
import { useRoute, useRouter } from "vue-router";
33
import TimeSince from "../components/TimeSince.vue";
44
import type EventLogItem from "@/resources/EventLogItem";
55
// eslint-disable-next-line no-duplicate-imports
@@ -8,6 +8,7 @@ import routeLinks from "@/router/routeLinks";
88
99
defineProps<{ eventLogItem: EventLogItem }>();
1010
const router = useRouter();
11+
const route = useRoute();
1112
1213
function navigateToEvent(eventLogItem: EventLogItem) {
1314
switch (eventLogItem.category) {
@@ -26,7 +27,7 @@ function navigateToEvent(eventLogItem: EventLogItem) {
2627
case "MessageFailures":
2728
if (eventLogItem.related_to?.length && eventLogItem.related_to[0].search("message") > 0) {
2829
const messageId = eventLogItem.related_to[0].substring(9);
29-
router.push(routeLinks.failedMessage.message.link(messageId));
30+
router.push({ path: routeLinks.messages.message.link(messageId), query: { back: route.path } });
3031
} else {
3132
router.push(routeLinks.failedMessage.root);
3233
}

src/Frontend/src/components/failedmessages/MessageList.vue

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script setup lang="ts">
2-
import { useRouter } from "vue-router";
2+
import { useRoute, useRouter } from "vue-router";
33
import TimeSince from "../TimeSince.vue";
44
import NoData from "../NoData.vue";
55
import routeLinks from "@/router/routeLinks";
@@ -17,6 +17,7 @@ export interface IMessageList {
1717
1818
let lastLabelClickedIndex: number | undefined;
1919
const router = useRouter();
20+
const route = useRoute();
2021
const emit = defineEmits(["retryRequested"]);
2122
const props = withDefaults(
2223
defineProps<{
@@ -77,7 +78,7 @@ function labelClicked($event: MouseEvent, index: number) {
7778
}
7879
7980
function navigateToMessage(messageId: string) {
80-
router.push(routeLinks.failedMessage.message.link(messageId));
81+
router.push({ path: routeLinks.messages.message.link(messageId), query: { back: route.path } });
8182
}
8283
8384
defineExpose<IMessageList>({
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<script setup lang="ts">
2+
import { onMounted } from "vue";
3+
import { useRoute, useRouter } from "vue-router";
4+
import routeLinks from "@/router/routeLinks";
5+
6+
const route = useRoute();
7+
const router = useRouter();
8+
const id = route.params.id;
9+
10+
onMounted(async () => {
11+
await router.push({ path: routeLinks.messages.message.link(id.toString()), query: { back: routeLinks.failedMessage.failedMessages.link } });
12+
});
13+
</script>

src/Frontend/src/components/failedmessages/FlowDiagram.vue renamed to src/Frontend/src/components/messages/FlowDiagram.vue

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
<script setup lang="ts">
22
import { onMounted, ref } from "vue";
3-
import { useTypedFetchFromServiceControl } from "../../composables/serviceServiceControlUrls";
3+
import { useTypedFetchFromServiceControl } from "@/composables/serviceServiceControlUrls";
44
import { type DefaultEdge, MarkerType, useVueFlow, VueFlow, type Styles, type Node } from "@vue-flow/core";
55
import TimeSince from "../TimeSince.vue";
66
import routeLinks from "@/router/routeLinks";
77
import Message from "@/resources/Message";
88
import { NServiceBusHeaders } from "@/resources/Header";
9+
import { useRoute } from "vue-router";
910
1011
const props = defineProps<{
1112
conversationId?: string;
@@ -42,6 +43,8 @@ interface MappedMessage {
4243
const nodeSpacingX = 300;
4344
const nodeSpacingY = 200;
4445
46+
const route = useRoute();
47+
4548
async function getConversation(conversationId: string) {
4649
const [, data] = await useTypedFetchFromServiceControl<Message[]>(`conversations/${conversationId}`);
4750
return data;
@@ -206,7 +209,7 @@ function typeIcon(type: MessageType) {
206209
<i class="fa" :class="typeIcon(nodeProps.data.type)" :title="nodeProps.data.type" />
207210
<div class="lead righ-side-ellipsis" :title="nodeProps.data.nodeName">
208211
<strong>
209-
<RouterLink v-if="nodeProps.data.isError" :to="routeLinks.failedMessage.message.link(nodeProps.data.id)">{{ nodeProps.data.nodeName }}</RouterLink>
212+
<RouterLink v-if="nodeProps.data.isError" :to="{ path: routeLinks.messages.message.link(nodeProps.data.id), query: { back: route.path } }">{{ nodeProps.data.nodeName }}</RouterLink>
210213
<span v-else>{{ nodeProps.data.nodeName }}</span>
211214
</strong>
212215
</div>

src/Frontend/src/components/failedmessages/MessageView.vue renamed to src/Frontend/src/components/messages/MessageView.vue

+49-47
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
<script setup lang="ts">
22
import { computed, onMounted, onUnmounted, ref, watch } from "vue";
3-
import { RouterLink, useRoute } from "vue-router";
4-
import { serviceControlUrl, useFetchFromServiceControl, useTypedFetchFromServiceControl } from "../../composables/serviceServiceControlUrls";
5-
import { useArchiveMessage, useRetryMessages, useUnarchiveMessage } from "../../composables/serviceFailedMessage";
6-
import { useDownloadFileFromString } from "../../composables/fileDownloadCreator";
7-
import { useShowToast } from "../../composables/toast";
3+
import { RouterLink, useRoute, useRouter } from "vue-router";
4+
import { serviceControlUrl, useFetchFromServiceControl, useTypedFetchFromServiceControl } from "@/composables/serviceServiceControlUrls";
5+
import { useArchiveMessage, useRetryMessages, useUnarchiveMessage } from "@/composables/serviceFailedMessage";
6+
import { useDownloadFileFromString } from "@/composables/fileDownloadCreator";
7+
import { useShowToast } from "@/composables/toast";
88
import NoData from "../NoData.vue";
99
import TimeSince from "../TimeSince.vue";
1010
import moment from "moment";
1111
import ConfirmDialog from "../ConfirmDialog.vue";
1212
import FlowDiagram from "./FlowDiagram.vue";
13-
import EditRetryDialog from "./EditRetryDialog.vue";
13+
import EditRetryDialog from "../failedmessages/EditRetryDialog.vue";
1414
import routeLinks from "@/router/routeLinks";
1515
import { EditAndRetryConfig } from "@/resources/Configuration";
1616
import { TYPE } from "vue-toastification";
@@ -28,6 +28,7 @@ const route = useRoute();
2828
const failedMessage = ref<ExtendedFailedMessage | FailedMessageError>();
2929
const editAndRetryConfiguration = ref<EditAndRetryConfig>();
3030
31+
const backLink = ref<string>(routeLinks.failedMessage.failedMessages.link);
3132
const id = computed(() => route.params.id as string);
3233
watch(id, async () => await loadFailedMessage());
3334
@@ -40,39 +41,34 @@ const configuration = useConfiguration();
4041
const isMassTransitConnected = useIsMassTransitConnected();
4142
4243
async function loadFailedMessage() {
43-
try {
44-
const response = await useFetchFromServiceControl("errors/last/" + id.value);
45-
if (response.status === 404) {
46-
failedMessage.value = { notFound: true } as FailedMessageError;
47-
return;
48-
} else if (!response.ok) {
49-
failedMessage.value = { error: true } as FailedMessageError;
50-
return;
51-
}
52-
const message = (await response.json()) as ExtendedFailedMessage;
53-
message.archived = message.status === FailedMessageStatus.Archived;
54-
message.resolved = message.status === FailedMessageStatus.Resolved;
55-
message.retried = message.status === FailedMessageStatus.RetryIssued;
56-
message.error_retention_period = moment.duration(configuration.value?.data_retention.error_retention_period).asHours();
57-
message.isEditAndRetryEnabled = editAndRetryConfiguration.value?.enabled ?? false;
58-
59-
// Maintain the mutations of the message in memory until the api returns a newer modified message
60-
if (failedMessage.value && !isError(failedMessage.value) && failedMessage.value.last_modified === message.last_modified) {
61-
message.retried = failedMessage.value?.retried;
62-
message.archiving = failedMessage.value?.archiving;
63-
message.restoring = failedMessage.value?.restoring;
64-
} else {
65-
message.archiving = false;
66-
message.restoring = false;
67-
}
68-
69-
updateMessageDeleteDate(message);
70-
await downloadHeadersAndBody(message);
71-
failedMessage.value = message;
72-
} catch (err) {
73-
console.log(err);
44+
const response = await useFetchFromServiceControl(`errors/last/${id.value}`);
45+
if (response.status === 404) {
46+
failedMessage.value = { notFound: true } as FailedMessageError;
7447
return;
48+
} else if (!response.ok) {
49+
failedMessage.value = { error: true } as FailedMessageError;
50+
return;
51+
}
52+
const message = (await response.json()) as ExtendedFailedMessage;
53+
message.archived = message.status === FailedMessageStatus.Archived;
54+
message.resolved = message.status === FailedMessageStatus.Resolved;
55+
message.retried = message.status === FailedMessageStatus.RetryIssued;
56+
message.error_retention_period = moment.duration(configuration.value?.data_retention.error_retention_period).asHours();
57+
message.isEditAndRetryEnabled = editAndRetryConfiguration.value?.enabled ?? false;
58+
59+
// Maintain the mutations of the message in memory until the api returns a newer modified message
60+
if (failedMessage.value && !isError(failedMessage.value) && failedMessage.value.last_modified === message.last_modified) {
61+
message.retried = failedMessage.value?.retried;
62+
message.archiving = failedMessage.value?.archiving;
63+
message.restoring = failedMessage.value?.restoring;
64+
} else {
65+
message.archiving = false;
66+
message.restoring = false;
7567
}
68+
69+
updateMessageDeleteDate(message);
70+
await downloadHeadersAndBody(message);
71+
failedMessage.value = message;
7672
}
7773
7874
async function getEditAndRetryConfig() {
@@ -361,11 +357,15 @@ function changeRefreshInterval(milliseconds: number) {
361357
}
362358
363359
onMounted(async () => {
360+
const back = useRouter().currentRoute.value.query.back as string;
361+
if (back) {
362+
backLink.value = back;
363+
}
364364
togglePanel(1);
365365
366366
await getEditAndRetryConfig();
367367
startRefreshInterval();
368-
loadFailedMessage();
368+
await loadFailedMessage();
369369
});
370370
371371
onUnmounted(() => {
@@ -386,6 +386,7 @@ onUnmounted(() => {
386386
<div v-if="!isError(failedMessage)">
387387
<div class="row">
388388
<div class="col-sm-12 no-side-padding">
389+
<RouterLink :to="backLink"><i class="fa fa-chevron-left"></i> Back</RouterLink>
389390
<div class="active break group-title">
390391
<h1 class="message-type-title">{{ failedMessage.message_type }}</h1>
391392
</div>
@@ -403,7 +404,9 @@ onUnmounted(() => {
403404
{{ failedMessage.number_of_processing_attempts - 1 }} Retry Failures
404405
</span>
405406
<span v-if="failedMessage.edited" v-tippy="`Message was edited`" class="label sidebar-label label-info metadata-label">Edited</span>
406-
<span v-if="failedMessage.edited" class="metadata metadata-link"><i class="fa fa-history"></i> <RouterLink :to="routeLinks.failedMessage.message.link(failedMessage.edit_of)">View previous version</RouterLink></span>
407+
<span v-if="failedMessage.edited" class="metadata metadata-link">
408+
<i class="fa fa-history"></i> <RouterLink :to="{ path: routeLinks.messages.message.link(failedMessage.edit_of), query: { back: route.path } }">View previous version</RouterLink>
409+
</span>
407410
<span v-if="failedMessage.time_of_failure" class="metadata"><i class="fa fa-clock-o"></i> Failed: <time-since :date-utc="failedMessage.time_of_failure"></time-since></span>
408411
<span class="metadata"><i class="fa pa-endpoint"></i> Endpoint: {{ failedMessage.receiving_endpoint.name }}</span>
409412
<span class="metadata"><i class="fa fa-laptop"></i> Machine: {{ failedMessage.receiving_endpoint.host }}</span>
@@ -426,7 +429,7 @@ onUnmounted(() => {
426429
<i class="fa fa-pencil"></i> Edit & retry
427430
</button>
428431
<button v-if="!isMassTransitConnected" type="button" class="btn btn-default" @click="debugInServiceInsight()" title="Browse this message in ServiceInsight, if installed">
429-
<img src="@/assets/si-icon.svg" /> View in ServiceInsight
432+
<img src="@/assets/si-icon.svg" alt="ServiceInsight logo" /> View in ServiceInsight
430433
</button>
431434
<button type="button" class="btn btn-default" @click="exportMessage()"><i class="fa fa-download"></i> Export message</button>
432435
</div>
@@ -440,7 +443,6 @@ onUnmounted(() => {
440443
<h5 :class="{ active: panel === 3 }" class="nav-item" @click="togglePanel(3)"><a href="javascript:void(0)">Message body</a></h5>
441444
<h5 v-if="!isMassTransitConnected" :class="{ active: panel === 4 }" class="nav-item" @click="togglePanel(4)"><a href="javascript:void(0)">Flow Diagram</a></h5>
442445
</div>
443-
<pre v-if="panel === 0">{{ failedMessage.exception?.message }}</pre>
444446
<pre v-if="panel === 1">{{ failedMessage.exception?.stack_trace }}</pre>
445447
<table class="table" v-if="panel === 2 && !failedMessage.headersNotFound">
446448
<tbody>
@@ -473,8 +475,8 @@ onUnmounted(() => {
473475
showDeleteConfirm = false;
474476
archiveMessage();
475477
"
476-
:heading="'Are you sure you want to delete this message?'"
477-
:body="'If you delete, this message won\'t be available for retrying unless it is later restored.'"
478+
heading="Are you sure you want to delete this message?"
479+
body="If you delete, this message won't be available for retrying unless it is later restored."
478480
></ConfirmDialog>
479481

480482
<ConfirmDialog
@@ -484,8 +486,8 @@ onUnmounted(() => {
484486
showRestoreConfirm = false;
485487
unarchiveMessage();
486488
"
487-
:heading="'Are you sure you want to restore this message?'"
488-
:body="'The restored message will be moved back to the list of failed messages.'"
489+
heading="Are you sure you want to restore this message?"
490+
body="The restored message will be moved back to the list of failed messages."
489491
></ConfirmDialog>
490492

491493
<ConfirmDialog
@@ -495,8 +497,8 @@ onUnmounted(() => {
495497
showRetryConfirm = false;
496498
retryMessage();
497499
"
498-
:heading="'Are you sure you want to retry this message?'"
499-
:body="'Are you sure you want to retry this message?'"
500+
heading="Are you sure you want to retry this message?"
501+
body="Are you sure you want to retry this message?"
500502
></ConfirmDialog>
501503

502504
<EditRetryDialog

src/Frontend/src/composables/serviceServiceControlUrls.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ export function useFetchFromServiceControl(suffix: string) {
5353

5454
export async function useTypedFetchFromServiceControl<T>(suffix: string): Promise<[Response, T]> {
5555
const response = await fetch(`${serviceControlUrl.value}${suffix}`);
56-
if (!response?.ok) throw new Error(response?.statusText ?? "No response");
56+
if (!response.ok) throw new Error(response.statusText ?? "No response");
5757
const data = await response.json();
5858

5959
return [response, data];

src/Frontend/src/router/config.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,15 @@ const config: RouteItem[] = [
9696
{
9797
path: routeLinks.failedMessage.message.template,
9898
title: "Message",
99-
component: () => import("@/components/failedmessages/MessageView.vue"),
99+
component: () => import("@/components/failedmessages/MessageRedirectForBackwardsCompatibility.vue"),
100100
},
101101
],
102102
},
103+
{
104+
path: routeLinks.messages.message.template,
105+
title: "Message",
106+
component: () => import("@/components/messages/MessageView.vue"),
107+
},
103108
{
104109
path: routeLinks.monitoring.root,
105110
component: MonitoringView,

src/Frontend/src/router/routeLinks.ts

+8
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,13 @@ const failedMessagesLinks = (root: string) => {
3030
};
3131
};
3232

33+
const messagesLinks = (root: string) => {
34+
return {
35+
root,
36+
message: { link: (id: string) => `${root}/${id}`, template: "/messages/:id" },
37+
};
38+
};
39+
3340
const configurationLinks = (root: string) => {
3441
function createLink(template: string) {
3542
return { link: `${root}/${template}`, template: template };
@@ -96,6 +103,7 @@ const routeLinks = {
96103
failedMessage: failedMessagesLinks("/failed-messages"),
97104
customChecks: "/custom-checks",
98105
events: "/events",
106+
messages: messagesLinks("/messages"),
99107
configuration: configurationLinks("/configuration"),
100108
throughput: throughputLinks("/usage"),
101109
};

src/Frontend/src/views/FailedMessagesView.vue

+3-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<script setup lang="ts">
22
import { RouterLink, RouterView } from "vue-router";
3-
import { licenseStatus } from "../composables/serviceLicense";
4-
import { connectionState, stats } from "../composables/serviceServiceControl";
3+
import { licenseStatus } from "@/composables/serviceLicense";
4+
import { connectionState, stats } from "@/composables/serviceServiceControl";
55
import LicenseExpired from "../components/LicenseExpired.vue";
66
import routeLinks from "@/router/routeLinks";
77
import isRouteSelected from "@/composables/isRouteSelected";
@@ -31,10 +31,7 @@ const showPendingRetry = window.defaultConfig.showPendingRetry;
3131
</h5>
3232

3333
<!--All Failed Messages-->
34-
<h5
35-
v-if="!licenseStatus.isExpired"
36-
:class="{ active: isRouteSelected(routeLinks.failedMessage.failedMessages.link) || isRouteSelected(routeLinks.failedMessage.message.link(`id`)), disabled: !connectionState.connected && !connectionState.connectedRecently }"
37-
>
34+
<h5 v-if="!licenseStatus.isExpired" :class="{ active: isRouteSelected(routeLinks.failedMessage.failedMessages.link), disabled: !connectionState.connected && !connectionState.connectedRecently }">
3835
<RouterLink :to="routeLinks.failedMessage.failedMessages.link">All Failed Messages </RouterLink>
3936
<span v-if="stats.number_of_failed_messages !== 0" class="badge badge-important">{{ stats.number_of_failed_messages }}</span>
4037
</h5>

0 commit comments

Comments
 (0)