-
Notifications
You must be signed in to change notification settings - Fork 38
Expand file tree
/
Copy pathProcessCluster.tsx
More file actions
118 lines (110 loc) · 3.84 KB
/
ProcessCluster.tsx
File metadata and controls
118 lines (110 loc) · 3.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import { Paper, Flex, Transition, Badge, Text } from "@mantine/core";
import { useState } from "react";
import { IProcess, ISetting } from "@pm2.web/typings";
import cx from "clsx";
import ProcessHeader from "./ProcessHeader";
import ProcessClusterChart from "./ProcessClusterChart";
import ProcessClusterLog from "./ProcessClusterLog";
import ProcessClusterMetricRow from "./ProcessClusterMetricRow";
import ProcessClusterAction from "./ProcessClusterAction";
import classes from "@/styles/process.module.css";
interface ProcessClusterProps {
processes: IProcess[];
clusterName: string;
setting: ISetting;
}
export default function ProcessCluster({ processes, clusterName, setting }: ProcessClusterProps) {
const [collapsed, setCollapsed] = useState(true);
// Aggregate cluster information
const onlineCount = processes.filter(p => p.status === "online").length;
const stoppedCount = processes.filter(p => p.status === "stopped").length;
const erroredCount = processes.filter(p => p.status === "errored" || p.status === "offline").length;
// Determine overall cluster status
const getClusterStatus = () => {
if (onlineCount === processes.length) return "online";
if (stoppedCount === processes.length) return "stopped";
if (erroredCount > 0) return "errored";
return "mixed";
};
const getStatusColor = () => {
switch (getClusterStatus()) {
case "online": {
return "#12B886";
}
case "stopped": {
return "#FCC419";
}
case "mixed": {
return "#339AF0";
}
default: {
return "#FA5252";
}
}
};
// Get primary process for display (prefer online process)
const primaryProcess = processes.find(p => p.status === "online") || processes[0];
return (
<Paper
key={`cluster-${clusterName}`}
radius="md"
p="xs"
shadow="sm"
className={cx(classes.processItem, {
[classes.opened]: !collapsed,
[classes.closed]: collapsed,
})}
>
<Flex direction={"column"}>
<Flex align={"center"} justify={"space-between"} wrap={"wrap"}>
<Flex align={"center"} gap={"sm"}>
<ProcessHeader
statusColor={getStatusColor()}
interpreter={primaryProcess.type}
name={clusterName}
/>
<Badge
size="sm"
variant="light"
color={getClusterStatus() === "online" ? "green" : getClusterStatus() === "stopped" ? "yellow" : "red"}
>
{processes.length} instances
</Badge>
{getClusterStatus() === "mixed" && (
<Text size="xs" c="dimmed">
{onlineCount} online, {stoppedCount} stopped, {erroredCount} errored
</Text>
)}
</Flex>
<Flex align={"center"} rowGap={"10px"} columnGap={"40px"} wrap={"wrap"} justify={"end"}>
<ProcessClusterMetricRow
processes={processes}
refetchInterval={setting.polling.frontend}
showMetric={onlineCount > 0}
/>
<ProcessClusterAction
processes={processes}
collapse={() => setCollapsed(!collapsed)}
/>
</Flex>
</Flex>
<Transition transition="scale-y" duration={500} mounted={!collapsed}>
{(styles) => (
<div style={{ ...styles }}>
<ProcessClusterChart
processes={processes}
refetchInterval={setting.polling.frontend}
showMetric={onlineCount > 0}
polling={setting.polling.frontend}
/>
<ProcessClusterLog
processes={processes}
refetchInterval={setting.polling.frontend}
/>
</div>
)}
</Transition>
</Flex>
</Paper>
);
}