import * as React from "react"; import { compose } from "redux"; import { BigNumber, TxHash } from "@joincivil/typescript-types"; import { TwoStepEthTransaction } from "@joincivil/core"; import { Tabs, Tab, StyledDashboardSubTab, RescueTokensDescriptionText, ModalContent, StyledDashboardActivityDescription, TransactionButtonNoModal, NoTokensToRescue, } from "@joincivil/components"; import { CivilHelperContext, CivilHelper } from "../../apis/CivilHelper"; import { InjectedTransactionStatusModalProps, hasTransactionStatusModals } from "../utility/TransactionStatusModalsHOC"; import { ChallengesToProcess, StyledBatchButtonContainer, getChallengesToProcess, StyledTabsComponent, } from "./DashboardActivity"; import RescueTokensItem from "./RescueTokensItem"; enum TransactionTypes { MULTI_RESCUE_TOKENS = "MULTI_RESCUE_TOKENS", } const transactionLabels = { [TransactionTypes.MULTI_RESCUE_TOKENS]: "Rescue Tokens", }; const transactionSuccessContent = { [TransactionTypes.MULTI_RESCUE_TOKENS]: [ "You have successfully rescued your unrevealed tokens", We're sorry you were not able to reveal your vote, and hope that you will continue to participate and help curate high-quality, trustworthy journalism , ], }; const transactionRejectionContent = { [TransactionTypes.MULTI_RESCUE_TOKENS]: [ "Your tokens were not rescued", "To rescue your tokens, you need to confirm the transaction in your MetaMask wallet.", ], }; const transactionErrorContent = { [TransactionTypes.MULTI_RESCUE_TOKENS]: [ "The was an problem with rescuing your tokens", Please retry your transaction, ], }; const transactionStatusModalConfig = { transactionLabels, transactionSuccessContent, transactionRejectionContent, transactionErrorContent, }; export interface ChallengesWithTokensToRescueProps { challenges: any; appealChallenges: any; proposalChallenges: any; userChallengeData?: any; refetchUserChallengeData?(): void; onMobileTransactionClick?(): any; } interface ChallengesWithTokensToRescueState { challengesToRescue: ChallengesToProcess; } class ChallengesWithTokensToRescue extends React.Component< ChallengesWithTokensToRescueProps & InjectedTransactionStatusModalProps, ChallengesWithTokensToRescueState > { public static contextType = CivilHelperContext; public context: CivilHelper; public state = { challengesToRescue: {}, }; public componentWillMount(): void { this.props.setTransactions(this.getTransactions()); } public componentWillUnmount(): void { this.resetChallengesToMultiRescue(); } public render(): JSX.Element { const isRescueTokensButtonDisabled = this.isEmpty(this.state.challengesToRescue); const transactions = this.getTransactions(); const { resetChallengesToMultiRescue } = this; const { userChallengeData: allUserChallengeData, challenges, appealChallenges, proposalChallenges } = this.props; const hasNoChallenges = !challenges || challenges.count() === 0; const hasNoAppealChallenges = !appealChallenges || appealChallenges.count() === 0; const hasNoProposalChallenges = !proposalChallenges || proposalChallenges.count() === 0; const displayNoTasks = hasNoChallenges && hasNoAppealChallenges && hasNoProposalChallenges; return ( <> {displayNoTasks && } {!displayNoTasks && ( <> <> {this.props.challenges .sort((a: string, b: string) => parseInt(a, 10) - parseInt(b, 10)) .map((c: string) => { let userChallengeData; if (allUserChallengeData) { userChallengeData = allUserChallengeData.get(c!); } return ( ); })} {this.props.appealChallenges .sort((a: string, b: string) => parseInt(a, 10) - parseInt(b, 10)) .map((c: string) => { let userChallengeData; if (allUserChallengeData) { userChallengeData = allUserChallengeData.get(c!); } return ( ); })} <> {this.props.proposalChallenges .sort((a: string, b: string) => parseInt(a, 10) - parseInt(b, 10)) .map((c: string) => { let userChallengeData; if (allUserChallengeData) { userChallengeData = allUserChallengeData.get(c!); } return ( ); })} Rescue Tokens )} ); } private isEmpty(obj: any): boolean { for (const key in obj) { if (obj.hasOwnProperty(key)) { return false; } } return true; } private getTransactions = (): any[] => { return [ { transaction: async () => { this.props.updateTransactionStatusModalsState({ isWaitingTransactionModalOpen: true, isTransactionProgressModalOpen: false, isTransactionSuccessModalOpen: false, transactionType: TransactionTypes.MULTI_RESCUE_TOKENS, }); return this.multiRescue(); }, handleTransactionHash: (txHash: TxHash) => { this.props.updateTransactionStatusModalsState({ isWaitingTransactionModalOpen: false, isTransactionProgressModalOpen: true, }); }, postTransaction: () => { this.props.updateTransactionStatusModalsState({ isWaitingTransactionModalOpen: false, isTransactionProgressModalOpen: false, isTransactionSuccessModalOpen: true, }); if (this.props.refetchUserChallengeData) { this.props.refetchUserChallengeData(); } }, handleTransactionError: this.props.handleTransactionError, }, ]; }; private setChallengesToMultiRescue = (challengeID: string, isSelected: boolean, salt: BigNumber): void => { if (isSelected) { this.setState(() => ({ challengesToRescue: { ...this.state.challengesToRescue, [challengeID]: [isSelected, salt] }, })); } else { const newChallengesToRescue = this.state.challengesToRescue; delete newChallengesToRescue[challengeID]; this.setState(() => ({ challengesToRescue: { ...newChallengesToRescue }, })); } }; private resetChallengesToMultiRescue = (): void => { this.setState(() => ({ challengesToRescue: {} })); }; private multiRescue = async (): Promise => { const challengeIDs = getChallengesToProcess(this.state.challengesToRescue); return this.context.rescueTokensInMultiplePolls(challengeIDs); }; } export default compose>( hasTransactionStatusModals(transactionStatusModalConfig), )(ChallengesWithTokensToRescue);