Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

optimize query #48

Draft
wants to merge 3 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"@emotion/styled": "^11.0.0",
"@prisma/client": "^2.19.0",
"@sendgrid/mail": "^7.4.2",
"@types/lodash": "^4.14.168",
"autoprefixer": "^10.2.5",
"axios": "^0.21.1",
"class-validator": "^0.13.1",
Expand All @@ -34,6 +35,7 @@
"formidable": "^1.2.2",
"framer-motion": "^3.2.1",
"jsonwebtoken": "^8.5.1",
"lodash": "^4.17.21",
"markdown-it": "^12.0.6",
"milligram": "^1.4.1",
"nanoid": "^3.1.22",
Expand Down
4 changes: 3 additions & 1 deletion pages/api/comment/[commentId]/replyAsModerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,18 @@ export default async function handler(
if (req.method === 'POST') {
const body = req.body as {
content: string
ancestorId: string
}
const commentId = req.query.commentId as string

const project = await commentService.getProject(commentId)
if (!(await authService.projectOwnerGuard(project))) {
return
}
const created = await commentService.addCommentAsModerator(
const created = await commentService.addCommentAsModeratorV2(
commentId,
body.content,
body.ancestorId,
)
res.json({
data: created,
Expand Down
7 changes: 4 additions & 3 deletions pages/api/open/comments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,10 @@ export default async function handler(
nickname: string
pageUrl?: string
pageTitle?: string
ancestorId?: string
}

const comment = await commentService.addComment(
const comment = await commentService.addCommentV2(
body.appId,
body.pageId,
{
Expand All @@ -41,6 +42,7 @@ export default async function handler(
nickname: body.nickname,
},
body.parentId,
body.ancestorId,
)

res.json({
Expand All @@ -53,9 +55,8 @@ export default async function handler(
pageId: string
}

const comments = await commentService.getComments(query.appId, {
const comments = await commentService.getCommentsV2(query.appId, {
approved: true,
parentId: null,
pageSlug: query.pageId,
select: {
by_nickname: true,
Expand Down
2 changes: 1 addition & 1 deletion pages/api/project/[projectId]/comments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export default async function handler(
return
}

const comments = await commentService.getComments(projectId, {
const comments = await commentService.getCommentsV2(projectId, {
parentId: null,
page: Number(page),
onlyOwn: true,
Expand Down
13 changes: 9 additions & 4 deletions pages/dashboard/project/[projectId].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,10 @@ const deleteComment = async ({ commentId }) => {
return res.data
}

const replyAsModerator = async ({ parentId, content }) => {
const replyAsModerator = async ({ parentId, content, ancestorId }) => {
const res = await apiClient.post(`/comment/${parentId}/replyAsModerator`, {
content
content,
ancestorId,
})
return res.data.data
}
Expand Down Expand Up @@ -76,7 +77,7 @@ function CommentComponent(props: {

const refetch = props.refetch
const comment = props.comment

const isRoot = props.isRoot
const [showReplyForm, setShowReplyForm] = React.useState(false)

const approveCommentMutation = useMutation(approveComment, {
Expand Down Expand Up @@ -106,7 +107,11 @@ function CommentComponent(props: {
}) {
const form = useForm()
function onSubmit({ content }) {
replyMutation.mutate({ content, parentId: props.parentId })
replyMutation.mutate({
content,
parentId: props.parentId,
ancestorId: comment.ancestorId,
})
}
const replyMutation = useMutation(replyAsModerator, {
onSuccess() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "comments" ADD COLUMN "ancestorId" TEXT;
3 changes: 2 additions & 1 deletion prisma/sqlite/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,10 @@ model Comment {

approved Boolean @default(false)

ancestorId String?
parentId String?
parent Comment? @relation("replies", fields: [parentId], references: [id])
replies Comment[] @relation("replies")

@@map("comments")
}
178 changes: 175 additions & 3 deletions service/comment.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { PageService } from './page.service'
import dayjs from 'dayjs'
import MarkdownIt from 'markdown-it'
import { HookService } from './hook.service'

import { groupBy, get } from 'lodash'
export const markdown = MarkdownIt({
linkify: true,
})
Expand All @@ -15,7 +15,9 @@ markdown.disable(['image', 'link'])
export class CommentService extends RequestScopeService {
pageService = new PageService(this.req)
hookService = new HookService(this.req)

/**
* @deprecated
*/
async getComments(
projectId: string,
options?: {
Expand All @@ -35,6 +37,8 @@ export class CommentService extends RequestScopeService {
content: true,
...options?.select,
page: true,
ancestorId: true,
parentId: true,
}

const comments = await prisma.comment.findMany({
Expand Down Expand Up @@ -96,6 +100,107 @@ export class CommentService extends RequestScopeService {
return allComments as any[]
}

async getCommentsV2(
projectId: string,
options?: {
parentId?: string
page?: number
select?: Prisma.CommentSelect
pageSlug?: string | Prisma.StringFilter
onlyOwn?: boolean
approved?: boolean
},
): Promise<any[]> {
const pageSize = 10

const select = {
id: true,
createdAt: true,
content: true,
...options?.select,
page: true,
ancestorId: true,
parentId: true,
}

const rootComments = await prisma.comment.findMany({
skip: options?.page ? (options.page - 1) * pageSize : 0,
take: options?.page ? pageSize : 100,
orderBy: {
createdAt: 'desc',
},
select,
where: {
approved: options?.approved === true ? true : options?.approved,
parentId: null,
deletedAt: {
equals: null,
},
page: {
slug: options?.pageSlug,
projectId,
project: {
ownerId: options?.onlyOwn
? await (await this.getSession()).uid
: undefined,
},
},
},
})

const rootId = rootComments.map((v) => v.id)

const replies = await prisma.comment.findMany({
orderBy: {
createdAt: 'desc',
},
select,
where: {
approved: options?.approved === true ? true : options?.approved,
deletedAt: {
equals: null,
},
ancestorId: {
in: rootId,
},
page: {
slug: options?.pageSlug,
projectId,
},
},
})

const parseResult = (v) => ({
...v,
parsedCreatedAt: dayjs(v.createdAt).format('YYYY-MM-DD HH:mm'),
parsedContent: markdown.render(v.content),
})

const parsedComment = rootComments.map((v) => parseResult(v))
const parsedReply = replies.map((v) => parseResult(v))
const childrenDict = groupBy(parsedReply, 'parentId')
const makeChildren = (v) => {
if (get(childrenDict, v.id)) {
return {
...v,
replies: get(childrenDict, v.id).map((v) => makeChildren(v)),
}
}
return {
...v,
replies: [],
}
}

const replaiesTree = parsedReply.map((v) => makeChildren(v))
const replaiesDict = groupBy(replaiesTree, 'parentId')

return parsedComment.map((v) => ({
...v,
replies: get(replaiesDict, v.id, []),
}))
}

async getProject(commentId: string) {
const res = await prisma.comment.findUnique({
where: {
Expand All @@ -117,7 +222,9 @@ export class CommentService extends RequestScopeService {

return res.page.project
}

/**
* @deprecated
*/
async addComment(
projectId: string,
pageSlug: string,
Expand Down Expand Up @@ -151,6 +258,43 @@ export class CommentService extends RequestScopeService {
return created
}

async addCommentV2(
projectId: string,
pageSlug: string,
body: {
content: string
email: string
nickname: string
pageUrl?: string
pageTitle?: string
},
parentId?: string,
ancestorId?: string,
) {
// touch page
const page = await this.pageService.upsertPage(pageSlug, projectId, {
pageTitle: body.pageTitle,
pageUrl: body.pageUrl,
})

const created = await prisma.comment.create({
data: {
content: body.content,
by_email: body.email,
by_nickname: body.nickname,
pageId: page.id,
parentId,
ancestorId,
},
})

this.hookService.addComment(created, projectId)

return created
}
/**
* @deprecated
*/
async addCommentAsModerator(parentId: string, content: string) {
const session = await this.getSession()
const parent = await prisma.comment.findUnique({
Expand All @@ -174,6 +318,34 @@ export class CommentService extends RequestScopeService {
return created
}

async addCommentAsModeratorV2(
parentId: string,
content: string,
ancestorId?: string,
) {
const session = await this.getSession()
const parent = await prisma.comment.findUnique({
where: {
id: parentId,
},
})

const created = await prisma.comment.create({
data: {
content: content,
by_email: session.user.email,
by_nickname: session.user.name,
moderatorId: session.uid,
pageId: parent.pageId,
approved: true,
parentId,
ancestorId,
},
})

return created
}

async approve(commentId: string) {
await prisma.comment.update({
where: {
Expand Down
2 changes: 1 addition & 1 deletion widget/components/Comment.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
</div>

{#if showReplyForm}
<Reply parentId={comment.id} onSuccess={() => { showReplyForm = false }} />
<Reply parentId={comment.id} ancestorId={comment.ancestorId} onSuccess={() => { showReplyForm = false }} />
{/if}

{#if comment.replies.length > 0}
Expand Down
5 changes: 4 additions & 1 deletion widget/components/Reply.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script>
import { getContext } from "svelte";
export let parentId;

export let ancestorId;
// form data
let content = "";
let nickname = "";
Expand Down Expand Up @@ -38,6 +38,7 @@
parentId,
pageUrl,
pageTitle,
ancestorId
});
await refresh();
teardown();
Expand All @@ -47,6 +48,8 @@
}
}



function teardown() {
content = "";
nickname = "";
Expand Down
2 changes: 1 addition & 1 deletion widget/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<div style="width: 50%; margin: 0 auto;">
<div id="cusdis_thread"
data-host="http://localhost:3000"
data-app-id="9e8df409-5055-4751-aa5f-4e08a66ce014"
data-app-id="0cea3129-d338-4cad-92d8-9fe13ff025d9"
data-page-id="svelte"
data-show-indicator="true"
></div>
Expand Down
Loading