Enable like button (drop restriction on 1-per-user)

[Closes #82]
This commit is contained in:
Tom Russell 2018-10-25 13:34:54 +01:00
parent 4b16b69e8e
commit 6cc6630196
6 changed files with 84 additions and 23 deletions

View File

@ -166,7 +166,7 @@ function likeBuilding(building_id, user_id) {
`INSERT INTO logs (
forward_patch, building_id, user_id
) VALUES (
$1:jsonb, $2, $3
$1:json, $2, $3
) RETURNING log_id
`,
[{likes_total: building.likes}, building_id, user_id]

View File

@ -74,10 +74,28 @@ class EditForm extends Component {
}
handleLike(event) {
const liked = event.target.checked;
this.setState({
like: liked
});
event.preventDefault();
fetch(`/building/like/${this.props.building_id}`, {
method: 'POST',
headers:{
'Content-Type': 'application/json'
},
credentials: 'same-origin'
}).then(
res => res.json()
).then(function(res){
if (res.error) {
this.setState({error: res.error})
} else {
this.props.selectBuilding(res);
this.setState({
likes_total: res.likes_total
})
}
}.bind(this)).catch(
(err) => this.setState({error: err})
);
}
handleSubmit(event) {
@ -124,17 +142,28 @@ class EditForm extends Component {
</a>
: null
}
{
(this.props.slug === 'like')? // special-case for likes
<NavLink className="icon-button save" title="Done"
to={`/building/${this.props.building_id}.html?cat=${this.props.slug}`}>
Done
<SaveIcon />
</NavLink>
:
<Fragment>
<NavLink className="icon-button save" title="Save Changes"
onClick={this.handleSubmit}
onClick={this.handleSubmit}
to={`/building/${this.props.building_id}.html?cat=${this.props.slug}`}>
Save
<SaveIcon />
</NavLink>
<NavLink className="icon-button close-edit" title="Cancel"
to={`/building/${this.props.building_id}.html?cat=${this.props.slug}`}>
to={`/building/${this.props.building_id}.html?cat=${this.props.slug}`}>
Cancel
<CloseIcon />
</NavLink>
</Fragment>
}
</nav>
</header>
@ -174,11 +203,19 @@ class EditForm extends Component {
hitting refresh after saving (we're working on making this
smoother).</p>
<div className="buttons-container">
<Link to={`/building/${this.props.building_id}.html?cat=${this.props.slug}`}
className="btn btn-secondary">Cancel</Link>
<button type="submit" className="btn btn-primary">Save</button>
</div>
{
(this.props.slug === 'like')? // special-case for likes
<div className="buttons-container">
<Link to={`/building/${this.props.building_id}.html?cat=${this.props.slug}`}
className="btn btn-secondary">Done</Link>
</div>
:
<div className="buttons-container">
<Link to={`/building/${this.props.building_id}.html?cat=${this.props.slug}`}
className="btn btn-secondary">Cancel</Link>
<button type="submit" className="btn btn-primary">Save</button>
</div>
}
</form>
</section>
)
@ -231,14 +268,8 @@ const NumberInput = (props) => (
const LikeButton = (props) => (
<Fragment>
<label htmlFor="likes">Like this building?</label>
<div className="form-check">
<input className="form-check-input position-static"
type="checkbox"
checked={props.value}
onChange={props.handleLike}
/>
</div>
<p class="likes">{(props.value)? props.value : 0} likes</p>
<button class="btn btn-success btn-like" onClick={props.handleLike}>Like this building!</button>
</Fragment>
);

View File

@ -155,7 +155,7 @@
"title": "Like Me!", "slug": "like",
"help": "https://pages.colouring.london/likeme",
"fields": [
{ "title": "Like", "slug": "like", "type": "like", "tooltip": "Do you like the building?" }
{ "title": "Like", "slug": "likes_total", "type": "like", "tooltip": "Do you like the building?" }
]
}
]

View File

@ -53,3 +53,11 @@ form .btn {
margin-right: 0;
}
}
/* Like button */
.likes {
margin: 0.5rem 0;
}
form .btn-like {
margin: 0;
}

View File

@ -18,7 +18,7 @@ import App from './frontend/app';
import db from './db';
import { authUser, createUser, getUserById, authAPIUser, getNewUserAPIKey } from './user';
import { queryBuildingsAtPoint, queryBuildingsByReference, getBuildingById,
saveBuilding } from './building';
saveBuilding, likeBuilding } from './building';
import tileserver from './tileserver';
import { parseBuildingURL } from './parse';
@ -218,6 +218,28 @@ function updateBuilding(req, res, user_id){
)
}
// POST like building
server.post('/building/like/:building_id', function(req, res){
if (!req.session.user_id) {
res.send({error: 'Must be logged in'});
return
}
const { building_id } = req.params;
likeBuilding(building_id, req.session.user_id).then(building => {
if (building.error) {
res.send(building)
return
}
if (typeof(building) === "undefined") {
res.send({error:'Database error'})
return
}
res.send(building)
}).catch(
() => res.send({error:'Database error'})
)
});
// POST new user
server.post('/users', function(req, res){
const user = req.body;

View File

@ -86,4 +86,4 @@ CREATE INDEX building_likes_idx ON building_user_likes ( building_id );
CREATE INDEX user_likes_idx ON building_user_likes ( user_id );
-- One like per-building, per-user
ALTER TABLE building_user_likes ADD CONSTRAINT building_like_once UNIQUE (building_id, user_id);
-- ALTER TABLE building_user_likes ADD CONSTRAINT building_like_once UNIQUE (building_id, user_id);