mirror of
https://github.com/PluralKit/PluralKit.git
synced 2026-02-13 09:10:14 +00:00
refactor(dashboard): re-organize dashboard files
This commit is contained in:
parent
e0cde35b3d
commit
1b3f188997
41 changed files with 165 additions and 166 deletions
225
dashboard/src/routes/Status/status.svelte
Normal file
225
dashboard/src/routes/Status/status.svelte
Normal file
|
|
@ -0,0 +1,225 @@
|
|||
<script lang="ts">
|
||||
import { Container, Row, Col, Card, CardHeader, CardTitle, CardBody, Input, Button } from 'sveltestrap';
|
||||
import FaInfoCircle from 'svelte-icons/fa/FaInfoCircle.svelte'
|
||||
import ShardItem from '../../components/status/Shard.svelte';
|
||||
|
||||
import api from '../../api';
|
||||
|
||||
let message = "Loading...";
|
||||
let shards = [];
|
||||
let clusters = {};
|
||||
let pingAverage = "";
|
||||
|
||||
let foundShard = {
|
||||
id: 1,
|
||||
status: 1,
|
||||
ping:"",
|
||||
disconnection_count:0,
|
||||
last_connection:0,
|
||||
last_heartbeat:0,
|
||||
heartbeat_minutes_ago:0
|
||||
};
|
||||
foundShard = null;
|
||||
|
||||
let findShardInput = "";
|
||||
let valid = false;
|
||||
|
||||
const get = async () => {
|
||||
const pkdata = await api().private.meta.get();
|
||||
let data = pkdata.shards.sort((x, y) => (x.id > y.id) ? 1 : -1);
|
||||
let pings = 0;
|
||||
data = data.map(shard => {
|
||||
pings += shard.ping;
|
||||
shard.heartbeat_minutes_ago = heartbeatMinutesAgo(shard);
|
||||
shard.last_connection = new Date(Number(shard.last_connection) * 1000).toUTCString().match(/([0-9][0-9]:[0-9][0-9]:[0-9][0-9])/)?.shift()
|
||||
shard.last_heartbeat = new Date(Number(shard.last_heartbeat) * 1000).toUTCString().match(/([0-9][0-9]:[0-9][0-9]:[0-9][0-9])/)?.shift()
|
||||
return shard;
|
||||
});
|
||||
|
||||
if (data[0].cluster_id === 0) {
|
||||
let clusterData = {};
|
||||
data.forEach(shard => {
|
||||
if (clusterData[shard.cluster_id] === undefined) clusterData[shard.cluster_id] = [];
|
||||
clusterData[shard.cluster_id].push(shard);
|
||||
});
|
||||
clusters = clusterData;
|
||||
}
|
||||
|
||||
shards = data;
|
||||
pingAverage = Math.trunc(pings / shards.length).toString();
|
||||
|
||||
message = "";
|
||||
};
|
||||
|
||||
get();
|
||||
setTimeout(get, 30 * 1000);
|
||||
|
||||
// javascript wants everything to be BigInts
|
||||
const getShardID = (guild_id: string, num_shards: number) => guild_id == "" ? -1 : (BigInt(guild_id) >> BigInt(22)) % BigInt(num_shards);
|
||||
|
||||
let shardInfoMsg = "";
|
||||
|
||||
let shardInfoHandler = (_: Event) => {
|
||||
if (findShardInput == "" || !findShardInput) {
|
||||
valid = false;
|
||||
foundShard = null;
|
||||
shardInfoMsg = "";
|
||||
return;
|
||||
};
|
||||
var match = findShardInput.match(/https:\/\/(?:[\w]*\.)?discord(?:app)?\.com\/channels\/(\d+)\/\d+\/\d+/);
|
||||
if (match != null) {
|
||||
console.log("match", match)
|
||||
foundShard = shards[Number(getShardID(match[1], shards.length))];
|
||||
valid = true;
|
||||
shardInfoMsg = "";
|
||||
return;
|
||||
}
|
||||
try {
|
||||
var shard = getShardID(findShardInput, shards.length);
|
||||
if (shard == -1) {
|
||||
valid = false;
|
||||
foundShard == null;
|
||||
shardInfoMsg = "Invalid server ID";
|
||||
return;
|
||||
}
|
||||
foundShard = shards[Number(shard)];
|
||||
valid = true;
|
||||
shardInfoMsg = "";
|
||||
} catch(e) {
|
||||
valid = false;
|
||||
shardInfoMsg = "Invalid server ID";
|
||||
}
|
||||
};
|
||||
|
||||
function heartbeatMinutesAgo(shard) {
|
||||
// difference in milliseconds
|
||||
const msDifference = Math.abs((Number(new Date(Number(shard.last_heartbeat) * 1000)) - Date.now()));
|
||||
// convert to minutes
|
||||
const minuteDifference = msDifference / (60 * 1000);
|
||||
|
||||
return minuteDifference;
|
||||
}
|
||||
</script>
|
||||
|
||||
<Container>
|
||||
<Row>
|
||||
<Col class="mx-auto" xs={12} lg={11} xl={10}>
|
||||
<Card class="mb-4">
|
||||
<CardHeader>
|
||||
<CardTitle style="margin-top: 8px; outline: none;">
|
||||
<div class="icon d-inline-block">
|
||||
<FaInfoCircle />
|
||||
</div>
|
||||
Bot status
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardBody>
|
||||
<br>
|
||||
<noscript>Please enable JavaScript to view this page!</noscript>
|
||||
|
||||
<Row>
|
||||
<Col class="mb-2" xs={12} md={6} lg={4} >
|
||||
<span>{ shards.length } shards ({ shards.filter(x => x.status == "up").length } up)</span>
|
||||
</Col>
|
||||
<Col class="mb-2" xs={12} md={6} lg={4}>
|
||||
<span>Average latency: { pingAverage }ms</span>
|
||||
</Col>
|
||||
<Col class="mb-2" xs={12} md={6} lg={4}>
|
||||
<span>More statistics available at <a href="https://stats.pluralkit.me">https://stats.pluralkit.me</a></span>
|
||||
</Col>
|
||||
</Row>
|
||||
<hr/>
|
||||
<h3 style="font-size: 1.2rem;">Find my shard</h3>
|
||||
<p>Enter a server ID or a message link to find the shard currently assigned to your server</p>
|
||||
<label for="shardInput">Server ID or message link</label>
|
||||
<input id="shardInput" class="form form-control" bind:value={findShardInput} on:input={shardInfoHandler} />
|
||||
{#if shardInfoMsg || foundShard}
|
||||
<Card class="mt-4">
|
||||
<CardHeader>
|
||||
<CardTitle>
|
||||
{#if shardInfoMsg}
|
||||
{shardInfoMsg}
|
||||
{/if}
|
||||
{#if foundShard}
|
||||
Your shard is: Shard { foundShard.id }
|
||||
{/if}
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
|
||||
{#if valid}
|
||||
<CardBody>
|
||||
<span>Status: <b>{ foundShard.status }</b></span><br>
|
||||
<span>Latency: { foundShard.ping }ms</span><br>
|
||||
<span>Disconnection count: { foundShard.disconnection_count }</span><br>
|
||||
<span>Last connection: { foundShard.last_connection } UTC</span><br>
|
||||
<span>Last heartbeat: { foundShard.last_heartbeat } UTC</span><br>
|
||||
</CardBody>
|
||||
{/if}
|
||||
</Card>
|
||||
{/if}
|
||||
</CardBody>
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
{#if Object.keys(clusters).length == 0 && shards.length > 0}
|
||||
<Row>
|
||||
<Col class="mx-auto" xs={12} lg={11} xl={10}>
|
||||
<Card class="mb-4">
|
||||
<CardBody>
|
||||
<span>{ message }</span>
|
||||
{#each shards as shard}
|
||||
<ShardItem shard={shard} />
|
||||
{/each}
|
||||
</CardBody>
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
{/if}
|
||||
<Row>
|
||||
<Col class="mx-auto" xs={12} lg={11} xl={10}>
|
||||
<div class="cluster-grid">
|
||||
{#each Object.keys(clusters) as key}
|
||||
<div class="cluster-card">
|
||||
<span class="cluster-text">Cluster {key}  </span>
|
||||
</div>
|
||||
<div class="cluster-shards">
|
||||
{#each clusters[key] as shard}
|
||||
<ShardItem shard={shard} />
|
||||
{/each}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
|
||||
<style>
|
||||
.cluster-shards {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.cluster-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 100%;
|
||||
gap: 0.5em;
|
||||
}
|
||||
|
||||
@media (min-width: 576px) {
|
||||
.cluster-card {
|
||||
text-align: right;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.cluster-text {
|
||||
line-height: 3em;
|
||||
}
|
||||
|
||||
.cluster-grid {
|
||||
grid-template-columns: max-content 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Loading…
Add table
Add a link
Reference in a new issue