Browse Source

Refactor some logic to "getExtendedStatus" & voting section display conditions

Leszek Wiesner 4 years ago
parent
commit
a6a2968b46

+ 8 - 21
packages/joy-proposals/src/Proposal/Details.tsx

@@ -2,32 +2,19 @@ import React from "react";
 import { Item, Image, Header } from "semantic-ui-react";
 import { ParsedProposal } from "../runtime/transport";
 import { IdentityIcon } from '@polkadot/react-components';
-import { BlockNumber } from '@polkadot/types/interfaces';
+import { ExtendedProposalStatus } from "./ProposalDetails";
 
 type DetailsProps = {
   proposal: ParsedProposal,
-  bestNumber?: BlockNumber
+  extendedStatus: ExtendedProposalStatus,
 };
 
 export default function Details({
-  proposal: { type, createdAt, createdAtBlock, proposer, status, parameters },
-  bestNumber
+  proposal,
+  extendedStatus
 }: DetailsProps) {
-  const statusStr = Object.keys(status)[0];
-  const isActive = statusStr === 'Active';
-  const { votingPeriod, gracePeriod } = parameters;
-
-  const blockAge = bestNumber ? (bestNumber.toNumber() - createdAtBlock) : 0;
-  const substage = isActive && (
-    votingPeriod - blockAge  > 0 ?
-      'Voting period'
-      : 'Grace period'
-  );
-  const expiresIn = substage && (
-    substage === 'Voting period' ?
-      votingPeriod - blockAge
-      : (gracePeriod + votingPeriod) - blockAge
-  )
+  const { type, createdAt, proposer } = proposal;
+  const { statusStr, substage, expiresIn } = extendedStatus;
   return (
     <Item.Group className="details-container">
       <Item>
@@ -52,7 +39,7 @@ export default function Details({
           <Header as="h4">{ statusStr }</Header>
         </Item.Content>
       </Item>
-      { isActive && (
+      { (substage !== null) && (
         <Item>
           <Item.Content>
             <Item.Extra>Substage:</Item.Extra>
@@ -60,7 +47,7 @@ export default function Details({
           </Item.Content>
         </Item>
       ) }
-      { isActive && (
+      { (expiresIn !== null) && (
         <Item>
           <Item.Content>
             <Item.Extra>Expires in:</Item.Extra>

+ 41 - 2
packages/joy-proposals/src/Proposal/ProposalDetails.tsx

@@ -15,6 +15,39 @@ import { BlockNumber } from '@polkadot/types/interfaces'
 import { MemberId } from "@joystream/types/members";
 import { Seat } from "@joystream/types/";
 
+export type ExtendedProposalStatus = {
+  statusStr: string, // TODO: Active / Finalized?
+  substage: 'Voting period' | 'Grace period' | null,
+  expiresIn: number | null,
+}
+
+export function getExtendedStatus(proposal: ParsedProposal, bestNumber: BlockNumber | undefined): ExtendedProposalStatus {
+  const statusStr = Object.keys(proposal.status)[0];
+  const isActive = statusStr === 'Active';
+  const { votingPeriod, gracePeriod } = proposal.parameters;
+
+  const blockAge = bestNumber ? (bestNumber.toNumber() - proposal.createdAtBlock) : 0;
+  const substage =
+    (
+      isActive && (
+      votingPeriod - blockAge  > 0 ?
+        'Voting period'
+        : 'Grace period'
+      )
+    ) || null;
+  const expiresIn = substage && (
+    substage === 'Voting period' ?
+      votingPeriod - blockAge
+      : (gracePeriod + votingPeriod) - blockAge
+  )
+
+  return {
+    statusStr,
+    substage,
+    expiresIn
+  }
+}
+
 
 type ProposalDetailsProps = MyAccountProps & {
   proposal: ParsedProposal,
@@ -25,16 +58,22 @@ type ProposalDetailsProps = MyAccountProps & {
 
 function ProposalDetails({ proposal, proposalId, myAddress, myMemberId, iAmMember, council, bestNumber }: ProposalDetailsProps) {
   const iAmCouncilMember = iAmMember && council && council.some(seat => seat.member.toString() === myAddress);
+  const extendedStatus = getExtendedStatus(proposal, bestNumber);
   return (
     <Container className="Proposal">
-      <Details proposal={proposal} bestNumber={bestNumber}/>
+      <Details proposal={proposal} extendedStatus={extendedStatus}/>
       <Body
         type={ proposal.type }
         title={ proposal.title }
         description={ proposal.description }
         params={ proposal.details }
         />
-      { iAmCouncilMember && <VotingSection proposalId={proposalId} memberId={ myMemberId as MemberId }/> }
+      { iAmCouncilMember && (
+        <VotingSection
+          proposalId={proposalId}
+          memberId={ myMemberId as MemberId }
+          isVotingPeriod={ extendedStatus.substage === 'Voting period' }/>
+      ) }
       {/* <Votes votes={votes} total={totalVotes} />  TODO: Implement */}
     </Container>
   );

+ 8 - 4
packages/joy-proposals/src/Proposal/ProposalPreview.tsx

@@ -1,14 +1,18 @@
 import React from "react";
 import { Header, Card } from "semantic-ui-react";
 import Details from "./Details";
-import { ParsedProposal } from "../runtime/transport"
+import { ParsedProposal } from "../runtime/transport";
+import { getExtendedStatus } from "./ProposalDetails";
+import { BlockNumber } from '@polkadot/types/interfaces';
 
 import "./Proposal.css";
 
 type ProposalPreviewProps = {
-  proposal: ParsedProposal
+  proposal: ParsedProposal,
+  bestNumber?: BlockNumber
 };
-export default function ProposalPreview({ proposal }: ProposalPreviewProps) {
+export default function ProposalPreview({ proposal, bestNumber }: ProposalPreviewProps) {
+  const extendedStatus = getExtendedStatus(proposal, bestNumber);
   return (
     <Card
       fluid
@@ -19,7 +23,7 @@ export default function ProposalPreview({ proposal }: ProposalPreviewProps) {
           <Header as="h1">{proposal.title}</Header>
         </Card.Header>
         <Card.Description>{proposal.description}</Card.Description>
-        <Details proposal={proposal} />
+        <Details proposal={proposal} extendedStatus={extendedStatus} />
       </Card.Content>
     </Card>
   );

+ 13 - 2
packages/joy-proposals/src/Proposal/ProposalPreviewList.tsx

@@ -7,8 +7,10 @@ import { useTransport, ParsedProposal } from "../runtime";
 import { usePromise } from "../utils";
 import Loading from "./Loading";
 import Error from "./Error";
+import { withCalls } from '@polkadot/react-api';
+import { BlockNumber } from '@polkadot/types/interfaces';
 
-type ProposalFilter = "all" | "active" | "withdrawn" | "approved" | "rejected" | "slashed";
+// type ProposalFilter = "all" | "active" | "withdrawn" | "approved" | "rejected" | "slashed";
 
 // function filterProposals(filter: ProposalFilter, proposals: ParsedProposal[]) {
 //   if (filter === "all") {
@@ -33,7 +35,11 @@ type ProposalFilter = "all" | "active" | "withdrawn" | "approved" | "rejected" |
 //   return proposalsMap;
 // }
 
-export default function ProposalPreviewList() {
+type ProposalPreviewListProps = {
+  bestNumber?: BlockNumber
+};
+
+function ProposalPreviewList({ bestNumber }: ProposalPreviewListProps) {
   const transport = useTransport();
 
   const [proposals, error, loading] = usePromise<ParsedProposal[]>(transport.proposals(), []);
@@ -85,9 +91,14 @@ export default function ProposalPreviewList() {
           <ProposalPreview
             key={`${prop.title}-${idx}`}
             proposal={prop}
+            bestNumber={ bestNumber }
           />
         ))}
       </Card.Group>
     </Container>
   );
 }
+
+export default withCalls<ProposalPreviewListProps>(
+  ['derive.chain.bestNumber', { propName: 'bestNumber' }]
+)(ProposalPreviewList);

+ 6 - 1
packages/joy-proposals/src/Proposal/VotingSection.tsx

@@ -9,7 +9,7 @@ import { useTransport } from "../runtime";
 import { VoteKind } from '@joystream/types/proposals';
 import { usePromise } from "../utils";
 
-// TODO: joy-types (there is something similar already I think)
+// TODO: joy-types (there's something similar already I think)
 const voteKinds = ["Approve", "Slash", "Abstain", "Reject"] as const;
 type VoteKindStr = "Approve" | "Slash" | "Abstain" | "Reject";
 
@@ -46,11 +46,13 @@ function VoteButton({ voteKind, proposalId, memberId, onSuccess }: VoteButtonPro
 type VotingSectionProps = {
   memberId: MemberId,
   proposalId: ProposalId,
+  isVotingPeriod: boolean,
 };
 
 export default function VotingSection({
   memberId,
   proposalId,
+  isVotingPeriod
 }: VotingSectionProps) {
   const transport = useTransport();
   const [voted, setVoted] = useState<VoteKindStr | null >(null);
@@ -78,6 +80,9 @@ export default function VotingSection({
       </Message>
     );
   }
+  else if (!isVotingPeriod) {
+    return null;
+  }
 
   return (
     <>