mirror of
https://github.com/alexgo-io/ballot.git
synced 2026-01-12 22:46:04 +08:00
fix: Voting power will be captured on contract and shown on UI. Minor UI changes are done.
This commit is contained in:
@@ -1,13 +1,13 @@
|
||||
import { nanoid } from 'nanoid';
|
||||
import Router from 'next/router';
|
||||
import { useEffect, useState } from "react";
|
||||
import { Button, Col, Container, Form, Row } from "react-bootstrap";
|
||||
import { Button, Form } from "react-bootstrap";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { deployContract } from "../../services/contract"
|
||||
import { getRecentBlock } from "../../services/utils";
|
||||
import { getFileFromGaia, getMyStxAddress, getUserData, putFileToGaia } from "../../services/auth.js";
|
||||
import { deployContract } from "../../services/contract";
|
||||
import { getRecentBlock } from "../../services/utils";
|
||||
import styles from "../../styles/Builder.module.css";
|
||||
import PreviewComponent from "./Preview.component";
|
||||
import { nanoid } from 'nanoid'
|
||||
|
||||
export default function BuilderComponent(props) {
|
||||
// Variables
|
||||
|
||||
@@ -35,28 +35,6 @@ export function DashboardNavBarComponent() {
|
||||
setDisplayUsername(_username);
|
||||
}
|
||||
|
||||
const loadBlockSurveyWidgetScript = () => {
|
||||
// If script is not loaded, load first
|
||||
if (!window.blocksurvey) {
|
||||
let body = document.body;
|
||||
let script = document.createElement("script");
|
||||
script.innerHTML = "";
|
||||
script.src = "https://blocksurvey.io/assets/js/blocksurvey-widget.js";
|
||||
script.async = true;
|
||||
script.defer = true;
|
||||
script.onload = () => {
|
||||
window.blocksurvey = {
|
||||
loaded: true,
|
||||
};
|
||||
|
||||
feedbackButton.current.click();
|
||||
};
|
||||
body.appendChild(script);
|
||||
} else {
|
||||
feedbackButton.current.click();
|
||||
}
|
||||
};
|
||||
|
||||
// UI
|
||||
return (
|
||||
<>
|
||||
@@ -72,11 +50,11 @@ export function DashboardNavBarComponent() {
|
||||
isUserSignedIn ?
|
||||
<div style={{ display: "flex", gap: "26px", alignItems: "center" }}>
|
||||
<div style={{ margin: "10px 0" }}>
|
||||
<Link href="/builder/new">
|
||||
<a href="/builder/new">
|
||||
<Button variant="secondary">
|
||||
+ New Poll
|
||||
</Button>
|
||||
</Link>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div className="d-none d-md-block" style={{ margin: "10px 0" }}>
|
||||
@@ -112,9 +90,8 @@ export function DashboardNavBarComponent() {
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Divider />
|
||||
<Dropdown.Item
|
||||
onClick={() => {
|
||||
loadBlockSurveyWidgetScript();
|
||||
}}>
|
||||
href="https://github.com/BlockSurvey/ballot/issues"
|
||||
target="_blank">
|
||||
Share feedback
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item eventKey="1" onClick={() => { signOut() }}>Logout</Dropdown.Item>
|
||||
@@ -136,26 +113,6 @@ export function DashboardNavBarComponent() {
|
||||
handleCloseMyVotesPopup={handleCloseMyVotesPopup}
|
||||
handleShowMyVotesPopup={handleShowMyVotesPopup}
|
||||
/>
|
||||
|
||||
{/* Adding BlockSurvey script */}
|
||||
<blocksurvey-widget
|
||||
origin="blocksurvey.io"
|
||||
uid="t"
|
||||
sid="c4fc8c45-cc9f-4f8d-94eb-0dcc98ad716d"
|
||||
mode="popupcard"
|
||||
alignpopup="center"
|
||||
popupsize="large"
|
||||
background="rgb(0, 0, 0)"
|
||||
color="rgb(255, 255, 255)"
|
||||
params=""
|
||||
></blocksurvey-widget>
|
||||
<button
|
||||
style={{ display: "none" }}
|
||||
className="blocksurvey-share"
|
||||
ref={feedbackButton}
|
||||
>
|
||||
Launch me
|
||||
</button>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -43,7 +43,10 @@ export default function HeaderComponent(props) {
|
||||
<div style={{ display: "flex", alignItems: "center", columnGap: "20px", fontSize: "14px", marginBottom: "30px" }}>
|
||||
{/* Status */}
|
||||
<div>
|
||||
{pollObject?.status == "draft" ? "Draft" : "Active"} {' '}
|
||||
{pollObject?.status == "draft" ? "Draft" :
|
||||
((pollObject?.endAtDate && (new Date(pollObject?.endAtDate) < new Date())) ?
|
||||
(<span style={{ color: "#ff4d4d" }}>Closed</span>) : "Active")}
|
||||
{' '}
|
||||
</div>
|
||||
|
||||
{/* Created by */}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Table } from "react-bootstrap";
|
||||
import { Constants } from "../../common/constants";
|
||||
import { convertToDisplayDateFormat, formStacksExplorerUrl } from "../../services/utils";
|
||||
|
||||
@@ -116,14 +117,26 @@ export default function InformationComponent(props) {
|
||||
<h6>Current results</h6>
|
||||
|
||||
<div style={{ marginTop: "10px" }}>
|
||||
<Table striped bordered>
|
||||
<tbody>
|
||||
{pollObject?.options?.map((option, index) => (
|
||||
<div key={index}>
|
||||
<tr key={index}>
|
||||
<td style={{ width: "70%" }}>
|
||||
{option?.value}
|
||||
</td>
|
||||
<td>
|
||||
<span style={{ float: "right", fontWeight: "bold", textTransform: "capitalize" }}>
|
||||
{resultsByOption && resultsByOption[option.id] ? resultsByOption[option.id] : "-"}
|
||||
{resultsByOption && resultsByOption[option.id] ?
|
||||
<>
|
||||
{resultsByOption[option.id]["percentage"]}% ({resultsByOption[option.id]["total"]})
|
||||
</>
|
||||
: "-"}
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</Table>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@@ -125,7 +125,7 @@ export default function MyVotePopup(props) {
|
||||
) : // Once data found
|
||||
votes && votes.length > 0 ? (
|
||||
<div style={{ padding: "0px 20px 10px", fontSize: "14px" }}>
|
||||
<Table striped bordered hover>
|
||||
<Table striped bordered>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Title</th>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { Col, Container, Row, Button } from "react-bootstrap";
|
||||
import styles from "../../styles/Dashboard.module.css";
|
||||
import { deleteFileToGaia, getFileFromGaia, getUserData, putFileToGaia } from "../../services/auth.js"
|
||||
import Link from "next/link";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Button } from "react-bootstrap";
|
||||
import { deleteFileToGaia, getFileFromGaia, getUserData, putFileToGaia } from "../../services/auth.js";
|
||||
import { convertToDisplayDateFormat } from "../../services/utils";
|
||||
import styles from "../../styles/Dashboard.module.css";
|
||||
|
||||
export default function DashboardAllPollsComponent() {
|
||||
// Variables
|
||||
@@ -66,7 +66,11 @@ export default function DashboardAllPollsComponent() {
|
||||
|
||||
<div style={{ fontSize: "14px", color: "#737373" }}>
|
||||
<span>
|
||||
Status : {pollIndexObject?.status == "draft" ? "Draft" : "Active"}
|
||||
Status : {
|
||||
pollIndexObject?.status == "draft" ? "Draft" :
|
||||
((pollIndexObject?.endAt && (new Date(pollIndexObject?.endAt) < new Date())) ?
|
||||
(<span style={{ color: "#ff4d4d" }}>Closed</span>) : "Active")
|
||||
}
|
||||
</span>
|
||||
{', '}
|
||||
<span>
|
||||
|
||||
@@ -38,8 +38,8 @@ export default function PollComponent(props) {
|
||||
const handleShow = () => setShow(true);
|
||||
const handleClose = () => setShow(false);
|
||||
|
||||
// Loading
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
// Processing
|
||||
const [isProcessing, setIsProcessing] = useState(false);
|
||||
|
||||
// Functions
|
||||
useEffect(() => {
|
||||
@@ -127,7 +127,7 @@ export default function PollComponent(props) {
|
||||
const castMyVote = () => {
|
||||
if (pollObject?.publishedInfo?.contractAddress && pollObject?.publishedInfo?.contractName) {
|
||||
// Start processing
|
||||
setIsLoading(true);
|
||||
setIsProcessing(true);
|
||||
|
||||
const contractAddress = pollObject?.publishedInfo?.contractAddress;
|
||||
const contractName = pollObject?.publishedInfo?.contractName;
|
||||
@@ -183,7 +183,8 @@ export default function PollComponent(props) {
|
||||
{/* Vote button */}
|
||||
{isUserSignedIn ?
|
||||
<Button variant="dark" style={{ marginTop: "30px" }}
|
||||
disabled={(isPreview || !holdingTokenArr || alreadyVoted) ? true : false}
|
||||
disabled={(isPreview || !holdingTokenArr || alreadyVoted || isProcessing ||
|
||||
(pollObject?.endAtDate && (new Date(pollObject?.endAtDate) < new Date()))) ? true : false}
|
||||
onClick={() => { castMyVote() }}>
|
||||
Vote
|
||||
</Button>
|
||||
@@ -219,17 +220,19 @@ export default function PollComponent(props) {
|
||||
|
||||
{/* Results */}
|
||||
<div style={{ marginTop: "20px" }}>
|
||||
<h5>Votes ({total})</h5>
|
||||
<Table striped bordered hover>
|
||||
<h5>Votes {total >= 0 ? <>({total})</> : ""}</h5>
|
||||
<Table striped bordered>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Address</th>
|
||||
<th>Option</th>
|
||||
<th>Voting Power</th>
|
||||
<th>Voting power</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{Object.keys(resultsByPosition).map((position, index) => (
|
||||
{total >= 0 ?
|
||||
(total > 0 ?
|
||||
Object.keys(resultsByPosition).map((position, index) => (
|
||||
<tr key={index}>
|
||||
<td>{resultsByPosition[position]?.address &&
|
||||
<a className="ballot_link" target="_blank" rel="noreferrer" href={formStacksExplorerUrl(resultsByPosition[position]?.address)}>
|
||||
@@ -260,9 +263,25 @@ export default function PollComponent(props) {
|
||||
</div>
|
||||
))}
|
||||
</td>
|
||||
<td>1</td>
|
||||
<td>
|
||||
{Object.values(resultsByPosition[position]?.vote)?.[0]}
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
))
|
||||
:
|
||||
<tr>
|
||||
<td style={{ textAlign: "center" }} colSpan={3}>
|
||||
No data found
|
||||
</td>
|
||||
</tr>
|
||||
)
|
||||
:
|
||||
<tr>
|
||||
<td style={{ textAlign: "center" }} colSpan={3}>
|
||||
Loading
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</Table>
|
||||
</div>
|
||||
@@ -281,6 +300,7 @@ export default function PollComponent(props) {
|
||||
}
|
||||
</div>
|
||||
|
||||
{/* Success message popup */}
|
||||
<Modal show={show} onHide={handleClose}>
|
||||
<Modal.Header closeButton>
|
||||
<Modal.Title>Information</Modal.Title>
|
||||
|
||||
@@ -12,7 +12,6 @@ import { getMyStxAddress, getStacksAPIPrefix, userSession } from "../../services
|
||||
export default function Poll(props) {
|
||||
const { pollObject, pollId, gaiaAddress } = props;
|
||||
|
||||
// const [pollObject, setPollObject] = useState();
|
||||
const [publicUrl, setPublicUrl] = useState();
|
||||
const [optionsMap, setOptionsMap] = useState({});
|
||||
const [resultsByOption, setResultsByOption] = useState({});
|
||||
@@ -188,16 +187,21 @@ export default function Poll(props) {
|
||||
if (content && content.okay) {
|
||||
const results = cvToValue(parseReadOnlyResponse(content)).value;
|
||||
|
||||
let resultsObj = {};
|
||||
results?.options?.value.forEach((option, index) => {
|
||||
resultsObj[option?.value] = results?.results?.value?.[index]?.value;
|
||||
});
|
||||
setResultsByOption(resultsObj)
|
||||
|
||||
const total = parseInt(results?.total?.value);
|
||||
const total = parseInt(results?.["total-with-voting-power"]?.value ? (results?.["total-with-voting-power"]?.value) : (results?.total?.value));
|
||||
setTotal(total);
|
||||
|
||||
getFirstTenResults((total > 10 ? 10 : total), contractAddress, contractName);
|
||||
let resultsObj = {};
|
||||
results?.options?.value.forEach((option, index) => {
|
||||
resultsObj[option?.value] = {
|
||||
total: results?.results?.value?.[index]?.value,
|
||||
percentage: results?.results?.value?.[index]?.value == 0 ? 0 : ((results?.results?.value?.[index]?.value / total) * 100)
|
||||
};
|
||||
});
|
||||
setResultsByOption(resultsObj);
|
||||
|
||||
getFirstTenResults((results?.total?.value > 10 ? 10 : results?.total?.value), contractAddress, contractName);
|
||||
} else {
|
||||
setTotal(0);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -119,6 +119,7 @@ function getRawContract() {
|
||||
(define-map users {id: principal} {count: uint, vote: (list &{noOfOptions} (string-ascii 36)), volume: (list &{noOfOptions} uint)})
|
||||
(define-map register {id: uint} {user: principal, bns: (string-ascii 256), vote: (list &{noOfOptions} (string-ascii 36)), volume: (list &{noOfOptions} uint)})
|
||||
(define-data-var total uint u0)
|
||||
(define-data-var total-with-voting-power uint u0)
|
||||
(define-data-var options (list &{noOfOptions} (string-ascii 36)) (list))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
@@ -216,6 +217,9 @@ function getRawContract() {
|
||||
(map-set users {id: tx-sender} {count: u1, vote: vote, volume: volume})
|
||||
(map-set register {id: next-total} {user: tx-sender, bns: bns, vote: vote, volume: volume})
|
||||
|
||||
;; Increase the total with voting power
|
||||
(var-set total-with-voting-power (+ (unwrap-panic (element-at volume u0)) (var-get total-with-voting-power)))
|
||||
|
||||
;; Increase the total
|
||||
(var-set total next-total)
|
||||
|
||||
@@ -226,7 +230,7 @@ function getRawContract() {
|
||||
|
||||
(define-read-only (get-results)
|
||||
(begin
|
||||
(ok {total: (var-get total),options: (var-get options), results: (map get-single-result (var-get options))})
|
||||
(ok {total: (var-get total), total-with-voting-power: (var-get total-with-voting-power), options: (var-get options), results: (map get-single-result (var-get options))})
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user