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 |
|
| Admin | 🟢 | HIGH |
|
||||||
| Message count | 🟢 | MEDIUM |
|
| Message count | 🟢 | MEDIUM |
|
||||||
| Delete user | 🟢 | HIGH |
|
| Delete user | 🟢 | HIGH |
|
||||||
|
| Undelete | 🔴 | MEDIUM |
|
||||||
| About me | 🔴 | LOW |
|
| About me | 🔴 | LOW |
|
||||||
| Edit user | 🔴 | HIGH |
|
| Edit user | 🔴 | HIGH |
|
||||||
| IP ban | 🔴 | MEDIUM |
|
| IP ban | 🔴 | MEDIUM |
|
||||||
|
@ -42,6 +43,7 @@ And, you can learn about API in `util/APIDOCS.md`.
|
||||||
| Ratelimit | 🟢 | HIGH |
|
| Ratelimit | 🟢 | HIGH |
|
||||||
| Send | 🟢 | HIGH |
|
| Send | 🟢 | HIGH |
|
||||||
| Delete | 🟢 | HIGH |
|
| Delete | 🟢 | HIGH |
|
||||||
|
| Undelete | 🔴 | MEDIUM |
|
||||||
| React | 🟢 | MEDIUM |
|
| React | 🟢 | MEDIUM |
|
||||||
| Edit | 🔴 | MEDIUM |
|
| Edit | 🔴 | MEDIUM |
|
||||||
|
|
||||||
|
@ -51,12 +53,14 @@ And, you can learn about API in `util/APIDOCS.md`.
|
||||||
| Ratelimit | 🟢 | HIGH |
|
| Ratelimit | 🟢 | HIGH |
|
||||||
| Create | 🟢 | HIGH |
|
| Create | 🟢 | HIGH |
|
||||||
| Delete | 🟢 | HIGH |
|
| Delete | 🟢 | HIGH |
|
||||||
|
| Undelete | 🔴 | MEDIUM |
|
||||||
| Edit | 🔴 | MEDIUM |
|
| Edit | 🔴 | MEDIUM |
|
||||||
|
|
||||||
### API
|
### API
|
||||||
| To do | Is done? | Priority |
|
| To do | Is done? | Priority |
|
||||||
| ----- | -------- | -------- |
|
| ----- | -------- | -------- |
|
||||||
| Other clients for forum via API | 🟢 | LOW |
|
| Other clients for forum via API | 🟢 | LOW |
|
||||||
|
| Get message**s** | 🔴 | MEDIUM |
|
||||||
| Send message | 🟢 | MEDIUM |
|
| Send message | 🟢 | MEDIUM |
|
||||||
| Create thread | 🟢 | MEDIUM |
|
| Create thread | 🟢 | MEDIUM |
|
||||||
| Get info about thread | 🟢 | MEDIUM |
|
| Get info about thread | 🟢 | MEDIUM |
|
||||||
|
|
|
@ -99,7 +99,8 @@ hr {
|
||||||
border-color: var(--col-8);
|
border-color: var(--col-8);
|
||||||
}
|
}
|
||||||
|
|
||||||
button, input {
|
button,
|
||||||
|
input {
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
background-color: var(--col-bg);
|
background-color: var(--col-bg);
|
||||||
border: 2px solid var(--col-8);
|
border: 2px solid var(--col-8);
|
||||||
|
@ -186,11 +187,11 @@ button:hover {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
div.message {
|
||||||
*****************************
|
border: 2px solid var(--col-8);
|
||||||
IMAGES
|
padding: 10px;
|
||||||
*****************************
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -257,4 +258,4 @@ img.logo {
|
||||||
border: 2px solid var(--col-8);
|
border: 2px solid var(--col-8);
|
||||||
height: 20px;
|
height: 20px;
|
||||||
color: var(--col-15);
|
color: var(--col-15);
|
||||||
}
|
}
|
|
@ -1,34 +1,71 @@
|
||||||
import request from "./request.js";
|
import request from "./request.js";
|
||||||
document.addEventListener("click", async e => {
|
|
||||||
|
|
||||||
if (e.target.id === "delete_thread") {
|
const messages = document.getElementById("messages");
|
||||||
const response = await request("/api/threads/"+e.target.value+"/delete");
|
|
||||||
if (response.result.deleted) {
|
function renderMessage(message) {
|
||||||
alert("Thread deleted");
|
const messageElement = document.createElement("div");
|
||||||
window.location.href = "/threads";
|
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)
|
* Message Sender
|
||||||
|
*/
|
||||||
document.getElementById("count" + e.target.value).innerHTML = res.result;
|
document.getElementById("send").addEventListener("submit", async e => {
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
document.getElementById("send").addEventListener("submit", async e => {
|
|
||||||
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const form = e.target;
|
const form = e.target;
|
||||||
|
@ -37,28 +74,38 @@ document.getElementById("send").addEventListener("submit", async e => {
|
||||||
.then(res => {
|
.then(res => {
|
||||||
if (!res) return;
|
if (!res) return;
|
||||||
form.reset();
|
form.reset();
|
||||||
const message = res.result;
|
res.result.reactCount = 0;
|
||||||
document.getElementById("messages").innerHTML += `<br>
|
renderMessage(res.result);
|
||||||
<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>`;
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 rateLimit = require('express-rate-limit')
|
||||||
|
|
||||||
const { Router } = require("express")
|
const { Router } = require("express")
|
||||||
|
|
||||||
const app = Router();
|
const app = Router();
|
||||||
|
|
||||||
|
|
||||||
app.get("/:id", async (req, res) => {
|
app.get("/:id", async (req, res) => {
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -5,18 +5,36 @@ const app = Router();
|
||||||
|
|
||||||
app.get("/:id", async (req, res) => {
|
app.get("/:id", async (req, res) => {
|
||||||
|
|
||||||
const { id = null } = req.params;
|
const { id } = req.params;
|
||||||
if (!id) return res.error(400, "Missing id in query")
|
|
||||||
|
|
||||||
const thread = await ThreadModel.get(id);
|
const thread = await ThreadModel.get(id);
|
||||||
if (thread && (req.user?.admin || !thread.deleted))
|
if (thread && (req.user?.admin || !thread.deleted))
|
||||||
res.complate( thread);
|
res.complate(thread);
|
||||||
else
|
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) => {
|
app.post("/", async (req, res) => {
|
||||||
|
|
||||||
|
@ -36,10 +54,10 @@ app.post("/", async (req, res) => {
|
||||||
|
|
||||||
app.post("/:id/delete", async (req, res) => {
|
app.post("/:id/delete", async (req, res) => {
|
||||||
const thread = await ThreadModel.get(req.params.id);
|
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;
|
const user = req.user;
|
||||||
if (user.id != thread.authorID && !user.admin)
|
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;
|
thread.deleted = true;
|
||||||
await thread.save();
|
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.
|
- POST `/api/users/:id/admin` for give admin permissions for a user.
|
||||||
|
|
||||||
- GET `/api/threads/:id` for fetch thread.
|
- 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` for create thread.
|
||||||
- POST `/api/threads/:id/delete` for delete 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 }) %>
|
<%- include("extra/header", { title: thread.title }) %>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<%- include("extra/navbar", {user}) %>
|
<%- include("extra/navbar", {user}) %>
|
||||||
|
|
||||||
|
|
||||||
<h1 style="font-size: 35px;">
|
<h1 style="font-size: 35px;">
|
||||||
<%= thread.title %>
|
<%= thread.title %>
|
||||||
</h1>
|
</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){ %>
|
|
||||||
|
|
||||||
<button id="delete_thread" value="<%= thread.id %>" style="display:inline;" type="submit">DELETE</button>
|
<h2 style="display:inline;">By <a href=<%="/users/" + thread.author.id %>> <%= thread.author.name %></a>
|
||||||
<button id="edit_thread" style="display:inline;" type="submit">EDIT</button>
|
<img class="circle" src=<%=thread.author.avatar %> alt=<%= thread.author.name %>>
|
||||||
<% } else { %>
|
</h2>
|
||||||
<h3 style="display:inline;">This thread has been deleted</h3>
|
|
||||||
<% }; %>
|
|
||||||
|
|
||||||
<hr>
|
<% if (user && !thread.deleted){ %>
|
||||||
<div id="messages">
|
|
||||||
<% messages.forEach(message=>{ %>
|
|
||||||
<% if (message){ %>
|
|
||||||
|
|
||||||
<div id="message-<%= message.id %>" style="border: 2px solid #444444; padding: 10px;">
|
<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>
|
||||||
<h3 style="float:right;">
|
<% } else if (thread.deleted) { %>
|
||||||
<%=new Date(message.time).toLocaleString() %>
|
<h3 style="display:inline;">This thread has been deleted</h3>
|
||||||
</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>
|
|
||||||
<% }; %>
|
<% }; %>
|
||||||
|
|
||||||
<div style="float: right;">
|
<hr>
|
||||||
<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>
|
|
||||||
|
|
||||||
|
|
||||||
<% } %>
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
<div id="messages" value="<%= thread.id %>">
|
||||||
|
<% if (!user){ %>
|
||||||
|
<h1>Guests cant view messages!</h1>
|
||||||
|
<% }%>
|
||||||
|
</div>
|
||||||
|
|
||||||
<% } else { %>
|
<hr>
|
||||||
<div id="deleted-message" style="border: 2px solid #444444; padding: 10px;">
|
|
||||||
<h1>DELETED MESSAGE</h1>
|
|
||||||
</div>
|
|
||||||
<% } %>
|
|
||||||
<br>
|
|
||||||
|
|
||||||
<% }); %>
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
|
|
||||||
<form id= "send">
|
<form id="send">
|
||||||
<textarea rows="4" cols="133" name="content"></textarea>
|
<textarea rows="4" cols="133" name="content"></textarea>
|
||||||
<input name="threadID" type="hidden" value="<%= thread.id %>"></input>
|
<input name="threadID" type="hidden" value="<%= thread.id %>"></input>
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
<% if (user){ %>
|
<% if (user){ %>
|
||||||
<button type="submit">Send!</button>
|
<button type="submit">Send!</button>
|
||||||
<%} else {%>
|
<%} else {%>
|
||||||
<button disabled>Login for send</button>
|
<button disabled>Login for send</button>
|
||||||
<% }%>
|
<% }%>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
<% if (user){ %>
|
<% if (user){ %>
|
||||||
<script type="module" src="/js/thread.js"></script>
|
<script type="module" src="/js/thread.js"></script>
|
||||||
<% }%>
|
<% }%>
|
||||||
|
|
||||||
<%- include("extra/footer") %>
|
<%- include("extra/footer") %>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
|
@ -59,26 +59,27 @@
|
||||||
if (e.target.id == "admin") {
|
if (e.target.id == "admin") {
|
||||||
|
|
||||||
const response = await request("/api/users/<%= member.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");
|
const response = await request("/api/users/<%= member.id %>/delete");
|
||||||
|
|
||||||
if (response.result.deleted)
|
if (response.result.deleted)
|
||||||
alert("User Deleted");
|
alert("User Deleted");
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<% }; %>
|
<% }; %>
|
||||||
<% if (member.deleted) {%>
|
<% if (member.deleted) {%>
|
||||||
<h1>This user has been deleted!</h1>
|
<h1>This user has been deleted!</h1>
|
||||||
<% }; %>
|
<% }; %>
|
||||||
|
|
||||||
<%- include("extra/footer") %>
|
<%- include("extra/footer") %>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
Loading…
Reference in a new issue