mirror of
https://github.com/alexgo-io/ballot.git
synced 2026-01-12 08:54:02 +08:00
fix: .btc holders were not able to vote. Copy share link and QR code both are introduced.
This commit is contained in:
@@ -5,7 +5,7 @@ export const Constants = {
|
||||
GAIA_HUB_PREFIX: "https://gaia.blockstack.org/hub/",
|
||||
|
||||
// IPFS gateway
|
||||
IPFS_GATEWAY: "https://ipfs.owl.link/ipfs/",
|
||||
IPFS_GATEWAY: "https://cloudflare-ipfs.com/ipfs/",
|
||||
|
||||
// FAQs
|
||||
FAQ: [
|
||||
@@ -31,7 +31,7 @@ export const Constants = {
|
||||
},
|
||||
{
|
||||
question: "Who are the developers of Ballot.gg?",
|
||||
answer: `We are developers from Team BlockSurvey.`,
|
||||
answer: `We are developers from Team <a href="https://blocksurvey.io?ref=ballot" target="_blank" rel="noreferrer">BlockSurvey ↗</a>.`,
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
@@ -7,6 +7,7 @@ import { getRecentBlock } from "../../services/utils";
|
||||
import { getFileFromGaia, getMyStxAddress, getUserData, putFileToGaia } from "../../services/auth.js";
|
||||
import styles from "../../styles/Builder.module.css";
|
||||
import PreviewComponent from "./Preview.component";
|
||||
import { nanoid } from 'nanoid'
|
||||
|
||||
export default function BuilderComponent(props) {
|
||||
// Variables
|
||||
@@ -327,7 +328,7 @@ export default function BuilderComponent(props) {
|
||||
pollObject['endAtBlock'] = calculateBlockTime(new Date(pollObject?.endAtDate).getTime(), currentBlock?.height);
|
||||
}
|
||||
|
||||
const contractName = "ballot-" + getTitleWithOutSpecialChar();
|
||||
const contractName = "ballot-" + getTitleWithOutSpecialChar() + "-" + nanoid(5);
|
||||
pollObject["publishedInfo"] = {
|
||||
"contractAddress": getMyStxAddress(),
|
||||
"contractName": contractName
|
||||
@@ -338,7 +339,7 @@ export default function BuilderComponent(props) {
|
||||
|
||||
const publishContract = (contractName) => {
|
||||
// Publish contract
|
||||
deployContract(pollObject, contractName, callbackFunction);
|
||||
deployContract(pollObject, contractName, callbackFunction, cancelCallbackFunction);
|
||||
}
|
||||
|
||||
const callbackFunction = (data) => {
|
||||
@@ -353,6 +354,10 @@ export default function BuilderComponent(props) {
|
||||
}
|
||||
}
|
||||
|
||||
const cancelCallbackFunction = (data) => {
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
const publishPollToIPFS = async () => {
|
||||
setCurrentProgressMessage("Publishing to IPFS ...");
|
||||
|
||||
@@ -390,7 +395,7 @@ export default function BuilderComponent(props) {
|
||||
}
|
||||
|
||||
const getTitleWithOutSpecialChar = () => {
|
||||
return pollObject?.title?.replace(/[^a-zA-Z0-9]/g, '');
|
||||
return pollObject?.title?.replace(/\s+/g, '-').replace(/[^a-zA-Z0-9-]/g, '').substr(0, 16);
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -404,7 +409,7 @@ export default function BuilderComponent(props) {
|
||||
<h4>{pollId && pollId === "new" ? "New" : "Edit"} Poll</h4>
|
||||
|
||||
{pollObject && pollObject.id ?
|
||||
<Form style={{ marginTop: "20px" }}>
|
||||
<Form style={{ margin: "20px 0 50px 0" }}>
|
||||
<Form.Group className="mb-3">
|
||||
<Form.Label>Title</Form.Label>
|
||||
<Form.Control type="text" name="title" value={pollObject.title} onChange={handleChange} />
|
||||
@@ -491,6 +496,7 @@ export default function BuilderComponent(props) {
|
||||
id="voting-strategy-id"
|
||||
name="votingStrategyFlag"
|
||||
onChange={handleChange}
|
||||
checked={pollObject.votingStrategyFlag}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -498,7 +504,9 @@ export default function BuilderComponent(props) {
|
||||
<>
|
||||
<Form.Group className="mb-3">
|
||||
<Form.Label>Default strategy</Form.Label>
|
||||
<Form.Select id="voting-strategy-template" name="votingStrategyTemplate" defaultValue={""} onChange={handleChange}>
|
||||
<Form.Select id="voting-strategy-template" name="votingStrategyTemplate"
|
||||
value={pollObject?.votingStrategyTemplate ? pollObject.votingStrategyTemplate : ""}
|
||||
onChange={handleChange}>
|
||||
<option disabled value="">Select</option>
|
||||
<option value="satoshibles">Satoshibles</option>
|
||||
<option value="crashpunks">CrashPunks</option>
|
||||
|
||||
@@ -1,11 +1,25 @@
|
||||
import { formStacksExplorerUrl } from "../../services/utils";
|
||||
|
||||
import Tooltip from "react-bootstrap/Tooltip";
|
||||
import { useState } from "react";
|
||||
import OverlayTrigger from "react-bootstrap/OverlayTrigger";
|
||||
import QRCodePopup from "../poll/QRCodePopup";
|
||||
|
||||
export default function HeaderComponent(props) {
|
||||
// Variables
|
||||
const { pollObject } = props;
|
||||
const { pollObject, publicUrl } = props;
|
||||
|
||||
const [copyText, setCopyText] = useState("Copy");
|
||||
const [showQRCodePopupFlag, setShowQRCodePopupFlag] = useState(false);
|
||||
|
||||
// Function
|
||||
const copyToClipBoard = () => {
|
||||
if (pollObject?.id) {
|
||||
// Update tooltip message
|
||||
setCopyText("Copied");
|
||||
|
||||
navigator.clipboard.writeText(publicUrl);
|
||||
}
|
||||
};
|
||||
|
||||
// Design
|
||||
return (
|
||||
@@ -16,29 +30,63 @@ export default function HeaderComponent(props) {
|
||||
<h4>{pollObject?.title}</h4>
|
||||
|
||||
{/* Info Bar */}
|
||||
<div style={{ fontSize: "14px" }}>
|
||||
{pollObject?.status == "draft" ? "Draft" : "Active"} {' '}
|
||||
{pollObject?.userStxAddress &&
|
||||
<a target="_blank" rel="noreferrer" href={formStacksExplorerUrl(pollObject?.userStxAddress)}>
|
||||
<span>
|
||||
{pollObject?.userStxAddress?.substring(0, 10)} { }
|
||||
<svg
|
||||
width="10"
|
||||
height="10"
|
||||
viewBox="0 0 12 12"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M3.5044 0.743397C3.5044 0.33283 3.83723 -6.71395e-08 4.2478 0L11.2566 6.60206e-07C11.6672 6.60206e-07 12 0.33283 12 0.743397L12 7.7522C12 8.16277 11.6672 8.4956 11.2566 8.4956C10.846 8.4956 10.5132 8.16277 10.5132 7.7522V2.53811L1.26906 11.7823C0.978742 12.0726 0.50805 12.0726 0.217736 11.7823C-0.0725787 11.4919 -0.0725784 11.0213 0.217736 10.7309L9.46189 1.48679L4.2478 1.48679C3.83723 1.48679 3.5044 1.15396 3.5044 0.743397Z"
|
||||
fill="#0d6efd"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
}
|
||||
<div style={{ display: "flex", alignItems: "center", columnGap: "20px", fontSize: "14px" }}>
|
||||
{/* Status */}
|
||||
<div>
|
||||
{pollObject?.status == "draft" ? "Draft" : "Active"} {' '}
|
||||
</div>
|
||||
|
||||
{/* Created by */}
|
||||
<div>
|
||||
<span style={{ color: "#737373" }}>Created by</span> {' '}
|
||||
{pollObject?.userStxAddress &&
|
||||
<a target="_blank" rel="noreferrer" href={formStacksExplorerUrl(pollObject?.userStxAddress)}>
|
||||
<span>
|
||||
{pollObject?.userStxAddress?.substring(0, 10)} { }
|
||||
<svg
|
||||
width="10"
|
||||
height="10"
|
||||
viewBox="0 0 12 12"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M3.5044 0.743397C3.5044 0.33283 3.83723 -6.71395e-08 4.2478 0L11.2566 6.60206e-07C11.6672 6.60206e-07 12 0.33283 12 0.743397L12 7.7522C12 8.16277 11.6672 8.4956 11.2566 8.4956C10.846 8.4956 10.5132 8.16277 10.5132 7.7522V2.53811L1.26906 11.7823C0.978742 12.0726 0.50805 12.0726 0.217736 11.7823C-0.0725787 11.4919 -0.0725784 11.0213 0.217736 10.7309L9.46189 1.48679L4.2478 1.48679C3.83723 1.48679 3.5044 1.15396 3.5044 0.743397Z"
|
||||
fill="#0d6efd"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
}
|
||||
</div>
|
||||
|
||||
{/* Copy link */}
|
||||
<OverlayTrigger
|
||||
placement="top"
|
||||
overlay={<Tooltip>{copyText}</Tooltip>}>
|
||||
<button style={{ padding: "0px", border: "0px", background: "none" }}
|
||||
onClick={copyToClipBoard}
|
||||
onMouseEnter={() => setCopyText("Copy")}
|
||||
disabled={!publicUrl}>
|
||||
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M14.0625 21.25H8.75C7.02083 21.25 5.54688 20.6406 4.32813 19.4219C3.10938 18.2031 2.5 16.7292 2.5 15C2.5 13.2708 3.10938 11.7969 4.32813 10.5781C5.54688 9.35937 7.02083 8.75 8.75 8.75H14.0625V10.625H8.75C7.54167 10.625 6.51042 11.0521 5.65625 11.9062C4.80208 12.7604 4.375 13.7917 4.375 15C4.375 16.2083 4.80208 17.2396 5.65625 18.0938C6.51042 18.9479 7.54167 19.375 8.75 19.375H14.0625V21.25ZM10.1562 15.9375V14.0625H19.8438V15.9375H10.1562ZM15.9375 21.25V19.375H21.25C22.4583 19.375 23.4896 18.9479 24.3438 18.0938C25.1979 17.2396 25.625 16.2083 25.625 15C25.625 13.7917 25.1979 12.7604 24.3438 11.9062C23.4896 11.0521 22.4583 10.625 21.25 10.625H15.9375V8.75H21.25C22.9792 8.75 24.4531 9.35937 25.6719 10.5781C26.8906 11.7969 27.5 13.2708 27.5 15C27.5 16.7292 26.8906 18.2031 25.6719 19.4219C24.4531 20.6406 22.9792 21.25 21.25 21.25H15.9375Z" fill="black" />
|
||||
</svg>
|
||||
</button>
|
||||
</OverlayTrigger>
|
||||
|
||||
{/* QR code */}
|
||||
<OverlayTrigger
|
||||
placement="top"
|
||||
overlay={<Tooltip>QR code</Tooltip>}>
|
||||
<button style={{ padding: "0px", border: "0px", background: "none" }}
|
||||
disabled={!publicUrl} onClick={() => { setShowQRCodePopupFlag(true) }}>
|
||||
<svg width="26" height="26" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M3.75 14.0625V3.75H14.0625V14.0625H3.75ZM5.625 12.1875H12.1875V5.625H5.625V12.1875ZM3.75 26.25V15.9375H14.0625V26.25H3.75ZM5.625 24.375H12.1875V17.8125H5.625V24.375ZM15.9375 14.0625V3.75H26.25V14.0625H15.9375ZM17.8125 12.1875H24.375V5.625H17.8125V12.1875ZM23.6875 26.25V23.6875H26.25V26.25H23.6875ZM15.9375 18.5312V15.9375H18.5V18.5312H15.9375ZM18.5 21.0938V18.5312H21.0938V21.0938H18.5ZM15.9375 23.6875V21.0938H18.5V23.6875H15.9375ZM18.5 26.25V23.6875H21.0938V26.25H18.5ZM21.0938 23.6875V21.0938H23.6875V23.6875H21.0938ZM21.0938 18.5312V15.9375H23.6875V18.5312H21.0938ZM23.6875 21.0938V18.5312H26.25V21.0938H23.6875Z" fill="black" />
|
||||
</svg>
|
||||
</button>
|
||||
</OverlayTrigger>
|
||||
</div>
|
||||
|
||||
{/* Description */}
|
||||
@@ -50,6 +98,9 @@ export default function HeaderComponent(props) {
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
|
||||
<QRCodePopup pollObject={pollObject} publicUrl={publicUrl}
|
||||
showQRCodePopupFlag={showQRCodePopupFlag} setShowQRCodePopupFlag={setShowQRCodePopupFlag} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Constants } from "../../common/constants";
|
||||
import { convertToDisplayDateFormat, formStacksExplorerUrl } from "../../services/utils";
|
||||
|
||||
|
||||
@@ -47,7 +48,7 @@ export default function InformationComponent(props) {
|
||||
pollObject?.ipfsLocation &&
|
||||
<div>
|
||||
IPFS
|
||||
<a target="_blank" rel="noreferrer" href={`https://owllink.mypinata.cloud/ipfs/${pollObject?.ipfsLocation}`}>
|
||||
<a target="_blank" rel="noreferrer" href={`${Constants.IPFS_GATEWAY}${pollObject?.ipfsLocation}`}>
|
||||
<span style={{ float: "right", fontWeight: "bold" }}>
|
||||
#{pollObject?.ipfsLocation.substring(0, 8)} { }
|
||||
<svg
|
||||
|
||||
@@ -64,7 +64,7 @@ export default function DashboardAllPollsComponent() {
|
||||
{pollIndexObject?.title ? pollIndexObject?.title : "..."}
|
||||
</div>
|
||||
|
||||
<div style={{ fontSize: "14px" }}>
|
||||
<div style={{ fontSize: "14px", color: "#737373" }}>
|
||||
<span>
|
||||
Status : {pollIndexObject?.status == "draft" ? "Draft" : "Active"}
|
||||
</span>
|
||||
@@ -75,12 +75,12 @@ export default function DashboardAllPollsComponent() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{/* <div>
|
||||
<Button variant="danger" onClick={(event) => { event.stopPropagation(); deletePoll(pollIndexObject, setAllPolls) }}
|
||||
disabled={isDeleting}>
|
||||
Delete
|
||||
</Button>
|
||||
</div>
|
||||
</div> */}
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import Link from "next/link";
|
||||
import { Container, Row, Col, Button } from "react-bootstrap";
|
||||
import { signOut } from "../../services/auth";
|
||||
|
||||
export default function DashboardMenuComponent() {
|
||||
|
||||
@@ -8,23 +9,35 @@ export default function DashboardMenuComponent() {
|
||||
<Container>
|
||||
<Row>
|
||||
<Col md={12} style={{ paddingTop: "10px" }}>
|
||||
<h4>Ballot</h4>
|
||||
<div style={{ marginBottom: "20px" }}>
|
||||
<a href="/all-polls">
|
||||
<svg width="68" height="19" viewBox="0 0 68 19" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10.16 9.408C11.104 9.584 11.88 10.056 12.488 10.824C13.096 11.592 13.4 12.472 13.4 13.464C13.4 14.36 13.176 15.152 12.728 15.84C12.296 16.512 11.664 17.04 10.832 17.424C10 17.808 9.016 18 7.88 18H0.656V1.248H7.568C8.704 1.248 9.68 1.432 10.496 1.8C11.328 2.168 11.952 2.68 12.368 3.336C12.8 3.992 13.016 4.736 13.016 5.568C13.016 6.544 12.752 7.36 12.224 8.016C11.712 8.672 11.024 9.136 10.16 9.408ZM4.016 8.16H7.088C7.888 8.16 8.504 7.984 8.936 7.632C9.368 7.264 9.584 6.744 9.584 6.072C9.584 5.4 9.368 4.88 8.936 4.512C8.504 4.144 7.888 3.96 7.088 3.96H4.016V8.16ZM7.4 15.264C8.216 15.264 8.848 15.072 9.296 14.688C9.76 14.304 9.992 13.76 9.992 13.056C9.992 12.336 9.752 11.776 9.272 11.376C8.792 10.96 8.144 10.752 7.328 10.752H4.016V15.264H7.4ZM15.2139 11.304C15.2139 9.96 15.4779 8.768 16.0059 7.728C16.5499 6.688 17.2779 5.888 18.1899 5.328C19.1179 4.768 20.1499 4.488 21.2859 4.488C22.2779 4.488 23.1419 4.688 23.8779 5.088C24.6299 5.488 25.2299 5.992 25.6779 6.6V4.704H29.0619V18H25.6779V16.056C25.2459 16.68 24.6459 17.2 23.8779 17.616C23.1259 18.016 22.2539 18.216 21.2619 18.216C20.1419 18.216 19.1179 17.928 18.1899 17.352C17.2779 16.776 16.5499 15.968 16.0059 14.928C15.4779 13.872 15.2139 12.664 15.2139 11.304ZM25.6779 11.352C25.6779 10.536 25.5179 9.84 25.1979 9.264C24.8779 8.672 24.4459 8.224 23.9019 7.92C23.3579 7.6 22.7739 7.44 22.1499 7.44C21.5259 7.44 20.9499 7.592 20.4219 7.896C19.8939 8.2 19.4619 8.648 19.1259 9.24C18.8059 9.816 18.6459 10.504 18.6459 11.304C18.6459 12.104 18.8059 12.808 19.1259 13.416C19.4619 14.008 19.8939 14.464 20.4219 14.784C20.9659 15.104 21.5419 15.264 22.1499 15.264C22.7739 15.264 23.3579 15.112 23.9019 14.808C24.4459 14.488 24.8779 14.04 25.1979 13.464C25.5179 12.872 25.6779 12.168 25.6779 11.352ZM35.7035 0.24V18H32.3435V0.24H35.7035ZM42.3832 0.24V18H39.0232V0.24H42.3832ZM51.6069 18.216C50.3269 18.216 49.1749 17.936 48.1509 17.376C47.1269 16.8 46.3189 15.992 45.7269 14.952C45.1509 13.912 44.8629 12.712 44.8629 11.352C44.8629 9.992 45.1589 8.792 45.7509 7.752C46.3589 6.712 47.1829 5.912 48.2229 5.352C49.2629 4.776 50.4229 4.488 51.7029 4.488C52.9829 4.488 54.1429 4.776 55.1829 5.352C56.2229 5.912 57.0389 6.712 57.6309 7.752C58.2389 8.792 58.5429 9.992 58.5429 11.352C58.5429 12.712 58.2309 13.912 57.6069 14.952C56.9989 15.992 56.1669 16.8 55.1109 17.376C54.0709 17.936 52.9029 18.216 51.6069 18.216ZM51.6069 15.288C52.2149 15.288 52.7829 15.144 53.3109 14.856C53.8549 14.552 54.2869 14.104 54.6069 13.512C54.9269 12.92 55.0869 12.2 55.0869 11.352C55.0869 10.088 54.7509 9.12 54.0789 8.448C53.4229 7.76 52.6149 7.416 51.6549 7.416C50.6949 7.416 49.8869 7.76 49.2309 8.448C48.5909 9.12 48.2709 10.088 48.2709 11.352C48.2709 12.616 48.5829 13.592 49.2069 14.28C49.8469 14.952 50.6469 15.288 51.6069 15.288ZM64.9196 7.464V13.896C64.9196 14.344 65.0236 14.672 65.2316 14.88C65.4556 15.072 65.8236 15.168 66.3356 15.168H67.8956V18H65.7836C62.9516 18 61.5356 16.624 61.5356 13.872V7.464H59.9516V4.704H61.5356V1.416H64.9196V4.704H67.8956V7.464H64.9196Z" fill="black" />
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div style={{ margin: "10px 0" }}>
|
||||
<Link href="/builder/new">
|
||||
<Button>
|
||||
<Button variant="dark">
|
||||
+ New Poll
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div style={{ margin: "10px 0" }}>
|
||||
<Link href="/all-polls">
|
||||
<Button>
|
||||
<Button variant="dark">
|
||||
All Polls
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<div style={{ margin: "50px 0" }}>
|
||||
<Button variant="dark" onClick={() => { signOut() }}>
|
||||
Log out
|
||||
</Button>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
|
||||
@@ -23,7 +23,8 @@ export default function PollComponent(props) {
|
||||
noHoldingToken,
|
||||
holdingTokenArr,
|
||||
holdingTokenIdArr,
|
||||
votingPower } = props;
|
||||
votingPower,
|
||||
publicUrl } = props;
|
||||
|
||||
// Capture the vote
|
||||
const [voteObject, setVoteObject] = useState({});
|
||||
@@ -82,7 +83,7 @@ export default function PollComponent(props) {
|
||||
{/* Left Side */}
|
||||
<div className="col-sm-12 col-md-8">
|
||||
{/* Header */}
|
||||
<HeaderComponent pollObject={pollObject} />
|
||||
<HeaderComponent pollObject={pollObject} publicUrl={publicUrl} />
|
||||
|
||||
{/* Cast your vote */}
|
||||
<div style={{ marginTop: "20px" }}>
|
||||
@@ -103,13 +104,13 @@ export default function PollComponent(props) {
|
||||
))}
|
||||
|
||||
{userSession && userSession.isUserSignedIn() ?
|
||||
<Button style={{ marginTop: "10px" }}
|
||||
<Button variant="dark" style={{ marginTop: "10px" }}
|
||||
disabled={(isPreview || !holdingTokenArr || alreadyVoted) ? true : false}
|
||||
onClick={() => { castMyVote() }}>
|
||||
Vote
|
||||
</Button>
|
||||
:
|
||||
<Button style={{ marginTop: "10px" }}
|
||||
<Button variant="dark" style={{ marginTop: "10px" }}
|
||||
onClick={() => { authenticate() }}>
|
||||
Vote
|
||||
</Button>
|
||||
@@ -125,7 +126,7 @@ export default function PollComponent(props) {
|
||||
{/* Already voted */}
|
||||
{alreadyVoted &&
|
||||
<div style={{ fontSize: "14px", color: "red" }}>
|
||||
You have already cast your vote.
|
||||
Your vote has already been cast.
|
||||
</div>
|
||||
}
|
||||
</Form.Group>
|
||||
@@ -204,7 +205,7 @@ export default function PollComponent(props) {
|
||||
<Modal.Title>Information</Modal.Title>
|
||||
</Modal.Header>
|
||||
<Modal.Body>
|
||||
Successfully! You have cast your vote. Check your transaction status on explorer
|
||||
Voted successfully! Your vote has been cast. Here is a link to your transaction status
|
||||
<a
|
||||
style={{ textDecoration: "underline", color: "#000" }}
|
||||
href={formStacksExplorerUrl(txId)}
|
||||
|
||||
113
components/poll/QRCodePopup.js
Normal file
113
components/poll/QRCodePopup.js
Normal file
@@ -0,0 +1,113 @@
|
||||
import QRCode from "qrcode.react";
|
||||
import { Modal } from "react-bootstrap";
|
||||
import styles from "../../styles/QRCodePopup.module.css";
|
||||
|
||||
export default function QRCodePopup(props) {
|
||||
// Parent parameters
|
||||
const { pollObject, showQRCodePopupFlag, publicUrl } = props;
|
||||
|
||||
// Variables
|
||||
// Handle close popup
|
||||
const handleCloseQrCodePopup = () => {
|
||||
props.setShowQRCodePopupFlag(false);
|
||||
};
|
||||
|
||||
// Functions
|
||||
// Download QR code
|
||||
const downloadQRCode = () => {
|
||||
const qrCodeURL = document
|
||||
.getElementById("qrCodeEl")
|
||||
.toDataURL("image/png")
|
||||
.replace("image/png", "image/octet-stream");
|
||||
let aEl = document.createElement("a");
|
||||
aEl.href = qrCodeURL;
|
||||
aEl.download = "Ballot_" + (pollObject?.title ? pollObject?.title.replaceAll(".", "_") : "") + ".png";
|
||||
document.body.appendChild(aEl);
|
||||
aEl.click();
|
||||
document.body.removeChild(aEl);
|
||||
};
|
||||
|
||||
// View
|
||||
return (
|
||||
<>
|
||||
{/* QR code */}
|
||||
<Modal
|
||||
show={showQRCodePopupFlag}
|
||||
onHide={handleCloseQrCodePopup}
|
||||
keyboard={false}
|
||||
centered
|
||||
size="md"
|
||||
>
|
||||
{/* Header */}
|
||||
<div className={styles.dashboard_modal_header_box}>
|
||||
<div>Ballot QR code</div>
|
||||
<button
|
||||
className={styles.dashboard_modal_close_icon_btn_box}
|
||||
onClick={handleCloseQrCodePopup}
|
||||
>
|
||||
<svg
|
||||
width="10"
|
||||
height="10"
|
||||
viewBox="0 0 10 10"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M0.898377 0.898804C1.2108 0.586385 1.71733 0.586385 2.02975 0.898804L4.9996 3.86865L7.96945 0.898804C8.28186 0.586385 8.7884 0.586385 9.10082 0.898804C9.41324 1.21122 9.41324 1.71776 9.10082 2.03018L6.13097 5.00002L9.10082 7.96987C9.41324 8.28229 9.41324 8.78882 9.10082 9.10124C8.7884 9.41366 8.28186 9.41366 7.96945 9.10124L4.9996 6.13139L2.02975 9.10124C1.71733 9.41366 1.2108 9.41366 0.898377 9.10124C0.585958 8.78882 0.585958 8.28229 0.898377 7.96987L3.86823 5.00002L0.898377 2.03018C0.585958 1.71776 0.585958 1.21122 0.898377 0.898804Z"
|
||||
fill="black"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Body */}
|
||||
<div
|
||||
className={
|
||||
styles.dashboard_modal_body_box +
|
||||
" " +
|
||||
styles.dashboard_transactions_modal_body_box
|
||||
}
|
||||
style={{ padding: "0px", marginBottom: "20px" }}
|
||||
>
|
||||
{/* QR code */}
|
||||
<div style={{ padding: "20px", textAlign: "center" }}>
|
||||
{/* QR code */}
|
||||
<QRCode size={220} value={publicUrl} />
|
||||
|
||||
<div style={{ display: "none" }}>
|
||||
<QRCode
|
||||
id="qrCodeEl"
|
||||
size={600}
|
||||
includeMargin={true}
|
||||
value={publicUrl}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Download button */}
|
||||
<div style={{ margin: "30px 0 0 0" }}>
|
||||
<a style={{ cursor: "pointer" }} onClick={downloadQRCode}>
|
||||
<svg
|
||||
data-v-2381e482=""
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
data-v-2381e482=""
|
||||
d="M12.6668 6H10.0002V2H6.00016V6H3.3335L8.00016 10.6667L12.6668 6ZM3.3335 12V13.3333H12.6668V12H3.3335Z"
|
||||
fill="#394147"
|
||||
></path>
|
||||
</svg>
|
||||
Download
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
}
|
||||
8
node_modules/.package-lock.json
generated
vendored
8
node_modules/.package-lock.json
generated
vendored
@@ -3112,6 +3112,14 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/qrcode.react": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/qrcode.react/-/qrcode.react-3.1.0.tgz",
|
||||
"integrity": "sha512-oyF+Urr3oAMUG/OiOuONL3HXM+53wvuH3mtIWQrYmsXoAq0DkvZp2RYUWFSMFtbdOpuS++9v+WAkzNVkMlNW6Q==",
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/query-string": {
|
||||
"version": "6.14.1",
|
||||
"resolved": "https://registry.npmjs.org/query-string/-/query-string-6.14.1.tgz",
|
||||
|
||||
15
package-lock.json
generated
15
package-lock.json
generated
@@ -16,6 +16,7 @@
|
||||
"lodash": "^4.17.21",
|
||||
"nanoid": "^4.0.0",
|
||||
"next": "12.2.5",
|
||||
"qrcode.react": "^3.1.0",
|
||||
"react": "18.2.0",
|
||||
"react-bootstrap": "^2.5.0",
|
||||
"react-dom": "18.2.0",
|
||||
@@ -3315,6 +3316,14 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/qrcode.react": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/qrcode.react/-/qrcode.react-3.1.0.tgz",
|
||||
"integrity": "sha512-oyF+Urr3oAMUG/OiOuONL3HXM+53wvuH3mtIWQrYmsXoAq0DkvZp2RYUWFSMFtbdOpuS++9v+WAkzNVkMlNW6Q==",
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/query-string": {
|
||||
"version": "6.14.1",
|
||||
"resolved": "https://registry.npmjs.org/query-string/-/query-string-6.14.1.tgz",
|
||||
@@ -6365,6 +6374,12 @@
|
||||
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
|
||||
"dev": true
|
||||
},
|
||||
"qrcode.react": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/qrcode.react/-/qrcode.react-3.1.0.tgz",
|
||||
"integrity": "sha512-oyF+Urr3oAMUG/OiOuONL3HXM+53wvuH3mtIWQrYmsXoAq0DkvZp2RYUWFSMFtbdOpuS++9v+WAkzNVkMlNW6Q==",
|
||||
"requires": {}
|
||||
},
|
||||
"query-string": {
|
||||
"version": "6.14.1",
|
||||
"resolved": "https://registry.npmjs.org/query-string/-/query-string-6.14.1.tgz",
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
"lodash": "^4.17.21",
|
||||
"nanoid": "^4.0.0",
|
||||
"next": "12.2.5",
|
||||
"qrcode.react": "^3.1.0",
|
||||
"react": "18.2.0",
|
||||
"react-bootstrap": "^2.5.0",
|
||||
"react-dom": "18.2.0",
|
||||
|
||||
@@ -155,9 +155,9 @@ export default function Home() {
|
||||
|
||||
{/* Steps */}
|
||||
<div className='row'>
|
||||
<div style={{ marginBottom: "20px" }} className='col-md-6'>
|
||||
<div className='col-md-12'>
|
||||
{/* Step 1 */}
|
||||
<div style={{ height: "100%", display: "flex", alignItems: "center" }} className={styles.how_it_works_step_box}>
|
||||
<div style={{ marginBottom: "20px" }} className={styles.how_it_works_step_box}>
|
||||
<div>
|
||||
{/* Image */}
|
||||
<div className={styles.how_it_works_step_image}>
|
||||
@@ -168,7 +168,7 @@ export default function Home() {
|
||||
|
||||
{/* Text */}
|
||||
<h3 className={styles.how_it_works_step_title}>
|
||||
Sign in to Ballot.gg <br />using Hiro Wallet
|
||||
Sign in to Ballot.gg using Hiro Wallet.
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
@@ -179,9 +179,7 @@ export default function Home() {
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='col-md-6'>
|
||||
{/* Step 2 */}
|
||||
<div style={{ marginBottom: "20px" }} className={styles.how_it_works_step_box}>
|
||||
{/* Image */}
|
||||
@@ -261,8 +259,19 @@ export default function Home() {
|
||||
</button>
|
||||
</a> */}
|
||||
|
||||
{/* GitHub */}
|
||||
<a href="https://github.com/BlockSurvey/ballot"
|
||||
target="_blank" rel="noreferrer">
|
||||
<button className={styles.social_icon}>
|
||||
<svg width="20" height="23" viewBox="0 0 20 23" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.08554 21.7251C7.08645 21.7095 7.0869 21.6939 7.0869 21.6784C7.0869 21.5584 7.0847 21.3417 7.08184 21.0589C7.07646 20.5278 7.06871 19.7636 7.06871 18.9685C3.41303 19.6414 2.46728 18.0773 2.17628 17.2589C2.0126 16.8406 1.30329 15.5493 0.684912 15.2037C0.175663 14.9309 -0.551836 14.258 0.666724 14.2398C1.81253 14.2216 2.63097 15.2946 2.90378 15.7311C4.21328 17.9318 6.30484 17.3135 7.14146 16.9315C7.26877 15.9858 7.65071 15.3492 8.06902 14.9855C4.83165 14.6217 1.44879 13.3668 1.44879 7.80141C1.44879 6.2191 2.0126 4.9096 2.94016 3.89111C2.79466 3.52736 2.28541 2.03599 3.08566 0.0353652C3.08566 0.0353652 4.30422 -0.346571 7.0869 1.52674C8.2509 1.19936 9.48764 1.03568 10.7244 1.03568C11.9611 1.03568 13.1979 1.19936 14.3619 1.52674C17.1446 -0.364759 18.3631 0.0353652 18.3631 0.0353652C19.1634 2.03599 18.6541 3.52736 18.5086 3.89111C19.4362 4.9096 20 6.20091 20 7.80141C20 13.385 16.5989 14.6217 13.3616 14.9855C13.889 15.4401 14.3437 16.3131 14.3437 17.6772C14.3437 18.9726 14.3356 20.0987 14.3302 20.8518C14.3275 21.2301 14.3255 21.5142 14.3255 21.6784C14.3255 21.6907 14.3258 21.7029 14.3264 21.7153C13.1681 22.035 11.948 22.2059 10.688 22.2059C9.44103 22.2059 8.23313 22.0386 7.08554 21.7251Z" fill="black" />
|
||||
</svg>
|
||||
</button>
|
||||
</a>
|
||||
|
||||
{/* Discard */}
|
||||
<a href="https://blocksurvey.io/discord">
|
||||
<a href="https://blocksurvey.io/discord"
|
||||
target="_blank" rel="noreferrer">
|
||||
<button className={styles.social_icon}>
|
||||
<svg width="22" height="17" viewBox="0 0 22 17" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M18.6232 1.39277C17.2139 0.746864 15.7166 0.277115 14.1429 0.00113806C14.1136 0.00113806 14.0842 0.00113796 14.0725 0.0363691C13.8787 0.382809 13.6614 0.82907 13.5147 1.18138C11.8118 0.928891 10.1383 0.928891 8.48247 1.18138C8.3298 0.817326 8.11254 0.376937 7.89528 0.0363691C7.87767 0.0128817 7.85418 -0.0047338 7.82482 0.00113806C6.47429 0.271244 4.74797 0.76448 3.36221 1.39277C3.35046 1.39277 3.33872 1.40451 3.33285 1.41626C0.455637 5.70271 -0.307705 9.81301 0.103325 13.9233C0.103325 13.9409 0.115069 13.9644 0.132685 13.982C2.01168 15.3678 3.83196 16.2133 5.62875 16.7594C5.6581 16.7594 5.68746 16.7594 5.70508 16.7359C6.12785 16.1605 6.50365 15.5498 6.83248 14.9039C6.85009 14.8687 6.83248 14.8217 6.79137 14.81C6.20419 14.5751 5.617 14.305 5.07092 13.9879C5.02982 13.9644 5.02394 13.8998 5.07092 13.8705C5.18836 13.7824 5.30579 13.6943 5.41149 13.6062C5.4291 13.5886 5.45846 13.5886 5.48195 13.5945C9.08727 15.2386 12.9979 15.2386 16.521 13.5945C16.5445 13.5827 16.5739 13.5886 16.5915 13.6004C16.7031 13.6943 16.8146 13.7824 16.9321 13.8705C16.9732 13.8998 16.9673 13.9644 16.9321 13.9879C16.386 14.3109 15.8164 14.5751 15.2116 14.81C15.1705 14.8276 15.1529 14.8687 15.1764 14.9098C15.5052 15.5557 15.8869 16.1605 16.292 16.7301C16.3097 16.7536 16.339 16.7653 16.3684 16.7536C18.1652 16.1957 19.9913 15.356 21.8762 13.9762C21.8938 13.9644 21.9055 13.9468 21.9055 13.9174C22.3635 9.16711 21.1363 5.05094 18.6525 1.41038C18.6525 1.39864 18.6349 1.3869 18.6232 1.3869V1.39277ZM7.3492 11.4336C6.23355 11.4336 5.35277 10.4354 5.35277 9.20234C5.35277 7.96925 6.23355 6.97104 7.3492 6.97104C8.46485 6.97104 9.34563 7.96925 9.34563 9.20234C9.34563 10.4354 8.46485 11.4336 7.3492 11.4336ZM14.689 11.4336C13.5734 11.4336 12.6926 10.4354 12.6926 9.20234C12.6926 7.96925 13.5734 6.97104 14.689 6.97104C15.8047 6.97104 16.6855 7.96925 16.6855 9.20234C16.6855 10.4354 15.8047 11.4336 14.689 11.4336Z" fill="black" />
|
||||
|
||||
@@ -15,6 +15,8 @@ export default function Poll() {
|
||||
const router = useRouter();
|
||||
const pathParams = router.query.id;
|
||||
|
||||
const [publicUrl, setPublicUrl] = useState();
|
||||
|
||||
const [pollObject, setPollObject] = useState();
|
||||
const [optionsMap, setOptionsMap] = useState({});
|
||||
const [resultsByOption, setResultsByOption] = useState({});
|
||||
@@ -51,6 +53,9 @@ export default function Poll() {
|
||||
setIsResultScreen(true)
|
||||
}
|
||||
|
||||
// Set shareable public URL
|
||||
setPublicUrl(`https://ballot.gg/p/${pollId}/${gaiaAddress}`);
|
||||
|
||||
// Fetch from Gaia
|
||||
if (pollId && gaiaAddress) {
|
||||
// Form gaia url
|
||||
@@ -117,6 +122,11 @@ export default function Poll() {
|
||||
|
||||
// Take the btc dns name
|
||||
setDns(_dns);
|
||||
|
||||
// Allow to vote
|
||||
setHoldingTokenArr([]);
|
||||
setHoldingTokenIdArr([]);
|
||||
setVotingPower(1);
|
||||
} else {
|
||||
// Not a BTC holder
|
||||
|
||||
@@ -322,7 +332,7 @@ export default function Poll() {
|
||||
resultsByPosition={resultsByPosition} total={total}
|
||||
dns={dns} alreadyVoted={alreadyVoted} noHoldingToken={noHoldingToken}
|
||||
holdingTokenArr={holdingTokenArr} holdingTokenIdArr={holdingTokenIdArr}
|
||||
votingPower={votingPower} />
|
||||
votingPower={votingPower} publicUrl={publicUrl} />
|
||||
</div>
|
||||
</div>
|
||||
</Col>
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 2.2 KiB |
@@ -2,7 +2,7 @@ import { openContractCall, openContractDeploy } from "@stacks/connect";
|
||||
import { AnchorMode, bufferCV, listCV, stringAsciiCV, uintCV } from "@stacks/transactions";
|
||||
import { getNetworkType } from "../services/auth";
|
||||
|
||||
export async function deployContract(pollObject, contractName, callbackFunction) {
|
||||
export async function deployContract(pollObject, contractName, callbackFunction, cancelCallbackFunction) {
|
||||
const contract = getContract(pollObject);
|
||||
|
||||
// Transaction options
|
||||
@@ -16,6 +16,7 @@ export async function deployContract(pollObject, contractName, callbackFunction)
|
||||
icon: window.location.origin + "/images/logo/ballot.png"
|
||||
},
|
||||
onFinish: callbackFunction,
|
||||
onCancel: cancelCallbackFunction
|
||||
};
|
||||
|
||||
// Call contract function
|
||||
@@ -324,7 +325,7 @@ export async function castMyVoteContractCall(contractAddress, contractName, vote
|
||||
network: getNetworkType(),
|
||||
appDetails: {
|
||||
name: "Ballot",
|
||||
icon: window.location.origin + "/images/logo/owllink.png",
|
||||
icon: window.location.origin + "/images/logo/ballot.png",
|
||||
},
|
||||
onFinish: callbackFunction,
|
||||
};
|
||||
|
||||
27
styles/QRCodePopup.module.css
Normal file
27
styles/QRCodePopup.module.css
Normal file
@@ -0,0 +1,27 @@
|
||||
/* Modal */
|
||||
.dashboard_modal_header_box {
|
||||
position: relative;
|
||||
padding: 20px;
|
||||
font-size: 18px;
|
||||
font-weight: 500;
|
||||
}
|
||||
.dashboard_modal_close_icon_btn_box {
|
||||
position: absolute;
|
||||
right: 20px;
|
||||
top: 20px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 50%;
|
||||
border: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: 0.3s all ease;
|
||||
}
|
||||
.dashboard_modal_body_box {
|
||||
padding: 14px 20px;
|
||||
}
|
||||
.dashboard_transactions_modal_body_box {
|
||||
max-height: 360px;
|
||||
overflow: auto;
|
||||
}
|
||||
@@ -1780,6 +1780,11 @@
|
||||
"resolved" "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz"
|
||||
"version" "1.3.2"
|
||||
|
||||
"qrcode.react@^3.1.0":
|
||||
"integrity" "sha512-oyF+Urr3oAMUG/OiOuONL3HXM+53wvuH3mtIWQrYmsXoAq0DkvZp2RYUWFSMFtbdOpuS++9v+WAkzNVkMlNW6Q=="
|
||||
"resolved" "https://registry.npmjs.org/qrcode.react/-/qrcode.react-3.1.0.tgz"
|
||||
"version" "3.1.0"
|
||||
|
||||
"query-string@^6.13.1":
|
||||
"integrity" "sha512-XDxAeVmpfu1/6IjyT/gXHOl+S0vQ9owggJ30hhWKdHAsNPOcasn5o9BW0eejZqL2e4vMjhAxoW3jVHcD6mbcYw=="
|
||||
"resolved" "https://registry.npmjs.org/query-string/-/query-string-6.14.1.tgz"
|
||||
|
||||
Reference in New Issue
Block a user