From d833b7ef81cbb64b58ee738712d0e05ce5de04ec Mon Sep 17 00:00:00 2001 From: Adrien KISSIE Date: Sun, 26 Nov 2023 10:48:29 +0100 Subject: [PATCH 01/71] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20add=20`in`=20filters?= =?UTF-8?q?=20at=20the=20end=20of=20the=20search=20filters?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/(models)/issues/search.ts | 38 +++++++++++++++---------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/src/app/(models)/issues/search.ts b/src/app/(models)/issues/search.ts index f2a4d40e..5102754c 100644 --- a/src/app/(models)/issues/search.ts +++ b/src/app/(models)/issues/search.ts @@ -245,28 +245,8 @@ function issueSearchfiltersToSQLConditions( includeStatusFilter: boolean = true, currentUser?: User | null ) { - const query = filters.query; let queryFilters: SQL | undefined = undefined; - if (!filters.in) { - filters.in = new Set(IN_FILTERS); - } - - if (filters.in) { - const inFilters = []; - const searchQuery = `%${query ?? ""}%`; - if (filters.in.has("title")) { - inFilters.push(ilike(issues.title, searchQuery)); - } - if (filters.in.has("body")) { - inFilters.push(ilike(issues.body, searchQuery)); - } - if (filters.in.has("comments")) { - inFilters.push(ilike(comments.content, searchQuery)); - } - queryFilters = or(...inFilters); - } - if (filters.author || filters["-author"]) { if (filters["-author"]) { // Handle `@me` author and replace it with the current authenticated user @@ -553,6 +533,24 @@ function issueSearchfiltersToSQLConditions( ); } + const query = filters.query; + if (!filters.in) { + filters.in = new Set(IN_FILTERS); + } + + const inFilters = []; + const searchQuery = `%${query ?? ""}%`; + if (filters.in.has("title")) { + inFilters.push(ilike(issues.title, searchQuery)); + } + if (filters.in.has("body")) { + inFilters.push(ilike(issues.body, searchQuery)); + } + if (filters.in.has("comments")) { + inFilters.push(ilike(comments.content, searchQuery)); + } + queryFilters = or(...inFilters); + return queryFilters; } From 6260310a5485e28debe6feef607423b27f41e68c Mon Sep 17 00:00:00 2001 From: Adrien KISSIE Date: Sun, 26 Nov 2023 11:53:11 +0100 Subject: [PATCH 02/71] =?UTF-8?q?=F0=9F=90=9B=20add=20missing=20and=20logi?= =?UTF-8?q?c=20with=20`in`=20filter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/(models)/issues/search.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/(models)/issues/search.ts b/src/app/(models)/issues/search.ts index 5102754c..5573d52c 100644 --- a/src/app/(models)/issues/search.ts +++ b/src/app/(models)/issues/search.ts @@ -549,7 +549,7 @@ function issueSearchfiltersToSQLConditions( if (filters.in.has("comments")) { inFilters.push(ilike(comments.content, searchQuery)); } - queryFilters = or(...inFilters); + queryFilters = and(queryFilters, or(...inFilters)); return queryFilters; } From 7c09305df00b502fd6711a4c97cf621e6f99a061 Mon Sep 17 00:00:00 2001 From: Adrien KISSIE Date: Sun, 26 Nov 2023 12:17:57 +0100 Subject: [PATCH 03/71] =?UTF-8?q?=F0=9F=92=84=20reduce=20font-size=20on=20?= =?UTF-8?q?settings=20page?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/(components)/avatar.tsx | 2 +- src/app/(components)/dropdown-menu.tsx | 6 +++--- src/app/(components)/vertical-nav-link.tsx | 2 +- src/app/(routes)/(app)/settings/account/page.tsx | 8 ++++---- src/app/(routes)/(app)/settings/appearance/page.tsx | 4 ++-- src/app/(routes)/(app)/settings/layout.tsx | 4 ++-- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/app/(components)/avatar.tsx b/src/app/(components)/avatar.tsx index b1b58918..afdc8d3d 100644 --- a/src/app/(components)/avatar.tsx +++ b/src/app/(components)/avatar.tsx @@ -25,7 +25,7 @@ export function Avatar({ { "h-3.5 w-3.5": size === "x-small", "h-5 w-5": size === "small", - "h-16 w-16": size === "large", + "h-14 w-14": size === "large", "h-8 w-8": size === "medium" }, className diff --git a/src/app/(components)/dropdown-menu.tsx b/src/app/(components)/dropdown-menu.tsx index 22145ae8..e040b3db 100644 --- a/src/app/(components)/dropdown-menu.tsx +++ b/src/app/(components)/dropdown-menu.tsx @@ -87,7 +87,7 @@ export function DropdownMenu({ items={items} > {(item) => ( - + {({ isHovered, isFocused, isPressed, isFocusVisible }) => { const Icon = item.icon; if (isDropdownMenuButton(item)) { @@ -107,7 +107,7 @@ export function DropdownMenu({ > {Icon && ( )} @@ -132,7 +132,7 @@ export function DropdownMenu({ > {Icon && ( )} diff --git a/src/app/(components)/vertical-nav-link.tsx b/src/app/(components)/vertical-nav-link.tsx index 3cfefffb..c6784e0e 100644 --- a/src/app/(components)/vertical-nav-link.tsx +++ b/src/app/(components)/vertical-nav-link.tsx @@ -28,7 +28,7 @@ export function VerticalNavLink({
-

+

Update your public profile

@@ -38,14 +38,14 @@ export default async function Page() {
-

+

Danger Zone

-

Delete your account

+

Delete your account

This will delete your mentions, comments and issues references in this website. It won’t have any effect on your real diff --git a/src/app/(routes)/(app)/settings/appearance/page.tsx b/src/app/(routes)/(app)/settings/appearance/page.tsx index 451f81e3..9eb2c75c 100644 --- a/src/app/(routes)/(app)/settings/appearance/page.tsx +++ b/src/app/(routes)/(app)/settings/appearance/page.tsx @@ -14,13 +14,13 @@ export const metadata: Metadata = { title: "Appearance" }; -export default async function Page() { +export default async function AppearanceSettingsPage() { await redirectIfNotAuthed("/settings/appearance"); const theme = await getTheme(); return (

-

+

Theme preferences

diff --git a/src/app/(routes)/(app)/settings/layout.tsx b/src/app/(routes)/(app)/settings/layout.tsx index e2ac98c3..cbaa99fc 100644 --- a/src/app/(routes)/(app)/settings/layout.tsx +++ b/src/app/(routes)/(app)/settings/layout.tsx @@ -27,8 +27,8 @@ export default async function SettingsLayout({
-

{user.username}

-

Your personnal account

+

{user.username}

+

Your personnal account

From cfa3f42295ce28d1c9f8f91e5b874dec929eaaa2 Mon Sep 17 00:00:00 2001 From: Adrien KISSIE Date: Mon, 27 Nov 2023 18:45:45 +0100 Subject: [PATCH 04/71] =?UTF-8?q?=F0=9F=8E=A8=20use=20biomejs=20as=20a=20f?= =?UTF-8?q?ormatter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- biome.json | 27 ++++++++++++++++++++++ src/app/(actions)/github.ts | 4 +--- src/app/(components)/markdown/index.tsx | 5 ++--- src/lib/server/kv/sqlite/config.ts | 4 ++-- src/lib/server/session.server.ts | 4 ++-- src/lib/shared/utils.shared.ts | 30 ++++++++++--------------- 6 files changed, 46 insertions(+), 28 deletions(-) create mode 100644 biome.json diff --git a/biome.json b/biome.json new file mode 100644 index 00000000..9b56d41c --- /dev/null +++ b/biome.json @@ -0,0 +1,27 @@ +{ + "linter": { + "enabled": false + }, + "formatter": { + "enabled": true, + "formatWithErrors": false, + "indentStyle": "tab", + "indentWidth": 2, + "lineWidth": 80, + "ignore": [] + }, + "javascript": { + "formatter": { + "arrowParentheses": "always", + "indentStyle": "space", + "trailingComma": "none", + "indentWidth": 2 + } + }, + "json": { + "formatter": { + "indentWidth": 2, + "indentStyle": "space" + } + } +} diff --git a/src/app/(actions)/github.ts b/src/app/(actions)/github.ts index f0a4fbde..a0bd1f5f 100644 --- a/src/app/(actions)/github.ts +++ b/src/app/(actions)/github.ts @@ -133,9 +133,7 @@ export const getGithubRepoData = cache(async function () { while (hasNextPage) { const { - repository: { - stargazers: { pageInfo, edges } - } + repository: { stargazers: { pageInfo, edges } } } = await fetchFromGithubAPI(stargazersQuery, { cursor: nextCursor, repoName: GITHUB_REPOSITORY_NAME, diff --git a/src/app/(components)/markdown/index.tsx b/src/app/(components)/markdown/index.tsx index b682a34e..b181dd2f 100644 --- a/src/app/(components)/markdown/index.tsx +++ b/src/app/(components)/markdown/index.tsx @@ -68,8 +68,7 @@ export async function MarkdownContent({ className, linkHeaders = false, editableCheckboxes = false, - repository: - currentRepository = `${GITHUB_AUTHOR_USERNAME}/${GITHUB_REPOSITORY_NAME}` + repository: currentRepository = `${GITHUB_AUTHOR_USERNAME}/${GITHUB_REPOSITORY_NAME}` }: MarkdownProps) { const dt = new Date().getTime(); console.time(`[${dt}] Markdown Rendering`); @@ -106,7 +105,7 @@ async function processMarkdownContentAndGetReferences( content: string, repository: string ) { - let references: Reference[] = []; + const references: Reference[] = []; // preprocess links & mentions const preprocessedContent = await remark() diff --git a/src/lib/server/kv/sqlite/config.ts b/src/lib/server/kv/sqlite/config.ts index c71b1888..2511c578 100644 --- a/src/lib/server/kv/sqlite/config.ts +++ b/src/lib/server/kv/sqlite/config.ts @@ -1,10 +1,10 @@ import type { Config } from "drizzle-kit"; -export default { +export default ({ schema: "./src/lib/kv/sqlite/kv-entry.sql.ts", driver: "turso", dbCredentials: { url: process.env.TURSO_DB_URL!, authToken: process.env.TURSO_DB_TOKEN! } -} satisfies Config; +} satisfies Config); diff --git a/src/lib/server/session.server.ts b/src/lib/server/session.server.ts index 871d7062..5ded61e5 100644 --- a/src/lib/server/session.server.ts +++ b/src/lib/server/session.server.ts @@ -226,8 +226,8 @@ export class Session { expiry: options?.isBot ? new Date(Date.now() + 5 * 1000) // only five seconds for temporary session : options?.init?.user - ? new Date(Date.now() + LOGGED_IN_SESSION_TTL * 1000) - : new Date(Date.now() + LOGGED_OUT_SESSION_TTL * 1000), + ? new Date(Date.now() + LOGGED_IN_SESSION_TTL * 1000) + : new Date(Date.now() + LOGGED_OUT_SESSION_TTL * 1000), signature, flashMessages: options?.init?.flashMessages, additionnalData: options?.init?.additionnalData, diff --git a/src/lib/shared/utils.shared.ts b/src/lib/shared/utils.shared.ts index 126c90f1..e5232c33 100644 --- a/src/lib/shared/utils.shared.ts +++ b/src/lib/shared/utils.shared.ts @@ -275,26 +275,20 @@ export function getExcerpt(str: string, maxChars: number): string { } const issueSearchFiltersSchema = z.object({ - in: preprocess( - (arg) => { - if (Array.isArray(arg)) { - return new Set(arg); - } - return arg; - }, - z.set(z.enum(IN_FILTERS)).catch(new Set(IN_FILTERS)).nullish() - ), + in: preprocess((arg) => { + if (Array.isArray(arg)) { + return new Set(arg); + } + return arg; + }, z.set(z.enum(IN_FILTERS)).catch(new Set(IN_FILTERS)).nullish()), is: z.enum(STATUS_FILTERS).default("open").nullish().catch(null), reason: z.enum(REASON_FILTERS).nullish().catch(null), - no: preprocess( - (arg) => { - if (Array.isArray(arg)) { - return [...new Set(arg)]; - } - return arg; - }, - z.array(z.enum(NO_METADATA_FILTERS)).catch([]).default([]).nullish() - ), + no: preprocess((arg) => { + if (Array.isArray(arg)) { + return [...new Set(arg)]; + } + return arg; + }, z.array(z.enum(NO_METADATA_FILTERS)).catch([]).default([]).nullish()), label: z.array(z.string()).catch([]).default([]).nullish(), "-label": z.array(z.string()).catch([]).default([]).nullish(), assignee: z.array(z.string()).catch([]).default([]).nullish(), From e532e3cbca0bd9c450099d2a7ee64ba99ca7cfc0 Mon Sep 17 00:00:00 2001 From: Adrien KISSIE Date: Fri, 1 Dec 2023 02:59:37 +0100 Subject: [PATCH 05/71] =?UTF-8?q?=F0=9F=9A=A7=20some=20things?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/(routes)/(app)/[user]/[repository]/page.tsx | 1 + src/lib/types.ts | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/app/(routes)/(app)/[user]/[repository]/page.tsx b/src/app/(routes)/(app)/[user]/[repository]/page.tsx index c64e3d88..55ff8f7b 100644 --- a/src/app/(routes)/(app)/[user]/[repository]/page.tsx +++ b/src/app/(routes)/(app)/[user]/[repository]/page.tsx @@ -285,6 +285,7 @@ async function RepositoryHomePageContent({ href={repositoryData.url} target="_blank" className="font-semibold text-accent" + rel="noreferrer" > {repositoryData.url} diff --git a/src/lib/types.ts b/src/lib/types.ts index 509d6702..f732e870 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -1,5 +1,5 @@ export type PageProps< - TParams extends Record = {}, + TParams extends Record = {}, TSearchParams extends Record = {} > = { params: TParams; @@ -51,7 +51,7 @@ export type Prettify = { } & {}; export type FormState< - TFormData extends unknown = Record + TFormData = Record > = | { type: "success"; From 9ecaa8f678d67550dcc3e7883490c31fc932f75c Mon Sep 17 00:00:00 2001 From: Adrien KISSIE Date: Sun, 3 Dec 2023 01:09:10 +0100 Subject: [PATCH 06/71] =?UTF-8?q?=F0=9F=9A=9A=20move=20client=20providers?= =?UTF-8?q?=20to=20home?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/client-providers.tsx | 19 +++++++++++++++++++ src/app/layout.tsx | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 src/app/client-providers.tsx diff --git a/src/app/client-providers.tsx b/src/app/client-providers.tsx new file mode 100644 index 00000000..fd25b5a8 --- /dev/null +++ b/src/app/client-providers.tsx @@ -0,0 +1,19 @@ +// app/provider.tsx +"use client"; +import * as React from "react"; +// components +import { RouterProvider } from "react-aria-components"; +import { ReactQueryProvider } from "~/app/(components)/react-query-provider"; + +// utils +import { useRouter } from "next/navigation"; + +export function ClientProviders({ children }: { children: React.ReactNode }) { + const router = useRouter(); + + return ( + + {children} + + ); +} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 906422af..dea44ac8 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -8,6 +8,7 @@ import { IconSwitcher } from "~/app/(components)/icon-switcher"; import { TopLoader } from "~/app/(components)/top-loader"; import { SkipToMainButton } from "~/app/(components)/skip-to-main-button"; import { XMasDecorations } from "~/app/(components)/x-mas-decorations"; +import { ClientProviders } from "~/app/client-providers"; // utils import { GeistSans } from "geist/font"; @@ -16,7 +17,6 @@ import { clsx } from "~/lib/shared/utils.shared"; // types import type { Metadata } from "next"; -import { ClientProviders } from "~/app/(components)/providers"; export const metadata: Metadata = { title: { From 804546b175bce979146fd9f1e1262ae20428ca35 Mon Sep 17 00:00:00 2001 From: Adrien KISSIE Date: Sun, 3 Dec 2023 01:18:08 +0100 Subject: [PATCH 07/71] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20some=20refactors?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/(actions)/issue.tsx | 4 +--- .../(components)/hovercard/issue-hovercard-contents.tsx | 7 +++---- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/app/(actions)/issue.tsx b/src/app/(actions)/issue.tsx index 2ebe379f..76504f94 100644 --- a/src/app/(actions)/issue.tsx +++ b/src/app/(actions)/issue.tsx @@ -5,8 +5,7 @@ import { getIssueAssigneesByUsername, getIssueAssigneesByUsernameOrName, getIssueAuthorsByName, - getIssueAuthorsByUsername, - getSingleIssue + getIssueAuthorsByUsername } from "~/app/(models)/issues"; import { AsyncIssueHoverCardContents } from "~/app/(components)/hovercard/async-issue-hovercard-contents"; @@ -14,7 +13,6 @@ import { issueSearchListOutputValidator } from "~/app/(models)/dto/issue-search- import { searchIssues } from "~/app/(models)/issues/search"; import { getAuthedUser } from "./auth"; -import { cache } from "react"; import type { IssueSearchFilters } from "~/lib/shared/utils.shared"; diff --git a/src/app/(components)/hovercard/issue-hovercard-contents.tsx b/src/app/(components)/hovercard/issue-hovercard-contents.tsx index d9d9d88e..e6ba7c3d 100644 --- a/src/app/(components)/hovercard/issue-hovercard-contents.tsx +++ b/src/app/(components)/hovercard/issue-hovercard-contents.tsx @@ -6,8 +6,9 @@ import { SkipIcon } from "@primer/octicons-react"; import Link from "next/link"; -import { LabelBadge } from "../label-badge"; +import { LabelBadge } from "~/app/(components)/label-badge"; import { Avatar } from "~/app/(components)/avatar"; +import { Skeleton } from "~/app/(components)/skeleton"; // utils import { formatDate } from "~/lib/shared/utils.shared"; @@ -15,9 +16,7 @@ import { IssueStatuses } from "~/lib/server/db/schema/issue.sql"; // types import type { IssueStatus } from "~/lib/server/db/schema/issue.sql"; -import { labels, type Label } from "~/lib/server/db/schema/label.sql"; -import { Skeleton } from "~/app/(components)/skeleton"; -import { title } from "process"; +import type { Label } from "~/lib/server/db/schema/label.sql"; export type IssueHoverCardContentsProps = { id: number; From 2337196220fcc4743224c70a82ff05a2b140c718 Mon Sep 17 00:00:00 2001 From: Adrien KISSIE Date: Sun, 3 Dec 2023 02:09:52 +0100 Subject: [PATCH 08/71] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20set=20default=20cach?= =?UTF-8?q?e=20ttl=20to=207=20days=20&=20allow=20explicit=20caching=20in?= =?UTF-8?q?=20dev?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/(components)/cache/cache.server.tsx | 23 ++++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/app/(components)/cache/cache.server.tsx b/src/app/(components)/cache/cache.server.tsx index c10f7ff6..dc9b2620 100644 --- a/src/app/(components)/cache/cache.server.tsx +++ b/src/app/(components)/cache/cache.server.tsx @@ -9,6 +9,7 @@ import { CacheClient } from "~/app/(components)/cache/cache.client"; import { getClientManifest } from "~/app/(components)/cache/manifest"; import { cache } from "react"; import { kv } from "~/lib/server/kv/index.server"; +import { DEFAULT_CACHE_TTL } from "~/lib/shared/constants"; import fs from "fs/promises"; // types @@ -31,17 +32,23 @@ export type CacheProps = { export async function Cache({ id, ttl, - bypass = false, + bypass, debug = false, children, updatedAt }: CacheProps) { - if (bypass || process.env.NODE_ENV === "development") { + const fullKey = await computeCacheKey(id, updatedAt); + + if ( + bypass || + (bypass === undefined && process.env.NODE_ENV === "development") + ) { + console.log( + `\x1b[90mBYPASSING CACHE FOR key "\x1b[33m${fullKey}\x1b[90m"\x1b[37m` + ); return <>{children}; } - const fullKey = await computeCacheKey(id, updatedAt); - let cachedPayload = await kv.get<{ rsc: string; }>(fullKey); @@ -60,7 +67,7 @@ export async function Cache({ cachedPayload = { rsc: await transformStreamToString(rscStream) }; - await kv.set(fullKey, cachedPayload, ttl); + await kv.set(fullKey, cachedPayload, ttl ?? DEFAULT_CACHE_TTL); } if (debug) { @@ -100,11 +107,11 @@ async function computeCacheKey(id: CacheId, updatedAt?: Date | number) { let fullKey = Array.isArray(id) ? id.join("-") : id.toString(); // we also get encode the const buildId = await getBuildId(); - if (buildId) { - fullKey += `${buildId}-`; - } if (updatedAt) { fullKey += `-${new Date(updatedAt).getTime()}`; } + if (buildId) { + fullKey += `-${buildId}`; + } return fullKey; } From 77fcfa9e6976bca55509c3a76253087bd883b81f Mon Sep 17 00:00:00 2001 From: Adrien KISSIE Date: Sun, 3 Dec 2023 02:15:25 +0100 Subject: [PATCH 09/71] =?UTF-8?q?=F0=9F=9A=9A=20move=20markdown=20into=20i?= =?UTF-8?q?ts=20own=20file=20(too=20annoying=20to=20grep)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/(components)/markdown/{index.tsx => markdown.tsx} | 0 .../(routes)/(app)/[user]/[repository]/issues/[number]/page.tsx | 2 +- src/app/(routes)/(app)/[user]/[repository]/page.tsx | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename src/app/(components)/markdown/{index.tsx => markdown.tsx} (100%) diff --git a/src/app/(components)/markdown/index.tsx b/src/app/(components)/markdown/markdown.tsx similarity index 100% rename from src/app/(components)/markdown/index.tsx rename to src/app/(components)/markdown/markdown.tsx diff --git a/src/app/(routes)/(app)/[user]/[repository]/issues/[number]/page.tsx b/src/app/(routes)/(app)/[user]/[repository]/issues/[number]/page.tsx index f8891d48..329a9ace 100644 --- a/src/app/(routes)/(app)/[user]/[repository]/issues/[number]/page.tsx +++ b/src/app/(routes)/(app)/[user]/[repository]/issues/[number]/page.tsx @@ -2,7 +2,7 @@ import "server-only"; // components import { MarkdownTitle } from "~/app/(components)/markdown/markdown-title"; -import { Markdown } from "~/app/(components)/markdown"; +import { Markdown } from "~/app/(components)/markdown/markdown"; import { Cache } from "~/app/(components)/cache/cache.server"; // utils diff --git a/src/app/(routes)/(app)/[user]/[repository]/page.tsx b/src/app/(routes)/(app)/[user]/[repository]/page.tsx index 8bfcf12b..caa29432 100644 --- a/src/app/(routes)/(app)/[user]/[repository]/page.tsx +++ b/src/app/(routes)/(app)/[user]/[repository]/page.tsx @@ -17,7 +17,7 @@ import { Avatar } from "~/app/(components)/avatar"; import { Badge } from "~/app/(components)/badge"; import { CounterBadge } from "~/app/(components)/counter-badge"; import { Button } from "~/app/(components)/button"; -import { Markdown } from "~/app/(components)/markdown"; +import { Markdown } from "~/app/(components)/markdown/markdown"; import Link from "next/link"; import { Cache } from "~/app/(components)/cache/cache.server"; import { Skeleton } from "~/app/(components)/skeleton"; From 0b54a2d302c48ea1e5a30879367444b5fbd781af Mon Sep 17 00:00:00 2001 From: Adrien KISSIE Date: Sun, 3 Dec 2023 02:15:51 +0100 Subject: [PATCH 10/71] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20changed=20the=20defa?= =?UTF-8?q?ult=20cache=20TTL=20to=207=20days?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib/shared/constants.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/shared/constants.ts b/src/lib/shared/constants.ts index eb434c8d..3d8c18d8 100644 --- a/src/lib/shared/constants.ts +++ b/src/lib/shared/constants.ts @@ -3,7 +3,7 @@ export const SESSION_COOKIE_KEY = "__id"; export const LOGGED_OUT_SESSION_TTL = 1 * 24 * 60 * 60; // 1 day in seconds export const LOGGED_IN_SESSION_TTL = 2 * 24 * 60 * 60; // 2 days in seconds -export const DEFAULT_CACHE_TTL = 1 * 24 * 60 * 60; // 1 day in seconds +export const DEFAULT_CACHE_TTL = 7 * 24 * 60 * 60; // 7 day in seconds export const GITHUB_REPOSITORY_CACHE_KEY = "github:repository"; export const GITHUB_AUTHOR_USERNAME = "Fredkiss3"; From d82015a7a27dfe13f3a4ccec65d405093a4a41d7 Mon Sep 17 00:00:00 2001 From: Adrien KISSIE Date: Sun, 3 Dec 2023 04:57:27 +0100 Subject: [PATCH 11/71] =?UTF-8?q?=F0=9F=92=A1=20some=20comments?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/(components)/cache/cache.server.tsx | 6 ++++-- src/app/(components)/markdown/markdown.tsx | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/app/(components)/cache/cache.server.tsx b/src/app/(components)/cache/cache.server.tsx index dc9b2620..94fbc3c1 100644 --- a/src/app/(components)/cache/cache.server.tsx +++ b/src/app/(components)/cache/cache.server.tsx @@ -105,11 +105,13 @@ export const getBuildId = cache(async () => { async function computeCacheKey(id: CacheId, updatedAt?: Date | number) { let fullKey = Array.isArray(id) ? id.join("-") : id.toString(); - // we also get encode the - const buildId = await getBuildId(); if (updatedAt) { fullKey += `-${new Date(updatedAt).getTime()}`; } + // the build ID is necessary because the client references for one build + // won't necessarily be the same for another build, especially if the component + // changed in the meantime + const buildId = await getBuildId(); if (buildId) { fullKey += `-${buildId}`; } diff --git a/src/app/(components)/markdown/markdown.tsx b/src/app/(components)/markdown/markdown.tsx index d9ce77f1..ee403f42 100644 --- a/src/app/(components)/markdown/markdown.tsx +++ b/src/app/(components)/markdown/markdown.tsx @@ -68,7 +68,8 @@ export async function MarkdownContent({ className, linkHeaders = false, editableCheckboxes = false, - repository: currentRepository = `${GITHUB_AUTHOR_USERNAME}/${GITHUB_REPOSITORY_NAME}` + repository: + currentRepository = `${GITHUB_AUTHOR_USERNAME}/${GITHUB_REPOSITORY_NAME}` }: MarkdownProps) { const dt = new Date().getTime(); From 3f407e573d8974de1126b62c6bf18f74c06c65e9 Mon Sep 17 00:00:00 2001 From: Adrien KISSIE Date: Sun, 3 Dec 2023 21:51:38 +0100 Subject: [PATCH 12/71] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20small=20refactor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/(components)/user-dropdown/user-dropdown.client.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/(components)/user-dropdown/user-dropdown.client.tsx b/src/app/(components)/user-dropdown/user-dropdown.client.tsx index a9d27fc4..220d6586 100644 --- a/src/app/(components)/user-dropdown/user-dropdown.client.tsx +++ b/src/app/(components)/user-dropdown/user-dropdown.client.tsx @@ -2,7 +2,7 @@ import * as React from "react"; import * as ReactDOM from "react-dom"; // components -import { DropdownMenu } from "../dropdown-menu"; +import { DropdownMenu } from "~/app/(components)/dropdown-menu"; import { Avatar } from "~/app/(components)/avatar"; import { PaintbrushIcon, @@ -20,7 +20,7 @@ export type UserDropdownProps = { }; export function UserDropdown({ avatar_url, username }: UserDropdownProps) { - const [_, startTransition] = React.useTransition(); + const [, startTransition] = React.useTransition(); const [injectStyles, setInjectStyles] = React.useState(false); React.useEffect(() => { From eb3f25ea9ef8620fda459920f8828386feb332a2 Mon Sep 17 00:00:00 2001 From: Adrien KISSIE Date: Sun, 3 Dec 2023 21:52:06 +0100 Subject: [PATCH 13/71] =?UTF-8?q?=F0=9F=94=A7=20don't=20include=20node=5Fm?= =?UTF-8?q?odules=20symbols=20in=20search?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/settings.json | 4 +++- package.json | 4 ++-- pnpm-lock.yaml | 51 +++++++++++++++++++++---------------------- 3 files changed, 30 insertions(+), 29 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 97fa2b8f..ce83cc65 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,5 @@ { - "typescript.preferences.importModuleSpecifier": "non-relative" + "typescript.preferences.importModuleSpecifier": "non-relative", + "typescript.workspaceSymbols.excludeLibrarySymbols": true, + "typescript.tsdk": "node_modules/typescript/lib" } diff --git a/package.json b/package.json index 08598432..a381c93b 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,6 @@ "server-only": "^0.0.1", "sharp": "^0.32.5", "tailwind-merge": "^1.14.0", - "typescript": "5.2.2", "vfile": "^6.0.1", "zod": "^3.22.2", "zod-form-data": "^2.0.1", @@ -74,7 +73,8 @@ "prettier": "^3.0.3", "prettier-plugin-tailwindcss": "^0.5.4", "tailwindcss": "3.3.3", - "tsx": "^3.12.8" + "tsx": "^3.12.8", + "typescript": "5.3.2" }, "pnpm": { "patchedDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d14480bb..ce4041a4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -21,7 +21,7 @@ dependencies: version: 19.8.0(react@18.2.0) '@t3-oss/env-nextjs': specifier: ^0.6.1 - version: 0.6.1(typescript@5.2.2)(zod@3.22.2) + version: 0.6.1(typescript@5.3.2)(zod@3.22.2) '@tanstack/react-query': specifier: ^5.0.0 version: 5.0.0(react-dom@18.2.0)(react@18.2.0) @@ -45,7 +45,7 @@ dependencies: version: 8.48.0 eslint-config-next: specifier: 14.0.0 - version: 14.0.0(eslint@8.48.0)(typescript@5.2.2) + version: 14.0.0(eslint@8.48.0)(typescript@5.3.2) geist: specifier: ^1.0.0 version: 1.0.0 @@ -112,9 +112,6 @@ dependencies: tailwind-merge: specifier: ^1.14.0 version: 1.14.0 - typescript: - specifier: 5.2.2 - version: 5.2.2 vfile: specifier: ^6.0.1 version: 6.0.1 @@ -174,6 +171,9 @@ devDependencies: tsx: specifier: ^3.12.8 version: 3.13.0 + typescript: + specifier: 5.3.2 + version: 5.3.2 packages: @@ -2180,24 +2180,24 @@ packages: tslib: 2.6.2 dev: false - /@t3-oss/env-core@0.6.1(typescript@5.2.2)(zod@3.22.2): + /@t3-oss/env-core@0.6.1(typescript@5.3.2)(zod@3.22.2): resolution: {integrity: sha512-KQD7qEDJtkWIWWmTVjNvk0wnHpkvAQ6CRbUxbWMFNG/fiosBQDQvtRpBNu6USxBscJCoC4z6y7P9MN52/mLOzw==} peerDependencies: typescript: '>=4.7.2' zod: ^3.0.0 dependencies: - typescript: 5.2.2 + typescript: 5.3.2 zod: 3.22.2 dev: false - /@t3-oss/env-nextjs@0.6.1(typescript@5.2.2)(zod@3.22.2): + /@t3-oss/env-nextjs@0.6.1(typescript@5.3.2)(zod@3.22.2): resolution: {integrity: sha512-z1dIC++Vxj9kmzX5nSPfcrCSkszy3dTEPC4Ssx7Ap5AqR3c2Qa7S0xf8axn6coy7D/vCXDAAnHYnCMDhtcY3SQ==} peerDependencies: typescript: '>=4.7.2' zod: ^3.0.0 dependencies: - '@t3-oss/env-core': 0.6.1(typescript@5.2.2)(zod@3.22.2) - typescript: 5.2.2 + '@t3-oss/env-core': 0.6.1(typescript@5.3.2)(zod@3.22.2) + typescript: 5.3.2 zod: 3.22.2 dev: false @@ -2329,7 +2329,7 @@ packages: resolution: {integrity: sha512-ue/hDUpPjC85m+PM9OQDMZr3LywT+CT6mPsQq8OJtCLiERkGRcQUFvu9XASF5XWqyZFXbf15lvb3JFJ4dRLWPg==} dev: false - /@typescript-eslint/parser@6.7.3(eslint@8.48.0)(typescript@5.2.2): + /@typescript-eslint/parser@6.7.3(eslint@8.48.0)(typescript@5.3.2): resolution: {integrity: sha512-TlutE+iep2o7R8Lf+yoer3zU6/0EAUc8QIBB3GYBc1KGz4c4TRm83xwXUZVPlZ6YCLss4r77jbu6j3sendJoiQ==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: @@ -2341,11 +2341,11 @@ packages: dependencies: '@typescript-eslint/scope-manager': 6.7.3 '@typescript-eslint/types': 6.7.3 - '@typescript-eslint/typescript-estree': 6.7.3(typescript@5.2.2) + '@typescript-eslint/typescript-estree': 6.7.3(typescript@5.3.2) '@typescript-eslint/visitor-keys': 6.7.3 debug: 4.3.4 eslint: 8.48.0 - typescript: 5.2.2 + typescript: 5.3.2 transitivePeerDependencies: - supports-color dev: false @@ -2363,7 +2363,7 @@ packages: engines: {node: ^16.0.0 || >=18.0.0} dev: false - /@typescript-eslint/typescript-estree@6.7.3(typescript@5.2.2): + /@typescript-eslint/typescript-estree@6.7.3(typescript@5.3.2): resolution: {integrity: sha512-YLQ3tJoS4VxLFYHTw21oe1/vIZPRqAO91z6Uv0Ss2BKm/Ag7/RVQBcXTGcXhgJMdA4U+HrKuY5gWlJlvoaKZ5g==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: @@ -2378,8 +2378,8 @@ packages: globby: 11.1.0 is-glob: 4.0.3 semver: 7.5.4 - ts-api-utils: 1.0.3(typescript@5.2.2) - typescript: 5.2.2 + ts-api-utils: 1.0.3(typescript@5.3.2) + typescript: 5.3.2 transitivePeerDependencies: - supports-color dev: false @@ -3300,7 +3300,7 @@ packages: engines: {node: '>=12'} dev: false - /eslint-config-next@14.0.0(eslint@8.48.0)(typescript@5.2.2): + /eslint-config-next@14.0.0(eslint@8.48.0)(typescript@5.3.2): resolution: {integrity: sha512-jtXeE+/pGQ3h9n11QyyuPN50kO13GO5XvjU5ZRq6W+XTpOMjyobWmK2s7aowy0FtzA49krJzYzEU9s1RMwoJ6g==} peerDependencies: eslint: ^7.23.0 || ^8.0.0 @@ -3311,7 +3311,7 @@ packages: dependencies: '@next/eslint-plugin-next': 14.0.0 '@rushstack/eslint-patch': 1.5.0 - '@typescript-eslint/parser': 6.7.3(eslint@8.48.0)(typescript@5.2.2) + '@typescript-eslint/parser': 6.7.3(eslint@8.48.0)(typescript@5.3.2) eslint: 8.48.0 eslint-import-resolver-node: 0.3.9 eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.7.3)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.28.1)(eslint@8.48.0) @@ -3319,7 +3319,7 @@ packages: eslint-plugin-jsx-a11y: 6.7.1(eslint@8.48.0) eslint-plugin-react: 7.33.2(eslint@8.48.0) eslint-plugin-react-hooks: 4.6.0(eslint@8.48.0) - typescript: 5.2.2 + typescript: 5.3.2 transitivePeerDependencies: - eslint-import-resolver-webpack - supports-color @@ -3379,7 +3379,7 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: - '@typescript-eslint/parser': 6.7.3(eslint@8.48.0)(typescript@5.2.2) + '@typescript-eslint/parser': 6.7.3(eslint@8.48.0)(typescript@5.3.2) debug: 3.2.7 eslint: 8.48.0 eslint-import-resolver-node: 0.3.9 @@ -3398,7 +3398,7 @@ packages: '@typescript-eslint/parser': optional: true dependencies: - '@typescript-eslint/parser': 6.7.3(eslint@8.48.0)(typescript@5.2.2) + '@typescript-eslint/parser': 6.7.3(eslint@8.48.0)(typescript@5.3.2) array-includes: 3.1.7 array.prototype.findlastindex: 1.2.3 array.prototype.flat: 1.3.2 @@ -6493,13 +6493,13 @@ packages: resolution: {integrity: sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==} dev: false - /ts-api-utils@1.0.3(typescript@5.2.2): + /ts-api-utils@1.0.3(typescript@5.3.2): resolution: {integrity: sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==} engines: {node: '>=16.13.0'} peerDependencies: typescript: '>=4.2.0' dependencies: - typescript: 5.2.2 + typescript: 5.3.2 dev: false /ts-interface-checker@0.1.13: @@ -6594,11 +6594,10 @@ packages: is-typed-array: 1.1.12 dev: false - /typescript@5.2.2: - resolution: {integrity: sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==} + /typescript@5.3.2: + resolution: {integrity: sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==} engines: {node: '>=14.17'} hasBin: true - dev: false /unbox-primitive@1.0.2: resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} From 4c0e028dd7ccd5a18fe9cb63d6cb48fb6c329590 Mon Sep 17 00:00:00 2001 From: Adrien KISSIE Date: Mon, 4 Dec 2023 03:53:26 +0100 Subject: [PATCH 14/71] =?UTF-8?q?=F0=9F=94=A5=20remove=20new=20issue=20ico?= =?UTF-8?q?n=20from=20header?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{icon-switcher.tsx => favicon-switcher.tsx} | 2 +- src/app/(components)/header/index.tsx | 12 ------------ src/app/layout.tsx | 4 ++-- 3 files changed, 3 insertions(+), 15 deletions(-) rename src/app/(components)/{icon-switcher.tsx => favicon-switcher.tsx} (96%) diff --git a/src/app/(components)/icon-switcher.tsx b/src/app/(components)/favicon-switcher.tsx similarity index 96% rename from src/app/(components)/icon-switcher.tsx rename to src/app/(components)/favicon-switcher.tsx index ff8f5689..af0047f3 100644 --- a/src/app/(components)/icon-switcher.tsx +++ b/src/app/(components)/favicon-switcher.tsx @@ -16,7 +16,7 @@ function updateIcons(theme: Theme) { } } -export function IconSwitcher() { +export function FavIconSwitcher() { React.useEffect(() => { const darkQuery = window.matchMedia("(prefers-color-scheme: dark)"); diff --git a/src/app/(components)/header/index.tsx b/src/app/(components)/header/index.tsx index 04524e7d..e92a9d27 100644 --- a/src/app/(components)/header/index.tsx +++ b/src/app/(components)/header/index.tsx @@ -7,7 +7,6 @@ import { InboxIcon, IssueOpenedIcon, MarkGithubIcon, - PlusIcon, SearchIcon } from "@primer/octicons-react"; import Link from "next/link"; @@ -72,17 +71,6 @@ export async function Header({ children, pageTitle }: HeaderProps) { />
    -
  • - -
  • -
  • -
- - ); -} diff --git a/src/app/not-found.tsx b/src/app/not-found.tsx index 2d247a2f..e7b263e1 100644 --- a/src/app/not-found.tsx +++ b/src/app/not-found.tsx @@ -3,13 +3,21 @@ import { HomeIcon } from "@primer/octicons-react"; import { Button } from "~/app/(components)/button"; import type { Metadata } from "next"; + export const metadata: Metadata = { - title: "Page not found - Fredkiss3/gh-next" + title: "Page not found" }; export default function RootNotFound() { return ( <> + {/* + FIXME: this is a fix because nextjs considers the metadata on the children layouts + over the metadata set here, even though this is on top of the layout + So this way we manually overwrites the title above with a title inside + */} + Page not found · gh-next +
Date: Mon, 4 Dec 2023 07:30:45 +0100 Subject: [PATCH 17/71] =?UTF-8?q?=F0=9F=9A=A7=20new=20issue=20page?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 + pnpm-lock.yaml | 249 +++++++++++++++++- src/app/(components)/input.tsx | 3 +- .../issues/markdown-text-area.tsx | 96 +++++++ .../(components)/issues/new-issue-form.tsx | 60 +++++ src/app/(components)/textarea.tsx | 10 +- .../[user]/[repository]/issues/new/page.tsx | 42 ++- .../(app)/[user]/[repository]/layout.tsx | 4 +- 8 files changed, 453 insertions(+), 12 deletions(-) create mode 100644 src/app/(components)/issues/markdown-text-area.tsx create mode 100644 src/app/(components)/issues/new-issue-form.tsx diff --git a/package.json b/package.json index a381c93b..1bf70046 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "@headlessui/react": "^1.7.17", "@mdx-js/mdx": "^3.0.0", "@primer/octicons-react": "^19.7.0", + "@radix-ui/react-tabs": "^1.0.4", "@t3-oss/env-nextjs": "^0.6.1", "@tanstack/react-query": "^5.0.0", "bright": "^0.8.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ce4041a4..3b0e7003 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -19,6 +19,9 @@ dependencies: '@primer/octicons-react': specifier: ^19.7.0 version: 19.8.0(react@18.2.0) + '@radix-ui/react-tabs': + specifier: ^1.0.4 + version: 1.0.4(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0) '@t3-oss/env-nextjs': specifier: ^0.6.1 version: 0.6.1(typescript@5.3.2)(zod@3.22.2) @@ -738,6 +741,36 @@ packages: '@babel/runtime': 7.23.1 dev: false + /@radix-ui/primitive@1.0.1: + resolution: {integrity: sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw==} + dependencies: + '@babel/runtime': 7.23.1 + dev: false + + /@radix-ui/react-collection@1.0.3(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.1 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.37)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.37)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-slot': 1.0.2(@types/react@18.2.37)(react@18.2.0) + '@types/react': 18.2.37 + '@types/react-dom': 18.2.15 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-compose-refs@1.0.0(react@18.2.0): resolution: {integrity: sha512-0KaSv6sx787/hK3eF53iOkiSLwAGlFMx5lotrqD2pTjB18KbybKoEIgkNZTKC60YECDQTKGTRcDBILwZVqVKvA==} peerDependencies: @@ -747,6 +780,20 @@ packages: react: 18.2.0 dev: false + /@radix-ui/react-compose-refs@1.0.1(@types/react@18.2.37)(react@18.2.0): + resolution: {integrity: sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.23.1 + '@types/react': 18.2.37 + react: 18.2.0 + dev: false + /@radix-ui/react-context@1.0.0(react@18.2.0): resolution: {integrity: sha512-1pVM9RfOQ+n/N5PJK33kRSKsr1glNxomxONs5c49MliinBY6Yw2Q995qfBUUo0/Mbg05B/sGA0gkgPI7kmSHBg==} peerDependencies: @@ -756,6 +803,20 @@ packages: react: 18.2.0 dev: false + /@radix-ui/react-context@1.0.1(@types/react@18.2.37)(react@18.2.0): + resolution: {integrity: sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.23.1 + '@types/react': 18.2.37 + react: 18.2.0 + dev: false + /@radix-ui/react-dialog@1.0.0(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-Yn9YU+QlHYLWwV1XfKiqnGVpWYWk6MeBVM6x/bcoyPvxgjQGoeT35482viLPctTMWoMw0PoHgqfSox7Ig+957Q==} peerDependencies: @@ -783,6 +844,20 @@ packages: - '@types/react' dev: false + /@radix-ui/react-direction@1.0.1(@types/react@18.2.37)(react@18.2.0): + resolution: {integrity: sha512-RXcvnXgyvYvBEOhCBuddKecVkoMiI10Jcm5cTI7abJRAHYfFxeu+FBQs/DvdxSYucxR5mna0dNsL6QFlds5TMA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.23.1 + '@types/react': 18.2.37 + react: 18.2.0 + dev: false + /@radix-ui/react-dismissable-layer@1.0.0(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-n7kDRfx+LB1zLueRDvZ1Pd0bxdJWDUZNQ/GWoxDn2prnuJKRdxsjulejX/ePkOsLi2tTm6P24mDqlMSgQpsT6g==} peerDependencies: @@ -832,6 +907,21 @@ packages: react: 18.2.0 dev: false + /@radix-ui/react-id@1.0.1(@types/react@18.2.37)(react@18.2.0): + resolution: {integrity: sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.23.1 + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.37)(react@18.2.0) + '@types/react': 18.2.37 + react: 18.2.0 + dev: false + /@radix-ui/react-portal@1.0.0(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-a8qyFO/Xb99d8wQdu4o7qnigNjTPG123uADNecz0eX4usnQEj7o+cG4ZX4zkqq98NYekT7UoEQIjxBNWIFuqTA==} peerDependencies: @@ -857,6 +947,28 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false + /@radix-ui/react-presence@1.0.1(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.1 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.37)(react@18.2.0) + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.37)(react@18.2.0) + '@types/react': 18.2.37 + '@types/react-dom': 18.2.15 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-primitive@1.0.0(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-EyXe6mnRlHZ8b6f4ilTDrXmkLShICIuOTTj0GX4w1rp+wSxf3+TD05u1UOITC8VsJ2a9nwHvdXtOXEOl0Cw/zQ==} peerDependencies: @@ -869,6 +981,56 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false + /@radix-ui/react-primitive@1.0.3(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.1 + '@radix-ui/react-slot': 1.0.2(@types/react@18.2.37)(react@18.2.0) + '@types/react': 18.2.37 + '@types/react-dom': 18.2.15 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@radix-ui/react-roving-focus@1.0.4(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-2mUg5Mgcu001VkGy+FfzZyzbmuUWzgWkj3rvv4yu+mLw03+mTzbxZHvfcGyFp2b8EkQeMkpRQ5FiA2Vr2O6TeQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.1 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-collection': 1.0.3(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.37)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.37)(react@18.2.0) + '@radix-ui/react-direction': 1.0.1(@types/react@18.2.37)(react@18.2.0) + '@radix-ui/react-id': 1.0.1(@types/react@18.2.37)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.37)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.37)(react@18.2.0) + '@types/react': 18.2.37 + '@types/react-dom': 18.2.15 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-slot@1.0.0(react@18.2.0): resolution: {integrity: sha512-3mrKauI/tWXo1Ll+gN5dHcxDPdm/Df1ufcDLCecn+pnCIVcdWE7CujXo8QaXOWRJyZyQWWbpB8eFwHzWXlv5mQ==} peerDependencies: @@ -879,6 +1041,49 @@ packages: react: 18.2.0 dev: false + /@radix-ui/react-slot@1.0.2(@types/react@18.2.37)(react@18.2.0): + resolution: {integrity: sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.23.1 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.37)(react@18.2.0) + '@types/react': 18.2.37 + react: 18.2.0 + dev: false + + /@radix-ui/react-tabs@1.0.4(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-egZfYY/+wRNCflXNHx+dePvnz9FbmssDTJBtgRfDY7e8SE5oIo3Py2eCB1ckAbh1Q7cQ/6yJZThJ++sgbxibog==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.1 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-context': 1.0.1(@types/react@18.2.37)(react@18.2.0) + '@radix-ui/react-direction': 1.0.1(@types/react@18.2.37)(react@18.2.0) + '@radix-ui/react-id': 1.0.1(@types/react@18.2.37)(react@18.2.0) + '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-roving-focus': 1.0.4(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.37)(react@18.2.0) + '@types/react': 18.2.37 + '@types/react-dom': 18.2.15 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-use-callback-ref@1.0.0(react@18.2.0): resolution: {integrity: sha512-GZtyzoHz95Rhs6S63D2t/eqvdFCm7I+yHMLVQheKM7nBD8mbZIt+ct1jz4536MDnaOGKIxynJ8eHTkVGVVkoTg==} peerDependencies: @@ -888,6 +1093,20 @@ packages: react: 18.2.0 dev: false + /@radix-ui/react-use-callback-ref@1.0.1(@types/react@18.2.37)(react@18.2.0): + resolution: {integrity: sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.23.1 + '@types/react': 18.2.37 + react: 18.2.0 + dev: false + /@radix-ui/react-use-controllable-state@1.0.0(react@18.2.0): resolution: {integrity: sha512-FohDoZvk3mEXh9AWAVyRTYR4Sq7/gavuofglmiXB2g1aKyboUD4YtgWxKj8O5n+Uak52gXQ4wKz5IFST4vtJHg==} peerDependencies: @@ -898,6 +1117,21 @@ packages: react: 18.2.0 dev: false + /@radix-ui/react-use-controllable-state@1.0.1(@types/react@18.2.37)(react@18.2.0): + resolution: {integrity: sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.23.1 + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.37)(react@18.2.0) + '@types/react': 18.2.37 + react: 18.2.0 + dev: false + /@radix-ui/react-use-escape-keydown@1.0.0(react@18.2.0): resolution: {integrity: sha512-JwfBCUIfhXRxKExgIqGa4CQsiMemo1Xt0W/B4ei3fpzpvPENKpMKQ8mZSB6Acj3ebrAEgi2xiQvcI1PAAodvyg==} peerDependencies: @@ -917,6 +1151,20 @@ packages: react: 18.2.0 dev: false + /@radix-ui/react-use-layout-effect@1.0.1(@types/react@18.2.37)(react@18.2.0): + resolution: {integrity: sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.23.1 + '@types/react': 18.2.37 + react: 18.2.0 + dev: false + /@react-aria/breadcrumbs@3.5.8(react@18.2.0): resolution: {integrity: sha512-jeek23igeqXct7S3ShW2jtFUc5g3fS9ZEBZkF64FWBrwfCiaZwb8TcKkK/xFw36/q5mxEt+seNiqnNzvsICJuQ==} peerDependencies: @@ -2309,7 +2557,6 @@ packages: resolution: {integrity: sha512-HWMdW+7r7MR5+PZqJF6YFNSCtjz1T0dsvo/f1BV6HkV+6erD/nA7wd9NM00KVG83zf2nJ7uATPO9ttdIPvi3gg==} dependencies: '@types/react': 18.2.37 - dev: true /@types/react@18.2.37: resolution: {integrity: sha512-RGAYMi2bhRgEXT3f4B92WTohopH6bIXw05FuGlmJEnv/omEn190+QYEIYxIAuIBdKgboYYdVved2p1AxZVQnaw==} diff --git a/src/app/(components)/input.tsx b/src/app/(components)/input.tsx index c4eb0360..bb102883 100644 --- a/src/app/(components)/input.tsx +++ b/src/app/(components)/input.tsx @@ -5,13 +5,14 @@ import { AlertFillIcon, CheckCircleFillIcon } from "@primer/octicons-react"; export type InputProps = Omit< React.InputHTMLAttributes, - "size" | "defaultValue" | "value" + "size" | "defaultValue" | "value" | "name" > & { label: React.ReactNode; defaultValue?: string | number | ReadonlyArray | undefined | null; value?: string | number | ReadonlyArray | undefined | null; inputClassName?: string; helpText?: string; + name: string; renderLeadingIcon?: (classNames: string) => JSX.Element; renderTrailingIcon?: (classNames: string) => JSX.Element; size?: "small" | "medium" | "large"; diff --git a/src/app/(components)/issues/markdown-text-area.tsx b/src/app/(components)/issues/markdown-text-area.tsx new file mode 100644 index 00000000..39437014 --- /dev/null +++ b/src/app/(components)/issues/markdown-text-area.tsx @@ -0,0 +1,96 @@ +"use client"; +import * as React from "react"; +// components +import * as Tabs from "@radix-ui/react-tabs"; +import { Textarea } from "~/app/(components)/textarea"; + +// utils +import { clsx } from "~/lib/shared/utils.shared"; + +// types +import type { TextareaProps } from "~/app/(components)/textarea"; +export type MarkdownTextAreaProps = Omit; + +const TABS = { + PREVIEW: "PREVIEW", + EDITOR: "EDITOR" +} as const; +type TabValue = (typeof TABS)[keyof typeof TABS]; + +export function MarkdownTextArea({ + label, + defaultValue, + ...props +}: MarkdownTextAreaProps) { + const [textContent, setTextContent] = React.useState(defaultValue); + const [selectedTab, setSelectedTab] = React.useState(TABS.EDITOR); + + return ( +
+ +
+ setSelectedTab(tab as TabValue)} + > + + + Write + + + Preview + + + +
+ {/* + We do this because radix will not show the contents of the tab in DOM if it is not selected, + whereas we want to submit the contents of the tab regardless of tab selection + */} + {selectedTab !== "EDITOR" && ( +