overlaping, downvote & tc before submit

This commit is contained in:
Kamen Stoykov 2019-05-16 22:30:16 +03:00
parent 0a6db07355
commit df750b6dbb
9 changed files with 198 additions and 118 deletions

View File

@ -33,7 +33,10 @@ const DappListItem = props => {
return ( return (
<div className={isRanked ? styles.rankedListItem : styles.listItem}> <div className={isRanked ? styles.rankedListItem : styles.listItem}>
{isRanked && <div className={styles.position}>{position}</div>} {isRanked && <div className={styles.position}>{position}</div>}
<div onClick={() => onToggleProfileModal(name)}> <div
className={styles.imgWrapper}
onClick={() => onToggleProfileModal(name)}
>
<ReactImageFallback <ReactImageFallback
className={styles.image} className={styles.image}
src={image} src={image}
@ -41,7 +44,7 @@ const DappListItem = props => {
alt="App icon" alt="App icon"
/> />
</div> </div>
<div> <div className={styles.column}>
<div onClick={() => onToggleProfileModal(name)}> <div onClick={() => onToggleProfileModal(name)}>
<h2 className={styles.header}>{name}</h2> <h2 className={styles.header}>{name}</h2>
<p <p
@ -56,20 +59,22 @@ const DappListItem = props => {
&nbsp;&rarr; &nbsp;&rarr;
</a> </a>
{showActionButtons && ( {showActionButtons && (
<p className={styles.actionArea}> <div className={styles.actionArea}>
<span className={styles.sntAmount}> <span className={styles.sntAmount}>
<img src={sntIcon} alt="SNT" width="16" height="16" /> <img src={sntIcon} alt="SNT" width="16" height="16" />
{dapp.sntValue} {dapp.sntValue}
</span> </span>
<span className={styles.vote} onClick={handleUpVote}> <div className={styles.voteTriggers}>
<img src={upvoteArrowIcon} alt="" /> <span className={styles.vote} onClick={handleUpVote}>
Upvote <img src={upvoteArrowIcon} alt="" />
</span> Upvote
<span className={styles.vote} onClick={handleDownVote}> </span>
<img src={downvoteArrowIcon} alt="" /> <span className={styles.vote} onClick={handleDownVote}>
Downvote <img src={downvoteArrowIcon} alt="" />
</span> Downvote
</p> </span>
</div>
</div>
)} )}
</div> </div>
</div> </div>

View File

@ -18,6 +18,12 @@
position: relative; position: relative;
} }
.column {
display: flex;
flex-direction: column;
flex: 1 1 auto;
}
.header { .header {
color: $headline-color; color: $headline-color;
font-size: calculateRem(15); font-size: calculateRem(15);
@ -41,6 +47,7 @@
font-size: calculateRem(12); font-size: calculateRem(12);
color: $link-color; color: $link-color;
text-decoration: none; text-decoration: none;
margin-bottom: 12px;
} }
.description { .description {
@ -60,11 +67,16 @@
} }
.position { .position {
flex: 0 0 auto;
margin-top: calculateRem(20); margin-top: calculateRem(20);
margin-right: calculateRem(16); margin-right: calculateRem(16);
font-size: calculateRem(13); font-size: calculateRem(13);
} }
.imgWrapper {
flex: 0 0 auto;
}
.sntAmount { .sntAmount {
font-size: calculateRem(12); font-size: calculateRem(12);
font-weight: 500; font-weight: 500;
@ -99,6 +111,19 @@
} }
.actionArea { .actionArea {
bottom: 0; width: 100%;
position: absolute; display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
margin-top: auto;
.voteTriggers {
display: inherit;
align-items: inherit;
}
}
.actionArea > * {
margin-bottom: calculateRem(8);
} }

View File

@ -1,5 +1,6 @@
const howToSubmit = { const howToSubmit = {
visible: false, visible_how_to_submit: false,
visible_terms: false,
} }
export default howToSubmit export default howToSubmit

View File

@ -1,12 +1,16 @@
import { connect } from 'react-redux' import { connect } from 'react-redux'
import { withRouter } from 'react-router-dom' import { withRouter } from 'react-router-dom'
import HowToSubmit from './HowToSubmit' import HowToSubmit from './HowToSubmit'
import { hideHowToSubmitAction } from './HowToSubmit.reducer' import {
hideHowToSubmitAction,
switchToTermsAction,
} from './HowToSubmit.reducer'
import { showSubmitAction } from '../Submit/Submit.reducer' import { showSubmitAction } from '../Submit/Submit.reducer'
const mapStateToProps = state => state.howToSubmit const mapStateToProps = state => state.howToSubmit
const mapDispatchToProps = dispatch => ({ const mapDispatchToProps = dispatch => ({
onClickClose: () => dispatch(hideHowToSubmitAction()), onClickClose: () => dispatch(hideHowToSubmitAction()),
onClickContinue: () => dispatch(switchToTermsAction()),
onClickGetStarted: () => { onClickGetStarted: () => {
dispatch(hideHowToSubmitAction()) dispatch(hideHowToSubmitAction())
setTimeout(() => { setTimeout(() => {

View File

@ -2,14 +2,30 @@ import React from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import styles from './HowToSubmit.module.scss' import styles from './HowToSubmit.module.scss'
import Modal from '../../common/components/Modal' import Modal from '../../common/components/Modal'
import Terms from '../Terms/Terms'
class HowToSubmit extends React.Component { class HowToSubmit extends React.Component {
constructor(props) { constructor(props) {
super(props) super(props)
this.wrapper = React.createRef()
this.onClickNext = this.onClickNext.bind(this)
}
onClickNext() {
const {
visible_how_to_submit,
onClickContinue,
onClickGetStarted,
} = this.props
if (visible_how_to_submit) {
this.wrapper.current.parentNode.parentNode.scrollTop = 0
onClickContinue()
} else onClickGetStarted()
} }
render() { render() {
const { visible, onClickClose, onClickGetStarted } = this.props const { visible_how_to_submit, visible_terms, onClickClose } = this.props
const visible = visible_how_to_submit || visible_terms
return ( return (
<Modal <Modal
@ -17,90 +33,97 @@ class HowToSubmit extends React.Component {
onClickClose={onClickClose} onClickClose={onClickClose}
windowClassName={styles.modalWindow} windowClassName={styles.modalWindow}
> >
<div className={styles.cnt}> <div ref={this.wrapper} className={styles.cnt}>
<div className={styles.title}>Terms and conditions</div> {visible_how_to_submit && (
<div className={styles.frame}> <>
<div className={styles.frameTitle}>Submit your ÐApp</div> <div className={styles.title}>How to submit a ÐApp</div>
<ol> <div className={styles.frame}>
<li> <div className={styles.frameTitle}>Submit your ÐApp</div>
Upload a name, url, description, category and image for your <ol>
DApp in the next step compulsory. <li>
</li> Upload a name, url, description, category and image for your
<li> DApp in the next step compulsory.
Stake the amount of SNT you want to rank your DApp optional. </li>
</li> <li>
<li>Hit submit.</li> Stake the amount of SNT you want to rank your DApp optional.
<li> </li>
Our team will ensure that your DApp works well on mobile devices <li>Hit submit.</li>
and will then include it on the live site using the information <li>
you provided in Step 1. Our team will ensure that your DApp works well on mobile
</li> devices and will then include it on the live site using the
</ol> information you provided in Step 1.
</div> </li>
<div className={styles.frame}> </ol>
<div className={styles.frameTitle}>Staking</div> </div>
<p> <div className={styles.frame}>
You need not stake anything to be included - your DApp just wont <div className={styles.frameTitle}>Staking</div>
appear in the Highest Ranked section. If you do stake SNT, your <p>
DApp will appear in that section immediately. The DApp with the You need not stake anything to be included - your DApp just
highest effective balance (that is, SNT staked plus/minus votes wont appear in the Highest Ranked section. If you do stake
cast for/against) ranks highest. SNT, your DApp will appear in that section immediately. The
</p> DApp with the highest effective balance (that is, SNT staked
<p> plus/minus votes cast for/against) ranks highest.
SNT you stake is locked in the Discover contract. You can, at any </p>
time, withdraw a percentage of what you have staked. The more you <p>
stake, the lower the percentage you can withdraw. Withdrawals must SNT you stake is locked in the Discover contract. You can, at
be made from the same wallet as you submitted with, so PLEASE any time, withdraw a percentage of what you have staked. The
SECURE THIS ADDRESS. more you stake, the lower the percentage you can withdraw.
</p> Withdrawals must be made from the same wallet as you submitted
</div> with, so PLEASE SECURE THIS ADDRESS.
<div className={`${styles.frame} ${styles.withBorder}`}> </p>
<ol> </div>
<li> <div className={`${styles.frame} ${styles.withBorder}`}>
Staking <strong>10 000 SNT</strong> returns a rate of{' '} <ol>
<strong>99.5%</strong>, so you can withdraw up to{' '} <li>
<strong>9 950 SNT.</strong> Staking <strong>10 000 SNT</strong> returns a rate of{' '}
</li> <strong>99.5%</strong>, so you can withdraw up to{' '}
<li> <strong>9 950 SNT.</strong>
Staking <strong>1 000 000 SNT</strong> returns a rate of 50.99%, </li>
so you can withdraw up to <strong>509 958 SNT.</strong> <li>
</li> Staking <strong>1 000 000 SNT</strong> returns a rate of
</ol> 50.99%, so you can withdraw up to{' '}
</div> <strong>509 958 SNT.</strong>
<div className={styles.frame}> </li>
<p> </ol>
Furthermore, the operators of{' '} </div>
<a href="https://dap.ps">https://dap.ps</a> reserve the right to <div className={styles.frame}>
remove any DApp from the UI for reasons including, but not limited <p>
to: Furthermore, the operators of{' '}
</p> <a href="https://dap.ps">https://dap.ps</a> reserve the right
</div> to remove any DApp from the UI for reasons including, but not
<div className={`${styles.frame} ${styles.withBorder}`}> limited to:
<ol> </p>
<li>Malicious code injection</li> </div>
<li> <div className={`${styles.frame} ${styles.withBorder}`}>
Violation of <a>Status' principles</a> <ol>
</li> <li>Malicious code injection</li>
<li>Lack of usability (especially on mobile)</li> <li>
<li>Vote manipulation.</li> Violation of <a>Status' principles</a>
</ol> </li>
</div> <li>Lack of usability (especially on mobile)</li>
<div className={styles.frame}> <li>Vote manipulation.</li>
<p> </ol>
Anyone is welcome to fork the software and implement different UI </div>
choices for the same underlying contract. Note that Discover is <div className={styles.frame}>
not affiliated with Status directly, we have simply chosen to use <p>
SNT as a token of value, to abide by <a>Status principles</a>, Anyone is welcome to fork the software and implement different
and to take a mobile-first approach to development. UI choices for the same underlying contract. Note that
</p> Discover is not affiliated with Status directly, we have
</div> simply chosen to use SNT as a token of value, to abide by{' '}
<a>Status principles</a>, and to take a mobile-first approach
to development.
</p>
</div>
</>
)}
{visible_terms && <Terms />}
<div className={styles.footerActions}> <div className={styles.footerActions}>
<button <button
className={styles.submitButton} className={styles.submitButton}
type="submit" type="submit"
onClick={onClickGetStarted} onClick={this.onClickNext}
> >
Continue {visible_how_to_submit ? 'Continue' : 'Get started'}
</button> </button>
</div> </div>
</div> </div>
@ -110,8 +133,10 @@ class HowToSubmit extends React.Component {
} }
HowToSubmit.propTypes = { HowToSubmit.propTypes = {
visible: PropTypes.bool.isRequired, visible_how_to_submit: PropTypes.bool.isRequired,
visible_terms: PropTypes.bool.isRequired,
onClickClose: PropTypes.func.isRequired, onClickClose: PropTypes.func.isRequired,
onClickContinue: PropTypes.func.isRequired,
onClickGetStarted: PropTypes.func.isRequired, onClickGetStarted: PropTypes.func.isRequired,
} }

View File

@ -3,6 +3,7 @@ import reducerUtil from '../../common/utils/reducer'
const SHOW = 'HOW_TO_SHOW' const SHOW = 'HOW_TO_SHOW'
const HIDE = 'HOW_TO_HIDE' const HIDE = 'HOW_TO_HIDE'
const SWITCH_TO_TERMS = 'HOW_SWITCH_TO_TERMS'
export const showHowToSubmitAction = () => { export const showHowToSubmitAction = () => {
window.location.hash = 'how-to-submit' window.location.hash = 'how-to-submit'
@ -20,21 +21,36 @@ export const hideHowToSubmitAction = () => {
} }
} }
export const switchToTermsAction = () => ({
type: SWITCH_TO_TERMS,
payload: null,
})
const show = state => { const show = state => {
return Object.assign({}, state, { return Object.assign({}, state, {
visible: true, visible_how_to_submit: true,
visible_terms: false,
}) })
} }
const hide = state => { const hide = state => {
return Object.assign({}, state, { return Object.assign({}, state, {
visible: false, visible_how_to_submit: false,
visible_terms: false,
})
}
const switchToTerms = state => {
return Object.assign({}, state, {
visible_how_to_submit: false,
visible_terms: true,
}) })
} }
const map = { const map = {
[SHOW]: show, [SHOW]: show,
[HIDE]: hide, [HIDE]: hide,
[SWITCH_TO_TERMS]: switchToTerms,
} }
export default reducerUtil(map, howToSubmitInitialState) export default reducerUtil(map, howToSubmitInitialState)

View File

@ -61,8 +61,9 @@
align-items: center; align-items: center;
justify-content: center; justify-content: center;
color: #fff; color: #fff;
font-size: 16px; font-size: 18px;
font-weight: 300; font-weight: 300;
font-family: 'Times New Roman', Times, serif;
margin-left: auto; margin-left: auto;
border-radius: 50%; border-radius: 50%;
background: #939ba1; background: #939ba1;

View File

@ -34,7 +34,7 @@ class Vote extends Component {
onClickDownvote() { onClickDownvote() {
const { dapp, onClickDownvote, fetchVoteRating } = this.props const { dapp, onClickDownvote, fetchVoteRating } = this.props
onClickDownvote() onClickDownvote()
// fetchVoteRating(dapp, false, 3244) fetchVoteRating(dapp, false, DOWNVOTE_COST)
} }
handleChange(e) { handleChange(e) {
@ -91,7 +91,6 @@ class Vote extends Component {
afterVoteCategoryPosition = 1 afterVoteCategoryPosition = 1
for (let i = 0; i < dappsByCategory.length; ++i) { for (let i = 0; i < dappsByCategory.length; ++i) {
if (dappsByCategory[i] === dapp) continue if (dappsByCategory[i] === dapp) continue
if (dappsByCategory[i].sntValue < afterVoteRating) break if (dappsByCategory[i].sntValue < afterVoteRating) break
afterVoteCategoryPosition++ afterVoteCategoryPosition++
} }
@ -142,11 +141,11 @@ class Vote extends Component {
{`${afterVoteRating.toLocaleString()}`} {`${afterVoteRating.toLocaleString()}`}
</span> </span>
)} )}
{/* {!isUpvote && afterVoteRating !== null && ( {!isUpvote && afterVoteRating !== null && (
<span className={styles.redBadge}> <span className={styles.redBadge}>
{`${afterVoteRating.toLocaleString()}`} {`${afterVoteRating.toLocaleString()}`}
</span> </span>
)} */} )}
</div> </div>
<div className={styles.itemRow}> <div className={styles.itemRow}>
<span className={styles.item}> <span className={styles.item}>
@ -165,11 +164,13 @@ class Vote extends Component {
{`${afterVoteCategoryPosition}`} {`${afterVoteCategoryPosition}`}
</span> </span>
)} )}
{/* {!isUpvote && afterVoteCategoryPosition !== null && afterVoteCategoryPosition !== catPosition ( {!isUpvote &&
<span className={styles.redBadge}> afterVoteCategoryPosition !== null &&
{`${afterVoteCategoryPosition}`} afterVoteCategoryPosition !== catPosition && (
</span> <span className={styles.redBadge}>
)} */} {`${afterVoteCategoryPosition}`}
</span>
)}
</div> </div>
</div> </div>
{!isUpvote && ( {!isUpvote && (

View File

@ -111,15 +111,17 @@ export const updateAfterVotingValuesAction = rating => ({
export const fetchVoteRatingAction = (dapp, isUpvote, sntValue) => { export const fetchVoteRatingAction = (dapp, isUpvote, sntValue) => {
return async (dispatch, getState) => { return async (dispatch, getState) => {
let rating let rating
try { if (isUpvote === true) {
rating = await BlockchainSDK.DiscoverService.upVoteEffect( try {
dapp.id, rating = await BlockchainSDK.DiscoverService.upVoteEffect(
sntValue, dapp.id,
) sntValue,
} catch (e) { )
return rating = parseInt(rating, 10)
} } catch (e) {
rating = parseInt(rating, 10) return
}
} else rating = parseInt(dapp.sntValue * 0.99, 10)
const state = getState() const state = getState()
const voteState = state.vote const voteState = state.vote