new theme is fixed in everypage

This commit is contained in:
Akif9748 2022-08-29 16:16:44 +03:00
parent 9ad7c03162
commit facaf105eb
13 changed files with 143 additions and 254 deletions

View File

@ -33,11 +33,13 @@ Akf-forum has got an API for AJAX, other clients etc. And, you can learn about A
- Profile photos will store in database
- regex for pfp for now and
- admin perm for undelete, thread + message
- page support for threads
- page support for threads, send, if multi page, send => other page
- message "<b>"
- author name of thread
- page for threads - users
- edit & delete button for thread
- API, ?fast=
- fix error messages, ~~declared as id~~, other...
### Frontend
### User
| To do | Is done? | Priority |

View File

@ -14,7 +14,8 @@ const schema = new mongoose.Schema({
react: {
like: [Number],
dislike: [Number]
}
},
index: { type: Number, default: 0 }
})

View File

@ -1,12 +1,9 @@
const { Schema, model } = require("mongoose")
const schema = new Schema({
const mongoose = require("mongoose")
const schema = new mongoose.Schema({
username: { type: String, unique: true },
password: String,
id: { type:String, unique: true }
id: { type: String, unique: true }
});
module.exports = model('secret', schema);
module.exports = mongoose.model('secret', schema);

View File

@ -1,46 +1,4 @@
import request from "./request.js";
const message_div = document.getElementById("messages");
function render_message(message) {
const messageElement = document.createElement("div");
messageElement.classList.add("message");
messageElement.setAttribute("id", "message-" + message.id);
messageElement.innerHTML = `
<h3 style="float:right;">${new Date(message.time).toLocaleString()}</h3>
<h2>
<img class="circle" src="${message.author.avatar}">
<a href="/users/${message.author.id}"> ${message.author.name}</a>:
</h2>
<p>${message.content.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll("\"", "&quot;").replaceAll("'", "&#39;").replaceAll("\n", "<br>")}</p><br>
<div id="message-delete-${message.id}">
${/* if */!message.deleted ?
`
<a onclick="delete_message('${message.id}');">DELETE</a>
<a onclick="edit_message('${message.id}');">EDIT</a>
` /* else */ :
`<h3 style=\"display:inline;\">This message has been deleted</h3>
<a onclick="undelete_message('${message.id}');">UNDELETE</a>
`
}
</div>
<div style="float: right;">
<h3 id="count${message.id}" style="display:inline;">${message.reactCount}</h3>
<a onclick="react('${message.id}', 'like');">+🔼</a>
<a onclick="react('${message.id}', 'dislike');">-🔽</a>
</div>
`;
message_div.appendChild(messageElement);
message_div.innerHTML += "<br>";
};
window.scrollTo(0, document.body.scrollHeight);
/**
* Message Sender
@ -52,10 +10,7 @@ document.getElementById("send")?.addEventListener("submit", async e => {
const data = new FormData(form);
request("/api/messages", "POST", { threadID: data.get("threadID"), content: data.get("content") })
.then(res => {
if (!res) return;
form.reset();
res.reactCount = 0;
render_message(res);
if (res) location.href = `/messages/${res.id}`;
});
});
@ -63,7 +18,7 @@ document.getElementById("send")?.addEventListener("submit", async e => {
* OTHER FUNCTIONS
*/
async function delete_thread(id) {
window.delete_thread = async function (id) {
const response = await request("/api/threads/" + id + "/delete");
if (response.deleted) {
alert("Thread deleted");
@ -71,37 +26,39 @@ async function delete_thread(id) {
}
}
async function undelete_thread(id) {
window.undelete_thread = async function (id) {
const response = await request("/api/threads/" + id + "/undelete");
if (!response.deleted) {
alert("Thread undeleted");
location.reload();
}
}
async function undelete_message(id) {
window.undelete_message = async function (id) {
const response = await request(`/api/messages/${id}/undelete`);
if (!response.deleted)
document.getElementById("message-delete-" + id).innerHTML = `<a onclick=\"delete_message('${id}');\">DELETE</a>`;
if (response.deleted) return;
document.getElementById("deleted-" + id).remove();
document.getElementById("dot-" + id).innerHTML = `
<a onclick="delete_message('${id}');">DELETE</a>
<a onclick="edit_message('${id}');">EDIT</a>
`
}
async function delete_message(id) {
window.delete_message = async function (id) {
const response = await request(`/api/messages/${id}/delete`);
if (response.deleted) {
alert("Message deleted");
document.getElementById("message-delete-" + id).innerHTML = `
<h3 style=\"display:inline;\">This message has been deleted</h3>
document.getElementById("dots-" + id).innerHTML = `
<i class='bx bx-trash bx-sm' id="deleted-${id}" style="color: RED;"></i>
`+ document.getElementById("dots-" + id).innerHTML;
document.getElementById("dot-" + id).innerHTML = `
<a onclick="undelete_message('${id}');">UNDELETE</a>`;// ADMIN PERM FIX
}
}
async function react(id, type) {
window.react = async function (id, type) {
const res = await request(`/api/messages/${id}/react/${type}`)
document.getElementById(`count${id}`).innerHTML = res.reactCount;
document.getElementById(`like-${id}`).innerHTML = res.react.like.length;
document.getElementById(`dislike-${id}`).innerHTML = res.react.dislike.length;
}
window.delete_message = delete_message;
window.undelete_message = undelete_message;
window.react = react;
window.delete_thread = delete_thread;
window.undelete_thread = undelete_thread;

View File

@ -3,15 +3,7 @@ const { Router } = require("express")
const app = Router();
app.get("/", async (req, res) => {
if (!req.session.userid) return res.redirect('/login');
const user = req.user;
if (!user?.admin) return res.error( 403, "You have not got permissions for view to this page.");
res.reply("admin", { user2: false })
if (!req.user?.admin) return res.error(403, "You have not got permissions for view to this page.");
res.reply("admin")
});
module.exports = app;
module.exports = app;

View File

@ -31,7 +31,7 @@ app.post("/", rateLimit({
if (!thread) return res.error(404, `We don't have any thread with id ${threadID}.`);
const message = await new MessageModel({ content, author: req.user, threadID: thread.id }).takeId();
const message = await new MessageModel({ content, author: req.user, threadID: thread.id, index: thread.messages.length }).takeId();
await message.save();
await thread.push(message.id).save();

View File

@ -26,7 +26,7 @@ app.get("/:id/messages/", async (req, res) => {
const query = { threadID: id };
if (!req.user.admin) query.deleted = false;
const options = { sort: { date: -1 } };
const options = { sort: { time: -1 } };
if (limit) options.limit = limit;
if (skip) options.skip = skip;

View File

@ -3,7 +3,7 @@ const { Router } = require("express");
const app = Router();
const bcrypt = require("bcrypt");
app.get("/", (req, res) => res.reply("login",{redirect: req.query.redirect,user:null}));
app.get("/", (req, res) => res.reply("login", { redirect: req.query.redirect, user: null }));
app.post("/", async (req, res) => {
req.session.userid = null;
@ -14,19 +14,19 @@ app.post("/", async (req, res) => {
const user = await SecretModel.findOne({ username });
if (user) {
if (!await bcrypt.compare(password, user.password)) return res.error( 403, 'Incorrect Password!')
if (!await bcrypt.compare(password, user.password)) return res.error(403, 'Incorrect Password!')
const member = await UserModel.findOne({ name: username });
if (!member || member.deleted) return res.error( 403, 'Incorrect Username and/or Password!')
if (!member || member.deleted) return res.error(403, 'Incorrect Username and/or Password!')
req.session.userid = user.id;
res.redirect( req.query.redirect || '/');
res.redirect(req.query.redirect || '/');
} else
res.error( 403, 'Incorrect Username and/or Password!')
res.error(403, 'Incorrect Username and/or Password!')
} else
res.error( 400, "You forgot entering some values")
res.error(400, "You forgot entering some values")

View File

@ -7,8 +7,9 @@ const app = Router();
app.get("/:id", async (req, res) => {
const message = await MessageModel.get(req.params.id);
if (!message || (message.deleted && req.user && !req.user.admin)) return res.error( 404, "We have not got any message declared as this id.");
res.redirect("/threads/" + message.threadID+"?scroll="+req.params.id);
if (!message || (message.deleted && req.user && !req.user.admin)) return res.error( 404,
`We don't have any message with id ${req.params.id}.`);
res.redirect(`/threads/${message.threadID}?scroll=${req.params.id}`);
});

View File

@ -1,7 +1,7 @@
const { Router } = require("express");
const app = Router();
const { ThreadModel,MessageModel } = require("../models")
const { ThreadModel, MessageModel } = require("../models")
app.get("/", async (req, res) => {
@ -14,27 +14,33 @@ app.get("/", async (req, res) => {
app.get("/create*", (req, res) => res.reply("create_thread"));
app.get("/:id", async (req, res) => {
app.get("/:id/", async (req, res) => {
const { id } = req.params;
const page = req.query.page || 0;
const thread = await ThreadModel.get(id).skip(page * 10).limit(page * 10 + 10);
thread.views++;
const { user, params: { id } } = req
if (thread && (req.user?.admin || !thread.deleted)) {
const messages = await Promise.all(thread.messages.map(async id => {
const message = await MessageModel.get(id)
message.content = message.content.replaceAll("&", "&amp;")
.replaceAll("<", "&lt;").replaceAll(">", "&gt;")
.replaceAll("\"", "&quot;").replaceAll("'", "&#39;")
.replaceAll("\n", "<br>");
return req.user?.admin || !message?.deleted ? message.toObject({ virtuals: true }) : null;
}));
const page = Number(req.query.page || 0);
const thread = await ThreadModel.get(id)
if (thread && (user?.admin || !thread.deleted)) {
thread.views++;
const query = { threadID: id };
if (!user || !user.admin) query.deleted = false;
const messages = await MessageModel.find(query).sort({ time: 1 }).skip(page * 10).limit(page * 10 + 10)
.then(messages => messages.map(message => {
message.content = message.content.replaceAll("&", "&amp;")
.replaceAll("<", "&lt;").replaceAll(">", "&gt;")
.replaceAll("\"", "&quot;").replaceAll("'", "&#39;")
.replaceAll("\n", "<br>");
return message.toObject({ virtuals: true });
}))
res.reply("thread", { page, thread, messages, scroll: req.query.scroll || thread.messages[0].id });
thread.save();
res.reply("thread", { page,thread, messages, scroll: req.query.scroll || thread.messages[0]});
} else
res.error(404, "We have not got this thread.");
thread.save();
});

View File

@ -11,17 +11,16 @@ app.get("/", async ({ user }, res) => {
app.get("/:id", async (req, res) => {
const user = req.user
const { id = null } = req.params;
const { id } = req.params;
const member = await UserModel.get(id);
if (member && (user?.admin || !member.deleted)) {
const message = await MessageModel.count({ "author.id": id });// this place was having problem. fixed
const message = await MessageModel.count({ "author.id": id });
const thread = await ThreadModel.count({ "author.id": id });
res.reply("user", { member, counts: { message, thread } })
}
else res.error(404, "We have not got this user.");
else res.error(404, `We don't have any user with id ${id}.`);
});

View File

@ -1,97 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<%- include("extra/meta", {title: "Thread list!" }) %>
<body style="text-align: center;">
<%- include("extra/navbar") %>
<link rel="stylesheet" href="/css/thread.css" />
<% if (user){ %>
<script type="module" src="/js/thread.js"></script>
<% }%>
<h1 style="font-size: 35px;color: #4d18e6;" ><%= thread.title %></h1>
<h3 >View count: <%= thread.views %></h1>
<h2 style="display:inline;">By <a href="<%='/users/' + thread.author.id %>"> <%= thread.author.name %></a>
<img class="circle" src="<%=thread.author.avatar %>">
</h2>
<% if (user && !thread.deleted){ %>
<a onclick="delete_thread('<%= thread.id %>' )" value=style="display:inline;" >DELETE</a>
<a onclick="edit_thread('<%= thread.id %>')" style="display:inline;" >EDIT</a>
<% } else if (thread.deleted) { %>
<h3 style="display:inline;">This thread has been deleted</h3>
<a onclick="undelete_thread('<%= thread.id %>')" style="display:inline;" >UNDELETE</a>
<% }; %>
<hr>
<div id="messages" value="<%= thread.id %>">
<% messages.filter(Boolean).forEach(message=>{ %>
<div class="message" id="message-<%= message.id %>">
<h3 style="float:right;"><%= new Date(message.time).toLocaleString() %> </h3>
<h2>
<img class="circle" src="<%= message.author.avatar %>">
<a href="/users/<%=message.author.id %>"><%=message.author.name %></a>:
</h2>
<p><%= message.content%></p><br>
<div id="message-delete-<%=message.id %>">
<% if (!message.deleted){ %>
<a onclick="delete_message('<%=message.id %>');">DELETE</a>
<a onclick="edit_message('<%=message.id %>');">EDIT</a>
<% }else{ %>
<h3 style="display:inline;">This message has been deleted</h3>
<a onclick="undelete_message('<%=message.id %>');">UNDELETE</a>
<% } %>
</div>
<div style="float: right;">
<h3 id="count<%=message.id %>" style="display:inline;"><%=message.reactCount %></h3>
<a onclick="react('<%=message.id %>', 'like');">+🔼</a>
<a onclick="react('<%=message.id %>', 'dislike');">-🔽</a>
</div>
</div>
<% }); %>
</div>
<hr>
<form id="send">
<textarea rows="4" cols="133" name="content"></textarea>
<input name="threadID" type="hidden" value="<%= thread.id %>"></input>
<br>
<% if (user){ %>
<button type="submit">Send!</button>
<%} else {%>
<button disabled>Login for send</button>
<% }%>
</form>
<script>
document.getElementById("message-<%= scroll %>").scrollIntoView();
</script>
<!-- BURAYA Bİ İLERİ BİR GERİ SAYFA BUTONU GELMEZ Mİ BE-->
</body>
</html>

View File

@ -12,65 +12,96 @@
<% if (user){ %>
<script type="module" src="/js/thread.js"></script>
<% }; %>
<div style="text-align:center;padding:8px">
<div class="title"><%= thread.title %></div>
<div class="date">
<%= new Date(thread.time).toLocaleString() %> • Views: <%= thread.views %>
</div>
</div>
<div style="text-align:center;padding:8px">
<!-- THREAD AUTHOR AND PROFILE PHOTO -->
<% if (user && !thread.deleted){ %>
<a onclick="delete_thread('<%= thread.id %>' )" class="btn-outline-primary" >DELETE</a>
<a onclick="edit_thread('<%= thread.id %>')" class="btn-outline-primary" >EDIT</a>
<% } else if (thread.deleted) { %>
<h3 style="display:inline;">This thread has been deleted</h3>
<a onclick="undelete_thread('<%= thread.id %>')" class="btn-primary" >UNDELETE</a>
<% }; %>
</div>
<div id="messages" value="<%= thread.id %>">
<% messages.filter(Boolean).forEach(message=>{ %>
<% messages.filter(Boolean).forEach(message=>{ %>
<div class="message" id="message-<%= message.id %>">
<div class="left">
<img src="<%= message.author.avatar || '/images/guest.png' %>"/>
<div class="username"><a href="/users/<%=message.author.id %>"><%=message.author.name %></a></div>
<div class="date">
<%= new Date(message.time).toLocaleDateString() %>
<div class="message" id="message-<%= message.id %>">
<div class="left">
<img src="<%= message.author.avatar || '/images/guest.png' %>"/>
<div class="username"><a href="/users/<%=message.author.id %>"><%=message.author.name %></a></div>
<div class="date">
<%= new Date(message.time).toLocaleDateString() %>
</div>
<div class="date">
<%= new Date(message.time).toLocaleTimeString() %>
</div>
</div>
<div class="content"><%- message.content %></div>
<% if(user){ %>
<% if(user.id === message.author.id || user.admin){ %>
<div class="dots" id="dots-<%=message.id %>" onclick="dots('<%=message.id %>')">
<% if (message.deleted){ %>
<i class='bx bx-trash bx-sm' id="deleted-<%=message.id %>" style="color: RED;"></i>
<% } %>
<i class='bx bx-dots-horizontal-rounded' ></i>
</div>
<div class="date">
<%= new Date(message.time).toLocaleTimeString() %>
</div>
</div>
<div class="content"><%- message.content %></div>
<% if(user){ %>
<% if(user.id === message.author.id || user.admin){ %>
<div class="dots" onclick="dots('<%=message.id %>')">
<i class='bx bx-dots-horizontal-rounded' ></i>
</div>
<% if (!message.deleted){ %>
<div class="dots-menu" id="dot-<%=message.id %>">
<% if (!message.deleted){ %>
<a onclick="delete_message('<%=message.id %>');">Delete</a>
<a onclick="edit_message('<%=message.id %>');">Edit</a>
</div>
<% }else if (user.admin){ %>
<div class="dots-menu" id="dot-<%=message.id %>">
<a onclick="undelete_message('<%=message.id %>');">UNDELETE</a>
</div>
<% } %>
<% } %>
<a onclick="undelete_message('<%=message.id %>');">Undelete</a>
<% } %>
</div>
<% } %>
<div class="reactions">
<div>
<i class='bx bx-like'></i> <%=message.react.like.length %>
</div>
<div>
<i class='bx bx-dislike'></i> <%=message.react.dislike.length %>
</div>
</div>
<% }; %>
<div class="reactions">
<div>
<i onclick='react("<%= message.id %>","like");' class='bx bx-like'></i>
<div id="like-<%= message.id %>"><%=message.react.like.length %></div>
</div>
<div>
<i onclick='react("<%= message.id %>","dislike");' class='bx bx-dislike'></i>
<div id="dislike-<%= message.id %>"><%=message.react.dislike.length %></div>
</div>
</div>
<% }; %>
</div>
</div>
<% }); %>
</div>
<div class="message">
<form id="send">
<textarea rows="4" cols="100" name="content"></textarea>
<input name="threadID" type="hidden" value="<%= thread.id %>"></input>
<% if (user){ %>
<button class="btn-primary">Send!</button>
<%} else {%>
<a class="btn-outline-primary" href="/login?redirect=<%= thread.getLink() %>">Login for send</a>
<% }%>
</form>
</div>
<div class="pagination">
<div class="back">
<% if (page > 0){ %>
@ -80,15 +111,15 @@
<div class="numbers">
<% for(let i=0;i< Math.ceil(messages.length/10);i++){ %>
<a class="number <%= i==page?'active':'' %>" href="<%= thread.getLink() %>?page=<%= i %>"><%= i %></a>
<% for(let i=0;i <= Math.ceil(messages.length/10) ;i++){ %>
<a class="number <%= i==page?'active':'' %>" href="<%= thread.getLink() %>?page=<%= i %>"><%= i+1 %></a>
<% } %>
</div>
<div class="after">
<% if (Math.ceil(messages.length/10)-1 > page){ %>
<% if (Math.ceil(messages.length/10) > page){ %>
<a href="<%= thread.getLink() %>?page=<%= page +1 %>" class='bx bxs-chevron-right'></a>
<% } %>
<% } %>
</div>
</div>