@hypernetlabs/web-ui
Version:
Web ui react components for hypernet protocol
208 lines • 13.1 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const objects_1 = require("@hypernetlabs/objects");
const core_1 = require("@material-ui/core");
const contexts_1 = require("../../contexts");
const react_1 = __importStar(require("react"));
const components_1 = require("../../components");
const ProposalsWidget_1 = require("../../widgets/ProposalsWidget/ProposalsWidget");
const ProposalDetailWidget_style_1 = require("../../widgets/ProposalDetailWidget/ProposalDetailWidget.style");
const ProposalDetailWidget = ({ onProposalListNavigate, proposalId, }) => {
const classes = (0, ProposalDetailWidget_style_1.useStyles)();
const { coreProxy, viewUtils } = (0, contexts_1.useStoreContext)();
const { setLoading, handleCoreError } = (0, contexts_1.useLayoutContext)();
const [proposal, setProposal] = (0, react_1.useState)();
const [blockNumber, setBlockNumber] = (0, react_1.useState)();
const [accountAddress, setAccountAddress] = (0, react_1.useState)();
const [supportStatus, setSupportStatus] = (0, react_1.useState)();
const [proposalDescriptionFromIPFS, setProposalDescriptionFromIPFS] = (0, react_1.useState)();
// This is set to true for some existing proposals in rinkeby.
const [showRawDescription, setShowRawDescription] = (0, react_1.useState)();
(0, react_1.useEffect)(() => {
getProposalDetail();
getBlockNumber();
}, []);
const getProposalDetail = () => {
setLoading(true);
coreProxy.getEthereumAccounts().map((accounts) => {
setAccountAddress(accounts[0]);
// delegate votes, createProposal and then list all proposals
coreProxy.governance
.getProposalDetails(proposalId)
.map((proposal) => {
setProposal(proposal);
if (!(0, ProposalsWidget_1.hasProposalDescriptionHash)(proposal.description)) {
setShowRawDescription(true);
return;
}
const descriptionHash = viewUtils.getProposalDescriptionHash(proposal.description);
coreProxy.governance
.getProposalDescription((0, objects_1.IpfsCID)(descriptionHash))
.map((description) => {
setProposalDescriptionFromIPFS(description);
})
.mapErr(handleCoreError);
})
.mapErr(handleCoreError);
getProposalVotesReceipt(accounts[0]);
});
};
const getBlockNumber = () => {
setLoading(true);
coreProxy
.getBlockNumber()
.map((blockNumber) => {
setBlockNumber(blockNumber);
})
.mapErr(handleCoreError);
};
const getProposalVotesReceipt = (account) => {
setLoading(true);
coreProxy.governance
.getProposalVotesReceipt(proposalId, account)
.map((proposalVoteReceipt) => {
if (proposalVoteReceipt.hasVoted) {
setSupportStatus(Number(proposalVoteReceipt.support));
}
setLoading(false);
})
.mapErr(handleCoreError);
};
const proposalVotesFor = proposal ? proposal.votesFor : 0;
const proposalVotesAgainst = proposal ? proposal.votesAgainst : 0;
const proposalVotesAbstain = proposal ? proposal.votesAbstain : 0;
const totalVotes = proposalVotesFor + proposalVotesAgainst + proposalVotesAbstain;
const forPercentage = ((proposalVotesFor * 100) / totalVotes).toFixed(0) || "0";
const againstPercentage = ((proposalVotesAgainst * 100) / totalVotes).toFixed(0) || "0";
const abstainPercentage = ((proposalVotesAbstain * 100) / totalVotes).toFixed(0) || "0";
const showVotingButtons = Number(proposal === null || proposal === void 0 ? void 0 : proposal.state) === objects_1.EProposalState.ACTIVE;
const queueProposal = () => {
setLoading(true);
coreProxy.governance
.queueProposal(proposalId)
.map((proposal) => {
setProposal(proposal);
setLoading(false);
})
.mapErr(handleCoreError);
};
const cancelProposal = () => {
setLoading(true);
coreProxy.governance
.cancelProposal(proposalId)
.map((proposal) => {
setProposal(proposal);
setLoading(false);
})
.mapErr(handleCoreError);
};
const executeProposal = () => {
setLoading(true);
coreProxy.governance
.executeProposal(proposalId)
.map((proposal) => {
setProposal(proposal);
setLoading(false);
})
.mapErr(handleCoreError);
};
const castVote = (voteSupport) => {
setLoading(true);
coreProxy.governance
.castVote(proposalId, voteSupport)
.map((proposal) => {
setProposal(proposal);
if (accountAddress) {
getProposalVotesReceipt(accountAddress);
}
})
.mapErr(handleCoreError);
};
const isUserProposalOwner = (0, react_1.useMemo)(() => proposal &&
accountAddress &&
(0, objects_1.EthereumAccountAddress)(proposal.originator) === accountAddress, [JSON.stringify(proposal), accountAddress]);
const canQueueProposal = (0, react_1.useMemo)(() => {
return Number(proposal === null || proposal === void 0 ? void 0 : proposal.state) === objects_1.EProposalState.SUCCEEDED;
}, [JSON.stringify(proposal)]);
const canExecuteProposal = (0, react_1.useMemo)(() => {
return Number(proposal === null || proposal === void 0 ? void 0 : proposal.state) === objects_1.EProposalState.QUEUED;
}, [JSON.stringify(proposal)]);
const canCancelProposal = (0, react_1.useMemo)(() => {
return (isUserProposalOwner &&
[
objects_1.EProposalState.PENDING,
objects_1.EProposalState.QUEUED,
objects_1.EProposalState.ACTIVE,
objects_1.EProposalState.SUCCEEDED,
objects_1.EProposalState.DEFEATED,
objects_1.EProposalState.EXPIRED,
].includes(Number(proposal === null || proposal === void 0 ? void 0 : proposal.state)));
}, [JSON.stringify(proposal), isUserProposalOwner]);
return (react_1.default.createElement(core_1.Box, null,
react_1.default.createElement(components_1.GovernanceWidgetHeader, { label: "Proposal Detail", navigationLink: {
label: "Proposal List",
onClick: () => {
onProposalListNavigate === null || onProposalListNavigate === void 0 ? void 0 : onProposalListNavigate();
},
}, rightContent: react_1.default.createElement(core_1.Box, { display: "flex", flexDirection: "row" },
canCancelProposal && (react_1.default.createElement(core_1.Box, { marginLeft: "10px" },
react_1.default.createElement(components_1.GovernanceButton, { onClick: () => {
cancelProposal();
}, variant: "outlined" }, "Cancel Proposal"))),
canQueueProposal && (react_1.default.createElement(core_1.Box, { marginLeft: "10px" },
react_1.default.createElement(components_1.GovernanceButton, { color: "primary", size: "medium", onClick: () => {
queueProposal();
}, variant: "outlined" }, "Queue Proposal"))),
canExecuteProposal && (react_1.default.createElement(core_1.Box, { marginLeft: "10px" },
react_1.default.createElement(components_1.GovernanceButton, { onClick: () => {
executeProposal();
}, variant: "outlined" }, "Execute Proposal")))) }),
(proposal === null || proposal === void 0 ? void 0 : proposal.state) != null && (react_1.default.createElement(core_1.Box, { className: classes.proposalStatus },
react_1.default.createElement(components_1.GovernanceStatusTag, { status: proposal === null || proposal === void 0 ? void 0 : proposal.state }))),
react_1.default.createElement(core_1.Box, { display: "flex" },
react_1.default.createElement(core_1.Grid, { container: true, spacing: 3 },
react_1.default.createElement(core_1.Grid, { item: true, xs: 4 },
react_1.default.createElement(components_1.GovernanceVotingCard, { type: "for", value: proposalVotesFor, progressValue: parseFloat(forPercentage), onVoteClick: () => castVote(objects_1.EProposalVoteSupport.FOR), isVoted: supportStatus === objects_1.EProposalVoteSupport.FOR, showVoteButton: showVotingButtons, disableVoteButton: Number(proposal === null || proposal === void 0 ? void 0 : proposal.state) !== objects_1.EProposalState.ACTIVE })),
react_1.default.createElement(core_1.Grid, { item: true, xs: 4 },
react_1.default.createElement(components_1.GovernanceVotingCard, { type: "against", value: proposalVotesAgainst, progressValue: parseFloat(againstPercentage), onVoteClick: () => castVote(objects_1.EProposalVoteSupport.AGAINST), isVoted: supportStatus === objects_1.EProposalVoteSupport.AGAINST, showVoteButton: showVotingButtons, disableVoteButton: Number(proposal === null || proposal === void 0 ? void 0 : proposal.state) !== objects_1.EProposalState.ACTIVE })),
react_1.default.createElement(core_1.Grid, { item: true, xs: 4 },
react_1.default.createElement(components_1.GovernanceVotingCard, { type: "abstain", value: proposalVotesAbstain, progressValue: parseFloat(abstainPercentage), onVoteClick: () => castVote(objects_1.EProposalVoteSupport.ABSTAIN), isVoted: supportStatus === objects_1.EProposalVoteSupport.ABSTAIN, showVoteButton: showVotingButtons, disableVoteButton: Number(proposal === null || proposal === void 0 ? void 0 : proposal.state) !== objects_1.EProposalState.ACTIVE })))),
react_1.default.createElement(core_1.Box, { className: classes.proposalDetails },
react_1.default.createElement(core_1.Typography, { variant: "h6", className: classes.proposalDetailsLabel }, "Details:"),
react_1.default.createElement(core_1.Box, { className: classes.sectionWrapper },
react_1.default.createElement(core_1.Typography, { variant: "body1", className: classes.sectionLabel }, "Proposer"),
react_1.default.createElement(core_1.Typography, { variant: "body1", className: classes.sectionValue }, proposal === null || proposal === void 0 ? void 0 : proposal.originator)),
react_1.default.createElement(core_1.Box, { className: classes.sectionWrapper },
react_1.default.createElement(core_1.Typography, { variant: "body1", className: classes.sectionLabel }, "Current Block"),
react_1.default.createElement(core_1.Typography, { variant: "body1", className: classes.sectionValue }, blockNumber)),
react_1.default.createElement(core_1.Box, { className: classes.sectionWrapper },
react_1.default.createElement(core_1.Typography, { variant: "body1", className: classes.sectionLabel }, "Start Block"),
react_1.default.createElement(core_1.Typography, { variant: "body1", className: classes.sectionValue }, proposal === null || proposal === void 0 ? void 0 : proposal.startBlock)),
react_1.default.createElement(core_1.Box, { className: classes.sectionWrapper },
react_1.default.createElement(core_1.Typography, { variant: "body1", className: classes.sectionLabel }, "End Block"),
react_1.default.createElement(core_1.Typography, { variant: "body1", className: classes.sectionValue }, proposal === null || proposal === void 0 ? void 0 : proposal.endBlock)),
react_1.default.createElement(components_1.GovernanceMarkdown, { source: showRawDescription
? proposal === null || proposal === void 0 ? void 0 : proposal.description
: proposalDescriptionFromIPFS }))));
};
exports.default = ProposalDetailWidget;
//# sourceMappingURL=ProposalDetailWidget.js.map