Merge branch 'service-card-restructure'
This commit is contained in:
@ -1,15 +1,14 @@
|
|||||||
import React from "react";
|
import React, { ReactElement } from "react";
|
||||||
import { Service, Node, StatusPerTenant } from "../../types";
|
import { Service, Node, StatusPerTenant } from "../../types";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import Card from "@mui/material/Card";
|
import Card from "@mui/material/Card";
|
||||||
import CardContent from "@mui/material/CardContent";
|
import CardContent from "@mui/material/CardContent";
|
||||||
import Stack from "@mui/material/Stack";
|
import Stack from "@mui/material/Stack";
|
||||||
import IconButton from "@mui/material/IconButton";
|
|
||||||
import LaunchIcon from "@mui/icons-material/Launch";
|
|
||||||
import Tooltip from "@mui/material/Tooltip";
|
import Tooltip from "@mui/material/Tooltip";
|
||||||
import Chip from "@mui/material/Chip";
|
import Chip from "@mui/material/Chip";
|
||||||
import Grid from "@mui/material/Unstable_Grid2";
|
|
||||||
import Box from "@mui/material/Box";
|
import Box from "@mui/material/Box";
|
||||||
|
import Link from "@mui/material/Link";
|
||||||
|
import Avatar from "@mui/material/Avatar";
|
||||||
|
|
||||||
interface ServiceCardProps {
|
interface ServiceCardProps {
|
||||||
service: Service;
|
service: Service;
|
||||||
@ -32,8 +31,6 @@ function TenantsStatusTooltip({ tenantsStatus }: TenantsStatusTooltipProps) {
|
|||||||
console.log(`key: ${key}, value: ${value}`);
|
console.log(`key: ${key}, value: ${value}`);
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
// console.log(tenantsStatus);
|
|
||||||
// console.log(statusItems);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box className="tenants-status-tooltip">
|
<Box className="tenants-status-tooltip">
|
||||||
@ -43,66 +40,70 @@ function TenantsStatusTooltip({ tenantsStatus }: TenantsStatusTooltipProps) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getNodeNameElement(node: Node): React.ReactElement {
|
||||||
|
let statusMessage;
|
||||||
|
const statusOk = node.health_check_status?.status_ok;
|
||||||
|
|
||||||
|
if (statusOk) {
|
||||||
|
statusMessage = `Node ${node.name} is healthy`;
|
||||||
|
} else {
|
||||||
|
statusMessage = node.health_check_status?.message;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Tooltip title={statusMessage}>
|
||||||
|
<Avatar variant="square" className="node-name">
|
||||||
|
{node.name}
|
||||||
|
</Avatar>
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TenantsStatusProps {
|
||||||
|
statusPerTenant: StatusPerTenant | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function TenantsStatus({ statusPerTenant }: TenantsStatusProps) {
|
||||||
|
if (!statusPerTenant) return <></>;
|
||||||
|
|
||||||
|
let statuses: ReactElement[] = [];
|
||||||
|
|
||||||
|
for (const [tenantId, statusOk] of Object.entries(statusPerTenant)) {
|
||||||
|
statuses.push(
|
||||||
|
<Typography component="div" className={`tenant-status ${statusOk ? "status-ok" : "status-error"}`}>
|
||||||
|
{tenantId}
|
||||||
|
</Typography>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Stack direction="row" spacing={1} className="tenants-status-container">
|
||||||
|
<Typography component="div" className="tenants-status-title">
|
||||||
|
Tenants
|
||||||
|
</Typography>
|
||||||
|
{statuses}
|
||||||
|
</Stack>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
interface ServiceNodePropps {
|
interface ServiceNodePropps {
|
||||||
node: Node;
|
node: Node;
|
||||||
}
|
}
|
||||||
|
|
||||||
function ServiceNode({ node }: ServiceNodePropps) {
|
function ServiceNode({ node }: ServiceNodePropps) {
|
||||||
const nodeName = node.health_check_status?.status_ok ? (
|
const nodeUrl = node.url.replace("http://", "").replace("https://", "");
|
||||||
<Tooltip title={`Node ${node.name} is healthy`}>
|
const statusOk = node.health_check_status?.status_ok;
|
||||||
<Chip label={node.name} color="success" className="node-name" />
|
|
||||||
</Tooltip>
|
|
||||||
) : (
|
|
||||||
<Tooltip title={node.health_check_status?.message}>
|
|
||||||
<Chip label={node.name} color="error" className="node-name" />
|
|
||||||
</Tooltip>
|
|
||||||
);
|
|
||||||
|
|
||||||
let tenantsHealth: boolean[] = [];
|
|
||||||
if (node.health_check_status?.status_per_tenant) {
|
|
||||||
tenantsHealth = Object.values(node.health_check_status?.status_per_tenant);
|
|
||||||
}
|
|
||||||
|
|
||||||
let tenantsStatusContent = null;
|
|
||||||
if (tenantsHealth.length > 0) {
|
|
||||||
const okValues = tenantsHealth.filter((t) => t === true);
|
|
||||||
|
|
||||||
switch (okValues.length) {
|
|
||||||
case 0:
|
|
||||||
tenantsStatusContent = <Chip label="tenants" color="error" className="node-name" />;
|
|
||||||
break;
|
|
||||||
case tenantsHealth.length:
|
|
||||||
tenantsStatusContent = <Chip label="tenants" color="success" className="node-name" />;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
tenantsStatusContent = <Chip label="tenants" color="warning" className="node-name" />;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node.health_check_status?.status_per_tenant) {
|
|
||||||
tenantsStatusContent = (
|
|
||||||
<Tooltip title={<TenantsStatusTooltip tenantsStatus={node.health_check_status.status_per_tenant} />}>
|
|
||||||
{tenantsStatusContent}
|
|
||||||
</Tooltip>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Grid container spacing={2} className="service-node" sx={{ alignItems: "center" }}>
|
<Stack direction="row" className={`service-node ${statusOk ? "status-ok" : "status-error"}`}>
|
||||||
<Grid xs={2}>{nodeName}</Grid>
|
<Box>{getNodeNameElement(node)}</Box>
|
||||||
<Grid xs={6}>
|
<Box className="node-details">
|
||||||
<Typography className="version">{node.app_details?.app_version || "no version"}</Typography>
|
<Typography className="version">{node.app_details?.app_version || "no version"}</Typography>
|
||||||
</Grid>
|
<Link href={node.url} target="_blank">
|
||||||
<Grid xs={4} sx={{ textAlign: "right" }} className="status">
|
{nodeUrl}
|
||||||
<Tooltip title={node.url}>
|
</Link>
|
||||||
<IconButton target="_blank" href={node.url} className="docs-url">
|
<TenantsStatus statusPerTenant={node.health_check_status?.status_per_tenant} />
|
||||||
<LaunchIcon />
|
</Box>
|
||||||
</IconButton>
|
</Stack>
|
||||||
</Tooltip>
|
|
||||||
{tenantsStatusContent}
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,11 @@
|
|||||||
$color-ok: #27cb30;
|
@use "sass:color";
|
||||||
|
|
||||||
|
$color-ok: #1dad24;
|
||||||
$color-warning: #ed6c02;
|
$color-warning: #ed6c02;
|
||||||
$color-danger: #d32f2f;
|
$color-danger: #d32f2f;
|
||||||
|
|
||||||
.service-card {
|
.service-card {
|
||||||
width: 400px;
|
width: 450px;
|
||||||
.service-title-container {
|
.service-title-container {
|
||||||
color: white;
|
color: white;
|
||||||
background-color: #15232d;
|
background-color: #15232d;
|
||||||
@ -29,25 +31,67 @@ $color-danger: #d32f2f;
|
|||||||
}
|
}
|
||||||
|
|
||||||
.service-node {
|
.service-node {
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
|
||||||
.node-name {
|
.node-name {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
border-radius: 10px;
|
||||||
}
|
}
|
||||||
.status {
|
|
||||||
display: flex;
|
.node-details {
|
||||||
align-items: center;
|
border-left: 4px solid #c1c1c1;
|
||||||
.docs-url {
|
padding-left: 0.5rem;
|
||||||
margin-left: auto;
|
|
||||||
|
.version {
|
||||||
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
.status-icon {
|
.tenants-status-container {
|
||||||
margin-left: 0.5rem;
|
align-items: center;
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
flex-flow: wrap;
|
||||||
|
|
||||||
|
.tenants-status-title {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tenant-status {
|
||||||
|
color: white;
|
||||||
|
padding: 0.2rem 0.5rem;
|
||||||
|
border-radius: 10px;
|
||||||
|
&.status-ok {
|
||||||
|
background-color: color.change($color-ok, $alpha: 0.6);
|
||||||
|
}
|
||||||
|
&.status-error {
|
||||||
|
background-color: color.change($color-danger, $alpha: 0.6);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.status-ok {
|
||||||
|
.node-name {
|
||||||
|
background-color: $color-ok;
|
||||||
|
}
|
||||||
|
.node-details {
|
||||||
|
border-left-color: color.change($color-ok, $alpha: 0.6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.status-error {
|
||||||
|
.node-name {
|
||||||
|
background-color: $color-danger;
|
||||||
|
}
|
||||||
|
.node-details {
|
||||||
|
border-left-color: color.change($color-danger, $alpha: 0.6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
font-family: Verdana, Geneva, Tahoma, sans-serif;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.MuiCardContent-root {
|
.MuiCardContent-root {
|
||||||
padding-bottom: 16px !important;
|
padding-bottom: 16px !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.MuiTooltip-tooltip .tenants-status-tooltip {
|
|
||||||
}
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@ export type EnvTab = {
|
|||||||
|
|
||||||
export type StatusPerTenant = { [tenantId: string]: boolean };
|
export type StatusPerTenant = { [tenantId: string]: boolean };
|
||||||
|
|
||||||
type HealthCheckStatus = {
|
export type HealthCheckStatus = {
|
||||||
status_ok: boolean;
|
status_ok: boolean;
|
||||||
message: string;
|
message: string;
|
||||||
status_per_tenant: StatusPerTenant | null;
|
status_per_tenant: StatusPerTenant | null;
|
||||||
|
|||||||
Reference in New Issue
Block a user