Skip to content

Commit

Permalink
클러스터 내의 노드 리스트 UI 구성
Browse files Browse the repository at this point in the history
  • Loading branch information
seungh0 authored and akageun committed Jul 3, 2024
1 parent 9c30eb0 commit 9707ec8
Show file tree
Hide file tree
Showing 6 changed files with 160 additions and 15 deletions.
14 changes: 14 additions & 0 deletions cadio-web/src/main/webapp/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 9 additions & 8 deletions cadio-web/src/main/webapp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"@types/jest": "^27.5.2",
"@types/node": "^16.18.29",
"@types/react": "^18.2.6",
"@types/react-dom": "^18.2.4",
"@types/jest": "^27.5.2",
"@types/node": "^16.18.29",
"@types/react": "^18.2.6",
"@types/react-dom": "^18.2.4",
"axios": "^1.2.4",
"dayjs": "^1.11.7",
"bootstrap": "^5.3.3",
"bootstrap-icons": "^1.10.3",
"dayjs": "^1.11.7",
"moment": "^2.30.1",
"node-sass": "^7.0.3",
"react": "^18.3.1",
"react-bootstrap": "^2.10.3",
Expand Down Expand Up @@ -48,7 +49,7 @@
]
},
"proxy": "http://localhost:20000",
"devDependencies": {
"@types/bootstrap": "^5.2.10"
}
"devDependencies": {
"@types/bootstrap": "^5.2.10"
}
}
3 changes: 3 additions & 0 deletions cadio-web/src/main/webapp/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {useEffect} from "react";
import useCadio from "./pages/commons/hooks/useCadio";
import {useCadioState} from "./pages/commons/context/cadioContext";
import InitializeView from "./pages/commons/initialize-view";
import NodesHome from "./pages/cluster/components/nodes-home";
import SystemView from "./pages/system/system-view";

function App() {
Expand Down Expand Up @@ -56,6 +57,8 @@ function App() {
<Route path="/" element={<Home/>}></Route>
<Route path="/cluster/:clusterId"
element={<ClusterView><ClusterHome/></ClusterView>}></Route>
<Route path="/cluster/:clusterId/nodes"
element={<ClusterView><NodesHome/></ClusterView>}></Route>

<Route path="/cluster/:clusterId/query"
element={<ClusterView><QueryHome/></ClusterView>}></Route>
Expand Down
23 changes: 16 additions & 7 deletions cadio-web/src/main/webapp/src/pages/cluster/cluster-view.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import {Link, useParams} from "react-router-dom";
import {useEffect} from "react";
import QueryEditor from "./components/query/query-editor";
import useCluster from "./hooks/useCluster";
import {useClusterState} from "./context/clusterContext";

Expand Down Expand Up @@ -39,20 +38,30 @@ const ClusterView = (props) => {
<div className="offcanvas-body d-md-flex flex-column p-0 pt-lg-3 overflow-y-auto">
<ul className="nav flex-column">
<li className="nav-item">
<Link className={`nav-link d-flex align-items-center gap-2 link-body-emphasis text-decoration-none`}
to={`/cluster/${routeParams.clusterId}`}>
<Link
className={`nav-link d-flex align-items-center gap-2 link-body-emphasis text-decoration-none`}
to={`/cluster/${routeParams.clusterId}`}>
<i className="bi bi-house"></i> Cluster Home
</Link>
</li>
<li className="nav-item">
<Link className={`nav-link d-flex align-items-center gap-2 link-body-emphasis text-decoration-none`}
to={`/cluster/${routeParams.clusterId}/query`}>
<Link
className={`nav-link d-flex align-items-center gap-2 link-body-emphasis text-decoration-none`}
to={`/cluster/${routeParams.clusterId}/nodes`}>
<i className="bi bi-server"></i> Node List
</Link>
</li>
<li className="nav-item">
<Link
className={`nav-link d-flex align-items-center gap-2 link-body-emphasis text-decoration-none`}
to={`/cluster/${routeParams.clusterId}/query`}>
<i className="bi bi-journal-code"></i> Query Editor
</Link>
</li>
<li className="nav-item">
<Link className={`nav-link d-flex align-items-center gap-2 link-body-emphasis text-decoration-none`}
to={`/cluster/${routeParams.clusterId}/metrics`}>
<Link
className={`nav-link d-flex align-items-center gap-2 link-body-emphasis text-decoration-none`}
to={`/cluster/${routeParams.clusterId}/metrics`}>
<i className="bi bi-laptop"></i> Metrics
</Link>
</li>
Expand Down
111 changes: 111 additions & 0 deletions cadio-web/src/main/webapp/src/pages/cluster/components/nodes-home.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import {useParams} from "react-router-dom";
import {useEffect, useState} from "react";
import axios from "axios";
import {DateUtils} from "../../../utils/timeUtils";
import Spinner from "../../../components/spinner";

const NodesHome = () => {

const routeParams = useParams();

const [nodeLoading, setNodeLoading] = useState(false);
const [nodeList, setNodeList] = useState([]);
const [availableNodeSize, setAvailableNodeSize] = useState(0)
const [totalNodeSize, setTotalNodeSize] = useState(0)

useEffect(() => {
//show component
setNodeList([])

setNodeLoading(true)
axios({
method: "GET",
url: `/api/cassandra/cluster/${routeParams.clusterId}/node`,
}).then((response) => {
console.log("res ", response);
const nodes = response.data.result.items
setNodeList(nodes)
setTotalNodeSize(nodes.length)
setAvailableNodeSize(nodes.filter(node => node.nodeState === 'UP').length)
}).catch((error) => {
console.log(error)
//TODO : error catch
}).finally(() => {
setNodeLoading(false)
});

return () => {
//hide component

};
}, [routeParams.clusterId, routeParams.keyspaceName]);

const nodesByDcAndRack = nodeList.reduce((acc, node) => {
const { datacenter, rack } = node;
if (!acc[datacenter]) {
acc[datacenter] = {};
}
if (!acc[datacenter][rack]) {
acc[datacenter][rack] = [];
}
acc[datacenter][rack].push(node);
return acc;
}, {});

return (
<>
<div
className="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h2 className="h2">Node List</h2>
</div>

<div
className={`-flex justify-content-between flex-wrap flex-md-nowrap align-items-center alert ${availableNodeSize <= 0 || availableNodeSize === totalNodeSize ? 'alert-primary' : 'alert-danger'}`}>
Available nodes: {availableNodeSize}/{totalNodeSize}
</div>

<Spinner loading={nodeLoading}>
<div className="table-responsive small">
{Object.keys(nodesByDcAndRack).map((datacenter) => (
<div key={datacenter} className="mb-5">
<h3 className="mb-3 border-bottom">Datacenter: {datacenter}</h3>
{Object.keys(nodesByDcAndRack[datacenter]).map((rack) => (
<div key={rack} className="mb-4">
<h5 className="mb-2">{rack}</h5>
<table className="table table-striped table-sm">
<thead>
<tr>
<th className="text-center" scope="col">ID</th>
<th className="text-center" scope="col">Node State</th>
<th className="text-center" scope="col">Host IP</th>
<th className="text-center" scope="col">DC</th>
<th className="text-center" scope="col">Rack</th>
<th className="text-center" scope="col">Cassandra Version</th>
<th className="text-center" scope="col">Up-Time</th>
</tr>
</thead>
<tbody>
{nodesByDcAndRack[datacenter][rack].map((node) => (
<tr key={node.nodeId} className={node.nodeState !== 'UP' ? 'table-danger' : ''}>
<td className="text-center">{node.nodeId}</td>
<td className="text-center">{node.nodeState}</td>
<td className="text-center">{node.hostIp}</td>
<td className="text-center">{node.datacenter}</td>
<td className="text-center">{node.rack}</td>
<td className="text-center">{node.cassandraVersion}</td>
<td className="text-center">{DateUtils.yyyyMMDDHHmmss(node.upSinceMillis)}</td>
</tr>
))}
</tbody>
</table>
</div>
))}
</div>
))}
</div>
</Spinner>
</>
)
}

export default NodesHome;
7 changes: 7 additions & 0 deletions cadio-web/src/main/webapp/src/utils/timeUtils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import moment from "moment/moment";

export const DateUtils = {
yyyyMMDDHHmmss: (timestamp) => {
return moment(new Date(timestamp)).format('YYYY-MM-DD HH:mm:ss')
}
};

0 comments on commit 9707ec8

Please sign in to comment.