feat: upvote & downvote
This commit is contained in:
@@ -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
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>
|
||||
);
|
||||
|
||||
@@ -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],
|
||||
|
||||
Reference in New Issue
Block a user