Skip to content

Commit

Permalink
Merge branch 'dev' into kampus/setup-passport
Browse files Browse the repository at this point in the history
  • Loading branch information
usirin authored Aug 14, 2023
2 parents f632973 + 8484e3e commit 9943674
Show file tree
Hide file tree
Showing 45 changed files with 1,116 additions and 123 deletions.
35 changes: 35 additions & 0 deletions apps/gql/features/pano/commentUpvote.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { type Clients } from "~/clients";

interface CreateCommentUpvoteArgs {
commentID: string;
userID: string;
}

interface RemoveCommentUpvoteArgs {
commentID: string;
userID: string;
}

export function createCommentUpvoteActions({ prisma }: Clients) {
const create = (args: CreateCommentUpvoteArgs) => {
return prisma.commentUpvote.create({
data: {
comment: { connect: { id: args.commentID } },
owner: { connect: { id: args.userID } },
},
});
};

const remove = (args: RemoveCommentUpvoteArgs) => {
return prisma.commentUpvote.delete({
where: {
commentID_userID: {
commentID: args.commentID,
userID: args.userID,
},
},
});
};

return { create, remove };
}
2 changes: 2 additions & 0 deletions apps/gql/features/pano/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { createPanoCommentActions } from "~/features/pano/comment";
import { createPanoPostActions } from "~/features/pano/post";
import { type Clients } from "~/clients";
import { createCommentUpvoteActions } from "./commentUpvote";
import { createPostUpvoteActions } from "./postUpvote";

export function createPanoActions(clients: Clients) {
return {
post: createPanoPostActions(clients),
comment: createPanoCommentActions(clients),
postUpvote: createPostUpvoteActions(clients),
commentUpvote: createCommentUpvoteActions(clients),
};
}
18 changes: 16 additions & 2 deletions apps/gql/loaders/pano.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import {
createPrismaLoader,
} from "@kampus/gql-utils";
import { type Connection } from "@kampus/gql-utils/connection";
import { type Comment, type Post, type Upvote } from "@kampus/prisma";
import { stringify } from "@kampus/gql-utils/global-id";
import { type Comment, type CommentUpvote, type Post, type Upvote } from "@kampus/prisma";

import { type Clients } from "~/clients";
import {
Expand Down Expand Up @@ -101,6 +102,7 @@ const createPanoUpvoteLoaders = ({ prisma }: Clients) => {

return {
byPostID,
byCommentID,
byUserAndPostID,
byUserAndCommentID,
countByPostID,
Expand Down Expand Up @@ -200,9 +202,21 @@ export const transformPanoCommentConnection = (connection: Connection<Comment>)
} satisfies PanoCommentConnection;
};

export const transformPanoUpvote = (upvote: Upvote) => {
export function isPostUpvote(upvote: Upvote | CommentUpvote): upvote is Upvote {
return !!(upvote as Upvote).postID;
}

export function isCommentUpvote(upvote: Upvote | CommentUpvote): upvote is Upvote {
return !!(upvote as CommentUpvote).commentID;
}

export const transformPanoUpvote = (upvote: Upvote | CommentUpvote) => {
const type = isPostUpvote(upvote) ? "PanoPost" : "PanoComment";
const id = stringify(type, upvote.id);

return {
...upvote,
id,
__typename: "PanoUpvote",
node: null,
owner: null,
Expand Down
70 changes: 63 additions & 7 deletions apps/gql/schema/resolvers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -272,16 +272,41 @@ export const resolvers = {
totalCount: (connection) => connection.totalCount,
},
PanoUpvote: {
id: (upvote) => stringify("PanoUpvote", upvote.id),
id: (upvote) => upvote.id,
node: async (upvote, _, { loaders }) => {
const model = await loaders.pano.upvote.byPostID.load(upvote.id);
const post = await loaders.pano.post.byID.load(model.postID);
return transformPanoPost(post);
const { type, value } = parse<UpvotableTypename>(upvote.id);

switch (type) {
case "PanoComment": {
const model = await loaders.pano.upvote.byCommentID.load(value);
const comment = await loaders.pano.comment.byID.load(model.commentID);
return transformPanoComment(comment);
}
case "PanoPost": {
const model = await loaders.pano.upvote.byPostID.load(value);
const post = await loaders.pano.post.byID.load(model.postID);
return transformPanoPost(post);
}
}
},
owner: async (upvote, _, { loaders }) => {
const model = await loaders.pano.upvote.byPostID.load(upvote.id);
const user = await loaders.user.byID.load(model.userID);
return transformUser(user);
const id = parse<UpvotableTypename>(upvote.id);

switch (id.type) {
case "PanoComment": {
const model = await loaders.pano.upvote.byCommentID.load(id.value);
const user = await loaders.user.byID.load(model.userID);
return transformUser(user);
}
case "PanoPost": {
const model = await loaders.pano.upvote.byPostID.load(id.value);
const user = await loaders.user.byID.load(model.userID);
return transformUser(user);
}
default: {
return assertNever(id.type);
}
}
},
},

Expand Down Expand Up @@ -458,6 +483,23 @@ export const resolvers = {

upvote = await actions.pano.postUpvote.create({ postID: value, userID: session.user.id });

return { node: transformPanoUpvote(upvote), error: null };
}
case "PanoComment": {
let upvote = await loaders.pano.upvote.byUserAndCommentID.load({
commentID: value,
userID: session.user.id,
});

if (upvote) {
return { node: null, error: InvalidInput() };
}

upvote = await actions.pano.commentUpvote.create({
commentID: value,
userID: session.user.id,
});

return { node: transformPanoUpvote(upvote), error: null };
}
}
Expand All @@ -484,6 +526,20 @@ export const resolvers = {

return { node: transformPanoUpvote(upvote), error: null };
}
case "PanoComment": {
const upvote = await loaders.pano.upvote.byUserAndCommentID.load({
commentID: value,
userID: session.user.id,
});

if (!upvote) {
return { node: null, error: InvalidInput() };
}

await actions.pano.commentUpvote.remove(upvote);

return { node: transformPanoUpvote(upvote), error: null };
}
default: {
return assertNever(type);
}
Expand Down
2 changes: 1 addition & 1 deletion apps/gql/schema/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ type PanoPostEdge {
node: PanoPost
}

type PanoComment implements Node {
type PanoComment implements Node & Upvotable {
id: ID!
content: String!
owner: User
Expand Down
33 changes: 18 additions & 15 deletions apps/gql/schema/types.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,19 +131,20 @@ export type PageInfo = {
startCursor: Maybe<Scalars["String"]["output"]>;
};

export type PanoComment = Node & {
__typename?: "PanoComment";
commentCount: Maybe<Scalars["Int"]["output"]>;
comments: Maybe<PanoCommentConnection>;
content: Scalars["String"]["output"];
createdAt: Scalars["DateTime"]["output"];
id: Scalars["ID"]["output"];
isUpvotedByViewer: Scalars["Boolean"]["output"];
owner: Maybe<User>;
parent: Maybe<PanoComment>;
post: Maybe<PanoPost>;
upvoteCount: Maybe<Scalars["Int"]["output"]>;
};
export type PanoComment = Node &
Upvotable & {
__typename?: "PanoComment";
commentCount: Maybe<Scalars["Int"]["output"]>;
comments: Maybe<PanoCommentConnection>;
content: Scalars["String"]["output"];
createdAt: Scalars["DateTime"]["output"];
id: Scalars["ID"]["output"];
isUpvotedByViewer: Scalars["Boolean"]["output"];
owner: Maybe<User>;
parent: Maybe<PanoComment>;
post: Maybe<PanoPost>;
upvoteCount: Maybe<Scalars["Int"]["output"]>;
};

export type PanoCommentCommentsArgs = {
after: InputMaybe<Scalars["String"]["input"]>;
Expand Down Expand Up @@ -503,7 +504,9 @@ export type ResolversInterfaceTypes<RefType extends Record<string, unknown>> = R
| (PanoPost & { __typename: "PanoPost" })
| (SozlukTerm & { __typename: "SozlukTerm" })
| (User & { __typename: "User" });
Upvotable: PanoPost & { __typename: "PanoPost" };
Upvotable:
| (PanoComment & { __typename: "PanoComment" })
| (PanoPost & { __typename: "PanoPost" });
UserError:
| (InvalidInput & { __typename: "InvalidInput" })
| (NotAuthorized & { __typename: "NotAuthorized" });
Expand Down Expand Up @@ -1048,7 +1051,7 @@ export type UpvotableResolvers<
ContextType = KampusGQLContext,
ParentType extends ResolversParentTypes["Upvotable"] = ResolversParentTypes["Upvotable"]
> = ResolversObject<{
__resolveType?: TypeResolveFn<"PanoPost", ParentType, ContextType>;
__resolveType?: TypeResolveFn<"PanoComment" | "PanoPost", ParentType, ContextType>;
}>;

export type UserResolvers<
Expand Down
21 changes: 19 additions & 2 deletions apps/kampus/app/pano/PanoFeed.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { Suspense, useCallback } from "react";
import { graphql, usePaginationFragment } from "react-relay";
import { graphql, useFragment, usePaginationFragment } from "react-relay";

import { Button } from "@kampus/ui";

import { PostItem } from "~/app/pano/features/post-list/PostItem";
import { type PanoFeed_viewer$key } from "./__generated__/PanoFeed_viewer.graphql";
import { type PanoFeedFragment$key } from "./__generated__/PanoFeedFragment.graphql";

const fragment = graphql`
Expand All @@ -17,6 +18,7 @@ const fragment = graphql`
@refetchable(queryName: "PanoFeedPaginationQuery") {
panoFeed(first: $first, after: $after, last: $last, before: $before)
@connection(key: "PanoFeedFragment__panoFeed") {
__id
edges {
cursor
node {
Expand All @@ -28,15 +30,23 @@ const fragment = graphql`
}
`;

const viewerFragment = graphql`
fragment PanoFeed_viewer on Viewer {
...PostItem_viewer
}
`;

interface Props {
panoFeed: PanoFeedFragment$key;
panoViewer: PanoFeed_viewer$key;
}

export function PanoFeed(props: Props) {
const { data, hasNext, hasPrevious, loadNext, loadPrevious } = usePaginationFragment(
fragment,
props.panoFeed
);
const viewer = useFragment(viewerFragment, props.panoViewer);

const feed = data.panoFeed;

Expand All @@ -60,7 +70,14 @@ export function PanoFeed(props: Props) {
return null;
}

return <PostItem key={edge.node.id} post={edge.node} />;
return (
<PostItem
key={edge.node.id}
post={edge.node}
viewerRef={viewer}
postConnectionId={data.panoFeed?.__id}
/>
);
})}

<div className="flex gap-2">
Expand Down
3 changes: 2 additions & 1 deletion apps/kampus/app/pano/PostListContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const query = graphql`
query PostListContainerQuery {
viewer {
...PanoFeedFragment
...PanoFeed_viewer
}
}
`;
Expand All @@ -28,5 +29,5 @@ export const PostListContainer = (props: Props) => {
return null;
}

return <PanoFeed panoFeed={data.viewer} />;
return <PanoFeed panoFeed={data.viewer} panoViewer={data.viewer} />;
};
17 changes: 15 additions & 2 deletions apps/kampus/app/pano/__generated__/PanoFeedFragment.graphql.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 9943674

Please sign in to comment.