Skip to content

Commit

Permalink
Merge pull request #105 from hansmrtn/develop
Browse files Browse the repository at this point in the history
UI Bugfixes and minor updates
  • Loading branch information
hmrtn authored Jan 14, 2022
2 parents 0d894ed + e4d23c6 commit 85595e5
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 96 deletions.
3 changes: 3 additions & 0 deletions packages/react-app/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
HStack,
Flex,
Spacer,
Text,
IconButton,
Select,
Menu,
Expand Down Expand Up @@ -423,7 +424,9 @@ function App(props) {
const networkSelect = (
<Menu closeOnSelect={false}>
<MenuButton as={Button} variant="ghost">
<Text fontSize="sm">{targetNetwork.name}
<ChevronDownIcon />
</Text>
</MenuButton>
<MenuList>
<MenuOptionGroup value={targetNetwork.name} title="select network" type="radio">
Expand Down
145 changes: 72 additions & 73 deletions packages/react-app/src/routes/party/Party.jsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
import React, { useEffect, useState } from "react";
import React, { useEffect, useState, useMemo } from "react";
import {
Button,
Box,
Center,
Menu,
MenuOptionGroup,
MenuButton,
MenuList,
MenuItemOption,
Spacer,
MenuItem,
Text,
HStack,
} from "@chakra-ui/react";
import { ArrowBackIcon, ChevronDownIcon } from "@chakra-ui/icons";
import { useParams, useHistory } from "react-router-dom";
Expand All @@ -37,87 +34,95 @@ export default function Party({
const [canVote, setCanVote] = useState(false);
const [isParticipant, setIsParticipant] = useState(false);
const [distribution, setDistribution] = useState();
const [strategy, setStrategy] = useState("linear");
const [strategy, setStrategy] = useState("quadratic");
const [isPaid, setIsPaid] = useState(false);

const db = new MongoDBController();

useEffect(async () => {
db.fetchParty(id)
.then(res => {
setPartyData(res.data);
const votes = res?.data?.ballots?.filter(b => b.data.ballot.address === address);
const participating = res.data.participants.includes(address);
setAccountVoteData(votes);
setCanVote(votes.length === 0 && participating ? true : false);
setIsParticipant(participating);
setIsPaid(res.data.receipts.length > 0);
})
.catch(err => {
console.log(err);
});
}, [id]);
const party = await db.fetchParty(id);
const votes = party.data.ballots.filter(b => b.data.ballot.address === address);
const participating = party.data.participants.includes(address);
setAccountVoteData(votes);
setCanVote(votes.length === 0 && participating);
setPartyData(party.data);
}, []);

// Calculate percent distribution from submitted ballots
const calcDistribution = () => {
if (partyData && partyData.ballots && partyData.ballots.length > 0) {
const votes = partyData.ballots.map(b => JSON.parse(b.data.ballot.votes.replace(/[ \n\r]/g, "")));
let sum = 0;
let processed = [];
// let strategy = partyData.config.strategy;
if (!strategy || strategy === "") {
strategy = "linear";
console.log("Reverted to linear strategy");
// Calculate percent distribution from submitted ballots and memo table
const calculateDistribution = () => {
const votes = partyData.ballots.map(b => JSON.parse(b.data.ballot.votes.replace(/[ \n\r]/g, "")));
let sum = 0;
let processed = [];
let result;
for (let i = 0; i < partyData.candidates.length; i++) {
const candidate = partyData.candidates[i];
switch (strategy.toLowerCase()) {
default:
result = votes.reduce((total, vote) => vote[candidate] + total, 0);
break;
case "linear":
result = votes.reduce((total, vote) => vote[candidate] + total, 0);
break;
case "quadratic":
result = votes.reduce((total, vote) => vote[candidate] ** 0.5 + total, 0);
break;
}
for (let i = 0; i < partyData.candidates.length; i++) {
const candidate = partyData.candidates[i];
// Strategy handling
// TODO: Switch statement
if (strategy === "linear") {
let c = votes.reduce((total, vote) => vote[candidate] + total, 0);
sum += c;
processed.push({ address: candidate, reduced: c });
} else if (strategy === "quadratic") {
let c = votes.reduce((total, vote) => vote[candidate] ** 0.5 + total, 0);
sum += c;
processed.push({ address: candidate, reduced: c });
}
}
let final = [];
for (let i = 0; i < partyData.candidates.length; i++) {
const candidate = partyData.candidates[i];
final.push({ address: candidate, score: processed[i].reduced / sum });
}
setDistribution(final);
sum += result;
processed.push({ address: candidate, reduced: result });
}
};
let final = [];
for (let i = 0; i < partyData.candidates.length; i++) {
const candidate = partyData.candidates[i];
final.push({ address: candidate, score: processed[i].reduced / sum });
}
return final;
}

// Cache the calculated distribution and table component
const cachedViewTable = useMemo(() => {
try {
const dist = calculateDistribution();
setDistribution(dist);
return (
<ViewTable
partyData={partyData}
mainnetProvider={mainnetProvider}
votesData={accountVoteData}
distribution={dist}
strategy={strategy}
/>
);
} catch {
return null;
}
}, [partyData, strategy]);

const StrategySelect = () => {
return (
<Menu closeOnSelect={false}>
<Menu>
<MenuButton as={Button} variant="link" rightIcon={<ChevronDownIcon />}>
{strategy}
</MenuButton>
<MenuList>
<MenuOptionGroup title="select strategy" type="radio" onChange={e => setStrategy(e)}>
<MenuItemOption key="linear-select" value="linear">
Linear
</MenuItemOption>
,
<MenuItemOption key="quadratic-select" value="quadratic">
Quadratic
</MenuItemOption>
</MenuOptionGroup>
<MenuItem
onClick={() => {
setStrategy("quadratic");
}}
>
Quadratic
</MenuItem>
<MenuItem
onClick={() => {
setStrategy("linear");
}}
>
Linear
</MenuItem>
</MenuList>
</Menu>
);
};

// Calculate the distribution on load
useEffect(() => {
calcDistribution();
}, [partyData, strategy]);

return (
<Box>
<Button
Expand Down Expand Up @@ -165,13 +170,7 @@ export default function Party({
<Text pr="3">Strategy:</Text>
<StrategySelect />
</Center>
<ViewTable
partyData={partyData}
mainnetProvider={mainnetProvider}
votesData={accountVoteData}
distribution={distribution}
strategy={strategy}
/>
{cachedViewTable}
</Box>
)}
<Distribute
Expand Down
42 changes: 19 additions & 23 deletions packages/react-app/src/routes/party/components/ViewTable.jsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,24 @@
import {
Box,
HStack,
Text,
Spacer,
Center,
Divider,
Table,
Thead,
Tbody,
Tfoot,
Tr,
Th,
Td,
TableCaption,
} from "@chakra-ui/react";
import React, { useState, useMemo, useEffect } from "react";
import React, { useState, useMemo } from "react";
import AddressChakra from "../../../components/AddressChakra";

export const ViewTable = ({ partyData, mainnetProvider, votesData, distribution, strategy }) => {
const [castVotes, setCastVotes] = useState(null);
const [currentDist, setCurrentDist] = useState(null);
const [castVotes, setCastVotes] = useState(false);
const [isLoading, setIsLoading] = useState(true);

useEffect(() => {
const scores = votesData && votesData[0] && JSON.parse(votesData[0].data.ballot.votes);
setCastVotes(scores);
const dist =
distribution && distribution.reduce((obj, item) => Object.assign(obj, { [item.address]: item.score }), {});
setCurrentDist(dist);
}, [votesData, distribution]);

const candidateRows = useMemo(() => {
const ballotVotes = votesData && votesData[0] && JSON.parse(votesData[0].data.ballot.votes);
const dist = distribution && distribution.reduce((obj, item) => Object.assign(obj, { [item.address]: item.score }), {});
const row =
partyData &&
partyData.candidates &&
Expand All @@ -39,33 +27,41 @@ export const ViewTable = ({ partyData, mainnetProvider, votesData, distribution,
<Tbody key={`view-row-${d}`}>
<Tr>
<Td>
<AddressChakra
<AddressChakra
address={d}
ensProvider={mainnetProvider}
// blockExplorer={blockExplorer}
/>
</Td>
<Td>
<Center>{castVotes && castVotes[d]}</Center>
<Center>{ballotVotes && ballotVotes[d]}</Center>
</Td>
<Td>
<Center>{currentDist && (currentDist[d] * 100).toFixed(0)}%</Center>
<Center>{dist && (dist[d] * 100).toFixed(2)}%</Center>
</Td>
</Tr>
</Tbody>
);
});

setCastVotes(ballotVotes);
return row;
}, [partyData, castVotes, distribution]);
}, [partyData, votesData, distribution, strategy]);

return (
<Box>
<Table borderWidth="1px">
<Thead>
<Tr>
<Th><Center>Address</Center></Th>
<Th><Center>{castVotes ? "Your Ballot" : " "}</Center></Th>
<Th><Center>{`Score (${strategy})`}</Center></Th>
<Th>
<Center>Address</Center>
</Th>
<Th>
<Center>{castVotes ? "Your Ballot" : ""}</Center>
</Th>
<Th>
<Center>{`Score (${strategy})`}</Center>
</Th>
</Tr>
</Thead>
{candidateRows}
Expand Down

0 comments on commit 85595e5

Please sign in to comment.