Ver Fonte

several fixes and improvements

Joystream Stats há 3 anos atrás
pai
commit
e4e9264821

+ 1 - 1
public/index.html

@@ -5,7 +5,7 @@
     <meta name="viewport" content="width=device-width, initial-scale=1" />
     <meta name="theme-color" content="#000000" />
     <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
-    <title>Joystream Stats</title>
+    <title>JoystreamStats</title>
   </head>
   <body>
     <noscript>You need to enable JavaScript to run this app.</noscript>

+ 3 - 1
src/App.tsx

@@ -30,10 +30,11 @@ interface IProps {}
 const version = 0.3;
 
 const initialState = {
+  connecting: true,
+  loading: true,
   blocks: [],
   now: 0,
   block: 0,
-  loading: true,
   nominators: [],
   validators: [],
   channels: [],
@@ -62,6 +63,7 @@ class App extends React.Component<IProps, IState> {
     const provider = new WsProvider(wsLocation);
     const api = await ApiPromise.create({ provider, types });
     await api.isReady;
+    this.setState({ connecting: false });
     console.log(`Connected to ${wsLocation}`);
 
     let blocks: Block[] = [];

+ 2 - 2
src/components/Councils/VoteDiv.tsx

@@ -4,10 +4,10 @@ import { Member, Vote } from "../../types";
 
 const VoteDiv = (props: { votes?: Vote[]; member?: Member }) => {
   const { votes, member } = props;
-  if (!votes || !member) return <span />;
+  if (!votes || !member) return <td />;
 
   const v = votes.find((v) => v.handle === member.handle);
-  if (!v || v.vote === "") return <span />;
+  if (!v || v.vote === "") return <td />;
 
   const styles: { [key: string]: string } = {
     Approve: "success",

+ 4 - 1
src/components/Councils/index.tsx

@@ -2,7 +2,7 @@ import React from "react";
 import { Table } from "react-bootstrap";
 import LeaderBoard from "./Leaderboard";
 import CouncilVotes from "./CouncilVotes";
-
+import Back from "../Back";
 import { Member, ProposalDetail, Seat } from "../../types";
 
 // TODO fetch from chain
@@ -21,6 +21,9 @@ const Rounds = (props: {
   const { block, councils, members, proposals } = props;
   return (
     <div className="w-100">
+      <div className="position-fixed" style={{ right: "0", top: "0" }}>
+        <Back />
+      </div>
       <Table className="w-100 text-light">
         <thead>
           <tr>

+ 14 - 1
src/components/Dashboard/index.tsx

@@ -1,11 +1,22 @@
 import React from "react";
 import { Link } from "react-router-dom";
 import { ActiveProposals, Council } from "..";
+import Footer from "./Footer";
 import Validators from "../Validators";
 import { IState } from "../../types";
 
 const Dashboard = (props: IState) => {
-  const { block, now, domain, handles, members, proposals, tokenomics } = props;
+  const {
+    connecting,
+    block,
+    now,
+    domain,
+    handles,
+    members,
+    proposals,
+    tokenomics,
+  } = props;
+  const userLink = `${domain}/#/members/joystreamstats`;
   return (
     <div className="w-100 flex-grow-1 d-flex align-items-center justify-content-center d-flex flex-column">
       <div className="box position-abasolute" style={{ top: "0", right: "0" }}>
@@ -67,6 +78,8 @@ const Dashboard = (props: IState) => {
         issued={tokenomics ? Number(tokenomics.totalIssuance) : 0}
         price={tokenomics ? Number(tokenomics.price) : 0}
       />
+
+      <Footer show={!connecting} link={userLink} />
     </div>
   );
 };

+ 0 - 3
src/components/Forum/Content.tsx

@@ -73,8 +73,6 @@ const Content = (props: {
       {!latest.posts.length ? (
         <h2 className="text-center text-light my-2">Nothing found</h2>
       ) : (
-        <div>
-          <h2 className="text-center text-light my-2">Latest</h2>
           <div className="overflow-auto" style={{ height: "90%" }}>
             {latest.posts.map((p) => (
               <LatestPost
@@ -87,7 +85,6 @@ const Content = (props: {
               />
             ))}
           </div>
-        </div>
       )}
     </div>
   );

+ 1 - 1
src/components/Forum/NavBar.tsx

@@ -86,7 +86,7 @@ const NavBar = (props: {
             placeholder="Search"
             className="bg-dark text-light "
             onChange={handleChange}
-            ref={(i) => i && i.focus()}
+            //ref={(i) => i && i.focus()}
           />
         </Form>
       </Nav>

+ 5 - 1
src/components/Forum/PostBox.tsx

@@ -15,8 +15,12 @@ const PostBox = (props: {
   text: string;
   threadId: number;
 }) => {
-  const { createdAt, startTime, id, authorId, handles, text, threadId } = props;
+  const { createdAt, startTime, id, authorId, handles, threadId } = props;
   const created = moment(startTime + createdAt.block * 6000).fromNow();
+  const text = props.text
+    .split("\n")
+    .map((line) => line.replace(/>/g, "&gt;"))
+    .join("\n\n");
 
   return (
     <div className="box" key={id}>

+ 6 - 6
src/components/Forum/index.tsx

@@ -68,17 +68,17 @@ class Forum extends React.Component<IProps, IState> {
   filterPosts(posts: Post[], s: string) {
     return s === ""
       ? posts
-      : posts.filter(
-          (p) =>
-            (p && p.text.toLowerCase().includes(s)) ||
-            this.props.handles[p.authorId].includes(s)
-        );
+      : posts.filter((p) => {
+          const handle = this.props.handles[p.authorId] || "";
+          const text = p.text.toLowerCase();
+          return text.includes(s) || handle.includes(s);
+        });
   }
 
   filterThreads(list: any[], s: string) {
     return s === ""
       ? list
-      : list.filter((i) => i && i.title.toLowerCase().includes(s));
+      : list.filter((i) => i.title.toLowerCase().includes(s));
   }
 
   getLatest() {

+ 1 - 1
src/components/Members/Member.tsx

@@ -43,7 +43,7 @@ const MemberBox = (props: {
 
   return (
     <div>
-      <Back target="/members" />
+      <Back />
       <div className="box">
         {isCouncilMember && <div>council member</div>}
         <a href={`${domain}/#/members/${member.handle}`}>

+ 9 - 0
src/components/Mint/ValidatorRewards.tsx

@@ -47,6 +47,15 @@ const ValidatorRewards = (props: {
           ))}
         </tbody>
       </Table>
+      For details see{" "}
+      <a href="https://github.com/Joystream/community-repo/blob/master/community-contributions/miscellaneous_reports/Increase%20Validator%20Set%20Research.md">
+        Increase Validator Set Research
+      </a>{" "}
+      and{" "}
+      <a href="https://testnet.joystream.org/#/forum/threads/125">
+        Validator count discussion
+      </a>
+      .
     </div>
   );
 };

+ 9 - 7
src/components/Validators/MinMax.tsx

@@ -6,7 +6,7 @@ const dollar = (d: number) => (d > 0 ? `$ ${d.toFixed(2)}` : "");
 const MinMax = (props: {
   stakes?: { [key: string]: Stakes };
   issued: number;
-  validators: number;
+  validators: string[];
   nominators: number;
   waiting: number;
   reward: number;
@@ -18,12 +18,14 @@ const MinMax = (props: {
   let sum = 0;
   let minStake: number = 10000000;
   let maxStake: number = 0;
-  Object.values(stakes).forEach((s: Stakes) => {
-    if (s.total > 0) sum += s.total;
+  Object.keys(stakes).forEach((v: string) => {
+    if (!validators.includes(v)) return;
+    const { total } = stakes[v];
+    if (total > 0) sum += total;
     else return;
 
-    if (s.total > maxStake) maxStake = s.total;
-    if (s.total < minStake) minStake = s.total;
+    if (total > maxStake) maxStake = total;
+    if (total < minStake) minStake = total;
   });
 
   return (
@@ -35,7 +37,7 @@ const MinMax = (props: {
         </div>
         <div>
           <div className="float-left mr-1">validators:</div>
-          {validators}
+          {validators.length}
         </div>
         <div>
           <div className="float-left mr-1">waiting:</div>
@@ -56,7 +58,7 @@ const MinMax = (props: {
         <div className="float-left mr-1">max:</div> {maxStake} JOY
       </div>
 
-      <Reward reward={reward} price={price} validators={validators} />
+      <Reward reward={reward} price={price} validators={validators.length} />
     </div>
   );
 };

+ 30 - 24
src/components/Validators/index.tsx

@@ -1,4 +1,5 @@
 import React, { Component } from "react";
+import { ListGroup } from "react-bootstrap";
 import MinMax from "./MinMax";
 import Validator from "./Validator";
 import MemberBox from "../Members/MemberBox";
@@ -58,7 +59,7 @@ class Validators extends Component<IProps, IState> {
   sortBy(field: string, validators: string[]) {
     const { stakes, rewardPoints } = this.props;
     try {
-      if (field === "points")
+      if (field === "points" || !stakes)
         return validators.sort((a, b) =>
           rewardPoints
             ? rewardPoints.individual[b] - rewardPoints.individual[a]
@@ -67,17 +68,19 @@ class Validators extends Component<IProps, IState> {
 
       if (field === "commission")
         return validators.sort((a, b) =>
-          stakes ? stakes[a].commission - stakes[b].commission : 0
+          stakes[a] && stakes[b]
+            ? stakes[a].commission - stakes[b].commission
+            : 0
         );
 
       if (field === "ownStake")
         return validators.sort((a, b) =>
-          stakes ? stakes[b].own - stakes[a].own : 0
+          stakes[a] && stakes[b] ? stakes[b].own - stakes[a].own : 0
         );
 
       if (field === "totalStake")
         return validators.sort((a, b) =>
-          stakes ? stakes[b].total - stakes[a].total : 0
+          stakes[a] && stakes[b] ? stakes[b].total - stakes[a].total : 0
         );
 
       if (field === "othersStake") {
@@ -88,7 +91,9 @@ class Validators extends Component<IProps, IState> {
         };
 
         return validators.sort((a, b) =>
-          stakes ? sumOf(stakes[b].others) - sumOf(stakes[a].others) : 0
+          stakes[a] && stakes[b]
+            ? sumOf(stakes[b].others) - sumOf(stakes[a].others)
+            : 0
         );
       }
     } catch (e) {
@@ -124,9 +129,9 @@ class Validators extends Component<IProps, IState> {
     const starred = stashes.filter((v) => stars[v]);
     const unstarred = validators.filter((v) => !stars[v]);
     const waiting = stashes.filter((s) => !stars[s] && !validators.includes(s));
-
+    if (!unstarred.length) return <div />;
     return (
-      <div className="box w-100 m-0 px-5">
+      <div className="box w-100 m-0 px-5 mb-5">
         <div className="float-left">
           last block: {block}, era {era}
         </div>
@@ -134,7 +139,7 @@ class Validators extends Component<IProps, IState> {
           stakes={stakes}
           issued={issued}
           price={price}
-          validators={validators.length}
+          validators={validators}
           nominators={nominators.length}
           waiting={waiting.length}
           reward={lastReward}
@@ -182,25 +187,26 @@ class Validators extends Component<IProps, IState> {
             />
           ))}
           {waiting.length ? (
-            <div>
+            <ListGroup className="waiting-validators">
               <hr />
-              Waiting:
+              <h4>Waiting</h4>
               {waiting.map((v) => (
-                <MemberBox
-                  key={v}
-                  id={0}
-                  account={v}
-                  placement={"top"}
-                  councils={councils}
-                  handle={handles[v]}
-                  members={members}
-                  posts={posts}
-                  proposals={proposals}
-                  startTime={startTime}
-                  validators={validators}
-                />
+                <ListGroup.Item key={v}>
+                  <MemberBox
+                    id={0}
+                    account={v}
+                    placement={"top"}
+                    councils={councils}
+                    handle={handles[v]}
+                    members={members}
+                    posts={posts}
+                    proposals={proposals}
+                    startTime={startTime}
+                    validators={validators}
+                  />
+                </ListGroup.Item>
               ))}
-            </div>
+            </ListGroup>
           ) : (
             ""
           )}

+ 1 - 2
src/config.ts

@@ -1,3 +1,2 @@
 export const domain = "https://testnet.joystream.org";
-
-export const wsLocation = "wss://rome-rpc-endpoint.joystream.org:9944/";
+export const wsLocation = "wss://joystreamstats.live:9945";

+ 12 - 0
src/index.css

@@ -252,3 +252,15 @@ table td {
         display: none;
     }
 }
+
+.waiting-validators .list-group-item {
+    background-color: teal !important;
+}
+
+.footer {
+    background:  teal;
+    position:    fixed;
+    bottom:      0px;
+    padding:     10px;
+    text-align:  center;
+}

+ 7 - 3
src/lib/announcements.ts

@@ -37,9 +37,13 @@ export const channels = async (
     const channel: Channel = await query("title", () =>
       api.query.contentWorkingGroup.channelById(id)
     );
-    const member: any = { id: channel.owner, handle: "", url: "" };
-    member.handle = await memberHandle(api, member.id.toJSON());
-    member.url = `${domain}/#/members/${member.handle}`;
+
+    const handle = await memberHandle(api, channel.owner);
+    const member: { id: number; url: string; handle: string } = {
+      id: channel.owner.toNumber(),
+      handle,
+      url: `${domain}/#/members/${handle}`,
+    };
     messages.push(
       `<b>Channel <a href="${domain}/#//media/channels/${id}">${channel.title}</a> by <a href="${member.url}">${member.handle} (${member.id})</a></b>`
     );

+ 1 - 0
src/types.ts

@@ -17,6 +17,7 @@ export interface Api {
 
 export interface IState {
   //gethandle: (account: AccountId | string)  => string;
+  connecting: boolean;
   now: number;
   block: number;
   blocks: Block[];