Browse Source

feat: upvote & downvote

master
hole-thu 3 years ago
parent
commit
a3841ff54a
  1. 35
      src/Flows.css
  2. 66
      src/Flows.js
  3. 15
      src/flows_api.js

35
src/Flows.css

@ -393,3 +393,38 @@
.op-btn {
margin: 0 0.25em;
}
.box-content-wrapper {
display: flex;
}
.box-content-wrapper .box-content {
flex: 1 1;
}
.box-content-wrapper .box-content-vote {
flex: 0 0;
}
.vote-num {
text-align: center;
}
.vote-icon-inactive {
fill: None;
stroke: #333;
stroke-width: 2px;
}
.root-dark-mode .vote-icon-inactive {
stroke: #777;
}
.vote-icon-active {
fill: #333;
}
.root-dark-mode .vote-icon-active {
fill: #777;
}

66
src/Flows.js

@ -228,6 +228,7 @@ class FlowItem extends PureComponent {
show_pid,
do_vote,
do_block,
do_react,
search_param,
} = this.props;
const { cw } = this.state;
@ -340,6 +341,7 @@ class FlowItem extends PureComponent {
{!!info.hot_score && (
<span className="box-header">hot score: {info.hot_score}</span>
)}
<div className="box-content-wrapper">
<div className="box-content">
<HighlightedMarkdown
text={info.text}
@ -348,6 +350,54 @@ class FlowItem extends PureComponent {
search_param={search_param}
/>
</div>
<div className="box-content-vote">
<span
className={do_react ? 'clickable' : ''}
onClick={() => do_react && do_react(1)}
>
<svg
className={
info.reaction_status === 1
? 'vote-icon-active'
: 'vote-icon-inactive'
}
width="28"
height="28"
viewBox="0 0 36 36"
>
<path d="M2 25h32L18 9 2 25Z" />
</svg>
</span>
{do_react ? (
<>
<div className="vote-num">{info.up_votes}</div>
<hr />
<div className="vote-num">{info.down_votes}</div>
</>
) : (
<div className="vote-num">
{info.up_votes - info.down_votes}
</div>
)}
<span
className={do_react ? 'clickable' : ''}
onClick={() => do_react && do_react(-1)}
>
<svg
className={
info.reaction_status === -1
? 'vote-icon-active'
: 'vote-icon-inactive'
}
width="28"
height="28"
viewBox="0 0 36 36"
>
<path d="M2 11h32L18 27 2 11Z"></path>
</svg>
</span>
</div>
</div>
{info.poll && (
<div className="box-poll">
<Poll
@ -469,6 +519,21 @@ class FlowSidebar extends PureComponent {
});
}
set_reaction(reaction_status) {
console.log(reaction_status);
const prev_info = this.state.info;
const pid = prev_info.pid;
API.set_reaction(pid, reaction_status, this.props.token).then((json) => {
this.setState({
info: Object.assign({}, prev_info, json.data),
});
// TODO: save to localStore
this.syncState({
info: Object.assign({}, prev_info, json.data),
});
});
}
toggle_attention() {
const prev_info = this.state.info;
const pid = prev_info.pid;
@ -710,6 +775,7 @@ class FlowSidebar extends PureComponent {
window.location.reload();
});
}}
do_react={this.set_reaction.bind(this)}
/>
</ClickHandler>
);

15
src/flows_api.js

@ -100,6 +100,21 @@ export const API = {
return handle_response(response, true);
},
set_reaction: async (pid, reaction_status, token) => {
let data = new URLSearchParams([['status', reaction_status]]);
let response = await fetch(`${get_api_base_2()}/post/${pid}/reaction`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'User-Token': token,
},
body: data,
});
return handle_response(response, true);
},
report: async (pid, reason, should_hide, token) => {
let data = new URLSearchParams([
['pid', pid],

Loading…
Cancel
Save