(add) ballot card footer is now a component

This commit is contained in:
Gabriel Rodriguez Alsina 2018-12-21 18:41:29 -03:00
parent b59b4ab8da
commit 788c645bb9
17 changed files with 291 additions and 215 deletions

View File

@ -48,6 +48,12 @@ class App extends Component {
}
}
getVotingNetworkBranch = () => {
const { contractsStore } = this.props
return contractsStore.netId ? getNetworkBranch(contractsStore.netId) : null
}
onBallotsRender = () => {
return <Ballots isActiveFilter={false} />
}
@ -62,6 +68,7 @@ class App extends Component {
onNewBallotRender = () => {
const { commonStore, contractsStore } = this.props
if (!contractsStore.web3Instance) {
if (!commonStore.loading) {
swal({
@ -73,7 +80,7 @@ class App extends Component {
}
return null
}
return <NewBallot />
return <NewBallot networkBranch={this.getVotingNetworkBranch()} />
}
onSettingsRender = () => {
@ -117,7 +124,7 @@ class App extends Component {
render() {
const { commonStore, contractsStore } = this.props
const networkBranch = contractsStore.netId ? getNetworkBranch(contractsStore.netId) : null
const networkBranch = this.getVotingNetworkBranch()
return networkBranch ? (
<div className={`lo-App ${this.state.showMobileMenu ? 'lo-App-menu-open' : ''}`}>

View File

@ -1,59 +0,0 @@
.ballots-footer {
display: flex;
align-items: center;
justify-content: space-between;
&-left {
display: inline-flex;
align-items: center;
@media screen and (max-width: $mobile-width) {
display: block;
.btn {
display: block;
margin: 0 0 15px;
width: 100%;
}
}
}
@media screen and (max-width: $breakpoint-md) {
padding-top: $tablet-indent;
}
@media screen and (max-width: $mobile-width) {
flex-direction: column-reverse;
padding-top: 0;
}
p {
color: #777;
font-size: 14px;
font-stretch: normal;
font-style: normal;
font-weight: normal;
line-height: 18px;
max-width: 340px;
padding-left: 15px;
}
&-finalize {
@extend %_button;
margin-right: 20px;
background-color: fade-out(#08b3f2, 0.9);
white-space: nowrap;
&-finalized {
background-color: fade-out(#6d2eae, 0.9);
color: #6d2eae;
cursor: default;
}
@media screen and (max-width: $mobile-width) {
width: 100%;
margin-right: 0;
margin-top: $mobile-indent;
text-align: center;
}
}
}

View File

@ -1,13 +1,4 @@
.sw-BallotCard {
.title {
margin-bottom: 50px;
@media screen and (max-width: $breakpoint-md) {
margin-bottom: $tablet-indent;
}
@media screen and (max-width: $mobile-width) {
margin-bottom: $mobile-indent;
}
}
background-color: #fff;
border-radius: 6px;
border: 1px solid $base-border-color;
@ -63,42 +54,6 @@
text-overflow: ellipsis;
}
.sw-BallotCard_Vote {
border-radius: 2px;
border: 0;
box-sizing: border-box;
cursor: pointer;
display: inline-block;
font-size: 13px;
font-weight: bold;
line-height: 36px;
outline: none;
padding: 0 13px;
text-transform: uppercase;
transition: 0.3s opacity;
&:hover {
opacity: 0.9;
text-decoration: none;
}
}
.sw-BallotCard_VoteLabel {
color: #333;
cursor: default;
font-size: 14px;
font-weight: 700;
line-height: 1.2;
@media screen and (max-width: $mobile-width) {
margin-bottom: 25px;
}
}
.sw-BallotCard_VoteLabel-right {
margin-left: auto !important;
}
.sw-BallotCard_VoteButton {
line-height: 44px;
min-width: 55px;

View File

@ -0,0 +1,49 @@
.bc-BallotFooter {
display: flex;
flex-direction: column;
@media (min-width: $breakpoint-md) {
align-items: center;
flex-direction: row;
}
}
.bc-BallotFooter_Description {
color: #777;
font-size: 14px;
font-stretch: normal;
font-style: normal;
font-weight: normal;
line-height: 18px;
max-width: 340px;
@media (min-width: $breakpoint-md) {
padding-left: 15px;
}
}
.bc-BallotFooter_Voted {
box-sizing: border-box;
color: #333;
display: inline-block;
font-size: 14px;
font-weight: 700;
line-height: 1.2;
margin-left: auto;
padding: 0 13px;
text-transform: uppercase;
}
.bc-BallotFooter_ID {
color: #333;
font-size: 14px;
font-weight: normal;
line-height: 1.1;
margin-top: 10px;
@media (min-width: $breakpoint-md) {
margin-left: auto;
margin-top: 0;
}
}

View File

@ -0,0 +1,55 @@
.sw-ButtonFinalize {
align-items: center;
border-radius: 5px;
border: 0;
color: #fff;
cursor: pointer;
display: flex;
font-size: 14px;
font-weight: 700;
height: 42px;
justify-content: space-between;
line-height: 42px;
outline: none;
padding: 0 15px;
text-decoration: none;
text-transform: capitalize;
transition: 0.15s background-color;
&#{ & }-core {
background-color: $poa-purple;
}
&#{ & }-sokol {
background-color: $sokol-cyan;
}
&#{ & }-dai {
background-color: $xdai-orange;
}
&#{ & }-cancel {
background-color: #f21b57 !important;
}
&#{ & }-disabled {
background-color: #f0f0f0 !important;
color: #333;
}
.bc-BallotFooter & {
margin-top: 30px;
order: 3;
width: 100%;
@media (min-width: $breakpoint-md) {
margin-top: 0;
order: 0;
width: auto;
}
}
}
.sw-ButtonFinalize_Text {
margin-right: 50px;
}

View File

@ -0,0 +1,21 @@
.sw-IconFinalize_Path {
&#{ & }-core {
fill: #fff;
}
&#{ & }-sokol {
fill: #fff;
}
&#{ & }-dai {
fill: #fff;
}
.sw-ButtonFinalize-danger & {
fill: #fff !important;
}
.sw-ButtonFinalize-disabled & {
fill: #333 !important;
}
}

View File

@ -1,3 +1,3 @@
.nl-IconFinalize_Path {
.nl-IconToFinalize_Path {
@include menu-icon-colors();
}

View File

@ -2,20 +2,23 @@
@import "BallotAbout";
@import "BallotCard";
@import "BallotDataPair";
@import "Ballots";
@import "BallotFooter";
@import "BallotInfoContainer";
@import "Ballots";
@import "BaseLoader";
@import "ButtonFinalize";
@import "ButtonNewBallot";
@import "Footer";
@import "Header";
@import "IconAFinalize";
@import "IconActive";
@import "IconAdd";
@import "IconAll";
@import "IconFinalize";
@import "IconGithub";
@import "IconMobileMenu";
@import "IconPOA";
@import "IconTelegram";
@import "IconToFinalize";
@import "IconTwitter";
@import "Loading";
@import "LogoDai";

File diff suppressed because one or more lines are too long

View File

@ -14,6 +14,4 @@
@import 'application/ballot-types';
@import 'application/ballots/placeholders';
// @import 'application/ballots/base';
// @import 'application/ballots/about';
@import 'application/ballots/footer';
@import 'application/ballots/base'; // TODO: DELETE THIS, REFACTOR!!!

View File

@ -2,7 +2,9 @@ import React from 'react'
import moment from 'moment'
import swal from 'sweetalert2'
import { BallotDataPair } from '../BallotDataPair'
import { BallotFooter } from '../BallotFooter'
import { BallotInfoContainer } from '../BallotInfoContainer'
import { getNetworkBranch } from '../../utils/utils'
import { inject, observer } from 'mobx-react'
import { messages } from '../../utils/messages'
import { observable, action, computed } from 'mobx'
@ -68,15 +70,11 @@ export class BallotCard extends React.Component {
}
@computed
get cancelOrFinalizeButtonClass() {
if (this.isFinalized) {
return 'btn btn-primary btn-finalize disabled text-capitalize'
} else if (this.isCanceled) {
return 'btn btn-primary disabled text-capitalize'
get cancelOrFinalizeButtonState() {
if (this.isFinalized || this.isCanceled) {
return 'disabled'
} else if (this.timeToCancel.val > 0) {
return 'btn btn-danger text-capitalize'
} else {
return 'btn btn-primary btn-finalize text-capitalize'
return 'danger'
}
}
@ -235,6 +233,71 @@ export class BallotCard extends React.Component {
return (this.timeTo = this.timeToFinish)
}
constructor(props) {
super(props)
const { votingState, contractsStore, votingType } = this.props
// getTimes
if (
votingState.hasOwnProperty('creationTime') &&
contractsStore.ballotCancelingThreshold > 0 &&
votingState.creatorMiningKey === contractsStore.miningKey
) {
votingState.creationTime = Number(votingState.creationTime)
this.cancelDeadline = moment
.utc((votingState.creationTime + contractsStore.ballotCancelingThreshold) * 1000)
.format(USDateTimeFormat)
}
this.startTime = moment.utc(votingState.startTime * 1000).format(USDateTimeFormat)
this.endTime = moment.utc(votingState.endTime * 1000).format(USDateTimeFormat)
// getCreator
this.creator = votingState.creator
this.creatorMiningKey = votingState.creatorMiningKey
// getTotalVoters
if (votingState.hasOwnProperty('totalVoters')) {
this.totalVoters = Number(votingState.totalVoters)
} else {
this.burnVotes = Number(votingState.burnVotes)
this.freezeVotes = Number(votingState.freezeVotes)
this.sendVotes = Number(votingState.sendVotes)
this.totalVoters = this.burnVotes + this.freezeVotes + this.sendVotes
}
// getProgress
if (votingState.hasOwnProperty('progress')) {
this.progress = Number(votingState.progress)
}
// getIsFinalized
this.isFinalized = votingState.isFinalized
// getIsCanceled
if (votingState.hasOwnProperty('isCanceled')) {
this.isCanceled = votingState.isCanceled
}
this.calcTimeTo()
// canBeFinalizedNow
if (votingState.hasOwnProperty('canBeFinalizedNow')) {
this.canBeFinalized = votingState.canBeFinalizedNow
} else {
this.canBeFinalizedNow()
}
// getMemo
this.memo = votingState.memo
// hasAlreadyVoted
if (votingState.hasOwnProperty('alreadyVoted')) {
this.hasAlreadyVoted = votingState.alreadyVoted
} else {
this.getHasAlreadyVoted()
}
if (votingType === 'votingToManageEmissionFunds') {
this.getQuorumState()
}
}
formatMs(ms, format) {
let dur = moment.duration(ms)
let hours = Math.floor(dur.asHours())
@ -543,71 +606,6 @@ export class BallotCard extends React.Component {
}
}
constructor(props) {
super(props)
const { votingState, contractsStore, votingType } = this.props
// getTimes
if (
votingState.hasOwnProperty('creationTime') &&
contractsStore.ballotCancelingThreshold > 0 &&
votingState.creatorMiningKey === contractsStore.miningKey
) {
votingState.creationTime = Number(votingState.creationTime)
this.cancelDeadline = moment
.utc((votingState.creationTime + contractsStore.ballotCancelingThreshold) * 1000)
.format(USDateTimeFormat)
}
this.startTime = moment.utc(votingState.startTime * 1000).format(USDateTimeFormat)
this.endTime = moment.utc(votingState.endTime * 1000).format(USDateTimeFormat)
// getCreator
this.creator = votingState.creator
this.creatorMiningKey = votingState.creatorMiningKey
// getTotalVoters
if (votingState.hasOwnProperty('totalVoters')) {
this.totalVoters = Number(votingState.totalVoters)
} else {
this.burnVotes = Number(votingState.burnVotes)
this.freezeVotes = Number(votingState.freezeVotes)
this.sendVotes = Number(votingState.sendVotes)
this.totalVoters = this.burnVotes + this.freezeVotes + this.sendVotes
}
// getProgress
if (votingState.hasOwnProperty('progress')) {
this.progress = Number(votingState.progress)
}
// getIsFinalized
this.isFinalized = votingState.isFinalized
// getIsCanceled
if (votingState.hasOwnProperty('isCanceled')) {
this.isCanceled = votingState.isCanceled
}
this.calcTimeTo()
// canBeFinalizedNow
if (votingState.hasOwnProperty('canBeFinalizedNow')) {
this.canBeFinalized = votingState.canBeFinalizedNow
} else {
this.canBeFinalizedNow()
}
// getMemo
this.memo = votingState.memo
// hasAlreadyVoted
if (votingState.hasOwnProperty('alreadyVoted')) {
this.hasAlreadyVoted = votingState.alreadyVoted
} else {
this.getHasAlreadyVoted()
}
if (votingType === 'votingToManageEmissionFunds') {
this.getQuorumState()
}
}
componentDidMount() {
this.interval = setInterval(() => {
this.calcTimeTo()
@ -645,18 +643,20 @@ export class BallotCard extends React.Component {
}
}
getVotingNetworkBranch = () => {
const { contractsStore } = this.props
return contractsStore.netId ? getNetworkBranch(contractsStore.netId) : null
}
render() {
let { contractsStore, votingType, children } = this.props
let voteScaleClass = 'vote-scale'
let hasAlreadyVotedLabel = (
<div className="sw-BallotCard_Vote sw-BallotCard_VoteLabel sw-BallotCard_VoteLabel-right sw-BallotCard_Vote_no">
You already voted
</div>
)
let showHasAlreadyVotedLabel = this.hasAlreadyVoted ? hasAlreadyVotedLabel : ''
const threshold = this.getThreshold(contractsStore, votingType)
let votingScale
const threshold = this.getThreshold(contractsStore, votingType)
const networkBranch = this.getVotingNetworkBranch()
if (votingType === 'votingToManageEmissionFunds') {
votingScale = (
<div className="sw-BallotCard_Scale">
@ -762,11 +762,7 @@ export class BallotCard extends React.Component {
}
return (
<div
className={`sw-BallotCard ${this.isFinalized ? 'ballots-i-not-finalized' : ''} ${
!this.showCard() ? 'hidden' : ''
}`}
>
<div className={`sw-BallotCard ${!this.showCard() ? 'hidden' : ''}`}>
<div className="sw-BallotAbout">
<BallotDataPair dataType="name" title="Proposer" value={[this.creator]} />
{children}
@ -782,18 +778,16 @@ export class BallotCard extends React.Component {
threshold={threshold}
validatorsLength={contractsStore.validatorsLength}
/>
<div className="ballots-footer">
<div className="ballots-footer-left">
<button type="button" onClick={e => this.cancelOrFinalize(e)} className={this.cancelOrFinalizeButtonClass}>
{this.cancelOrFinalizeButtonDisplayName}
</button>
<p>{this.cancelOrFinalizeDescription}</p>
</div>
{showHasAlreadyVotedLabel}
<div className="sw-BallotCard_VoteLabel">
{this.typeName(votingType)} Ballot ID: {this.props.id}
</div>
</div>
<BallotFooter
buttonState={this.cancelOrFinalizeButtonState}
buttonText={this.cancelOrFinalizeButtonDisplayName}
description={this.cancelOrFinalizeDescription}
networkBranch={networkBranch}
onClick={e => this.cancelOrFinalize(e)}
voteId={this.props.id}
voteType={this.typeName(votingType)}
voted={this.hasAlreadyVoted}
/>
</div>
)
}

View File

@ -0,0 +1,25 @@
import React from 'react'
import { ButtonFinalize } from '../ButtonFinalize'
export const BallotFooter = ({
buttonText,
buttonState,
description = '',
networkBranch,
onClick,
voteId,
voteType,
voted
}) => {
return (
<div className={`bc-BallotFooter bc-BallotFooter-${networkBranch}`}>
<ButtonFinalize onClick={onClick} text={buttonText} state={buttonState} networkBranch={networkBranch} />
{description ? <p className="bc-BallotFooter_Description">{description}</p> : null}
{voted ? <div className="bc-BallotFooter_Voted">You already voted</div> : null}
<div className="bc-BallotFooter_ID">
{voteType} Ballot ID: {voteId}
</div>
</div>
)
}

View File

@ -13,6 +13,7 @@ export class Ballots extends React.Component {
this.limit = this.props.commonStore.loadMoreLimit
this.step = this.limit
this.onClick = this.onClick.bind(this)
this.networkBranch = this.props.networkBranch
}
onClick = async () => {

View File

@ -0,0 +1,14 @@
import React from 'react'
import { IconFinalize } from '../IconFinalize'
export const ButtonFinalize = ({ extraClassName = '', networkBranch, onClick, state = '', text = '' }) => {
return (
<button
type="button"
onClick={onClick}
className={`sw-ButtonFinalize ${extraClassName} sw-ButtonFinalize-${networkBranch} sw-ButtonFinalize-${state}`}
>
<span className="sw-ButtonFinalize_Text">{text}</span> <IconFinalize networkBranch={networkBranch} />
</button>
)
}

View File

@ -0,0 +1,13 @@
import React from 'react'
export const IconFinalize = ({ networkBranch }) => {
return (
<svg className="sw-IconFinalize" xmlns="http://www.w3.org/2000/svg" width="16" height="18">
<path
className={`sw-IconFinalize_Path sw-IconFinalize_Path-${networkBranch}`}
d="M15 15h-5a1 1 0 0 1-1-1v-3H2v6a1 1 0 0 1-2 0V1a1 1 0 0 1 1-1h9a1 1 0 0 1 1 1v3h4a1 1 0 0 1 1 1v9a1 1 0 0 1-1 1zM9 2H2v7h7V2zm2 11h3V6h-3v7z"
fillRule="evenodd"
/>
</svg>
)
}

View File

@ -1,10 +1,10 @@
import React from 'react'
export const IconFinalize = ({ networkBranch }) => {
export const IconToFinalize = ({ networkBranch }) => {
return (
<svg className={`nl-IconFinalize`} xmlns="http://www.w3.org/2000/svg" width="18" height="17">
<svg className={`nl-IconToFinalize`} xmlns="http://www.w3.org/2000/svg" width="18" height="17">
<path
className={`nl-IconFinalize_Path nl-IconFinalize_Path-${networkBranch}`}
className={`nl-IconToFinalize_Path nl-IconToFinalize_Path-${networkBranch}`}
fillRule="evenodd"
d="M16 10.95V11H2v-.05a2.502 2.502 0 0 1 0-4.9V6h14v.05a2.502 2.502 0 0 1 0 4.9zM16 8H2v1h14V8zm0-3.05V5H2v-.05a2.502 2.502 0 0 1 0-4.9V0h14v.05a2.502 2.502 0 0 1 0 4.9zM16 2H2v1h14V2zM2 12.05V12h14v.05a2.502 2.502 0 0 1 0 4.9V17H2v-.05a2.502 2.502 0 0 1 0-4.9zM2 15h14v-1H2v1z"
/>

View File

@ -1,7 +1,7 @@
import React from 'react'
import { IconAll } from './IconAll'
import { IconActive } from './IconActive'
import { IconFinalize } from './IconFinalize'
import { IconToFinalize } from './IconToFinalize'
export const NavigationIcon = ({ icon, networkBranch }) => {
switch (icon) {
@ -10,7 +10,7 @@ export const NavigationIcon = ({ icon, networkBranch }) => {
case 'active':
return <IconActive networkBranch={networkBranch} />
case 'finalize':
return <IconFinalize networkBranch={networkBranch} />
return <IconToFinalize networkBranch={networkBranch} />
default:
return null
}