Skip to content

Commit f0e7a20

Browse files
committed
Add MithrilStakeDistributions to explorer
Snapshots list is now inside a tab, alongside it is the new mithrilStakeDistributions list.
1 parent 91fdec2 commit f0e7a20

File tree

4 files changed

+109
-9
lines changed

4 files changed

+109
-9
lines changed
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import React, {useEffect, useState} from 'react';
2+
import {Badge, Button, Card, Col, Container, ListGroup, Row, Stack} from "react-bootstrap";
3+
import CertificateModal from '../../CertificateModal';
4+
import RawJsonButton from "../../RawJsonButton";
5+
import {useSelector} from "react-redux";
6+
7+
export default function MithrilStakeDistributionsList(props) {
8+
const [mithrilStakeDistributions, setMithrilStakeDistributions] = useState([]);
9+
const [selectedCertificateHash, setSelectedCertificateHash] = useState(undefined);
10+
const aggregator = useSelector((state) => state.settings.selectedAggregator);
11+
const autoUpdate = useSelector((state) => state.settings.autoUpdate);
12+
const updateInterval = useSelector((state) => state.settings.updateInterval);
13+
14+
useEffect(() => {
15+
if (!autoUpdate) {
16+
return;
17+
}
18+
19+
let fetchMithrilStakeDistribution = () => {
20+
fetch(`${aggregator}/artifact/mithril-stake-distributions`)
21+
.then(response => response.json())
22+
.then(data => setMithrilStakeDistributions(data))
23+
.catch(error => {
24+
setMithrilStakeDistributions([]);
25+
console.error("Fetch mithrilStakeDistributions error:", error);
26+
});
27+
};
28+
29+
// Fetch them once without waiting
30+
fetchMithrilStakeDistribution();
31+
32+
const interval = setInterval(fetchMithrilStakeDistribution, updateInterval);
33+
return () => clearInterval(interval);
34+
}, [aggregator, updateInterval, autoUpdate]);
35+
36+
function handleCertificateHashChange(hash) {
37+
setSelectedCertificateHash(hash);
38+
}
39+
40+
function showCertificate(hash) {
41+
setSelectedCertificateHash(hash);
42+
}
43+
44+
return (
45+
<>
46+
<CertificateModal
47+
aggregator={aggregator}
48+
hash={selectedCertificateHash}
49+
onHashChange={handleCertificateHashChange}/>
50+
51+
<div className={props.className}>
52+
<h2>Mithril Stake Distribution <RawJsonButton href={`${aggregator}/artifact/mithril-stake-distributions`} variant="outline-light" size="sm"/></h2>
53+
{Object.entries(mithrilStakeDistributions).length === 0
54+
? <p>No snapshot available</p>
55+
:
56+
<Container fluid>
57+
<Row xs={1} md={2} lg={3} xl={4}>
58+
{mithrilStakeDistributions.map((mithrilStakeDistribution, index) =>
59+
<Col key={mithrilStakeDistribution.hash} className="mb-2">
60+
<Card border={index === 0 ? "primary" : ""}>
61+
<Card.Body>
62+
<Card.Title>{mithrilStakeDistribution.hash}</Card.Title>
63+
<ListGroup variant="flush" className="data-list-group">
64+
<ListGroup.Item>Epoch: {mithrilStakeDistribution.epoch}</ListGroup.Item>
65+
<ListGroup.Item>Certificate hash: <br/>
66+
{mithrilStakeDistribution.certificate_hash}{' '}
67+
<Button size="sm" onClick={() => showCertificate(mithrilStakeDistribution.certificate_hash)}>Show</Button>
68+
</ListGroup.Item>
69+
</ListGroup>
70+
</Card.Body>
71+
<Card.Footer>
72+
<Stack direction="horizontal" gap={1}>
73+
{index === 0 &&
74+
<><Badge bg="primary">Latest</Badge>{' '}</>
75+
}
76+
77+
<RawJsonButton href={`${aggregator}/artifact/mithril-stake-distribution/${mithrilStakeDistribution.hash}`} size="sm"
78+
className="ms-auto"/>
79+
</Stack>
80+
</Card.Footer>
81+
</Card>
82+
</Col>
83+
)}
84+
</Row>
85+
</Container>
86+
}
87+
</div>
88+
</>
89+
);
90+
}

mithril-explorer/components/SnapshotsList/index.js renamed to mithril-explorer/components/Artifacts/SnapshotsList/index.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React, {useEffect, useState} from 'react';
22
import {Badge, Button, Card, Col, Container, ListGroup, Row, Stack} from "react-bootstrap";
3-
import CertificateModal from '../CertificateModal';
4-
import RawJsonButton from "../RawJsonButton";
3+
import CertificateModal from '../../CertificateModal';
4+
import RawJsonButton from "../../RawJsonButton";
55
import {useSelector} from "react-redux";
66

77
/*
@@ -32,6 +32,8 @@ export default function SnapshotsList(props) {
3232
}
3333

3434
let fetchSnapshots = () => {
35+
// todo: update this to the new route (`${aggregator}/artifact/snapshots`) when all of our aggregators are updated
36+
// also update both <RawJsonButton> href below.
3537
fetch(`${aggregator}/snapshots`)
3638
.then(response => response.json())
3739
.then(data => setSnapshots(data))

mithril-explorer/components/RawJsonButton.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ export default function RawJsonButton(props) {
55
return (
66
<OverlayTrigger overlay={<Tooltip>Raw JSON</Tooltip>}>
77
<Button variant="outline-secondary" target="_blank" {...props}>
8-
<i class="bi bi-filetype-json" style={{color: 'black'}}></i>
8+
<i className="bi bi-filetype-json" style={{color: 'black'}}></i>
99
</Button>
1010
</OverlayTrigger>
1111
);

mithril-explorer/pages/index.js

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
import React, {useEffect} from 'react';
2-
import PendingCertificate from '../components/PendingCertificate';
3-
import SnapshotsList from '../components/SnapshotsList';
2+
import {useRouter} from "next/router";
3+
import {useSelector} from "react-redux";
44
import Head from "next/head";
55
import Image from "next/image";
6-
import {Col, Form, Row, Stack} from "react-bootstrap";
6+
import {Col, Form, Row, Stack, Tab, Tabs} from "react-bootstrap";
77
import styles from "../styles/Home.module.css";
88
import AggregatorSetter from "../components/AggregatorSetter";
9-
import {useRouter} from "next/router";
109
import EpochSettings from "../components/EpochSettings";
11-
import {useSelector} from "react-redux";
1210
import IntervalSetter from "../components/IntervalSetter";
11+
import PendingCertificate from '../components/PendingCertificate';
12+
import SnapshotsList from '../components/Artifacts/SnapshotsList';
13+
import MithrilStakeDistributionsList from "../components/Artifacts/MithrilStakeDistributionsList";
1314

1415
export default function Explorer() {
1516
const router = useRouter();
@@ -46,7 +47,14 @@ export default function Explorer() {
4647
<PendingCertificate/>
4748
</Col>
4849
</Row>
49-
<SnapshotsList/>
50+
<Tabs defaultActiveKey="snapshots">
51+
<Tab title="Snapshots" eventKey="snapshots">
52+
<SnapshotsList/>
53+
</Tab>
54+
<Tab title="Mithril Stake Distribution" eventKey="mithrilStakeDistribution">
55+
<MithrilStakeDistributionsList/>
56+
</Tab>
57+
</Tabs>
5058
</Stack>
5159
</main>
5260
</div>

0 commit comments

Comments
 (0)