Browse Source

Types in most components have been adjusted. Some bugs corrected and
some variables got a bit stronger typing. The build errors went down to
18 from 40.

Gamaranto 4 years ago
parent
commit
f2d5415368

+ 5 - 5
packages/joy-proposals/src/Proposal/Body.tsx

@@ -2,11 +2,11 @@ import React from "react";
 import { Card, Header, Item } from "semantic-ui-react";
 
 type BodyProps = {
-  title?: string;
-  description?: string;
-  params?: {
-    tokensAmount?: number;
-    destinationAccount?: string;
+  title: string;
+  description: string;
+  params: {
+    tokensAmount: number;
+    destinationAccount: string;
   };
 };
 

+ 10 - 10
packages/joy-proposals/src/Proposal/Details.tsx

@@ -1,16 +1,16 @@
-import React from 'react';
-import { Item, Image, Header } from 'semantic-ui-react';
+import React from "react";
+import { Item, Image, Header } from "semantic-ui-react";
 
-import { Member } from './ProposalDetails';
+import { Member } from "./ProposalDetails";
 
 type DetailsProps = {
   // FIXME: Stage, substage and type all should be an enum
-  stage?: string;
-  substage?: string;
-  expiresIn?: number;
-  type?: string;
-  createdBy?: Member;
-  createdAt?: string;
+  stage: string;
+  substage: string;
+  expiresIn: number;
+  type: string;
+  createdBy: Member;
+  createdAt: string;
 };
 
 export default function Details({ stage, substage, createdAt, createdBy, type, expiresIn }: DetailsProps) {
@@ -45,7 +45,7 @@ export default function Details({ stage, substage, createdAt, createdBy, type, e
       <Item>
         <Item.Content>
           <Item.Extra>Expires in:</Item.Extra>
-          <Header as="h4">{`${expiresIn.toLocaleString('en-US')} blocks`}</Header>
+          <Header as="h4">{`${expiresIn.toLocaleString("en-US")} blocks`}</Header>
         </Item.Content>
       </Item>
     </Item.Group>

+ 22 - 22
packages/joy-proposals/src/Proposal/ProposalDetails.tsx

@@ -9,8 +9,8 @@ import VotingSection from "./VotingSection";
 import "./Proposal.css";
 
 export type Member = {
-  name?: string;
-  avatar?: string;
+  name: string;
+  avatar: string;
 };
 
 export type VoteValue = "Approve" | "Slash" | "Abstain" | "Reject";
@@ -22,28 +22,28 @@ export type Vote = {
 };
 
 export type ProposalProps = {
-  title?: string;
-  description?: string;
-  finalized?: "approved" | "rejected" | "slashed" | "withdrawn";
-  params?: {
-    tokensAmount?: number;
-    destinationAccount?: string;
+  title: string;
+  description: string;
+  finalized: "approved" | "rejected" | "slashed" | "withdrawn";
+  params: {
+    tokensAmount: number;
+    destinationAccount: string;
   };
-  votes?: Vote[];
-  totalVotes?: number;
-  details?: {
+  votes: Vote[];
+  totalVotes: number;
+  details: {
     // FIXME: Stage, substage and type all should be an enum
-    stage?: string;
-    substage?: string;
-    expiresIn?: number;
-    type?: string;
-    createdBy?: Member;
-    createdAt?: string;
+    stage: string;
+    substage: string;
+    expiresIn: number;
+    type: string;
+    createdBy: Member;
+    createdAt: string;
   };
-  onVote?: (vote: VoteValue) => void;
-  vote?: {
-    hasVoted?: boolean;
-    value?: VoteValue;
+  onVote: (vote: VoteValue) => void;
+  vote: {
+    hasVoted: boolean;
+    value: VoteValue;
   };
 };
 
@@ -62,7 +62,7 @@ export default function ProposalDetails({
     <Container className="Proposal">
       <Details {...details} />
       <Body title={title} description={description} params={params} />
-      <VotingSection onVote={onVote} hasVoted={hasVoted} value={value} />
+      <VotingSection onVote={onVote} hasVoted={hasVoted} value={value || "Approve"} />
       <Votes votes={votes} total={totalVotes} />
     </Container>
   );

+ 66 - 66
packages/joy-proposals/src/Proposal/ProposalPreviewList.tsx

@@ -1,77 +1,77 @@
-import React, { useState } from 'react';
-import { Card, Menu, Container } from 'semantic-ui-react';
+import React, { useState } from "react";
+import { Card, Menu, Container } from "semantic-ui-react";
 
-import { ProposalProps } from './ProposalDetails';
-import ProposalPreview from './ProposalPreview';
+import { ProposalProps } from "./ProposalDetails";
+import ProposalPreview from "./ProposalPreview";
 
-type ProposalFilter = 'all' | 'active' | 'withdrawn' | 'approved' | 'rejected' | 'slashed';
+type ProposalFilter = "all" | "active" | "withdrawn" | "approved" | "rejected" | "slashed";
 
 export default function ProposalPreviewList({ proposals }: { proposals: ProposalProps[] }) {
-    const [activeFilter, setActiveFilter] = useState<ProposalFilter>('all');
-    const proposalsMap = new Map();
+  const [activeFilter, setActiveFilter] = useState<ProposalFilter>("all");
+  const proposalsMap = new Map();
 
-    proposalsMap.set('all', proposals);
-    proposalsMap.set('withdrawn', filterProposals('withdrawn', proposals));
-    proposalsMap.set('active', filterProposals('withdrawn', proposals));
-    proposalsMap.set('approved', filterProposals('approved', proposals));
-    proposalsMap.set('rejected', filterProposals('rejected', proposals));
-    proposalsMap.set('slashed', filterProposals('slashed', proposals));
+  proposalsMap.set("all", proposals);
+  proposalsMap.set("withdrawn", filterProposals("withdrawn", proposals));
+  proposalsMap.set("active", filterProposals("withdrawn", proposals));
+  proposalsMap.set("approved", filterProposals("approved", proposals));
+  proposalsMap.set("rejected", filterProposals("rejected", proposals));
+  proposalsMap.set("slashed", filterProposals("slashed", proposals));
 
-    return (
-        <Container className="Proposal">
-            <Menu tabular className="list-menu">
-                <Menu.Item
-                    name={`all - ${proposalsMap.get('withdrawn').length} `}
-                    active={activeFilter === 'all'}
-                    onClick={() => setActiveFilter('all')}
-                />
-                <Menu.Item
-                    name={`withdrawn (${proposalsMap.get('withdrawn').length})`}
-                    active={activeFilter === 'withdrawn'}
-                    onClick={() => setActiveFilter('withdrawn')}
-                />
-                <Menu.Item
-                    name={`active (${proposalsMap.get('active').length})`}
-                    active={activeFilter === 'active'}
-                    onClick={() => setActiveFilter('active')}
-                />
-                <Menu.Item
-                    name={`approved (${proposalsMap.get('approved').length})`}
-                    active={activeFilter === 'approved'}
-                    onClick={() => setActiveFilter('approved')}
-                />
-                <Menu.Item
-                    name={`rejected (${proposalsMap.get('rejected').length})`}
-                    active={activeFilter === 'rejected'}
-                    onClick={() => setActiveFilter('rejected')}
-                />
-                <Menu.Item
-                    name={`slashed (${proposalsMap.get('slashed').length})`}
-                    active={activeFilter === 'slashed'}
-                    onClick={() => setActiveFilter('slashed')}
-                />
-            </Menu>
+  return (
+    <Container className="Proposal">
+      <Menu tabular className="list-menu">
+        <Menu.Item
+          name={`all - ${proposalsMap.get("withdrawn").length} `}
+          active={activeFilter === "all"}
+          onClick={() => setActiveFilter("all")}
+        />
+        <Menu.Item
+          name={`withdrawn (${proposalsMap.get("withdrawn").length})`}
+          active={activeFilter === "withdrawn"}
+          onClick={() => setActiveFilter("withdrawn")}
+        />
+        <Menu.Item
+          name={`active (${proposalsMap.get("active").length})`}
+          active={activeFilter === "active"}
+          onClick={() => setActiveFilter("active")}
+        />
+        <Menu.Item
+          name={`approved (${proposalsMap.get("approved").length})`}
+          active={activeFilter === "approved"}
+          onClick={() => setActiveFilter("approved")}
+        />
+        <Menu.Item
+          name={`rejected (${proposalsMap.get("rejected").length})`}
+          active={activeFilter === "rejected"}
+          onClick={() => setActiveFilter("rejected")}
+        />
+        <Menu.Item
+          name={`slashed (${proposalsMap.get("slashed").length})`}
+          active={activeFilter === "slashed"}
+          onClick={() => setActiveFilter("slashed")}
+        />
+      </Menu>
 
-            <Card.Group>
-                {proposalsMap.get(activeFilter).map((prop, idx) => (
-                    <ProposalPreview
-                        key={`${prop.title}-${idx}`}
-                        title={prop.title}
-                        description={prop.description}
-                        details={prop.details}
-                    />
-                ))}
-            </Card.Group>
-        </Container>
-    );
+      <Card.Group>
+        {proposalsMap.get(activeFilter).map((prop: any, idx: number) => (
+          <ProposalPreview
+            key={`${prop.title}-${idx}`}
+            title={prop.title}
+            description={prop.description}
+            details={prop.details}
+          />
+        ))}
+      </Card.Group>
+    </Container>
+  );
 }
 
-function filterProposals(filter, proposals) {
-    if (filter === 'all') {
-        return proposals;
-    } else if (filter === 'active') {
-        return proposals.filter((prop: any) => prop.details.stage === 'active');
-    }
+function filterProposals(filter: ProposalFilter, proposals: ProposalProps[]) {
+  if (filter === "all") {
+    return proposals;
+  } else if (filter === "active") {
+    return proposals.filter((prop: any) => prop.details.stage === "active");
+  }
 
-    return proposals.filter((prop: any) => prop.finalized === filter);
+  return proposals.filter((prop: any) => prop.finalized === filter);
 }

+ 6 - 4
packages/joy-proposals/src/Proposal/Votes.tsx

@@ -1,8 +1,6 @@
 import React from "react";
 import { Header, Divider, Table, Image, Icon } from "semantic-ui-react";
 
-import Section from "@polkadot/joy-utils/Section";
-
 import { Vote } from "./ProposalDetails";
 import useVoteStyles from "./useVoteStyles";
 
@@ -13,7 +11,11 @@ type VotesProps = {
 
 export default function Votes({ votes, total }: VotesProps) {
   return (
-    <Section level={3} title={`All Votes: (${votes.length} / ${total})`}>
+    <>
+      <Header as h3>
+        All Votes: ({votes.length} / {total})
+      </Header>
+      <Divider />
       <Table basic="very">
         <Table.Body>
           {votes.map((vote, idx) => {
@@ -33,6 +35,6 @@ export default function Votes({ votes, total }: VotesProps) {
           })}
         </Table.Body>
       </Table>
-    </Section>
+    </>
   );
 }

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

@@ -2,14 +2,13 @@ import React from "react";
 
 import { Icon, Button, Message, Divider, Header } from "semantic-ui-react";
 
-import Section from "@polkadot/joy-utils/Section";
 import { VoteValue } from "./ProposalDetails";
 import useVoteStyles from "./useVoteStyles";
 
 type VotingSectionProps = {
-  onVote?: (vote: VoteValue) => void;
-  hasVoted?: boolean;
-  value?: VoteValue;
+  onVote: (vote: VoteValue) => void;
+  hasVoted: boolean;
+  value: VoteValue;
 };
 
 export default function VotingSection({ onVote, hasVoted, value }: VotingSectionProps) {
@@ -27,7 +26,9 @@ export default function VotingSection({ onVote, hasVoted, value }: VotingSection
   }
 
   return (
-    <Section level={3} title="Sumbit your vote">
+    <>
+      <Header as="h3">Sumbit your vote</Header>
+      <Divider />
       <Button color="green" icon labelPosition="left" onPress={() => onVote("Approve")}>
         <Icon name="smile" inverted />
         Approve
@@ -44,6 +45,6 @@ export default function VotingSection({ onVote, hasVoted, value }: VotingSection
         <Icon name="times" inverted />
         Slash
       </Button>
-    </Section>
+    </>
   );
 }

+ 7 - 3
packages/joy-proposals/src/Proposal/useVoteStyles.tsx

@@ -1,7 +1,11 @@
-export default function useVoteStyles(value) {
+import { SemanticCOLORS, SemanticICONS } from "semantic-ui-react";
+
+export default function useVoteStyles(
+  value: "Approve" | "Abstain" | "Reject" | "Slash"
+): { textColor: string; icon: SemanticICONS; color: SemanticCOLORS } {
   let textColor;
-  let icon;
-  let color;
+  let icon: SemanticICONS;
+  let color: SemanticCOLORS;
 
   switch (value) {
     case "Approve": {

+ 5 - 5
packages/joy-proposals/src/forms/EvictStorageProviderForm.tsx

@@ -3,7 +3,7 @@ import { FormikProps } from "formik";
 import { Form, Icon, Button, Dropdown, Label } from "semantic-ui-react";
 import { getFormErrorLabelsProps } from "./errorHandling";
 import * as Yup from "yup";
-import LabelWithHelp from './LabelWithHelp';
+import LabelWithHelp from "./LabelWithHelp";
 
 import { withFormContainer } from "./FormContainer";
 import "./forms.css";
@@ -24,7 +24,7 @@ function EvictStorageProviderForm(props: EvictStorageProviderProps & FormikProps
     <div className="Forms">
       <Form className="proposal-form" onSubmit={handleSubmit}>
         <Form.Field error={Boolean(errorLabelsProps.title)}>
-          <LabelWithHelp text="Title" help="The title of your proposal"/>
+          <LabelWithHelp text="Title" help="The title of your proposal" />
           <Form.Input
             onChange={handleChange}
             name="title"
@@ -33,7 +33,7 @@ function EvictStorageProviderForm(props: EvictStorageProviderProps & FormikProps
           />
         </Form.Field>
         <Form.Field error={Boolean(errorLabelsProps.rationale)}>
-          <LabelWithHelp text="Rationale" help="The rationale behind your proposal"/>
+          <LabelWithHelp text="Rationale" help="The rationale behind your proposal" />
           <Form.TextArea
             onChange={handleChange}
             name="rationale"
@@ -42,7 +42,7 @@ function EvictStorageProviderForm(props: EvictStorageProviderProps & FormikProps
           />
         </Form.Field>
         <Form.Field error={Boolean(errorLabelsProps.storageProvider)}>
-          <LabelWithHelp text="Storage provider" help="The storage provider you propose to evict"/>
+          <LabelWithHelp text="Storage provider" help="The storage provider you propose to evict" />
           <Dropdown
             clearable
             name="storageProvider"
@@ -85,7 +85,7 @@ export default withFormContainer<OuterFormProps, FormValues>({
     rationale: Yup.string().required("Rationale is required!"),
     storageProvider: Yup.string().required("Select a storage provider!")
   }),
-  handleSubmit: (values, { setSubmitting, resetForm }) => {
+  handleSubmit: (values: FormValues, { setSubmitting, resetForm }: { [k: string]: any }) => {
     setTimeout(() => {
       alert(JSON.stringify(values, null, 2));
       resetForm({});

+ 69 - 51
packages/joy-proposals/src/forms/FileDropdown.tsx

@@ -1,14 +1,14 @@
 import React, { useState } from "react";
 import { FormikProps } from "formik";
 import { Icon, Loader } from "semantic-ui-react";
-import Dropzone from 'react-dropzone';
+import Dropzone from "react-dropzone";
 
 enum Status {
-  Accepted = 'accepted',
-  Rejected = 'rejected',
-  Active = 'active',
-  Parsing = 'parsing',
-  Default = 'default'
+  Accepted = "accepted",
+  Rejected = "rejected",
+  Active = "active",
+  Parsing = "parsing",
+  Default = "default"
 }
 
 const determineStatus = (
@@ -24,90 +24,108 @@ const determineStatus = (
   if (isDragActive) return Status.Active;
 
   return Status.Default;
-}
+};
 
 // Get color by status (imporant to use #FFFFFF format, so we can easily swicth the opacity!)
-const getStatusColor = (status:Status): string => {
-  switch(status) {
-    case Status.Accepted: return '#00DBB0';
-    case Status.Rejected: return '#FF3861';
+const getStatusColor = (status: Status): string => {
+  switch (status) {
+    case Status.Accepted:
+      return "#00DBB0";
+    case Status.Rejected:
+      return "#FF3861";
     case Status.Active:
     case Status.Parsing:
-      return '#000000';
-    default: return '#333333';
+      return "#000000";
+    default:
+      return "#333333";
   }
-}
+};
 
-const dropdownDivStyle = (status:Status): React.CSSProperties => {
-  let mainColor = getStatusColor(status);
+const dropdownDivStyle = (status: Status): React.CSSProperties => {
+  const mainColor = getStatusColor(status);
 
   return {
-    border: `1px solid ${ mainColor + '30' }`,
-    borderRadius: '3px',
-    padding: '1.5em',
+    border: `1px solid ${mainColor + "30"}`,
+    borderRadius: "3px",
+    padding: "1.5em",
     color: mainColor,
-    fontWeight: 'bold',
-    transition: 'color 0.5s, border-color 0.5s'
+    fontWeight: "bold",
+    transition: "color 0.5s, border-color 0.5s"
   };
-}
+};
 
 const dropdownIconStyle = (): React.CSSProperties => {
   return {
-    marginRight: '0.5em',
+    marginRight: "0.5em",
     opacity: 0.5
   };
-}
+};
 
 const innerSpanStyle = (): React.CSSProperties => {
   return {
-    display: 'flex',
-    alignItems: 'center'
+    display: "flex",
+    alignItems: "center"
   };
-}
+};
 
 // Here we define a way of coverting the file into string for Formik purposes
 // This may change depnding on how we decide to actually send the data
-const parseFile = async (file: File): Promise<string> => {
-  return await file.text();
-}
+const parseFile = async (file: any): Promise<string> => {
+  const text = await file.text();
+  return text;
+};
 
 type FileDropdownProps<FormValuesT> = {
-  error: string | undefined,
-  name: keyof FormValuesT & string,
-  setFieldValue: FormikProps<FormValuesT>["setFieldValue"],
-  acceptedFormats: string | string[],
-  defaultText: string
-}
+  error: string | undefined;
+  name: keyof FormValuesT & string;
+  setFieldValue: FormikProps<FormValuesT>["setFieldValue"];
+  acceptedFormats: string | string[];
+  defaultText: string;
+};
 
 export default function FileDropdown<ValuesT = {}>(props: FileDropdownProps<ValuesT>) {
-  const [ parsing, setParsing ] = useState(false);
+  const [parsing, setParsing] = useState(false);
   const { error, name, setFieldValue, acceptedFormats, defaultText } = props;
   return (
     <Dropzone
-      onDropAccepted={ async(acceptedFiles) => {
+      onDropAccepted={async acceptedFiles => {
         setParsing(true);
-        const fileAsString:string = await parseFile(acceptedFiles[0]);
+        const fileAsString: string = await parseFile(acceptedFiles[0]);
         setFieldValue(name, fileAsString, true);
         setParsing(false);
-      } }
+      }}
       multiple={false}
       accept={acceptedFormats}
-      >
-      {({getRootProps, getInputProps, acceptedFiles, rejectedFiles, isDragActive }) => {
+    >
+      {({ getRootProps, getInputProps, acceptedFiles, rejectedFiles, isDragActive }) => {
         const status = determineStatus(acceptedFiles, rejectedFiles, error, isDragActive, parsing);
         return (
           <section>
             <div {...getRootProps({ style: dropdownDivStyle(status) })}>
-              <input {...getInputProps()}/>
+              <input {...getInputProps()} />
               {
-                <span style={ innerSpanStyle() }>
-                    <Icon name="cloud upload" size="huge" style={ dropdownIconStyle() }/>
-                    <p>
-                      { status === Status.Parsing && <><Loader style={{marginRight: '0.5em'}} size="small" inline active/> Uploading...</> }
-                      { status === Status.Rejected && (<>{ error || 'This is not a correct file!'}<br/></>) }
-                      { status === Status.Accepted && (<>{`Current file: ${ acceptedFiles[0].name }`}<br/></>) }
-                      { status !== Status.Parsing && defaultText }
-                    </p>
+                <span style={innerSpanStyle()}>
+                  <Icon name="cloud upload" size="huge" style={dropdownIconStyle()} />
+                  <p>
+                    {status === Status.Parsing && (
+                      <>
+                        <Loader style={{ marginRight: "0.5em" }} size="small" inline active /> Uploading...
+                      </>
+                    )}
+                    {status === Status.Rejected && (
+                      <>
+                        {error || "This is not a correct file!"}
+                        <br />
+                      </>
+                    )}
+                    {status === Status.Accepted && (
+                      <>
+                        {`Current file: ${acceptedFiles[0].name}`}
+                        <br />
+                      </>
+                    )}
+                    {status !== Status.Parsing && defaultText}
+                  </p>
                 </span>
               }
             </div>

+ 2 - 2
packages/joy-proposals/src/forms/FormContainer.tsx

@@ -4,13 +4,13 @@ import { withFormik } from "formik";
 export function withFormContainer<MyFormProps, FormValues>(formikProps) {
   return function(InnerForm: React.ComponentType<any>) {
     return withFormik<MyFormProps, FormValues>(formikProps)(function(props) {
-      const handleBlur = (e, data: any) => {
+      const handleBlur = (e: React.FocusEvent<HTMLInputElement>, data: any): void => {
         if (data && data.name) {
           props.setFieldValue(data.name, data.value);
           props.setFieldTouched(data.name);
         }
       };
-      const handleChange = (e, data: any) => {
+      const handleChange = (e: React.ChangeEvent<HTMLInputElement>, data: any): void => {
         if (data && data.name) {
           props.setFieldValue(data.name, data.value);
           props.setFieldTouched(data.name);

+ 11 - 11
packages/joy-proposals/src/forms/SetCouncilParamsForm.tsx

@@ -32,7 +32,7 @@ function SetCouncilParamsForm(props: SetCouncilParamsProps & FormikProps<FormVal
     <div className="Forms">
       <Form className="proposal-form" onSubmit={handleSubmit}>
         <Form.Field error={Boolean(errorLabelsProps.title)}>
-          <LabelWithHelp text="Title" help="The title of your proposal"/>
+          <LabelWithHelp text="Title" help="The title of your proposal" />
           <Form.Input
             onChange={handleChange}
             name="title"
@@ -41,7 +41,7 @@ function SetCouncilParamsForm(props: SetCouncilParamsProps & FormikProps<FormVal
           />
         </Form.Field>
         <Form.Field error={Boolean(errorLabelsProps.rationale)}>
-          <LabelWithHelp text="Rationale" help="The rationale behind your proposal"/>
+          <LabelWithHelp text="Rationale" help="The rationale behind your proposal" />
           <Form.TextArea
             onChange={handleChange}
             name="rationale"
@@ -54,7 +54,7 @@ function SetCouncilParamsForm(props: SetCouncilParamsProps & FormikProps<FormVal
 
         <Form.Group widths="equal" style={{ marginBottom: "8rem" }}>
           <Form.Field error={Boolean(errorLabelsProps.announcingPeriod)}>
-            <LabelWithHelp text="Announcing Period" help="Announcing period in days"/>
+            <LabelWithHelp text="Announcing Period" help="Announcing period in days" />
             <Form.Input
               fluid
               onChange={handleChange}
@@ -64,7 +64,7 @@ function SetCouncilParamsForm(props: SetCouncilParamsProps & FormikProps<FormVal
             />
           </Form.Field>
           <Form.Field error={Boolean(errorLabelsProps.votingPeriod)}>
-            <LabelWithHelp text="Voting Period" help="Voting period in days"/>
+            <LabelWithHelp text="Voting Period" help="Voting period in days" />
             <Form.Input
               fluid
               onChange={handleChange}
@@ -74,7 +74,7 @@ function SetCouncilParamsForm(props: SetCouncilParamsProps & FormikProps<FormVal
             />
           </Form.Field>
           <Form.Field error={Boolean(errorLabelsProps.revealingPeriod)}>
-            <LabelWithHelp text="Revealing Period" help="Revealing period in days"/>
+            <LabelWithHelp text="Revealing Period" help="Revealing period in days" />
             <Form.Input
               fluid
               onChange={handleChange}
@@ -84,7 +84,7 @@ function SetCouncilParamsForm(props: SetCouncilParamsProps & FormikProps<FormVal
             />
           </Form.Field>
           <Form.Field error={Boolean(errorLabelsProps.minVotingStake)}>
-            <LabelWithHelp text="Minimum Voting Stake" help="The minimum voting stake"/>
+            <LabelWithHelp text="Minimum Voting Stake" help="The minimum voting stake" />
             <Form.Input
               fluid
               onChange={handleChange}
@@ -97,7 +97,7 @@ function SetCouncilParamsForm(props: SetCouncilParamsProps & FormikProps<FormVal
         <Divider horizontal>Council</Divider>
         <Form.Group widths="equal" style={{ marginBottom: "8rem" }}>
           <Form.Field error={Boolean(errorLabelsProps.minCouncilStake)}>
-            <LabelWithHelp text="Minimum Council Stake" help="The minimum council stake"/>
+            <LabelWithHelp text="Minimum Council Stake" help="The minimum council stake" />
             <Form.Input
               fluid
               onChange={handleChange}
@@ -107,7 +107,7 @@ function SetCouncilParamsForm(props: SetCouncilParamsProps & FormikProps<FormVal
             />
           </Form.Field>
           <Form.Field error={Boolean(errorLabelsProps.newTermDuration)}>
-            <LabelWithHelp text="New Term Duration" help="Duration of the new term in days"/>
+            <LabelWithHelp text="New Term Duration" help="Duration of the new term in days" />
             <Form.Input
               fluid
               onChange={handleChange}
@@ -117,7 +117,7 @@ function SetCouncilParamsForm(props: SetCouncilParamsProps & FormikProps<FormVal
             />
           </Form.Field>
           <Form.Field error={Boolean(errorLabelsProps.councilSize)}>
-            <LabelWithHelp text="Council Size" help="The size of the council (number of seats)"/>
+            <LabelWithHelp text="Council Size" help="The size of the council (number of seats)" />
             <Form.Input
               fluid
               onChange={handleChange}
@@ -127,7 +127,7 @@ function SetCouncilParamsForm(props: SetCouncilParamsProps & FormikProps<FormVal
             />
           </Form.Field>
           <Form.Field error={Boolean(errorLabelsProps.candidacyLimit)}>
-            <LabelWithHelp text="Candidacy Limit" help="How many times can a member candidate"/>
+            <LabelWithHelp text="Candidacy Limit" help="How many times can a member candidate" />
             <Form.Input
               fluid
               onChange={handleChange}
@@ -202,7 +202,7 @@ export default withFormContainer<OuterFormProps, FormValues>({
     candidacyLimit: Yup.number().required("All fields must be filled!"),
     councilSize: Yup.number().required("All fields must be filled!")
   }),
-  handleSubmit: (values, { setSubmitting }) => {
+  handleSubmit: (values: FormValues, { setSubmitting }) => {
     setTimeout(() => {
       alert(JSON.stringify(values, null, 2));
 

+ 44 - 41
packages/joy-proposals/src/forms/SetStorageRoleParamsForm.tsx

@@ -9,24 +9,24 @@ import {
   genericFormDefaultOptions,
   DefaultOuterFormProps,
   genericFormDefaultValues
-} from './GenericProposalForm';
-import FormField from './FormField';
+} from "./GenericProposalForm";
+import FormField from "./FormField";
 import { withFormContainer } from "./FormContainer";
 import "./forms.css";
 
 // All of those are strings, because that's how those values are beeing passed from inputs
 type FormValues = GenericFormValues & {
-  storageProviderCount: string,
-  storageProviderReward: string,
-  storageProviderStakingLimit: string,
+  storageProviderCount: string;
+  storageProviderReward: string;
+  storageProviderStakingLimit: string;
 };
 
-const defaultValues:FormValues = {
+const defaultValues: FormValues = {
   ...genericFormDefaultValues,
-  storageProviderCount: '',
-  storageProviderReward: '',
-  storageProviderStakingLimit: '',
-}
+  storageProviderCount: "",
+  storageProviderReward: "",
+  storageProviderStakingLimit: ""
+};
 
 type FormAdditionalProps = {};
 type SetStorageRoleParamsFormProps = FormikProps<FormValues> & FormAdditionalProps;
@@ -37,48 +37,51 @@ const SetStorageRoleParamsForm: React.FunctionComponent<SetStorageRoleParamsForm
   const errorLabelsProps = getFormErrorLabelsProps<FormValues>(errors, touched);
   return (
     <GenericProposalForm {...passProps}>
-        <Divider horizontal>Parameters</Divider>
-        <Form.Group widths="equal" style={{ marginBottom: "8rem" }}>
-          <FormField
-            label="Providers Count"
-            help="The proposed maximum number of active Storage Providers"
-            onChange={handleChange}
-            name="storageProviderCount"
-            placeholder="10"
-            error={errorLabelsProps.storageProviderCount}/>
-          <FormField
-            label="Provider Reward"
-            help="The proposed reward for Storage Providers (every x blocks)"
-            onChange={handleChange}
-            name="storageProviderReward"
-            placeholder="50"
-            error={errorLabelsProps.storageProviderReward}
-            unit={'tJOY'}/>
-          <FormField
-            label="Staking Limit"
-            help="The minimum stake for Storage Providers"
-            onChange={handleChange}
-            name="storageProviderStakingLimit"
-            placeholder="1500"
-            error={errorLabelsProps.storageProviderStakingLimit}
-            unit={'tJOY'}/>
-        </Form.Group>
+      <Divider horizontal>Parameters</Divider>
+      <Form.Group widths="equal" style={{ marginBottom: "8rem" }}>
+        <FormField
+          label="Providers Count"
+          help="The proposed maximum number of active Storage Providers"
+          onChange={handleChange}
+          name="storageProviderCount"
+          placeholder="10"
+          error={errorLabelsProps.storageProviderCount}
+        />
+        <FormField
+          label="Provider Reward"
+          help="The proposed reward for Storage Providers (every x blocks)"
+          onChange={handleChange}
+          name="storageProviderReward"
+          placeholder="50"
+          error={errorLabelsProps.storageProviderReward}
+          unit={"tJOY"}
+        />
+        <FormField
+          label="Staking Limit"
+          help="The minimum stake for Storage Providers"
+          onChange={handleChange}
+          name="storageProviderStakingLimit"
+          placeholder="1500"
+          error={errorLabelsProps.storageProviderStakingLimit}
+          unit={"tJOY"}
+        />
+      </Form.Group>
     </GenericProposalForm>
   );
-}
+};
 
 type OuterFormProps = DefaultOuterFormProps<FormAdditionalProps, FormValues>;
 
 export default withFormContainer<OuterFormProps, FormValues>({
-  mapPropsToValues: (props:OuterFormProps) => ({
+  mapPropsToValues: (props: OuterFormProps) => ({
     ...defaultValues,
     ...(props.initialData || {})
   }),
   validationSchema: Yup.object().shape({
     ...genericFormDefaultOptions.validationSchema,
-    storageProviderCount: Yup.number().required('Enter the provider count'),
-    storageProviderReward: Yup.number().required('Enter the reward'),
-    storageProviderStakingLimit: Yup.number().required('Enter the provider staking limit')
+    storageProviderCount: Yup.number().required("Enter the provider count"),
+    storageProviderReward: Yup.number().required("Enter the reward"),
+    storageProviderStakingLimit: Yup.number().required("Enter the provider staking limit")
   }),
   handleSubmit: genericFormDefaultOptions.handleSubmit,
   displayName: "SetStorageRoleParamsForm"

+ 12 - 11
packages/joy-proposals/src/forms/SignalForm.tsx

@@ -3,7 +3,7 @@ import { FormikProps } from "formik";
 import { Form, Icon, Button } from "semantic-ui-react";
 import { getFormErrorLabelsProps } from "./errorHandling";
 import * as Yup from "yup";
-import LabelWithHelp from './LabelWithHelp';
+import LabelWithHelp from "./LabelWithHelp";
 
 import { withFormContainer } from "./FormContainer";
 import "./forms.css";
@@ -22,30 +22,31 @@ function SignalForm(props: SignalFormProps & FormikProps<FormValues>) {
   return (
     <div className="Forms">
       <Form className="proposal-form" onSubmit={handleSubmit}>
-        <Form.Field error={ Boolean(errorLabelsProps.title) } >
-          <LabelWithHelp text="Title" help="The title of your proposal"/>
+        <Form.Field error={Boolean(errorLabelsProps.title)}>
+          <LabelWithHelp text="Title" help="The title of your proposal" />
           <Form.Input
             name="title"
             placeholder="Title for your awesome proposal..."
             onChange={handleChange}
-            error={errorLabelsProps.title}/>
+            error={errorLabelsProps.title}
+          />
         </Form.Field>
-        <Form.Field error={ Boolean(errorLabelsProps.description) }>
-          <LabelWithHelp text="Description" help="The extensive description of your proposal"/>
+        <Form.Field error={Boolean(errorLabelsProps.description)}>
+          <LabelWithHelp text="Description" help="The extensive description of your proposal" />
           <Form.TextArea
             onChange={handleChange}
             name="description"
             placeholder="What I would like to propose is..."
-            error={ errorLabelsProps.description }
+            error={errorLabelsProps.description}
           />
         </Form.Field>
-        <Form.Field error={ Boolean(errorLabelsProps.rationale) }>
-          <LabelWithHelp text="Rationale" help="The rationale behind your proposal"/>
+        <Form.Field error={Boolean(errorLabelsProps.rationale)}>
+          <LabelWithHelp text="Rationale" help="The rationale behind your proposal" />
           <Form.TextArea
             onChange={handleChange}
             name="rationale"
             placeholder="This proposal is awesome because..."
-            error={ errorLabelsProps.rationale }
+            error={errorLabelsProps.rationale}
           />
         </Form.Field>
         <div className="form-buttons">
@@ -79,7 +80,7 @@ export default withFormContainer<OuterFormProps, FormValues>({
     rationale: Yup.string().required("Rationale is required!"),
     description: Yup.string().required("Description is required!")
   }),
-  handleSubmit: (values, { setSubmitting }) => {
+  handleSubmit: (values: FormValues, { setSubmitting }) => {
     setTimeout(() => {
       alert(JSON.stringify(values, null, 2));
       setSubmitting(false);

+ 6 - 6
packages/joy-proposals/src/forms/SpendingProposalForm.tsx

@@ -3,7 +3,7 @@ import { FormikProps } from "formik";
 import { Form, Icon, Button, Dropdown, Label } from "semantic-ui-react";
 import { getFormErrorLabelsProps } from "./errorHandling";
 import * as Yup from "yup";
-import LabelWithHelp from './LabelWithHelp';
+import LabelWithHelp from "./LabelWithHelp";
 
 import { withFormContainer } from "./FormContainer";
 import "./forms.css";
@@ -26,7 +26,7 @@ function SpendingProposalForm(props: SpendingProposalProps & FormikProps<FormVal
     <div className="Forms">
       <Form className="proposal-form" onSubmit={handleSubmit}>
         <Form.Field error={Boolean(errorLabelsProps.title)}>
-          <LabelWithHelp text="Title" help="The title of your proposal"/>
+          <LabelWithHelp text="Title" help="The title of your proposal" />
           <Form.Input
             onChange={handleChange}
             name="title"
@@ -35,7 +35,7 @@ function SpendingProposalForm(props: SpendingProposalProps & FormikProps<FormVal
           />
         </Form.Field>
         <Form.Field error={Boolean(errorLabelsProps.rationale)}>
-          <LabelWithHelp text="Rationale" help="The rationale behind your proposal"/>
+          <LabelWithHelp text="Rationale" help="The rationale behind your proposal" />
           <Form.TextArea
             onChange={handleChange}
             name="rationale"
@@ -44,7 +44,7 @@ function SpendingProposalForm(props: SpendingProposalProps & FormikProps<FormVal
           />
         </Form.Field>
         <Form.Field error={Boolean(errorLabelsProps.tokens)}>
-          <LabelWithHelp text="Amount of tokens" help="The amount of tokens you propose to spend"/>
+          <LabelWithHelp text="Amount of tokens" help="The amount of tokens you propose to spend" />
           <Form.Input
             style={{ display: "flex", alignItems: "center" }}
             onChange={handleChange}
@@ -58,7 +58,7 @@ function SpendingProposalForm(props: SpendingProposalProps & FormikProps<FormVal
           </Form.Input>
         </Form.Field>
         <Form.Field error={Boolean(errorLabelsProps.destinationAccount)}>
-          <LabelWithHelp text="Destination account" help="The account you propose to send the tokens into"/>
+          <LabelWithHelp text="Destination account" help="The account you propose to send the tokens into" />
           <Dropdown
             clearable
             name="destinationAccount"
@@ -106,7 +106,7 @@ export default withFormContainer<OuterFormProps, FormValues>({
     tokens: Yup.number().required("You need to specify an amount of tokens."),
     destinationAccount: Yup.string().required("Select a destination account!")
   }),
-  handleSubmit: (values, { setSubmitting }) => {
+  handleSubmit: (values: FormValues, { setSubmitting }) => {
     setTimeout(() => {
       console.log(JSON.stringify(values, null, 2));
       setSubmitting(false);

+ 2 - 3
packages/joy-proposals/src/index.tsx

@@ -9,11 +9,10 @@ import "./index.css";
 
 import translate from "./translate";
 import NotDone from "./NotDone";
-import { ProposalPreviewList } from "./Proposal";
 
-type Props = AppProps & I18nProps & ApiProps;
+interface Props extends AppProps, I18nProps {}
 
-function App(props: Props) {
+function App(props: Props): React.ReactElement<Props> {
   const { t, basePath } = props;
 
   // TODO: Can use semantic here?

+ 27 - 27
packages/joy-proposals/src/stories/data/ProposalDetails.mock.ts

@@ -1,56 +1,56 @@
-import { ProposalProps } from '../../Proposal/ProposalDetails';
+import { ProposalProps } from "../../Proposal/ProposalDetails";
 
-const mockedProposal: ProposalProps = {
-  title: 'Send me some tokens for coffee',
+const mockedProposal: Partial<ProposalProps> = {
+  title: "Send me some tokens for coffee",
   description:
-    'Change the total reward across all validators in a given block. This is not the direct reward, but base reward for Pallet staking module. The minimum value must be greater than 450 tJOY based on current runtime. Also, coffee is getting expensive.',
+    "Change the total reward across all validators in a given block. This is not the direct reward, but base reward for Pallet staking module. The minimum value must be greater than 450 tJOY based on current runtime. Also, coffee is getting expensive.",
   params: {
     tokensAmount: 123.45,
-    destinationAccount: '0x4977CA8ADB17758aD2eac7220CE0C21D46421BB7'
+    destinationAccount: "0x4977CA8ADB17758aD2eac7220CE0C21D46421BB7"
   },
   details: {
     createdBy: {
-      name: 'Satoshi',
-      avatar: 'https://react.semantic-ui.com/images/avatar/large/steve.jpg'
+      name: "Satoshi",
+      avatar: "https://react.semantic-ui.com/images/avatar/large/steve.jpg"
     },
-    stage: 'Active',
-    createdAt: 'Mar 25, 2020 at 14:20',
-    type: 'Spending Proposal',
-    substage: 'Grace period',
+    stage: "Active",
+    createdAt: "Mar 25, 2020 at 14:20",
+    type: "Spending Proposal",
+    substage: "Grace period",
     expiresIn: 5678
   },
   votes: [
     {
-      value: 'Approve',
+      value: "Approve",
       by: {
-        name: 'Alice Ellison',
-        avatar: 'https://react.semantic-ui.com/images/avatar/large/jenny.jpg'
+        name: "Alice Ellison",
+        avatar: "https://react.semantic-ui.com/images/avatar/large/jenny.jpg"
       },
-      createdAt: 'Mar 25, 2020 at 14:20'
+      createdAt: "Mar 25, 2020 at 14:20"
     },
     {
-      value: 'Abstain',
+      value: "Abstain",
       by: {
-        name: 'Bob Bobston',
-        avatar: 'https://react.semantic-ui.com/images/avatar/large/daniel.jpg'
+        name: "Bob Bobston",
+        avatar: "https://react.semantic-ui.com/images/avatar/large/daniel.jpg"
       },
-      createdAt: 'Mar 24, 2020 at 12:11'
+      createdAt: "Mar 24, 2020 at 12:11"
     },
     {
-      value: 'Reject',
+      value: "Reject",
       by: {
-        name: 'Charlie Chen',
-        avatar: 'https://react.semantic-ui.com/images/avatar/large/matthew.png'
+        name: "Charlie Chen",
+        avatar: "https://react.semantic-ui.com/images/avatar/large/matthew.png"
       },
-      createdAt: 'Mar 23, 2020 at 11:34'
+      createdAt: "Mar 23, 2020 at 11:34"
     },
     {
-      value: 'Slash',
+      value: "Slash",
       by: {
-        name: 'David Douglas',
-        avatar: 'https://react.semantic-ui.com/images/avatar/large/elliot.jpg'
+        name: "David Douglas",
+        avatar: "https://react.semantic-ui.com/images/avatar/large/elliot.jpg"
       },
-      createdAt: 'Mar 21, 2020 at 9:54'
+      createdAt: "Mar 21, 2020 at 9:54"
     }
   ],
   totalVotes: 12

+ 15 - 14
packages/joy-proposals/src/stories/data/ProposalPreview.mock.ts

@@ -1,20 +1,21 @@
 import { ProposalProps } from "../../Proposal/ProposalDetails";
 
-const mockedProposalPreview: ProposalProps = {
-    title: "Send me some tokens for coffee",
-    description:
-        "Change the total reward across all validators in a given block. This is not the direct reward, but base reward for Pallet staking module. The minimum value must be greater than 450 tJOY based on current runtime. Also, coffee is getting expensive.",
+const mockedProposalPreview: Partial<ProposalProps> = {
+  title: "Send me some tokens for coffee",
+  description:
+    "Change the total reward across all validators in a given block. This is not the direct reward, but base reward for Pallet staking module. The minimum value must be greater than 450 tJOY based on current runtime. Also, coffee is getting expensive.",
 
-    details: {
-        createdBy: {
-            name: "Satoshi",
-            avatar: "https://react.semantic-ui.com/images/avatar/large/steve.jpg",
-        },
-        stage: "Active",
-        createdAt: "Mar 25, 2020 at 14:20",
-        type: "Spending Proposal",
-        expiresIn: 5678,
+  details: {
+    createdBy: {
+      name: "Satoshi",
+      avatar: "https://react.semantic-ui.com/images/avatar/large/steve.jpg"
     },
+    stage: "Active",
+    substage: "Active",
+    createdAt: "Mar 25, 2020 at 14:20",
+    type: "Spending Proposal",
+    expiresIn: 5678
+  }
 };
 
-export default mockedProposalPreview;
+export default mockedProposalPreview;

+ 86 - 81
packages/joy-proposals/src/stories/data/ProposalPreviewList.mock.ts

@@ -1,90 +1,95 @@
 import { ProposalProps } from "../../Proposal/ProposalDetails";
 
 const MockProposalPreviewList: ProposalProps[] = [
-    {
-        title: "Send me some tokens for coffee",
-        description:
-            "Change the total reward across all validators in a given block. This is not the direct reward, but base reward for Pallet staking module. The minimum value must be greater than 450 tJOY based on current runtime. Also, coffee is getting expensive.",
-        finalized: "approved",
-        details: {
-            createdBy: {
-                name: "Satoshi",
-                avatar: "https://react.semantic-ui.com/images/avatar/large/steve.jpg",
-            },
-            stage: "Finalized",
-            createdAt: "Mar 25, 2020 at 14:20",
-            type: "Spending Proposal",
-            expiresIn: 5678,
-        },
-    },
-    {
-        title: "Send me some tokens for coffee",
-        description:
-            "Change the total reward across all validators in a given block. This is not the direct reward, but base reward for Pallet staking module. The minimum value must be greater than 450 tJOY based on current runtime. Also, coffee is getting expensive.",
+  {
+    title: "Send me some tokens for coffee",
+    description:
+      "Change the total reward across all validators in a given block. This is not the direct reward, but base reward for Pallet staking module. The minimum value must be greater than 450 tJOY based on current runtime. Also, coffee is getting expensive.",
+    finalized: "approved",
+    details: {
+      createdBy: {
+        name: "Satoshi",
+        avatar: "https://react.semantic-ui.com/images/avatar/large/steve.jpg"
+      },
+      stage: "Finalized",
+      substage: "Grace Period",
+      createdAt: "Mar 25, 2020 at 14:20",
+      type: "Spending Proposal",
+      expiresIn: 5678
+    }
+  },
+  {
+    title: "Send me some tokens for coffee",
+    description:
+      "Change the total reward across all validators in a given block. This is not the direct reward, but base reward for Pallet staking module. The minimum value must be greater than 450 tJOY based on current runtime. Also, coffee is getting expensive.",
 
-        finalized: "slashed",
-        details: {
-            createdBy: {
-                name: "David Douglas",
-                avatar: "https://react.semantic-ui.com/images/avatar/large/elliot.jpg",
-            },
-            stage: "Active",
-            createdAt: "Mar 25, 2020 at 14:20",
-            type: "Spending Proposal",
-            expiresIn: 5678,
-        },
-    },
-    {
-        title: "Send me some tokens for coffee",
-        description:
-            "Change the total reward across all validators in a given block. This is not the direct reward, but base reward for Pallet staking module. The minimum value must be greater than 450 tJOY based on current runtime. Also, coffee is getting expensive.",
+    finalized: "slashed",
+    details: {
+      createdBy: {
+        name: "David Douglas",
+        avatar: "https://react.semantic-ui.com/images/avatar/large/elliot.jpg"
+      },
+      stage: "Active",
+      substage: "Grace Period",
+      createdAt: "Mar 25, 2020 at 14:20",
+      type: "Spending Proposal",
+      expiresIn: 5678
+    }
+  },
+  {
+    title: "Send me some tokens for coffee",
+    description:
+      "Change the total reward across all validators in a given block. This is not the direct reward, but base reward for Pallet staking module. The minimum value must be greater than 450 tJOY based on current runtime. Also, coffee is getting expensive.",
 
-        finalized: "approved",
-        details: {
-            createdBy: {
-                name: "David Douglas",
-                avatar: "https://react.semantic-ui.com/images/avatar/large/elliot.jpg",
-            },
-            stage: "Active",
-            createdAt: "Mar 25, 2020 at 14:20",
-            type: "Spending Proposal",
-            expiresIn: 5678,
-        },
-    },
-    {
-        title: "Send me some tokens for coffee",
-        description:
-            "Change the total reward across all validators in a given block. This is not the direct reward, but base reward for Pallet staking module. The minimum value must be greater than 450 tJOY based on current runtime. Also, coffee is getting expensive.",
+    finalized: "approved",
+    details: {
+      createdBy: {
+        name: "David Douglas",
+        avatar: "https://react.semantic-ui.com/images/avatar/large/elliot.jpg"
+      },
+      stage: "Active",
+      substage: "Grace Period",
+      createdAt: "Mar 25, 2020 at 14:20",
+      type: "Spending Proposal",
+      expiresIn: 5678
+    }
+  },
+  {
+    title: "Send me some tokens for coffee",
+    description:
+      "Change the total reward across all validators in a given block. This is not the direct reward, but base reward for Pallet staking module. The minimum value must be greater than 450 tJOY based on current runtime. Also, coffee is getting expensive.",
 
-        finalized: "approved",
-        details: {
-            createdBy: {
-                name: "David Douglas",
-                avatar: "https://react.semantic-ui.com/images/avatar/large/elliot.jpg",
-            },
-            stage: "Active",
-            createdAt: "Mar 25, 2020 at 14:20",
-            type: "Spending Proposal",
-            expiresIn: 5678,
-        },
-    },
-    {
-        title: "Send me some tokens for coffee",
-        description:
-            "Change the total reward across all validators in a given block. This is not the direct reward, but base reward for Pallet staking module. The minimum value must be greater than 450 tJOY based on current runtime. Also, coffee is getting expensive.",
+    finalized: "approved",
+    details: {
+      createdBy: {
+        name: "David Douglas",
+        avatar: "https://react.semantic-ui.com/images/avatar/large/elliot.jpg"
+      },
+      stage: "Active",
+      substage: "Grace Period",
+      createdAt: "Mar 25, 2020 at 14:20",
+      type: "Spending Proposal",
+      expiresIn: 5678
+    }
+  },
+  {
+    title: "Send me some tokens for coffee",
+    description:
+      "Change the total reward across all validators in a given block. This is not the direct reward, but base reward for Pallet staking module. The minimum value must be greater than 450 tJOY based on current runtime. Also, coffee is getting expensive.",
 
-        finalized: "withdrawn",
-        details: {
-            createdBy: {
-                name: "David Douglas",
-                avatar: "https://react.semantic-ui.com/images/avatar/large/elliot.jpg",
-            },
-            stage: "Active",
-            createdAt: "Mar 25, 2020 at 14:20",
-            type: "Spending Proposal",
-            expiresIn: 5678,
-        },
-    },
+    finalized: "withdrawn",
+    details: {
+      createdBy: {
+        name: "David Douglas",
+        avatar: "https://react.semantic-ui.com/images/avatar/large/elliot.jpg"
+      },
+      stage: "Active",
+      substage: "Grace Period",
+      createdAt: "Mar 25, 2020 at 14:20",
+      type: "Spending Proposal",
+      expiresIn: 5678
+    }
+  }
 ];
 
-export default MockProposalPreviewList;
+export default MockProposalPreviewList;