Unlike buildings

This commit is contained in:
Tom Russell 2019-01-22 17:52:32 +00:00
parent efe05d4483
commit d3907f7362
3 changed files with 102 additions and 21 deletions

View File

@ -220,6 +220,59 @@ function likeBuilding(building_id, user_id) {
});
}
function unlikeBuilding(building_id, user_id) {
// start transaction around save operation
// - insert building-user like
// - count total likes
// - insert changeset
// - update building to latest state
// commit or rollback (serializable - could be more compact?)
return db.tx({serializable}, t => {
return t.none(
"DELETE FROM building_user_likes WHERE building_id = $1 AND user_id = $2;",
[building_id, user_id]
).then(() => {
return t.one(
"SELECT count(*) as likes FROM building_user_likes WHERE building_id = $1;",
[building_id]
).then(building => {
return t.one(
`INSERT INTO logs (
forward_patch, building_id, user_id
) VALUES (
$1:json, $2, $3
) RETURNING log_id
`,
[{likes_total: building.likes}, building_id, user_id]
).then(revision => {
return t.one(
`UPDATE buildings
SET
revision_id = $1,
likes_total = $2
WHERE
building_id = $3
RETURNING
*
`,
[revision.log_id, building.likes, building_id]
)
})
});
});
}).catch(function(error){
// TODO report transaction error as 'Need to re-fetch building before update'
console.error(error);
if (error.detail && error.detail.includes("already exists")){
// 'already exists' is thrown if user already liked it
return {error: 'It looks like you already like that building!'};
} else {
return undefined
}
});
}
const BUILDING_FIELD_WHITELIST = new Set([
'ref_osm_id',
// 'location_name',
@ -297,5 +350,6 @@ export {
getBuildingLikeById,
getBuildingUPRNsById,
saveBuilding,
likeBuilding
likeBuilding,
unlikeBuilding
};

View File

@ -116,13 +116,15 @@ class EditForm extends Component {
*/
handleLike(event) {
event.preventDefault();
const like = event.target.checked;
fetch(`/building/${this.props.building_id}/like.json`, {
method: 'POST',
headers:{
'Content-Type': 'application/json'
},
credentials: 'same-origin'
credentials: 'same-origin',
body: JSON.stringify({like: like})
}).then(
res => res.json()
).then(function(res){
@ -380,7 +382,7 @@ const NumberInput = (props) => (
);
const CheckboxInput = (props) => (
<div class="form-check">
<div className="form-check">
<input className="form-check-input" type="checkbox"
id={props.slug} name={props.slug}
checked={!!props.value}
@ -397,11 +399,18 @@ const CheckboxInput = (props) => (
const LikeButton = (props) => (
<Fragment>
<p className="likes">{(props.value)? props.value : 0} likes</p>
{
(props.building_like)?
<p>You already like this building!</p>
: <button className="btn btn-success btn-like" onClick={props.handleLike}>Like this building!</button>
}
<div className="form-check">
<input className="form-check-input" type="checkbox"
id={props.slug} name={props.slug}
checked={!!props.building_like}
disabled={props.disabled}
onChange={props.handleLike}
/>
<label htmlFor={props.slug} className="form-check-label">
I like this building!
{ props.tooltip? <Tooltip text={ props.tooltip } /> : null }
</label>
</div>
</Fragment>
);

View File

@ -24,7 +24,8 @@ import {
getBuildingLikeById,
getBuildingUPRNsById,
saveBuilding,
likeBuilding
likeBuilding,
unlikeBuilding
} from './building';
import tileserver from './tileserver';
import { parseBuildingURL } from './parse';
@ -275,19 +276,36 @@ server.route('/building/:building_id/like.json')
return
}
const { building_id } = req.params;
likeBuilding(building_id, req.session.user_id).then(building => {
if (building.error) {
const { like } = req.body;
if (like){
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)
return
}
if (typeof(building) === "undefined") {
res.send({error:'Database error'})
return
}
res.send(building)
}).catch(
() => res.send({error:'Database error'})
)
}).catch(
() => res.send({error:'Database error'})
)
} else {
unlikeBuilding(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