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};