From 7b9ee6804ace45b766f8495bcb0ac3c2bd614e6c Mon Sep 17 00:00:00 2001 From: Giovanni Marcon Date: Tue, 27 Apr 2021 18:33:24 -0300 Subject: [PATCH] Finalizado delete, Adicionado update Livro --- .../controllers/bookController.js" | 216 +++++++++++++++++- .../controllers/bookinstanceController.js" | 50 +++- .../controllers/genreController.js" | 39 +++- .../views/book_delete.pug" | 26 +++ .../views/book_detail.pug" | 7 +- .../views/book_form.pug" | 25 +- .../views/bookinstance_delete.pug" | 13 ++ .../views/bookinstance_detail.pug" | 6 +- 8 files changed, 355 insertions(+), 27 deletions(-) create mode 100644 "Dia 59 at\303\251 62 - Node - Proj Biblioteca/views/book_delete.pug" create mode 100644 "Dia 59 at\303\251 62 - Node - Proj Biblioteca/views/bookinstance_delete.pug" diff --git "a/Dia 59 at\303\251 62 - Node - Proj Biblioteca/controllers/bookController.js" "b/Dia 59 at\303\251 62 - Node - Proj Biblioteca/controllers/bookController.js" index 8541263..1a5fbe0 100644 --- "a/Dia 59 at\303\251 62 - Node - Proj Biblioteca/controllers/bookController.js" +++ "b/Dia 59 at\303\251 62 - Node - Proj Biblioteca/controllers/bookController.js" @@ -190,18 +190,216 @@ exports.book_create_post = [ ]; // Display book delete form on GET. -exports.book_delete_get = function (req, res) { - res.send("NOT IMPLEMENTED: Book delete GET"); +exports.book_delete_get = function (req, res, next) { + async.parallel( + { + book: function (callback) { + Book.findById(req.params.id).exec(callback); + }, + books_books: function (callback) { + BookInstance.find({ book: req.params.id }).exec(callback); + }, + }, + function (err, results) { + if (err) { + return next(err); + } + if (results.book == null) { + // No results. + res.redirect("/catalog/books"); + } + // Successful, so render. + res.render("book_delete", { + title: "Delete Book", + book: results.book, + book_books: results.books_books, + }); + } + ); }; + // Handle book delete on POST. -exports.book_delete_post = function (req, res) { - res.send("NOT IMPLEMENTED: Book delete POST"); +exports.book_delete_post = function (req, res, next) { + async.parallel( + { + book: function (callback) { + Book.findById(req.body.bookid).exec(callback); + }, + books_books: function (callback) { + BookInstance.find({ book: req.body.bookid }).exec(callback); + }, + }, + function (err, results) { + if (err) { + return next(err); + } + // Success + if (results.books_books.length > 0) { + // Book has books. Render in same way as for GET route. + res.render("author_delete", { + title: "Delete Book", + book: results.book, + book_books: results.books_books, + }); + return; + } else { + // Book has no books. Delete object and redirect to the list of books. + Book.findByIdAndRemove(req.body.bookid, function deleteAuthor(err) { + if (err) { + return next(err); + } + // Success - go to book list + res.redirect("/catalog/books"); + }); + } + } + ); }; + +// Display book update form on GET. // Display book update form on GET. -exports.book_update_get = function (req, res) { - res.send("NOT IMPLEMENTED: Book update GET"); +exports.book_update_get = function (req, res, next) { + // Get book, authors and genres for form. + async.parallel( + { + book: function (callback) { + Book.findById(req.params.id) + .populate("author") + .populate("genre") + .exec(callback); + }, + authors: function (callback) { + Author.find(callback); + }, + genres: function (callback) { + Genre.find(callback); + }, + }, + function (err, results) { + if (err) { + return next(err); + } + if (results.book == null) { + // No results. + var err = new Error("Book not found"); + err.status = 404; + return next(err); + } + // Success. + // Mark our selected genres as checked. + for ( + var all_g_iter = 0; + all_g_iter < results.genres.length; + all_g_iter++ + ) { + for ( + var book_g_iter = 0; + book_g_iter < results.book.genre.length; + book_g_iter++ + ) { + if ( + results.genres[all_g_iter]._id.toString() === + results.book.genre[book_g_iter]._id.toString() + ) { + results.genres[all_g_iter].checked = "true"; + } + } + } + res.render("book_form", { + title: "Update Book", + authors: results.authors, + genres: results.genres, + book: results.book, + }); + } + ); }; + // Handle book update on POST. -exports.book_update_post = function (req, res) { - res.send("NOT IMPLEMENTED: Book update POST"); -}; +exports.book_update_post = [ + // Convert the genre to an array + (req, res, next) => { + if (!(req.body.genre instanceof Array)) { + if (typeof req.body.genre === "undefined") req.body.genre = []; + else req.body.genre = new Array(req.body.genre); + } + next(); + }, + + // Validate and sanitise fields. + body("title", "Title must not be empty.") + .trim() + .isLength({ min: 1 }) + .escape(), + body("author", "Author must not be empty.") + .trim() + .isLength({ min: 1 }) + .escape(), + body("summary", "Summary must not be empty.") + .trim() + .isLength({ min: 1 }) + .escape(), + body("isbn", "ISBN must not be empty").trim().isLength({ min: 1 }).escape(), + body("genre.*").escape(), + + // Process request after validation and sanitization. + (req, res, next) => { + // Extract the validation errors from a request. + const errors = validationResult(req); + + // Create a Book object with escaped/trimmed data and old id. + var book = new Book({ + title: req.body.title, + author: req.body.author, + summary: req.body.summary, + isbn: req.body.isbn, + genre: typeof req.body.genre === "undefined" ? [] : req.body.genre, + _id: req.params.id, //This is required, or a new ID will be assigned! + }); + + if (!errors.isEmpty()) { + // There are errors. Render form again with sanitized values/error messages. + + // Get all authors and genres for form. + async.parallel( + { + authors: function (callback) { + Author.find(callback); + }, + genres: function (callback) { + Genre.find(callback); + }, + }, + function (err, results) { + if (err) { + return next(err); + } + + // Mark our selected genres as checked. + for (let i = 0; i < results.genres.length; i++) { + if (book.genre.indexOf(results.genres[i]._id) > -1) { + results.genres[i].checked = "true"; + } + } + res.render("book_form", { + title: "Update Book", + authors: results.authors, + genres: results.genres, + book: book, + errors: errors.array(), + }); + } + ); + return; + } else { + // Data from form is valid. Update the record. + Book.findByIdAndUpdate(req.params.id, book, {}, function (err, thebook) { + if (err) { + return next(err); + } + // Successful - redirect to book detail page. + res.redirect(thebook.url); + }); + } + }, +]; diff --git "a/Dia 59 at\303\251 62 - Node - Proj Biblioteca/controllers/bookinstanceController.js" "b/Dia 59 at\303\251 62 - Node - Proj Biblioteca/controllers/bookinstanceController.js" index 65735b1..8999290 100644 --- "a/Dia 59 at\303\251 62 - Node - Proj Biblioteca/controllers/bookinstanceController.js" +++ "b/Dia 59 at\303\251 62 - Node - Proj Biblioteca/controllers/bookinstanceController.js" @@ -1,5 +1,6 @@ var BookInstance = require("../models/bookinstance"); const { body, validationResult } = require("express-validator"); +const async = require("async"); var Book = require("../models/book"); // Display list of all BookInstances. @@ -111,12 +112,53 @@ exports.bookinstance_create_post = [ ]; // Display BookInstance delete form on GET. -exports.bookinstance_delete_get = function (req, res) { - res.send("NOT IMPLEMENTED: BookInstance delete GET"); +exports.bookinstance_delete_get = function (req, res, next) { + async.parallel( + { + bookinstance: function (callback) { + BookInstance.findById(req.params.id).exec(callback); + }, + }, + function (err, results) { + if (err) { + return next(err); + } + if (results.bookinstance == null) { + // No results. + res.redirect("/catalog/bookinstances"); + } + // Successful, so render. + res.render("bookinstance_delete", { + title: "Delete Book Instance", + book: results.book, + bookinstance: results.bookinstance, + }); + } + ); }; // Handle BookInstance delete on POST. -exports.bookinstance_delete_post = function (req, res) { - res.send("NOT IMPLEMENTED: BookInstance delete POST"); +exports.bookinstance_delete_post = function (req, res, next) { + async.parallel( + { + bookinstance: function (callback) { + BookInstance.findById(req.body.bookinstanceid).exec(callback); + }, + }, + function (err, results) { + if (err) { + return next(err); + } + // Success + // Delete object and redirect to the list of book Instances. + BookInstance.findByIdAndRemove(req.body.bookinstanceid, function deleteBookinstance(err) { + if (err) { + return next(err); + } + // Success - go to book list + res.redirect("/catalog/bookinstances"); + }); + } + ); }; // Display BookInstance update form on GET. exports.bookinstance_update_get = function (req, res) { diff --git "a/Dia 59 at\303\251 62 - Node - Proj Biblioteca/controllers/genreController.js" "b/Dia 59 at\303\251 62 - Node - Proj Biblioteca/controllers/genreController.js" index 7f4139e..f6dbe0d 100644 --- "a/Dia 59 at\303\251 62 - Node - Proj Biblioteca/controllers/genreController.js" +++ "b/Dia 59 at\303\251 62 - Node - Proj Biblioteca/controllers/genreController.js" @@ -109,7 +109,6 @@ exports.genre_delete_get = function (req, res, next) { }, }, function (err, results) { - console.log(results.genre_books); if (err) { return next(err); } @@ -128,9 +127,43 @@ exports.genre_delete_get = function (req, res, next) { }; // Handle Genre delete on POST. -exports.genre_delete_post = function (req, res) { - res.send("NOT IMPLEMENTED: Genre delete POST"); +exports.genre_delete_post = function (req, res, next) { + async.parallel( + { + genre: function (callback) { + Genre.findById(req.body.genreid).exec(callback); + }, + genre_books: function (callback) { + Book.find({ genre: req.body.genreid }).exec(callback); + }, + }, + function (err, results) { + if (err) { + return next(err); + } + // Success + if (results.genre_books.length > 0) { + // Genre has books. Render in same way as for GET route. + res.render("genre_delete", { + title: "Delete Genre", + author: results.genre, + author_books: results.genre_books, + }); + return; + } else { + // Genre has no books. Delete object and redirect to the list of Genres. + Genre.findByIdAndRemove(req.body.genreid, function deleteGenre(err) { + if (err) { + return next(err); + } + // Success - go to author list + res.redirect("/catalog/genres"); + }); + } + } + ); }; + // Display Genre update form on GET. exports.genre_update_get = function (req, res) { res.send("NOT IMPLEMENTED: Genre update GET"); diff --git "a/Dia 59 at\303\251 62 - Node - Proj Biblioteca/views/book_delete.pug" "b/Dia 59 at\303\251 62 - Node - Proj Biblioteca/views/book_delete.pug" new file mode 100644 index 0000000..31a654c --- /dev/null +++ "b/Dia 59 at\303\251 62 - Node - Proj Biblioteca/views/book_delete.pug" @@ -0,0 +1,26 @@ +extends layout + +block content + h1 #{title}: #{book.title} + + if book_books.length + + p #[strong Delete the following books instances before attempting to delete this book.] + + div(style='margin-left:20px;margin-top:20px') + + h4 Books + + dl + each booki in book_books + dt + a(href=booki.url) #{book.title} + + else + p Do you really want to delete this Book? + + form(method='POST' action='') + div.form-group + input#bookid.form-control(type='hidden',name='bookid', required='true', value=book._id ) + + button.btn.btn-primary(type='submit') Delete \ No newline at end of file diff --git "a/Dia 59 at\303\251 62 - Node - Proj Biblioteca/views/book_detail.pug" "b/Dia 59 at\303\251 62 - Node - Proj Biblioteca/views/book_detail.pug" index f857e0b..12ed9bf 100644 --- "a/Dia 59 at\303\251 62 - Node - Proj Biblioteca/views/book_detail.pug" +++ "b/Dia 59 at\303\251 62 - Node - Proj Biblioteca/views/book_detail.pug" @@ -31,4 +31,9 @@ block content a(href=val.url) #{val._id} else - p There are no copies of this book in the library. \ No newline at end of file + p There are no copies of this book in the library. + hr + p + a(href=book.url+'/delete') Delete Book + p + a(href=book.url+'/update') Update Book \ No newline at end of file diff --git "a/Dia 59 at\303\251 62 - Node - Proj Biblioteca/views/book_form.pug" "b/Dia 59 at\303\251 62 - Node - Proj Biblioteca/views/book_form.pug" index 079183a..176b74c 100644 --- "a/Dia 59 at\303\251 62 - Node - Proj Biblioteca/views/book_form.pug" +++ "b/Dia 59 at\303\251 62 - Node - Proj Biblioteca/views/book_form.pug" @@ -8,14 +8,21 @@ block content label(for='title') Title: input#title.form-control(type='text', placeholder='Name of book' name='title' required='true' value=(undefined===book ? '' : book.title) ) div.form-group - label(for='author') Author: - select#author.form-control(type='select', placeholder='Select author' name='author' required='true' ) - - authors.sort(function(a, b) {let textA = a.family_name.toUpperCase(); let textB = b.family_name.toUpperCase(); return (textA < textB) ? -1 : (textA > textB) ? 1 : 0;}); - for author in authors - if book - option(value=author._id selected=(author._id.toString()===book.author._id.toString() ? 'selected' : false) ) #{author.name} - else - option(value=author._id) #{author.name} + label(for='author') Author: + select#author.form-control(type='select' placeholder='Select author' name='author' required='true' ) + - authors.sort(function(a, b) {let textA = a.family_name.toUpperCase(); let textB = b.family_name.toUpperCase(); return (textA < textB) ? -1 : (textA > textB) ? 1 : 0;}); + for author in authors + if book + //- Handle GET form, where book.author is an object, and POST form, where it is a string. + option( + value=author._id + selected=( + author._id.toString()==book.author._id + || author._id.toString()==book.author + ) ? 'selected' : false + ) #{author.name} + else + option(value=author._id) #{author.name} div.form-group label(for='summary') Summary: textarea#summary.form-control(type='textarea', placeholder='Summary' name='summary' required='true') #{undefined===book ? '' : book.summary} @@ -34,4 +41,4 @@ block content if errors ul for error in errors - li!= error.msg \ No newline at end of file + li!= error.msg diff --git "a/Dia 59 at\303\251 62 - Node - Proj Biblioteca/views/bookinstance_delete.pug" "b/Dia 59 at\303\251 62 - Node - Proj Biblioteca/views/bookinstance_delete.pug" new file mode 100644 index 0000000..88dd51c --- /dev/null +++ "b/Dia 59 at\303\251 62 - Node - Proj Biblioteca/views/bookinstance_delete.pug" @@ -0,0 +1,13 @@ +extends layout + +block content + h1 #{title} + h2 Imprint: #{bookinstance.imprint} + + p Do you really want to delete this Book Instance? + + form(method='POST' action='') + div.form-group + input#bookinstanceid.form-control(type='hidden',name='bookinstanceid', required='true', value=bookinstance._id ) + + button.btn.btn-primary(type='submit') Delete \ No newline at end of file diff --git "a/Dia 59 at\303\251 62 - Node - Proj Biblioteca/views/bookinstance_detail.pug" "b/Dia 59 at\303\251 62 - Node - Proj Biblioteca/views/bookinstance_detail.pug" index c91f722..32d518f 100644 --- "a/Dia 59 at\303\251 62 - Node - Proj Biblioteca/views/bookinstance_detail.pug" +++ "b/Dia 59 at\303\251 62 - Node - Proj Biblioteca/views/bookinstance_detail.pug" @@ -17,4 +17,8 @@ block content span.text-warning #{bookinstance.status} if bookinstance.status!='Available' - p #[strong Due back: ] #{bookinstance.due_back_formatted} \ No newline at end of file + p #[strong Due back: ] #{bookinstance.due_back_formatted} + + hr + p + a(href=bookinstance.url+'/delete') Delete book instance \ No newline at end of file