Bläddra i källkod

Validator styling

Joystream Stats 3 år sedan
förälder
incheckning
6951c910bf

+ 3 - 2
src/App.tsx

@@ -170,8 +170,9 @@ class App extends React.Component<IProps, IState> {
 
   async fetchLastReward(api: Api, era: number) {
     const lastReward = Number(await api.query.staking.erasValidatorReward(era));
-    console.debug(`last reward`, lastReward);
-    this.save("lastReward", lastReward);
+    console.debug(`last reward`, era, lastReward);
+    if (lastReward > 0) this.save("lastReward", lastReward);
+    else this.fetchLastReward(api, era - 1);
   }
 
   async fetchTokenomics() {

+ 12 - 5
src/components/Members/MemberBox.tsx

@@ -1,9 +1,14 @@
 import React from "react";
-import { OverlayTrigger, Tooltip } from "react-bootstrap";
 import { Link } from "react-router-dom";
-import { Member, Post, ProposalDetail, Seat } from "../../types";
+import { OverlayTrigger, Tooltip } from "react-bootstrap";
 import MemberOverlay from "./MemberOverlay";
 
+import { Member, Post, ProposalDetail, Seat } from "../../types";
+
+const shortName = (name: string) => {
+  return `${name.slice(0, 5)}..${name.slice(+name.length - 5)}`;
+};
+
 const MemberBox = (props: {
   councils: Seat[][];
   members: Member[];
@@ -16,7 +21,7 @@ const MemberBox = (props: {
   placement: "left" | "bottom" | "right" | "top";
   validators: string[];
 }) => {
-  const { councils, handle, members, posts, placement, proposals } = props;
+  const { account, handle, members, posts, placement, proposals } = props;
   return (
     <OverlayTrigger
       placement={placement}
@@ -25,7 +30,7 @@ const MemberBox = (props: {
           <MemberOverlay
             handle={handle}
             members={members}
-            councils={councils}
+            councils={props.councils}
             proposals={proposals}
             posts={posts}
             startTime={props.startTime}
@@ -34,7 +39,9 @@ const MemberBox = (props: {
         </Tooltip>
       }
     >
-      <Link to={`/members/${handle}`}>{handle}</Link>
+      <Link to={`/members/${handle || account}`}>
+        {handle || shortName(account)}
+      </Link>
     </OverlayTrigger>
   );
 };

+ 3 - 9
src/components/User/index.tsx

@@ -1,6 +1,5 @@
 import React from "react";
 import { Link } from "react-router-dom";
-import { OverlayTrigger, Tooltip } from "react-bootstrap";
 
 const shortName = (name: string) => {
   return `${name.slice(0, 5)}..${name.slice(+name.length - 5)}`;
@@ -10,14 +9,9 @@ const User = (props: { id: string; handle?: string }) => {
   const { id, handle } = props;
 
   return (
-    <OverlayTrigger
-      placement="bottom"
-      overlay={<Tooltip id={id}>{id}</Tooltip>}
-    >
-      <span className="user mx-1">
-        <Link to={`/members/${handle || id}`}>{handle || shortName(id)}</Link>
-      </span>
-    </OverlayTrigger>
+    <span className="user mx-1">
+      <Link to={`/members/${handle || id}`}>{handle || shortName(id)}</Link>
+    </span>
   );
 };
 

+ 6 - 6
src/components/Validators/MinMax.tsx

@@ -1,7 +1,7 @@
 import React from "react";
 import { Stakes } from "../../types";
 
-const dollar = (d: number) => (d > 0 ? `$ ${Math.round(d * 100) / 100}` : "");
+const dollar = (d: number) => (d > 0 ? `$ ${d.toFixed(2)}` : "");
 
 const MinMax = (props: {
   stakes?: { [key: string]: Stakes };
@@ -27,7 +27,7 @@ const MinMax = (props: {
   });
 
   return (
-    <div className="float-right text-right">
+    <div className="float-right text-right d-none d-md-block">
       <div className="mb-2">
         <div>
           <div className="float-left mr-1">nominators:</div>
@@ -45,9 +45,9 @@ const MinMax = (props: {
 
       <b>total stake</b>
       <div className="mb-2">
-        <div>{Math.floor(sum / 100000) / 10} M JOY</div>/{" "}
-        {Math.floor(issued / 100000) / 10} M JOY
-        <div>({Math.floor((sum / issued) * 1000) / 10}%)</div>
+        <div>{(sum / 1000000).toFixed(1)} M JOY</div>/{" "}
+        {(issued / 1000000).toFixed(1)} M JOY
+        <div>({((sum / issued) * 100).toFixed(1)}%)</div>
       </div>
       <div>
         <div className="float-left mr-1">min:</div> {minStake} JOY
@@ -76,7 +76,7 @@ const Reward = (props: {
       <div>{dollar(price * reward)}</div>
       <div className="mt-2">per validator:</div>
       <div className="text-warning">
-        {Math.round(reward / validators)} JOY
+        {(reward / validators).toFixed(0)} JOY
         <div>{dollar((price * reward) / validators)}</div>
       </div>
     </div>

+ 32 - 38
src/components/Validators/Nominators.tsx

@@ -6,12 +6,13 @@ import { Handles, Stake } from "../../types";
 
 const Reward = (reward: number) =>
   reward > 0 ? (
-    <span className="text-warning mx-1">+{Math.round(reward)}</span>
+    <span className="text-warning mx-1">+{reward.toFixed(0)}</span>
   ) : (
     <span />
   );
 
 const Nominators = (props: {
+  fNum: (n: number) => string;
   sortBy: (field: string) => void;
   toggleExpand: () => void;
   expand: boolean;
@@ -19,50 +20,43 @@ const Nominators = (props: {
   nominators?: Stake[];
   reward: number;
 }) => {
-  const { sortBy, toggleExpand, expand, handles, nominators, reward } = props;
+  const { fNum, sortBy, handles, nominators, reward } = props;
 
   if (!nominators || !nominators.length) return <div />;
 
   let sum: number = 0;
   nominators.forEach((n) => (sum += n.value));
 
-  if (nominators.length === 1)
-    return (
-      <div className="d-flex flex-row">
-        <div onClick={() => sortBy("othersStake")}>{nominators[0].value}</div>
-        {Reward(reward)}
-        <User id={nominators[0].who} handle={handles[nominators[0].who]} />
-      </div>
-    );
-
-  if (expand)
-    return (
-      <div>
-        <span onClick={() => sortBy("othersStake")}>{sum}</span>
-        <span onClick={toggleExpand}> -</span>
-        {nominators.map((n) => (
-          <div key={n.who} className="d-flex flex-row">
-            <div>{n.value}</div>
-            {Reward(reward * (n.value / sum))}
-            <User id={n.who} handle={handles[n.who]} />
-          </div>
-        ))}
-      </div>
-    );
-
   return (
-    <div>
-      <span onClick={() => sortBy("othersStake")}> {sum}</span>
-      {nominators
-        .sort((a, b) => b.value - a.value)
-        .map((n) => (
-          <span key={n.who}>
-            {Reward(reward * (n.value / sum))}
-            <User id={n.who} handle={handles[n.who]} />
-          </span>
-        ))}
-      <span onClick={toggleExpand}> +</span>
-    </div>
+    <table onClick={() => sortBy("othersStake")}>
+      <tbody>
+        {nominators.length > 1 && (
+          <tr>
+            <td className="text-right" style={{ width: "75px" }}>
+              {fNum(sum)}
+            </td>
+            <td className="text-right" style={{ width: "40px" }}>
+              {Reward(reward)}
+            </td>
+          </tr>
+        )}
+        {nominators
+          .sort((a, b) => b.value - a.value)
+          .map((n) => (
+            <tr key={n.who}>
+              <td className="text-right" style={{ width: "75px" }}>
+                {fNum(n.value)}
+              </td>
+              <td className="text-right" style={{ width: "40px" }}>
+                {Reward(reward * (n.value / sum))}
+              </td>
+              <td>
+                <User id={n.who} handle={handles[n.who]} />
+              </td>
+            </tr>
+          ))}
+      </tbody>
+    </table>
   );
 };
 

+ 50 - 25
src/components/Validators/Validator.tsx

@@ -35,6 +35,12 @@ interface IState {
   hidden: boolean;
 }
 
+const fNum = (n: number) =>
+  n.toLocaleString(undefined, {
+    minimumFractionDigits: 2,
+    maximumFractionDigits: 2,
+  });
+
 class Validator extends Component<IProps, IState> {
   constructor(props: IProps) {
     super(props);
@@ -69,7 +75,6 @@ class Validator extends Component<IProps, IState> {
     const { expandNominators, hidden } = this.state;
     if (hidden) return <div />;
 
-    const handle = handles[validator] || validator;
     const points = rewardPoints ? rewardPoints.individual[validator] : "";
     const myStakes = stakes ? stakes[validator] : undefined;
     let totalStake = 0;
@@ -91,30 +96,36 @@ class Validator extends Component<IProps, IState> {
     }
 
     return (
-      <div className="mx-3 d-flex flex-row">
-        <Minus width={15} color={"black"} onClick={this.hide} />
-        <Star
-          width={15}
-          color={"black"}
-          fill={starred ? "black" : "teal"}
-          onClick={() => toggleStar(validator)}
-        />
-        <a
-          href={`${domain}/#/staking/query/${validator}`}
-          title="Show Stats (External)"
+      <div className="d-flex flex-row justify-content-around">
+        <div className="col-2 col-md-1">
+          <Minus width={15} color={"black"} onClick={this.hide} />
+          <Star
+            width={15}
+            color={"black"}
+            fill={starred ? "black" : "teal"}
+            onClick={() => toggleStar(validator)}
+          />
+          <a
+            href={`${domain}/#/staking/query/${validator}`}
+            title="Show Stats (External)"
+          >
+            <Activity width={15} />
+          </a>
+        </div>
+        <div
+          className="col-1 text-right"
+          onClick={() => sortBy("points")}
+          title="era points"
         >
-          <Activity width={15} />
-        </a>
-        <div className="col-1 text-right" onClick={() => sortBy("points")}>
           {points}
         </div>
-        <div className="col-4 text-right">
+        <div className="col-2 text-right">
           <MemberBox
             id={0}
             account={validator}
             placement={"right"}
             councils={councils}
-            handle={handle}
+            handle={handles[validator]}
             members={members}
             posts={posts}
             proposals={proposals}
@@ -123,22 +134,37 @@ class Validator extends Component<IProps, IState> {
           />
         </div>
 
-        <div className="col-1 text-right" onClick={() => sortBy("commission")}>
+        <div
+          className="col-1 text-right"
+          onClick={() => sortBy("commission")}
+          title="commission"
+        >
           {commission}
         </div>
-        <div className="col-1 text-right" onClick={() => sortBy("totalStake")}>
-          {totalStake > 0 && totalStake}
+        <div
+          className="col-2 text-black text-right"
+          onClick={() => sortBy("totalStake")}
+          title="total stake"
+        >
+          {totalStake > 0 && fNum(totalStake)}
         </div>
-        <div className="col-1 text-right" onClick={() => sortBy("ownStake")}>
-          {ownStake > 0 && ownStake}
+        <div
+          className="col-2 text-right"
+          onClick={() => sortBy("ownStake")}
+          title="own stake"
+        >
+          {ownStake > 0 && fNum(ownStake)}
         </div>
         {ownReward ? (
-          <div className="text-warning">+{Math.round(ownReward)}</div>
+          <div className="col-1 text-warning" title="reward">
+            +{Math.round(ownReward)}
+          </div>
         ) : (
           <div />
         )}
-        <div className="col-3 mb-1 text-left">
+        <div className="d-none d-md-block col-3 mb-1 text-left">
           <Nominators
+            fNum={fNum}
             reward={othersReward}
             toggleExpand={this.toggleExpandNominators}
             sortBy={sortBy}
@@ -147,7 +173,6 @@ class Validator extends Component<IProps, IState> {
             handles={handles}
           />
         </div>
-        <div onClick={() => sortBy("profit")}></div>
       </div>
     );
   }

+ 17 - 20
src/components/Validators/index.tsx

@@ -1,6 +1,7 @@
 import React, { Component } from "react";
 import MinMax from "./MinMax";
 import Validator from "./Validator";
+import MemberBox from "../Members/MemberBox";
 import {
   Handles,
   Member,
@@ -106,6 +107,7 @@ class Validators extends Component<IProps, IState> {
       handles,
       members,
       posts,
+      proposals,
       validators,
       nominators,
       stashes,
@@ -124,7 +126,7 @@ class Validators extends Component<IProps, IState> {
     const waiting = stashes.filter((s) => !stars[s] && !validators.includes(s));
 
     return (
-      <div className="box w-100">
+      <div className="box w-100 m-0 px-5">
         <div className="float-left">
           last block: {block}, era {era}
         </div>
@@ -154,13 +156,12 @@ class Validators extends Component<IProps, IState> {
               handles={handles}
               members={members}
               posts={posts}
-              proposals={this.props.proposals}
-              validators={this.props.validators}
+              proposals={proposals}
+              validators={validators}
               stakes={stakes}
               rewardPoints={rewardPoints}
             />
           ))}
-
           {this.sortBy(sortBy, unstarred).map((v) => (
             <Validator
               key={v}
@@ -174,31 +175,27 @@ class Validators extends Component<IProps, IState> {
               handles={handles}
               members={members}
               posts={posts}
-              proposals={this.props.proposals}
-              validators={this.props.validators}
+              proposals={proposals}
+              validators={validators}
               stakes={stakes}
               rewardPoints={rewardPoints}
             />
           ))}
-
-          <h3>Waiting</h3>
-
+          <hr />
+          Waiting:
           {waiting.map((v) => (
-            <Validator
+            <MemberBox
               key={v}
-              sortBy={this.setSortBy}
-              starred={stars[v] ? `teal` : undefined}
-              toggleStar={this.toggleStar}
-              startTime={startTime}
-              validator={v}
+              id={0}
+              account={v}
+              placement={"top"}
               councils={councils}
-              handles={handles}
+              handle={handles[v]}
               members={members}
               posts={posts}
-              proposals={this.props.proposals}
-              validators={this.props.validators}
-              stakes={stakes}
-              rewardPoints={rewardPoints}
+              proposals={proposals}
+              startTime={startTime}
+              validators={validators}
             />
           ))}
         </div>