Added categories to front end

This commit is contained in:
Akif9748 2022-09-09 20:47:28 +03:00
parent 0ed4a34c8c
commit 035b2b7184
12 changed files with 144 additions and 15 deletions

View file

@ -22,8 +22,7 @@ app.use(
session({ secret: 'secret', resave: true, saveUninitialized: true }), session({ secret: 'secret', resave: true, saveUninitialized: true }),
express.static("public"), express.json(), ipBlock(app.ips), express.static("public"), express.json(), ipBlock(app.ips),
async (req, res, next) => { async (req, res, next) => {
if (req.session.userID) req.user = req.session.userID ? await UserModel.findOneAndUpdate({ id: req.session.userID }, { lastSeen: Date.now() }) : null;
req.user = await UserModel.findOneAndUpdate({ id: req.session.userID }, { lastSeen: Date.now() });
res.reply = (page, options = {}, status = 200) => res.status(status) res.reply = (page, options = {}, status = 200) => res.status(status)
.render(page, { user: req.user, theme: req.user?.theme || def_theme, forum_name, desp, ...options }); .render(page, { user: req.user, theme: req.user?.theme || def_theme, forum_name, desp, ...options });

View file

@ -11,6 +11,11 @@ schema.methods.takeId = async function () {
this.id = String(await model.count() || 0); this.id = String(await model.count() || 0);
return this; return this;
} }
schema.methods.getLink = function (id = this.id) {
return "/categories/" + this.id;
}
const model = mongoose.model('category', schema); const model = mongoose.model('category', schema);
module.exports = model; module.exports = model;

View file

@ -40,8 +40,8 @@ app.post("/", async (req, res) => {
if (!name) return res.error(400, "You have to give a name for the category."); if (!name) return res.error(400, "You have to give a name for the category.");
if (await CategoryModel.exists({ name })) return res.error(400, "This category is already opened."); if (await CategoryModel.exists({ name })) return res.error(400, "This category is already opened.");
const category = await new CategoryModel({ name, desp, authorID: req.user.id }).takeId();
res.complate(await CategoryModel.create({ name, desp, authorID: req.user.id }).then(c => c.takeId())); res.complate(await category.save());
}); });

View file

@ -39,7 +39,7 @@ app.get("/:id/messages/", async (req, res) => {
app.post("/", async (req, res) => { app.post("/", async (req, res) => {
const { title, content } = req.body; const { title, content } = req.body;
return console.log(req.body)
if (!content || !title) return res.error(400, "Missing content/title in request body."); if (!content || !title) return res.error(400, "Missing content/title in request body.");
const { user } = req; const { user } = req;

25
routes/categories.js Normal file
View file

@ -0,0 +1,25 @@
const { CategoryModel,ThreadModel } = require("../models");
const { Router } = require("express");
const app = Router();
app.get("/", async (req, res) => {
const categories = await CategoryModel.find({});
res.reply("categories", { categories });
});
app.get("/create",(req,res)=>res.reply("create_category"));
app.get("/:id", async (req, res) => {
const category = await CategoryModel.findOne({ id: req.params.id });
if (!category) return res.error(404, "Category not found.");
const page = Number(req.query.page) || 0;
const query = { categoryID: category.id };
if (!req.user?.admin) query.deleted= false;
let threads = await ThreadModel.find(query).limit(10).skip(page * 10);
threads = await Promise.all(threads.map(thread => thread.get_author()));
res.reply("threads", { threads, page, title: `Threads in ${category.name}`, desp: category.desp, pages: Math.ceil(await ThreadModel.count(query) / 10) });
});
module.exports = app;

View file

@ -42,8 +42,7 @@ app.get("/threads", async (req, res) => {
if (req.query.authorID) query.authorID = req.query.authorID; if (req.query.authorID) query.authorID = req.query.authorID;
const threads = await ThreadModel.find(query, null, req.so) const threads = await ThreadModel.find(query, null, req.so)
res.reply("threads", { res.reply("threads", {
threads, threads, page: req.page, title: "Threads with query " + req.query.q,
page: null, page: req.page,
pages: Math.ceil(await ThreadModel.count(query) / 10) pages: Math.ceil(await ThreadModel.count(query) / 10)
}); });
}); });

View file

@ -1,7 +1,7 @@
const { Router } = require("express"); const { Router } = require("express");
const app = Router(); const app = Router();
const { clearContent } = require("../lib"); const { clearContent } = require("../lib");
const { ThreadModel, MessageModel } = require("../models") const { ThreadModel, MessageModel, CategoryModel } = require("../models")
app.get("/", async (req, res) => { app.get("/", async (req, res) => {
const page = Number(req.query.page) || 0; const page = Number(req.query.page) || 0;
@ -9,11 +9,11 @@ app.get("/", async (req, res) => {
let threads = await ThreadModel.find(query).limit(10).skip(page * 10); let threads = await ThreadModel.find(query).limit(10).skip(page * 10);
threads = await Promise.all(threads.map(thread => thread.get_author())); threads = await Promise.all(threads.map(thread => thread.get_author()));
return res.reply("threads", { threads, page, pages: Math.ceil(await ThreadModel.count(query) / 10) }); return res.reply("threads", { threads, page, title: "Threads", desp: threads.length + " thread listed", pages: Math.ceil(await ThreadModel.count(query) / 10) });
}); });
app.get("/create/", (req, res) => res.reply("create_thread")); app.get("/create/", async (req, res) => res.reply("create_thread", { categories: await CategoryModel.find() }));
app.get("/:id/", async (req, res) => { app.get("/:id/", async (req, res) => {

58
views/categories.ejs Normal file
View file

@ -0,0 +1,58 @@
<!DOCTYPE html>
<html lang="en">
<%- include("extra/meta", {title: "Thread list!" }) %>
<body>
<link href='https://unpkg.com/boxicons@2.1.2/css/boxicons.min.css' rel='stylesheet'>
<link rel="stylesheet" href="/css/threads.css" />
<link rel="stylesheet" href="/css/pages.css" />
<%- include("extra/navbar") %>
<div class="threads">
<%if(user?.admin) {%>
<a href="/categories/create" class="btn-primary">Create Category</a>
<% }; %>
<% categories.forEach(category=>{ %>
<a href="<%= category.getLink() %>" >
<div class="threads-box">
<div class="thread-box-title">
<%= category.name %>
</div>
<div class="box-username"> <%if(user?.admin) {%>
<a class="btn-danger" onclick="fetch('/api/categories/<%= category.id %>/',{method:'DELETE'})"><i class="bx bx-trash bx-sm"></i></a>
<% }; %><%= category.desp %>
</div>
</div>
</a>
<br>
<% }); %>
</div>
<% if(typeof page === "number"){ %>
<div class="pagination">
<div class="back">
<% if (page > 0){ %>
<a href="/threads?page=<%= page-1 %>" class='bx bxs-chevron-left'></a>
<% } %>
</div>
<div class="numbers">
<% for(let i=0; i < pages; i++){ %>
<a class="number <%= i==page?'active':'' %>" href="/threads?page=<%= i %>"><%= i+1 %></a>
<% } %>
</div>
<div class="after">
<% if (pages-1 > page) { %>
<a href="/threads?page=<%= page +1 %>" class='bx bxs-chevron-right'></a>
<% } %>
</div>
</div>
<% } %>
</body>

38
views/create_category.ejs Normal file
View file

@ -0,0 +1,38 @@
<!DOCTYPE html>
<html lang="en">
<%- include("extra/meta", {title: "Create Category!" }) %>
<body>
<link rel="stylesheet" href="/css/create_thread.css" />
<%- include("extra/navbar") %>
<form>
<h2 class="title" style="align-self: baseline;">Name:</h2>
<input name="name" class="input"></input>
<h2 class="title" style="align-self: baseline;">Description:</h2>
<textarea rows="4" cols="50" name="desp" class="input"></textarea>
<button class="btn-primary" style="width:100%" type="submit">Create Category!</button>
</form>
<script type="module">
import request from "../../js/request.js";
document.addEventListener("submit", async e => {
e.preventDefault();
const data = new FormData(e.target);
const response = await request("/api/categories/", "POST", {
name: data.get("name"),
desp: data.get("desp")
});
if (response)
window.location.href = "/categories/" + response.id;
});
</script>
</body>

View file

@ -12,11 +12,13 @@
<form> <form>
<h2 class="title" style="align-self: baseline;">Title:</h2> <h2 class="title" style="align-self: baseline;">Title:</h2>
<input name="title" class="input"></input> <input name="title" class="input"></input>
<h2 class="title" style="align-self: baseline;">Content:</h2> <h2 class="title" style="align-self: baseline;">Content:</h2>
<textarea rows="4" cols="50" name="content" class="input"></textarea> <textarea rows="4" cols="50" name="content" class="input"></textarea>
<select name="category">
<% for (const category of categories) { %>
<option name="<%= category.id %>" value="<%= category.name %>"><%= category.name %></option>
<% } %>
</select>
<button class="btn-primary" style="width:100%" type="submit">Create Thread!</button> <button class="btn-primary" style="width:100%" type="submit">Create Thread!</button>
</form> </form>
@ -32,7 +34,8 @@
const response = await request("/api/threads/", "POST", { const response = await request("/api/threads/", "POST", {
title: data.get("title"), title: data.get("title"),
content: data.get("content") content: data.get("content"),
categord: data.get("category")
}); });

View file

@ -43,6 +43,7 @@
</div> </div>
<div class="menu"> <div class="menu">
<a href="/threads/create/" class="menu-item">Create Thread</a> <a href="/threads/create/" class="menu-item">Create Thread</a>
<a href="/categories" class="menu-item">Categories</a>
<a href="/threads" class="menu-item">Threads</a> <a href="/threads" class="menu-item">Threads</a>
<a href="/users" class="menu-item">Users</a> <a href="/users" class="menu-item">Users</a>
<a href="/search" class="menu-item">Search</a> <a href="/search" class="menu-item">Search</a>

View file

@ -9,7 +9,8 @@
<link rel="stylesheet" href="/css/pages.css" /> <link rel="stylesheet" href="/css/pages.css" />
<%- include("extra/navbar") %> <%- include("extra/navbar") %>
<h1><%= title || "Threads" %></h1>
<h2><%= desp %></h2>
<div class="threads"> <div class="threads">
<% threads.forEach(thread=>{ %> <% threads.forEach(thread=>{ %>