Big layout update

This commit is contained in:
Marco van Dijk 2022-03-08 17:02:15 +01:00
parent 1db2a934a2
commit fcdc274014
13 changed files with 489 additions and 298 deletions

View File

@ -7,6 +7,9 @@ const Block = (obj) => {
const [thisDate, thisTime] = dateObj.toISOString().split('T'); const [thisDate, thisTime] = dateObj.toISOString().split('T');
return ( return (
<div className="rowAlignLeft" style={{ width: '100%', marginTop: '1em' }}> <div className="rowAlignLeft" style={{ width: '100%', marginTop: '1em' }}>
<a className="selectOrch" href={obj.url}>
<img alt="" src="arb.svg" width="30em" height="30em" />
</a>
<span className="rowAlignRight elipsText"> <span className="rowAlignRight elipsText">
<a className="selectOrch" href={"https://arbiscan.io/block/" + obj.block}> <a className="selectOrch" href={"https://arbiscan.io/block/" + obj.block}>
🔗{obj.block} 🔗{obj.block}

View File

@ -3,9 +3,9 @@ import ReactTooltip from "react-tooltip";
const Address = (obj) => { const Address = (obj) => {
return ( return (
<div className="rowAlignLeft" style={{ width: 'unset' }}> <div className="rowAlignLeft" style={{ width: 'unset', margin: 0 }}>
<a className="selectOrchLight" href={"https://explorer.livepeer.org/accounts/" + obj.address} data-tip data-for={obj.seed} > <a className="selectOrchLight" href={"https://explorer.livepeer.org/accounts/" + obj.address} data-tip data-for={obj.seed} >
<div className="rowAlignLeft" style={{ width: 'unset' }}> <div className="rowAlignLeft" style={{ width: 'unset', margin: 0 }}>
<img alt="" src="livepeer.png" width="20" height="20" /> <img alt="" src="livepeer.png" width="20" height="20" />
<span className="elipsText">{obj.address}</span> <span className="elipsText">{obj.address}</span>
</div> </div>

View File

@ -0,0 +1,47 @@
import React from "react";
import ScrollContainer from "react-indiana-drag-scroll";
import Address from "./OrchAddressViewer";
const OrchDelegatorViewer = (obj) => {
let delegators = obj.delegators;
if (delegators && delegators.length) {
return (
<div className="row" style={{ width: 'unset', marginBottom: '1em', marginTop: '1em' }}>
<div className="strokeSmollLeft" style={{ display: "flex" }}>
<div className="row" style={{ margin: '0' }}>
<h3 style={{ padding: 0, margin: 0 }}>{delegators.length} Current Delegators</h3>
</div>
<div className="content-wrapper">
<ScrollContainer className="overflow-container" hideScrollbars={false}>
<div className="overflow-content" style={{ cursor: 'grab', padding: 0, maxHeight: '300px' }}>
{
delegators.map((delObj, idx) => {
return (
<div className={obj.forceVertical ? "flexContainer forceWrap" : "flexContainer"} key={"delegator" + idx} style={{ margin: 0, textAlign: 'center',alignItems: 'center', justifyContent:'center' }}>
<Address address={delObj.id} seed={"delegator" + idx + delObj.id} />
<div className="rowAlignRight" style={{ margin: 0 }}>
<p className="darkText">{parseFloat(delObj.bondedAmount).toFixed(2)} LPT since round {delObj.startRound}</p>
</div>
</div>
)
})
}
</div>
</ScrollContainer>
</div>
</div>
</div>
)
}
return (
<div className="row" style={{ width: 'unset', marginBottom: '1em', marginTop: '1em' }}>
<div className="strokeSmollLeft" style={{ display: "flex" }}>
<div className="row" style={{ margin: '0' }}>
<h3 style={{ padding: 0, margin: 0 }}>The selected Orchestrator has no Delegators</h3>
</div>
</div>
</div>
)
}
export default OrchDelegatorViewer;

115
src/OrchInfoViewer.js Normal file
View File

@ -0,0 +1,115 @@
import React from "react";
import Stat from "./statViewer";
import ReactTooltip from "react-tooltip";
import Address from "./OrchAddressViewer";
function updateClipboard(newClip) {
navigator.clipboard.writeText(newClip).then(
() => {
console.log("Copied!");
},
() => {
console.log("Copy failed!");
}
);
}
function copyLink(addr) {
navigator.permissions
.query({ name: "clipboard-write" })
.then((result) => {
if (result.state === "granted" || result.state === "prompt") {
updateClipboard(addr);
}
});
}
const OrchInfoViewer = (obj) => {
let rewardCut = 0;
let feeCut = 0;
let totalStake = 0;
let totalVolumeETH = 0;
let totalVolumeUSD = 0;
let selfStake = 0;
let selfStakeRatio = 0;
let thisUrl = "";
let thisID = "";
if (obj.totalStake && obj.totalStake > 0) {
if (obj.rewardCut) {
rewardCut = (obj.rewardCut / 10000).toFixed(2);
}
if (obj.feeShare) {
feeCut = (100 - (obj.feeShare / 10000)).toFixed(2);
}
if (obj.totalStake) {
totalStake = parseFloat(obj.totalStake).toFixed(2);
}
if (obj.totalVolumeETH) {
totalVolumeETH = parseFloat(obj.totalVolumeETH * 1).toFixed(4);
}
if (obj.totalVolumeUSD) {
totalVolumeUSD = parseFloat(obj.totalVolumeUSD * 1).toFixed(2);
}
if (obj.delegator) {
selfStake = parseFloat(obj.delegator.bondedAmount);
selfStakeRatio = ((selfStake / totalStake) * 100).toFixed(2);
selfStake = selfStake.toFixed(2);
thisID = obj.delegator.id;
thisUrl = "https://explorer.livepeer.org/accounts/" + thisID;
}
let shareUrl;
if (obj.rootOnly) {
shareUrl = window.location.href;
} else {
let thisFullPath = window.location.href;
if (thisFullPath.lastIndexOf("?") > -1) {
thisFullPath = thisFullPath.substring(0, thisFullPath.lastIndexOf("?"));
}
shareUrl = thisFullPath + "?orchAddr=" + thisID;
}
return (
<div className="row" style={{ width: 'unset', }}>
<div className="strokeSmollLeft" style={{ display: "flex" }}>
<div style={{ flexDirection: 'row', display: "flex", borderBottom: '2px solid rgba(15,15,15,0.05)', marginTop: '1em' }}>
<a href={thisUrl}>
<h3 style={{ padding: 0, margin: 0 }}>Orchestrator Info</h3>
<Address address={thisID} />
</a>
</div>
<div className="row" style={{ margin: 0 }}>
<Stat header={"Earned Fees"} content1={totalVolumeETH + " Eth"} content2={"$" + totalVolumeUSD} />
</div>
<div className="row" style={{ margin: 0 }}>
<Stat header={"Commission"} title1={"Reward"} content1={rewardCut + "%"} title2={"Fee"} content2={feeCut + "%"} />
</div>
<div className="row" style={{ margin: 0 }}>
<Stat header={"Stake"} title1={"Total"} content1={totalStake + " LPT"} title2={"Self"} content2={selfStake + " LPT (" + selfStakeRatio + ")%"} />
</div>
<div className="strokeSmollLeft" style={{ display: "flex" }}>
<button style={{ marginBottom: '1em' }} className="selectOrchLight" data-tip data-for="registerTip" onClick={() => {
copyLink(shareUrl);
}}>
<img alt="" src="clipboard.svg" width="20em" height="20em" />
</button>
<ReactTooltip id="registerTip" place="top" effect="solid">
Copy to clipboard
</ReactTooltip>
</div>
</div>
</div>
)
}
return (
<div className="row" style={{ width: 'unset', marginBottom: '1em', marginTop: '1em' }}>
<div className="strokeSmollLeft" style={{ display: "flex" }}>
<div className="row" style={{ margin: '0' }}>
<h3 style={{ padding: 0, margin: 0 }}>The selected Orchestrator is currently inactive</h3>
</div>
</div>
</div>
)
}
export default OrchInfoViewer;

View File

@ -17,6 +17,7 @@ export const RECEIVE_BLOCKCHAIN_DATA = "RECEIVE_BLOCKCHAIN_DATA";
export const RECEIVE_EVENTS = "RECEIVE_EVENTS"; export const RECEIVE_EVENTS = "RECEIVE_EVENTS";
export const RECEIVE_CURRENT_ORCHESTRATOR = "RECEIVE_CURRENT_ORCHESTRATOR"; export const RECEIVE_CURRENT_ORCHESTRATOR = "RECEIVE_CURRENT_ORCHESTRATOR";
export const RECEIVE_ORCHESTRATOR = "RECEIVE_ORCHESTRATOR"; export const RECEIVE_ORCHESTRATOR = "RECEIVE_ORCHESTRATOR";
export const CLEAR_ORCHESTRATOR = "CLEAR_ORCHESTRATOR";
const setQuotes = message => ({ const setQuotes = message => ({
type: RECEIVE_QUOTES, message type: RECEIVE_QUOTES, message
@ -33,6 +34,9 @@ const setCurrentOrchestratorInfo = message => ({
const setOrchestratorInfo = message => ({ const setOrchestratorInfo = message => ({
type: RECEIVE_ORCHESTRATOR, message type: RECEIVE_ORCHESTRATOR, message
}); });
const clearOrchestratorInfo = () => ({
type: CLEAR_ORCHESTRATOR
})
export const getQuotes = () => async dispatch => { export const getQuotes = () => async dispatch => {
const response = await apiUtil.getQuotes(); const response = await apiUtil.getQuotes();
@ -127,7 +131,7 @@ export const getEvents = () => async dispatch => {
else if (eventContainsRebond) { else if (eventContainsRebond) {
eventType = "Stake"; eventType = "Stake";
eventColour = stakeColour; eventColour = stakeColour;
eventDescription = "increased their stake to " + tmpAmount.toFixed(2) + " LPT at"; eventDescription = "is now staking " + tmpAmount.toFixed(2) + " LPT";
} }
// Fill description of Stake Event if it wasn't set yet // Fill description of Stake Event if it wasn't set yet
@ -136,7 +140,7 @@ export const getEvents = () => async dispatch => {
eventDescription = "staked " + tmpAmount.toFixed(2) + " LPT"; eventDescription = "staked " + tmpAmount.toFixed(2) + " LPT";
} else if (eventFrom === eventTo) { } else if (eventFrom === eventTo) {
eventFrom = ""; eventFrom = "";
eventDescription = "increased their stake to " + tmpAmount.toFixed(2) + " LPT"; eventDescription = "is now staking " + tmpAmount.toFixed(2) + " LPT";
} else { } else {
eventDescription = "moved a " + tmpAmount.toFixed(2) + " LPT stake"; eventDescription = "moved a " + tmpAmount.toFixed(2) + " LPT stake";
} }
@ -370,3 +374,7 @@ export const getOrchestratorInfo = (orchAddr) => async dispatch => {
} }
return dispatch(receiveErrors(data)); return dispatch(receiveErrors(data));
}; };
export const clearOrchestrator = () => async dispatch => {
return dispatch(clearOrchestratorInfo({}));
};

View File

@ -10,7 +10,7 @@ import Block from "./BlockViewer";
const EventButton = (obj) => { const EventButton = (obj) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
let eventArrow;
let eventTo; let eventTo;
let eventFrom; let eventFrom;
let eventCaller; let eventCaller;
@ -21,13 +21,14 @@ const EventButton = (obj) => {
if (obj.eventObj.eventTo === "0x0000000000000000000000000000000000000000") { if (obj.eventObj.eventTo === "0x0000000000000000000000000000000000000000") {
obj.eventObj.eventTo = ""; obj.eventObj.eventTo = "";
} }
if (obj.eventObj.eventTo !== "" || obj.eventObj.eventFrom !== "") {
eventArrow = <p style={{marginRight: 0}}></p>;
}
if (obj.eventObj.eventTo || obj.eventObj.eventFrom || obj.eventObj.eventCaller) { if (obj.eventObj.eventTo || obj.eventObj.eventFrom || obj.eventObj.eventCaller) {
if (obj.eventObj.eventTo) { if (obj.eventObj.eventTo) {
eventTo = eventTo =
<div className="rowAlignRight" style={{ width: 'unset', marginLeft: 0 }}> <div className="rowAlignLeft" style={{ width: '100%', margin: 0, marginLeft: '0.5em' }}>
<p>To</p>
<a className="selectOrch" href={"https://explorer.livepeer.org/accounts/" + obj.eventObj.eventTo}>
<img alt="" src="livepeer.png" width="20em" height="20em" style={{ margin: 0 }} />
</a>
<button className="selectOrch" style={{ margin: 0, padding: '0.5em' }} onClick={() => { obj.setSearchTerm(obj.eventObj.eventTo) }} > <button className="selectOrch" style={{ margin: 0, padding: '0.5em' }} onClick={() => { obj.setSearchTerm(obj.eventObj.eventTo) }} >
<span className="elipsText">🔎</span> <span className="elipsText">🔎</span>
</button> </button>
@ -38,7 +39,11 @@ const EventButton = (obj) => {
} }
if (obj.eventObj.eventFrom) { if (obj.eventObj.eventFrom) {
eventFrom = eventFrom =
<div className="rowAlignRight" style={{ width: 'unset', margin: 0 }}> <div className="rowAlignLeft" style={{ width: '100%', margin: 0, marginLeft: '0.5em' }}>
<p>From</p>
<a className="selectOrch" href={"https://explorer.livepeer.org/accounts/" + obj.eventObj.eventFrom}>
<img alt="" src="livepeer.png" width="20em" height="20em" style={{ margin: 0 }} />
</a>
<button className="selectOrch" style={{ margin: 0, padding: '0.5em' }} onClick={() => { obj.setSearchTerm(obj.eventObj.eventFrom) }} > <button className="selectOrch" style={{ margin: 0, padding: '0.5em' }} onClick={() => { obj.setSearchTerm(obj.eventObj.eventFrom) }} >
<span className="elipsText">🔎</span> <span className="elipsText">🔎</span>
</button> </button>
@ -49,7 +54,11 @@ const EventButton = (obj) => {
} }
if (obj.eventObj.eventCaller) { if (obj.eventObj.eventCaller) {
eventCaller = eventCaller =
<div className="rowAlignLeft" style={{ width: 'unset', margin: 0 }}> <div className="rowAlignLeft" style={{ width: '100%', margin: 0, marginLeft: '0.5em' }}>
<p>Caller</p>
<a className="selectOrch" href={"https://explorer.livepeer.org/accounts/" + obj.eventObj.eventCaller}>
<img alt="" src="livepeer.png" width="20em" height="20em" style={{ margin: 0 }} />
</a>
<button className="selectOrch" style={{ margin: 0, padding: '0.5em' }} onClick={() => { obj.setSearchTerm(obj.eventObj.eventCaller) }} > <button className="selectOrch" style={{ margin: 0, padding: '0.5em' }} onClick={() => { obj.setSearchTerm(obj.eventObj.eventCaller) }} >
<span className="elipsText">🔎</span> <span className="elipsText">🔎</span>
</button> </button>
@ -58,40 +67,29 @@ const EventButton = (obj) => {
</button> </button>
</div> </div>
} }
eventRightAddr = <div className="rowAlignRight" style={{ width: 'unset', padding: 0, margin: 0 }}> eventRightAddr = <div className="strokeSmollLeft" style={{ width: 'unset', padding: 0, margin: 0 }}>
{eventFrom}
{eventArrow}
{eventTo}
</div> </div>
} }
let blockNumber; let blockNumber;
if (obj.isFirstOfBlock) { if (obj.isFirstOfBlock) {
blockNumber = <Block block={obj.isFirstOfBlock} time={obj.time} /> blockNumber = <Block block={obj.isFirstOfBlock} time={obj.time} url={obj.eventObj.transactionUrl} />
} }
return ( return (
<div className="stroke" style={{ width: '100%', padding: 0, margin: 0 }}> <div className="stroke" style={{ width: '100%', padding: 0, margin: 0 }}>
{blockNumber} {blockNumber}
<div className="rowAlignLeft" style={{ backgroundColor: obj.eventObj.eventColour, borderRadius: "1.2em", width: '100%' }}> <div className="rowAlignLeft" style={{ borderRadius: "1.2em", backgroundColor: obj.eventObj.eventColour, padding: 0, margin: 0 }}>
<div className="rowAlignLeft" style={{ flex: '1', width: 'unset' }}> <div className="strokeSmollLeft">
<a className="selectOrch" href={obj.eventObj.transactionUrl}> {eventCaller}
<img alt="" src="arb.svg" width="30" height="30" /> <p className="rowAlignLeft withWrap" style={{ width: '100%' }}>
</a> 💬 {obj.eventObj.eventDescription}
<a className="selectOrch" href={"https://explorer.livepeer.org/accounts/" + obj.eventObj.eventCaller}> </p>
<img alt="" src="livepeer.png" width="30" height="30" /> {eventFrom}
</a> {eventTo}
<div className="rowAlignLeft" style={{ flex: '1', width: '100%', padding: 0, margin: 0 }}>
{eventCaller}
</div>
</div> </div>
<div className="rowAlignLeft" style={{ flex: '2', width: 'unset', padding: 0, margin: 0 }}> </div>
<span className="rowAlignLeft elipsText">
{obj.eventObj.eventDescription}
</span>
{eventRightAddr}
</div>
</div >
</div> </div>
) )
} }

View File

@ -17,7 +17,6 @@ const defaultMaxShown = 100;
const defaultIncrementMaxShown = 100; const defaultIncrementMaxShown = 100;
const EventViewer = (obj) => { const EventViewer = (obj) => {
const [searchTerm, setSearchTerm] = useState(obj.prefill || "");
const [amountFilter, setAmountFilter] = useState("0"); const [amountFilter, setAmountFilter] = useState("0");
const [maxAmount, setMaxAmount] = useState(defaultMaxShown); const [maxAmount, setMaxAmount] = useState(defaultMaxShown);
const [filterActivated, setFilterActivated] = useState(true); const [filterActivated, setFilterActivated] = useState(true);
@ -49,35 +48,29 @@ const EventViewer = (obj) => {
let prevBlock = 0; let prevBlock = 0;
let showMoreBlock; let showMoreBlock;
if (maxAmount < limitShown) { if (maxAmount < limitShown) {
showMoreBlock = <div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}> showMoreBlock = <button className={"nonHomeButton"} style={{ backgroundColor: greyColour, margin: 0, padding: '0', width: '5em' }} onClick={() => {
<h3></h3> setMaxAmount(maxAmount + defaultIncrementMaxShown);
<button className={"nonHomeButton"} style={{ backgroundColor: greyColour, margin: 0, padding: '0', width: '5em' }} onClick={() => { }}>
setMaxAmount(maxAmount + defaultIncrementMaxShown); <h3>Show more</h3>
}}> </button>
<h3>Show more</h3>
</button>
</div>
} }
let showLessBlock; let showLessBlock;
if (defaultMaxShown < maxAmount) { if (defaultMaxShown < maxAmount) {
showLessBlock = <div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}> showLessBlock = <button className={"nonHomeButton"} style={{ backgroundColor: greyColour, margin: 0, padding: '0', width: '5em' }} onClick={() => {
<h3></h3> setMaxAmount(defaultMaxShown);
<button className={"nonHomeButton"} style={{ backgroundColor: greyColour, margin: 0, padding: '0', width: '5em' }} onClick={() => { }}>
setMaxAmount(defaultMaxShown); <h3>Show {defaultMaxShown}</h3>
}}> </button>
<h3>Show {defaultMaxShown}</h3>
</button>
</div>
} else { } else {
showLessBlock = <div className="strokeSmollLeft" style={{ margin: 0, padding: 0, width: '5em' }}></div> showLessBlock = <div className="strokeSmollLeft" style={{ margin: 0, padding: 0, width: '5em' }}></div>
} }
let searchTermText; let searchTermText;
if (searchTerm !== "") { if (obj.searchTerm !== "") {
if (searchTerm.length > 15) { if (obj.searchTerm.length > 15) {
searchTermText = <h3>Only showing addresses containing {searchTerm.substring(0, 15)}...</h3> searchTermText = <h3>Only showing addresses containing {obj.searchTerm.substring(0, 15)}...</h3>
} else { } else {
searchTermText = <h3>Only showing addresses containing {searchTerm}</h3> searchTermText = <h3>Only showing addresses containing {obj.searchTerm}</h3>
} }
} else { } else {
searchTermText = <h3>Filter by Orchestrator address</h3> searchTermText = <h3>Filter by Orchestrator address</h3>
@ -95,11 +88,11 @@ const EventViewer = (obj) => {
} }
} }
// Filter name on from, to, caller // Filter name on from, to, caller
if (searchTerm !== "") { if (obj.searchTerm !== "") {
let isFiltered = true; let isFiltered = true;
if (eventObj.eventCaller.toLowerCase().includes(searchTerm.toLowerCase())) isFiltered = false; if (eventObj.eventCaller.toLowerCase().includes(obj.searchTerm.toLowerCase())) isFiltered = false;
if (eventObj.eventFrom.toLowerCase().includes(searchTerm.toLowerCase())) isFiltered = false; if (eventObj.eventFrom.toLowerCase().includes(obj.searchTerm.toLowerCase())) isFiltered = false;
if (eventObj.eventTo.toLowerCase().includes(searchTerm.toLowerCase())) isFiltered = false; if (eventObj.eventTo.toLowerCase().includes(obj.searchTerm.toLowerCase())) isFiltered = false;
if (isFiltered) continue; if (isFiltered) continue;
} }
// Filter Events on filter buttons // Filter Events on filter buttons
@ -164,7 +157,7 @@ const EventViewer = (obj) => {
eventList.push(<EventButton eventList.push(<EventButton
key={eventObj.transactionHash + unfiltered} key={eventObj.transactionHash + unfiltered}
eventObj={eventObj} eventObj={eventObj}
setSearchTerm={setSearchTerm} setSearchTerm={obj.setSearchTerm}
/>); />);
} else { } else {
prevBlock = eventObj.transactionBlock; prevBlock = eventObj.transactionBlock;
@ -173,81 +166,69 @@ const EventViewer = (obj) => {
eventObj={eventObj} eventObj={eventObj}
isFirstOfBlock={prevBlock} isFirstOfBlock={prevBlock}
time={eventObj.transactionTime} time={eventObj.transactionTime}
setSearchTerm={setSearchTerm} setSearchTerm={obj.setSearchTerm}
/>); />);
} }
} }
} }
return ( let filterBit;
<div className="stroke roundedOpaque" style={{ padding: 0, margin: 0, marginTop: '2em', position: 'absolute', bottom: 0, top: '300px', overflowY: 'auto', overflowX: 'hidden', width: 'unset' }}> if (obj.showFilter) {
<div className="row showNeverOnMobile"> filterBit = <div className="row roundedOpaque" style={{ borderTopLeftRadius: 0, borderTopRightRadius: 0, borderBottomLeftRadius: 0, margin: 0 }}>
<div className="row"> <div className="strokeSmollLeft" style={{ margin: 0, padding: 0, flex: 1 }}>
{showLessBlock} <div className="stroke" style={{ margin: "0", padding: 0 }}>
<div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}> <div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}>
<h3>Showing max {maxAmount} results</h3> <h3>Showing max {maxAmount} results</h3>
</div> </div>
{showMoreBlock} <div className="row" style={{ margin: 0, padding: 0 }}>
</div> <div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}>
<div className="row"> {showLessBlock}
<div className="stroke" style={{ margin: "0", padding: 0 }}> </div>
{searchTermText} <div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}>
<input className="searchField" style={{ width: '100%' }} {showMoreBlock}
value={searchTerm} </div>
onChange={(evt) => setSearchTerm(evt.target.value)}
placeholder='Filter by Orchestrator address'
type="text"
/>
</div> </div>
</div> </div>
<div className="row"> </div>
<div className="strokeSmollLeft" style={{ margin: 0, padding: 0, flex: 2 }}>
<div className="row" style={{ margin: 0, padding: 0 }}>
{searchTermText}
</div>
<div className="row" style={{ margin: 0, padding: 0 }}>
<input className="searchField" style={{ width: '80%', paddingLeft: '1em', paddingRight: '1em' }}
value={obj.searchTerm}
onChange={(evt) => obj.setSearchTerm(evt.target.value)}
placeholder='Filter by Orchestrator address'
type="text"
/>
<div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}>
<button className={"nonHomeButton"} style={{ backgroundColor: greyColour, margin: 0, padding: '0', width: '6em' }} onClick={() => {
obj.setSearchTerm("");
}}>
<h3>Clear</h3>
</button>
</div>
</div>
</div>
<div className="strokeSmollLeft" style={{ margin: 0, padding: 0, flex: 2 }}>
<div className="row" style={{ margin: 0, padding: 0 }}>
<h3>{parseFloat(amountFilter) > 0 ? ("Only showing higher than " + amountFilter) : "Filter by minimum value"}</h3>
</div>
<div className="row" style={{ margin: 0, padding: 0 }}>
<div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}> <div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}>
<h3></h3>
<button className={"nonHomeButton"} style={{ backgroundColor: greyColour, margin: 0, padding: '0', width: '5em' }} onClick={() => { <button className={"nonHomeButton"} style={{ backgroundColor: greyColour, margin: 0, padding: '0', width: '5em' }} onClick={() => {
const curVal = parseFloat(amountFilter); setAmountFilter(0);
setAmountFilter(curVal - 1000);
}}> }}>
<h3>-1000</h3> <h3>0</h3>
</button> </button>
</div> </div>
<input className="searchField" style={{ margin: 0, padding: 0, height: '2em', width: '80%', paddingLeft: '1em', paddingRight: '1em' }}
value={amountFilter}
onChange={(evt) => setAmountFilter(evt.target.value)}
placeholder='Filter by minimum value'
type="number"
/>
<div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}> <div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}>
<h3></h3>
<button className={"nonHomeButton"} style={{ backgroundColor: greyColour, margin: 0, padding: '0', width: '4em' }} onClick={() => {
const curVal = parseFloat(amountFilter);
setAmountFilter(curVal - 100);
}}>
<h3>-100</h3>
</button>
</div>
<div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}>
<h3></h3>
<button className={"nonHomeButton"} style={{ backgroundColor: greyColour, margin: 0, padding: '0', width: '3em' }} onClick={() => {
const curVal = parseFloat(amountFilter);
setAmountFilter(curVal - 10);
}}>
<h3>-10</h3>
</button>
</div>
<div className="strokeSmollLeft" style={{ margin: "0", padding: 0 }}>
<h3>{parseFloat(amountFilter) > 0 ? ("Only showing higher than " + amountFilter) : "Filter by minimum value"}</h3>
<input className="searchField" style={{ margin: 0, padding: 0, height: '2em', width: '80%', paddingLeft: '1em', paddingRight: '1em' }}
value={amountFilter}
onChange={(evt) => setAmountFilter(evt.target.value)}
placeholder='Filter by minimum value'
type="number"
/>
</div>
<div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}>
<h3></h3>
<button className={"nonHomeButton"} style={{ backgroundColor: greyColour, margin: 0, padding: '0', width: '3em' }} onClick={() => {
const curVal = parseFloat(amountFilter);
setAmountFilter(curVal + 10);
}}>
<h3>+10</h3>
</button>
</div>
<div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}>
<h3></h3>
<button className={"nonHomeButton"} style={{ backgroundColor: greyColour, margin: 0, padding: '0', width: '4em' }} onClick={() => { <button className={"nonHomeButton"} style={{ backgroundColor: greyColour, margin: 0, padding: '0', width: '4em' }} onClick={() => {
const curVal = parseFloat(amountFilter); const curVal = parseFloat(amountFilter);
setAmountFilter(curVal + 100); setAmountFilter(curVal + 100);
@ -256,7 +237,6 @@ const EventViewer = (obj) => {
</button> </button>
</div> </div>
<div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}> <div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}>
<h3></h3>
<button className={"nonHomeButton"} style={{ backgroundColor: greyColour, margin: 0, padding: '0', width: '5em' }} onClick={() => { <button className={"nonHomeButton"} style={{ backgroundColor: greyColour, margin: 0, padding: '0', width: '5em' }} onClick={() => {
const curVal = parseFloat(amountFilter); const curVal = parseFloat(amountFilter);
setAmountFilter(curVal + 1000); setAmountFilter(curVal + 1000);
@ -266,48 +246,60 @@ const EventViewer = (obj) => {
</div> </div>
</div> </div>
</div> </div>
<div className="content-wrapper" style={{ alignItems: 'stretch', width: '100%' }}> </div>
<ScrollContainer className="overflow-container" hideScrollbars={false} style={{}}> }
<div className="overflow-content" style={{ cursor: 'grab', paddingTop: 0}}>
{eventList} return (
<div className="strokeSmollLeft" style={{ padding: 0, margin: 0, height: 'calc( 100vh - 50px)' }}>
{filterBit}
<div className="row" style={{ padding: 0, margin: 0, width: '100%', height: '100%' }}>
<div className="stroke roundedOpaque" style={{ padding: 0, margin: 0, width: 'unset', height: '100%', marginRight: '1em', overflow: 'hidden', marginTop: '1em', overflowX: 'scroll' }}>
<div className="content-wrapper" style={{ width: '100%' }}>
<ScrollContainer className="overflow-container" hideScrollbars={false}>
<div className="overflow-content" style={{ cursor: 'grab', paddingTop: 0 }}>
<div className={obj.forceVertical ? "flexContainer forceWrap" : "flexContainer"} style={{ margin: 0, textAlign: 'center', alignItems: 'center', justifyContent: 'center' }}>
{eventList}
</div>
</div>
</ScrollContainer>
<div className="strokeSmollLeft" style={{ marginRight: "1em" }}>
<button className={filterActivated ? "row nonHomeButton active" : "row nonHomeButton"} style={{ backgroundColor: filterActivatedColour }} onClick={() => {
setFilterActivated(!filterActivated);
}}>
<h3>Activated</h3>
</button>
<button className={rewardActivated ? "row nonHomeButton active" : "row nonHomeButton"} style={{ backgroundColor: rewardActivatedColour }} onClick={() => {
setRewardActivated(!rewardActivated);
}}>
<h3>Reward</h3>
</button>
<button className={updateActivated ? "row nonHomeButton active" : "row nonHomeButton"} style={{ backgroundColor: updateActivatedColour }} onClick={() => {
setUpdateActivated(!updateActivated);
}}>
<h3>Update</h3>
</button>
<button className={withdrawActivated ? "row nonHomeButton active" : "row nonHomeButton"} style={{ backgroundColor: withdrawActivatedColour }} onClick={() => {
setWithdrawActivated(!withdrawActivated);
}}>
<h3>Withdraw</h3>
</button>
<button className={stakeActivated ? "row nonHomeButton active" : "row nonHomeButton"} style={{ backgroundColor: stakeActivatedColour }} onClick={() => {
setStakeActivated(!stakeActivated);
}}>
<h3>Stake</h3>
</button>
<button className={delegatorRewardActivated ? "row nonHomeButton active" : "row nonHomeButton"} style={{ backgroundColor: delegatorActivatedColour }} onClick={() => {
setDelegatorRewardActivated(!delegatorRewardActivated);
}}>
<h3>Claim</h3>
</button>
<button className={unbondActivated ? "row nonHomeButton active" : "row nonHomeButton"} style={{ backgroundColor: unbondActivatedColour }} onClick={() => {
setUnbondActivated(!unbondActivated);
}}>
<h3>Unbond</h3>
</button>
</div>
</div> </div>
</ScrollContainer>
<div className="strokeSmollLeft" style={{ marginRight: "1em" }}>
<button className={filterActivated ? "row nonHomeButton active" : "row nonHomeButton"} style={{ backgroundColor: filterActivatedColour }} onClick={() => {
setFilterActivated(!filterActivated);
}}>
<h3>Activated</h3>
</button>
<button className={rewardActivated ? "row nonHomeButton active" : "row nonHomeButton"} style={{ backgroundColor: rewardActivatedColour }} onClick={() => {
setRewardActivated(!rewardActivated);
}}>
<h3>Reward</h3>
</button>
<button className={updateActivated ? "row nonHomeButton active" : "row nonHomeButton"} style={{ backgroundColor: updateActivatedColour }} onClick={() => {
setUpdateActivated(!updateActivated);
}}>
<h3>Update</h3>
</button>
<button className={withdrawActivated ? "row nonHomeButton active" : "row nonHomeButton"} style={{ backgroundColor: withdrawActivatedColour }} onClick={() => {
setWithdrawActivated(!withdrawActivated);
}}>
<h3>Withdraw</h3>
</button>
<button className={stakeActivated ? "row nonHomeButton active" : "row nonHomeButton"} style={{ backgroundColor: stakeActivatedColour }} onClick={() => {
setStakeActivated(!stakeActivated);
}}>
<h3>Stake</h3>
</button>
<button className={delegatorRewardActivated ? "row nonHomeButton active" : "row nonHomeButton"} style={{ backgroundColor: delegatorActivatedColour }} onClick={() => {
setDelegatorRewardActivated(!delegatorRewardActivated);
}}>
<h3>Claim</h3>
</button>
<button className={unbondActivated ? "row nonHomeButton active" : "row nonHomeButton"} style={{ backgroundColor: unbondActivatedColour }} onClick={() => {
setUnbondActivated(!unbondActivated);
}}>
<h3>Unbond</h3>
</button>
</div> </div>
</div> </div>
</div> </div>

View File

@ -44,7 +44,7 @@ const Grafana = (obj) => {
<div className="flexContainer"> <div className="flexContainer">
<div className="stroke" style={{ marginTop: 0, marginBottom: 5, paddingBottom: 0 }}> <div className="stroke" style={{ marginTop: 0, marginBottom: 5, paddingBottom: 0 }}>
<div className="stroke roundedOpaque" style={{}}> <div className="stroke roundedOpaque" style={{}}>
<div className="row"> <div className="flexContainer" style={{ margin: 0, textAlign: 'center',alignItems: 'center', justifyContent:'center' }}>
<div className="row"> <div className="row">
<img alt="" src="livepeer.png" width="30" height="30" /> <img alt="" src="livepeer.png" width="30" height="30" />
<p>${lptPrice}</p> <p>${lptPrice}</p>

View File

@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react'
import './style.css'; import './style.css';
import { Navigate, useSearchParams } from "react-router-dom"; import { Navigate, useSearchParams } from "react-router-dom";
import { useSelector, useDispatch } from 'react-redux' import { useSelector, useDispatch } from 'react-redux'
import { getOrchestratorInfo } from "./actions/livepeer"; import { getOrchestratorInfo, clearOrchestrator } from "./actions/livepeer";
import EventViewer from "./eventViewer"; import EventViewer from "./eventViewer";
import Orchestrator from "./orchestratorViewer"; import Orchestrator from "./orchestratorViewer";
import Stat from "./statViewer"; import Stat from "./statViewer";
@ -11,14 +11,18 @@ import Stat from "./statViewer";
const Livepeer = (obj) => { const Livepeer = (obj) => {
const [prefill, setPrefill] = useSearchParams(); const [prefill, setPrefill] = useSearchParams();
const [searchTerm, setSearchTerm] = useState("");
const dispatch = useDispatch(); const dispatch = useDispatch();
const livepeer = useSelector((state) => state.livepeerstate); const livepeer = useSelector((state) => state.livepeerstate);
const [redirectToHome, setRedirectToHome] = useState(false); const [redirectToHome, setRedirectToHome] = useState(false);
const [showFilter, setShowFilter] = useState(false);
const [showSidebar, setShowSidebar] = useState(true);
console.log("Rendering Livepeer"); console.log("Rendering Livepeer");
useEffect(() => { useEffect(() => {
if (prefill.get('orchAddr') && prefill.get('orchAddr') !== "") { if (prefill.get('orchAddr') && prefill.get('orchAddr') !== "") {
dispatch(getOrchestratorInfo(prefill.get('orchAddr'))); dispatch(getOrchestratorInfo(prefill.get('orchAddr')));
setSearchTerm(prefill.get('orchAddr'));
} }
}, [prefill]); }, [prefill]);
@ -123,36 +127,72 @@ const Livepeer = (obj) => {
} }
let thisOrchObj; let thisOrchObj;
let headerString;
if (livepeer.selectedOrchestrator) { if (livepeer.selectedOrchestrator) {
thisOrchObj = livepeer.selectedOrchestrator; thisOrchObj = livepeer.selectedOrchestrator;
headerString = "Inspecting " + thisOrchObj.id;
} else {
headerString = "Livepeer Orchestrator Explorer";
}
let sidebar;
if (showSidebar){
sidebar = <div id='sideContent'>
<div className="strokeSmollLeft" style={{ margin: 0, padding: 0, width: '100%', marginTop: '1em' }}>
<div className="row" style={{ alignItems: 'stretch', height: '100%', padding: '0.2em', width: "unset" }}>
<Orchestrator thisOrchestrator={thisOrchObj} rootOnly={false} forceVertical={true} />
</div>
<div className="stroke metaSidebar" style={{ padding: 0, maxWidth: "300px" }}>
<div className="row" style={{ margin: 0, padding: 0 }}>
<h3 style={{ margin: 0, padding: 0 }}>Smart contract prices</h3>
</div>
<div className="stroke" style={{ margin: 0, padding: 0 }}>
<Stat header={"Reward Call"} content1={"$" + redeemRewardCostL2USD + " (vs " + redeemRewardCostL1USD + " on L1)"} />
<Stat header={"Claim Ticket"} content1={"$" + claimTicketCostL2USD + " (vs " + claimTicketCostL1USD + " on L1)"} />
<Stat header={"Staking Fees"} content1={"$" + stakeFeeCostL2USD + " (vs " + stakeFeeCostL1USD + " on L1)"} />
<Stat header={"Change Commission"} content1={"$" + commissionFeeCostL2USD + " (vs " + commissionFeeCostL1USD + " on L1)"} />
<Stat header={"Change URI"} content1={"$" + serviceUriFeeCostL2USD + " (vs " + serviceUriFeeCostL1USD + " on L1)"} />
</div>
</div>
</div>
</div >
} }
return ( return (
<div style={{ width: '100%', height: '100%' }}> <div style={{ margin: 0, padding: 0, height: '100%', width: '100%', overflow: 'hidden' }}>
<div className="row" style={{ margin: 0, padding: 0, backgroundColor: "rgba(180, 175, 252, 0.80)", boxSizing: "border-box", backdropDilter: "blur(6px)", boxSshadow: "9px 13px 18px 8px rgba(8, 7, 56, 0.692)", position: 'absolute', top: '0px', left: '0px', height: '300px', right: '0px', overflow: 'hidden' }}> <div id='header'>
<button className="homeButton" onClick={() => { <div className='rowAlignLeft'>
setRedirectToHome(true); <button className="homeButton" onClick={() => {
}}> setRedirectToHome(true);
<img alt="" src="livepeer.png" width="100em" height="100em" /> }}>
</button> <h1 style={{margin: 0, padding: 0}}>🏠</h1>
<div className="row" style={{ alignItems: 'stretch', height: '100%', flex: 2, padding: '0.2em', maxWidth: "1100px" }}> </button>
<Orchestrator thisOrchestrator={thisOrchObj} rootOnly={false} /> <h4>{headerString}</h4>
</div> </div>
<div className="stroke metaSidebar showNeverOnMobile" style={{ padding: 0, maxWidth: "300px" }}> <div className='rowAlignRight'>
<div className="row" style={{ margin: 0, padding: 0 }}> <button className="homeButton" style={{padding: 0, paddingRight: '1em', paddingLeft: '1em'}} onClick={() => {
<h3 style={{ margin: 0, padding: 0 }}>Smart contract prices</h3> dispatch(clearOrchestrator());
</div> setSearchTerm("");
<div className="stroke" style={{ margin: 0, padding: 0 }}> }}>
<Stat header={"Reward Call"} content1={"$" + redeemRewardCostL2USD + " (vs " + redeemRewardCostL1USD + " on L1)"} /> <h4> Clear</h4>
<Stat header={"Claim Ticket"} content1={"$" + claimTicketCostL2USD + " (vs " + claimTicketCostL1USD + " on L1)"} /> </button>
<Stat header={"Staking Fees"} content1={"$" + stakeFeeCostL2USD + " (vs " + stakeFeeCostL1USD + " on L1)"} /> <button className="homeButton" style={{padding: 0, paddingRight: '1em', paddingLeft: '1em'}} onClick={() => {
<Stat header={"Change Commission"} content1={"$" + commissionFeeCostL2USD + " (vs " + commissionFeeCostL1USD + " on L1)"} /> setShowSidebar(!showSidebar);
<Stat header={"Change URI"} content1={"$" + serviceUriFeeCostL2USD + " (vs " + serviceUriFeeCostL1USD + " on L1)"} /> }}>
</div> <h4>🔎 Sidebar</h4>
</button>
<button className="homeButton" style={{padding: 0, paddingRight: '1em', paddingLeft: '1em'}} onClick={() => {
setShowFilter(!showFilter);
}}>
<h4>🛠 Filter</h4>
</button>
</div>
</div>
<div id='bodyContent'>
{sidebar}
<div className="mainContent">
<EventViewer events={eventsList} searchTerm={searchTerm} setSearchTerm={setSearchTerm} forceVertical={true} showFilter={showFilter} />
</div> </div>
</div >
<div className="row" style={{ margin: 0, padding: 0 }}>
<EventViewer events={eventsList} prefill={prefill.get('orchAddr')} />
</div> </div>
</div > </div >
); );

View File

@ -3,6 +3,8 @@ import ScrollContainer from "react-indiana-drag-scroll";
import Stat from "./statViewer"; import Stat from "./statViewer";
import ReactTooltip from "react-tooltip"; import ReactTooltip from "react-tooltip";
import Address from "./OrchAddressViewer"; import Address from "./OrchAddressViewer";
import OrchDelegatorViewer from "./OrchDelegatorViewer";
import OrchInfoViewer from "./OrchInfoViewer";
function updateClipboard(newClip) { function updateClipboard(newClip) {
navigator.clipboard.writeText(newClip).then( navigator.clipboard.writeText(newClip).then(
@ -26,118 +28,71 @@ function copyLink(addr) {
} }
const Orchestrator = (obj) => { const Orchestrator = (obj) => {
let rewardCut = 0;
let feeCut = 0;
let totalStake = 0;
let totalVolumeETH = 0;
let totalVolumeUSD = 0;
let delegators = [];
let selfStake = 0;
let selfStakeRatio = 0;
let thisUrl = "";
let thisID = "";
if (obj.thisOrchestrator) { if (obj.thisOrchestrator) {
if (obj.thisOrchestrator.rewardCut) { if (obj.forceVertical) {
rewardCut = (obj.thisOrchestrator.rewardCut / 10000).toFixed(2); return (
} <div className="hostInfo">
if (obj.thisOrchestrator.feeShare) { <div className="flexContainer" style={{ justifyContent: 'flex-start', alignItems: 'flex-start', flexDirection: 'column' }}>
feeCut = (100 - (obj.thisOrchestrator.feeShare / 10000)).toFixed(2); <OrchInfoViewer
} rewardCut={obj.thisOrchestrator.rewardCut}
if (obj.thisOrchestrator.totalStake) { feeShare={obj.thisOrchestrator.feeShare}
totalStake = parseFloat(obj.thisOrchestrator.totalStake).toFixed(2); totalStake={obj.thisOrchestrator.totalStake}
} totalVolumeETH={obj.thisOrchestrator.totalVolumeETH}
if (obj.thisOrchestrator.totalVolumeETH) { totalVolumeUSD={obj.thisOrchestrator.totalVolumeUSD}
totalVolumeETH = parseFloat(obj.thisOrchestrator.totalVolumeETH * 1).toFixed(4); delegator={obj.thisOrchestrator.delegator}
} />
if (obj.thisOrchestrator.totalVolumeUSD) { <OrchDelegatorViewer delegators={obj.thisOrchestrator.delegators} forceVertical={obj.forceVertical} />
totalVolumeUSD = parseFloat(obj.thisOrchestrator.totalVolumeUSD * 1).toFixed(2);
}
if (obj.thisOrchestrator.delegators && obj.thisOrchestrator.delegator) {
delegators = obj.thisOrchestrator.delegators;
selfStake = parseFloat(obj.thisOrchestrator.delegator.bondedAmount);
selfStakeRatio = ((selfStake / totalStake) * 100).toFixed(2);
selfStake = selfStake.toFixed(2);
thisID = obj.thisOrchestrator.delegator.id;
thisUrl = "https://explorer.livepeer.org/accounts/" + thisID;
}
let shareUrl;
if (obj.rootOnly) {
shareUrl = window.location.href;
} else {
let thisFullPath = window.location.href;
if (thisFullPath.lastIndexOf("?") > -1) {
thisFullPath = thisFullPath.substring(0, thisFullPath.lastIndexOf("?"));
}
shareUrl = thisFullPath + "?orchAddr=" + thisID;
}
return (
<div className="hostInfo">
<div className="strokeSmollLeft" style={{ display: "flex" }}>
<div style={{ flexDirection: 'row', display: "flex" }} style={{ marginTop: '1em' }}>
<a href={thisUrl}>
<h3 style={{ padding: 0, margin: 0 }}>Orchestrator Info</h3>
<Address address={thisID} />
</a>
</div>
<div className="row" style={{}}>
<Stat header={"Earned Fees"} content1={totalVolumeETH + " Eth"} content2={"$" + totalVolumeUSD} />
</div>
<div className="row" style={{}}>
<Stat header={"Commission"} title1={"Reward"} content1={rewardCut + "%"} title2={"Fee"} content2={feeCut + "%"} />
</div>
<div className="row" style={{}}>
<Stat header={"Stake"} title1={"Total"} content1={totalStake + " LPT"} title2={"Self"} content2={selfStake + " LPT (" + selfStakeRatio + ")%"} />
</div>
<div className="strokeSmollLeft" style={{ display: "flex" }}>
<button style={{marginBottom:'1em'}} className="selectOrchLight" data-tip data-for="registerTip" onClick={() => {
copyLink(shareUrl);
}}>
<img alt="" src="clipboard.svg" width="20em" height="20em" />
</button>
<ReactTooltip id="registerTip" place="top" effect="solid">
Copy to clipboard
</ReactTooltip>
</div> </div>
</div> </div>
<div className="strokeSmollLeft" style={{ alignItems: 'stretch', flex: 2, marginLeft: '1em', borderLeft: '3px solid rgba(15,15,15,0.05)' }}> )
<div className="row" style={{ marginTop: '1em' }}> }else{
<h3 style={{ padding: 0, margin: 0 }}>{delegators.length} Current Delegators</h3> return (
<div className="hostInfo">
<div className="flexContainer" style={{ justifyContent: 'flex-start', alignItems: 'flex-start' }}>
<OrchInfoViewer
rewardCut={obj.thisOrchestrator.rewardCut}
feeShare={obj.thisOrchestrator.feeShare}
totalStake={obj.thisOrchestrator.totalStake}
totalVolumeETH={obj.thisOrchestrator.totalVolumeETH}
totalVolumeUSD={obj.thisOrchestrator.totalVolumeUSD}
delegator={obj.thisOrchestrator.delegator}
/>
<OrchDelegatorViewer delegators={obj.thisOrchestrator.delegators} forceVertical={obj.forceVertical} />
</div> </div>
<div className="content-wrapper"> </div>
<ScrollContainer className="overflow-container" hideScrollbars={false}> )
<div className="overflow-content" style={{ cursor: 'grab' }}> }
{ }
delegators.map((delObj, idx) => { if (obj.forceVertical) {
return ( return (
<div className="rowAlignLeft" key={"delegator" + idx} style={{ marginLeft: '1em', borderBottom: '2px solid rgba(15,15,15,0.05)' }}> <div className="hostInfo">
<Address address={delObj.id} seed={"delegator" + idx + delObj.id} /> <div className="flexContainer" style={{ alignItems: 'center', flexDirection: 'column' }}>
<div className="rowAlignRight"> <div className="rowAlignLeft">
<p className="darkText">{parseFloat(delObj.bondedAmount).toFixed(2)} LPT since round {delObj.startRound}</p> <img alt="" src="livepeer.png" width="30" height="30" />
</div> <h3>Orchestrator Info</h3>
</div> </div>
) <div className="rowAlignLeft">
}) <p>Inspect an Orchestrator by clicking on their address</p>
} </div>
</div> </div>
</ScrollContainer> </div>
)
} else {
return (
<div className="hostInfo">
<div className="flexContainer" style={{ alignItems: 'center' }}>
<div className="rowAlignLeft">
<img alt="" src="livepeer.png" width="30" height="30" />
<h3>Orchestrator Info</h3>
</div>
<div className="rowAlignLeft">
<p>Inspect an Orchestrator by clicking on their address</p>
</div> </div>
</div> </div>
</div> </div>
) )
} }
return (
<div className="hostInfo">
<div className="rowAlignLeft">
<img alt="" src="livepeer.png" width="30" height="30" />
<h3>Orchestrator Info</h3>
</div>
<div className="rowAlignLeft">
<p>Click on an orchestrator address in the list below!</p>
</div>
</div>
)
} }
export default Orchestrator; export default Orchestrator;

View File

@ -3,7 +3,8 @@ import {
RECEIVE_BLOCKCHAIN_DATA, RECEIVE_BLOCKCHAIN_DATA,
RECEIVE_EVENTS, RECEIVE_EVENTS,
RECEIVE_ORCHESTRATOR, RECEIVE_ORCHESTRATOR,
RECEIVE_CURRENT_ORCHESTRATOR RECEIVE_CURRENT_ORCHESTRATOR,
CLEAR_ORCHESTRATOR
} from "../../actions/livepeer"; } from "../../actions/livepeer";
export default (state = {}, { type, message }) => { export default (state = {}, { type, message }) => {
@ -19,6 +20,8 @@ export default (state = {}, { type, message }) => {
return { ...state, thisOrchestrator: message }; return { ...state, thisOrchestrator: message };
case RECEIVE_ORCHESTRATOR: case RECEIVE_ORCHESTRATOR:
return { ...state, selectedOrchestrator: message }; return { ...state, selectedOrchestrator: message };
case CLEAR_ORCHESTRATOR:
return { ...state, selectedOrchestrator: null };
default: default:
return { ...state }; return { ...state };
} }

View File

@ -15,16 +15,16 @@ const Stat = (obj) => {
<div className="rowAlignLeft" style={{ margin: 0, padding: 0 }}> <div className="rowAlignLeft" style={{ margin: 0, padding: 0 }}>
<h3 style={{ margin: 0, padding: 0 }}>{obj.header}</h3> <h3 style={{ margin: 0, padding: 0 }}>{obj.header}</h3>
</div> </div>
<div className="row" style={{}}> <div className="row" style={{ margin: 0 }}>
<div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}> <div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}>
<h4 style={{ margin: 0, padding: 0 }}>{obj.title1}</h4> <h4 style={{ margin: 0, padding: 0 }}>{obj.title1}</h4>
<div className="rowAlignLeft" style={{ margin: 0, marginLeft: '1em', padding: 0 }}> <div className="rowAlignLeft" style={{ margin: 0, padding: 0 }}>
<p className="darkText">{obj.content1}</p> <p className="darkText">{obj.content1}</p>
</div> </div>
</div> </div>
<div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}> <div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}>
<h4 style={{ margin: 0, padding: 0 }}>{obj.title2}</h4> <h4 style={{ margin: 0, padding: 0 }}>{obj.title2}</h4>
<div className="rowAlignLeft" style={{ margin: 0, marginLeft: '1em', padding: 0 }}> <div className="rowAlignLeft" style={{ margin: 0, padding: 0 }}>
<p className="darkText">{obj.content2}</p> <p className="darkText">{obj.content2}</p>
</div> </div>
</div> </div>

View File

@ -140,10 +140,36 @@ svg {
from { top: 0; } to { top: calc(100vh - 69px); } from { top: 0; } to { top: calc(100vh - 69px); }
} }
.metaSidebar {
#header {
height: 50px;
display: flex; display: flex;
flex-direction: row; align-items: center;
background-color: rgba(180, 175, 252, 0.80);
} }
#bodyContent {
height: calc( 100vh - 50px);
max-height: calc( 100vh - 50px);
display: flex;
flex-wrap: nowrap;
overflow: hidden;
}
#sideContent {
background-color: rgba(180, 175, 252, 0.80);
backdrop-filter: blur(6px);
box-shadow: 9px 13px 8px 8px rgba(8, 7, 56, 0.692);
border-bottom-right-radius: 1em;
width: 400px;
}
.mainContent {
overflow: hidden;
justify-content: center;
align-content: center;
align-items: center;
flex-basis: 0;
flex-grow: 999;
}
.fullGrafana { .fullGrafana {
width: 100%; width: 100%;
@ -194,6 +220,10 @@ svg {
width: auto; width: auto;
} }
.forceWrap{
flex-direction: column;
}
.stroke { .stroke {
box-sizing: border-box; box-sizing: border-box;
padding-bottom: 20px; padding-bottom: 20px;