Application de blogs Express.js

Oct 26 2020

J'ai mis en place cette application de blogging avec Express , EJS et MongoDB.

Il y a une partie frontale publique et un tableau de bord. Dans index.js, j'ai:

// Bring the Dashboard
const dashboardRoute = require("./routes/admin/dashboard");

// Register Dashboard Routes
app.use('/dashboard', dashboardRoute);

// Bring the Posts Routes
const postsRoute = require('./routes/front-end/posts');

// Register Posts Routes
app.use('/', postsRoute);

Dans routes\admin\dashboard.jsj'ai:

const express = require('express');
const imageUploader = require('../../utils/imageupload.js');
const validator = require('../../utils/validation.js');
const dashboardController = require('../../controllers/admin/dashboard');
const categoriesController = require('../../controllers/admin/categories');

// Express router
const router = express.Router();

// Display Dashboard
router.get('/', dashboardController.displayDashboard);

// Render add Post Form
router.get('/addpost', dashboardController.addPostForm);

// Add Post
router.post('/post/add', imageUploader.upload, validator.addPostCheck, dashboardController.addPost);

// Edit Post
router.get('/post/edit/:id', dashboardController.editPost);

// Update Post
router.post('/post/update/:id', imageUploader.upload, validator.addPostCheck, dashboardController.updatePost);

// Delete Post
router.delete('/post/delete/:id', dashboardController.deletePost);

// Display Categories
router.get('/categories', categoriesController.showCategories);

// Render add Categories Form
router.get('/categories/addcategory', categoriesController.addCategoryForm);

// Add Category
router.post('/category/add', validator.addCategoryCheck, categoriesController.addCategory);

// Edit Post
router.get('/category/edit/:id', categoriesController.editCategory);

// Update Category
router.post('/category/update/:id', validator.addCategoryCheck, categoriesController.updateCategory);

// Delete Category
router.delete('/category/delete/:id', categoriesController.deleteCategory);

module.exports = router;

Je suis particulièrement préoccupé par les contrôleurs "sous" le tableau de bord ( controllers\admin\dashboard.js):

const Post = require('../../models/post');
const Category = require('../../models/categories');
const {upload} = require('multer');
const {validationResult} = require('express-validator');

exports.displayDashboard = async (req, res, next) => {
    const posts = await Post.find({}, (err, posts) => {
        if (err) {
            console.log('Error: ', err);
        } else {
            res.render('admin/index', {
                layout: 'admin/layout',
                website_name: 'MEAN Blog',
                page_heading: 'Dashboard',
                posts: posts
            });
        }
    }).populate('category');
};

exports.addPostForm = async (req, res, next) => {
    const categories = await Category.find({}, (err, categories) => {
        if (err) {
            console.log('Error: ', err);
        } else {
            res.render('admin/addpost', {
                layout: 'admin/layout',
                website_name: 'MEAN Blog',
                page_heading: 'Dashboard',
                page_subheading: 'Add New Post',
                categories: categories
            });
        }
    });
}

exports.addPost = (req, res, next) => {

    const form = {
        titleholder: req.body.title,
        excerptholder: req.body.excerpt,
        bodyholder: req.body.body
    };

    const errors = validationResult(req);

    const post = new Post();

    post.title = req.body.title;
    post.short_description = req.body.excerpt
    post.full_text = req.body.body;
    post.category = req.body.category;
    if (req.file) {
        post.post_image = req.file.filename;
    }

    if (!errors.isEmpty()) {
        const categories = Category.find({}, (err, categories) => {
            req.flash('danger', errors.array())
            res.render('admin/addpost', {
                layout: 'admin/layout',
                website_name: 'MEAN Blog',
                page_heading: 'Dashboard',
                page_subheading: 'Add New Post',
                categories: categories,
                form: form
            });
        });
    } else {
        post.save(function(err) {
            if (err) {
                console.log(err);
                return;
            } else {
                req.flash('success', "The post was successfully added");
                req.session.save(() => res.redirect('/dashboard'));
            }
        });
    }
}

exports.editPost = async (req, res, next) => {
    const postId = req.params.id;

    Post.findById(postId, function(err, post) {
        const categories = Category.find({}, (err, categories) => {
            if (err) {
                console.log('Error: ', err);
            } else {
                res.render('admin/editpost', {
                    layout: 'admin/layout',
                    website_name: 'MEAN Blog',
                    page_heading: 'Dashboard',
                    page_subheading: 'Edit Post',
                    categories: categories,
                    post: post
                });
            }
        });
    });
}

exports.updatePost = (req, res, next) => {

    const query = {
        _id: req.params.id
    }

    const form = {
        titleholder: req.body.title,
        excerptholder: req.body.excerpt,
        bodyholder: req.body.body
    };

    const errors = validationResult(req);

    const post = {};

    post._id = req.params.id;
    post.title = req.body.title;
    post.short_description = req.body.excerpt
    post.full_text = req.body.body;
    post.category = req.body.category;
    if (req.file) {
        post.post_image = req.file.filename;
    }

    if (!errors.isEmpty()) {
        req.flash('danger', errors.array());
        const categories = Category.find({}, (err, categories) => {
            res.render('admin/editpost', {
                layout: 'admin/layout',
                website_name: 'MEAN Blog',
                page_heading: 'Dashboard',
                page_subheading: 'Edit Post',
                categories: categories,
                form: form,
                post: post
            });
        });
    } else {
        Post.update(query, post, function(err) {
            if (err) {
                console.log(err);
                return;
            } else {
                req.flash('success', "The post was successfully updated");
                req.session.save(() => res.redirect('/dashboard'));
            }
        });
    }
}

exports.deletePost = (req, res, next) => {
    const postId = req.params.id;
    Post.findByIdAndRemove(postId, function(err) {
        if (err) {
            console.log('Error: ', err);
        }
        res.sendStatus(200);
    });
}

Le responsable du traitement concernant les catégories :

const Category = require('../../models/categories');
const { validationResult } = require('express-validator');

exports.showCategories = async (req, res, next) => {
    const categories = await Category.find({}, (err, categories) => {
        if(err){
            console.log('Error: ', err);
        } else {
            res.render('admin/categories', {
              layout: 'admin/layout',
              website_name: 'MEAN Blog',
                            page_heading: 'Dashboard',
                            page_subheading: 'Categories',
              categories: categories
            });
        }
    });
};

exports.addCategoryForm = (req, res, next) => {
    res.render('admin/addcategory', {
        layout: 'admin/layout',
        website_name: 'MEAN Blog',
        page_heading: 'Dashboard',
        page_subheading: 'Add New Category',
    });
}

exports.addCategory = (req, res, next) => {

    var form = {
        categoryholder: req.body.cat_name
    };
    
    const errors = validationResult(req);

    const category = new Category();

    category.cat_name = req.body.cat_name;

    if (!errors.isEmpty()) {
        req.flash('danger', errors.array())
        res.render('admin/addcategory',{
            layout: 'admin/layout',
            website_name: 'MEAN Blog',
            page_heading: 'Dashboard',
            page_subheading: 'Add New Category',
            form:form
        }
        );
    } else {
        category.save(function(err) {
            if (err) {
                console.log(err);
                return;
            } else {
                req.flash('success', "The category was successfully added");
                req.session.save(() => res.redirect('/dashboard/categories'));
            }
        });
    }
}

exports.editCategory = (req, res, next) => {
    const catId = req.params.id;

    Category.findById(catId, function(err, category){
        if (err) {
            console.log('Error: ', err);
        } else {
            res.render('admin/editcategory', {
                layout: 'admin/layout',
                website_name: 'MEAN Blog',
                page_heading: 'Dashboard',
                page_subheading: 'Edit Category',
                category: category
            });
        }
    });
}

exports.updateCategory = (req, res, next) => {

    const query = {_id:req.params.id}

    var form = {
        categoryholder: req.body.cat_name
    };

    const errors = validationResult(req);
    
    const category = {};
    
    category._id = req.params.id;
    category.cat_name = req.body.cat_name;

    if (!errors.isEmpty()) {
        req.flash('danger', errors.array())
        res.render('admin/editcategory',{
            layout: 'admin/layout',
            website_name: 'MEAN Blog',
            page_heading: 'Dashboard',
            page_subheading: 'Edit Category',
            form: form,
            category: category
        }
        );
    } else {
        Category.update(query, category, function(err){
            if(err){
                console.log(err);
                return;
            } else {
                req.flash('success', "The category was successfully updated");
                req.session.save(() => res.redirect('/dashboard/categories'));
            }
        });
    }
}

exports.deleteCategory = (req, res, next) => {
    const catId = req.params.id;
    Category.findByIdAndRemove(catId, function(err){
        if (err) {
            console.log('Error: ', err);
        }
        res.sendStatus(200);
    });
}

Réponses

2 SᴀᴍOnᴇᴌᴀ Oct 31 2020 at 14:20

Notation de définition de propriété abrégée

Comme je l'ai mentionné dans une réponse à l'un de vos articles précédents, la notation de définition de propriété abrégée peut être utilisée pour simplifier les lignes comme celles-ci où la clé est la même que le nom de la variable référencée:

 categories: categories,
 posts: posts

Pour simplement:

 categories,
 posts

En attendant avec await

Avec async / await, le code qui est généralement dans le rappel de promesse peut être déplacé vers l'extérieur - prenez donc cette section par exemple:

 const posts = await Post.find({}, (err, posts) => {
     if (err) {
             console.log('Error: ', err);
         } else {
             res.render('admin/index', {
                 layout: 'admin/layout',
                 website_name: 'MEAN Blog',
                 page_heading: 'Dashboard',
                 posts: posts
             });
         }
     }).populate('category');

Je n'ai pas testé ce code mais je suppose que l'appel à .populate('category')vient après le rappel où res.render()est appelé - donc cela peut être un bogue .

Cela peut être comme simplifié à quelque chose comme ceci:

const posts = await Post.find({}).populate('category').catch(err => {
        console.log('Error: ', err);
    });
res.render('admin/index', {
    layout: 'admin/layout',
    website_name: 'MEAN Blog',
    page_heading: 'Dashboard',
    posts
});

Bien que l'appel de remplissage de la catégorie doive peut-être venir après la valeur de Post.find({})Est assignée à posts.

Et de même pour les autres fonctions appelées avec await. De cette façon, la valeur attribuée à postsfrom peut être utilisée correctement.

elseMot-clé inutile aprèsreturn

Dans le rappel à post.save():

  if (err) {
      console.log(err);
      return;
  } else {
      req.flash('success', "The post was successfully added");
      req.session.save(() => res.redirect('/dashboard'));
  }

Le code du elsebloc peut être déplacé car dans le premier cas, il y a une returninstruction. Cela peut réduire le niveau d'indentation.

variable déclarée avec var

La réponse de CertainPerformance à votre article précédent recommande d'éviter le varmot - clé. Pourtant ce code l'utilise:

exports.addCategory = (req, res, next) => {

     var form = {
         categoryholder: req.body.cat_name
     };

Cette variable n'est jamais réaffectée et peut donc être déclarée avec const. Et de même pour updateCategory()- il a une variable déclarée avec varnamed formqui n'est jamais réaffectée.