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

Feat: Umamin Social & Umamin Partners #233

Open
wants to merge 24 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
a7c7ba6
chore: add schema for post and upvote
joshxfi Aug 16, 2024
f367c6f
Merge branch 'dev' of github.com:omsimos/umamin into social
joshxfi Aug 18, 2024
5ff3b2b
feat: personal user profile
hyamero Aug 20, 2024
9b597aa
feat: post form ui
hyamero Aug 20, 2024
cd12cd4
chore: post design adjustments
hyamero Aug 20, 2024
7b1ee67
feat: nested comment ui design
hyamero Aug 22, 2024
50f7cc5
feat: add shared package for reused pages
joshxfi Aug 25, 2024
df71510
feat(partners): setup graphql server
joshxfi Aug 18, 2024
0098122
feat(partners): display messages
joshxfi Aug 18, 2024
94c8d0c
fix(partners): add signout action in btn
joshxfi Aug 18, 2024
3e3a801
chore(partners): adjust limit for messages
joshxfi Aug 25, 2024
63ba776
fix: resolve lockfile conflict
joshxfi Aug 25, 2024
cdd506a
feat: share authenticaton pages
joshxfi Aug 31, 2024
d183a4b
chore: move shared utils to package
joshxfi Aug 31, 2024
8489e49
chore: implement shared routes in www
joshxfi Aug 31, 2024
524b170
chore: upgrade turbo and pnpm
joshxfi Aug 31, 2024
daa8695
chore: upgrade deps
joshxfi Sep 1, 2024
8bb66cf
chore: upgrade graphql yoga dependencies
joshxfi Sep 2, 2024
77915ba
fix: update lockfile
joshxfi Sep 2, 2024
cde63e4
chore: upgrade next deps
joshxfi Sep 5, 2024
19abe96
chore: upgrade deps
joshxfi Sep 17, 2024
abec2b7
fix: move actions to server route in shared
joshxfi Sep 17, 2024
86af98b
chore: add cn utils in shared
joshxfi Sep 17, 2024
663c87a
chore: add className in share auth pages
joshxfi Sep 17, 2024
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: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 9.6.0
version: 9.10.0
- uses: actions/setup-node@v4
with:
node-version: 20
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/playwright.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 9.6.0
version: 9.10.0
- uses: actions/setup-node@v4
with:
node-version: 20
Expand Down Expand Up @@ -70,7 +70,7 @@ jobs:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 9.5.0
version: 9.10.0
- uses: actions/setup-node@v4
with:
node-version: 20
Expand Down
7 changes: 6 additions & 1 deletion apps/partners/next.config.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
transpilePackages: ["@umamin/ui", "@umamin/db", "@umamin/gql"],
transpilePackages: [
"@umamin/ui",
"@umamin/db",
"@umamin/gql",
"@umamin/shared",
],
experimental: {
serverComponentsExternalPackages: ["@node-rs/argon2"],
},
Expand Down
35 changes: 17 additions & 18 deletions apps/partners/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,44 +6,43 @@
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
"lint": "next lint",
"gql:generate-persisted": "gql.tada generate-persisted",
"gql:generate-schema": "gql.tada generate-schema http://localhost:3000/api/graphql"
},
"dependencies": {
"@graphql-yoga/plugin-csrf-prevention": "^3.6.2",
"@graphql-yoga/plugin-disable-introspection": "^2.6.2",
"@graphql-yoga/plugin-persisted-operations": "^3.6.2",
"@graphql-yoga/plugin-response-cache": "^3.8.2",
"@graphql-yoga/plugin-csrf-prevention": "^3.7.0",
"@graphql-yoga/plugin-disable-introspection": "^2.7.0",
"@graphql-yoga/plugin-persisted-operations": "^3.7.0",
"@graphql-yoga/plugin-response-cache": "^3.9.0",
"@lucia-auth/adapter-drizzle": "^1.0.7",
"@node-rs/argon2": "^1.8.3",
"@tanstack/react-virtual": "^3.9.0",
"@umamin/db": "workspace:*",
"@umamin/gql": "workspace:*",
"@umamin/ui": "workspace:*",
"@urql/core": "^5.0.5",
"@urql/exchange-graphcache": "^7.1.1",
"@urql/exchange-persisted": "^4.3.0",
"@urql/next": "^1.1.1",
"@umamin/shared": "workspace:*",
"@whatwg-node/server": "^0.9.46",
"arctic": "^1.9.2",
"date-fns": "^3.6.0",
"geist": "^1.3.1",
"gql.tada": "^1.8.5",
"gql.tada": "^1.8.6",
"graphql": "^16.9.0",
"graphql-yoga": "^5.6.2",
"graphql-yoga": "^5.7.0",
"lucia": "^3.2.0",
"lucide-react": "^0.407.0",
"modern-screenshot": "^4.4.39",
"nanoid": "^5.0.7",
"next": "14.2.5",
"nextjs-toploader": "^1.6.12",
"react": "^18",
"react-dom": "^18",
"next": "14.2.11",
"nextjs-toploader": "^3.6.15",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-intersection-observer": "^9.10.2",
"sonner": "^1.5.0",
"urql": "^4.1.0",
"zod": "^3.22.4"
},
"devDependencies": {
"@0no-co/graphqlsp": "^1.12.12",
"@0no-co/graphqlsp": "^1.12.13",
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
Expand All @@ -54,6 +53,6 @@
"eslint-config-next": "14.2.5",
"postcss": "^8",
"tailwindcss": "^3.4.1",
"typescript": "^5"
"typescript": "^5.5.4"
}
}
97 changes: 97 additions & 0 deletions apps/partners/src/app/api/graphql/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { cookies } from "next/headers";
import { createYoga } from "graphql-yoga";
import { getSession, lucia } from "@umamin/shared/lib/auth";
import persistedOperations from "@/persisted-operations.json";
import { partners_schema, initContextCache } from "@umamin/gql";
import { useResponseCache } from "@graphql-yoga/plugin-response-cache";
import { useCSRFPrevention } from "@graphql-yoga/plugin-csrf-prevention";
import { usePersistedOperations } from "@graphql-yoga/plugin-persisted-operations";
import { useDisableIntrospection } from "@graphql-yoga/plugin-disable-introspection";

const { handleRequest } = createYoga({
schema: partners_schema,
context: async () => {
const { session } = await getSession();

return {
...initContextCache(),
userId: session?.userId,
};
},
graphqlEndpoint: "/api/graphql",
graphiql: process.env.NODE_ENV === "development",
fetchAPI: { Response },
cors: {
origin:
process.env.NODE_ENV === "production"
? "https://www.umamin.link"
: "http://localhost:3000",
credentials: true,
methods: ["POST", "GET", "OPTIONS"],
allowedHeaders: ["Content-Type", "Authorization"],
},
plugins: [
useCSRFPrevention({
requestHeaders: ["x-graphql-yoga-csrf"],
}),
useResponseCache({
session: () => cookies().get(lucia.sessionCookieName)?.value,
invalidateViaMutation: false,
scopePerSchemaCoordinate: {
"Query.user": "PRIVATE",
"Query.note": "PRIVATE",
"Query.messages": "PRIVATE",
"Query.messagesFromCursor": "PRIVATE",
},
ttl: 30_000,
ttlPerSchemaCoordinate: {
"Query.notes": 120_000,
"Query.notesFromCursor": 120_000,
"Query.userByUsername": 120_000,
},
}),
useDisableIntrospection({
isDisabled: () => process.env.NODE_ENV === "production",
}),
usePersistedOperations({
allowArbitraryOperations: process.env.NODE_ENV === "development",
customErrors: {
notFound: {
message: "Operation is not found",
extensions: {
http: {
status: 404,
},
},
},
keyNotFound: {
message: "Key is not found",
extensions: {
http: {
status: 404,
},
},
},
persistedQueryOnly: {
message: "Operation is not allowed",
extensions: {
http: {
status: 403,
},
},
},
},
skipDocumentValidation: true,
async getPersistedOperation(key: string) {
// @ts-ignore
return persistedOperations[key];
},
}),
],
});

export {
handleRequest as GET,
handleRequest as POST,
handleRequest as OPTIONS,
};
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
import Link from "next/link";
import { Badge } from "@umamin/ui/components/badge";
import { logout } from "@umamin/shared/actions";
import { SignOutButton } from "./sign-out-btn";
import { Badge } from "@umamin/ui/components/badge";

export async function Navbar() {
export function Navbar() {
return (
<nav className="fixed left-0 right-0 top-0 z-50 w-full bg-background bg-opacity-40 bg-clip-padding py-5 backdrop-blur-xl backdrop-filter lg:z-40 container max-w-screen-xl flex justify-between items-center">
<nav className="fixed left-0 right-0 top-0 z-50 w-full bg-background bg-opacity-40 bg-clip-padding py-5 backdrop-blur-xl backdrop-filter lg:z-40 container max-w-screen-2xl flex justify-between items-center">
<div className="space-x-2 flex items-center">
<Link href="/" aria-label="logo">
<span className="text-muted-foreground font-medium">partners.</span>
<span className="font-semibold text-foreground">umamin</span>
<span className="text-muted-foreground font-medium">.link</span>
</Link>

<Badge variant="outline">partners</Badge>
<Badge variant="outline">beta</Badge>
</div>

<SignOutButton />
<form action={logout}>
<SignOutButton />
</form>
</nav>
);
}
55 changes: 55 additions & 0 deletions apps/partners/src/app/dashboard/components/received/card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { formatDistanceToNow, fromUnixTime } from "date-fns";
import { FragmentOf, graphql, readFragment } from "gql.tada";

import {
Card,
CardContent,
CardFooter,
CardHeader,
} from "@umamin/ui/components/card";

export const receivedMessageFragment = graphql(`
fragment MessageFragment on Message {
id
question
content
reply
createdAt
updatedAt
}
`);

export function ReceivedMessageCard({
data,
}: {
data: FragmentOf<typeof receivedMessageFragment>;
}) {
const msg = readFragment(receivedMessageFragment, data);

return (
<div id={`umamin-${msg.id}`} className="w-full">
<Card>
<CardHeader className="flex px-12">
<p className="font-bold text-center leading-normal text-lg min-w-0 break-words">
{msg.question}
</p>
</CardHeader>
<CardContent>
<div
data-testid="received-msg-content"
className="flex w-full flex-col gap-2 rounded-lg p-5 whitespace-pre-wrap bg-muted break-words min-w-0"
>
{msg.content}
</div>
</CardContent>
<CardFooter className="flex justify-center">
<span className="text-muted-foreground text-sm mt-1 italic w-full text-center">
{formatDistanceToNow(fromUnixTime(msg.createdAt), {
addSuffix: true,
})}
</span>
</CardFooter>
</Card>
</div>
);
}
Loading