dyno-bot/Dyno-web-member-dash/react/status/Status.jsx
2020-09-12 19:08:48 +01:00

138 lines
5.4 KiB
JavaScript

import React from 'react';
import Server from './Server.jsx';
import axios from 'axios';
import { Circle } from 'rc-progress';
export default class Status extends React.Component {
constructor(props) {
super(props);
this.state = {
fetching: true,
statuses: {},
error: '',
serverId: '',
foundInfo: { shard: '', cluster: '' },
foundInfoError: '',
percentage: 0,
onlineOffline: '',
};
}
async componentDidMount() {
this.getStatus();
}
getStatus = async () => {
try {
this.setState({ fetching: true });
let statusRequest = await axios.get('/api/status');
const totalShards = 864;
let connectedShards = 0;
for (let server in statusRequest.data) {
statusRequest.data[server].forEach(function(cluster) {
let connectedCount = 0;
if (cluster.result) connectedCount += cluster.result.connectedCount;
connectedShards += connectedCount || 0;
});
}
let percentage = (connectedShards / totalShards) * 100;
percentage = percentage.toFixed(0);
this.setState({
statuses: statusRequest.data,
fetching: false,
percentage,
onlineOffline: `${connectedShards} / ${totalShards}`
});
this.findInfo();
} catch (e) {
this.setState({ error: 'Failed to load status, trying again in 30 seconds.', fetching: false });
}
setTimeout(this.getStatus, 30 * 1000);
}
onServerIDChange = (serverId) => {
this.setState({ serverId: serverId.target.value });
}
findInfo = () => {
this.setState({ foundInfo: { shard: '', cluster: '' }, foundInfoError: ''})
if (this.state.serverId === '') return;
let serverId = this.state.serverId.match(/(\d{15,})/);
const totalShards = 864;
if (serverId === null || serverId[1] === undefined) {
this.setState({ foundInfo: { shard: '', cluster: '' }, foundInfoError: 'Invalid Server ID'});
return;
}
let shard = ~~((serverId[1]*1 / 4194304) % totalShards);
let cluster = 0;
Object.keys(this.state.statuses).forEach(server => {
if (cluster !== 0) { return; }
let search = this.state.statuses[server].find(i => (i.result && i.result.shards.includes(shard)) || (i.guessedShards && i.guessedShards.includes(shard)));
if (search !== undefined) {
cluster = server[0] + search.id;
return;
}
});
if (cluster === 0) {
cluster = 'unknown';
}
this.setState({ foundInfo: { shard, cluster }, foundInfoError: ''})
}
render() {
let servers;
let foundInfo;
let hasLoaded = !!Object.keys(this.state.statuses).length;
let percent = this.state.percentage;
let shards = this.state.onlineOffline;
if (this.state.foundInfoError !== '') {
foundInfo = (<p>{this.state.foundInfoError}</p>);
}
if (this.state.foundInfo.shard !== '') {
foundInfo = (<p>This server is on shard #{this.state.foundInfo.shard} which is on cluster {this.state.foundInfo.cluster}. <strong>The cluster has been highlighted blue, hover over it to see if there's any problems with it.</strong></p>);
}
if (this.state.error === '') {
servers = Object.keys(this.state.statuses).map(server => <Server key={server} server={server} foundInfo={this.state.foundInfo} clusters={this.state.statuses[server]}/>);
}
let fetching = (<p>This page auto-updates every 30 seconds.</p>);
if (this.state.fetching) {
fetching = (<p>Getting status information, please wait...</p>);
}
return (<div>
<div className="status-wrapper">
<div className="container">{fetching}</div>
{hasLoaded ? (<div className="server-finder container">
<label className="label">Enter your Server ID to find your shard and cluster information.</label>
<div className="text-form">
<p className="control has-addons">
<input className="input" type="text" onChange={this.onServerIDChange} />
<a className="button is-info" onClick={this.findInfo}>Find info</a>
</p>
</div>
{foundInfo}
</div>) : ''}
<div className='container'><p>{this.state.error}</p></div>
<div className='legend container'>
<div className='cluster-grid'>
<p>Legend:</p>
<div className='cluster bg-success'>Operational</div>
<div className='cluster bg-warning'>Partial Outage</div>
<div className='cluster bg-error'>Major Outage</div>
<div className='cluster bg-ipc-timeout'>IPC Timeout</div>
</div>
<p><strong>Hover over a cluster for more information.</strong></p>
</div>
<div className='container percentage'>
<Circle className='percent-circle' percent={percent} trailWidth="10" trailColor="#ed6c63" strokeWidth="10" strokeColor="#009b54"/>
<ul className='up-info'>
<li>{percent}% online</li>
<li>{shards} shards connected</li>
</ul>
</div>
<div className="servers">
{servers}
</div>
</div></div>);
}
}