mirror of
https://github.com/Akif9748/akf-forum.git
synced 2024-11-26 05:10:41 +03:00
Better rendering for messages
This commit is contained in:
parent
faeb832fdd
commit
e7dafd3561
8 changed files with 183 additions and 156 deletions
|
@ -32,6 +32,7 @@ And, you can learn about API in `util/APIDOCS.md`.
|
|||
| Admin | 🟢 | HIGH |
|
||||
| Message count | 🟢 | MEDIUM |
|
||||
| Delete user | 🟢 | HIGH |
|
||||
| Undelete | 🔴 | MEDIUM |
|
||||
| About me | 🔴 | LOW |
|
||||
| Edit user | 🔴 | HIGH |
|
||||
| IP ban | 🔴 | MEDIUM |
|
||||
|
@ -42,6 +43,7 @@ And, you can learn about API in `util/APIDOCS.md`.
|
|||
| Ratelimit | 🟢 | HIGH |
|
||||
| Send | 🟢 | HIGH |
|
||||
| Delete | 🟢 | HIGH |
|
||||
| Undelete | 🔴 | MEDIUM |
|
||||
| React | 🟢 | MEDIUM |
|
||||
| Edit | 🔴 | MEDIUM |
|
||||
|
||||
|
@ -51,12 +53,14 @@ And, you can learn about API in `util/APIDOCS.md`.
|
|||
| Ratelimit | 🟢 | HIGH |
|
||||
| Create | 🟢 | HIGH |
|
||||
| Delete | 🟢 | HIGH |
|
||||
| Undelete | 🔴 | MEDIUM |
|
||||
| Edit | 🔴 | MEDIUM |
|
||||
|
||||
### API
|
||||
| To do | Is done? | Priority |
|
||||
| ----- | -------- | -------- |
|
||||
| Other clients for forum via API | 🟢 | LOW |
|
||||
| Get message**s** | 🔴 | MEDIUM |
|
||||
| Send message | 🟢 | MEDIUM |
|
||||
| Create thread | 🟢 | MEDIUM |
|
||||
| Get info about thread | 🟢 | MEDIUM |
|
||||
|
|
|
@ -99,7 +99,8 @@ hr {
|
|||
border-color: var(--col-8);
|
||||
}
|
||||
|
||||
button, input {
|
||||
button,
|
||||
input {
|
||||
font-family: monospace;
|
||||
background-color: var(--col-bg);
|
||||
border: 2px solid var(--col-8);
|
||||
|
@ -186,11 +187,11 @@ button:hover {
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
*****************************
|
||||
IMAGES
|
||||
*****************************
|
||||
*/
|
||||
div.message {
|
||||
border: 2px solid var(--col-8);
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
@ -257,4 +258,4 @@ img.logo {
|
|||
border: 2px solid var(--col-8);
|
||||
height: 20px;
|
||||
color: var(--col-15);
|
||||
}
|
||||
}
|
|
@ -1,34 +1,71 @@
|
|||
import request from "./request.js";
|
||||
document.addEventListener("click", async e => {
|
||||
|
||||
if (e.target.id === "delete_thread") {
|
||||
const response = await request("/api/threads/"+e.target.value+"/delete");
|
||||
if (response.result.deleted) {
|
||||
alert("Thread deleted");
|
||||
window.location.href = "/threads";
|
||||
const messages = document.getElementById("messages");
|
||||
|
||||
function renderMessage(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} alt=${message.author.name}>
|
||||
<a href=${"/users/" + message.author.id}> ${message.author.name}</a>:
|
||||
</h2>
|
||||
|
||||
<h2>${message.content}</h2><br>
|
||||
<div id="message-delete-${message.id}">
|
||||
${!message.deleted ?
|
||||
`<form style="display:inline;">
|
||||
<button id="delete_message" value="${message.id}" type="submit">DELETE</button>
|
||||
</form>` :
|
||||
"<h3 style=\"display:inline;\">This message has been deleted</h3>"}
|
||||
</div>
|
||||
<div style="float: right;">
|
||||
<h3 id="count${message.id}" style="display:inline;">${message.reactCount}</h3>
|
||||
<button style="display:inline;" id="like" value="${message.id}">+🔼</button>
|
||||
<button style="display:inline;" id="dislike" value="${message.id}" >-🔽</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
messages.appendChild(messageElement);
|
||||
messages.innerHTML += "<br>";
|
||||
};
|
||||
|
||||
/**
|
||||
* Main Renderer
|
||||
*/
|
||||
(async () => {
|
||||
|
||||
const { result } = await fetch(`/api/threads/${messages.getAttribute("value")}/messages/`).then(res => res.json());
|
||||
|
||||
if (result?.error) {
|
||||
|
||||
document.getElementById("messages").innerHTML
|
||||
+= '<div class="message"><h1>THIS THREAD HAS NOT GOT ANY MESSAGE</h1></div>';
|
||||
|
||||
|
||||
} else
|
||||
for (const message of result) {
|
||||
|
||||
const arr = Object.values(message.react || {})
|
||||
|
||||
message.reactCount = arr.filter(Boolean).length - arr.filter(x => !x).length;
|
||||
|
||||
renderMessage(message);
|
||||
}
|
||||
|
||||
} else if (e.target.id === "delete_message") {
|
||||
const response = await request(`/api/messages/${e.target.value}/delete`);
|
||||
if (response.result.deleted) {
|
||||
alert("Message deleted");
|
||||
location.reload();
|
||||
}
|
||||
} /*else if (e.target.id === "edit_thread") {
|
||||
window.location.href = "/threads/<%= thread.id %>/edit";
|
||||
} */
|
||||
|
||||
})();
|
||||
|
||||
|
||||
|
||||
if (!e.target.id.includes("like")) return;
|
||||
const res = await request("/api/messages/" + e.target.value + "/react/" + e.target.id)
|
||||
|
||||
document.getElementById("count" + e.target.value).innerHTML = res.result;
|
||||
|
||||
});
|
||||
|
||||
|
||||
document.getElementById("send").addEventListener("submit", async e => {
|
||||
/**
|
||||
* Message Sender
|
||||
*/
|
||||
document.getElementById("send").addEventListener("submit", async e => {
|
||||
|
||||
e.preventDefault();
|
||||
const form = e.target;
|
||||
|
@ -37,28 +74,38 @@ document.getElementById("send").addEventListener("submit", async e => {
|
|||
.then(res => {
|
||||
if (!res) return;
|
||||
form.reset();
|
||||
const message = res.result;
|
||||
document.getElementById("messages").innerHTML += `<br>
|
||||
<div id="message-${message.id}" style="border: 2px solid #444444; padding: 10px;">
|
||||
|
||||
<h3 style="float:right;">${new Date(message.time).toLocaleString()}</h3>
|
||||
|
||||
<h2>
|
||||
<img class="circle" src=${message.author.avatar} alt=${message.author.name}>
|
||||
<a href="/users/${message.author.id}"> ${message.author.name}</a>:
|
||||
</h2>
|
||||
|
||||
<h2>${message.content}</h2><br>
|
||||
|
||||
<form style="display:inline;" action="/message/${message.id}/delete/" method="post">
|
||||
</a><button type="submit">DELETE</button>
|
||||
</form>
|
||||
<div style="float: right;">
|
||||
<h3 id="count${message.id}" style="display:inline;">0</h3>
|
||||
<button style="display:inline;" id="like" value="${message.id}">+🔼</button>
|
||||
<button style="display:inline;" id="dislike" value="${message.id}" >-🔽</button>
|
||||
</div>
|
||||
|
||||
</div>`;
|
||||
res.result.reactCount = 0;
|
||||
renderMessage(res.result);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Button Listener
|
||||
*/
|
||||
document.addEventListener("click", async e => {
|
||||
// e.preventDefault();
|
||||
if (e.target.id === "delete_thread") {
|
||||
const response = await request("/api/threads/" + e.target.value + "/delete");
|
||||
if (response.result.deleted) {
|
||||
alert("Thread deleted");
|
||||
window.location.href = "/threads";
|
||||
}
|
||||
|
||||
} else if (e.target.id === "delete_message") {
|
||||
e.preventDefault();
|
||||
const response = await request(`/api/messages/${e.target.value}/delete`);
|
||||
if (response.result.deleted) {
|
||||
alert("Message deleted");
|
||||
document.getElementById("message-delete-" + e.target.value).innerHTML="<h3 style=\"display:inline;\">This message has been deleted</h3>";
|
||||
}
|
||||
} /*else if (e.target.id === "edit_thread") {
|
||||
window.location.href = "/threads/<%= thread.id }/edit";
|
||||
} */
|
||||
|
||||
if (!e.target.id.includes("like")) return;
|
||||
const res = await request("/api/messages/" + e.target.value + "/react/" + e.target.id)
|
||||
|
||||
document.getElementById("count" + e.target.value).innerHTML = res.result;
|
||||
|
||||
});
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
const { UserModel, MessageModel, ThreadModel } = require("../../../models");
|
||||
const { MessageModel, ThreadModel } = require("../../../models");
|
||||
const rateLimit = require('express-rate-limit')
|
||||
|
||||
const { Router } = require("express")
|
||||
|
||||
const app = Router();
|
||||
|
||||
|
||||
app.get("/:id", async (req, res) => {
|
||||
|
||||
|
||||
|
|
|
@ -5,18 +5,36 @@ const app = Router();
|
|||
|
||||
app.get("/:id", async (req, res) => {
|
||||
|
||||
const { id = null } = req.params;
|
||||
if (!id) return res.error(400, "Missing id in query")
|
||||
const { id } = req.params;
|
||||
|
||||
const thread = await ThreadModel.get(id);
|
||||
if (thread && (req.user?.admin || !thread.deleted))
|
||||
res.complate( thread);
|
||||
res.complate(thread);
|
||||
else
|
||||
return res.error(404, "We have not got any thread declared as this id.");
|
||||
return res.error(404, "We don't have any thread with this id.");
|
||||
|
||||
|
||||
});
|
||||
|
||||
app.get("/:id/messages/", async (req, res) => {
|
||||
|
||||
|
||||
const { id = null } = req.params;
|
||||
const limit = Number(req.query.limit);
|
||||
|
||||
const query = { threadID: id };
|
||||
if (!req.user.admin) query.deleted = false;
|
||||
|
||||
const options = { sort: { date: -1 } };
|
||||
if (limit) options.limit = limit;
|
||||
|
||||
const messages = await MessageModel.find(query, null, options)
|
||||
|
||||
if (!messages.length) return res.error(404, "We don't have any messages in this thread.");
|
||||
|
||||
res.complate(messages);
|
||||
|
||||
})
|
||||
|
||||
app.post("/", async (req, res) => {
|
||||
|
||||
|
@ -36,10 +54,10 @@ app.post("/", async (req, res) => {
|
|||
|
||||
app.post("/:id/delete", async (req, res) => {
|
||||
const thread = await ThreadModel.get(req.params.id);
|
||||
if (!thread || thread.deleted) return res.error( 404, "We have not got any thread declared as this id.");
|
||||
if (!thread || thread.deleted) return res.error(404, "We don't have any thread with this id.");
|
||||
const user = req.user;
|
||||
if (user.id != thread.authorID && !user.admin)
|
||||
return res.error( 403, "You have not got permission for this.");
|
||||
return res.error(403, "You have not got permission for this.");
|
||||
|
||||
thread.deleted = true;
|
||||
await thread.save();
|
||||
|
|
|
@ -22,6 +22,7 @@ You need this headers for send request to API:
|
|||
- POST `/api/users/:id/admin` for give admin permissions for a user.
|
||||
|
||||
- GET `/api/threads/:id` for fetch thread.
|
||||
- GET `/api/threads/:id/messages/:limit` for fetch messages in thread.
|
||||
- POST `/api/threads` for create thread.
|
||||
- POST `/api/threads/:id/delete` for delete thread.
|
||||
|
||||
|
|
118
views/thread.ejs
118
views/thread.ejs
|
@ -3,102 +3,56 @@
|
|||
|
||||
<%- include("extra/header", { title: thread.title }) %>
|
||||
|
||||
<body>
|
||||
<body>
|
||||
|
||||
<%- include("extra/navbar", {user}) %>
|
||||
<%- include("extra/navbar", {user}) %>
|
||||
|
||||
|
||||
<h1 style="font-size: 35px;">
|
||||
<%= thread.title %>
|
||||
</h1>
|
||||
|
||||
<h2 style="display:inline;">By <a href=<%="/users/" + thread.author.id %>> <%= thread.author.name %></a>
|
||||
<img class="circle" src=<%= thread.author.avatar %> alt=<%= thread.author.name %>>
|
||||
</h2>
|
||||
|
||||
<% if (user && !thread.deleted){ %>
|
||||
<h1 style="font-size: 35px;">
|
||||
<%= thread.title %>
|
||||
</h1>
|
||||
|
||||
<button id="delete_thread" value="<%= thread.id %>" style="display:inline;" type="submit">DELETE</button>
|
||||
<button id="edit_thread" style="display:inline;" type="submit">EDIT</button>
|
||||
<% } else { %>
|
||||
<h3 style="display:inline;">This thread has been deleted</h3>
|
||||
<% }; %>
|
||||
<h2 style="display:inline;">By <a href=<%="/users/" + thread.author.id %>> <%= thread.author.name %></a>
|
||||
<img class="circle" src=<%=thread.author.avatar %> alt=<%= thread.author.name %>>
|
||||
</h2>
|
||||
|
||||
<hr>
|
||||
<div id="messages">
|
||||
<% messages.forEach(message=>{ %>
|
||||
<% if (message){ %>
|
||||
<% if (user && !thread.deleted){ %>
|
||||
|
||||
<div id="message-<%= message.id %>" style="border: 2px solid #444444; padding: 10px;">
|
||||
|
||||
<h3 style="float:right;">
|
||||
<%=new Date(message.time).toLocaleString() %>
|
||||
</h3>
|
||||
|
||||
<h2>
|
||||
<img class="circle" src=<%=message.author.avatar %> alt=<%= message.author.name %>>
|
||||
<a href=<%="/users/" + message.author.id %>> <%= message.author.name %></a>:
|
||||
</h2>
|
||||
|
||||
<h2>
|
||||
<%= message.content %>
|
||||
</h2>
|
||||
|
||||
<br>
|
||||
|
||||
<% if (user){ %>
|
||||
<% if (!message.deleted){ %>
|
||||
<form style="display:inline;">
|
||||
<button id="delete_message" value="<%= message.id %>" type="submit">DELETE</button>
|
||||
</form>
|
||||
<% } else { %>
|
||||
<h3 style="display:inline;">This message has been deleted</h3>
|
||||
<button id="delete_thread" value="<%= thread.id %>" style="display:inline;" type="submit">DELETE</button>
|
||||
<button id="edit_thread" style="display:inline;" type="submit">EDIT</button>
|
||||
<% } else if (thread.deleted) { %>
|
||||
<h3 style="display:inline;">This thread has been deleted</h3>
|
||||
<% }; %>
|
||||
|
||||
<div style="float: right;">
|
||||
<h3 id="count<%= message.id %>" style="display:inline;"><%= message.reactCount %></h3>
|
||||
<button style="display:inline;" id="like" value="<%= message.id %>">+🔼</button>
|
||||
<button style="display:inline;" id="dislike" value="<%= message.id %>" >-🔽</button>
|
||||
</div>
|
||||
|
||||
|
||||
<% } %>
|
||||
<hr>
|
||||
|
||||
|
||||
</div>
|
||||
<div id="messages" value="<%= thread.id %>">
|
||||
<% if (!user){ %>
|
||||
<h1>Guests cant view messages!</h1>
|
||||
<% }%>
|
||||
</div>
|
||||
|
||||
<% } else { %>
|
||||
<div id="deleted-message" style="border: 2px solid #444444; padding: 10px;">
|
||||
<h1>DELETED MESSAGE</h1>
|
||||
</div>
|
||||
<% } %>
|
||||
<br>
|
||||
|
||||
<% }); %>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<hr>
|
||||
|
||||
|
||||
<form id= "send">
|
||||
<textarea rows="4" cols="133" name="content"></textarea>
|
||||
<input name="threadID" type="hidden" value="<%= thread.id %>"></input>
|
||||
<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>
|
||||
<% }%>
|
||||
<br>
|
||||
<% if (user){ %>
|
||||
<button type="submit">Send!</button>
|
||||
<%} else {%>
|
||||
<button disabled>Login for send</button>
|
||||
<% }%>
|
||||
|
||||
</form>
|
||||
<% if (user){ %>
|
||||
<script type="module" src="/js/thread.js"></script>
|
||||
<% }%>
|
||||
</form>
|
||||
<% if (user){ %>
|
||||
<script type="module" src="/js/thread.js"></script>
|
||||
<% }%>
|
||||
|
||||
<%- include("extra/footer") %>
|
||||
</body>
|
||||
<%- include("extra/footer") %>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</html>
|
|
@ -59,26 +59,27 @@
|
|||
if (e.target.id == "admin") {
|
||||
|
||||
const response = await request("/api/users/<%= member.id %>/admin");
|
||||
|
||||
if (response.result.admin)
|
||||
return alert("Making admin of " + response.result.name + " is success!");
|
||||
|
||||
}
|
||||
|
||||
if (response.result.admin)
|
||||
return alert("Making admin of "+response.result.name+" is success!");
|
||||
}
|
||||
|
||||
const response = await request("/api/users/<%= member.id %>/delete");
|
||||
|
||||
if (response.result.deleted)
|
||||
|
||||
if (response.result.deleted)
|
||||
alert("User Deleted");
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
</script>
|
||||
<% }; %>
|
||||
<% if (member.deleted) {%>
|
||||
<h1>This user has been deleted!</h1>
|
||||
<% }; %>
|
||||
|
||||
<%- include("extra/footer") %>
|
||||
<% if (member.deleted) {%>
|
||||
<h1>This user has been deleted!</h1>
|
||||
<% }; %>
|
||||
|
||||
<%- include("extra/footer") %>
|
||||
</body>
|
||||
|
||||
</html>
|
Loading…
Reference in a new issue