mirror of
https://github.com/alexgo-io/ballot.git
synced 2026-04-28 20:05:43 +08:00
improments : Dashboard, Builder and Poll screen has been improved.
This commit is contained in:
1
.env.development
Normal file
1
.env.development
Normal file
@@ -0,0 +1 @@
|
||||
NEXT_PUBLIC_STACKS_MAINNET_FLAG=false
|
||||
1
.env.production
Normal file
1
.env.production
Normal file
@@ -0,0 +1 @@
|
||||
NEXT_PUBLIC_STACKS_MAINNET_FLAG=true
|
||||
@@ -246,7 +246,7 @@ export default function BuilderComponent(props) {
|
||||
putFileToGaia("pollIndex.json", JSON.stringify(currentPollIndexObj), {}).then(response => {
|
||||
if (pollObject?.ipfsLocation) {
|
||||
const gaiaAddress = getUserData()?.gaiaHubConfig?.address;
|
||||
Router.replace("/p/" + pollObject?.id + "/" + gaiaAddress + "/results");
|
||||
Router.replace("/p/" + pollObject?.id + "/" + gaiaAddress);
|
||||
} else if (pollId === "new") {
|
||||
Router.replace("/builder/" + pollObject.id + "/draft");
|
||||
setPollId(pollObject.id);
|
||||
@@ -395,181 +395,175 @@ export default function BuilderComponent(props) {
|
||||
}
|
||||
|
||||
const getTitleWithOutSpecialChar = () => {
|
||||
return pollObject?.title?.replace(/\s+/g, '-').replace(/[^a-zA-Z0-9-]/g, '').substr(0, 16);
|
||||
return pollObject?.title?.replace(/\s+/g, '-').replace(/[^a-zA-Z0-9-]/g, '').toLowerCase().substr(0, 16);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Container fluid>
|
||||
<Row className="justify-content-md-center">
|
||||
<Col lg={8} md={12}>
|
||||
<div className={styles.builder_container}>
|
||||
<div className={styles.builder_container}>
|
||||
|
||||
{/* Title */}
|
||||
<h4>{pollId && pollId === "new" ? "New" : "Edit"} Poll</h4>
|
||||
{/* Title */}
|
||||
<h5>{pollId && pollId === "new" ? "New" : "Edit"} Poll</h5>
|
||||
|
||||
{pollObject && pollObject.id ?
|
||||
<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} />
|
||||
</Form.Group>
|
||||
{pollObject && pollObject.id ?
|
||||
<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} />
|
||||
</Form.Group>
|
||||
|
||||
<Form.Group className="mb-3">
|
||||
<Form.Label>Description</Form.Label>
|
||||
<Form.Control as="textarea" name="description" value={pollObject.description} rows={5} onChange={handleChange} />
|
||||
</Form.Group>
|
||||
<Form.Group className="mb-3">
|
||||
<Form.Label>Description</Form.Label>
|
||||
<Form.Control as="textarea" name="description" value={pollObject.description} rows={5} onChange={handleChange} />
|
||||
</Form.Group>
|
||||
|
||||
<Form.Group className="mb-3">
|
||||
<Form.Label>Voting system</Form.Label>
|
||||
<div>
|
||||
{['Single', 'Multiple'].map((option, index) => (
|
||||
<Form.Check
|
||||
inline
|
||||
key={index}
|
||||
<Form.Group className="mb-3">
|
||||
<Form.Label>Voting system</Form.Label>
|
||||
<div>
|
||||
{['Single', 'Multiple'].map((option, index) => (
|
||||
<Form.Check
|
||||
inline
|
||||
key={index}
|
||||
type='radio'
|
||||
name="votingSystem"
|
||||
value={option.toLowerCase()}
|
||||
checked={pollObject.votingSystem === option.toLowerCase()}
|
||||
id={`voting_system_${option}`}
|
||||
label={option}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* List of options */}
|
||||
<div style={{ margin: "10px 0 0 10px" }}>
|
||||
{pollObject?.options &&
|
||||
pollObject.options.map((option, index) => (
|
||||
<div key={index} style={{ margin: "5px 0", display: "flex", alignItems: "center" }}>
|
||||
|
||||
{pollObject?.votingSystem === "single" ?
|
||||
<Form.Check style={{ marginRight: "10px" }}
|
||||
type='radio'
|
||||
name="votingSystem"
|
||||
value={option.toLowerCase()}
|
||||
checked={pollObject.votingSystem === option.toLowerCase()}
|
||||
id={`voting_system_${option}`}
|
||||
label={option}
|
||||
onChange={handleChange}
|
||||
disabled
|
||||
/>
|
||||
:
|
||||
<Form.Check style={{ marginRight: "10px" }}
|
||||
type='checkbox'
|
||||
disabled
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* List of options */}
|
||||
<div style={{ margin: "10px 0 0 10px" }}>
|
||||
{pollObject?.options &&
|
||||
pollObject.options.map((option, index) => (
|
||||
<div key={index} style={{ margin: "5px 0", display: "flex", alignItems: "center" }}>
|
||||
|
||||
{pollObject?.votingSystem === "single" ?
|
||||
<Form.Check style={{ marginRight: "10px" }}
|
||||
type='radio'
|
||||
disabled
|
||||
/>
|
||||
:
|
||||
<Form.Check style={{ marginRight: "10px" }}
|
||||
type='checkbox'
|
||||
disabled
|
||||
/>
|
||||
}
|
||||
|
||||
<Form.Control type="text" placeholder="" value={option?.value} onChange={e => handleOptionChange(e, option)} />
|
||||
|
||||
<Button variant="secondary" style={{ marginLeft: "10px", width: "80px" }} onClick={() => { deleteOption(index); }}>Delete</Button>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
|
||||
<div style={{ display: "flex", justifyContent: "flex-end" }}>
|
||||
<Button variant="secondary" style={{ width: "75px" }} onClick={() => { addOption(); }}>Add</Button>
|
||||
<Form.Control type="text" placeholder="" value={option?.value} onChange={e => handleOptionChange(e, option)} />
|
||||
|
||||
<Button variant="secondary" style={{ marginLeft: "10px", width: "80px" }} onClick={() => { deleteOption(index); }}>Delete</Button>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
|
||||
<div style={{ display: "flex", justifyContent: "flex-end" }}>
|
||||
<Button variant="secondary" style={{ width: "75px" }} onClick={() => { addOption(); }}>Add</Button>
|
||||
</div>
|
||||
</Form.Group>
|
||||
|
||||
{/* Voting Period */}
|
||||
<div>
|
||||
<Form.Label>Voting period</Form.Label>
|
||||
<Form.Group className="mb-3" style={{ display: "flex", alignItems: "center" }}>
|
||||
<Form.Label style={{ marginRight: "10px", width: "50px" }}>Start</Form.Label>
|
||||
<Form.Control type="datetime-local" name="startAtDate" value={pollObject.startAtDate} style={{ width: "250px" }}
|
||||
min={new Date().toISOString().slice(0, 16)}
|
||||
onChange={handleChange} />
|
||||
</Form.Group>
|
||||
|
||||
<Form.Group className="mb-3" style={{ display: "flex", alignItems: "center" }}>
|
||||
<Form.Label style={{ marginRight: "10px", width: "50px" }}>End</Form.Label>
|
||||
<Form.Control type="datetime-local" name="endAtDate" value={pollObject.endAtDate} style={{ width: "250px" }}
|
||||
onChange={handleChange} disabled={!pollObject?.startAtDate} min={pollObject?.startAtDate} />
|
||||
</Form.Group>
|
||||
</div>
|
||||
|
||||
{/* Voting Strategy */}
|
||||
<div>
|
||||
<div style={{ display: "flex", alignItems: "center", padding: "10px 0" }}>
|
||||
<Form.Label>Voting strategy</Form.Label>
|
||||
<Form.Check style={{ marginLeft: "10px" }}
|
||||
inline
|
||||
type="switch"
|
||||
id="voting-strategy-id"
|
||||
name="votingStrategyFlag"
|
||||
onChange={handleChange}
|
||||
checked={pollObject.votingStrategyFlag}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{pollObject?.votingStrategyFlag &&
|
||||
<>
|
||||
<Form.Group className="mb-3">
|
||||
<Form.Label>Default strategy</Form.Label>
|
||||
<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>
|
||||
<option value="theexplorerguild">The Explorer Guild</option>
|
||||
<option value="stacksparrots">Stacks Parrots</option>
|
||||
<option value="blocksurvey">BlockSurvey</option>
|
||||
<option value="btcholders">.btc holders</option>
|
||||
<option value="other">Other</option>
|
||||
</Form.Select>
|
||||
</Form.Group>
|
||||
|
||||
{/* Voting Period */}
|
||||
<div>
|
||||
<Form.Label>Voting period</Form.Label>
|
||||
<Form.Group className="mb-3" style={{ display: "flex", alignItems: "center" }}>
|
||||
<Form.Label style={{ marginRight: "10px", width: "50px" }}>Start</Form.Label>
|
||||
<Form.Control type="datetime-local" name="startAtDate" value={pollObject.startAtDate} style={{ width: "250px" }}
|
||||
min={new Date().toISOString().slice(0, 16)}
|
||||
onChange={handleChange} />
|
||||
</Form.Group>
|
||||
|
||||
<Form.Group className="mb-3" style={{ display: "flex", alignItems: "center" }}>
|
||||
<Form.Label style={{ marginRight: "10px", width: "50px" }}>End</Form.Label>
|
||||
<Form.Control type="datetime-local" name="endAtDate" value={pollObject.endAtDate} style={{ width: "250px" }}
|
||||
onChange={handleChange} disabled={!pollObject?.startAtDate} min={pollObject?.startAtDate} />
|
||||
</Form.Group>
|
||||
</div>
|
||||
|
||||
{/* Voting Strategy */}
|
||||
<div>
|
||||
<div style={{ display: "flex", alignItems: "center", padding: "10px 0" }}>
|
||||
<Form.Label>Voting strategy</Form.Label>
|
||||
<Form.Check style={{ marginLeft: "10px" }}
|
||||
inline
|
||||
type="switch"
|
||||
id="voting-strategy-id"
|
||||
name="votingStrategyFlag"
|
||||
onChange={handleChange}
|
||||
checked={pollObject.votingStrategyFlag}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{pollObject?.votingStrategyFlag &&
|
||||
<>
|
||||
<Form.Group className="mb-3">
|
||||
<Form.Label>Default strategy</Form.Label>
|
||||
<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>
|
||||
<option value="theexplorerguild">The Explorer Guild</option>
|
||||
<option value="stacksparrots">Stacks Parrots</option>
|
||||
<option value="blocksurvey">BlockSurvey</option>
|
||||
<option value="btcholders">.btc holders</option>
|
||||
<option value="other">Other</option>
|
||||
</Form.Select>
|
||||
</Form.Group>
|
||||
|
||||
{/* Only for other */}
|
||||
{pollObject?.votingStrategyTemplate && pollObject?.votingStrategyTemplate == "other" &&
|
||||
<>
|
||||
<Form.Group className="mb-3">
|
||||
<Form.Label>NFT name</Form.Label>
|
||||
<Form.Control type="text" name="strategyNFTName" value={pollObject.strategyNFTName}
|
||||
onChange={handleChange} />
|
||||
</Form.Group>
|
||||
<Form.Group className="mb-3">
|
||||
<Form.Label>Contract name</Form.Label>
|
||||
<Form.Control type="text" name="strategyContractName" value={pollObject.strategyContractName}
|
||||
onChange={handleChange}
|
||||
placeholder="ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM.contract" />
|
||||
</Form.Group>
|
||||
</>
|
||||
}
|
||||
</>
|
||||
}
|
||||
</div>
|
||||
|
||||
{/* Error Message */}
|
||||
{errorMessage &&
|
||||
<div style={{ margin: "10px 0" }}>
|
||||
<span style={{ fontSize: "14px" }}>{errorMessage}</span>
|
||||
</div>
|
||||
{/* Only for other */}
|
||||
{pollObject?.votingStrategyTemplate && pollObject?.votingStrategyTemplate == "other" &&
|
||||
<>
|
||||
<Form.Group className="mb-3">
|
||||
<Form.Label>NFT name</Form.Label>
|
||||
<Form.Control type="text" name="strategyNFTName" value={pollObject.strategyNFTName}
|
||||
onChange={handleChange} />
|
||||
</Form.Group>
|
||||
<Form.Group className="mb-3">
|
||||
<Form.Label>Contract name</Form.Label>
|
||||
<Form.Control type="text" name="strategyContractName" value={pollObject.strategyContractName}
|
||||
onChange={handleChange}
|
||||
placeholder="ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM.contract" />
|
||||
</Form.Group>
|
||||
</>
|
||||
}
|
||||
|
||||
{/* CTA */}
|
||||
{
|
||||
pollId !== "new" &&
|
||||
<Button variant="secondary" onClick={() => { handleShow() }}>Preview</Button>
|
||||
}
|
||||
{' '}
|
||||
<Button variant="secondary" onClick={() => { savePollToGaia() }} disabled={isProcessing || pollObject?.status != "draft"}>
|
||||
Save
|
||||
</Button>
|
||||
{' '}
|
||||
<Button variant="secondary" onClick={() => { publishPoll() }} disabled={isProcessing || pollObject?.status != "draft"}>
|
||||
Publish
|
||||
</Button>
|
||||
{' '}
|
||||
{currentProgressMessage &&
|
||||
<span>{currentProgressMessage}</span>
|
||||
}
|
||||
</Form>
|
||||
:
|
||||
<>Loading...</>
|
||||
</>
|
||||
}
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
|
||||
{/* Error Message */}
|
||||
{errorMessage &&
|
||||
<div style={{ margin: "10px 0" }}>
|
||||
<span style={{ fontSize: "14px" }}>{errorMessage}</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
{/* CTA */}
|
||||
{
|
||||
pollId !== "new" &&
|
||||
<Button variant="secondary" onClick={() => { handleShow() }}>Preview</Button>
|
||||
}
|
||||
{' '}
|
||||
<Button variant="secondary" onClick={() => { savePollToGaia() }} disabled={isProcessing || pollObject?.status != "draft"}>
|
||||
Save
|
||||
</Button>
|
||||
{' '}
|
||||
<Button variant="secondary" onClick={() => { publishPoll() }} disabled={isProcessing || pollObject?.status != "draft"}>
|
||||
Publish
|
||||
</Button>
|
||||
{' '}
|
||||
{currentProgressMessage &&
|
||||
<span>{currentProgressMessage}</span>
|
||||
}
|
||||
</Form>
|
||||
:
|
||||
<>Loading...</>
|
||||
}
|
||||
</div>
|
||||
|
||||
{/* Preview popup */}
|
||||
<PreviewComponent pollObject={pollObject} show={show} handleClose={handleClose} />
|
||||
|
||||
83
components/common/DashboardNavBarComponent.js
Normal file
83
components/common/DashboardNavBarComponent.js
Normal file
@@ -0,0 +1,83 @@
|
||||
import Link from "next/link";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Button } from "react-bootstrap";
|
||||
import Dropdown from 'react-bootstrap/Dropdown';
|
||||
import DropdownButton from 'react-bootstrap/DropdownButton';
|
||||
import { authenticate, signOut, userSession } from "../../services/auth";
|
||||
import { getDomainNamesFromBlockchain } from "../../services/utils";
|
||||
|
||||
export function DashboardNavBarComponent() {
|
||||
// Variables
|
||||
const [displayUsername, setDisplayUsername] = useState();
|
||||
|
||||
const [isUserSignedIn, setIsUserSignedIn] = useState(false);
|
||||
|
||||
// Functions
|
||||
useEffect(() => {
|
||||
getDisplayUsername();
|
||||
|
||||
if (userSession && userSession.isUserSignedIn()) {
|
||||
setIsUserSignedIn(true)
|
||||
}
|
||||
}, []);
|
||||
|
||||
const getDisplayUsername = async () => {
|
||||
const _username = await getDomainNamesFromBlockchain();
|
||||
setDisplayUsername(_username);
|
||||
}
|
||||
|
||||
// UI
|
||||
return (
|
||||
<>
|
||||
<div style={{ margin: "30px 0", display: "flex", justifyContent: "space-between", alignItems: "center" }}>
|
||||
<div>
|
||||
<a href={isUserSignedIn ? "/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>
|
||||
{
|
||||
isUserSignedIn ?
|
||||
<div style={{ display: "flex", gap: "26px", alignItems: "center" }}>
|
||||
<div style={{ margin: "10px 0" }}>
|
||||
<Link href="/builder/new">
|
||||
<Button variant="secondary">
|
||||
+ New Poll
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<div style={{ margin: "10px 0" }}>
|
||||
<Link href="/all-polls">
|
||||
<Button variant="secondary">
|
||||
All Polls
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{/* Profile */}
|
||||
<div>
|
||||
<DropdownButton
|
||||
align="end"
|
||||
title={displayUsername ? displayUsername : "..."}
|
||||
id="dropdown-menu-align-end"
|
||||
variant="secondary"
|
||||
>
|
||||
<Dropdown.Item eventKey="1" onClick={() => { signOut() }}>Logout</Dropdown.Item>
|
||||
</DropdownButton>
|
||||
</div>
|
||||
</div>
|
||||
:
|
||||
<div>
|
||||
<Button variant="dark"
|
||||
onClick={() => { authenticate() }}>
|
||||
Sign up
|
||||
</Button>
|
||||
</div>
|
||||
}
|
||||
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -27,10 +27,10 @@ export default function HeaderComponent(props) {
|
||||
{pollObject && pollObject.id &&
|
||||
<>
|
||||
{/* Title */}
|
||||
<h4>{pollObject?.title}</h4>
|
||||
<h1 style={{ fontSize: "30px" }}>{pollObject?.title}</h1>
|
||||
|
||||
{/* Info Bar */}
|
||||
<div style={{ display: "flex", alignItems: "center", columnGap: "20px", fontSize: "14px" }}>
|
||||
<div style={{ display: "flex", alignItems: "center", columnGap: "20px", fontSize: "14px", marginBottom: "30px" }}>
|
||||
{/* Status */}
|
||||
<div>
|
||||
{pollObject?.status == "draft" ? "Draft" : "Active"} {' '}
|
||||
@@ -40,7 +40,7 @@ export default function HeaderComponent(props) {
|
||||
<div>
|
||||
<span style={{ color: "#737373" }}>Created by</span> {' '}
|
||||
{pollObject?.userStxAddress &&
|
||||
<a target="_blank" rel="noreferrer" href={formStacksExplorerUrl(pollObject?.userStxAddress)}>
|
||||
<a className="ballot_link" target="_blank" rel="noreferrer" href={formStacksExplorerUrl(pollObject?.userStxAddress)}>
|
||||
<span>
|
||||
{pollObject?.userStxAddress?.substring(0, 10)} { }
|
||||
<svg
|
||||
@@ -54,7 +54,7 @@ export default function HeaderComponent(props) {
|
||||
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"
|
||||
fill="initial"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
@@ -90,7 +90,7 @@ export default function HeaderComponent(props) {
|
||||
</div>
|
||||
|
||||
{/* Description */}
|
||||
<div style={{ margin: "20px 0", whiteSpace: "pre-wrap" }}>
|
||||
<div style={{ marginBottom: "30px", whiteSpace: "pre-wrap" }}>
|
||||
<h5>Description</h5>
|
||||
<p>
|
||||
{pollObject?.description}
|
||||
|
||||
@@ -13,7 +13,7 @@ export default function InformationComponent(props) {
|
||||
<>
|
||||
{pollObject && pollObject.id &&
|
||||
<>
|
||||
<div style={{ padding: "10px", border: "1px solid #cccccc", borderRadius: "5px", width: "100%" }}>
|
||||
<div style={{ padding: "10px", border: "1px solid #cccccc", borderRadius: "5px", width: "100%", overflow: "auto" }}>
|
||||
{/* Title */}
|
||||
<h6>Information</h6>
|
||||
|
||||
@@ -23,8 +23,8 @@ export default function InformationComponent(props) {
|
||||
pollObject?.publishedInfo?.txId &&
|
||||
<div>
|
||||
Contract
|
||||
<a target="_blank" rel="noreferrer" href={formStacksExplorerUrl(pollObject?.publishedInfo?.txId)}>
|
||||
<span style={{ float: "right", fontWeight: "bold" }}>
|
||||
<span style={{ float: "right", fontWeight: "bold" }}>
|
||||
<a className="ballot_link" target="_blank" rel="noreferrer" href={formStacksExplorerUrl(pollObject?.publishedInfo?.txId)}>
|
||||
{pollObject?.publishedInfo?.contractName.substring(0, 10)} { }
|
||||
<svg
|
||||
width="10"
|
||||
@@ -37,19 +37,19 @@ export default function InformationComponent(props) {
|
||||
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"
|
||||
fill="initial"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
{
|
||||
pollObject?.ipfsLocation &&
|
||||
<div>
|
||||
IPFS
|
||||
<a target="_blank" rel="noreferrer" href={`${Constants.IPFS_GATEWAY}${pollObject?.ipfsLocation}`}>
|
||||
<span style={{ float: "right", fontWeight: "bold" }}>
|
||||
<span style={{ float: "right", fontWeight: "bold" }}>
|
||||
<a className="ballot_link" target="_blank" rel="noreferrer" href={`${Constants.IPFS_GATEWAY}${pollObject?.ipfsLocation}`}>
|
||||
#{pollObject?.ipfsLocation.substring(0, 8)} { }
|
||||
<svg
|
||||
width="10"
|
||||
@@ -62,19 +62,19 @@ export default function InformationComponent(props) {
|
||||
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"
|
||||
fill="initial"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
{
|
||||
pollObject?.strategyContractName &&
|
||||
<div>
|
||||
Strategy
|
||||
<a target="_blank" rel="noreferrer" href={formStacksExplorerUrl(pollObject?.strategyContractName)}>
|
||||
<span style={{ float: "right", fontWeight: "bold" }}>
|
||||
<span style={{ float: "right", fontWeight: "bold" }}>
|
||||
<a className="ballot_link" target="_blank" rel="noreferrer" href={formStacksExplorerUrl(pollObject?.strategyContractName)}>
|
||||
{pollObject?.strategyContractName.substring(0, 10)} { }
|
||||
<svg
|
||||
width="10"
|
||||
@@ -87,11 +87,11 @@ export default function InformationComponent(props) {
|
||||
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"
|
||||
fill="initial"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
<div>
|
||||
|
||||
@@ -56,11 +56,11 @@ export default function DashboardAllPollsComponent() {
|
||||
}
|
||||
|
||||
return (
|
||||
<Link href={pollIndexObject?.status == "draft" ? `/builder/${pollIndexObject.id}/draft` : `/p/${pollIndexObject.id}/${gaiaAddress}/results`}>
|
||||
<Link href={pollIndexObject?.status == "draft" ? `/builder/${pollIndexObject.id}/draft` : `/p/${pollIndexObject.id}/${gaiaAddress}`}>
|
||||
<div style={{ border: "1px solid black", borderRadius: "4px", padding: "10px", marginBottom: "10px", cursor: "pointer" }}>
|
||||
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
|
||||
<div>
|
||||
<div style={{ fontSize: "16px", fontWeight: "bold" }}>
|
||||
<div style={{ fontSize: "16px", fontWeight: 600, marginBottom: "10px" }}>
|
||||
{pollIndexObject?.title ? pollIndexObject?.title : "..."}
|
||||
</div>
|
||||
|
||||
@@ -90,38 +90,28 @@ export default function DashboardAllPollsComponent() {
|
||||
// Design
|
||||
return (
|
||||
<>
|
||||
<Container fluid>
|
||||
<Row className="justify-content-md-center">
|
||||
<Col lg={8} md={12}>
|
||||
<div className={styles.dashboard_container}>
|
||||
{/* Title */}
|
||||
<h5>All Polls</h5>
|
||||
|
||||
<div className={styles.dashboard_container}>
|
||||
{/* Welcome */}
|
||||
|
||||
{/* Title */}
|
||||
<h4>All Polls</h4>
|
||||
|
||||
{/* List of all polls */}
|
||||
<div style={{ padding: "10px 0" }}>
|
||||
{allPolls?.list && allPolls?.ref ?
|
||||
allPolls?.list?.length > 0 ?
|
||||
allPolls?.list.map(
|
||||
(pollId, i) => (
|
||||
<div key={i}>
|
||||
{getEachRow(allPolls.ref[pollId])}
|
||||
</div>
|
||||
)
|
||||
)
|
||||
:
|
||||
<>No data found</>
|
||||
:
|
||||
<>Loading...</>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
{/* List of all polls */}
|
||||
<div style={{ padding: "10px 0" }}>
|
||||
{allPolls?.list && allPolls?.ref ?
|
||||
allPolls?.list?.length > 0 ?
|
||||
allPolls?.list.map(
|
||||
(pollId, i) => (
|
||||
<div key={i}>
|
||||
{getEachRow(allPolls.ref[pollId])}
|
||||
</div>
|
||||
)
|
||||
)
|
||||
:
|
||||
<>No data found</>
|
||||
:
|
||||
<>Loading...</>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -69,136 +69,130 @@ export default function PollComponent(props) {
|
||||
}
|
||||
}
|
||||
|
||||
// Design
|
||||
return (
|
||||
<>
|
||||
<Container fluid>
|
||||
<Row className="justify-content-md-center">
|
||||
<Col lg={isPreview ? 12 : 8} md={12}>
|
||||
<div className={styles.results_container}>
|
||||
<div className={styles.poll_container}>
|
||||
{pollObject && pollObject.id ?
|
||||
<>
|
||||
<div style={{ margin: "0px 0 50px 0" }}>
|
||||
<div className="row">
|
||||
{/* Left Side */}
|
||||
<div className="col-sm-12 col-md-8">
|
||||
{/* Header */}
|
||||
<HeaderComponent pollObject={pollObject} publicUrl={publicUrl} />
|
||||
|
||||
{pollObject && pollObject.id ?
|
||||
<>
|
||||
<div className="row">
|
||||
{/* Left Side */}
|
||||
<div className="col-sm-12 col-md-8">
|
||||
{/* Header */}
|
||||
<HeaderComponent pollObject={pollObject} publicUrl={publicUrl} />
|
||||
{/* Cast your vote */}
|
||||
<div style={{ marginBottom: "30px" }}>
|
||||
<h5>Cast your vote</h5>
|
||||
<div>
|
||||
<Form>
|
||||
<Form.Group className="mb-3">
|
||||
{pollObject?.options.map((option, index) => (
|
||||
<Form.Check
|
||||
key={index}
|
||||
type={pollObject?.votingSystem == "single" ? "radio" : "checkbox"}
|
||||
name="vote"
|
||||
value={option.id}
|
||||
label={option.value}
|
||||
id={option.id}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
))}
|
||||
|
||||
{/* Cast your vote */}
|
||||
<div style={{ marginTop: "20px" }}>
|
||||
<h5>Cast your vote</h5>
|
||||
<div>
|
||||
<Form>
|
||||
<Form.Group className="mb-3">
|
||||
{pollObject?.options.map((option, index) => (
|
||||
<Form.Check
|
||||
key={index}
|
||||
type={pollObject?.votingSystem == "single" ? "radio" : "checkbox"}
|
||||
name="vote"
|
||||
value={option.id}
|
||||
label={option.value}
|
||||
id={option.id}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
))}
|
||||
{userSession && userSession.isUserSignedIn() ?
|
||||
<Button variant="dark" style={{ marginTop: "10px" }}
|
||||
disabled={(isPreview || !holdingTokenArr || alreadyVoted) ? true : false}
|
||||
onClick={() => { castMyVote() }}>
|
||||
Vote
|
||||
</Button>
|
||||
:
|
||||
<Button variant="dark" style={{ marginTop: "10px" }}
|
||||
onClick={() => { authenticate(window?.location?.href) }}>
|
||||
Login to Vote
|
||||
</Button>
|
||||
}
|
||||
|
||||
{userSession && userSession.isUserSignedIn() ?
|
||||
<Button variant="dark" style={{ marginTop: "10px" }}
|
||||
disabled={(isPreview || !holdingTokenArr || alreadyVoted) ? true : false}
|
||||
onClick={() => { castMyVote() }}>
|
||||
Vote
|
||||
</Button>
|
||||
:
|
||||
<Button variant="dark" style={{ marginTop: "10px" }}
|
||||
onClick={() => { authenticate() }}>
|
||||
Vote
|
||||
</Button>
|
||||
}
|
||||
{/* Holdings Required */}
|
||||
{noHoldingToken &&
|
||||
<div style={{ fontSize: "14px", color: "red" }}>
|
||||
Holdings required to vote this poll.
|
||||
</div>
|
||||
}
|
||||
|
||||
{/* Holdings Required */}
|
||||
{noHoldingToken &&
|
||||
<div style={{ fontSize: "14px", color: "red" }}>
|
||||
Holdings required to vote this poll.
|
||||
</div>
|
||||
}
|
||||
|
||||
{/* Already voted */}
|
||||
{alreadyVoted &&
|
||||
<div style={{ fontSize: "14px", color: "red" }}>
|
||||
Your vote has already been cast.
|
||||
</div>
|
||||
}
|
||||
</Form.Group>
|
||||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Results */}
|
||||
<div style={{ marginTop: "20px" }}>
|
||||
<h5>Votes ({total})</h5>
|
||||
<Table striped bordered hover>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Address</th>
|
||||
<th>Option</th>
|
||||
<th>Voting Power</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{Object.keys(resultsByPosition).map((position, index) => (
|
||||
<tr key={index}>
|
||||
<td>{resultsByPosition[position]?.address &&
|
||||
<a target="_blank" rel="noreferrer" href={formStacksExplorerUrl(resultsByPosition[position]?.address)}>
|
||||
<span>
|
||||
{resultsByPosition[position]?.address} { }
|
||||
<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>
|
||||
|
||||
}</td>
|
||||
<td>
|
||||
{Object.keys(resultsByPosition[position]?.vote).map((optionId, voteIndex) => (
|
||||
<div key={voteIndex}>
|
||||
{optionsMap[optionId] ? optionsMap[optionId] : "-"}
|
||||
</div>
|
||||
))}
|
||||
</td>
|
||||
<td>1</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</Table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right Side */}
|
||||
<div className="col-sm-12 col-md-4">
|
||||
{/* Information */}
|
||||
<InformationComponent pollObject={pollObject} resultsByOption={resultsByOption} />
|
||||
{/* Already voted */}
|
||||
{alreadyVoted &&
|
||||
<div style={{ fontSize: "14px", color: "red" }}>
|
||||
Your vote has already been cast.
|
||||
</div>
|
||||
}
|
||||
</Form.Group>
|
||||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
:
|
||||
<>Loading...</>
|
||||
}
|
||||
|
||||
{/* Results */}
|
||||
<div style={{ marginTop: "20px" }}>
|
||||
<h5>Votes ({total})</h5>
|
||||
<Table striped bordered hover>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Address</th>
|
||||
<th>Option</th>
|
||||
<th>Voting Power</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{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)}>
|
||||
<span>
|
||||
{resultsByPosition[position]?.address} { }
|
||||
<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="initial"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
}</td>
|
||||
<td>
|
||||
{Object.keys(resultsByPosition[position]?.vote).map((optionId, voteIndex) => (
|
||||
<div key={voteIndex}>
|
||||
{optionsMap[optionId] ? optionsMap[optionId] : "-"}
|
||||
</div>
|
||||
))}
|
||||
</td>
|
||||
<td>1</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</Table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right Side */}
|
||||
<div className="col-sm-12 col-md-4">
|
||||
{/* Information */}
|
||||
<InformationComponent pollObject={pollObject} resultsByOption={resultsByOption} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
</>
|
||||
:
|
||||
<>Loading...</>
|
||||
}
|
||||
</div>
|
||||
|
||||
<Modal show={show} onHide={handleClose}>
|
||||
<Modal.Header closeButton>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Container, Row, Col } from "react-bootstrap";
|
||||
import { Col, Container, Row } from "react-bootstrap";
|
||||
import { DashboardNavBarComponent } from "../components/common/DashboardNavBarComponent";
|
||||
import DashboardAllPollsComponent from "../components/dashboard/DashboardAllPollsComponent";
|
||||
import DashboardMenuComponent from "../components/dashboard/DashboardMenuComponent";
|
||||
import styles from "../styles/Dashboard.module.css";
|
||||
|
||||
export default function Dashboard() {
|
||||
// Variables
|
||||
@@ -10,23 +9,14 @@ export default function Dashboard() {
|
||||
return (
|
||||
<>
|
||||
{/* Outer layer */}
|
||||
<Container fluid>
|
||||
<Container>
|
||||
<Row>
|
||||
<Col md={12} className={styles.full_container}>
|
||||
{/* Inner layer */}
|
||||
<div className={styles.dashboard}>
|
||||
{/* Left side */}
|
||||
<div className={"d-none d-md-block " + styles.dashboard_left}>
|
||||
{/* Menu */}
|
||||
<DashboardMenuComponent />
|
||||
</div>
|
||||
<Col md={12}>
|
||||
{/* Dashboard nav bar */}
|
||||
<DashboardNavBarComponent />
|
||||
|
||||
{/* Right side */}
|
||||
<div className={styles.dashboard_center}>
|
||||
{/* List of all polls */}
|
||||
<DashboardAllPollsComponent />
|
||||
</div>
|
||||
</div>
|
||||
{/* List of all polls */}
|
||||
<DashboardAllPollsComponent />
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { useRouter } from "next/router";
|
||||
import { Col, Container, Row } from "react-bootstrap";
|
||||
import BuilderComponent from "../../components/builder/BuilderComponent";
|
||||
import DashboardMenuComponent from "../../components/dashboard/DashboardMenuComponent";
|
||||
import styles from "../../styles/Builder.module.css";
|
||||
import { DashboardNavBarComponent } from "../../components/common/DashboardNavBarComponent";
|
||||
|
||||
export default function Builder() {
|
||||
// Variables
|
||||
@@ -13,22 +12,14 @@ export default function Builder() {
|
||||
return (
|
||||
<>
|
||||
{/* Outer layer */}
|
||||
<Container fluid>
|
||||
<Container>
|
||||
<Row>
|
||||
<Col md={12} className={styles.full_container}>
|
||||
{/* Inner layer */}
|
||||
<div className={styles.builder}>
|
||||
{/* Left side */}
|
||||
<div className={"d-none d-md-block " + styles.builder_left}>
|
||||
{/* Menu */}
|
||||
<DashboardMenuComponent />
|
||||
</div>
|
||||
<Col md={12}>
|
||||
{/* Dashboard nav bar */}
|
||||
<DashboardNavBarComponent />
|
||||
|
||||
{/* Right side */}
|
||||
<div className={styles.builder_center}>
|
||||
<BuilderComponent pathParams={pathParams} />
|
||||
</div>
|
||||
</div>
|
||||
{/* Body */}
|
||||
<BuilderComponent pathParams={pathParams} />
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
|
||||
@@ -264,7 +264,7 @@ export default function Home() {
|
||||
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" />
|
||||
<path fillRule="evenodd" clipRule="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>
|
||||
|
||||
@@ -5,7 +5,7 @@ import { useRouter } from "next/router";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Col, Container, Row } from "react-bootstrap";
|
||||
import { Constants } from "../../common/constants";
|
||||
import DashboardMenuComponent from "../../components/dashboard/DashboardMenuComponent";
|
||||
import { DashboardNavBarComponent } from "../../components/common/DashboardNavBarComponent";
|
||||
import PollComponent from "../../components/poll/PollComponent";
|
||||
import { getMyStxAddress, getStacksAPIPrefix, userSession } from "../../services/auth";
|
||||
import styles from "../../styles/Poll.module.css";
|
||||
@@ -35,9 +35,6 @@ export default function Poll() {
|
||||
// Voting power
|
||||
const [votingPower, setVotingPower] = useState();
|
||||
|
||||
// Result screen flag
|
||||
const [isResultScreen, setIsResultScreen] = useState(false);
|
||||
|
||||
// Function
|
||||
useEffect(() => {
|
||||
let pollId, gaiaAddress;
|
||||
@@ -49,10 +46,6 @@ export default function Poll() {
|
||||
gaiaAddress = pathParams[1];
|
||||
}
|
||||
|
||||
if (pathParams && pathParams?.[2]) {
|
||||
setIsResultScreen(true)
|
||||
}
|
||||
|
||||
// Set shareable public URL
|
||||
setPublicUrl(`https://ballot.gg/p/${pollId}/${gaiaAddress}`);
|
||||
|
||||
@@ -312,29 +305,18 @@ export default function Poll() {
|
||||
return (
|
||||
<>
|
||||
{/* Outer layer */}
|
||||
<Container fluid>
|
||||
<Container>
|
||||
<Row>
|
||||
<Col md={12} className={styles.full_container}>
|
||||
{/* Inner layer */}
|
||||
<div className={styles.results}>
|
||||
{/* Left side */}
|
||||
{
|
||||
isResultScreen &&
|
||||
<div className={"d-none d-md-block " + styles.results_left}>
|
||||
{/* Menu */}
|
||||
<DashboardMenuComponent />
|
||||
</div>
|
||||
}
|
||||
<Col md={12}>
|
||||
{/* Nav bar */}
|
||||
<DashboardNavBarComponent />
|
||||
|
||||
{/* Right side */}
|
||||
<div className={styles.results_center}>
|
||||
<PollComponent pollObject={pollObject} optionsMap={optionsMap} resultsByOption={resultsByOption}
|
||||
resultsByPosition={resultsByPosition} total={total}
|
||||
dns={dns} alreadyVoted={alreadyVoted} noHoldingToken={noHoldingToken}
|
||||
holdingTokenArr={holdingTokenArr} holdingTokenIdArr={holdingTokenIdArr}
|
||||
votingPower={votingPower} publicUrl={publicUrl} />
|
||||
</div>
|
||||
</div>
|
||||
{/* Body */}
|
||||
<PollComponent pollObject={pollObject} optionsMap={optionsMap} resultsByOption={resultsByOption}
|
||||
resultsByPosition={resultsByPosition} total={total}
|
||||
dns={dns} alreadyVoted={alreadyVoted} noHoldingToken={noHoldingToken}
|
||||
holdingTokenArr={holdingTokenArr} holdingTokenIdArr={holdingTokenIdArr}
|
||||
votingPower={votingPower} publicUrl={publicUrl} />
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
|
||||
@@ -30,7 +30,7 @@ export function alreadyLoggedIn() {
|
||||
/**
|
||||
* Sign in
|
||||
*/
|
||||
export function authenticate() {
|
||||
export function authenticate(redirectTo) {
|
||||
// Sign up
|
||||
if (!userSession.isUserSignedIn() && !userSession.isSignInPending()) {
|
||||
showConnect({
|
||||
@@ -40,8 +40,13 @@ export function authenticate() {
|
||||
},
|
||||
redirectTo: "/",
|
||||
onFinish: () => {
|
||||
// Redirect to dashboard
|
||||
window.location.assign("/all-polls");
|
||||
if (redirectTo) {
|
||||
// Redirect to dashboard
|
||||
window.location.assign(redirectTo);
|
||||
} else {
|
||||
// Redirect to dashboard
|
||||
window.location.assign("/all-polls");
|
||||
}
|
||||
},
|
||||
userSession: userSession,
|
||||
});
|
||||
|
||||
@@ -299,7 +299,7 @@ export async function castMyVoteContractCall(contractAddress, contractName, vote
|
||||
|
||||
// Parse dns
|
||||
let domain, namespace;
|
||||
if (dns && dns.split(".").length <= 1) {
|
||||
if (dns && dns.split(".").length > 1) {
|
||||
// Parse dns
|
||||
let splittedDns = dns.split(".");
|
||||
domain = splittedDns.pop();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Constants } from "../common/constants";
|
||||
import { getStacksAPIPrefix } from "../services/auth";
|
||||
import { getMyStxAddress, getStacksAPIPrefix, getUserData, userSession } from "../services/auth";
|
||||
|
||||
export async function getRecentBlock() {
|
||||
// Get btc domain for logged in user
|
||||
@@ -22,4 +22,50 @@ export function formStacksExplorerUrl(txId) {
|
||||
|
||||
export function convertToDisplayDateFormat(date) {
|
||||
return new Date(date).toLocaleDateString('general', { month: 'short', day: 'numeric', year: 'numeric', hour: 'numeric', hour12: true, minute: 'numeric' })
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch and store once
|
||||
var displayUsername;
|
||||
export async function getDomainNamesFromBlockchain() {
|
||||
if (displayUsername) {
|
||||
return displayUsername;
|
||||
}
|
||||
|
||||
// If user is not signed in, just return
|
||||
if (!userSession.isUserSignedIn()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get btc domain for logged in user
|
||||
const response = await fetch(
|
||||
getStacksAPIPrefix() + "/v1/addresses/stacks/" + getMyStxAddress()
|
||||
);
|
||||
const responseObject = await response.json();
|
||||
|
||||
// Testnet code
|
||||
if (Constants.STACKS_MAINNET_FLAG == false) {
|
||||
displayUsername = getMyStxAddress().substr(-5) + ".btc";
|
||||
return displayUsername;
|
||||
}
|
||||
|
||||
// Get btc dns
|
||||
if (responseObject?.names?.length > 0) {
|
||||
const btcDNS = responseObject.names.filter((bns) =>
|
||||
bns.endsWith(".btc")
|
||||
);
|
||||
|
||||
// Check does BTC dns is available
|
||||
if (btcDNS && btcDNS.length > 0) {
|
||||
// BTC holder
|
||||
displayUsername = btcDNS[0];
|
||||
|
||||
} else {
|
||||
// Not a BTC holder
|
||||
displayUsername = responseObject.names?.[0];
|
||||
}
|
||||
} else {
|
||||
displayUsername = getUserData().identityAddress;
|
||||
}
|
||||
|
||||
return displayUsername;
|
||||
};
|
||||
@@ -1,39 +1,3 @@
|
||||
/* Full container */
|
||||
.full_container {
|
||||
height: 100vh;
|
||||
overflow-y: hidden;
|
||||
overflow-x: hidden;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
/* Builder Layout */
|
||||
.builder {
|
||||
height: 100%;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
z-index: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
.builder_left {
|
||||
flex-shrink: 0;
|
||||
position: relative;
|
||||
width: 220px;
|
||||
height: 100%;
|
||||
box-shadow: 1px 0px 0px rgba(100, 100, 100, 0.15);
|
||||
z-index: 999;
|
||||
}
|
||||
.builder_center {
|
||||
height: 100%;
|
||||
flex-grow: 1;
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.builder_container {
|
||||
/* padding-left: 60px;
|
||||
padding-right: 60px; */
|
||||
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
@@ -1,38 +1,3 @@
|
||||
/* Full container */
|
||||
.full_container {
|
||||
height: 100vh;
|
||||
overflow-y: hidden;
|
||||
overflow-x: hidden;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
/* Dashboard Layout */
|
||||
.dashboard {
|
||||
height: 100%;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
z-index: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
.dashboard_left {
|
||||
flex-shrink: 0;
|
||||
position: relative;
|
||||
width: 220px;
|
||||
height: 100%;
|
||||
box-shadow: 1px 0px 0px rgba(100, 100, 100, 0.15);
|
||||
z-index: 999;
|
||||
}
|
||||
.dashboard_center {
|
||||
height: 100%;
|
||||
flex-grow: 1;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.dashboard_container {
|
||||
/* padding-left: 60px;
|
||||
padding-right: 60px; */
|
||||
|
||||
padding-top: 10px;
|
||||
}
|
||||
}
|
||||
@@ -1,39 +1,3 @@
|
||||
/* Full container */
|
||||
.full_container {
|
||||
height: 100vh;
|
||||
overflow-y: hidden;
|
||||
overflow-x: hidden;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
/* Results Layout */
|
||||
.results {
|
||||
height: 100%;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
z-index: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
.results_left {
|
||||
flex-shrink: 0;
|
||||
position: relative;
|
||||
width: 220px;
|
||||
height: 100%;
|
||||
box-shadow: 1px 0px 0px rgba(100, 100, 100, 0.15);
|
||||
z-index: 999;
|
||||
}
|
||||
.results_center {
|
||||
height: 100%;
|
||||
flex-grow: 1;
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.results_container {
|
||||
/* padding-left: 60px;
|
||||
padding-right: 60px; */
|
||||
|
||||
.poll_container {
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
@@ -13,4 +13,14 @@
|
||||
.btn_big {
|
||||
padding-left: 2rem;
|
||||
padding-right: 2rem;
|
||||
}
|
||||
|
||||
.ballot_link {
|
||||
color: black;
|
||||
text-decoration: underline;
|
||||
fill: black
|
||||
}
|
||||
|
||||
.ballot_link:hover {
|
||||
color: black;
|
||||
}
|
||||
Reference in New Issue
Block a user