diff --git a/package.json b/package.json
index 99baa98..2dc2759 100644
--- a/package.json
+++ b/package.json
@@ -17,7 +17,8 @@
"react-scripts": "^3.4.1",
"react-timeago": "^4.4.0",
"typescript": "^4.0.2",
- "workbox-sw": "^5.1.3"
+ "workbox-sw": "^5.1.3",
+ "react-polls": "^1.2.0"
},
"scripts": {
"start": "react-scripts start",
diff --git a/src/Flows.css b/src/Flows.css
index 1e53ef6..036d959 100644
--- a/src/Flows.css
+++ b/src/Flows.css
@@ -198,6 +198,10 @@
overflow-y: hidden;
}
+.box-poll.disabled {
+ pointer-events: none;
+}
+
.box-id {
color: #666666;
}
diff --git a/src/Flows.js b/src/Flows.js
index 94221a6..01f5d9d 100644
--- a/src/Flows.js
+++ b/src/Flows.js
@@ -24,6 +24,7 @@ import { TokenCtx, ReplyForm } from './UserAction';
import { API } from './flows_api';
import { cache } from './cache';
import { save_attentions } from './Attention'
+import Poll from 'react-polls';
/*
const IMAGE_BASE = 'https://thimg.yecdn.com/';
@@ -159,7 +160,7 @@ class FlowItem extends PureComponent {
this.state = {
hot_score: props.info.hot_score || 0,
cw: props.info.cw || '',
- }
+ };
}
copy_link(event) {
@@ -199,7 +200,8 @@ class FlowItem extends PureComponent {
render() {
const {
info, is_quote, cached, attention, can_del, do_filter_name, do_delete,
- do_edit_cw, do_edit_score, timestamp, img_clickable, color_picker, show_pid
+ do_edit_cw, do_edit_score, timestamp, img_clickable, color_picker,
+ show_pid, do_vote
} = this.props;
const { cw, hot_score } = this.state;
return (
@@ -348,6 +350,19 @@ class FlowItem extends PureComponent {
)}
{/*{info.type==='audio' &&
最新回复{' '} @@ -458,21 +473,16 @@ class FlowSidebar extends PureComponent { } toggle_attention() { - this.setState({ - loading_status: 'loading', - }); const prev_info = this.state.info; const pid = prev_info.pid; API.set_attention(pid, !this.state.attention, this.props.token) .then((json) => { this.setState({ - loading_status: 'done', attention: json.attention, info: Object.assign({}, prev_info, { likenum: ''+json.likenum, }), }); - console.log(json); let saved_attentions = window.saved_attentions; if (json.attention && !saved_attentions.includes(pid)) { @@ -500,6 +510,28 @@ class FlowSidebar extends PureComponent { }); } + do_vote(vote) { + this.setState({ + loading_status: 'loading', + error_msg: null, + }); + API.add_vote(vote, this.state.info.pid, this.props.token) + .then((json) => { + if (json.code !== 0) return; + this.setState( + (prev, props) => ({ + info: Object.assign({}, prev.info, { poll: json.data }), + loading_status: 'done', + }), + () => { + this.syncState({ + info: this.state.info, + }); + }, + ); + }); + } + report() { let reason = prompt(`举报 #${this.state.info.pid} 的理由:`); if (reason !== null) { @@ -543,7 +575,6 @@ class FlowSidebar extends PureComponent { make_do_delete(token, on_complete=null) { const do_delete = (type, id) => { - console.log('del', type, id, token); let note = prompt(`将删除${type}=${id}, 备注:`, '(无)'); if (note !== null) { API.del(type, id, note, token) @@ -562,7 +593,6 @@ class FlowSidebar extends PureComponent { make_do_edit_cw(token) { const do_edit_cw = (cw, id) => { - console.log('edit cw', cw); API.update_cw(cw, id, token) .then((json) => { alert('已更新\n刷新列表显示新版本'); @@ -577,7 +607,6 @@ class FlowSidebar extends PureComponent { make_do_edit_score(token) { const do_edit_score = (score, id) => { - console.log('edit score', score); API.update_score(score, id, token) .then((json) => { console.log('已更新'); @@ -636,6 +665,7 @@ class FlowSidebar extends PureComponent { do_delete={this.make_do_delete(this.props.token, ()=>{window.location.reload();})} do_edit_cw={this.make_do_edit_cw(this.props.token)} do_edit_score={this.make_do_edit_score(this.props.token)} + do_vote={this.do_vote.bind(this)} /> ); diff --git a/src/UserAction.css b/src/UserAction.css index e7c49a4..53d2aea 100644 --- a/src/UserAction.css +++ b/src/UserAction.css @@ -116,3 +116,16 @@ margin-bottom: 5px; padding: 2px; } + +.post-form-poll-options { + display: flex; + flex-direction: column; +} + +.post-form-poll-options input { + margin: 5px 0; +} + +.post-form-poll-options h6 { + margin-bottom: 0; +} diff --git a/src/UserAction.js b/src/UserAction.js index 9679a8b..fa04dea 100644 --- a/src/UserAction.js +++ b/src/UserAction.js @@ -284,10 +284,9 @@ export class ReplyForm extends Component { .then(get_json) .then((json) => { if (json.code !== 0) { - if (json.msg) alert(json.msg); - throw new Error(JSON.stringify(json)); + throw new Error(json.msg); } - + let saved_attentions = window.saved_attentions; if (!saved_attentions.includes(pid)) { saved_attentions.unshift(pid) @@ -376,12 +375,15 @@ export class PostForm extends Component { loading_status: 'done', img_tip: null, preview: false, + has_poll: !!window.POLL_BACKUP, + poll_options: JSON.parse(window.POLL_BACKUP || '[""]'), }; this.img_ref = React.createRef(); this.area_ref = React.createRef(); this.on_change_bound = this.on_change.bind(this); this.on_allow_search_change_bound = this.on_allow_search_change.bind(this); this.on_cw_change_bound = this.on_cw_change.bind(this); + this.on_poll_option_change_bound = this.on_poll_option_change.bind(this); this.on_img_change_bound = this.on_img_change.bind(this); this.color_picker = new ColorPicker(); } @@ -391,8 +393,10 @@ export class PostForm extends Component { } componentWillUnmount() { - window.CW_BACKUP = this.state.cw; - window.AS_BACKUP = this.state.allow_search; + const { cw, allow_search, has_poll, poll_options } = this.state; + window.CW_BACKUP = cw; + window.AS_BACKUP = allow_search; + window.POLL_BACKUP = has_poll ? JSON.stringify(poll_options) : null; } on_allow_search_change(event) { @@ -413,13 +417,21 @@ export class PostForm extends Component { }); } - do_post(text, img) { + do_post() { let data = new URLSearchParams(); + const { cw, text, allow_search, has_poll, poll_options } = this.state; data.append('cw', this.state.cw); data.append('text', this.state.text); data.append('allow_search', this.state.allow_search ? '1' : ''); - data.append('type', img ? 'image' : 'text'); - if (img) data.append('data', img); + //data.append('type', img ? 'image' : 'text'); + //if (img) data.append('data', img); + data.append('type', 'text') + if (has_poll) { + poll_options.forEach((opt) => { + if (opt) + data.append('poll_options', opt); + }); + } fetch(API_BASE + '/dopost', { method: 'POST', @@ -432,8 +444,7 @@ export class PostForm extends Component { .then(get_json) .then((json) => { if (json.code !== 0) { - if (json.msg) alert(json.msg); - throw new Error(JSON.stringify(json)); + throw new Error(json.msg); } this.setState({ @@ -444,6 +455,7 @@ export class PostForm extends Component { this.area_ref.current.clear(); this.props.on_complete(); window.CW_BACKUP = ''; + window.POLL_BACKUP = null; }) .catch((e) => { console.error(e); @@ -593,7 +605,7 @@ export class PostForm extends Component { this.setState({ loading_status: 'loading', }); - this.do_post(this.state.text, null); + this.do_post(); } } @@ -603,24 +615,26 @@ export class PostForm extends Component { }); } + on_poll_option_change(event, idx) { + let poll_options = this.state.poll_options; + let text = event.target.value; + poll_options[idx] = text; + if (!text && poll_options.length > 1) { + poll_options.splice(idx, 1) + } + if (poll_options[poll_options.length - 1] && poll_options.length < 8) { + poll_options.push('') + } + this.setState({ poll_options: poll_options }); + } + + render() { + const { has_poll, poll_options, preview, loading_status } = this.state; return (