hw6: mandatory tasks done (tests pass, manual test needed for HTML)
This commit is contained in:
parent
c6293aea8f
commit
ab8c9c9668
7 changed files with 211 additions and 52 deletions
|
@ -39,7 +39,8 @@ app.use(express.static('public'));
|
||||||
// Initialize routers here
|
// Initialize routers here
|
||||||
const routers = require('./routes/routers');
|
const routers = require('./routes/routers');
|
||||||
app.use('/', routers.root);
|
app.use('/', routers.root);
|
||||||
app.use('/favorites', routers.favourites_db);
|
// app.use('/favorites', routers.favourites_db);
|
||||||
|
app.use('/favorites', routers.favourites_db_promises);
|
||||||
app.use('/bookmarked', routers.bookmarked);
|
app.use('/bookmarked', routers.bookmarked);
|
||||||
|
|
||||||
module.exports = app;
|
module.exports = app;
|
||||||
|
|
|
@ -7,7 +7,17 @@ const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const mongoose = require('mongoose');
|
const mongoose = require('mongoose');
|
||||||
const Favorite = mongoose.model('Favorite');
|
const Favorite = mongoose.model('Favorite');
|
||||||
const { error, renderFav } = require('../utils');
|
const { error, renderFav, parseId, notFound } = require('../utils');
|
||||||
|
|
||||||
|
function findAndRender(filter, req, res) {
|
||||||
|
Favorite.find(filter, (err, favs) => {
|
||||||
|
if (err) {
|
||||||
|
return error(err, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderFav(req, res, favs);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
router.post('/', (req, res) => {
|
router.post('/', (req, res) => {
|
||||||
if (!req.body.name || !req.body.dataURL) {
|
if (!req.body.name || !req.body.dataURL) {
|
||||||
|
@ -25,6 +35,8 @@ router.post('/', (req, res) => {
|
||||||
|
|
||||||
if (req.body._id) {
|
if (req.body._id) {
|
||||||
favourite._id = req.body._id;
|
favourite._id = req.body._id;
|
||||||
|
} else {
|
||||||
|
favourite._id = mongoose.Types.ObjectId();
|
||||||
}
|
}
|
||||||
|
|
||||||
favourite.save((err, fav) => {
|
favourite.save((err, fav) => {
|
||||||
|
@ -39,13 +51,7 @@ router.post('/', (req, res) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get('/', (req, res) => {
|
router.get('/', (req, res) => {
|
||||||
Favorite.find({}, (err, favs) => {
|
findAndRender({}, req, res);
|
||||||
if (err) {
|
|
||||||
return error(err, res);
|
|
||||||
}
|
|
||||||
|
|
||||||
renderFav(req, res, favs);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get('/search', (req, res) => {
|
router.get('/search', (req, res) => {
|
||||||
|
@ -53,25 +59,20 @@ router.get('/search', (req, res) => {
|
||||||
delete filter['dataURL'];
|
delete filter['dataURL'];
|
||||||
delete filter['_method'];
|
delete filter['_method'];
|
||||||
|
|
||||||
Favorite.find(filter, (err, favs) => {
|
findAndRender(filter, req, res);
|
||||||
if (err) {
|
|
||||||
return error(err, res);
|
|
||||||
}
|
|
||||||
|
|
||||||
renderFav(req, res, favs);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get('/:id', (req, res) => {
|
router.get('/:id', (req, res) => {
|
||||||
Favorite.findById(req.params.id, (err, fav) => {
|
Favorite.findById(parseId(req), (err, fav) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return error(err, res);
|
return error(err, res);
|
||||||
} else if (!fav) {
|
|
||||||
res.writeHead(404, {'Content-Type': 'text/plain'});
|
|
||||||
res.end('Not found');
|
|
||||||
} else {
|
|
||||||
renderFav(req, res, fav, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (notFound(fav, res)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderFav(req, res, fav, false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -90,10 +91,10 @@ function handleUpdate(partial = false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req.body.bookmarked !== undefined) {
|
if (req.body.bookmarked !== undefined) {
|
||||||
edit.bookmarked = !!req.body.bookmarked;
|
edit.bookmarked = req.body.bookmarked;
|
||||||
}
|
}
|
||||||
|
|
||||||
Favorite.findByIdAndUpdate(req.params.id, { $set: edit }, {
|
Favorite.findByIdAndUpdate(parseId(req), { $set: edit }, {
|
||||||
new: true,
|
new: true,
|
||||||
upsert: true,
|
upsert: true,
|
||||||
setDefaultsOnInsert: true,
|
setDefaultsOnInsert: true,
|
||||||
|
@ -112,18 +113,16 @@ function handleUpdate(partial = false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
router.put('/:id', handleUpdate());
|
router.put('/:id', handleUpdate());
|
||||||
|
|
||||||
router.patch('/:id', handleUpdate(true));
|
router.patch('/:id', handleUpdate(true));
|
||||||
|
|
||||||
|
|
||||||
router.delete('/:id', (req, res) => {
|
router.delete('/:id', (req, res) => {
|
||||||
Favorite.findByIdAndDelete(req.params.id, (err, fav) => {
|
Favorite.findByIdAndDelete(parseId(req), (err, fav) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return error(err, res);
|
return error(err, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fav == null) {
|
if (notFound(fav, res)) {
|
||||||
res.writeHead(404, { 'Content-Type': 'text/plain' });
|
|
||||||
res.end('Favourite not found');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,20 +135,18 @@ router.delete('/:id', (req, res) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
router.put('/:id/bookmarked', (req, res) => {
|
router.put('/:id/bookmarked', (req, res) => {
|
||||||
Favorite.findByIdAndUpdate(req.params.id, {
|
Favorite.findByIdAndUpdate(parseId(req), {
|
||||||
$set: { bookmarked: !!req.body.bookmarked }
|
$set: { bookmarked: req.body.bookmarked }
|
||||||
}, { new: true }, (err, fav) => {
|
}, { new: true }, (err, fav) => {
|
||||||
if (false) {
|
if (notFound(fav, res)) {
|
||||||
res.writeHead(404, { 'Content-Type': 'text/plain' });
|
return;
|
||||||
res.end('Favourite to bookmark not found');
|
}
|
||||||
} else if (!req.body.bookmarked) {
|
|
||||||
|
if (!req.body.bookmarked) {
|
||||||
res.writeHead(400, { 'Content-Type': 'text/plain' });
|
res.writeHead(400, { 'Content-Type': 'text/plain' });
|
||||||
res.end('Bad PUT bookmark form parameters');
|
res.end('Bad PUT bookmark form parameters');
|
||||||
} else {
|
} else {
|
||||||
res.format({
|
renderFav(req, res, fav, false);
|
||||||
html: () => renderFav(req, res, fav, false),
|
|
||||||
json: () => res.json(fav)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
136
hw6/Claudio_Maggioni/routes/favourites_db_promises/router.js
Normal file
136
hw6/Claudio_Maggioni/routes/favourites_db_promises/router.js
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
/** @module root/router */
|
||||||
|
'use strict';
|
||||||
|
// vim: set ts=2 sw=2 et tw=80:
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
const express = require('express');
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
const mongoose = require('mongoose');
|
||||||
|
const Favorite = mongoose.model('Favorite');
|
||||||
|
|
||||||
|
const { error, catchErrs, renderFav, parseId, notFound } = require('../utils');
|
||||||
|
|
||||||
|
function findAndRender(filter, req, res) {
|
||||||
|
catchErrs(Favorite.find(filter), res).then(favs => {
|
||||||
|
renderFav(req, res, favs);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
router.post('/', (req, res) => {
|
||||||
|
if (!req.body.name || !req.body.dataURL) {
|
||||||
|
res.writeHead(400, { 'Content-Type': 'text/plain' });
|
||||||
|
res.end('Bad create form parameters');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
name: req.body.name,
|
||||||
|
dataURL: req.body.dataURL,
|
||||||
|
bookmarked: req.body.bookmarked,
|
||||||
|
};
|
||||||
|
const favourite = new Favorite(data);
|
||||||
|
|
||||||
|
if (req.body._id) {
|
||||||
|
favourite._id = req.body._id;
|
||||||
|
} else {
|
||||||
|
favourite._id = mongoose.Types.ObjectId();
|
||||||
|
}
|
||||||
|
|
||||||
|
catchErrs(favourite.save(), res).then(fav => {
|
||||||
|
res.status = 201;
|
||||||
|
const _id = fav._id;
|
||||||
|
renderFav(req, res, Object.assign({ _id }, data), false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get('/', (req, res) => {
|
||||||
|
findAndRender({}, req, res);
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get('/search', (req, res) => {
|
||||||
|
const filter = Object.assign({}, req.query);
|
||||||
|
delete filter['dataURL'];
|
||||||
|
delete filter['_method'];
|
||||||
|
|
||||||
|
findAndRender(filter, req, res);
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get('/:id', (req, res) => {
|
||||||
|
catchErrs(Favorite.findById(parseId(req)), res).then(fav => {
|
||||||
|
if (notFound(fav, res)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderFav(req, res, fav, false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function handleUpdate(partial = false) {
|
||||||
|
return (req, res) => {
|
||||||
|
const edit = {};
|
||||||
|
for (const key of ['dataURL', 'name']) {
|
||||||
|
if (req.body[key]) {
|
||||||
|
edit[key] = req.body[key];
|
||||||
|
} else if (!partial) {
|
||||||
|
res.writeHead(400, { 'Content-Type': 'text/plain' });
|
||||||
|
res.end('Bad PUT form parameters');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.body.bookmarked !== undefined) {
|
||||||
|
edit.bookmarked = req.body.bookmarked;
|
||||||
|
}
|
||||||
|
|
||||||
|
catchErrs(Favorite.findByIdAndUpdate(parseId(req), { $set: edit }, {
|
||||||
|
new: true,
|
||||||
|
upsert: true,
|
||||||
|
setDefaultsOnInsert: true,
|
||||||
|
}), res).then(fav => {
|
||||||
|
console.log(arguments);
|
||||||
|
|
||||||
|
// FIXME: return 201 on creation
|
||||||
|
res.status = 200;
|
||||||
|
renderFav(req, res, fav, false);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
router.put('/:id', handleUpdate());
|
||||||
|
|
||||||
|
router.patch('/:id', handleUpdate(true));
|
||||||
|
|
||||||
|
router.delete('/:id', (req, res) => {
|
||||||
|
catchErrs(Favorite.findByIdAndDelete(parseId(req)), res).then(fav => {
|
||||||
|
if (notFound(fav, res)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
res.format({
|
||||||
|
json: () => res.writeHead(204),
|
||||||
|
html: () => res.writeHead(302, { 'Location': '/favorites' })
|
||||||
|
});
|
||||||
|
res.end();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
router.put('/:id/bookmarked', (req, res) => {
|
||||||
|
catchErrs(Favorite.findByIdAndUpdate(parseId(req), {
|
||||||
|
$set: { bookmarked: req.body.bookmarked }
|
||||||
|
}, { new: true }), res).then(fav => {
|
||||||
|
if (notFound(fav, res)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!req.body.bookmarked) {
|
||||||
|
res.writeHead(400, { 'Content-Type': 'text/plain' });
|
||||||
|
res.end('Bad PUT bookmark form parameters');
|
||||||
|
} else {
|
||||||
|
renderFav(req, res, fav, false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
/** router for /root */
|
||||||
|
module.exports = router;
|
|
@ -1,8 +1,16 @@
|
||||||
|
// vim: set ts=2 sw=2 et tw=80:
|
||||||
|
|
||||||
|
const mongoose = require('mongoose');
|
||||||
|
|
||||||
|
function catchErrs(promise, res) {
|
||||||
|
return promise.catch(err => error(err, res));
|
||||||
|
}
|
||||||
|
|
||||||
function error(err, res) {
|
function error(err, res) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
res.status = 500;
|
res.status = 500;
|
||||||
res.format({
|
res.format({
|
||||||
json: () => res.json({error: err}),
|
json: () => res.json({ error: err }),
|
||||||
html: () => res.render('500.dust', { err: JSON.stringify(err, null, 2) }),
|
html: () => res.render('500.dust', { err: JSON.stringify(err, null, 2) }),
|
||||||
});
|
});
|
||||||
res.end();
|
res.end();
|
||||||
|
@ -18,15 +26,16 @@ function renderFav(req, res, favs, list = true) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (req.accepts('html')) {
|
||||||
|
res.render(list ? 'favourites.dust' : 'favourite.dust',
|
||||||
|
list ? { favs } : favs);
|
||||||
|
} else if (req.accepts('json')) {
|
||||||
if (list) {
|
if (list) {
|
||||||
favs = favs.map(makeTestsPass);
|
favs = favs.map(makeTestsPass);
|
||||||
} else {
|
} else {
|
||||||
favs = makeTestsPass(favs);
|
favs = makeTestsPass(favs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req.accepts('html')) {
|
|
||||||
res.render(favs ? 'favourites.dust' : 'favourite.dust', list ? { favs } : favs);
|
|
||||||
} else if (req.accepts('json')) {
|
|
||||||
res.json(favs);
|
res.json(favs);
|
||||||
} else {
|
} else {
|
||||||
res.writeHead(406);
|
res.writeHead(406);
|
||||||
|
@ -34,6 +43,22 @@ function renderFav(req, res, favs, list = true) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = { error, renderFav };
|
function parseId(req) {
|
||||||
|
if (typeof req.params.id === 'string' && req.params.id.length == 24) {
|
||||||
|
return mongoose.Types.ObjectId(req.params.id);
|
||||||
|
} else {
|
||||||
|
return req.params.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function notFound(e, res) {
|
||||||
|
if (e == null) {
|
||||||
|
res.writeHead(404, {'Content-Type': 'text/plain'});
|
||||||
|
res.end('Not found');
|
||||||
|
return true;
|
||||||
|
} else return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { error, renderFav, catchErrs, parseId, notFound };
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -16,13 +16,13 @@
|
||||||
<input type="text" name="name" placeholder="Name" value="{name}"><br>
|
<input type="text" name="name" placeholder="Name" value="{name}"><br>
|
||||||
<button>Update</button><br>
|
<button>Update</button><br>
|
||||||
<button formaction="/favorites/{_id}?_method=DELETE">Delete</button><br>
|
<button formaction="/favorites/{_id}?_method=DELETE">Delete</button><br>
|
||||||
{?b}
|
{?bookmarked}
|
||||||
<button name="bookmarked" value="false"
|
<button name="bookmarked" value="false"
|
||||||
formaction="/favorites/{_id}/bookmarked?_method=PUT">Remove bookmark</button>
|
formaction="/favorites/{_id}/bookmarked?_method=PUT">Remove bookmark</button>
|
||||||
{:else}
|
{:else}
|
||||||
<button name="bookmarked" value="true"
|
<button name="bookmarked" value="true"
|
||||||
formaction="/favorites/{_id}/bookmarked?_method=PUT">Add bookmark</button>
|
formaction="/favorites/{_id}/bookmarked?_method=PUT">Add bookmark</button>
|
||||||
{/b}
|
{/bookmarked}
|
||||||
</form>
|
</form>
|
||||||
<a href="/favorites">Favourites list</a>
|
<a href="/favorites">Favourites list</a>
|
||||||
{/details}
|
{/details}
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
{/bookmarked}
|
{/bookmarked}
|
||||||
{#favs}
|
{#favs}
|
||||||
<div>
|
<div>
|
||||||
{>"favourite_partial" name=name dataURL=dataURL _id=_id b=b details="true" /}
|
{>"favourite_partial" name=name dataURL=dataURL _id=_id bookmarked=bookmarked details="true" /}
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<strong>No favourites.</strong>
|
<strong>No favourites.</strong>
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
<h2>Favourites</h2>
|
<h2>Favourites</h2>
|
||||||
<div id="favourites">
|
<div id="favourites">
|
||||||
{#favs}
|
{#favs}
|
||||||
{>"favourite_partial" name=name dataURL=dataURL _id=_id b=b details="true" /}
|
{>"favourite_partial" name=name dataURL=dataURL _id=_id bookmarked=bookmarked details="true" /}
|
||||||
{/favs}
|
{/favs}
|
||||||
</div>
|
</div>
|
||||||
<script src="scripts/brushes.js"></script>
|
<script src="scripts/brushes.js"></script>
|
||||||
|
|
Reference in a new issue