diff --git a/js/components/services/ServiceStatusRow.js b/js/components/services/ServiceStatusRow.js
new file mode 100644
index 000000000..976cf7c86
--- /dev/null
+++ b/js/components/services/ServiceStatusRow.js
@@ -0,0 +1,58 @@
+import { TableCell, TableRow, makeStyles, styled } from "@material-ui/core";
+import React, { memo, useEffect, useRef, useState } from "react";
+import { StatusLight } from "./StatusLight";
+
+const useStyles = makeStyles(theme => ({
+ cell: {
+ color: theme.palette.primary.contrastText
+ }
+}));
+
+export const ServiceStatusRow = memo(({ service }) => {
+
+ const classes = useStyles();
+ const interval = useRef(null);
+ const [uptime, setUptime] = useState(0);
+
+ const StyledTableRow = styled(TableRow)(({ theme }) => ({
+ // hide last border
+ '&:last-child td, &:last-child th': {
+ border: 0
+ }
+ }));
+
+ useEffect(() => {
+ if (service.timestamp) {
+ interval.current = setInterval(() => {
+ setUptime(Date.now() - service.timestamp);
+ }, 1000);
+ }
+
+ return () => {
+ if (interval) {
+ clearInterval(interval.current);
+ }
+ }
+ }, [service, interval]);
+
+ const getServiceDowntime = () => {
+ if (uptime) {
+ let minutes = Math.floor(uptime / (1000 * 60));
+ let seconds = Math.floor(uptime / (1000) % 60);
+ if (minutes) {
+ return `${minutes} m ${seconds} s`;
+ } else {
+ return `${seconds} s`;
+ }
+ } else {
+ return '';
+ }
+ }
+
+ return
+
+ {service.state}
+ {service.name}
+ {getServiceDowntime()}
+ ;
+});
\ No newline at end of file
diff --git a/js/components/services/ServicesStatus.js b/js/components/services/ServicesStatus.js
index 5a47c4ab3..197ef3774 100644
--- a/js/components/services/ServicesStatus.js
+++ b/js/components/services/ServicesStatus.js
@@ -1,19 +1,11 @@
-import { Grid, Table, TableBody, TableCell, TableRow, Tooltip, makeStyles, styled } from "@material-ui/core";
+import { Grid, Table, TableBody, Tooltip, styled } from "@material-ui/core";
import React, { memo } from "react";
import { ServiceStatus } from "./ServiceStatus";
-import { StatusLight } from "./StatusLight";
import { tooltipClasses } from "@mui/material";
-
-const useStyles = makeStyles(theme => ({
- cell: {
- color: theme.palette.primary.contrastText
- }
-}));
+import { ServiceStatusRow } from "./ServiceStatusRow";
export const ServicesStatus = memo(({ services }) => {
- const classes = useStyles();
-
const NoMaxWidthTooltip = styled(({ className, ...props }) => (
))({
@@ -22,19 +14,8 @@ export const ServicesStatus = memo(({ services }) => {
}
});
- const StyledTableRow = styled(TableRow)(({ theme }) => ({
- // hide last border
- '&:last-child td, &:last-child th': {
- border: 0
- }
- }));
-
return
- {services.map((service) =>
-
- {service.state}
- {service.name}
- )}
+ {services.map((service) => )}
}>
{services.map((service) =>
diff --git a/js/components/services/ServicesStatusWrapper.js b/js/components/services/ServicesStatusWrapper.js
index ae5b627af..52fad2f6d 100644
--- a/js/components/services/ServicesStatusWrapper.js
+++ b/js/components/services/ServicesStatusWrapper.js
@@ -3,23 +3,39 @@ import React, { memo, useCallback, useContext, useEffect, useState } from "react
import { ServicesStatus } from "./ServicesStatus";
import { getServicesStatus } from "./api/api";
import { ToastContext } from "../toast";
+import { SERVICE_STATUSES } from "./constants";
export const ServicesStatusWrapper = memo(() => {
const [services, setServices] = useState([]);
- const { toastError, toastInfo } = useContext(ToastContext);
+ const { toastError } = useContext(ToastContext);
const checkServices = useCallback((previous, current) => {
if (previous.length > 0) {
- const changedServices = current.filter(newService => {
+ // update timestamps for services
+ current.forEach(newService => {
const currentService = previous.find(previousService => previousService.id === newService.id);
+ // remember previous value
+ newService.timestamp = currentService.timestamp;
if (currentService && currentService.state !== newService.state) {
- return true;
+ if (![SERVICE_STATUSES.OK, SERVICE_STATUSES.DEGRADED].includes(newService.state)) {
+ newService.timestamp = Date.now();
+ } else {
+ // clear timestamp
+ newService.timestamp = null;
+ }
+ }
+ });
+ } else {
+ // initial set
+ current.forEach(service => {
+ if (![SERVICE_STATUSES.OK, SERVICE_STATUSES.DEGRADED].includes(service.state)) {
+ service.timestamp = Date.now();
+ } else {
+ service.timestamp = null;
}
- return false;
});
- changedServices.forEach(service => toastInfo(`Status of ${service.name} changed to ${service.state}`));
}
- }, [toastInfo]);
+ }, []);
const fetchServicesStatus = useCallback(async () => {
const temp = await getServicesStatus();
@@ -29,7 +45,7 @@ export const ServicesStatusWrapper = memo(() => {
if (!(prevState.length === 1 && prevState[0]?.id === 'services')) {
toastError('Status of services is not available');
}
- return [{ id: 'services', name: 'Status of services', state: 'NOT_AVAILABLE' }];
+ return [{ id: 'services', name: 'Status of services', state: 'NOT_AVAILABLE', timestamp: Date.now() }];
});
} else {
setServices((prevState) => {
diff --git a/js/components/services/StatusLight.js b/js/components/services/StatusLight.js
index c70a48507..3ba936b68 100644
--- a/js/components/services/StatusLight.js
+++ b/js/components/services/StatusLight.js
@@ -1,5 +1,6 @@
import { makeStyles } from "@material-ui/core";
import React, { memo } from "react";
+import { SERVICE_STATUSES, SERVICE_STATUS_COLORS } from "./constants";
const useStyles = makeStyles(theme => ({
circle: {
@@ -8,17 +9,6 @@ const useStyles = makeStyles(theme => ({
}
}));
-export const SERVICE_STATUSES = {
- OK: 'OK',
- DEGRADED: 'DEGRADED'
-}
-
-export const SERVICE_STATUS_COLORS = {
- OK: 'green',
- DEGRADED: 'orange',
- OTHER: 'red'
-}
-
export const StatusLight = memo(({ service }) => {
const getColor = (status) => {
switch (status) {
diff --git a/js/components/services/constants.js b/js/components/services/constants.js
new file mode 100644
index 000000000..17cbc8b80
--- /dev/null
+++ b/js/components/services/constants.js
@@ -0,0 +1,10 @@
+export const SERVICE_STATUSES = {
+ OK: 'OK',
+ DEGRADED: 'DEGRADED'
+}
+
+export const SERVICE_STATUS_COLORS = {
+ OK: 'green',
+ DEGRADED: 'orange',
+ OTHER: 'red'
+}
\ No newline at end of file
diff --git a/js/components/services/index.js b/js/components/services/index.js
index 039373908..8c29f48d4 100644
--- a/js/components/services/index.js
+++ b/js/components/services/index.js
@@ -2,3 +2,4 @@ export * from './ServicesStatus';
export * from './ServicesStatusWrapper';
export * from './ServiceStatus';
export * from './api/api';
+export * from './constants';