|
@@ -1,7 +1,8 @@
|
|
|
import React from "react";
|
|
|
-import { Button, OverlayTrigger, Tooltip } from "react-bootstrap";
|
|
|
+import { OverlayTrigger, Tooltip } from "react-bootstrap";
|
|
|
import Row from "./Row";
|
|
|
-
|
|
|
+import NavBar from "./NavBar";
|
|
|
+import Types from "./Types";
|
|
|
import { Member, ProposalDetail, ProposalPost } from "../../types";
|
|
|
|
|
|
interface IProps {
|
|
@@ -16,14 +17,22 @@ interface IState {
|
|
|
key: any;
|
|
|
asc: boolean;
|
|
|
hidden: string[];
|
|
|
+ showTypes: boolean;
|
|
|
}
|
|
|
|
|
|
class ProposalTable extends React.Component<IProps, IState> {
|
|
|
constructor(props: IProps) {
|
|
|
super(props);
|
|
|
- this.state = { key: "id", asc: false, hidden: [], author: "All" };
|
|
|
+ this.state = {
|
|
|
+ key: "id",
|
|
|
+ asc: false,
|
|
|
+ hidden: [],
|
|
|
+ author: "All",
|
|
|
+ showTypes: false,
|
|
|
+ };
|
|
|
this.selectAuthor = this.selectAuthor.bind(this);
|
|
|
this.toggleHide = this.toggleHide.bind(this);
|
|
|
+ this.toggleShowTypes = this.toggleShowTypes.bind(this);
|
|
|
}
|
|
|
|
|
|
setKey(key: string) {
|
|
@@ -31,6 +40,9 @@ class ProposalTable extends React.Component<IProps, IState> {
|
|
|
else this.setState({ key });
|
|
|
}
|
|
|
|
|
|
+ toggleShowTypes() {
|
|
|
+ this.setState({ showTypes: !this.state.showTypes });
|
|
|
+ }
|
|
|
toggleHide(type: string) {
|
|
|
const isHidden = this.state.hidden.includes(type);
|
|
|
const hidden = isHidden
|
|
@@ -39,7 +51,7 @@ class ProposalTable extends React.Component<IProps, IState> {
|
|
|
this.setState({ hidden });
|
|
|
}
|
|
|
selectAuthor(event: any) {
|
|
|
- this.setState({ author: event.target.value });
|
|
|
+ this.setState({ author: event.target.text });
|
|
|
}
|
|
|
|
|
|
filterProposals() {
|
|
@@ -62,7 +74,7 @@ class ProposalTable extends React.Component<IProps, IState> {
|
|
|
}
|
|
|
|
|
|
render() {
|
|
|
- const { avgDays, avgHours, block, members, proposalPosts } = this.props;
|
|
|
+ const { block, members, proposalPosts } = this.props;
|
|
|
const { author, hidden } = this.state;
|
|
|
|
|
|
// proposal types
|
|
@@ -76,32 +88,39 @@ class ProposalTable extends React.Component<IProps, IState> {
|
|
|
const proposals = this.sortProposals(this.filterProposals());
|
|
|
const approved = proposals.filter((p) => p.result === "Approved").length;
|
|
|
|
|
|
+ // calculate finalization times
|
|
|
+ const durations: any = proposals.map((p) =>
|
|
|
+ p.finalizedAt
|
|
|
+ ? p.finalizedAt - p.createdAt
|
|
|
+ : (block && block - p.createdAt) || 0
|
|
|
+ );
|
|
|
+
|
|
|
+ // calculate mean voting duration
|
|
|
+ const avgBlocks =
|
|
|
+ durations.reduce((a: number, b: number) => a + b) / durations.length;
|
|
|
+ const avgDays = Math.floor(avgBlocks / 14400);
|
|
|
+ const avgHours = Math.floor((avgBlocks - avgDays * 14400) / 600);
|
|
|
+
|
|
|
return (
|
|
|
- <div className="h-100 overflow-hidden">
|
|
|
- <div className="">
|
|
|
- {Object.keys(types).map((type) => (
|
|
|
- <Button
|
|
|
- key={type}
|
|
|
- variant={hidden.includes(type) ? "outline-dark" : "dark"}
|
|
|
- className="btn-sm m-1"
|
|
|
- onClick={() => this.toggleHide(type)}
|
|
|
- >
|
|
|
- {type}
|
|
|
- </Button>
|
|
|
- ))}
|
|
|
- </div>
|
|
|
+ <div className="h-100 overflow-hidden bg-light">
|
|
|
+ <NavBar
|
|
|
+ author={author}
|
|
|
+ authors={authors}
|
|
|
+ selectAuthor={this.selectAuthor}
|
|
|
+ toggleShowTypes={this.toggleShowTypes}
|
|
|
+ />
|
|
|
+
|
|
|
+ <Types
|
|
|
+ hidden={hidden}
|
|
|
+ show={this.state.showTypes}
|
|
|
+ toggleHide={this.toggleHide}
|
|
|
+ types={types}
|
|
|
+ />
|
|
|
|
|
|
<div className="d-flex flex-row justify-content-between p-2 bg-dark text-light text-left font-weight-bold">
|
|
|
<div onClick={() => this.setKey("id")}>ID</div>
|
|
|
<div className="col-2" onClick={() => this.setKey("author")}>
|
|
|
Author
|
|
|
- <br />
|
|
|
- <select value={author} onChange={this.selectAuthor}>
|
|
|
- <option>All</option>
|
|
|
- {Object.keys(authors).map((author: string) => (
|
|
|
- <option key={author}>{author}</option>
|
|
|
- ))}
|
|
|
- </select>
|
|
|
</div>
|
|
|
<div className="col-3" onClick={() => this.setKey("description")}>
|
|
|
Description
|
|
@@ -125,8 +144,7 @@ class ProposalTable extends React.Component<IProps, IState> {
|
|
|
</div>
|
|
|
<div className="col-2">
|
|
|
Voting Duration
|
|
|
- <br />
|
|
|
- Average: {avgDays ? `${avgDays}d` : ""}
|
|
|
+ <br />∅ {avgDays ? `${avgDays}d` : ""}
|
|
|
{avgHours ? `${avgHours}h` : ""}
|
|
|
</div>
|
|
|
<div className="col-1" onClick={() => this.setKey("createdAt")}>
|
|
@@ -139,7 +157,7 @@ class ProposalTable extends React.Component<IProps, IState> {
|
|
|
|
|
|
<div
|
|
|
className="d-flex flex-column overflow-auto p-2"
|
|
|
- style={{ height: `75%` }}
|
|
|
+ style={{ height: `85%` }}
|
|
|
>
|
|
|
{proposals.map((p) => (
|
|
|
<Row
|