diff --git a/.vscode/launch.json b/.vscode/launch.json index e750064a6..5cc617f73 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -6,10 +6,25 @@ "configurations": [ { "name": "Next.js: debug server-side", - "type": "node-terminal", + "type": "node", "request": "launch", - "command": "npm run debug", - "cwd": "${workspaceFolder}/apps/main" + "runtimeExecutable": "${workspaceFolder}/node_modules/next/dist/bin/next", + "env": { + "NODE_OPTIONS": "--inspect" + }, + "cwd": "${workspaceFolder}/apps/main", + "sourceMapPathOverrides": { + "webpack:///./*": "${workspaceRoot}/apps/main/*" + }, + "console": "integratedTerminal", + + // Files to exclude from debugger (e.g. call stack) + "skipFiles": [ + // Node.js internal core modules + "/**", + // Ignore all dependencies (optional) + "${workspaceFolder}/apps/main/node_modules/**" + ] }, { "type": "node", diff --git a/apps/main/src/pages/api/sdk/page.ts b/apps/main/src/pages/api/sdk/page.ts new file mode 100644 index 000000000..373fa0185 --- /dev/null +++ b/apps/main/src/pages/api/sdk/page.ts @@ -0,0 +1,33 @@ +import { prisma } from '@chirpy-dev/trpc'; +import type { NextApiRequest, NextApiResponse } from 'next'; + +import { getAPIHandler } from '$/server/common/api-handler'; + +const handler = getAPIHandler(); +handler.get(getPage); + +export default handler; + +async function getPage(req: NextApiRequest, res: NextApiResponse) { + const auth = req.headers.authorization; + const apiKey = auth?.split(' ')[1]; + if (!auth || !apiKey) { + res.status(401).end('Unauthorized, missing API key'); + return; + } + const setting = await prisma.settings.findUnique({ + where: { + sdkKey: apiKey, + }, + }); + if (!setting) { + res.status(401).end('Unauthorized, invalid API key'); + return; + } + const page = await prisma.page.findUnique({ + where: { + url: req.query.url as string, + }, + }); + res.status(200).json(page); +} diff --git a/apps/main/src/pages/api/sdk/page/link-author.ts b/apps/main/src/pages/api/sdk/page/link-author.ts new file mode 100644 index 000000000..ebf87091a --- /dev/null +++ b/apps/main/src/pages/api/sdk/page/link-author.ts @@ -0,0 +1,47 @@ +import { prisma } from '@chirpy-dev/trpc'; +import type { NextApiRequest, NextApiResponse } from 'next'; +import { z } from 'zod'; + +import { getAPIHandler } from '$/server/common/api-handler'; + +const handler = getAPIHandler(); +handler.post(linkAuthor); + +export default handler; + +const SCHEMA = z.object({ + pageUrl: z.string().url(), + authorId: z.string(), +}); + +async function linkAuthor(req: NextApiRequest, res: NextApiResponse) { + const auth = req.headers.authorization; + const apiKey = auth?.split(' ')[1]; + if (!auth || !apiKey) { + res.status(401).end('Unauthorized, missing API key'); + return; + } + const setting = await prisma.settings.findUnique({ + where: { + sdkKey: apiKey, + }, + }); + if (!setting) { + res.status(401).end('Unauthorized, invalid API key'); + return; + } + const result = SCHEMA.safeParse(JSON.parse(req.body)); + if (!result.success) { + res.status(400).end('Bad request, expect pageURL and authorId'); + return; + } + await prisma.page.update({ + where: { + url: result.data.pageUrl, + }, + data: { + authorId: result.data.authorId, + }, + }); + res.status(200).end('ok'); +} diff --git a/apps/main/src/pages/api/sdk/project.ts b/apps/main/src/pages/api/sdk/project.ts index 739f9aacb..5fe5f5f61 100644 --- a/apps/main/src/pages/api/sdk/project.ts +++ b/apps/main/src/pages/api/sdk/project.ts @@ -1,5 +1,6 @@ import { prisma } from '@chirpy-dev/trpc'; import type { NextApiRequest, NextApiResponse } from 'next'; +import { z } from 'zod'; import { getAPIHandler } from '$/server/common/api-handler'; @@ -46,6 +47,11 @@ async function getProject(req: NextApiRequest, res: NextApiResponse) { res.status(200).json(setting.user.projects[0] || null); } +const SCHEMA = z.object({ + domain: z.string(), + name: z.string(), +}); + async function createProject(req: NextApiRequest, res: NextApiResponse) { const auth = req.headers.authorization; const apiKey = auth?.split(' ')[1]; @@ -53,11 +59,7 @@ async function createProject(req: NextApiRequest, res: NextApiResponse) { res.status(401).end('Unauthorized, missing API key'); return; } - const domain = req.query.domain as string; - if (!domain) { - res.status(400).end('Bad request, missing domain'); - return; - } + const setting = await prisma.settings.findUnique({ where: { sdkKey: apiKey, @@ -87,14 +89,26 @@ async function createProject(req: NextApiRequest, res: NextApiResponse) { .end('Forbidden, too many projects. Please upgrade to Enterprise plan'); return; } - const proj = await prisma.project.create({ - data: { - name: req.query.name as string, - domain, - userId: setting.user.id, - }, - }); - res.status(200).json(proj); + const result = SCHEMA.safeParse(JSON.parse(req.body)); + if (!result.success) { + res.status(400).end(`Bad request, ${result.error}`); + return; + } + try { + const proj = await prisma.project.create({ + data: { + name: result.data.name, + domain: result.data.domain, + userId: setting.user.id, + }, + }); + res.status(200).json(proj); + } catch (error) { + console.error('create project failed', error); + res + .status(400) + .end(`Bad request, create project failed, double check your input`); + } } async function deleteProject(req: NextApiRequest, res: NextApiResponse) { diff --git a/apps/main/src/pages/api/sdk/user.ts b/apps/main/src/pages/api/sdk/user.ts new file mode 100644 index 000000000..8c672c889 --- /dev/null +++ b/apps/main/src/pages/api/sdk/user.ts @@ -0,0 +1,52 @@ +import { prisma } from '@chirpy-dev/trpc'; +import type { NextApiRequest, NextApiResponse } from 'next'; +import { z } from 'zod'; + +import { getAPIHandler } from '$/server/common/api-handler'; + +const handler = getAPIHandler(); +handler.post(createUser); + +export default handler; + +const schema = z.object({ + email: z.string().email(), + name: z.string(), +}); + +async function createUser(req: NextApiRequest, res: NextApiResponse) { + const auth = req.headers.authorization; + const apiKey = auth?.split(' ')[1]; + if (!auth || !apiKey) { + res.status(401).end('Unauthorized, missing API key'); + return; + } + const setting = await prisma.settings.findUnique({ + where: { + sdkKey: apiKey, + }, + }); + if (!setting) { + res.status(401).end('Unauthorized, invalid API key'); + return; + } + const result = schema.safeParse(JSON.parse(req.body)); + if (!result.success) { + res.status(400).end(`Bad request, ${result.error}`); + return; + } + try { + const user = await prisma.user.create({ + data: { + email: result.data.email, + name: result.data.name, + }, + }); + res.status(200).json(user); + } catch (error) { + console.error('create user failed', error); + res + .status(400) + .end(`Bad request, create user failed, double check your input`); + } +} diff --git a/apps/main/src/pages/widget/comment/[pageURL].tsx b/apps/main/src/pages/widget/comment/[pageURL].tsx index 13fb7910f..1f9c762d5 100644 --- a/apps/main/src/pages/widget/comment/[pageURL].tsx +++ b/apps/main/src/pages/widget/comment/[pageURL].tsx @@ -1,17 +1,15 @@ import { prisma, ssg } from '@chirpy-dev/trpc'; -import { CommonWidgetProps, Theme } from '@chirpy-dev/types'; +import { Theme } from '@chirpy-dev/types'; +import { PageCommentProps } from '@chirpy-dev/ui'; import { GetStaticPaths, GetStaticProps, GetStaticPropsContext, GetStaticPropsResult, - InferGetStaticPropsType, } from 'next'; import { log } from 'next-axiom'; import superjson from 'superjson'; -export type PageCommentProps = InferGetStaticPropsType; - /** * Comment tree widget for a page * @param props @@ -48,10 +46,7 @@ export const getStaticPaths: GetStaticPaths = async () => { return { paths, fallback: 'blocking' }; }; -type StaticProps = PathParams & - CommonWidgetProps & { - pageId: string; - }; +type StaticProps = PageCommentProps; type StaticError = { error: string; }; @@ -72,6 +67,22 @@ export const getStaticProps: GetStaticProps< where: { url: pageURL, }, + select: { + id: true, + url: true, + authorId: true, + project: { + select: { + id: true, + theme: true, + user: { + select: { + plan: true, + }, + }, + }, + }, + }, }); const pageId = page?.id; if (!pageId) { @@ -83,37 +94,18 @@ export const getStaticProps: GetStaticProps< url: pageURL, }); - const pageByPk = await prisma.page.findUnique({ - where: { - id: pageId, - }, - select: { - project: { - select: { - id: true, - theme: true, - user: { - select: { - plan: true, - }, - }, - }, - }, - }, - }); - if (!pageByPk?.project.id) { - log.error(`Can't find theme info`); + if (!page.project.id) { + log.error(`Can't find the project`, page); return { notFound: true }; } return { props: { trpcState: ssg.dehydrate(), - pageURL, - pageId, - projectId: pageByPk.project.id, - theme: (pageByPk.project.theme as Theme) || null, + page, + projectId: page.project.id, + theme: (page.project.theme as Theme) || null, isWidget: true, - plan: pageByPk.project.user?.plan || 'HOBBY', + plan: page.project.user?.plan || 'HOBBY', }, revalidate: 5 * 60, }; diff --git a/apps/main/src/pages/widget/comment/timeline/[commentId].tsx b/apps/main/src/pages/widget/comment/timeline/[commentId].tsx index 786aa0a41..4a0835020 100644 --- a/apps/main/src/pages/widget/comment/timeline/[commentId].tsx +++ b/apps/main/src/pages/widget/comment/timeline/[commentId].tsx @@ -60,6 +60,7 @@ export const getStaticProps: GetStaticProps< select: { id: true, url: true, + authorId: true, project: { select: { id: true, @@ -76,17 +77,16 @@ export const getStaticProps: GetStaticProps< }, }); if (!data?.page.project.id) { - log.error(`Can't find theme info`); + log.error(`Can't find the project`, data || undefined); return { notFound: true }; } return { props: { trpcState: ssg.dehydrate(), - pageId: data.page.id, + page: data.page, projectId: data.page.project.id, commentId, - pageURL: data.page.url, theme: (data.page.project.theme as Theme) || null, isWidget: true, plan: data.page.project.user?.plan || 'HOBBY', diff --git a/apps/main/vercel.json b/apps/main/vercel.json new file mode 100644 index 000000000..6b101a9e0 --- /dev/null +++ b/apps/main/vercel.json @@ -0,0 +1,7 @@ +{ + "functions": { + "src/pages/**/*": { + "maxDuration": 50 + } + } +} diff --git a/packages/sdk/.npmignore b/packages/sdk/.npmignore new file mode 100644 index 000000000..81a38be68 --- /dev/null +++ b/packages/sdk/.npmignore @@ -0,0 +1 @@ +.env* diff --git a/packages/sdk/package.json b/packages/sdk/package.json index 0ed23f0b9..6f1d671f8 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -1,6 +1,6 @@ { "name": "@chirpy-dev/sdk", - "version": "0.0.2", + "version": "0.0.5", "license": "AGPL-3.0-or-later", "main": "./lib/index.js", "types": "./lib/index.d.ts", @@ -9,6 +9,7 @@ }, "sideEffects": false, "devDependencies": { + "@chirpy-dev/tsconfigs": "workspace:*", "dotenv": "16.3.1", "typescript": "5.2.2" }, diff --git a/packages/sdk/src/sdk.test.ts b/packages/sdk/src/sdk.test.ts index 6dd95abdf..ee77e041e 100644 --- a/packages/sdk/src/sdk.test.ts +++ b/packages/sdk/src/sdk.test.ts @@ -7,8 +7,11 @@ async function test() { process.env.CHIRPY_SDK_KEY!, 'http://localhost:3000', ); - const proj = await sdk.getProject('chirpy.dev'); - console.log(proj); + const page = await sdk.getPage('http://localhost:3000/play'); + console.log(page); + const user = await sdk.createUser('pickle@mac.com', 'Pickle'); + console.log(user); + await sdk.linkPageAuthor('http://localhost:3000/play', user.id); } test(); diff --git a/packages/sdk/src/sdk.tsx b/packages/sdk/src/sdk.tsx index 4de6cd5f7..2b0aa79b1 100644 --- a/packages/sdk/src/sdk.tsx +++ b/packages/sdk/src/sdk.tsx @@ -1,8 +1,10 @@ -import type { Project } from '@prisma/client'; +import type { Page, Project, User } from '@prisma/client'; type RequestProps = { - searchParams: Record; + path: string; + searchParams?: Record; method?: 'GET' | 'POST' | 'DELETE'; + body?: Record; }; export class ChirpySDK { @@ -11,21 +13,60 @@ export class ChirpySDK { private origin: string = 'https://chirpy.dev', ) {} - public getProject(domain: string): Promise { - return this.request({ searchParams: { domain } }); + public getProject(domain: string): Promise { + return this.request({ path: '/api/sdk/project', searchParams: { domain } }); } public createProject(domain: string, name: string): Promise { - return this.request({ searchParams: { domain, name }, method: 'POST' }); + return this.request({ + path: '/api/sdk/project', + body: { domain, name }, + method: 'POST', + }); } public deleteProject(domain: string): Promise { - return this.request({ searchParams: { domain }, method: 'DELETE' }); + return this.request({ + path: '/api/sdk/project', + searchParams: { domain }, + method: 'DELETE', + }); + } + + public getPage(url: string): Promise { + return this.request({ path: '/api/sdk/page', searchParams: { url } }); } - private async request({ searchParams, method = 'GET' }: RequestProps) { - const url = new URL(`${this.origin}/api/sdk/project`); - Object.entries(searchParams).forEach(([key, value]) => { + public linkPageAuthor(pageUrl: string, authorId: string): Promise { + return this.request({ + path: '/api/sdk/page/link-author', + body: { + pageUrl, + authorId, + }, + method: 'POST', + }); + } + + public createUser(email: string, name: string): Promise { + return this.request({ + path: '/api/sdk/user', + body: { + email, + name, + }, + method: 'POST', + }); + } + + private async request({ + path, + body, + searchParams, + method = 'GET', + }: RequestProps) { + const url = new URL(`${this.origin}${path}`); + Object.entries(searchParams || {}).forEach(([key, value]) => { url.searchParams.set(key, value); }); const res = await fetch(url.href, { @@ -33,13 +74,19 @@ export class ChirpySDK { authorization: `Bearer ${this.apiKey}`, }, method, + body: body ? JSON.stringify(body) : undefined, }); if (!res.ok) { throw new Error( - `Chirpy SDK API Error:\nstatus:${res.status}\n${res.text}`, + `Chirpy SDK API Error:\nstatus:${res.status}\n${await res.text()}`, ); } - const data = await res.json(); - return data; + try { + const data = await res.json(); + return data; + } catch { + // ignore, no json response + console.log(`No JSON response, ${await res.text()}`); + } } } diff --git a/packages/trpc/prisma/migrations/20240417130014_add_page_author/migration.sql b/packages/trpc/prisma/migrations/20240417130014_add_page_author/migration.sql new file mode 100644 index 000000000..cff9a9288 --- /dev/null +++ b/packages/trpc/prisma/migrations/20240417130014_add_page_author/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "Page" ADD COLUMN "authorId" TEXT; diff --git a/packages/trpc/prisma/schema.prisma b/packages/trpc/prisma/schema.prisma index bc5d1e721..15c6ed7cf 100644 --- a/packages/trpc/prisma/schema.prisma +++ b/packages/trpc/prisma/schema.prisma @@ -129,6 +129,8 @@ model Page { projectId String project Project @relation(fields: [projectId], references: [id], onDelete: Cascade, onUpdate: Cascade) comments Comment[] + authorId String? + author User? @relation(fields: [authorId], references: [id], onDelete: Cascade, onUpdate: Cascade) @@index([projectId]) } @@ -211,6 +213,7 @@ model User { billingCycleDay Int? stripeCustomerId String? @unique stripeSubscriptionId String? @unique + pages Page[] } enum Plan { diff --git a/packages/trpc/src/services/mutation-event/comment-handler.ts b/packages/trpc/src/services/mutation-event/comment-handler.ts index 8acb572fd..50750dc86 100644 --- a/packages/trpc/src/services/mutation-event/comment-handler.ts +++ b/packages/trpc/src/services/mutation-event/comment-handler.ts @@ -33,23 +33,23 @@ export async function handleCommentEvent( const commentId = event.comment.id; const body = getTextFromRteDoc(event.comment.content as JSONContent); - const siteOwnerData = await getSiteOwnerByTriggeredCommentId(commentId); + const ownerData = await getSiteOwnerAndPageAuthor(commentId); - const owner = siteOwnerData?.page.project.user; - if (!siteOwnerData || !owner?.id) { + const owner = ownerData?.page.project.user; + if (!ownerData || !owner?.id) { throw new Error( `Can't find the site owner for comment id (${commentId})`, ); } - const url = siteOwnerData.page.url; + const url = ownerData.page.url; revalidatePromises.push(revalidateCommentWidget(url, res)); const ownerId = owner.id; const triggeredById = event.comment.userId; const triggeredBy = { id: triggeredById, - name: siteOwnerData.user.name || siteOwnerData.user.username || 'Unnamed', + name: ownerData.user.name || ownerData.user.username || 'Unnamed', }; - if (owner.id !== triggeredById) { + if (ownerId !== triggeredById) { // Notify the owner of the site that a comment has been added notificationPayloads.push({ recipient: { @@ -64,6 +64,26 @@ export async function handleCommentEvent( contextId: commentId, }); } + const pageAuthor = ownerData?.page.author; + if ( + pageAuthor && + pageAuthor.id !== triggeredById && + pageAuthor.id !== ownerId + ) { + // Notify the author of the page that a comment has been added + notificationPayloads.push({ + recipient: { + id: pageAuthor.id, + email: pageAuthor.email, + name: pageAuthor.name || pageAuthor.username || 'Unnamed', + }, + type: 'ReceivedAComment', + triggeredBy, + url, + body, + contextId: commentId, + }); + } const parentCommentId = event.comment.parentId; if (parentCommentId) { @@ -92,9 +112,9 @@ export async function handleCommentEvent( } else if (event.op === 'DELETE') { const { comment } = event; // Delete the existing notification sent to the owner of site - const siteOwnerData = await getSiteOwnerByTriggeredCommentId(comment.id); - const ownerId = siteOwnerData?.page.project.user?.id; - if (!siteOwnerData || !ownerId) { + const ownerData = await getSiteOwnerAndPageAuthor(comment.id); + const ownerId = ownerData?.page.project.user?.id; + if (!ownerData || !ownerId) { throw new Error( `Can't find the site owner for comment id (${comment.id})`, ); @@ -109,6 +129,19 @@ export async function handleCommentEvent( contextId, }); } + const pageAuthor = ownerData.page.author; + if ( + pageAuthor && + pageAuthor.id !== comment.userId && + pageAuthor.id !== ownerId + ) { + await deleteNotificationMessage({ + triggeredById: comment.userId, + recipientId: pageAuthor.id, + type: 'ReceivedAComment', + contextId, + }); + } // Delete the existing notification sent to the parent comment author if (comment.parentId) { const parentData = await getAuthorByCommentId(comment.parentId); @@ -190,7 +223,7 @@ export async function handleCommentEvent( return; } -export async function getSiteOwnerByTriggeredCommentId(commentId: string) { +export async function getSiteOwnerAndPageAuthor(commentId: string) { return await prisma.comment.findFirst({ where: { id: commentId, @@ -200,6 +233,14 @@ export async function getSiteOwnerByTriggeredCommentId(commentId: string) { select: { id: true, url: true, + author: { + select: { + id: true, + name: true, + email: true, + username: true, + }, + }, project: { select: { user: { diff --git a/packages/ui/src/blocks/comment-card/comment-card.tsx b/packages/ui/src/blocks/comment-card/comment-card.tsx index 365a7b530..ce43c50f4 100644 --- a/packages/ui/src/blocks/comment-card/comment-card.tsx +++ b/packages/ui/src/blocks/comment-card/comment-card.tsx @@ -55,7 +55,8 @@ export function CommentCard({ }: CommentCardProps): JSX.Element { const { image, name, username, email } = author; const [showReplyEditor, setShowReplyEditor] = React.useState(false); - const { projectId, deleteAComment, createAComment } = useCommentContext(); + const { projectId, page, deleteAComment, createAComment } = + useCommentContext(); const { showToast } = useToast(); const handleClickConfirmDelete = () => { deleteAComment(commentId); @@ -102,6 +103,7 @@ export function CommentCard({ data?.editableProjectIds?.includes(projectId); const createdAtDate = cpDayjs(createdAt); const [showDelDialog, setShowDelDialog] = React.useState(false); + const isPageAuthor = page.authorId === author.id; if (isDeleted) { return ; @@ -127,15 +129,22 @@ export function CommentCard({ />
-
- - {name} - +
+
+ + {name} + + {isPageAuthor && ( +

+ Author +

+ )} +
diff --git a/packages/ui/src/blocks/comment-widget-preview/comment-widget-preview.tsx b/packages/ui/src/blocks/comment-widget-preview/comment-widget-preview.tsx index fa4c89dbd..4963520f0 100644 --- a/packages/ui/src/blocks/comment-widget-preview/comment-widget-preview.tsx +++ b/packages/ui/src/blocks/comment-widget-preview/comment-widget-preview.tsx @@ -115,7 +115,10 @@ function CommentWidgetPreviewInternal( }, [showToast]); const commentContext: CommentContextType = React.useMemo( () => ({ - pageId: PAGE_ID, + page: { + id: PAGE_ID, + authorId: null, + }, projectId: PROJECT_ID, createAComment, deleteAComment, diff --git a/packages/ui/src/contexts/comment-context/comment-context-provider.tsx b/packages/ui/src/contexts/comment-context/comment-context-provider.tsx index aefa0f263..d1890e12b 100644 --- a/packages/ui/src/contexts/comment-context/comment-context-provider.tsx +++ b/packages/ui/src/contexts/comment-context/comment-context-provider.tsx @@ -6,13 +6,17 @@ import { useCreateAComment } from './use-create-a-comment'; import { useDeleteAComment } from './use-delete-a-comment'; import { useToggleALikeAction } from './use-toggle-a-like-action'; -export type CommentContextProviderProps = React.PropsWithChildren< - Pick ->; +export type CommentContextProviderProps = React.PropsWithChildren<{ + projectId: string; + page: { + id: string; + authorId: string | null; + }; +}>; export function CommentContextProvider(props: CommentContextProviderProps) { const createAComment = useCreateAComment({ - pageId: props.pageId, + pageId: props.page.id, }); const deleteAComment = useDeleteAComment(); const toggleALikeAction = useToggleALikeAction(); @@ -26,7 +30,7 @@ export function CommentContextProvider(props: CommentContextProviderProps) { const value: CommentContextType = React.useMemo( () => ({ projectId: props.projectId, - pageId: props.pageId, + page: props.page, createAComment, deleteAComment, toggleALikeAction, @@ -34,7 +38,7 @@ export function CommentContextProvider(props: CommentContextProviderProps) { }), [ props.projectId, - props.pageId, + props.page, createAComment, deleteAComment, toggleALikeAction, diff --git a/packages/ui/src/contexts/comment-context/comment-context.ts b/packages/ui/src/contexts/comment-context/comment-context.ts index ec991e160..5c32867af 100644 --- a/packages/ui/src/contexts/comment-context/comment-context.ts +++ b/packages/ui/src/contexts/comment-context/comment-context.ts @@ -7,7 +7,10 @@ import { UseToggleALikeAction } from './use-toggle-a-like-action'; export type CommentContextType = { projectId: string; - pageId: string; + page: { + id: string; + authorId: string | null; + }; createAComment: UseCreateAComment; deleteAComment: UseDeleteAComment; toggleALikeAction: UseToggleALikeAction; @@ -16,7 +19,10 @@ export type CommentContextType = { export const CommentContext = React.createContext({ projectId: '', - pageId: '', + page: { + id: '', + authorId: null, + }, createAComment: asyncNoop, deleteAComment: asyncNoop, toggleALikeAction: asyncNoop, diff --git a/packages/ui/src/pages/widget/page-url.tsx b/packages/ui/src/pages/widget/page-url.tsx index 2c5f23bcd..b31e14732 100644 --- a/packages/ui/src/pages/widget/page-url.tsx +++ b/packages/ui/src/pages/widget/page-url.tsx @@ -8,8 +8,11 @@ import { CommentContextProvider } from '../../contexts'; import { useRefetchInterval } from './use-refetch-interval'; export type PageCommentProps = CommonWidgetProps & { - pageURL: string; - pageId: string; + page: { + id: string; + url: string; + authorId: string | null; + }; }; /** @@ -20,7 +23,7 @@ export function CommentWidgetPage(props: PageCommentProps): JSX.Element { const refetchInterval = useRefetchInterval(); const { data: comments } = trpc.comment.forest.useQuery( { - url: props.pageURL, + url: props.page.url, }, { refetchInterval, @@ -35,7 +38,7 @@ export function CommentWidgetPage(props: PageCommentProps): JSX.Element { return ( - +
{/* @ts-ignore */} diff --git a/packages/ui/src/pages/widget/timeline.tsx b/packages/ui/src/pages/widget/timeline.tsx index fd637bda0..21cf2b62f 100644 --- a/packages/ui/src/pages/widget/timeline.tsx +++ b/packages/ui/src/pages/widget/timeline.tsx @@ -14,8 +14,11 @@ import { useRefetchInterval } from './use-refetch-interval'; export type CommentTimelineWidgetProps = CommonWidgetProps & { commentId: string; - pageId: string; - pageURL: string; + page: { + id: string; + url: string; + authorId: string | null; + }; }; export function CommentTimelineWidget( @@ -33,11 +36,11 @@ export function CommentTimelineWidget( return ( - +
{/* Can't use history.back() here in case user open this page individual */} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6cac409e7..48378c76d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -613,6 +613,9 @@ importers: specifier: 18.16.18 version: 18.16.18 devDependencies: + '@chirpy-dev/tsconfigs': + specifier: workspace:* + version: link:../tsconfigs dotenv: specifier: 16.3.1 version: 16.3.1