Unlike buildings
This commit is contained in:
parent
efe05d4483
commit
d3907f7362
@ -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
|
||||
};
|
||||
|
@ -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>
|
||||
);
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user