mirror of
https://github.com/Akif9748/akf-forum.git
synced 2024-11-22 20:10:40 +03:00
Added search
This commit is contained in:
parent
0358e9e5a2
commit
5b2399bec5
11 changed files with 183 additions and 26 deletions
26
README.md
26
README.md
|
@ -31,31 +31,17 @@ Akf-forum has got an API for AJAX (fetch), other clients etc. And, you can learn
|
||||||
<img src="https://user-images.githubusercontent.com/70021050/187901065-fd75ef85-56e3-42ce-8b34-cb8d799a6517.png"></img>
|
<img src="https://user-images.githubusercontent.com/70021050/187901065-fd75ef85-56e3-42ce-8b34-cb8d799a6517.png"></img>
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## Roadmap
|
## TO-DO list
|
||||||
### TO-DO:
|
|
||||||
| To do | Is done? | Priority |
|
| To do | Is done? | Priority |
|
||||||
| ----- | -------- | -------- |
|
| ----- | -------- | -------- |
|
||||||
| Profile Message | 🔴 | LOW |
|
| Search & message a | 🟡 | MEDIUM |
|
||||||
| Search | 🔴 | MEDIUM |
|
|
||||||
| Footer | 🟡 | LOW |
|
| Footer | 🟡 | LOW |
|
||||||
| Better Auth | 🔴 | MEDIUM |
|
|
||||||
| Local pfp store | 🔴 | MEDIUM |
|
| Local pfp store | 🔴 | MEDIUM |
|
||||||
| IPs of users will add SecretModel | 🔴 | MEDIUM |
|
| IPs of users will add SecretModel | 🔴 | MEDIUM |
|
||||||
|
| better theme patch UserModel | 🟡 | VERY LOW |
|
||||||
- message counts for API
|
| Category | ⚪ | MEDIUM |
|
||||||
- better theme patch UserModel
|
| Profile Message | 🔴 | LOW |
|
||||||
- ajax, delete update thread dom
|
| Better Auth | 🔴 | MEDIUM |
|
||||||
|
|
||||||
### API
|
|
||||||
| To do | Is done?
|
|
||||||
| ----- | --------
|
|
||||||
| RATELIMITS | 🟢
|
|
||||||
| Get a lots of message & thread & user | 🔴
|
|
||||||
| Create message & thread & user | 🟢
|
|
||||||
| Get message & thread & user | 🟢
|
|
||||||
| Delete message & thread & user | 🟢
|
|
||||||
| Undelete message & thread & user | 🟢
|
|
||||||
| Edit message & thread & user | 🟢
|
|
||||||
|
|
||||||
## Major Version History
|
## Major Version History
|
||||||
- V4: Caching
|
- V4: Caching
|
||||||
|
|
34
public/css/messages.css
Normal file
34
public/css/messages.css
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
.date {
|
||||||
|
color: var(--second);
|
||||||
|
}
|
||||||
|
|
||||||
|
.message {
|
||||||
|
max-width: 800px;
|
||||||
|
box-shadow: 0 0 5px 0 var(--box-shadow);
|
||||||
|
margin: 10px auto;
|
||||||
|
padding: 20px;
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message .left {
|
||||||
|
text-align: center;
|
||||||
|
border-right: 2px solid var(--borders);
|
||||||
|
}
|
||||||
|
|
||||||
|
.message .left img {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
border-radius: 50%;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message .left .username a {
|
||||||
|
color: var(--t-username);
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
width: 70%;
|
||||||
|
color: var(--reaction-hover);
|
||||||
|
}
|
3
public/css/search.css
Normal file
3
public/css/search.css
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
.search {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
28
routes/api/routes/search.js
Normal file
28
routes/api/routes/search.js
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
const { Router } = require("express")
|
||||||
|
const { MessageModel, ThreadModel, UserModel } = require("../../../models");
|
||||||
|
|
||||||
|
const app = Router();
|
||||||
|
|
||||||
|
app.get("/users", async (req, res) => {
|
||||||
|
if (!req.query.q) return res.error(400, "Missing query parameter 'q' in request body.");
|
||||||
|
const results = await UserModel.find({ name: { $regex: req.query.q, $options: "i" } }).limit(10);
|
||||||
|
res.complate(results);
|
||||||
|
});
|
||||||
|
app.get("/messages", async (req, res) => {
|
||||||
|
if (!Object.values(req.query).length) return res.error(400, "Missing query parameters in request body.");
|
||||||
|
const query = {};
|
||||||
|
if (req.query.q) query.content = { $regex: req.query.q, $options: "i" };
|
||||||
|
if (req.query.authorID) query.authorID = req.query.authorID;
|
||||||
|
const results = await MessageModel.find(query).limit(10);
|
||||||
|
res.complate(results);
|
||||||
|
});
|
||||||
|
app.get("/threads", async (req, res) => {
|
||||||
|
if (!Object.values(req.query).length) return res.error(400, "Missing query parameters in request body.");
|
||||||
|
const query = {};
|
||||||
|
if (req.query.q) query.title = { $regex: req.query.q, $options: "i" };
|
||||||
|
if (req.query.authorID) query.authorID = req.query.authorID;
|
||||||
|
const results = await ThreadModel.find(query).limit(10);
|
||||||
|
res.complate(results);
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = app;
|
31
routes/search.js
Normal file
31
routes/search.js
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
const { UserModel, ThreadModel, MessageModel } = require("../models")
|
||||||
|
const { Router } = require("express");
|
||||||
|
|
||||||
|
const app = Router();
|
||||||
|
|
||||||
|
app.get("/", (req, res) => res.reply("search"));
|
||||||
|
|
||||||
|
app.get("/users", async (req, res) => {
|
||||||
|
if (!req.query.q) return res.error(400, "Missing query parameter 'q' in request body.");
|
||||||
|
const users = await UserModel.find({ name: { $regex: req.query.q, $options: "i" } }).limit(10);
|
||||||
|
res.reply("users", { users, page: null });
|
||||||
|
});
|
||||||
|
app.get("/messages", async (req, res) => {
|
||||||
|
if (!Object.values(req.query).length) return res.error(400, "Missing query parameters in request body.");
|
||||||
|
const query = {};
|
||||||
|
if (req.query.q) query.content = { $regex: req.query.q, $options: "i" };
|
||||||
|
if (req.query.authorID) query.authorID = req.query.authorID;
|
||||||
|
const messages = await MessageModel.find(query).limit(10);
|
||||||
|
res.reply("messages",{messages});
|
||||||
|
});
|
||||||
|
app.get("/threads", async (req, res) => {
|
||||||
|
if (!Object.values(req.query).length) return res.error(400, "Missing query parameters in request body.");
|
||||||
|
const query = {};
|
||||||
|
if (req.query.q) query.title = { $regex: req.query.q, $options: "i" };
|
||||||
|
if (req.query.authorID) query.authorID = req.query.authorID;
|
||||||
|
const threads = await ThreadModel.find(query).limit(10);
|
||||||
|
res.reply("threads", { threads, page: null });
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = app;
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
<a id="logout" href="/login" class="btn-primary">Logout</a>
|
<a id="logout" href="/login" class="btn-primary">Logout</a>
|
||||||
<a onclick="invert()" class="btn-outline-primary"><%=(user.theme === "default" ? "black" : "default" ) + " mode" %></a>
|
<a onclick="invert()" class="btn-outline-primary"><%=(user.theme === "default" ? "black" : "default" ) + " mode" %></a>
|
||||||
<script>
|
<script>
|
||||||
async function invert() {
|
async function invert() {
|
||||||
await fetch('/api/users/<%= user.id %>', {
|
await fetch('/api/users/<%= user.id %>', {
|
||||||
method: 'PATCH',
|
method: 'PATCH',
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
location.reload()
|
location.reload()
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<% } else { %>
|
<% } else { %>
|
||||||
|
|
||||||
|
@ -45,15 +45,17 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="menu">
|
<div class="menu">
|
||||||
|
<a href="/threads/create/" class="menu-item">Create Thread</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>
|
||||||
<a href="/threads/create/" class="menu-item">Create Thread</a>
|
|
||||||
<script>
|
<script>
|
||||||
const menuItems = document.getElementsByClassName("menu-item");
|
const menuItems = document.getElementsByClassName("menu-item");
|
||||||
|
|
||||||
for (let i = 0; i < menuItems.length; i++)
|
for (let i = 0; i < menuItems.length; i++)
|
||||||
if (menuItems[i].getAttribute("href") == window.location.pathname)
|
if (window.location.pathname.includes(menuItems[i].getAttribute("href"))) {
|
||||||
menuItems[i].classList.add("active-menu");
|
menuItems[i].classList.add("active-menu");
|
||||||
|
break;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
</div>
|
</div>
|
33
views/messages.ejs
Normal file
33
views/messages.ejs
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<%- include("extra/meta", {title:"Message search!" }) %>
|
||||||
|
|
||||||
|
|
||||||
|
<body style="text-align: center;">
|
||||||
|
<%- include("extra/navbar") %>
|
||||||
|
<link rel="stylesheet" href="/css/messages.css" />
|
||||||
|
|
||||||
|
<div id="messages">
|
||||||
|
|
||||||
|
<% 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.authorID %>"><%=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>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<% }); %>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
35
views/search.ejs
Normal file
35
views/search.ejs
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<%- include("extra/meta", {title: "Search page!" }) %>
|
||||||
|
|
||||||
|
|
||||||
|
<body style="text-align: center;">
|
||||||
|
<%- include("extra/navbar") %>
|
||||||
|
<link rel="stylesheet" href="/css/search.css" />
|
||||||
|
|
||||||
|
<div id="search">
|
||||||
|
<form action="/search/users" method="GET">
|
||||||
|
<input type="text" name="q" placeholder="Search for users" />
|
||||||
|
<input type="submit" value="Search" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="search">
|
||||||
|
<form action="/search/messages" method="GET">
|
||||||
|
<input type="text" name="q" placeholder="Search for messages" />
|
||||||
|
<input type="text" name="authorID" placeholder="(Not Required) Author id" />
|
||||||
|
<input type="submit" value="Search" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="search">
|
||||||
|
<form action="/search/threads" method="GET">
|
||||||
|
<input type="text" name="q" placeholder="Search for threads" />
|
||||||
|
<input type="text" name="authorID" placeholder="(Not Required) Author id" />
|
||||||
|
<input type="submit" value="Search" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
|
@ -25,8 +25,6 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style="text-align:center;padding:8px">
|
<div style="text-align:center;padding:8px">
|
||||||
<!-- THREAD AUTHOR AND PROFILE PHOTO -->
|
|
||||||
|
|
||||||
<% if (user && !thread.deleted){ %>
|
<% if (user && !thread.deleted){ %>
|
||||||
|
|
||||||
<a onclick="delete_thread('<%= thread.id %>')" class="btn-outline-primary">DELETE</a>
|
<a onclick="delete_thread('<%= thread.id %>')" class="btn-outline-primary">DELETE</a>
|
||||||
|
|
|
@ -33,6 +33,8 @@
|
||||||
<% }); %>
|
<% }); %>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
<% if(typeof page === "number"){ %>
|
||||||
|
|
||||||
<div class="pagination">
|
<div class="pagination">
|
||||||
<div class="back">
|
<div class="back">
|
||||||
<% if (page > 0){ %>
|
<% if (page > 0){ %>
|
||||||
|
@ -53,4 +55,6 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
<% } %>
|
||||||
|
|
||||||
</body>
|
</body>
|
|
@ -24,6 +24,7 @@
|
||||||
<% }); %>
|
<% }); %>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
<% if(typeof page === "number"){ %>
|
||||||
<div class="pagination">
|
<div class="pagination">
|
||||||
<div class="back">
|
<div class="back">
|
||||||
<% if (page > 0){ %>
|
<% if (page > 0){ %>
|
||||||
|
@ -44,4 +45,6 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
<% } %>
|
||||||
|
|
||||||
</body>
|
</body>
|
Loading…
Reference in a new issue