Skip to content

Commit 8ce0606

Browse files
committed
new design for the vote app
1 parent 42cbee3 commit 8ce0606

File tree

6 files changed

+129
-438
lines changed

6 files changed

+129
-438
lines changed

components/vote/app-style.scss

Lines changed: 10 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@
33

44
.vote-app {
55
&__self-info {
6-
border-left: 1px solid black;
7-
border-right: 1px solid black;
8-
border-bottom: 1px solid black;
6+
margin-top: 10px;
97
}
108

119
&__update-button {
@@ -32,87 +30,45 @@
3230
}
3331
}
3432

35-
&__vote-list {
36-
display: flex;
37-
38-
& > li {
39-
display: block;
40-
padding: 5px;
41-
flex: 2;
42-
text-align: center;
43-
}
44-
45-
& > .vote-app__vote-score {
46-
flex: 1;
47-
width: auto;
48-
font-size: 150%;
49-
}
33+
&__item-table td {
34+
vertical-align: middle;
5035
}
5136

37+
&__item-score {
38+
font-size: 150%;
39+
}
5240

5341
&__items-list {
5442
display: block;
5543

5644
& > li {
5745
display: block;
5846
padding: 5px;
59-
border: 1px solid black;
60-
border-top: inherit;
61-
62-
&:first-child {
63-
border-top: 1px solid black;
64-
}
65-
}
66-
}
67-
68-
&__vote-buttons {
69-
display: flex;
70-
}
71-
72-
&__vote-positive {
73-
text-align: left;
74-
flex: 1;
75-
display: flex;
76-
flex-wrap: wrap;
77-
> * {
78-
height: 20px;
79-
}
80-
}
81-
82-
&__vote-negative {
83-
text-align: right;
84-
flex: 1;
85-
display: flex;
86-
flex-direction: row-reverse;
87-
justify-content: flex-start;
88-
flex-wrap: wrap;
89-
> * {
90-
height: 20px;
9147
}
9248
}
9349

94-
&__currency-influence, &__vote-influence &__vote-value {
50+
&__currency-influence, &__vote-influence {
9551
color: blue;
9652
&:before {
9753
content: "\2009";
9854
}
9955
}
10056

101-
&__currency-goldenInfluence, &__vote-golden &__vote-value {
57+
&__currency-goldenInfluence, &__vote-golden {
10258
color: #bfa203;
10359
&:before {
10460
content: "\2009";
10561
}
10662
}
10763

108-
&__currency-support, &__vote-support &__vote-value {
64+
&__currency-support, &__vote-support {
10965
color: green;
11066
&:before {
11167
content: "$\2009";
11268
}
11369
}
11470

115-
&__vote-thumb &__vote-value {
71+
&__vote-thumb {
11672

11773
}
11874

components/vote/app.jsx

Lines changed: 46 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import React from 'react';
22
import SidebarItem from '../sidebar-item/sidebar-item';
33
import * as api from "./api";
44
import './app-style';
5-
import VoteSlider from './slider/slider';
5+
import VoteButton from './button/button';
66

77
function updateByProperty(array, property, propertyValue, update) {
88
return array.map(item => {
@@ -65,14 +65,14 @@ export default class VoteApp extends React.Component {
6565
this.setState({
6666
isFetchingSelf: true
6767
});
68-
api.getSelf(voteAppToken).then(result => {
68+
api.getSelf(voteAppToken).catch(e => {
6969
this.setState({
70-
selfInfo: result,
70+
selfInfo: null,
7171
isFetchingSelf: false
7272
});
73-
}).catch(e => {
73+
}).then(result => {
7474
this.setState({
75-
selfInfo: null,
75+
selfInfo: result,
7676
isFetchingSelf: false
7777
});
7878
});
@@ -85,14 +85,14 @@ export default class VoteApp extends React.Component {
8585
this.setState({
8686
isFetchingList: true
8787
});
88-
api.getList(voteAppToken, name).then(result => {
88+
api.getList(voteAppToken, name).catch(e => {
8989
this.setState({
90-
listInfo: result,
90+
listInfo: null,
9191
isFetchingList: false
9292
});
93-
}).catch(e => {
93+
}).then(result => {
9494
this.setState({
95-
listInfo: null,
95+
listInfo: result,
9696
isFetchingList: false
9797
});
9898
});
@@ -186,44 +186,37 @@ export default class VoteApp extends React.Component {
186186
<div>{listInfo.description}</div>
187187
<ul className="vote-app__items-list">
188188
{ listInfo.items.map(item => <li key={item.id}>
189-
<span className="vote-app__item-title">{item.title}</span>
190-
<span>{item.description}</span><br />
191-
<ul className="vote-app__vote-list">
192-
{listInfo.possibleVotes.map((voteSettings, idx) => {
193-
let vote = item.votes[idx];
194-
let userVote = item.userVotes && item.userVotes[idx];
195-
let currencyInfo = selfInfo && voteSettings.currency && this.findByName(selfInfo.currencies, voteSettings.currency);
196-
let maximum = voteSettings.maximum || 1000; // infinity
197-
let minimum = voteSettings.minimum || 0;
198-
let value = (userVote && userVote.votes) ? userVote.votes: 0;
199-
if(currencyInfo && currencyInfo.remaining + value < maximum) maximum = currencyInfo.remaining + value;
200-
let visibleMaxValue = voteSettings.maximum || (maxVoteInfo[idx] + currencyInfo.remaining);
201-
202-
return <li className={"vote-app__vote-" + voteSettings.name} key={voteSettings.name} title={userVote ? "You voted " + userVote.votes + "." : "Login to see your votes."}>
203-
<div className="vote-app__vote-value">
204-
{vote.votes > 0 && voteSettings.minimum < 0 ? "+" + vote.votes : vote.votes}
205-
{userVote && userVote.votes ? " (You: " + (userVote.votes > 0 && voteSettings.minimum < 0 ? "+" + userVote.votes : userVote.votes) + ")" : ""}
206-
</div>
207-
{ selfInfo &&
208-
<VoteSlider minValue={minimum} maxValue={maximum} visibleMaxValue={visibleMaxValue}
209-
value={value} step={this.getStep(visibleMaxValue)} color={this.getColor(voteSettings.name)}
210-
valueChanged={(v) => {
211-
let diff = v;
212-
213-
if((userVote && userVote.votes)) {
214-
diff = v - userVote.votes;
215-
}
216-
217-
this.vote(item.id, voteSettings.name, diff, voteSettings.currency, voteSettings.score * diff);
218-
}}
219-
/>
220-
}
221-
</li>;
222-
})}
223-
<li className="vote-app__vote-score" key="score">
224-
Score {item.score}
225-
</li>
226-
</ul>
189+
<table className="vote-app__item-table">
190+
<tbody>
191+
<tr>
192+
<td className="vote-app__item-score">
193+
{item.score}
194+
</td>
195+
{listInfo.possibleVotes.map((voteSettings, idx) => {
196+
let vote = item.votes[idx];
197+
let userVote = item.userVotes && item.userVotes[idx];
198+
let currencyInfo = selfInfo && voteSettings.currency && this.findByName(selfInfo.currencies, voteSettings.currency);
199+
let maximum = voteSettings.maximum || 1000; // infinity
200+
let minimum = voteSettings.minimum || 0;
201+
let value = (userVote && userVote.votes) ? userVote.votes: 0;
202+
if(currencyInfo && currencyInfo.remaining + value < maximum) maximum = currencyInfo.remaining + value;
203+
return <td>
204+
<VoteButton
205+
className={"vote-app__vote-" + voteSettings.name}
206+
value={vote.votes} myValue={userVote.votes}
207+
maxUp={maximum - userVote.votes} maxDown={userVote.votes - minimum}
208+
color={this.getColor(voteSettings.name)} onVote={(diffValue) => {
209+
this.vote(item.id, voteSettings.name, diffValue, voteSettings.currency, voteSettings.score);
210+
}} />
211+
</td>;
212+
})}
213+
<td className="vote-app__item-content">
214+
<span className="vote-app__item-title">{item.title}</span>
215+
<span>{item.description}</span>
216+
</td>
217+
</tr>
218+
</tbody>
219+
</table>
227220
</li>)}
228221
{ listInfo.isAdmin && <li className="vote-app__admin">
229222
<div><input type="text" value={this.state.newTitle} disabled={inProgress} onChange={e => this.setState({newTitle: e.target.value})} /></div>
@@ -258,7 +251,7 @@ export default class VoteApp extends React.Component {
258251
}
259252

260253
renderSelf() {
261-
let { selfInfo, isFetchingSelf } = this.state;
254+
let { listInfo, selfInfo, isFetchingSelf } = this.state;
262255
if(!selfInfo) {
263256
if(isFetchingSelf) {
264257
return <div className="vote-app__self-info">Loading user info...</div>;
@@ -272,11 +265,13 @@ export default class VoteApp extends React.Component {
272265
delete window.localStorage.voteAppToken;
273266
window.location.reload();
274267
}}>Log out</button>
275-
<ul className="vote-app__currency-list">
276-
{ selfInfo.currencies.map(currency => <li className={"vote-app__currency-" + currency.name} title={`${currency.description}\nYou used ${currency.used} of a total of ${currency.value} ${currency.displayName}.`}>
268+
{ listInfo && <ul className="vote-app__currency-list">
269+
{ selfInfo.currencies
270+
.filter(currency => listInfo.possibleVotes.some(voteSettings => voteSettings.currency === currency.name))
271+
.map(currency => <li className={"vote-app__currency-" + currency.name} title={`${currency.description}\nYou used ${currency.used} of a total of ${currency.value} ${currency.displayName}.`}>
277272
{currency.remaining} {currency.displayName}
278273
</li>) }
279-
</ul>
274+
</ul> }
280275
</div>;
281276
}
282277
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
.vote-button {
2+
text-align: center;
3+
&__value {
4+
font-size: 150%;
5+
}
6+
7+
&__value, &__my-value, &__upMax, &__up10, &__up1, &__down1, &__down10, &__downMax {
8+
display: block;
9+
}
10+
11+
&__upMax, &__up10, &__up1, &__down1, &__down10, &__downMax {
12+
border: 0;
13+
padding: 0;
14+
margin: 0;
15+
}
16+
}

components/vote/button/button.jsx

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import React from 'react';
2+
require("./button-style.scss");
3+
4+
export default (props) => {
5+
let { value, myValue, maxDown, maxUp, color, onVote, className } = props;
6+
7+
let click = (n) => {
8+
onVote(Math.min(maxUp, Math.max(n, -maxDown)));
9+
return false;
10+
};
11+
12+
let titleText = (n) => {
13+
n = Math.min(maxUp, Math.max(n, -maxDown));
14+
if(n === 0)
15+
return "";
16+
return n > 0 ? "+" + n : "" + n;
17+
};
18+
19+
let makeTriangle = (n, fn, size, minForEnabled) => {
20+
const enabled = n > 0 ? (maxUp >= minForEnabled) : (maxDown >= minForEnabled);
21+
return <a href="#"
22+
title={titleText(n)}
23+
onClick={() => click(n)}
24+
className="vote-button__upMax">
25+
{fn({size: size, color: enabled ? color : "transparent"})}
26+
</a>;
27+
};
28+
29+
return <div className="vote-button" style={{color: color}}>
30+
{makeTriangle(Infinity, triangleUp, 30, 11)}
31+
{makeTriangle(10, triangleUp, 20, 2)}
32+
{makeTriangle(1, triangleUp, 15, 1)}
33+
<div className="vote-button__value"><span className={className}>{value}</span></div>
34+
<div className="vote-button__my-value">(<span className={className}>{myValue}</span>)</div>
35+
{makeTriangle(-1, triangleDown, 15, 1)}
36+
{makeTriangle(-10, triangleDown, 20, 2)}
37+
{makeTriangle(-Infinity, triangleDown, 30, 11)}
38+
</div>;
39+
};
40+
41+
function triangleUp({color, size}) {
42+
let path = `m ${size},0 -${size},${size / 3 * 2} ${size*2},0 z`;
43+
return <svg width={size*2} height={size/3*2}>
44+
<path d={path} style={{
45+
fill: color
46+
}}/>
47+
</svg>;
48+
}
49+
50+
function triangleDown({color, size}) {
51+
let path = `m ${size},${size / 3 * 2} ${size},-${size / 3 * 2} -${size*2},0 z`;
52+
return <svg width={size*2} height={size/3*2}>
53+
<path d={path} style={{
54+
fill: color
55+
}}/>
56+
</svg>;
57+
}

components/vote/slider/slider-style.scss

Whitespace-only changes.

0 commit comments

Comments
 (0)