From 2bea30033481a2dca2ea4c6510e95127a08a3552 Mon Sep 17 00:00:00 2001 From: Nick Winters Date: Sun, 17 Nov 2024 23:40:36 -0800 Subject: [PATCH 1/5] Update Comments.tsx --- app/routes/_comments+/components/Comments.tsx | 34 +++++++++++++------ 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/app/routes/_comments+/components/Comments.tsx b/app/routes/_comments+/components/Comments.tsx index b5bbd330..3f1b718d 100644 --- a/app/routes/_comments+/components/Comments.tsx +++ b/app/routes/_comments+/components/Comments.tsx @@ -51,7 +51,29 @@ export function Comments({ }> }> {(comments) => ( -
+
+
+
+ {totalComments > 0 ? ( + <> + + {totalComments} + + + {`Comment${totalComments > 1 ? "s" : ""}`} + + + ) : ( + <> + + + Start a discussion + + + )} +
+ +
@@ -73,15 +95,7 @@ export function Comments({ parentId={parentId} siteId={siteId} /> - {totalComments > 0 && ( -
-
- {totalComments} - Comments -
- -
- )} + {comments && comments.length > 0 ? comments.map((comment, index) => ( Date: Mon, 18 Nov 2024 18:40:28 -0800 Subject: [PATCH 2/5] Update Column-4.tsx --- app/routes/_site+/_components/Column-4.tsx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/app/routes/_site+/_components/Column-4.tsx b/app/routes/_site+/_components/Column-4.tsx index 2b0e4270..19b525d5 100644 --- a/app/routes/_site+/_components/Column-4.tsx +++ b/app/routes/_site+/_components/Column-4.tsx @@ -1,4 +1,4 @@ -import { Fragment } from "react"; +import { Fragment, useState } from "react"; import { Tab, TabGroup, TabList, TabPanel, TabPanels } from "@headlessui/react"; import { Link, useLoaderData } from "@remix-run/react"; @@ -19,6 +19,8 @@ import { useTheme } from "~/utils/client-hints"; import { Contributors } from "./Contributors"; import { AdUnit } from "./RampUnit"; import { DarkModeToggle } from "../action+/theme-toggle"; +import { SideMenu } from "./sidemenu/SideMenu"; +import { ViewSideMenu } from "./sidemenu/ViewSideMenu"; function AboutSection({ site, @@ -92,6 +94,8 @@ export function ColumnFour() { groupedTrendingPages.push(trendingPages.slice(i, i + 10)); } + const [editMode, setEditMode] = useState(false); + return (
{site.enableAds ? ( @@ -336,7 +340,10 @@ export function ColumnFour() {
)} -
+
+ +
+
{!site.isWhiteLabel && ( Date: Mon, 18 Nov 2024 21:40:39 -0800 Subject: [PATCH 3/5] Update join.tsx --- app/routes/_auth+/join.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/routes/_auth+/join.tsx b/app/routes/_auth+/join.tsx index 3fc84a5a..b9d47673 100644 --- a/app/routes/_auth+/join.tsx +++ b/app/routes/_auth+/join.tsx @@ -63,8 +63,8 @@ const JoinFormSchema = z.object({ username: z .string() .regex( - new RegExp(/^[a-z0-9]+(-[a-z0-9]+)*$/), - "Username contains invalid characters", + /^[a-z0-9]+(-[a-z0-9]+)*$/, + "Username can only contain lowercase letters, numbers, and hyphens. Hyphens cannot be at the start or end, and cannot be consecutive.", ) .min(3, "Username must be at least 3 characters long") .max(24, "Username cannot be more than 24 characters long") From c7c43a660591dbc319c282e4fb3a256e0253ccba Mon Sep 17 00:00:00 2001 From: Nick Winters Date: Wed, 20 Nov 2024 13:03:55 -1000 Subject: [PATCH 4/5] add date-fns --- package.json | 1 + yarn.lock | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/package.json b/package.json index 1b3c1766..5d50833f 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,7 @@ "compression": "^1.7.4", "cross-env": "^7.0.3", "date-and-time": "^3.0.3", + "date-fns": "^4.1.0", "dotenv": "^16.0.3", "express": "^4.21.1", "graphql": "^16.8.0", diff --git a/yarn.lock b/yarn.lock index da85f268..d06a4339 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5559,6 +5559,11 @@ date-fns@2.30.0, date-fns@^2.30.0: dependencies: "@babel/runtime" "^7.21.0" +date-fns@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-4.1.0.tgz#64b3d83fff5aa80438f5b1a633c2e83b8a1c2d14" + integrity sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg== + dateformat@^4.6.3: version "4.6.3" resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-4.6.3.tgz#556fa6497e5217fedb78821424f8a1c22fa3f4b5" From 0737ce9129d0ae4eba8389e43aa02a60cecea693 Mon Sep 17 00:00:00 2001 From: Nick Winters Date: Thu, 21 Nov 2024 13:49:34 -1000 Subject: [PATCH 5/5] community page latest comments, display account username --- app/routes/_comments+/components/Comments.tsx | 1 + app/routes/_site+/_components/PrimaryMenu.tsx | 73 +++--- app/routes/_site+/community/_community.tsx | 240 +++++++++++++++++- app/routes/_user+/user+/account.tsx | 8 +- 4 files changed, 283 insertions(+), 39 deletions(-) diff --git a/app/routes/_comments+/components/Comments.tsx b/app/routes/_comments+/components/Comments.tsx index 3f1b718d..0146a04e 100644 --- a/app/routes/_comments+/components/Comments.tsx +++ b/app/routes/_comments+/components/Comments.tsx @@ -163,6 +163,7 @@ function CommentRow({ return ( <>
)} - - -
-
-
- -
-
- Community -
+ + clsx( + isActive + ? "bg-zinc-200/40 dark:bg-dark350" + : "hover:dark:bg-dark350 hover:bg-zinc-200/40 text-1", + !isSidebar && "p-1.5", + "flex items-center gap-3 max-desktop:justify-center desktop:p-1.5 rounded-lg relative group", + ) + } + to="/community" + > + {({ isActive }) => ( +
+
+ +
+
+ Community
- - Coming Soon - + )} +
); } diff --git a/app/routes/_site+/community/_community.tsx b/app/routes/_site+/community/_community.tsx index 96c22b95..ceb9c5b9 100644 --- a/app/routes/_site+/community/_community.tsx +++ b/app/routes/_site+/community/_community.tsx @@ -1,6 +1,124 @@ -import type { MetaFunction } from "@remix-run/node"; +import type { LoaderFunctionArgs, MetaFunction } from "@remix-run/node"; import type { loader as siteLayoutLoader } from "~/routes/_site+/_layout"; +import { getSiteSlug } from "../_utils/getSiteSlug.server"; +import { json, useLoaderData } from "@remix-run/react"; +import { EditorView } from "~/routes/_editor+/core/components/EditorView"; +import { gqlFetch, gqlFormat } from "~/utils/fetchers.server"; +import { gql } from "graphql-request"; +import { cacheThis } from "~/utils/cache.server"; +import { Image } from "~/components/Image"; +import { Comment } from "~/db/payload-types"; +import { Icon } from "~/components/Icon"; +import { Link } from "@remix-run/react"; + +import { format, formatDistanceStrict } from "date-fns"; + +export async function loader({ + context: { payload, user }, + params, + request, +}: LoaderFunctionArgs) { + const { siteSlug } = await getSiteSlug(request, payload, user); + + const getSite = await cacheThis( + () => + payload.find({ + collection: "sites", + where: { + slug: { + equals: siteSlug, + }, + }, + depth: 0, + }), + `sites-slug-${siteSlug}`, + ); + + const siteId = getSite?.docs?.[0]?.id; + + const { comments } = await gqlFetch({ + isCustomDB: false, + isCached: true, + query: COMMENTS_QUERY, + request, + variables: { siteId }, + }); + + const parentIdsBySlug = comments.docs.reduce( + (acc, comment) => { + const slug = comment.parentSlug; + acc[slug] = acc[slug] || {}; + acc[slug][comment.parentId] = true; + return acc; + }, + {} as Record>, + ); + + const getParentQuery = (slug: string) => + slug === "posts" + ? PARENT_DATA_QUERY + : gql` + query ($parentIds: [String!]) { + docs: ${gqlFormat( + slug, + "list", + )}(where: { id: { in: $parentIds } }) { + docs { + id + name + slug + icon { + url + } + } + } + } + `; + + const parentData = await Promise.all( + Object.entries(parentIdsBySlug).map(([slug, idsObj]) => + gqlFetch({ + isCustomDB: slug !== "posts", + isCached: true, + query: getParentQuery(slug), + request, + variables: { parentIds: Object.keys(idsObj) }, + }), + ), + ); + + const parentMap = new Map( + parentData.flatMap( + (data, index) => + data.docs?.docs?.map((item: any) => [ + item.id, + { + id: item.id, + title: item.name, + icon: item.icon?.url, + slug: + Object.keys(parentIdsBySlug)[index] === "posts" + ? `/p/${item.slug}` + : `/c/${Object.keys(parentIdsBySlug)[index]}/${ + item.slug + }`, + }, + ]) ?? [], + ), + ); + + const enhancedComments = comments.docs.map((comment) => ({ + ...comment, + parent: parentMap.get(comment.parentId) || { + title: null, + icon: null, + slug: null, + }, + })); + + return json({ comments: enhancedComments }); +} export const meta: MetaFunction< null, @@ -19,13 +137,125 @@ export const meta: MetaFunction< }; export default function PostList() { + const { comments } = useLoaderData(); + console.log(comments); return (
-
-

Community

- +
+ {comments.length > 0 ? ( + <> +
+ + Latest Comments +
+
+ {comments.map((comment: Comment) => ( +
+ + {comment.parent.title} + +
+ + +
+
+
+ {comment?.author?.username + + {comment?.author?.username} + +
+ + + {formatDistanceStrict( + new Date(comment.updatedAt), + new Date(), + { addSuffix: true }, + )} + + {comment?.upVotesStatic && + comment.upVotesStatic > 0 && ( + <> + +
+
+ +
+ + {comment.upVotesStatic} + +
+ + )} +
+
+ ))} +
+ + ) : ( + "No comments yet" + )}
-
Coming soon!
); } + +const COMMENTS_QUERY = gql` + query ($siteId: JSON!) { + comments: Comments( + where: { site: { equals: $siteId } } + sort: "-updatedAt" + ) { + docs { + id + comment + updatedAt + upVotesStatic + parentId + parentSlug + author { + username + avatar { + url + } + } + } + } + } +`; + +const PARENT_DATA_QUERY = gql` + query ($parentIds: [String!]) { + docs: Posts(where: { id: { in: $parentIds } }) { + docs { + id + name + slug + } + } + } +`; diff --git a/app/routes/_user+/user+/account.tsx b/app/routes/_user+/user+/account.tsx index 0959bf73..23fcae2c 100644 --- a/app/routes/_user+/user+/account.tsx +++ b/app/routes/_user+/user+/account.tsx @@ -1,6 +1,6 @@ import { useEffect, useState } from "react"; -import { Transition } from "@headlessui/react"; +import { Label, Transition } from "@headlessui/react"; import { useFetcher } from "@remix-run/react"; import type { MetaFunction } from "@remix-run/react"; import type { ActionFunction } from "@remix-run/server-runtime"; @@ -24,6 +24,8 @@ import { import { useRootLoaderData } from "~/utils/useSiteLoaderData"; import { UserContainer } from "../components/UserContainer"; +import { Input } from "~/components/Input"; +import { Field } from "~/components/Fieldset"; const UserAccountSchema = z.object({ userAvatar: z.any().optional(), @@ -72,6 +74,10 @@ export default function UserAccount() { return ( + + + +