mirror of
https://github.com/Akif9748/akf-forum.git
synced 2024-11-26 05:10:41 +03:00
new theme is fixed in everypage
This commit is contained in:
parent
9ad7c03162
commit
facaf105eb
13 changed files with 143 additions and 254 deletions
|
@ -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
|
- Profile photos will store in database
|
||||||
- regex for pfp for now and
|
- regex for pfp for now and
|
||||||
- admin perm for undelete, thread + message
|
- admin perm for undelete, thread + message
|
||||||
- page support for threads
|
- page support for threads, send, if multi page, send => other page
|
||||||
- message "<b>"
|
- message "<b>"
|
||||||
- author name of thread
|
- author name of thread
|
||||||
- page for threads - users
|
- page for threads - users
|
||||||
- edit & delete button for thread
|
- API, ?fast=
|
||||||
|
- fix error messages, ~~declared as id~~, other...
|
||||||
|
|
||||||
### Frontend
|
### Frontend
|
||||||
### User
|
### User
|
||||||
| To do | Is done? | Priority |
|
| To do | Is done? | Priority |
|
||||||
|
|
|
@ -14,7 +14,8 @@ const schema = new mongoose.Schema({
|
||||||
react: {
|
react: {
|
||||||
like: [Number],
|
like: [Number],
|
||||||
dislike: [Number]
|
dislike: [Number]
|
||||||
}
|
},
|
||||||
|
index: { type: Number, default: 0 }
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
const { Schema, model } = require("mongoose")
|
const mongoose = require("mongoose")
|
||||||
|
|
||||||
const schema = new Schema({
|
|
||||||
|
|
||||||
|
const schema = new mongoose.Schema({
|
||||||
username: { type: String, unique: true },
|
username: { type: String, unique: true },
|
||||||
password: String,
|
password: String,
|
||||||
id: { type:String, unique: true }
|
id: { type: String, unique: true }
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = model('secret', schema);
|
module.exports = mongoose.model('secret', schema);
|
|
@ -1,46 +1,4 @@
|
||||||
import request from "./request.js";
|
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("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll("\"", """).replaceAll("'", "'").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
|
* Message Sender
|
||||||
|
@ -52,10 +10,7 @@ document.getElementById("send")?.addEventListener("submit", async e => {
|
||||||
const data = new FormData(form);
|
const data = new FormData(form);
|
||||||
request("/api/messages", "POST", { threadID: data.get("threadID"), content: data.get("content") })
|
request("/api/messages", "POST", { threadID: data.get("threadID"), content: data.get("content") })
|
||||||
.then(res => {
|
.then(res => {
|
||||||
if (!res) return;
|
if (res) location.href = `/messages/${res.id}`;
|
||||||
form.reset();
|
|
||||||
res.reactCount = 0;
|
|
||||||
render_message(res);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -63,7 +18,7 @@ document.getElementById("send")?.addEventListener("submit", async e => {
|
||||||
* OTHER FUNCTIONS
|
* OTHER FUNCTIONS
|
||||||
*/
|
*/
|
||||||
|
|
||||||
async function delete_thread(id) {
|
window.delete_thread = async function (id) {
|
||||||
const response = await request("/api/threads/" + id + "/delete");
|
const response = await request("/api/threads/" + id + "/delete");
|
||||||
if (response.deleted) {
|
if (response.deleted) {
|
||||||
alert("Thread 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");
|
const response = await request("/api/threads/" + id + "/undelete");
|
||||||
if (!response.deleted) {
|
if (!response.deleted) {
|
||||||
alert("Thread undeleted");
|
alert("Thread undeleted");
|
||||||
location.reload();
|
location.reload();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
async function undelete_message(id) {
|
window.undelete_message = async function (id) {
|
||||||
const response = await request(`/api/messages/${id}/undelete`);
|
const response = await request(`/api/messages/${id}/undelete`);
|
||||||
if (!response.deleted)
|
if (response.deleted) return;
|
||||||
document.getElementById("message-delete-" + id).innerHTML = `<a onclick=\"delete_message('${id}');\">DELETE</a>`;
|
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`);
|
const response = await request(`/api/messages/${id}/delete`);
|
||||||
if (response.deleted) {
|
if (response.deleted) {
|
||||||
alert("Message deleted");
|
alert("Message deleted");
|
||||||
document.getElementById("message-delete-" + id).innerHTML = `
|
document.getElementById("dots-" + id).innerHTML = `
|
||||||
<h3 style=\"display:inline;\">This message has been deleted</h3>
|
<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
|
<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}`)
|
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;
|
|
|
@ -3,15 +3,7 @@ const { Router } = require("express")
|
||||||
const app = Router();
|
const app = Router();
|
||||||
|
|
||||||
app.get("/", async (req, res) => {
|
app.get("/", async (req, res) => {
|
||||||
if (!req.session.userid) return res.redirect('/login');
|
if (!req.user?.admin) return res.error(403, "You have not got permissions for view to this page.");
|
||||||
|
res.reply("admin")
|
||||||
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 })
|
|
||||||
});
|
});
|
||||||
|
module.exports = app;
|
||||||
|
|
||||||
|
|
||||||
module.exports = app;
|
|
|
@ -31,7 +31,7 @@ app.post("/", rateLimit({
|
||||||
|
|
||||||
if (!thread) return res.error(404, `We don't have any thread with id ${threadID}.`);
|
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 message.save();
|
||||||
await thread.push(message.id).save();
|
await thread.push(message.id).save();
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ app.get("/:id/messages/", async (req, res) => {
|
||||||
const query = { threadID: id };
|
const query = { threadID: id };
|
||||||
if (!req.user.admin) query.deleted = false;
|
if (!req.user.admin) query.deleted = false;
|
||||||
|
|
||||||
const options = { sort: { date: -1 } };
|
const options = { sort: { time: -1 } };
|
||||||
if (limit) options.limit = limit;
|
if (limit) options.limit = limit;
|
||||||
if (skip) options.skip = skip;
|
if (skip) options.skip = skip;
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ const { Router } = require("express");
|
||||||
const app = Router();
|
const app = Router();
|
||||||
const bcrypt = require("bcrypt");
|
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) => {
|
app.post("/", async (req, res) => {
|
||||||
req.session.userid = null;
|
req.session.userid = null;
|
||||||
|
@ -14,19 +14,19 @@ app.post("/", async (req, res) => {
|
||||||
const user = await SecretModel.findOne({ username });
|
const user = await SecretModel.findOne({ username });
|
||||||
if (user) {
|
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 });
|
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;
|
req.session.userid = user.id;
|
||||||
|
|
||||||
res.redirect( req.query.redirect || '/');
|
res.redirect(req.query.redirect || '/');
|
||||||
} else
|
} else
|
||||||
res.error( 403, 'Incorrect Username and/or Password!')
|
res.error(403, 'Incorrect Username and/or Password!')
|
||||||
|
|
||||||
|
|
||||||
} else
|
} else
|
||||||
res.error( 400, "You forgot entering some values")
|
res.error(400, "You forgot entering some values")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,9 @@ const app = Router();
|
||||||
app.get("/:id", async (req, res) => {
|
app.get("/:id", async (req, res) => {
|
||||||
const message = await MessageModel.get(req.params.id);
|
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.");
|
if (!message || (message.deleted && req.user && !req.user.admin)) return res.error( 404,
|
||||||
res.redirect("/threads/" + message.threadID+"?scroll="+req.params.id);
|
`We don't have any message with id ${req.params.id}.`);
|
||||||
|
res.redirect(`/threads/${message.threadID}?scroll=${req.params.id}`);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
const { Router } = require("express");
|
const { Router } = require("express");
|
||||||
const app = Router();
|
const app = Router();
|
||||||
|
|
||||||
const { ThreadModel,MessageModel } = require("../models")
|
const { ThreadModel, MessageModel } = require("../models")
|
||||||
|
|
||||||
|
|
||||||
app.get("/", async (req, res) => {
|
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("/create*", (req, res) => res.reply("create_thread"));
|
||||||
|
|
||||||
app.get("/:id", async (req, res) => {
|
app.get("/:id/", async (req, res) => {
|
||||||
|
|
||||||
const { id } = req.params;
|
const { user, params: { id } } = req
|
||||||
const page = req.query.page || 0;
|
|
||||||
const thread = await ThreadModel.get(id).skip(page * 10).limit(page * 10 + 10);
|
|
||||||
thread.views++;
|
|
||||||
|
|
||||||
if (thread && (req.user?.admin || !thread.deleted)) {
|
const page = Number(req.query.page || 0);
|
||||||
const messages = await Promise.all(thread.messages.map(async id => {
|
const thread = await ThreadModel.get(id)
|
||||||
const message = await MessageModel.get(id)
|
if (thread && (user?.admin || !thread.deleted)) {
|
||||||
message.content = message.content.replaceAll("&", "&")
|
thread.views++;
|
||||||
.replaceAll("<", "<").replaceAll(">", ">")
|
const query = { threadID: id };
|
||||||
.replaceAll("\"", """).replaceAll("'", "'")
|
if (!user || !user.admin) query.deleted = false;
|
||||||
.replaceAll("\n", "<br>");
|
|
||||||
return req.user?.admin || !message?.deleted ? message.toObject({ virtuals: true }) : null;
|
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("&", "&")
|
||||||
|
.replaceAll("<", "<").replaceAll(">", ">")
|
||||||
|
.replaceAll("\"", """).replaceAll("'", "'")
|
||||||
|
.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
|
} else
|
||||||
res.error(404, "We have not got this thread.");
|
res.error(404, "We have not got this thread.");
|
||||||
thread.save();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -11,17 +11,16 @@ app.get("/", async ({ user }, res) => {
|
||||||
|
|
||||||
app.get("/:id", async (req, res) => {
|
app.get("/:id", async (req, res) => {
|
||||||
const user = req.user
|
const user = req.user
|
||||||
const { id = null } = req.params;
|
const { id } = req.params;
|
||||||
const member = await UserModel.get(id);
|
const member = await UserModel.get(id);
|
||||||
|
|
||||||
|
|
||||||
if (member && (user?.admin || !member.deleted)) {
|
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 });
|
const thread = await ThreadModel.count({ "author.id": id });
|
||||||
res.reply("user", { member, counts: { message, thread } })
|
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}.`);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -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>
|
|
115
views/thread.ejs
115
views/thread.ejs
|
@ -12,65 +12,96 @@
|
||||||
<% if (user){ %>
|
<% if (user){ %>
|
||||||
<script type="module" src="/js/thread.js"></script>
|
<script type="module" src="/js/thread.js"></script>
|
||||||
<% }; %>
|
<% }; %>
|
||||||
|
|
||||||
<div style="text-align:center;padding:8px">
|
<div style="text-align:center;padding:8px">
|
||||||
<div class="title"><%= thread.title %></div>
|
<div class="title"><%= thread.title %></div>
|
||||||
<div class="date">
|
<div class="date">
|
||||||
<%= new Date(thread.time).toLocaleString() %> • Views: <%= thread.views %>
|
<%= new Date(thread.time).toLocaleString() %> • Views: <%= thread.views %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</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 %>">
|
<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="message" id="message-<%= message.id %>">
|
||||||
<div class="left">
|
<div class="left">
|
||||||
<img src="<%= message.author.avatar || '/images/guest.png' %>"/>
|
<img src="<%= message.author.avatar || '/images/guest.png' %>"/>
|
||||||
<div class="username"><a href="/users/<%=message.author.id %>"><%=message.author.name %></a></div>
|
<div class="username"><a href="/users/<%=message.author.id %>"><%=message.author.name %></a></div>
|
||||||
<div class="date">
|
<div class="date">
|
||||||
<%= new Date(message.time).toLocaleDateString() %>
|
<%= 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>
|
||||||
<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 %>">
|
<div class="dots-menu" id="dot-<%=message.id %>">
|
||||||
|
<% if (!message.deleted){ %>
|
||||||
<a onclick="delete_message('<%=message.id %>');">Delete</a>
|
<a onclick="delete_message('<%=message.id %>');">Delete</a>
|
||||||
<a onclick="edit_message('<%=message.id %>');">Edit</a>
|
<a onclick="edit_message('<%=message.id %>');">Edit</a>
|
||||||
</div>
|
|
||||||
<% }else if (user.admin){ %>
|
<% }else if (user.admin){ %>
|
||||||
<div class="dots-menu" id="dot-<%=message.id %>">
|
<a onclick="undelete_message('<%=message.id %>');">Undelete</a>
|
||||||
<a onclick="undelete_message('<%=message.id %>');">UNDELETE</a>
|
<% } %>
|
||||||
</div>
|
</div>
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|
||||||
<% } %>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="reactions">
|
<div class="reactions">
|
||||||
<div>
|
<div>
|
||||||
<i class='bx bx-like'></i> <%=message.react.like.length %>
|
<i onclick='react("<%= message.id %>","like");' class='bx bx-like'></i>
|
||||||
</div>
|
<div id="like-<%= message.id %>"><%=message.react.like.length %></div>
|
||||||
<div>
|
</div>
|
||||||
<i class='bx bx-dislike'></i> <%=message.react.dislike.length %>
|
<div>
|
||||||
</div>
|
<i onclick='react("<%= message.id %>","dislike");' class='bx bx-dislike'></i>
|
||||||
</div>
|
<div id="dislike-<%= message.id %>"><%=message.react.dislike.length %></div>
|
||||||
<% }; %>
|
</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="pagination">
|
||||||
<div class="back">
|
<div class="back">
|
||||||
<% if (page > 0){ %>
|
<% if (page > 0){ %>
|
||||||
|
@ -80,15 +111,15 @@
|
||||||
|
|
||||||
|
|
||||||
<div class="numbers">
|
<div class="numbers">
|
||||||
<% for(let i=0;i< Math.ceil(messages.length/10);i++){ %>
|
<% for(let i=0;i <= Math.ceil(messages.length/10) ;i++){ %>
|
||||||
<a class="number <%= i==page?'active':'' %>" href="<%= thread.getLink() %>?page=<%= i %>"><%= i %></a>
|
<a class="number <%= i==page?'active':'' %>" href="<%= thread.getLink() %>?page=<%= i %>"><%= i+1 %></a>
|
||||||
<% } %>
|
<% } %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="after">
|
<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>
|
<a href="<%= thread.getLink() %>?page=<%= page +1 %>" class='bx bxs-chevron-right'></a>
|
||||||
<% } %>
|
<% } %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in a new issue