Oleksandr Korniienko пре 3 година
родитељ
комит
83cbb4929b

+ 0 - 6
src/components/Bounties/index.tsx

@@ -13,14 +13,8 @@ class Bounties extends React.Component<iProps> {
     this.state = { bounties };
   }
 
-  componentDidMount() {
-    //this.fetchBounties();
-  }
-
   async fetchBounties() {
-    console.log(`Fetching bounties`);
     const { data } = await axios.get(`/static/bounties.json`);
-    console.debug(`bounties`, data);
     if (bounties) this.setState({ bounties: data });
   }
 

+ 3 - 3
src/components/Council/ElectionStatus.tsx

@@ -27,13 +27,13 @@ const ElectionStage = (props: {
   let stageString = Object.keys(stage)[0];
   const left = timeLeft(stage[stageString] - block);
   if (stageString === "announcing")
-    return <a href={`${domain}/#/council/applicants`}>{left} to apply</a>;
+    return <a style={{color: "#fff"}} href={`${domain}/#/council/applicants`}>{left} to apply</a>;
 
   if (stageString === "voting")
-    return <a href={`${domain}/#/council/applicants`}>{left} to vote</a>;
+    return <a style={{color: "#fff"}} href={`${domain}/#/council/applicants`}>{left} to vote</a>;
 
   if (stageString === "revealing")
-    return <a href={`${domain}/#/council/votes`}>{left} to reveal votes</a>;
+    return <a style={{color: "#fff"}} href={`${domain}/#/council/votes`}>{left} to reveal votes</a>;
 
   return <span>{JSON.stringify(stage)}</span>;
 };

+ 58 - 23
src/components/Council/index.tsx

@@ -2,6 +2,7 @@ import React from "react";
 import ElectionStatus from "./ElectionStatus";
 import MemberBox from "../Members/MemberBox";
 import Loading from "../Loading";
+import {Paper, Grid, makeStyles, Theme, createStyles, Toolbar, Typography, AppBar} from "@material-ui/core";
 
 import {
   Handles,
@@ -12,6 +13,19 @@ import {
   Status,
 } from "../../types";
 
+const useStyles = makeStyles((theme: Theme) =>
+    createStyles({
+      root: {
+        flexGrow: 1,
+        backgroundColor: "#4038FF",
+      },
+      title: {
+        textAlign: "left",
+        flexGrow: 1,
+      },
+    })
+);
+
 const Council = (props: {
   councils: Seat[][];
   councilElection?: any;
@@ -25,6 +39,7 @@ const Council = (props: {
 }) => {
   const { councils, handles, members, posts, proposals, status } = props;
   const council = councils[councils.length - 1];
+  const classes = useStyles();
   if (!council) return <Loading target="council" />;
 
   const sortCouncil = (council) =>
@@ -35,29 +50,49 @@ const Council = (props: {
     });
 
   return (
-    <div className="box w-50 p-3 m-3">
-      <h3>Council</h3>
-      <div className="d-flex flex-wrap justify-content-between">
-        {sortCouncil(council).map((m) => (
-          <div key={m.member} className="col-12 col-md-4">
-            <MemberBox
-              id={m.id || 0}
-              account={m.member}
-              handle={handles[m.member]}
-              members={members}
-              councils={councils}
-              proposals={proposals}
-              placement={"bottom"}
-              posts={posts}
-              startTime={status.startTime}
-              validators={props.validators}
-            />
-          </div>
-        ))}
-      </div>
-      <hr />
-      <ElectionStatus domain={props.domain} status={status} />
-    </div>
+    <Grid
+      style={{ textAlign: "center", backgroundColor: "#000", color: "#fff" }}
+      item
+      lg={6}
+    >
+      <Paper
+        style={{
+          textAlign: "center",
+          backgroundColor: "#4038FF",
+          color: "#fff",
+          height: 500,
+          overflow: "auto",
+        }}
+      >
+        <AppBar className={classes.root} position="static">
+          <Toolbar>
+            <Typography variant="h6" className={classes.title}>
+              Council
+            </Typography>
+          </Toolbar>
+        </AppBar>
+        <div className="d-flex flex-wrap justify-content-between mt-2">
+          {sortCouncil(council).map((m) => (
+            <div key={m.member} className="col-12 col-md-4">
+              <MemberBox
+                id={m.id || 0}
+                account={m.member}
+                handle={handles[m.member]}
+                members={members}
+                councils={councils}
+                proposals={proposals}
+                placement={"bottom"}
+                posts={posts}
+                startTime={status.startTime}
+                validators={props.validators}
+              />
+            </div>
+          ))}
+        </div>
+        <hr />
+        <ElectionStatus domain={props.domain} status={status} />
+      </Paper>
+    </Grid>
   );
 };
 

+ 66 - 21
src/components/Dashboard/Forum.tsx

@@ -1,9 +1,33 @@
 import React from "react";
-import { Link } from "react-router-dom";
 import LatestPost from "../Forum/LatestPost";
 import Loading from "../Loading";
 
 import { Handles, Post, Thread } from "../../types";
+import {
+    Grid,
+    Paper,
+    Link,
+    makeStyles,
+    Theme,
+    createStyles,
+    Toolbar,
+    AppBar, Typography,
+} from "@material-ui/core";
+
+const useStyles = makeStyles((theme: Theme) =>
+  createStyles({
+    root: {
+      flexGrow: 1,
+      backgroundColor: "#4038FF",
+    },
+    title: {
+      textAlign: "left",
+      flexGrow: 1,
+      padding: "10px",
+      color: "#fff",
+    },
+  })
+);
 
 const Forum = (props: {
   handles: Handles;
@@ -11,28 +35,49 @@ const Forum = (props: {
   threads: Thread[];
 }) => {
   const { handles, posts, threads, startTime } = props;
+  const classes = useStyles();
   if (!posts.length) return <Loading target="posts" />;
   return (
-    <div className="w-100 p-3 m-3 d-flex flex-column">
-      <h3>
-        <Link className="text-light" to={"/forum"}>
-          Forum
-        </Link>
-      </h3>
-      {props.posts
-        .sort((a, b) => b.id - a.id)
-        .slice(0, 10)
-        .map((post) => (
-          <LatestPost
-            key={post.id}
-            selectThread={() => {}}
-            handles={handles}
-            post={post}
-            thread={threads.find((t) => t.id === post.threadId)}
-            startTime={startTime}
-          />
-        ))}
-    </div>
+    <Grid
+      style={{ textAlign: "center", backgroundColor: "#000", color: "#fff" }}
+      item
+      lg={6}
+    >
+      <Paper
+        style={{
+          textAlign: "center",
+          backgroundColor: "#4038FF",
+          color: "#fff",
+          minHeight: 470,
+          maxHeight: 600,
+          overflow: "auto",
+        }}
+      >
+        <AppBar className={classes.root} position="static">
+          <Toolbar>
+              <Typography variant="h5" className={classes.title}>
+                  <Link style={{ color: "#fff" }} href={"/forum"}>
+                    Forum
+                  </Link>
+              </Typography>
+          </Toolbar>
+        </AppBar>
+
+        {props.posts
+          .sort((a, b) => b.id - a.id)
+          .slice(0, 10)
+          .map((post) => (
+            <LatestPost
+              key={post.id}
+              selectThread={() => {}}
+              handles={handles}
+              post={post}
+              thread={threads.find((t) => t.id === post.threadId)}
+              startTime={startTime}
+            />
+          ))}
+      </Paper>
+    </Grid>
   );
 };
 

+ 75 - 36
src/components/Dashboard/Proposals.tsx

@@ -1,7 +1,30 @@
 import React from "react";
-import { Link } from "react-router-dom";
 import ProposalsTable from "../Proposals/ProposalTable";
 import Loading from "../Loading";
+import {
+  AppBar,
+  createStyles,
+  Grid,
+  Link,
+  makeStyles,
+  Paper,
+  Theme,
+  Toolbar,
+  Typography,
+} from "@material-ui/core";
+
+const useStyles = makeStyles((theme: Theme) =>
+  createStyles({
+    root: {
+      flexGrow: 1,
+      backgroundColor: "#4038FF",
+    },
+    title: {
+      textAlign: "left",
+      flexGrow: 1,
+    },
+  })
+);
 
 const Proposals = (props: {
   proposals;
@@ -12,16 +35,9 @@ const Proposals = (props: {
   startTime: number;
   block: number;
 }) => {
-  const {
-    proposals,
-    validators,
-    councils,
-    members,
-    posts,
-    startTime,
-    block,
-  } = props;
-
+  const { proposals, validators, councils, members, posts, startTime, block } =
+    props;
+  const classes = useStyles();
   const pending = proposals.filter((p) => p && p.result === "Pending");
   if (!proposals.length) return <Loading target="proposals" />;
   if (!pending.length) {
@@ -32,32 +48,55 @@ const Proposals = (props: {
       <div className="box">No active proposals.</div>
     );
   }
+
   return (
-    <div className="w-100 p-3 m-3">
-      <div className="d-flex flex-row">
-        <h3 className="ml-1 text-light">Active Proposals</h3>
-        <Link className="m-3 text-light" to={"/proposals"}>
-          All
-        </Link>
-        <Link className="m-3 text-light" to={"/spending"}>
-          Spending
-        </Link>
-        <Link className="m-3 text-light" to={"/councils"}>
-          Votes
-        </Link>
-      </div>
-      <ProposalsTable
-        block={block}
-        hideNav={true}
-        proposals={pending}
-        proposalPosts={props.proposalPosts}
-        members={members}
-        councils={councils}
-        posts={posts}
-        startTime={startTime}
-        validators={validators}
-      />
-    </div>
+    <Grid
+      style={{
+        textAlign: "center",
+        backgroundColor: "#000",
+        color: "#fff",
+      }}
+      item
+      lg={6}
+    >
+      <Paper
+        style={{
+          textAlign: "center",
+          backgroundColor: "#4038FF",
+          color: "#fff",
+          height: 500,
+          overflow: "auto",
+        }}
+      >
+        <AppBar className={classes.root} position="static">
+          <Toolbar>
+            <Typography variant="h6" className={classes.title}>
+              Active Proposals
+            </Typography>
+            <Link className="m-3 text-light" href={"/proposals"}>
+              All
+            </Link>
+            <Link className="m-3 text-light" href={"/spending"}>
+              Spending
+            </Link>
+            <Link className="m-3 text-light" href={"/councils"}>
+              Votes
+            </Link>
+          </Toolbar>
+        </AppBar>
+        <ProposalsTable
+          block={block}
+          hideNav={true}
+          proposals={pending}
+          proposalPosts={props.proposalPosts}
+          members={members}
+          councils={councils}
+          posts={posts}
+          startTime={startTime}
+          validators={validators}
+        />
+      </Paper>
+    </Grid>
   );
 };
 

+ 62 - 66
src/components/Dashboard/index.tsx

@@ -1,10 +1,10 @@
 import React from "react";
-import { Link } from "react-router-dom";
-import { Council } from "..";
+import Council from "../Council";
 import Forum from "./Forum";
 import Proposals from "./Proposals";
 import Validators from "../Validators";
 import { IState } from "../../types";
+import { Container, Grid } from "@material-ui/core";
 
 interface IProps extends IState {
   toggleStar: (a: string) => void;
@@ -32,70 +32,66 @@ const Dashboard = (props: IProps) => {
   } = props;
 
   return (
-    <>
-      <div className="w-100 flex-grow-1 d-flex align-items-center justify-content-center d-flex flex-column pb-5">
-        <div className="back bg-warning d-flex flex-column p-2">
-          <Link to={`/calendar`}>Calendar</Link>
-          <Link to={`/timeline`}>Timeline</Link>
-          <Link to={`/tokenomics`}>Reports</Link>
-          <Link to={`/validators`}>Validators</Link>
-          <Link to={`/validator-report`}>Validator Report</Link>
-          <Link to={`/storage`}>Storage</Link>
-          <Link to={`/spending`}>Spending</Link>
-          <Link to={`/transactions`}>Transfers</Link>
-          <Link to={`/burners`}>Top Burners</Link>
-          <Link to="/mint">Toolbox</Link>
-        </div>
-
-        <Council
-          councils={councils}
-          members={members}
-          handles={handles}
-          posts={posts}
-          proposals={proposals}
-          stars={stars}
-          status={status}
-          validators={validators}
-          domain={domain}
-        />
-
-        <Proposals
-          block={status.block ? status.block.id : 0}
-          members={members}
-          councils={councils}
-          posts={posts}
-          proposals={proposals}
-          proposalPosts={props.proposalPosts}
-          validators={validators}
-          startTime={status.startTime}
-        />
-
-        <Forum
-          handles={handles}
-          posts={posts}
-          threads={threads}
-          startTime={status.startTime}
-        />
-
-        <Validators
-          hideBackButton={true}
-          toggleStar={toggleStar}
-          councils={councils}
-          handles={handles}
-          members={members}
-          posts={posts}
-          proposals={proposals}
-          nominators={nominators}
-          validators={validators}
-          stashes={stashes}
-          stars={stars}
-          stakes={stakes}
-          rewardPoints={rewardPoints}
-          tokenomics={tokenomics}
-          status={status}
-        />
-      </div>
-    </>
+    <div style={{ flexGrow: 1 }}>
+      <Container maxWidth="xl">
+        <Grid container spacing={3}>
+          <Council
+            councils={councils}
+            members={members}
+            handles={handles}
+            posts={posts}
+            proposals={proposals}
+            stars={stars}
+            status={status}
+            validators={validators}
+            domain={domain}
+          />
+          <Proposals
+            block={status.block ? status.block.id : 0}
+            members={members}
+            councils={councils}
+            posts={posts}
+            proposals={proposals}
+            proposalPosts={props.proposalPosts}
+            validators={validators}
+            startTime={status.startTime}
+          />
+          <Forum
+            handles={handles}
+            posts={posts}
+            threads={threads}
+            startTime={status.startTime}
+          />
+          <Grid
+            style={{
+              textAlign: "center",
+              backgroundColor: "#000",
+              color: "#fff",
+            }}
+            item
+            lg={6}
+          >
+            <Validators
+              hideBackButton={true}
+              toggleStar={toggleStar}
+              councils={councils}
+              handles={handles}
+              members={members}
+              posts={posts}
+              proposals={proposals}
+              nominators={nominators}
+              validators={validators}
+              stashes={stashes}
+              stars={stars}
+              stakes={stakes}
+              rewardPoints={rewardPoints}
+              tokenomics={tokenomics}
+              status={status}
+            />
+          </Grid>
+        </Grid>
+      </Container>
+    </div>
   );
 };
 

+ 14 - 6
src/components/Loading.tsx

@@ -1,14 +1,22 @@
 import React from "react";
 import { Button, Spinner } from "react-bootstrap";
+import { Grid } from "@material-ui/core";
+import {GridSize} from "@material-ui/core/Grid/Grid";
 
-const Loading = (props: { target?: string }) => {
-  const { target } = props;
+const Loading = (props: { target?: string, gridSize?: GridSize }) => {
+  const { gridSize, target } = props;
   const title = target ? `Fetching ${target}` : "Connecting to Websocket";
   return (
-    <Button variant="warning" className="m-1 py-0 mr-2">
-      <Spinner animation="border" variant="dark" size="sm" className="mr-1" />
-      {title}
-    </Button>
+    <Grid
+      style={{ textAlign: "center", backgroundColor: "#000", color: "#fff" }}
+      lg={`${gridSize ? gridSize!! : '6'}`}
+      item
+    >
+      <Button variant="warning" className="m-1 py-0 mr-2 mt-3">
+        <Spinner animation="border" variant="dark" size="sm" className="mr-1" />
+        {title}
+      </Button>
+    </Grid>
   );
 };
 

+ 26 - 17
src/components/Members/MemberBox.tsx

@@ -1,9 +1,9 @@
 import React from "react";
-import { Link } from "react-router-dom";
-import { OverlayTrigger, Tooltip } from "react-bootstrap";
 import MemberOverlay from "./MemberOverlay";
 
 import { Member, Post, ProposalDetail, Seat } from "../../types";
+import { Link } from "@material-ui/core";
+import InfoTooltip from "../Tooltip";
 
 const shortName = (name: string) => {
   return `${name.slice(0, 5)}..${name.slice(+name.length - 5)}`;
@@ -23,26 +23,35 @@ const MemberBox = (props: {
 }) => {
   const { account, handle, members, posts, placement, proposals } = props;
   return (
-    <OverlayTrigger
+    <InfoTooltip
       placement={placement}
-      overlay={
-        <Tooltip id={`overlay-${handle}`} className="member-tooltip">
-          <MemberOverlay
-            handle={handle}
-            members={members}
-            councils={props.councils}
-            proposals={proposals}
-            posts={posts}
-            startTime={props.startTime}
-            validators={props.validators}
-          />
-        </Tooltip>
+      id={`overlay-${handle}`}
+      title={
+        <MemberOverlay
+          handle={handle}
+          members={members}
+          councils={props.councils}
+          proposals={proposals}
+          posts={posts}
+          startTime={props.startTime}
+          validators={props.validators}
+        />
       }
     >
-      <Link to={`/members/${handle || account}`}>
+      <Link
+        variant={"button"}
+        style={{
+          color: "#fff",
+          display: "block",
+          margin: 4,
+          border: "1px solid #fff",
+          borderRadius: "4px",
+        }}
+        href={`/members/${handle || account}`}
+      >
         {handle || shortName(account)}
       </Link>
-    </OverlayTrigger>
+    </InfoTooltip>
   );
 };
 

+ 2 - 2
src/components/Members/MemberOverlay.tsx

@@ -24,10 +24,10 @@ const MemberBox = (props: {
   );
 
   return (
-    <div className="box">
+    <div style={{backgroundColor: '#4038FF', padding: 5}}>
       {isCouncilMember && <div>council member</div>}
       <a href={`${domain}/#/members/${handle}`}>
-        <h1>{handle}</h1>
+        <h3>{handle}</h3>
       </a>
 
       <Summary

+ 2 - 2
src/components/Members/Summary/index.tsx

@@ -51,12 +51,12 @@ const Summary = (props: {
 
   return (
     <div className="text-left">
-      <div className="my-1">
+      <div>
         Registered on {created} (id {member.id})
       </div>
 
       {runsValidator && (
-        <div className="my-1">
+        <div>
           This user runs a <a href={`${domain}/#/staking`}>validator node</a>.
         </div>
       )}

+ 16 - 17
src/components/Proposals/Bar.tsx

@@ -1,5 +1,5 @@
 import React from "react";
-import { OverlayTrigger, Tooltip } from "react-bootstrap";
+import InfoTooltip from "../Tooltip";
 
 const Bar = (props: {
   id: number;
@@ -14,27 +14,26 @@ const Bar = (props: {
   const bg = percent < 25 ? `danger` : percent < 50 ? `warning` : `success`;
 
   return (
-    <OverlayTrigger
-      key={id}
+    <InfoTooltip
       placement="bottom"
-      overlay={
-        <Tooltip id={String(id)}>
-          <div className="text-left">
-            <div className="mb-2">
-              created:
-              <div className="text-nowrap">{created}</div>
-            </div>
-            {left}
-            <div>expires {expires}</div>
+      key={id}
+      title={
+        <div className="text-left">
+          <div className="mb-2">
+            created:
+            <div className="text-nowrap">{created}</div>
           </div>
-        </Tooltip>
+          {left}
+          <div>expires {expires}</div>
+        </div>
       }
     >
       <div
-        className={`bg-${bg} mr-2`}
-        style={{ height: `5px`, width: `${percent}%` }}
-      ></div>
-    </OverlayTrigger>
+          className={`bg-${bg} mr-2 mt-2`}
+          style={{ cursor: "pointer", height: `5px`, width: `${percent}%` }}
+      />
+
+    </InfoTooltip>
   );
 };
 

+ 3 - 3
src/components/Proposals/ProposalTable.tsx

@@ -6,7 +6,7 @@ import NavButtons from "./NavButtons";
 import Types from "./Types";
 import { Member, Post, ProposalDetail, ProposalPost, Seat } from "../../types";
 
-const LIMIT = 10;
+const LIMIT = 3;
 
 interface IProps {
   hideNav?: boolean;
@@ -126,7 +126,7 @@ class ProposalTable extends React.Component<IProps, IState> {
 
     if (!proposals.length) return <div />;
     return (
-      <div className="h-100 overflow-hidden bg-light">
+      <div className="h-100 overflow-hidden">
         <NavBar
           show={!hideNav}
           author={author}
@@ -171,7 +171,7 @@ class ProposalTable extends React.Component<IProps, IState> {
         <NavButtons
           setPage={this.setPage}
           page={page}
-          limit={LIMIT}
+          limit={LIMIT+1}
           proposals={proposals.length}
         />
       </div>

+ 41 - 37
src/components/Proposals/Row.tsx

@@ -1,7 +1,4 @@
 import React from "react";
-import { Link } from "react-router-dom";
-import { OverlayTrigger, Tooltip } from "react-bootstrap";
-
 import MemberOverlay from "../Members/MemberOverlay";
 import Bar from "./Bar";
 import Posts from "./Posts";
@@ -18,6 +15,8 @@ import {
   Vote,
 } from "../../types";
 import { ProposalParameters, VotingResults } from "@joystream/types/proposals";
+import InfoTooltip from "../Tooltip";
+import { Link, makeStyles } from "@material-ui/core";
 
 const formatTime = (time: number) => {
   return moment(time).format("DD/MM/YYYY HH:mm");
@@ -31,6 +30,15 @@ const colors: { [key: string]: string } = {
   Pending: "",
 };
 
+const useStyles = makeStyles({
+  link: {
+    color: "#000",
+    "&:hover": {
+      color: "#fff",
+    },
+  },
+});
+
 const ProposalRow = (props: {
   block: number;
   createdAt: number;
@@ -89,22 +97,19 @@ const ProposalRow = (props: {
   const time = formatTime(props.startTime + createdAt * 6000);
   const created = blocks ? `${age} at ${time}` : time;
   const left = `${period - blocks} / ${period} blocks left (${percent}%)`;
-
+  const classes = useStyles();
   return (
     <div className="d-flex flex-column">
       <div className="d-flex flex-wrap justify-content-left text-left mt-3">
-        <OverlayTrigger
+        <InfoTooltip
           placement="right"
-          overlay={
-            <Tooltip id={`votes-${id}`}>
-              <VotesTooltip
-                votesByAccount={props.votesByAccount}
-                votes={votes}
-              />
-            </Tooltip>
+          id={`votes-${id}`}
+          title={
+            <VotesTooltip votesByAccount={props.votesByAccount} votes={votes} />
           }
         >
           <div
+            style={{ borderRadius: "4px" }}
             className={`col-3 col-md-1 text-center p-2 border border-${color}`}
           >
             <b>{result}</b>
@@ -112,40 +117,39 @@ const ProposalRow = (props: {
               <VotesBubbles votes={votes} />
             </div>
           </div>
-        </OverlayTrigger>
+        </InfoTooltip>
 
         <div className="col-9 col-md-3 text-left">
-          <OverlayTrigger
-            placement={"bottom"}
-            overlay={
-              <Tooltip id={`overlay-${author}`} className="member-tooltip">
-                <MemberOverlay
-                  handle={author}
-                  members={members}
-                  councils={props.councils}
-                  proposals={props.proposals}
-                  posts={props.forumPosts}
-                  startTime={props.startTime}
-                  validators={props.validators}
-                />
-              </Tooltip>
+          <InfoTooltip
+            placement="bottom"
+            id={`overlay-${author}`}
+            title={
+              <MemberOverlay
+                handle={author}
+                members={members}
+                councils={props.councils}
+                proposals={props.proposals}
+                posts={props.forumPosts}
+                startTime={props.startTime}
+                validators={props.validators}
+              />
             }
           >
             <div>
-              <Link to={`/members/${author}`}> {author}</Link>
+              <Link className={classes.link} href={`/members/${author}`}>
+                {" "}
+                {author}
+              </Link>
             </div>
-          </OverlayTrigger>
-
-          <OverlayTrigger
-            key={id}
-            placement="bottom"
-            overlay={<Tooltip id={String(id)}>{description}</Tooltip>}
-          >
+          </InfoTooltip>
+          <InfoTooltip placement="bottom" key={id} title={description}>
             <b>
-              <Link to={`/proposals/${id}`}>{title}</Link>
+              <Link className={classes.link} href={`/proposals/${id}`}>
+                {title}
+              </Link>
               <Posts posts={props.posts} />
             </b>
-          </OverlayTrigger>
+          </InfoTooltip>
           <Detail detail={detail} type={type} />
         </div>
 

+ 166 - 106
src/components/Routes/index.tsx

@@ -1,116 +1,176 @@
-import { Switch, Route } from "react-router-dom";
+import {Switch, Route, Link} from "react-router-dom";
 import {
-  Calendar,
-  Councils,
-  Curation,
-  Dashboard,
-  Forum,
-  Member,
-  Members,
-  Mint,
-  Proposals,
-  Proposal,
-  Timeline,
-  Tokenomics,
-  Validators,
-  Spending,
-  Storage,
-  Transactions,
-  Bounties,
-  Burners,
-  ValidatorReport,
+    Calendar,
+    Councils,
+    Curation,
+    Dashboard,
+    Forum,
+    Member,
+    Members,
+    Mint,
+    Proposals,
+    Proposal,
+    Timeline,
+    Tokenomics,
+    Validators,
+    Spending,
+    Storage,
+    Transactions,
+    Bounties,
+    Burners,
+    ValidatorReport,
 } from "..";
-
-import { IState } from "../../types";
+import React from 'react'
+import {AppBar, Button, makeStyles, Toolbar} from '@material-ui/core'
+import {MemoryRouter} from 'react-router'
+import joystream from '../../joystream.svg'
+import {IState} from "../../types";
 
 interface IProps extends IState {
-  toggleStar: (a: string) => void;
-  toggleFooter: () => void;
+    toggleStar: (a: string) => void;
+    toggleFooter: () => void;
 }
 
+const useStyles = makeStyles({
+    appBar: {
+        flexDirection: 'row',
+        backgroundColor: '#000',
+        color: '#fff',
+    },
+    appLogo: {
+        display: 'block',
+        width: '150px',
+        color: '#4038ff',
+    },
+    navbar: {
+        '&:hover': {
+            backgroundColor: '#4038ff',
+        },
+    },
+})
+
 const Routes = (props: IProps) => {
-  const { reports, tokenomics } = props;
-  return (
-    <Switch>
-      <Route
-        path="/tokenomics"
-        render={(routeprops) => (
-          <Tokenomics
-            {...routeprops}
-            reports={reports}
-            tokenomics={tokenomics}
-          />
-        )}
-      />
-      <Route
-        path="/spending"
-        render={(routeprops) => <Spending {...routeprops} {...props} />}
-      />
-      <Route
-        path="/proposals/:id"
-        render={(routeprops) => <Proposal {...routeprops} {...props} />}
-      />
-      <Route path="/proposals" render={() => <Proposals {...props} />} />
-      <Route
-        path="/councils"
-        render={(routeprops) => <Councils {...routeprops} {...props} />}
-      />
-      <Route
-        path="/curation"
-        render={(routeprops) => <Curation {...routeprops} {...props} />}
-      />
-      <Route
-        path="/forum/threads/:thread"
-        render={(routeprops) => <Forum {...routeprops} {...props} />}
-      />
-      <Route path="/forum" render={() => <Forum {...props} />} />
-      <Route
-        path="/mint"
-        render={(routeprops) => <Mint {...routeprops} {...props} />}
-      />
-      <Route
-        path="/members/:handle"
-        render={(routeprops) => <Member {...routeprops} {...props} />}
-      />
-      <Route
-        path="/members"
-        render={(routeprops) => <Members {...routeprops} {...props} />}
-      />
-      <Route
-        path="/calendar"
-        render={(routeprops) => <Calendar {...routeprops} {...props} />}
-      />
-      <Route
-        path="/timeline"
-        render={(routeprops) => <Timeline {...routeprops} {...props} />}
-      />
-      <Route
-        path="/validators"
-        render={(routeprops) => <Validators {...routeprops} {...props} />}
-      />
-      <Route
-        path="/validator-report"
-        render={(routeprops) => <ValidatorReport {...routeprops} {...props} />}
-      />
-      <Route
-        path="/storage"
-        render={(routeprops) => <Storage {...routeprops} {...props} />}
-      />
-      <Route
-        path="/transactions"
-        render={(routeprops) => <Transactions {...routeprops} {...props} />}
-      />
-      <Route
-        path="/bounties"
-        render={(routeprops) => <Bounties {...routeprops} {...props} />}
-      />
-      <Route
-        path="/burners"
-        render={(routeprops) => <Burners {...routeprops} {...props} />}
-      />
-      <Route path="/" render={() => <Dashboard {...props} />} />
-    </Switch>
-  );
+    const classes = useStyles()
+    const navBarLink = {color: '#fff'}
+    const {reports, tokenomics} = props;
+    return (
+        <div>
+            <MemoryRouter>
+                <div style={{flexGrow: 1}}>
+                    <AppBar position='static' className={classes.appBar}>
+                        <Toolbar style={{paddingLeft: '12px', backgroundColor: '#000'}}>
+                            <Button color='inherit' component={Link} to='/'>
+                                <img src={joystream} className={classes.appLogo} alt='Joystream logo'/>
+                            </Button>
+                            <Button className={classes.navbar} style={navBarLink} component={Link}
+                                    to='/dashboard'>Dashboard</Button>
+                            <Button className={classes.navbar} style={navBarLink} component={Link}
+                                    to='/calendar'>Calendar</Button>
+                            <Button className={classes.navbar} style={navBarLink} component={Link}
+                                    to='/timeline'>Timeline</Button>
+                            <Button className={classes.navbar} style={navBarLink} component={Link}
+                                    to='/tokenomics'>Reports</Button>
+                            <Button className={classes.navbar} style={navBarLink} component={Link}
+                                    to='/validators'>Validators</Button>
+                            <Button className={classes.navbar} style={navBarLink} component={Link}
+                                    to='/validator-report'>Validator Report</Button>
+                            <Button className={classes.navbar} style={navBarLink} component={Link}
+                                    to='/storage'>Storage</Button>
+                            <Button className={classes.navbar} style={navBarLink} component={Link}
+                                    to='/spending'>Spending</Button>
+                            <Button className={classes.navbar} style={navBarLink} component={Link}
+                                    to='/transactions'>Transfers</Button>
+                            <Button className={classes.navbar} style={navBarLink} component={Link}
+                                    to='/burners'>Top Burners</Button>
+                            <Button className={classes.navbar} style={navBarLink} component={Link}
+                                    to='/mint'>Toolbox</Button>
+                        </Toolbar>
+                    </AppBar>
+                </div>
+                <div>
+                    <Switch>
+                        <Route
+                            path="/tokenomics"
+                            render={(routeprops) => (
+                                <Tokenomics
+                                    {...routeprops}
+                                    reports={reports}
+                                    tokenomics={tokenomics}
+                                />
+                            )}
+                        />
+                        <Route
+                            path="/spending"
+                            render={(routeprops) => <Spending {...routeprops} {...props} />}
+                        />
+                        <Route
+                            path="/proposals/:id"
+                            render={(routeprops) => <Proposal {...routeprops} {...props} />}
+                        />
+                        <Route path="/proposals" render={() => <Proposals {...props} />}/>
+                        <Route
+                            path="/councils"
+                            render={(routeprops) => <Councils {...routeprops} {...props} />}
+                        />
+                        <Route
+                            path="/curation"
+                            render={(routeprops) => <Curation {...routeprops} {...props} />}
+                        />
+                        <Route
+                            path="/forum/threads/:thread"
+                            render={(routeprops) => <Forum {...routeprops} {...props} />}
+                        />
+                        <Route path="/forum" render={() => <Forum {...props} />}/>
+                        <Route
+                            path="/mint"
+                            render={(routeprops) => <Mint {...routeprops} {...props} />}
+                        />
+                        <Route
+                            path="/members/:handle"
+                            render={(routeprops) => <Member {...routeprops} {...props} />}
+                        />
+                        <Route
+                            path="/members"
+                            render={(routeprops) => <Members {...routeprops} {...props} />}
+                        />
+                        <Route
+                            path="/calendar"
+                            render={(routeprops) => <Calendar {...routeprops} {...props} />}
+                        />
+                        <Route
+                            path="/timeline"
+                            render={(routeprops) => <Timeline {...routeprops} {...props} />}
+                        />
+                        <Route
+                            path="/validators"
+                            render={(routeprops) => <Validators {...routeprops} {...props} />}
+                        />
+                        <Route
+                            path="/validator-report"
+                            render={(routeprops) => <ValidatorReport {...routeprops} {...props} />}
+                        />
+                        <Route
+                            path="/storage"
+                            render={(routeprops) => <Storage {...routeprops} {...props} />}
+                        />
+                        <Route
+                            path="/transactions"
+                            render={(routeprops) => <Transactions {...routeprops} {...props} />}
+                        />
+                        <Route
+                            path="/bounties"
+                            render={(routeprops) => <Bounties {...routeprops} {...props} />}
+                        />
+                        <Route
+                            path="/burners"
+                            render={(routeprops) => <Burners {...routeprops} {...props} />}
+                        />
+                        <Route path="/" render={() => <Dashboard {...props} />}/>
+                    </Switch>
+                </div>
+            </MemoryRouter>
+        </div>
+    );
 };
 
 export default Routes;

+ 21 - 0
src/components/Tooltip/index.tsx

@@ -0,0 +1,21 @@
+import Tooltip, { TooltipProps } from "@material-ui/core/Tooltip";
+import React from "react";
+import { makeStyles, Theme } from "@material-ui/core";
+
+const useStylesBootstrap = makeStyles((theme: Theme) => ({
+  arrow: {
+    color: theme.palette.common.black,
+  },
+  tooltip: {
+    border: "1px solid #fff",
+    backgroundColor: "#4038FF",
+    fontSize: '0.8rem'
+  },
+}));
+
+const InfoTooltip = (props: TooltipProps) => {
+  const classes = useStylesBootstrap();
+  return <Tooltip classes={classes} {...props} />;
+};
+
+export default InfoTooltip;

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

@@ -52,10 +52,7 @@ class Transactions extends React.Component<IProps, IState> {
         <h3>Transactions</h3>
         <Form>
           <Form.Group className="mb-3" controlId="formBasicEmail">
-            <Form.Control type="address" placeholder="Wallet account" onChange={(e) => this.accountTxFilterChanged(e.target.value)} value={address}/>
-            <Form.Text className="text-muted">
-              48 character string starting with 5
-            </Form.Text>
+            <Form.Control type="address" placeholder="Wallet account(48 character string starting with 5)" onChange={(e) => this.accountTxFilterChanged(e.target.value)} value={address}/>
           </Form.Group>
         </Form>
         <>

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

@@ -1,5 +1,5 @@
+import { Table } from "@material-ui/core";
 import React from "react";
-import { Table } from "react-bootstrap";
 import { Link } from "react-router-dom";
 import { Stakes } from "../../types";
 
@@ -37,7 +37,7 @@ const MinMax = (props: {
   const validatorReward = reward ? reward / validators.length : 0;
 
   return (
-    <Table className="bg-secondary">
+    <Table style={{ textAlign: "center", backgroundColor: "#4038FF", color: "#fff" }}>
       <tbody>
         <tr>
           <td {...name}>Validators</td>

+ 111 - 79
src/components/Validators/index.tsx

@@ -1,9 +1,8 @@
-import React, { Component } from "react";
+import React, { useState } from "react";
 import { Button } from "react-bootstrap";
 import Stats from "./MinMax";
 import Validator from "./Validator";
 import Waiting from "./Waiting";
-import { Back } from "..";
 import Loading from "../Loading";
 
 import {
@@ -17,6 +16,16 @@ import {
   Status,
   Tokenomics,
 } from "../../types";
+import {
+  AppBar,
+  createStyles,
+  Grid,
+  makeStyles,
+  Paper,
+  Theme,
+  Toolbar,
+  Typography,
+} from "@material-ui/core";
 
 interface IProps {
   councils: Seat[][];
@@ -36,34 +45,32 @@ interface IProps {
   status: Status;
 }
 
-interface IState {
-  sortBy: string;
-  showValidators: boolean;
-  showWaiting: boolean;
-}
+const useStyles = makeStyles((theme: Theme) =>
+  createStyles({
+    root: {
+      flexGrow: 1,
+      backgroundColor: "#4038FF",
+    },
+    title: {
+      textAlign: "left",
+      flexGrow: 1,
+    },
+  })
+);
+
+const Validators = (iProps: IProps) => {
+  const [props] = useState(iProps);
+  const [sortBy, setSortBy] = useState("totalStake");
+
+  const [showWaiting, setShowWaiting] = useState(false);
+  const [showValidators, setShowValidators] = useState(false);
 
-class Validators extends Component<IProps, IState> {
-  constructor(props: IProps) {
-    super(props);
-    this.state = {
-      sortBy: "totalStake",
-      showWaiting: false,
-      showValidators: false,
-    };
-    this.setSortBy = this.setSortBy.bind(this);
-  }
-
-  toggleValidators() {
-    this.setState({ showValidators: !this.state.showValidators });
-  }
-  toggleWaiting() {
-    this.setState({ showWaiting: !this.state.showWaiting });
-  }
-  setSortBy(sortBy: string) {
-    this.setState({ sortBy });
-  }
-  sortBy(field: string, validators: string[]) {
-    const { stakes, rewardPoints } = this.props;
+  const toggleValidators = () => setShowValidators((prev) => !prev);
+
+  const toggleWaiting = () => setShowWaiting((prev) => !prev);
+
+  const sortValidators = (field: string, validators: string[]) => {
+    const { stakes, rewardPoints } = props;
     try {
       if (field === "points" || !stakes)
         return validators.sort((a, b) =>
@@ -107,45 +114,69 @@ class Validators extends Component<IProps, IState> {
     }
 
     return validators;
-  }
-
-  render() {
-    const {
-      hideBackButton,
-      history,
-      councils,
-      handles,
-      members,
-      posts,
-      proposals,
-      validators,
-      nominators,
-      stashes,
-      stars,
-      rewardPoints,
-      status,
-      stakes,
-      tokenomics,
-    } = this.props;
-
-    if (!status || !status.block) return <Loading />;
-
-    const { lastReward, block, era, startTime } = status;
-    const { sortBy, showWaiting, showValidators } = this.state;
-
-    const issued = tokenomics ? Number(tokenomics.totalIssuance) : 0;
-    const price = tokenomics ? Number(tokenomics.price) : 0;
-
-    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 <Loading target="validators" />;
-
-    return (
-      <div className="box w-100 m-3 mx-5 p-3">
-        <Back hide={hideBackButton} history={history} />
-        <h3 onClick={() => this.toggleValidators()}>Validator Stats</h3>
+  };
+
+  const {
+    councils,
+    handles,
+    members,
+    posts,
+    proposals,
+    validators,
+    nominators,
+    stashes,
+    stars,
+    rewardPoints,
+    status,
+    stakes,
+    tokenomics,
+  } = props;
+
+  const classes = useStyles();
+
+  if (!status || !status.block) return <Loading gridSize={12}/>;
+
+  const { lastReward, block, era, startTime } = status;
+
+  const issued = tokenomics ? Number(tokenomics.totalIssuance) : 0;
+  const price = tokenomics ? Number(tokenomics.price) : 0;
+
+  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 <Loading gridSize={12} target="validators" />;
+
+  return (
+    <Grid
+      style={{
+        textAlign: "center",
+        backgroundColor: "#000",
+        color: "#fff",
+      }}
+      item
+      lg={12}
+    >
+      <Paper
+        style={{
+          textAlign: "center",
+          backgroundColor: "#4038FF",
+          color: "#fff",
+          height: 600,
+          overflow: "auto",
+        }}
+      >
+        <AppBar className={classes.root} position="static">
+          <Toolbar>
+            <Typography
+              className={classes.title}
+              variant="h6"
+              onClick={() => toggleValidators()}
+            >
+              Validator Stats
+            </Typography>
+          </Toolbar>
+        </AppBar>
 
         <Stats
           block={block}
@@ -160,12 +191,12 @@ class Validators extends Component<IProps, IState> {
         />
 
         <div className="d-flex flex-column">
-          {this.sortBy(sortBy, starred).map((v) => (
+          {sortValidators(sortBy, starred).map((v) => (
             <Validator
               key={v}
-              sortBy={this.setSortBy}
+              sortBy={setSortBy}
               starred={stars[v] ? `teal` : undefined}
-              toggleStar={this.props.toggleStar}
+              toggleStar={props.toggleStar}
               startTime={startTime}
               validator={v}
               reward={lastReward / validators.length}
@@ -180,17 +211,17 @@ class Validators extends Component<IProps, IState> {
             />
           ))}
 
-          <Button variant="secondary" onClick={() => this.toggleValidators()}>
+          <Button onClick={() => toggleValidators()}>
             Toggle {unstarred.length} validators
           </Button>
 
           {showValidators &&
-            this.sortBy(sortBy, unstarred).map((v) => (
+            sortValidators(sortBy, unstarred).map((v) => (
               <Validator
                 key={v}
-                sortBy={this.setSortBy}
+                sortBy={sortBy}
                 starred={stars[v] ? `teal` : undefined}
-                toggleStar={this.props.toggleStar}
+                toggleStar={props.toggleStar}
                 startTime={startTime}
                 validator={v}
                 reward={lastReward / validators.length}
@@ -206,6 +237,7 @@ class Validators extends Component<IProps, IState> {
             ))}
 
           <Waiting
+            toggleWaiting={toggleWaiting}
             show={showWaiting}
             waiting={waiting}
             posts={posts}
@@ -214,9 +246,9 @@ class Validators extends Component<IProps, IState> {
             handles={handles}
           />
         </div>
-      </div>
-    );
-  }
-}
+      </Paper>
+    </Grid>
+  );
+};
 
 export default Validators;

+ 2 - 2
src/components/Votes.tsx

@@ -34,7 +34,7 @@ export const VoteNowButton = (props: { show: boolean; url: string }) => {
   if (!show) return <div />;
 
   return (
-    <Button variant="danger">
+    <Button variant="success">
       <a href={url}>Vote</a>
     </Button>
   );
@@ -51,7 +51,7 @@ const VoteBubble = (props: {
   if (!count) return <span />;
 
   return (
-    <Button className="btn-sm m-0" variant={voteStyles[voteKeys[vote]]}>
+    <Button className="btn-sm m-1" variant={voteStyles[voteKeys[vote]]}>
       {count} {detailed && vote}
     </Button>
   );

+ 0 - 1
src/components/index.ts

@@ -2,7 +2,6 @@ export { default as Back } from "./Back";
 export { default as Bounties } from "./Bounties";
 export { default as Calendar } from "./Calendar";
 export { default as Routes } from "./Routes";
-export { default as Council } from "./Council";
 export { default as Councils } from "./Councils";
 export { default as Curation } from "./Curation";
 export { default as Dashboard } from "./Dashboard";

+ 8 - 8
src/index.css

@@ -3,8 +3,8 @@ body,
 #root,
 .App {
   height: 100%;
-  background-color: #343a40;
-  font-size: 0.8rem;
+  background-color: #000;
+  font-size: 1rem;
 }
 
 body {
@@ -25,7 +25,7 @@ a:visited {
 a:active,
 a:hover {
   -color: #fff !important;
-  -background: teal;
+  -background: #4038FF;
   -padding: 1px;
 }
 
@@ -34,7 +34,7 @@ select {
 }
 
 .select div:hover {
-  background-color: teal !important;
+  background-color: #4038FF !important;
 }
 
 ::-moz-selection,
@@ -42,7 +42,7 @@ select {
 .select-selected,
 .select-items div:hover {
   color: white;
-  background-color: teal !important;
+  background-color: #4038FF !important;
 }
 
 h3 {
@@ -53,13 +53,13 @@ h3 {
   color: white;
   margin: 5px;
   padding: 15px;
-  background-color: teal;
+  background-color: #4038FF;
   text-align: center;
 }
 .box a:hover,
 .box a:active {
   color: #fff !important;
-  -background: teal;
+  -background: #4038FF;
 }
 
 table td {
@@ -256,7 +256,7 @@ table td {
 }
 
 .waiting-validators .list-group-item {
-  background-color: teal !important;
+  background-color: #4038FF !important;
 }
 
 .connecting {

Разлика између датотеке није приказан због своје велике величине
+ 2 - 1
src/joystream.svg


+ 1 - 1
tsconfig.json

@@ -1,6 +1,6 @@
 {
   "compilerOptions": {
-    "target": "es5",
+    "target": "es6",
     "lib": [
       "dom",
       "dom.iterable",

Неке датотеке нису приказане због велике количине промена