mirror of
https://gitea.smigz.com/smiggiddy/odin-codeprojects.git
synced 2025-04-05 03:10:57 -04:00
more code
This commit is contained in:
parent
e07590d6e5
commit
90769c9bf1
16 changed files with 1710 additions and 63 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,3 +1,4 @@
|
||||||
|
*.db
|
||||||
# Logs
|
# Logs
|
||||||
logs
|
logs
|
||||||
*.log
|
*.log
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
FROM node:23-alpine
|
FROM node:23-alpine
|
||||||
|
|
||||||
COPY package*.json /app/package*.json
|
COPY package.json package-lock.json /app
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
@ -12,6 +12,8 @@ EXPOSE 3000
|
||||||
|
|
||||||
USER nobody
|
USER nobody
|
||||||
|
|
||||||
CMD ["node", "src/app.js"]
|
ENTRYPOINT ["node"]
|
||||||
|
|
||||||
|
CMD ["src/app.js"]
|
||||||
|
|
||||||
|
|
||||||
|
|
1487
nodejs-mini-message-board/package-lock.json
generated
1487
nodejs-mini-message-board/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,14 @@
|
||||||
{
|
{
|
||||||
|
"name": "Odin - Message Board",
|
||||||
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ejs": "^3.1.10",
|
"ejs": "^3.1.10",
|
||||||
"express": "^4.21.2"
|
"express": "^4.21.2",
|
||||||
|
"express-validator": "^7.2.0",
|
||||||
|
"sqlite3": "^5.1.7"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"seed_db": "node $PWD/src/db/seedDb.js",
|
||||||
|
"start": "node --watch src/app.js"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ const port = 3000;
|
||||||
|
|
||||||
const { indexRouter } = require("./routes/indexRouter");
|
const { indexRouter } = require("./routes/indexRouter");
|
||||||
//const { msgRouter } = require("./routes/msgRouter");
|
//const { msgRouter } = require("./routes/msgRouter");
|
||||||
|
//
|
||||||
|
|
||||||
app.set("views", path.join(__dirname, "views"));
|
app.set("views", path.join(__dirname, "views"));
|
||||||
app.set("view engine", "ejs");
|
app.set("view engine", "ejs");
|
||||||
|
@ -15,8 +16,15 @@ app.use(express.static(assetsPath));
|
||||||
|
|
||||||
app.use(express.urlencoded({ extended: true }));
|
app.use(express.urlencoded({ extended: true }));
|
||||||
|
|
||||||
|
app.use((req, res, next) => {
|
||||||
|
req.time = new Date(Date.now()).toISOString();
|
||||||
|
console.log(req.time, req.method, req.hostname, req.path);
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
|
||||||
app.use("/", indexRouter);
|
app.use("/", indexRouter);
|
||||||
//app.use("/new", msgRouter);
|
//app.use("/new", msgRouter);
|
||||||
|
//
|
||||||
|
|
||||||
const server = app.listen(port, () => {
|
const server = app.listen(port, () => {
|
||||||
console.log(`Webserver running on ${port}.`);
|
console.log(`Webserver running on ${port}.`);
|
||||||
|
|
53
nodejs-mini-message-board/src/controllers/indexController.js
Normal file
53
nodejs-mini-message-board/src/controllers/indexController.js
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
const db = require("../db/query");
|
||||||
|
const { body, validationResult } = require("express-validator");
|
||||||
|
|
||||||
|
const links = [
|
||||||
|
{ href: "/", text: "Home" },
|
||||||
|
{ href: "/new", text: "New" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const validateContent = [
|
||||||
|
body("message").isLength({ min: 2 }).withMessage("Must enter a message!"),
|
||||||
|
body("username")
|
||||||
|
.trim()
|
||||||
|
.isLength({ min: 2, max: 25 })
|
||||||
|
.withMessage("Username Must be between 2 and 25 chars."),
|
||||||
|
];
|
||||||
|
|
||||||
|
async function indexGet(req, res, next) {
|
||||||
|
try {
|
||||||
|
const rows = await db.getAllMessages();
|
||||||
|
if (rows === undefined) rows = [];
|
||||||
|
res.render("index", { links: links, msgs: rows });
|
||||||
|
} catch {
|
||||||
|
res.render("index", { links: links, msgs: [] });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function newGet(req, res) {
|
||||||
|
res.render("msgs", { links: links });
|
||||||
|
}
|
||||||
|
|
||||||
|
async function newPost(req, res) {
|
||||||
|
const errors = validationResult(req);
|
||||||
|
if (!errors.isEmpty()) {
|
||||||
|
return res.status(400).render("msgs", {
|
||||||
|
links: links,
|
||||||
|
errors: errors.array(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const { message, username } = req.body;
|
||||||
|
db.insertMessage({
|
||||||
|
message: message,
|
||||||
|
username: username,
|
||||||
|
date: new Date().toISOString(),
|
||||||
|
});
|
||||||
|
res.redirect("/");
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
indexGet,
|
||||||
|
newGet,
|
||||||
|
newPost,
|
||||||
|
validateContent,
|
||||||
|
};
|
0
nodejs-mini-message-board/src/controllers/newMessage.js
Normal file
0
nodejs-mini-message-board/src/controllers/newMessage.js
Normal file
22
nodejs-mini-message-board/src/db.js
Normal file
22
nodejs-mini-message-board/src/db.js
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
const sqlite3 = require("sqlite3").verbose();
|
||||||
|
const path = require("node:path");
|
||||||
|
const { stat } = require("node:fs");
|
||||||
|
const { mkdir } = require("node:fs/promises");
|
||||||
|
|
||||||
|
const dbDirPath = path.join(path.dirname(__dirname));
|
||||||
|
const dbPath = path.join(dbDirPath, "/message-board.db");
|
||||||
|
|
||||||
|
async function makeDirectory(path) {
|
||||||
|
const dirCreation = await mkdir(path);
|
||||||
|
return dirCreation;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure DB exists
|
||||||
|
stat(dbDirPath, (err, stats) => {
|
||||||
|
if (err !== null) {
|
||||||
|
makeDirectory(dbDirPath);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const db = new sqlite3.Database(dbPath);
|
||||||
|
|
||||||
|
module.exports = db;
|
22
nodejs-mini-message-board/src/db/query.js
Normal file
22
nodejs-mini-message-board/src/db/query.js
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
const db = require("../db");
|
||||||
|
|
||||||
|
async function getAllMessages() {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
db.all("SELECT * FROM messages ORDER BY date DESC;", async (err, rows) =>
|
||||||
|
resolve(rows),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function insertMessage(msg) {
|
||||||
|
db.run("INSERT INTO MESSAGES (message, username, date) VALUES (?, ?, ?)", [
|
||||||
|
msg.message,
|
||||||
|
msg.username,
|
||||||
|
msg.date,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
getAllMessages,
|
||||||
|
insertMessage,
|
||||||
|
};
|
26
nodejs-mini-message-board/src/db/seedDb.js
Normal file
26
nodejs-mini-message-board/src/db/seedDb.js
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
const db = require("../db");
|
||||||
|
|
||||||
|
const SQL = `
|
||||||
|
CREATE TABLE IF NOT EXISTS messages (
|
||||||
|
id INTEGER PRIMARY KEY ASC,
|
||||||
|
message TEXT,
|
||||||
|
username VARCHAR(25),
|
||||||
|
date TEXT
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO messages (message, username, date)
|
||||||
|
VALUES
|
||||||
|
('this is cool', 'smig.tech', '2024-12-24T01:12:340Z'),
|
||||||
|
('I like this app', 'smigz', '2024-12-25T00:32:43.540Z'),
|
||||||
|
('For real, it is nice', 'mikey', '2024-12-28T00:35:43.540Z')
|
||||||
|
`;
|
||||||
|
|
||||||
|
async function main(db) {
|
||||||
|
console.log("seeding db...");
|
||||||
|
db.serialize(() => {
|
||||||
|
db.exec(SQL);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
main(db);
|
0
nodejs-mini-message-board/src/populateDb.js
Normal file
0
nodejs-mini-message-board/src/populateDb.js
Normal file
|
@ -8,6 +8,7 @@
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
|
font-size: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-item {
|
.nav-item {
|
||||||
|
@ -25,7 +26,39 @@
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.msg-feed {
|
||||||
|
margin-top: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
.card {
|
.card {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
min-width: 300px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 10px 0;
|
||||||
|
min-width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item input {
|
||||||
|
padding: 10px 20px;
|
||||||
|
margin: 8px 0;
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
padding: 1rem;
|
||||||
|
margin: 0 1rem;
|
||||||
|
font-size: 1.3rem;
|
||||||
|
/*width: 100%;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
.errors {
|
||||||
|
color: red;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,45 +1,15 @@
|
||||||
const { Router } = require("express");
|
const { Router } = require("express");
|
||||||
|
const indexController = require("../controllers/indexController");
|
||||||
|
const db = require("../db");
|
||||||
|
|
||||||
const indexRouter = Router();
|
const indexRouter = Router();
|
||||||
|
|
||||||
links = [
|
indexRouter.get("/", indexController.indexGet);
|
||||||
{ href: "/", text: "Home" },
|
indexRouter.get("/new", indexController.newGet);
|
||||||
{ href: "/new", text: "New" },
|
indexRouter.post(
|
||||||
];
|
"/new",
|
||||||
|
indexController.validateContent,
|
||||||
const messages = [
|
indexController.newPost,
|
||||||
{
|
);
|
||||||
text: "Hi there!",
|
|
||||||
user: "Amando",
|
|
||||||
added: new Date(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: "Hello World!",
|
|
||||||
user: "Charles",
|
|
||||||
added: new Date(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: "This is a smig's app",
|
|
||||||
user: "Smig's",
|
|
||||||
added: new Date(),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
indexRouter.get("/", (req, res) => {
|
|
||||||
res.render("index", { links: links, msgs: messages });
|
|
||||||
});
|
|
||||||
|
|
||||||
indexRouter.get("/new", (req, res) => {
|
|
||||||
res.render("msgs");
|
|
||||||
});
|
|
||||||
|
|
||||||
indexRouter.post("/new", (req, res) => {
|
|
||||||
messages.unshift({
|
|
||||||
text: req.body.message,
|
|
||||||
user: req.body.username,
|
|
||||||
added: new Date(),
|
|
||||||
});
|
|
||||||
res.redirect("/");
|
|
||||||
});
|
|
||||||
|
|
||||||
module.exports = { indexRouter };
|
module.exports = { indexRouter };
|
||||||
|
|
|
@ -6,13 +6,12 @@
|
||||||
<body>
|
<body>
|
||||||
<!-- this should be some stuff that loads --!>
|
<!-- this should be some stuff that loads --!>
|
||||||
<%- include('navbar', {links: links}) %>
|
<%- include('navbar', {links: links}) %>
|
||||||
<div class="container">
|
<div class="container msg-feed">
|
||||||
|
|
||||||
<% msgs.forEach((msg) => { %>
|
<% msgs.forEach((msg) => { %>
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h3><%= msg.user %></h3>
|
<h3><%= msg.username %></h3>
|
||||||
<span><%= msg.added %></span>
|
<span><%= msg.date %></span>
|
||||||
<p><%= msg.text %></p>
|
<p><%= msg.message %></p>
|
||||||
</div>
|
</div>
|
||||||
<% }); %>
|
<% }); %>
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,28 @@
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Message the people</title>
|
||||||
|
<link rel="stylesheet" href="/styles.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<%- include('navbar', {links: links}) %>
|
||||||
|
<%- include('partials/errors.ejs') %>
|
||||||
<form method="POST" action="/new">
|
<form method="POST" action="/new">
|
||||||
<div class="form-item">
|
<div class="container">
|
||||||
|
<div class="form-item">
|
||||||
<label for="uername">Username</label>
|
<label for="uername">Username</label>
|
||||||
<input type="text" id="username" name="username">
|
<input type="text" id="username" name="username">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-item">
|
<div class="form-item">
|
||||||
<label for="message">Message</label>
|
<label for="message">Message</label>
|
||||||
<input type="text" id="message" name="message">
|
<input type="text" id="message" name="message">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-item">
|
<div class="form-item">
|
||||||
<button type="submit">Submit</button>
|
<button class="btn" type="submit">Submit</button>
|
||||||
</div>
|
<button class="btn" type="button" onCLick="window.location='/';">Return</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
<!-- vim: sts=2 sw=2 et ts=2 # -->
|
<!-- vim: sts=2 sw=2 et ts=2 # -->
|
||||||
|
|
9
nodejs-mini-message-board/src/views/partials/errors.ejs
Normal file
9
nodejs-mini-message-board/src/views/partials/errors.ejs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<% if (locals.errors) {%>
|
||||||
|
<div class="container errors">
|
||||||
|
<ul>
|
||||||
|
<% errors.forEach(function(error) { %>
|
||||||
|
<li><%= error.msg %></li>
|
||||||
|
<% }); %>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<% } %>
|
Loading…
Add table
Reference in a new issue