Tags.
Search by tags. Return tags used by posts. Signed-off-by: Armored Dragon <publicmail@armoreddragon.com>pull/1/head
parent
2997e4315f
commit
e0b530c606
|
@ -131,9 +131,19 @@ async function getPost({ requester_id, post_id, visibility = "PUBLISHED" } = {},
|
|||
// Get a single post
|
||||
if (post_id) {
|
||||
let post;
|
||||
post = await prisma.post.findUnique({ where: { id: post_id }, include: { owner: true } });
|
||||
post = await prisma.post.findUnique({ where: { id: post_id }, include: { owner: true, tags: true } });
|
||||
if (!post) return _r(false, "Post does not exist");
|
||||
post = _stripPrivatePost(post);
|
||||
|
||||
// Tags
|
||||
let post_tags = [];
|
||||
post.raw_tags = [];
|
||||
post.tags.forEach((tag) => {
|
||||
post_tags.push(tag.name);
|
||||
post.raw_tags.push();
|
||||
});
|
||||
post.tags = post_tags;
|
||||
|
||||
// Render post
|
||||
return { success: true, data: await _renderPost(post) };
|
||||
}
|
||||
|
@ -170,7 +180,7 @@ async function getPost({ requester_id, post_id, visibility = "PUBLISHED" } = {},
|
|||
};
|
||||
// Build the "where_object" object
|
||||
if (search) {
|
||||
if (search_tags) where_object["AND"][0]["OR"].push({ tags: { hasSome: [search?.toLowerCase()] } });
|
||||
if (search_tags) where_object["AND"][0]["OR"].push({ tags: { some: { name: search?.toLowerCase() } } });
|
||||
if (search_title) where_object["AND"][0]["OR"].push({ title: { contains: search, mode: "insensitive" } });
|
||||
if (search_content) where_object["AND"][0]["OR"].push({ content: { contains: search, mode: "insensitive" } });
|
||||
}
|
||||
|
@ -179,7 +189,7 @@ async function getPost({ requester_id, post_id, visibility = "PUBLISHED" } = {},
|
|||
where: where_object,
|
||||
take: limit,
|
||||
skip: Math.max(page, 0) * limit,
|
||||
include: { owner: true },
|
||||
include: { owner: true, tags: true },
|
||||
orderBy: [{ publish_date: "desc" }, { created_date: "desc" }],
|
||||
});
|
||||
|
||||
|
@ -187,6 +197,10 @@ async function getPost({ requester_id, post_id, visibility = "PUBLISHED" } = {},
|
|||
post = _stripPrivatePost(post);
|
||||
post = await _renderPost(post);
|
||||
post_list.push(post);
|
||||
|
||||
let post_tags = [];
|
||||
post.tags.forEach((tag) => post_tags.push(tag.name));
|
||||
post.tags = post_tags;
|
||||
}
|
||||
|
||||
// Calculate pagination
|
||||
|
@ -226,6 +240,20 @@ async function editPost({ requester_id, post_id, post_content }) {
|
|||
publish_date = new Date(year, month - 1, day, hour, minute);
|
||||
}
|
||||
|
||||
// Handle tags ----
|
||||
let database_tag_list = [];
|
||||
const existing_tags = post.tags?.map((tag) => ({ name: tag })) || [];
|
||||
|
||||
// Add new tags
|
||||
for (let tag_index = 0; post_content.tags.length > tag_index; tag_index++) {
|
||||
let tag = post_content.tags[tag_index];
|
||||
|
||||
// Check to see if tag exists, create if necessary,
|
||||
let database_tag = await prisma.tag.upsert({ where: { name: tag }, update: {}, create: { name: tag } });
|
||||
|
||||
database_tag_list.push(database_tag);
|
||||
}
|
||||
|
||||
// Rebuild the post to save
|
||||
let post_formatted = {
|
||||
title: post_content.title,
|
||||
|
@ -233,7 +261,7 @@ async function editPost({ requester_id, post_id, post_content }) {
|
|||
content: post_content.content,
|
||||
visibility: post_content.visibility || "PRIVATE",
|
||||
publish_date: publish_date || post_content.publish_date,
|
||||
tags: post_content.tags,
|
||||
tags: { disconnect: [...existing_tags], connect: [...database_tag_list] },
|
||||
media: [...post.raw_media, ...post_content.media],
|
||||
};
|
||||
|
||||
|
@ -345,6 +373,29 @@ async function getMedia({ parent_id, file_name }) {
|
|||
// Unreferenced images and media will be deleted
|
||||
async function deleteMedia({ parent_id, file_name }) {}
|
||||
|
||||
async function getTags({ order = "count" } = {}) {
|
||||
if (order == "count") {
|
||||
return await prisma.tag.findMany({
|
||||
include: { _count: { select: { posts: true } } },
|
||||
where: {
|
||||
posts: {
|
||||
some: {},
|
||||
},
|
||||
},
|
||||
take: 15,
|
||||
orderBy: {
|
||||
posts: {
|
||||
_count: "desc",
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// Will be done automatically in the background
|
||||
async function deleteTag({ tag_id }) {}
|
||||
|
||||
// async function deleteImage(image, requester_id) {
|
||||
// const user = await getUser({ id: requester_id });
|
||||
// const post = await getBlog({ id: image.parent, raw: true });
|
||||
|
@ -540,4 +591,4 @@ const _r = (s, m) => {
|
|||
return { success: s, message: m };
|
||||
};
|
||||
|
||||
module.exports = { settings, newUser, getUser, editUser, getPost, newPost, editPost, getBiography, updateBiography, uploadMedia, deleteBlog, postSetting, getSetting };
|
||||
module.exports = { settings, newUser, getUser, editUser, getPost, newPost, editPost, getBiography, updateBiography, uploadMedia, deleteBlog, getTags, postSetting, getSetting };
|
||||
|
|
|
@ -14,6 +14,7 @@ async function index(request, response) {
|
|||
// if (!is_setup_complete) return response.redirect("/register");
|
||||
|
||||
const blog_list = await core.getPost({ requester_id: request.session.user?.id, page: request.query.page || 0 });
|
||||
const tags = await core.getTags();
|
||||
|
||||
blog_list.data.forEach((post) => {
|
||||
let published_date_parts = new Date(post.publish_date).toLocaleDateString().split("/");
|
||||
|
@ -27,6 +28,7 @@ async function index(request, response) {
|
|||
pagination: blog_list.pagination,
|
||||
current_page: request.query.page || 0,
|
||||
loaded_page: request.path,
|
||||
tags: tags,
|
||||
});
|
||||
}
|
||||
function register(request, response) {
|
||||
|
@ -52,7 +54,7 @@ async function authorEdit(request, response) {
|
|||
response.render(getThemePage("authorEdit"), { ...getDefaults(request), profile: author.data });
|
||||
}
|
||||
async function blogList(req, res) {
|
||||
const blog_list = await core.getPost({ requester_id: req.session.user?.id }, { search: req.query.search, search_title: true });
|
||||
const blog_list = await core.getPost({ requester_id: req.session.user?.id }, { search: req.query.search, search_title: true, search_tags: true, search_content: true });
|
||||
|
||||
blog_list.data.forEach((post) => {
|
||||
let published_date_parts = new Date(post.publish_date).toLocaleDateString().split("/");
|
||||
|
|
|
@ -85,7 +85,8 @@
|
|||
height: -moz-fit-content;
|
||||
height: fit-content;
|
||||
background-color: lightgray;
|
||||
margin-bottom: 0.1rem;
|
||||
margin-bottom: 0.5rem;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
.post-list-container .tag-list .list .tag::before {
|
||||
display: none;
|
||||
|
@ -98,6 +99,8 @@
|
|||
padding: 0.2rem 0.3rem;
|
||||
box-sizing: border-box;
|
||||
border-radius: 4px;
|
||||
color: black;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.tag::before {
|
||||
|
|
|
@ -95,7 +95,8 @@
|
|||
.tag {
|
||||
height: fit-content;
|
||||
background-color: lightgray;
|
||||
margin-bottom: 0.1rem;
|
||||
margin-bottom: 0.5rem;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
.tag::before {
|
||||
|
@ -111,6 +112,9 @@
|
|||
padding: 0.2rem 0.3rem;
|
||||
box-sizing: border-box;
|
||||
border-radius: 4px;
|
||||
|
||||
color: black;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.tag::before {
|
||||
|
|
|
@ -22,7 +22,9 @@
|
|||
<div class="tag-list">
|
||||
<div class="tag-header">TAGS</div>
|
||||
<div class="list">
|
||||
<div class="tag icon">Tag 1</div>
|
||||
<% for(tag of tags) { %>
|
||||
<a class="tag icon" href="/posts/?search=<%= tag.name %> "><%= tag.name %></a>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -35,7 +35,7 @@ model Post {
|
|||
ownerid String?
|
||||
|
||||
// Tags
|
||||
tags String[]
|
||||
tags Tag[]
|
||||
|
||||
// Dates
|
||||
publish_date DateTime?
|
||||
|
@ -62,6 +62,18 @@ model Group {
|
|||
permissions String[]
|
||||
}
|
||||
|
||||
model Tag {
|
||||
id String @id @unique @default(uuid())
|
||||
name String @unique
|
||||
type TagMode @default(NORMAL)
|
||||
posts Post[]
|
||||
}
|
||||
|
||||
enum TagMode {
|
||||
NORMAL
|
||||
ALIAS
|
||||
}
|
||||
|
||||
enum Role {
|
||||
LOCKED
|
||||
USER
|
||||
|
|
Loading…
Reference in New Issue