mirror of
https://gitea.smigz.com/smiggiddy/odin-codeprojects.git
synced 2025-04-04 19:10:56 -04:00
feat: added a comment section
This commit is contained in:
parent
27840f3537
commit
eda40eb113
11 changed files with 197 additions and 12 deletions
|
@ -15,11 +15,40 @@ const validateContent = [
|
|||
body("message").isLength({ min: 2 }).withMessage("Please enter a message."),
|
||||
];
|
||||
|
||||
const validateComment = [body("comment").trim().isLength({ min: 2, max: 140 })];
|
||||
|
||||
async function getCommentPerMessage(rows) {
|
||||
const commentsTotal = rows.map(async (row) =>
|
||||
db.getAllCommentsForMessage(row.id),
|
||||
);
|
||||
|
||||
return Promise.all(commentsTotal)
|
||||
.then((c) =>
|
||||
c.filter((msg) => {
|
||||
if (msg.length > 0) return msg;
|
||||
}),
|
||||
)
|
||||
.then((c) =>
|
||||
c.map((m) => {
|
||||
return { [m[0].message_id]: m.length };
|
||||
}),
|
||||
)
|
||||
.then((result) => Object.assign({}, ...result));
|
||||
}
|
||||
|
||||
async function indexGet(req, res, next) {
|
||||
try {
|
||||
const rows = await db.getAllMessages();
|
||||
if (rows === undefined) rows = [];
|
||||
res.render("index", { links: links, msgs: rows, dateParser: dateParser });
|
||||
|
||||
const messageComments = await getCommentPerMessage(rows);
|
||||
|
||||
res.render("index", {
|
||||
links: links,
|
||||
msgs: rows,
|
||||
dateParser: dateParser,
|
||||
comments: messageComments,
|
||||
});
|
||||
} catch {
|
||||
res.render("index", { links: links, msgs: [] });
|
||||
}
|
||||
|
@ -46,9 +75,39 @@ async function newPost(req, res) {
|
|||
res.redirect("/");
|
||||
}
|
||||
|
||||
async function commentsGet(req, res) {
|
||||
const { id } = req.query;
|
||||
const messageId = Number(id);
|
||||
try {
|
||||
if (!isNaN(messageId)) {
|
||||
const message = await db.getMessageById(messageId);
|
||||
const comments = await db.getAllCommentsForMessage(messageId);
|
||||
|
||||
res.render("comments", {
|
||||
message: message,
|
||||
comments: comments,
|
||||
links: links,
|
||||
dateParser: dateParser,
|
||||
});
|
||||
} else {
|
||||
res.status(404).send("error");
|
||||
}
|
||||
} catch {
|
||||
res.send("something went wrong");
|
||||
}
|
||||
}
|
||||
|
||||
async function commentsPost(req, res, next) {
|
||||
const { comment, messageId } = req.body;
|
||||
db.insertComment(messageId, comment);
|
||||
res.redirect(`/comment?id=${messageId}`);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
indexGet,
|
||||
newGet,
|
||||
newPost,
|
||||
commentsGet,
|
||||
validateContent,
|
||||
commentsPost,
|
||||
};
|
||||
|
|
|
@ -28,6 +28,13 @@ CREATE TABLE IF NOT EXISTS messages (
|
|||
username VARCHAR(25),
|
||||
date NUMBER
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS comments (
|
||||
id INTEGER PRIMARY KEY ASC,
|
||||
comment TEXT,
|
||||
message_id INTEGER,
|
||||
FOREIGN KEY (message_id) REFERENCES messages(id)
|
||||
)
|
||||
`;
|
||||
db.exec(SQL);
|
||||
});
|
||||
|
|
|
@ -8,15 +8,43 @@ async function getAllMessages() {
|
|||
});
|
||||
}
|
||||
|
||||
async function getMessageById(id) {
|
||||
return new Promise((resolve) => {
|
||||
db.get("SELECT * FROM messages WHERE id = (?)", [id], async (err, rows) => {
|
||||
resolve(rows);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function insertMessage(msg) {
|
||||
db.run("INSERT INTO MESSAGES (message, username, date) VALUES ($1, $2, $3)", [
|
||||
db.run("INSERT INTO messages (message, username, date) VALUES ($1, $2, $3)", [
|
||||
msg.message,
|
||||
msg.username,
|
||||
msg.date,
|
||||
]);
|
||||
}
|
||||
|
||||
async function getAllCommentsForMessage(msgId) {
|
||||
return new Promise((resolve) => {
|
||||
db.all(
|
||||
"SELECT * FROM COMMENTS WHERE message_id = (?)",
|
||||
[msgId],
|
||||
async (err, rows) => resolve(rows),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
async function insertComment(msgId, comment) {
|
||||
db.run("INSERT INTO comments (comment, message_id) VALUES ($1, $2)", [
|
||||
comment,
|
||||
msgId,
|
||||
]);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getMessageById,
|
||||
getAllMessages,
|
||||
insertMessage,
|
||||
getAllCommentsForMessage,
|
||||
insertComment,
|
||||
};
|
||||
|
|
4
nodejs-mini-message-board/src/public/script.js
Normal file
4
nodejs-mini-message-board/src/public/script.js
Normal file
|
@ -0,0 +1,4 @@
|
|||
function test(event) {
|
||||
const messageId = event.target.dataset.messageId;
|
||||
window.location.href = `comment?id=${messageId}`;
|
||||
}
|
|
@ -68,6 +68,10 @@ a {
|
|||
box-shadow: 0px 1px 4px #525252;
|
||||
}
|
||||
|
||||
.material-symbols-outlined:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.card-message {
|
||||
width: 100%;
|
||||
background-color: white;
|
||||
|
@ -100,6 +104,12 @@ a {
|
|||
font-weight: 400;
|
||||
}
|
||||
|
||||
.metadata-right {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.form-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
@ -162,3 +172,26 @@ a {
|
|||
.errors {
|
||||
color: red;
|
||||
}
|
||||
.comment-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
max-width: 600px;
|
||||
}
|
||||
|
||||
.comment {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.comment span {
|
||||
margin-right: 1rem;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.comment .material-symbols-outlined:hover {
|
||||
cursor: initial;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
const { Router } = require("express");
|
||||
const indexController = require("../controllers/indexController");
|
||||
const db = require("../db");
|
||||
|
||||
const indexRouter = Router();
|
||||
|
||||
|
@ -11,5 +10,7 @@ indexRouter.post(
|
|||
indexController.validateContent,
|
||||
indexController.newPost,
|
||||
);
|
||||
indexRouter.get("/comment", indexController.commentsGet);
|
||||
indexRouter.post("/comment", indexController.commentsPost);
|
||||
|
||||
module.exports = { indexRouter };
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
const { Router } = require("express");
|
||||
|
||||
const msgRouter = Router();
|
||||
|
||||
msgRouter.get("/", (req, res) => {
|
||||
res.render("msgs");
|
||||
});
|
||||
|
||||
module.exports = { msgRouter };
|
49
nodejs-mini-message-board/src/views/comments.ejs
Normal file
49
nodejs-mini-message-board/src/views/comments.ejs
Normal file
|
@ -0,0 +1,49 @@
|
|||
<%- include('header') %>
|
||||
<%- include('partials/errors.ejs') %>
|
||||
|
||||
<div class="container">
|
||||
<h1 class="msg-headline"> @<%= message.username %>'s message</h1>
|
||||
<div class="card">
|
||||
<div class="card-metadata">
|
||||
<h3>@<%= message.username %></h3>
|
||||
<div class="metadata-right">
|
||||
<span><%= dateParser(message.date) %></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-message">
|
||||
<p><%= message.message %></p>
|
||||
</div>
|
||||
</div>
|
||||
<h2> Comments</h2>
|
||||
<div class="comment-section">
|
||||
<% if (comments.length > 0) { %>
|
||||
<% comments.forEach((comment) => { %>
|
||||
<div class="comment">
|
||||
<span class="material-symbols-outlined">chat</span>
|
||||
<p> <%= comment.comment %></p>
|
||||
</div>
|
||||
|
||||
<% }); %>
|
||||
<% } else { %>
|
||||
<p> No comments yet, add one below </p>
|
||||
<% } %>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<form method="POST" action="/comment">
|
||||
<div class="container">
|
||||
<h1 class="msg-headline">Add a comment :)</h1>
|
||||
<div class="form-item">
|
||||
<label for="message">Comment</label>
|
||||
<textarea id="comment" name="comment" rows="5" placeholder="Add your two cents..." required></textarea>
|
||||
<input type="hidden" name="messageId" value=<%= message.id %> id="messageId">
|
||||
</div>
|
||||
<div class="form-item btn-row">
|
||||
<button class="btn primary-btn" type="submit">Post</button>
|
||||
<button class="btn" type="button" onCLick="window.location='/';">Return</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<%- include('footer') %>
|
||||
<!-- vim: sts=2 sw=2 et ts=2 # -->
|
|
@ -1,2 +1,3 @@
|
|||
<script src="/script.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&family=Leckerli+One&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&icon_names=chat,comment,mode_comment" />
|
||||
</head>
|
||||
<body>
|
||||
<!-- this should be some stuff that loads --!>
|
||||
|
|
|
@ -8,7 +8,18 @@
|
|||
<div class="card">
|
||||
<div class="card-metadata">
|
||||
<h3>@<%= msg.username %></h3>
|
||||
<div class="metadata-right">
|
||||
<span><%= dateParser(msg.date) %></span>
|
||||
<% if (comments[msg.id]) { %>
|
||||
<span class="material-symbols-outlined" onClick="test(event)" data-message-id="<%= msg.id %>">
|
||||
comment
|
||||
</span>
|
||||
<% } else { %>
|
||||
<span class="material-symbols-outlined" onClick="test(event)" data-message-id="<%= msg.id %>">
|
||||
mode_comment
|
||||
</span>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-message">
|
||||
<p><%= msg.message %></p>
|
||||
|
|
Loading…
Add table
Reference in a new issue