litebb/controllers/post.controller.js

1const { Board, Post, User, Reply } = require("../models"); 2const { makeSlug, displayDateTime, convertMdToHTML } = require("../helpers"); 3 4const getNewPostPage = async (req, res, next) => { 5 try { 6 const board = await Board.findOne({ 7 where: { 8 slug: req.params.board_slug, 9 }, 10 attributes: ["id", "name"], 11 }); 12 13 if (!board) { 14 const err = { 15 message: "Board not found!", 16 status: 404, 17 }; 18 next(err); 19 return; 20 } 21 22 const breadcrumbData = [ 23 { link: "/", name: "Index" }, 24 { link: `/b/${req.params.board_slug}`, name: board.name }, 25 { name: "New Post" }, 26 ]; 27 28 res.render("new_post", { title: "New Post", board, breadcrumbData }); 29 return; 30 } catch (e) { 31 console.log(e); 32 next(e); 33 return; 34 } 35}; 36 37const createPost = async (req, res, next) => { 38 try { 39 const board_id = req.params.board_id; 40 const post = { 41 name: req.body.name, 42 content: req.body.content, 43 renderedContent: "", 44 slug: makeSlug(req.body.name), 45 boardId: board_id, 46 createdByUser: req.session.user.id, 47 }; 48 49 post.renderedContent = convertMdToHTML(post.content); 50 51 const newPost = await Post.create(post); 52 53 if (!newPost) { 54 req.flash("error", ["Could not create post"]); 55 res.render("new_post", { 56 title: "New Post", 57 body: req.body, 58 flashes: req.flash(), 59 }); 60 return; 61 } 62 63 res.redirect(`/p/${post.slug}`); 64 return; 65 } catch (e) { 66 console.log(e); 67 next(e); 68 return; 69 } 70}; 71 72const getPostPage = async (req, res, next) => { 73 try { 74 const post = await Post.findOne({ 75 where: { 76 slug: req.params.post_slug, 77 }, 78 attributes: [ 79 "id", 80 "name", 81 "content", 82 "renderedContent", 83 "boardId", 84 "createdByUser", 85 "createdAt", 86 "updatedAt", 87 ], 88 include: [ 89 { 90 model: User, 91 as: "author", 92 attributes: ["id", "username", "avatar"], 93 }, 94 { 95 model: Board, 96 as: "board", 97 attributes: ["id", "name", "slug"], 98 }, 99 ], 100 }); 101 102 if (!post) { 103 const err = { 104 message: "Post not found!", 105 status: 404, 106 }; 107 next(err); 108 return; 109 } 110 111 post.createdAtFormatted = displayDateTime(post.createdAt); 112 post.updatedAtFormatted = displayDateTime(post.updatedAt); 113 114 // get paginated replies in board too 115 // console.log(JSON.stringify(post), displayDateTime(post.createdAt), '<<- post') 116 const page = req.query.page || 1; 117 const limit = 10; 118 const skip = page * limit - limit; 119 120 const repliesQuery = Reply.findAll({ 121 where: { 122 postId: post.id, 123 }, 124 attributes: ["id", "content", "createdAt", "createdByUser"], 125 offset: skip, 126 limit: limit, 127 include: [ 128 { 129 model: User, 130 as: "replied_by", 131 attributes: ["id", "username", "avatar"], 132 }, 133 ], 134 }); 135 136 const countQuery = Reply.count({ 137 where: { 138 postId: post.id, 139 }, 140 }); 141 142 const [replies, count] = await Promise.all([repliesQuery, countQuery]); 143 144 const pages = Math.ceil(count / limit); // no replies would make it 0 145 146 const formattedReplies = replies.map((r) => { 147 const replyObject = JSON.parse(JSON.stringify(r)); 148 const newReply = { ...replyObject }; 149 newReply.createdAtFormatted = displayDateTime(newReply.createdAt); 150 return newReply; 151 }); 152 // console.log(formattedReplies) 153 // console.log(JSON.stringify(replies), '<<- replies') 154 155 const breadcrumbData = [ 156 { link: "/", name: "Index" }, 157 { link: `/b/${post.board.slug}`, name: post.board.name }, 158 { name: post.name }, 159 ]; 160 161 res.render("post", { 162 title: post.name, 163 post, 164 replies: formattedReplies, 165 page, 166 pages, 167 count, 168 skip, 169 breadcrumbData, 170 }); 171 return; 172 } catch (e) { 173 console.log(e); 174 next(e); 175 return; 176 } 177}; 178 179const getPostEditPage = async (req, res, next) => { 180 try { 181 const post = await Post.findOne({ 182 where: { 183 slug: req.params.post_slug, 184 }, 185 attributes: [ 186 "id", 187 "name", 188 "content", 189 "boardId", 190 "createdByUser", 191 "createdAt", 192 "slug", 193 ], 194 include: [ 195 { 196 model: Board, 197 as: "board", 198 attributes: ["id", "name", "slug"], 199 }, 200 ], 201 }); 202 203 if (!post) { 204 res.redirect("/"); 205 return; 206 } 207 208 if (post.createdByUser !== req.session.user.id) { 209 res.redirect("/"); 210 return; 211 } 212 213 const breadcrumbData = [ 214 { link: "/", name: "Index" }, 215 { link: `/b/${post.board.slug}`, name: post.board.name }, 216 { link: `/p/${post.slug}`, name: post.name }, 217 { name: "Edit Post" }, 218 ]; 219 220 res.render("edit_post", { title: "Edit Post", post, breadcrumbData }); 221 return; 222 } catch (e) { 223 console.log(e); 224 next(e); 225 return; 226 } 227}; 228 229const updatePost = async (req, res, next) => { 230 try { 231 const post = await Post.findOne({ 232 where: { 233 id: req.params.post_id, 234 createdByUser: req.session.user.id, 235 }, 236 attributes: ["id", "slug"], 237 }); 238 239 if (!post) { 240 res.redirect("/"); 241 return; 242 } 243 244 post.content = req.xop.content; 245 post.renderedContent = convertMdToHTML(post.content); 246 247 await post.save(); 248 249 res.redirect(`/p/${post.slug}`); 250 return; 251 } catch (e) { 252 console.log(e); 253 next(e); 254 return; 255 } 256}; 257 258module.exports = { 259 getNewPostPage, 260 createPost, 261 getPostPage, 262 getPostEditPage, 263 updatePost, 264};