Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion src/ServicePulse.Host/vue/src/components/BusyIndicator.vue
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<script setup></script>
<script setup lang="ts"></script>

<template>
<div class="row">
Expand Down
14 changes: 7 additions & 7 deletions src/ServicePulse.Host/vue/src/components/ConfirmDialog.vue
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
<script setup>
<script setup lang="ts">
import { onMounted, onUnmounted } from "vue";

const emit = defineEmits(["confirm", "cancel"]);

const settings = defineProps({
heading: String,
body: String,
secondParagraph: String,
hideCancel: Boolean,
});
const settings = defineProps<{
heading: string;
body: string;
secondParagraph: string;
hideCancel: boolean;
}>();

function confirm() {
emit("confirm", settings);
Expand Down
12 changes: 6 additions & 6 deletions src/ServicePulse.Host/vue/src/components/DashboardItem.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<script setup>
const props = defineProps({
counter: Number,
url: String,
iconClass: String,
});
<script setup lang="ts">
const props = defineProps<{
counter: number;
url: string;
iconClass: string;
}>();
</script>

<template>
Expand Down
74 changes: 29 additions & 45 deletions src/ServicePulse.Host/vue/src/components/DataView.vue
Original file line number Diff line number Diff line change
@@ -1,36 +1,27 @@
<script setup>
<script setup lang="ts" generic="T">
import { onMounted, onUnmounted, ref, watch } from "vue";
import { useFetchFromServiceControl } from "../composables/serviceServiceControlUrls";
import ItemsPerPage from "../components/ItemsPerPage.vue";
import PaginationStrip from "../components/PaginationStrip.vue";
const props = defineProps({
apiUrl: String,
itemsPerPageOptions: {
type: Array,
default: () => [20, 35, 50, 75],
},
itemsPerPage: {
type: Number,
default: 50,
},
autoRefreshSeconds: {
type: Number,
},
showPagination: {
type: Boolean,
default: true,
},
showItemsPerPage: {
type: Boolean,
default: false,
},
});
import { useTypedFetchFromServiceControl } from "@/composables/serviceServiceControlUrls";
import ItemsPerPage from "@/components/ItemsPerPage.vue";
import PaginationStrip from "@/components/PaginationStrip.vue";
import type DataViewPageModel from "./DataViewPageModel";

const props = withDefaults(
defineProps<{
apiUrl: string;
itemsPerPageOptions?: number[];
itemsPerPage?: number;
autoRefreshSeconds: number;
showPagination?: boolean;
showItemsPerPage?: boolean;
}>(),
{ itemsPerPageOptions: () => [20, 35, 50, 75], itemsPerPage: 50, showPagination: true, showItemsPerPage: false }
);

let refreshTimer: number | undefined;
const viewModel = defineModel<DataViewPageModel<T>>({ required: true });

const refreshTimer = ref();
const items = ref([]);
const pageNumber = ref(1);
const itemsPerPage = ref(props.itemsPerPage);
const totalCount = ref(0);

watch(
() => props.autoRefreshSeconds,
Expand All @@ -44,30 +35,23 @@ watch(itemsPerPage, () => loadData());
watch(pageNumber, () => loadData());

async function loadData() {
try {
const response = await useFetchFromServiceControl(`${props.apiUrl}?page=${pageNumber.value}&per_page=${itemsPerPage.value}`);
if (response.ok) {
totalCount.value = parseInt(response.headers.get("Total-Count"));
const data = await response.json();
items.value = data;
}
} catch (error) {
console.log(error);
const [response, data] = await useTypedFetchFromServiceControl<T[]>(`${props.apiUrl}?page=${pageNumber.value}&per_page=${itemsPerPage.value}`);
if (response.ok) {
viewModel.value.totalCount = parseInt(response.headers.get("Total-Count") ?? "0");
viewModel.value.data = data;
}
}

function startRefreshTimer() {
if (props.autoRefreshSeconds) {
refreshTimer.value = setInterval(() => {
refreshTimer = window.setInterval(() => {
loadData();
}, props.autoRefreshSeconds * 1000);
}
}

function stopRefreshTimer() {
if (refreshTimer.value) {
clearInterval(refreshTimer.value);
}
window.clearInterval(refreshTimer);
}

onMounted(() => {
Expand All @@ -81,10 +65,10 @@ onUnmounted(() => {
</script>

<template>
<slot name="data" v-bind="items"></slot>
<slot name="data"></slot>
<div class="row">
<ItemsPerPage v-if="showItemsPerPage" v-model="itemsPerPage" :options="itemsPerPageOptions" />
<PaginationStrip v-if="showPagination" v-model="pageNumber" :totalCount="totalCount" :itemsPerPage="itemsPerPage" />
<PaginationStrip v-if="showPagination" v-model="pageNumber" :totalCount="viewModel.totalCount" :itemsPerPage="itemsPerPage" />
</div>
<slot name="footer" :count="totalCount"></slot>
<slot name="footer"></slot>
</template>
4 changes: 4 additions & 0 deletions src/ServicePulse.Host/vue/src/components/DataViewPageModel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export default interface DataViewPageModel<T> {
data: T[];
totalCount: number;
}
22 changes: 14 additions & 8 deletions src/ServicePulse.Host/vue/src/components/EventItemShort.vue
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
<script setup>
import DataView from "../components/DataView.vue";
import EventLogItem from "../components/EventLogItem.vue";
<script setup lang="ts">
import DataView from "@/components/DataView.vue";
import EventLogItem from "@/components/EventLogItem.vue";
import type EventLogItemType from "@/resources/EventLogItem";
import { ref } from "vue";
import { RouterLink } from "vue-router";

import type DataViewPageModel from "@/components/DataViewPageModel";

const pageModel = ref<DataViewPageModel<EventLogItemType>>({ data: [], totalCount: 0 });
</script>

<template>
<div class="events">
<DataView api-url="eventlogitems" :auto-refresh-seconds="5" :itemsPerPage="10" :show-pagination="false">
<template #data="items">
<DataView api-url="eventlogitems" v-model="pageModel" :auto-refresh-seconds="5" :itemsPerPage="10" :show-pagination="false">
<template #data>
<div class="col-12">
<h6>Last 10 events</h6>
<EventLogItem v-for="item of items" :eventLogItem="item" :key="item.id" />
<EventLogItem v-for="item of pageModel.data" :eventLogItem="item" :key="item.id" />
</div>
</template>
<template #footer="{ count }">
<div v-if="count > 10" class="row text-center">
<template #footer>
<div v-if="pageModel.totalCount > 10" class="row text-center">
<div class="col-12">
<RouterLink :to="{ name: 'events' }" class="btn btn-default btn-secondary btn-all-events">View all events</RouterLink>
</div>
Expand Down
34 changes: 17 additions & 17 deletions src/ServicePulse.Host/vue/src/components/EventLogItem.vue
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
<script setup>
<script setup lang="ts">
import { useRouter } from "vue-router";
import TimeSince from "../components/TimeSince.vue";
import type EventLogItem from "@/resources/EventLogItem";
import { Severity } from "@/resources/EventLogItem";

defineProps({
eventLogItem: Object,
});
defineProps<{ eventLogItem: EventLogItem }>();
const router = useRouter();

function navigateToEvent(eventLogItem) {
function navigateToEvent(eventLogItem: EventLogItem) {
switch (eventLogItem.category) {
case "Endpoints":
router.push({ name: "endpoint-connection" });
break;
case "HeartbeatMonitoring":
window.location = "/a/#/endpoints";
window.location.assign("/a/#/endpoints");
break;
case "CustomChecks":
window.location = "/a/#/custom-checks";
window.location.assign("/a/#/custom-checks");
break;
case "EndpointControl":
window.location = "/a/#/endpoints";
window.location.assign("/a/#/endpoints");
break;
case "MessageFailures":
if (eventLogItem.related_to?.length && eventLogItem.related_to[0].search("message") > 0) {
Expand All @@ -39,10 +39,10 @@ function navigateToEvent(eventLogItem) {
}
}

function iconClasses(eventItem) {
function iconClasses(eventItem: EventLogItem) {
return {
normal: eventItem.severity === "info",
danger: eventItem.severity === "error",
normal: eventItem.severity === Severity.Info,
danger: eventItem.severity === Severity.Error,
"fa-heartbeat": eventItem.category === "Endpoints" || eventItem.category === "EndpointControl" || eventItem.category === "HeartbeatMonitoring",
"fa-check": eventItem.category === "CustomChecks",
"fa-envelope": eventItem.category === "MessageFailures" || eventItem.category === "Recoverability",
Expand All @@ -51,12 +51,12 @@ function iconClasses(eventItem) {
};
}

function iconSubClasses(eventItem) {
function iconSubClasses(eventItem: EventLogItem) {
return {
"fa-times fa-error": (eventItem.severity === "error" || eventItem.category === "MessageRedirects") && eventItem.severity === "error",
"fa-pencil": (eventItem.severity === "error" || eventItem.category === "MessageRedirects") && eventItem.category === "MessageRedirects" && eventItem.event_type === "MessageRedirectChanged",
"fa-plus": (eventItem.severity === "error" || eventItem.category === "MessageRedirects") && eventItem.category === "MessageRedirects" && eventItem.event_type === "MessageRedirectCreated",
"fa-trash": (eventItem.severity === "error" || eventItem.category === "MessageRedirects") && eventItem.category === "MessageRedirects" && eventItem.event_type === "MessageRedirectRemoved",
"fa-times fa-error": (eventItem.severity === Severity.Error || eventItem.category === "MessageRedirects") && eventItem.severity === Severity.Error,
"fa-pencil": (eventItem.severity === Severity.Error || eventItem.category === "MessageRedirects") && eventItem.category === "MessageRedirects" && eventItem.event_type === "MessageRedirectChanged",
"fa-plus": (eventItem.severity === Severity.Error || eventItem.category === "MessageRedirects") && eventItem.category === "MessageRedirects" && eventItem.event_type === "MessageRedirectCreated",
"fa-trash": (eventItem.severity === Severity.Error || eventItem.category === "MessageRedirects") && eventItem.category === "MessageRedirects" && eventItem.event_type === "MessageRedirectRemoved",
};
}
</script>
Expand All @@ -68,7 +68,7 @@ function iconSubClasses(eventItem) {
<div class="col-1">
<span class="fa-stack fa-lg">
<i class="fa fa-stack-2x" :class="iconClasses(eventLogItem)" />
<i v-if="eventLogItem.severity === 'error' || eventLogItem.category === 'MessageRedirects'" class="fa fa-o fa-stack-1x fa-inverse" :class="iconSubClasses(eventLogItem)" />
<i v-if="eventLogItem.severity === Severity.Error || eventLogItem.category === 'MessageRedirects'" class="fa fa-o fa-stack-1x fa-inverse" :class="iconSubClasses(eventLogItem)" />
</span>
</div>
<div class="col-9">
Expand Down
17 changes: 11 additions & 6 deletions src/ServicePulse.Host/vue/src/components/ExclamationMark.vue
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
<script setup>
const props = defineProps({
type: String,
});
<script setup lang="ts">
import { WarningLevel } from "@/components/WarningLevel";

const props = withDefaults(
defineProps<{
type: WarningLevel;
}>(),
{ type: WarningLevel.None }
);
</script>

<template>
<template v-if="props.type">
<span class="fa fa-exclamation-triangle" :class="type"></span>
<template v-if="props.type !== WarningLevel.None">
<span class="fa fa-exclamation-triangle" :class="props.type"></span>
</template>
</template>
19 changes: 8 additions & 11 deletions src/ServicePulse.Host/vue/src/components/ItemsPerPage.vue
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
<script setup>
defineProps({
options: {
type: Array,
default: () => [20, 35, 50, 75],
},
});
<script setup lang="ts">
withDefaults(
defineProps<{
options: number[];
}>(),
{ options: () => [20, 35, 50, 75] }
);

const current = defineModel({
type: Number,
default: 50,
});
const current = defineModel<number>({ default: 50 });
</script>

<template>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<script setup>
<script setup lang="ts">
import { licenseStatus } from "../composables/serviceLicense";
</script>

Expand Down
10 changes: 5 additions & 5 deletions src/ServicePulse.Host/vue/src/components/NoData.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<script setup>
const props = defineProps({
title: String,
message: String,
});
<script setup lang="ts">
const props = defineProps<{
title: string;
message: string;
}>();
</script>

<template>
Expand Down
6 changes: 3 additions & 3 deletions src/ServicePulse.Host/vue/src/components/PageFooter.vue
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<script setup>
<script setup lang="ts">
import { computed } from "vue";
import { connectionState, environment, monitoringConnectionState, newVersions } from "../composables/serviceServiceControl";
import { monitoringUrl, serviceControlUrl } from "../composables/serviceServiceControlUrls";
Expand All @@ -8,11 +8,11 @@ const isMonitoringEnabled = computed(() => {
});

const scAddressTooltip = computed(() => {
return "ServiceControl URL " + serviceControlUrl.value;
return `ServiceControl URL ${serviceControlUrl.value}`;
});

const scMonitoringAddressTooltip = computed(() => {
return "Monitoring URL " + monitoringUrl.value;
return `Monitoring URL ${monitoringUrl.value}`;
});
</script>

Expand Down
9 changes: 5 additions & 4 deletions src/ServicePulse.Host/vue/src/components/PageHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { connectionState, monitoringConnectionState, stats } from "../composable
import { useIsMonitoringEnabled } from "../composables/serviceServiceControlUrls";
import { licenseStatus } from "../composables/serviceLicense";
import ExclamationMark from "./ExclamationMark.vue";
import { LicenseWarningLevel } from "@/composables/LicenseStatus";

const baseUrl = window.defaultConfig.base_url;

Expand All @@ -17,10 +18,10 @@ function subIsActive(input, exact) {
}

const displayWarn = computed(() => {
return licenseStatus.warningLevel === "warning";
return licenseStatus.warningLevel === LicenseWarningLevel.Warning;
});
const displayDanger = computed(() => {
return connectionState.unableToConnect || (monitoringConnectionState.unableToConnect && useIsMonitoringEnabled()) || licenseStatus.warningLevel === "danger";
return connectionState.unableToConnect || (monitoringConnectionState.unableToConnect && useIsMonitoringEnabled()) || licenseStatus.warningLevel === LicenseWarningLevel.Danger;
});
</script>

Expand Down Expand Up @@ -79,8 +80,8 @@ const displayDanger = computed(() => {
<RouterLink :to="{ name: 'license' }" exact>
<i class="fa fa-cog icon-white" title="Configuration"></i>
<span class="navbar-label">Configuration</span>
<exclamation-mark :type="'warning'" v-if="displayWarn" />
<exclamation-mark :type="'danger'" v-if="displayDanger" />
<exclamation-mark :type="WarningLevel.Warning" v-if="displayWarn" />
<exclamation-mark :type="WarningLevel.Danger" v-if="displayDanger" />
</RouterLink>
</li>
<li>
Expand Down
Loading