From be3ea0c7b2d1f3591c4be1361ac50cb9a9003d48 Mon Sep 17 00:00:00 2001 From: Can Sirin Date: Sun, 13 Aug 2023 13:29:57 -0700 Subject: [PATCH 1/4] feat(apps/pano): show "Duzenle" and "Sil" on more options for the post (#629) Closes #634 This PR introduces a functionality to check if viewer and owner of the post are the same person, so we can show "Duzenle" and "Sil" options in the MoreOptions component. --------- Co-authored-by: Can Sirin <8138047+cansirin@users.noreply.github.com> Co-authored-by: Umut Sirin --- apps/kampus/app/pano/PanoFeed.tsx | 21 +- apps/kampus/app/pano/PostListContainer.tsx | 3 +- .../__generated__/PanoFeedFragment.graphql.ts | 17 +- .../PanoFeedPaginationQuery.graphql.ts | 20 +- .../__generated__/PanoFeed_viewer.graphql.ts | 40 ++++ .../PostListContainerQuery.graphql.ts | 71 +++++-- .../pano/features/post-list/MoreOptions.tsx | 178 ++++++++++------- .../app/pano/features/post-list/PostItem.tsx | 28 ++- .../MoreOptionsRemovePostMutation.graphql.ts | 189 ++++++++++++++++++ .../__generated__/MoreOptions_post.graphql.ts | 63 ++++++ .../MoreOptions_viewer.graphql.ts | 55 +++++ .../__generated__/PostItem_post.graphql.ts | 11 +- .../__generated__/PostItem_viewer.graphql.ts | 61 ++++++ 13 files changed, 651 insertions(+), 106 deletions(-) create mode 100644 apps/kampus/app/pano/__generated__/PanoFeed_viewer.graphql.ts create mode 100644 apps/kampus/app/pano/features/post-list/__generated__/MoreOptionsRemovePostMutation.graphql.ts create mode 100644 apps/kampus/app/pano/features/post-list/__generated__/MoreOptions_post.graphql.ts create mode 100644 apps/kampus/app/pano/features/post-list/__generated__/MoreOptions_viewer.graphql.ts create mode 100644 apps/kampus/app/pano/features/post-list/__generated__/PostItem_viewer.graphql.ts diff --git a/apps/kampus/app/pano/PanoFeed.tsx b/apps/kampus/app/pano/PanoFeed.tsx index 661e7a6e..569b375a 100644 --- a/apps/kampus/app/pano/PanoFeed.tsx +++ b/apps/kampus/app/pano/PanoFeed.tsx @@ -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-next"; 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` @@ -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 { @@ -28,8 +30,15 @@ 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) { @@ -37,6 +46,7 @@ export function PanoFeed(props: Props) { fragment, props.panoFeed ); + const viewer = useFragment(viewerFragment, props.panoViewer); const feed = data.panoFeed; @@ -60,7 +70,14 @@ export function PanoFeed(props: Props) { return null; } - return ; + return ( + + ); })}
diff --git a/apps/kampus/app/pano/PostListContainer.tsx b/apps/kampus/app/pano/PostListContainer.tsx index eee9c796..d3a93228 100644 --- a/apps/kampus/app/pano/PostListContainer.tsx +++ b/apps/kampus/app/pano/PostListContainer.tsx @@ -16,6 +16,7 @@ const query = graphql` query PostListContainerQuery { viewer { ...PanoFeedFragment + ...PanoFeed_viewer } } `; @@ -28,5 +29,5 @@ export const PostListContainer = (props: Props) => { return null; } - return ; + return ; }; diff --git a/apps/kampus/app/pano/__generated__/PanoFeedFragment.graphql.ts b/apps/kampus/app/pano/__generated__/PanoFeedFragment.graphql.ts index e80778c7..fae43885 100644 --- a/apps/kampus/app/pano/__generated__/PanoFeedFragment.graphql.ts +++ b/apps/kampus/app/pano/__generated__/PanoFeedFragment.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<3c9f3f7de053b4688b2404c72e9daa59>> + * @generated SignedSource<<845cce7dd6f615c692812a518c6c92de>> * @lightSyntaxTransform * @nogrep */ @@ -12,6 +12,7 @@ import { ReaderFragment, RefetchableFragment } from 'relay-runtime'; import { FragmentRefs } from "relay-runtime"; export type PanoFeedFragment$data = { readonly panoFeed: { + readonly __id: string; readonly edges: ReadonlyArray<{ readonly cursor: string; readonly node: { @@ -178,6 +179,18 @@ return { } ], "storageKey": null + }, + { + "kind": "ClientExtension", + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "__id", + "storageKey": null + } + ] } ], "storageKey": null @@ -188,6 +201,6 @@ return { }; })(); -(node as any).hash = "c0d59088c3d65e88fdd5d8da836c2d76"; +(node as any).hash = "169d642e0dd7ef004b6ba9327f096aca"; export default node; diff --git a/apps/kampus/app/pano/__generated__/PanoFeedPaginationQuery.graphql.ts b/apps/kampus/app/pano/__generated__/PanoFeedPaginationQuery.graphql.ts index e6de5cd9..cf2714ab 100644 --- a/apps/kampus/app/pano/__generated__/PanoFeedPaginationQuery.graphql.ts +++ b/apps/kampus/app/pano/__generated__/PanoFeedPaginationQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<09ed6683c9184c2f89dbaad228142867>> + * @generated SignedSource<> * @lightSyntaxTransform * @nogrep */ @@ -270,6 +270,18 @@ return { } ], "storageKey": null + }, + { + "kind": "ClientExtension", + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "__id", + "storageKey": null + } + ] } ], "storageKey": null @@ -289,16 +301,16 @@ return { ] }, "params": { - "cacheID": "4ca0994c46e6a44f1dc573f87eb2c3b6", + "cacheID": "2fa3d4b245b0acc80462563f1be852b7", "id": null, "metadata": {}, "name": "PanoFeedPaginationQuery", "operationKind": "query", - "text": "query PanoFeedPaginationQuery(\n $after: String\n $before: String\n $first: Int = 10\n $last: Int\n) {\n viewer {\n ...PanoFeedFragment_pbnwq\n }\n}\n\nfragment PanoFeedFragment_pbnwq on Viewer {\n panoFeed(first: $first, after: $after, last: $last, before: $before) {\n edges {\n cursor\n node {\n id\n ...PostItem_post\n __typename\n }\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n}\n\nfragment PostItem_post on PanoPost {\n id\n title\n content\n url\n createdAt\n site\n ...PostUpvoteButton_post\n owner {\n displayName\n id\n }\n}\n\nfragment PostUpvoteButton_post on PanoPost {\n id\n isUpvotedByViewer\n upvoteCount\n}\n" + "text": "query PanoFeedPaginationQuery(\n $after: String\n $before: String\n $first: Int = 10\n $last: Int\n) {\n viewer {\n ...PanoFeedFragment_pbnwq\n }\n}\n\nfragment MoreOptions_post on PanoPost {\n id\n owner {\n displayName\n id\n }\n}\n\nfragment PanoFeedFragment_pbnwq on Viewer {\n panoFeed(first: $first, after: $after, last: $last, before: $before) {\n edges {\n cursor\n node {\n id\n ...PostItem_post\n __typename\n }\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n}\n\nfragment PostItem_post on PanoPost {\n id\n title\n content\n url\n createdAt\n site\n ...PostUpvoteButton_post\n owner {\n displayName\n id\n }\n ...MoreOptions_post\n}\n\nfragment PostUpvoteButton_post on PanoPost {\n id\n isUpvotedByViewer\n upvoteCount\n}\n" } }; })(); -(node as any).hash = "c0d59088c3d65e88fdd5d8da836c2d76"; +(node as any).hash = "169d642e0dd7ef004b6ba9327f096aca"; export default node; diff --git a/apps/kampus/app/pano/__generated__/PanoFeed_viewer.graphql.ts b/apps/kampus/app/pano/__generated__/PanoFeed_viewer.graphql.ts new file mode 100644 index 00000000..a1aeb7a0 --- /dev/null +++ b/apps/kampus/app/pano/__generated__/PanoFeed_viewer.graphql.ts @@ -0,0 +1,40 @@ +/** + * @generated SignedSource<<285a7607218f1bcd3ce4cf4f6613f8d0>> + * @lightSyntaxTransform + * @nogrep + */ + +/* tslint:disable */ +/* eslint-disable */ +// @ts-nocheck + +import { Fragment, ReaderFragment } from 'relay-runtime'; +import { FragmentRefs } from "relay-runtime"; +export type PanoFeed_viewer$data = { + readonly " $fragmentSpreads": FragmentRefs<"PostItem_viewer">; + readonly " $fragmentType": "PanoFeed_viewer"; +}; +export type PanoFeed_viewer$key = { + readonly " $data"?: PanoFeed_viewer$data; + readonly " $fragmentSpreads": FragmentRefs<"PanoFeed_viewer">; +}; + +const node: ReaderFragment = { + "argumentDefinitions": [], + "kind": "Fragment", + "metadata": null, + "name": "PanoFeed_viewer", + "selections": [ + { + "args": null, + "kind": "FragmentSpread", + "name": "PostItem_viewer" + } + ], + "type": "Viewer", + "abstractKey": null +}; + +(node as any).hash = "aa9717b7dd3561c13af770ff24544e2d"; + +export default node; diff --git a/apps/kampus/app/pano/__generated__/PostListContainerQuery.graphql.ts b/apps/kampus/app/pano/__generated__/PostListContainerQuery.graphql.ts index 967966b2..4a3edfd9 100644 --- a/apps/kampus/app/pano/__generated__/PostListContainerQuery.graphql.ts +++ b/apps/kampus/app/pano/__generated__/PostListContainerQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<> + * @generated SignedSource<> * @lightSyntaxTransform * @nogrep */ @@ -13,7 +13,7 @@ import { FragmentRefs } from "relay-runtime"; export type PostListContainerQuery$variables = {}; export type PostListContainerQuery$data = { readonly viewer: { - readonly " $fragmentSpreads": FragmentRefs<"PanoFeedFragment">; + readonly " $fragmentSpreads": FragmentRefs<"PanoFeedFragment" | "PanoFeed_viewer">; } | null; }; export type PostListContainerQuery = { @@ -35,6 +35,20 @@ v1 = { "kind": "ScalarField", "name": "id", "storageKey": null +}, +v2 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "displayName", + "storageKey": null +}, +v3 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "__typename", + "storageKey": null }; return { "fragment": { @@ -55,6 +69,11 @@ return { "args": null, "kind": "FragmentSpread", "name": "PanoFeedFragment" + }, + { + "args": null, + "kind": "FragmentSpread", + "name": "PanoFeed_viewer" } ], "storageKey": null @@ -166,24 +185,12 @@ return { "name": "owner", "plural": false, "selections": [ - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "displayName", - "storageKey": null - }, + (v2/*: any*/), (v1/*: any*/) ], "storageKey": null }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "__typename", - "storageKey": null - } + (v3/*: any*/) ], "storageKey": null } @@ -228,6 +235,18 @@ return { } ], "storageKey": null + }, + { + "kind": "ClientExtension", + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "__id", + "storageKey": null + } + ] } ], "storageKey": "panoFeed(first:10)" @@ -240,6 +259,20 @@ return { "key": "PanoFeedFragment__panoFeed", "kind": "LinkedHandle", "name": "panoFeed" + }, + { + "alias": null, + "args": null, + "concreteType": null, + "kind": "LinkedField", + "name": "actor", + "plural": false, + "selections": [ + (v3/*: any*/), + (v2/*: any*/), + (v1/*: any*/) + ], + "storageKey": null } ], "storageKey": null @@ -247,16 +280,16 @@ return { ] }, "params": { - "cacheID": "18eb8eaf3693895b2efd987ddc3b9362", + "cacheID": "8d8a203cd59b6775cfbc8daaad9001ef", "id": null, "metadata": {}, "name": "PostListContainerQuery", "operationKind": "query", - "text": "query PostListContainerQuery {\n viewer {\n ...PanoFeedFragment\n }\n}\n\nfragment PanoFeedFragment on Viewer {\n panoFeed(first: 10) {\n edges {\n cursor\n node {\n id\n ...PostItem_post\n __typename\n }\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n}\n\nfragment PostItem_post on PanoPost {\n id\n title\n content\n url\n createdAt\n site\n ...PostUpvoteButton_post\n owner {\n displayName\n id\n }\n}\n\nfragment PostUpvoteButton_post on PanoPost {\n id\n isUpvotedByViewer\n upvoteCount\n}\n" + "text": "query PostListContainerQuery {\n viewer {\n ...PanoFeedFragment\n ...PanoFeed_viewer\n }\n}\n\nfragment MoreOptions_post on PanoPost {\n id\n owner {\n displayName\n id\n }\n}\n\nfragment MoreOptions_viewer on Viewer {\n actor {\n __typename\n displayName\n id\n }\n}\n\nfragment PanoFeedFragment on Viewer {\n panoFeed(first: 10) {\n edges {\n cursor\n node {\n id\n ...PostItem_post\n __typename\n }\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n}\n\nfragment PanoFeed_viewer on Viewer {\n ...PostItem_viewer\n}\n\nfragment PostItem_post on PanoPost {\n id\n title\n content\n url\n createdAt\n site\n ...PostUpvoteButton_post\n owner {\n displayName\n id\n }\n ...MoreOptions_post\n}\n\nfragment PostItem_viewer on Viewer {\n ...MoreOptions_viewer\n actor {\n __typename\n displayName\n id\n }\n}\n\nfragment PostUpvoteButton_post on PanoPost {\n id\n isUpvotedByViewer\n upvoteCount\n}\n" } }; })(); -(node as any).hash = "38254b185df77d46946b76194dd61219"; +(node as any).hash = "246fd8479a18172b183f288ff6f3e842"; export default node; diff --git a/apps/kampus/app/pano/features/post-list/MoreOptions.tsx b/apps/kampus/app/pano/features/post-list/MoreOptions.tsx index 66955884..9bf7cc2a 100644 --- a/apps/kampus/app/pano/features/post-list/MoreOptions.tsx +++ b/apps/kampus/app/pano/features/post-list/MoreOptions.tsx @@ -1,17 +1,20 @@ "use client"; -import { useRouter } from "next/navigation"; +import Link from "next/link"; import { MoreHorizontal } from "lucide-react"; +import { graphql, useFragment, useMutation } from "react-relay"; import { + AlertDialog, + AlertDialogAction, + AlertDialogCancel, + AlertDialogContent, + AlertDialogDescription, + AlertDialogFooter, + AlertDialogHeader, + AlertDialogTitle, + AlertDialogTrigger, Button, - Dialog, - DialogContent, - DialogDescription, - DialogFooter, - DialogHeader, - DialogTitle, - DialogTrigger, DropdownMenu, DropdownMenuContent, DropdownMenuItem, @@ -20,56 +23,81 @@ import { useToast, } from "@kampus/ui-next"; +import { type MoreOptions_post$key } from "./__generated__/MoreOptions_post.graphql"; +import { type MoreOptions_viewer$key } from "./__generated__/MoreOptions_viewer.graphql"; + interface Props { - post: Post; - shareUrl: string; + post: MoreOptions_post$key; + viewerRef: MoreOptions_viewer$key | null; + postConnectionId?: string; } -type Post = { - __typename?: "PanoPost"; - content: string; - createdAt: string; - id: string; - owner: string; - title: string; - url: string; -}; -type User = { - username: string; -}; +const useMoreOptionsPostFragment = (key: MoreOptions_post$key | null) => + useFragment( + graphql` + fragment MoreOptions_post on PanoPost { + id + owner { + displayName + } + } + `, + key + ); -function canUserEdit(user: User, post: Post) { - console.log(user, post); - return true; -} +const useMoreOptionsViewerFragment = (key: MoreOptions_viewer$key | null) => + useFragment( + graphql` + fragment MoreOptions_viewer on Viewer { + actor { + displayName + } + } + `, + key + ); + +const removePostMutation = graphql` + mutation MoreOptionsRemovePostMutation($connections: [ID!]!, $postID: ID!) { + removePanoPost(input: { id: $postID }) { + edge { + node { + id @deleteEdge(connections: $connections) + title + } + } + } + } +`; + +// TODO: move this to server side +function canUserEdit(username?: string | null, owner?: string | null) { + if (!owner) return false; + if (!username) return false; -export const MoreOptionsDropdown = ({ post, shareUrl }: Props) => { - const user = { username: "John Doe" }; - console.log(post, shareUrl); + return username === owner; +} - const router = useRouter(); +export const MoreOptionsDropdown = (props: Props) => { + const post = useMoreOptionsPostFragment(props.post); + const viewer = useMoreOptionsViewerFragment(props.viewerRef); const { toast } = useToast(); + const [removePost, isRemoving] = useMutation(removePostMutation); - const ownerItems: JSX.Element[] = []; - if (canUserEdit(user, post)) { - ownerItems.push( - router.push(`/posts/${post.id}/edit`)} key="edit"> - Düzenle - - ); - ownerItems.push( - - Sil - - ); - ownerItems.push(); - } + const onClick = () => { + if (!post) { + return; + } - // // FIXME: below appears to be redundant, is it? - // const menuItems = [...ownerItems]; + if (isRemoving) { + return; + } + + removePost({ variables: { postID: post.id, connections: [props.postConnectionId] } }); + }; return ( - + - {ownerItems} + {canUserEdit(viewer?.actor?.displayName, post?.owner?.displayName) && ( + <> + + Düzenle + + + Sil + + + + )} { - toast({ - description: "Link kopyalandı", - }); - }} - > - Linki kopyala - + onSelect={() => { + toast({ + description: "Link kopyalandı", + }); + }} + > + Linki kopyala + - - - Silmek istediğine emin misin? - + + + Silmek istediğine emin misin? + Eğer bu gönderiyi silersen, bu işlemi geri alamazsın. - - - - - - - - + + + + Hayır + Evet + + + ); }; diff --git a/apps/kampus/app/pano/features/post-list/PostItem.tsx b/apps/kampus/app/pano/features/post-list/PostItem.tsx index 0fa7f3a3..9b3498c9 100644 --- a/apps/kampus/app/pano/features/post-list/PostItem.tsx +++ b/apps/kampus/app/pano/features/post-list/PostItem.tsx @@ -7,10 +7,10 @@ import { cn } from "@kampus/ui-next/utils"; import { TimeAgo } from "~/../../packages/ui"; import { type PostItem_post$key } from "./__generated__/PostItem_post.graphql"; +import { type PostItem_viewer$key } from "./__generated__/PostItem_viewer.graphql"; +import { MoreOptionsDropdown } from "./MoreOptions"; import { UpvoteButton } from "./PostUpvoteButton"; -// import { MoreOptionsDropdown } from "./MoreOptions"; - interface LinkProps { href: string; children: string; @@ -34,7 +34,6 @@ const usePanoPostFragment = (key: PostItem_post$key | null) => content url createdAt - id site ...PostUpvoteButton_post @@ -42,6 +41,20 @@ const usePanoPostFragment = (key: PostItem_post$key | null) => owner @required(action: LOG) { displayName @required(action: LOG) } + ...MoreOptions_post + } + `, + key + ); + +const usePanoViewerFragment = (key: PostItem_viewer$key | null) => + useFragment( + graphql` + fragment PostItem_viewer on Viewer { + ...MoreOptions_viewer + actor { + displayName + } } `, key @@ -49,11 +62,14 @@ const usePanoPostFragment = (key: PostItem_post$key | null) => interface PostItemProps { post: PostItem_post$key; + viewerRef: PostItem_viewer$key; showContent?: boolean; + postConnectionId?: string; } export const PostItem = (props: PostItemProps) => { const post = usePanoPostFragment(props.post); + const viewer = usePanoViewerFragment(props.viewerRef); if (!post) { return null; @@ -78,6 +94,12 @@ export const PostItem = (props: PostItemProps) => { 0 yorum |
+ diff --git a/apps/kampus/app/pano/features/post-list/__generated__/MoreOptionsRemovePostMutation.graphql.ts b/apps/kampus/app/pano/features/post-list/__generated__/MoreOptionsRemovePostMutation.graphql.ts new file mode 100644 index 00000000..c0c26e25 --- /dev/null +++ b/apps/kampus/app/pano/features/post-list/__generated__/MoreOptionsRemovePostMutation.graphql.ts @@ -0,0 +1,189 @@ +/** + * @generated SignedSource<> + * @lightSyntaxTransform + * @nogrep + */ + +/* tslint:disable */ +/* eslint-disable */ +// @ts-nocheck + +import { ConcreteRequest, Mutation } from 'relay-runtime'; +export type MoreOptionsRemovePostMutation$variables = { + connections: ReadonlyArray; + postID: string; +}; +export type MoreOptionsRemovePostMutation$data = { + readonly removePanoPost: { + readonly edge: { + readonly node: { + readonly id: string; + readonly title: string; + } | null; + } | null; + } | null; +}; +export type MoreOptionsRemovePostMutation = { + response: MoreOptionsRemovePostMutation$data; + variables: MoreOptionsRemovePostMutation$variables; +}; + +const node: ConcreteRequest = (function(){ +var v0 = [ + { + "defaultValue": null, + "kind": "LocalArgument", + "name": "connections" + }, + { + "defaultValue": null, + "kind": "LocalArgument", + "name": "postID" + } +], +v1 = [ + { + "fields": [ + { + "kind": "Variable", + "name": "id", + "variableName": "postID" + } + ], + "kind": "ObjectValue", + "name": "input" + } +], +v2 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "id", + "storageKey": null +}, +v3 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "title", + "storageKey": null +}; +return { + "fragment": { + "argumentDefinitions": (v0/*: any*/), + "kind": "Fragment", + "metadata": null, + "name": "MoreOptionsRemovePostMutation", + "selections": [ + { + "alias": null, + "args": (v1/*: any*/), + "concreteType": "RemovePanoPostPayload", + "kind": "LinkedField", + "name": "removePanoPost", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "PanoPostEdge", + "kind": "LinkedField", + "name": "edge", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "PanoPost", + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + (v2/*: any*/), + (v3/*: any*/) + ], + "storageKey": null + } + ], + "storageKey": null + } + ], + "storageKey": null + } + ], + "type": "Mutation", + "abstractKey": null + }, + "kind": "Request", + "operation": { + "argumentDefinitions": (v0/*: any*/), + "kind": "Operation", + "name": "MoreOptionsRemovePostMutation", + "selections": [ + { + "alias": null, + "args": (v1/*: any*/), + "concreteType": "RemovePanoPostPayload", + "kind": "LinkedField", + "name": "removePanoPost", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "PanoPostEdge", + "kind": "LinkedField", + "name": "edge", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "PanoPost", + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + (v2/*: any*/), + { + "alias": null, + "args": null, + "filters": null, + "handle": "deleteEdge", + "key": "", + "kind": "ScalarHandle", + "name": "id", + "handleArgs": [ + { + "kind": "Variable", + "name": "connections", + "variableName": "connections" + } + ] + }, + (v3/*: any*/) + ], + "storageKey": null + } + ], + "storageKey": null + } + ], + "storageKey": null + } + ] + }, + "params": { + "cacheID": "6c9942183f760e86a8cbfcf94dbc7ebe", + "id": null, + "metadata": {}, + "name": "MoreOptionsRemovePostMutation", + "operationKind": "mutation", + "text": "mutation MoreOptionsRemovePostMutation(\n $postID: ID!\n) {\n removePanoPost(input: {id: $postID}) {\n edge {\n node {\n id\n title\n }\n }\n }\n}\n" + } +}; +})(); + +(node as any).hash = "0bc137edfc163648cc5c8a5969e5697a"; + +export default node; diff --git a/apps/kampus/app/pano/features/post-list/__generated__/MoreOptions_post.graphql.ts b/apps/kampus/app/pano/features/post-list/__generated__/MoreOptions_post.graphql.ts new file mode 100644 index 00000000..3f0a86bd --- /dev/null +++ b/apps/kampus/app/pano/features/post-list/__generated__/MoreOptions_post.graphql.ts @@ -0,0 +1,63 @@ +/** + * @generated SignedSource<> + * @lightSyntaxTransform + * @nogrep + */ + +/* tslint:disable */ +/* eslint-disable */ +// @ts-nocheck + +import { Fragment, ReaderFragment } from 'relay-runtime'; +import { FragmentRefs } from "relay-runtime"; +export type MoreOptions_post$data = { + readonly id: string; + readonly owner: { + readonly displayName: string | null; + } | null; + readonly " $fragmentType": "MoreOptions_post"; +}; +export type MoreOptions_post$key = { + readonly " $data"?: MoreOptions_post$data; + readonly " $fragmentSpreads": FragmentRefs<"MoreOptions_post">; +}; + +const node: ReaderFragment = { + "argumentDefinitions": [], + "kind": "Fragment", + "metadata": null, + "name": "MoreOptions_post", + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "id", + "storageKey": null + }, + { + "alias": null, + "args": null, + "concreteType": "User", + "kind": "LinkedField", + "name": "owner", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "displayName", + "storageKey": null + } + ], + "storageKey": null + } + ], + "type": "PanoPost", + "abstractKey": null +}; + +(node as any).hash = "01fe2324527daa720ea5ca88add6406c"; + +export default node; diff --git a/apps/kampus/app/pano/features/post-list/__generated__/MoreOptions_viewer.graphql.ts b/apps/kampus/app/pano/features/post-list/__generated__/MoreOptions_viewer.graphql.ts new file mode 100644 index 00000000..ef707e16 --- /dev/null +++ b/apps/kampus/app/pano/features/post-list/__generated__/MoreOptions_viewer.graphql.ts @@ -0,0 +1,55 @@ +/** + * @generated SignedSource<> + * @lightSyntaxTransform + * @nogrep + */ + +/* tslint:disable */ +/* eslint-disable */ +// @ts-nocheck + +import { Fragment, ReaderFragment } from 'relay-runtime'; +import { FragmentRefs } from "relay-runtime"; +export type MoreOptions_viewer$data = { + readonly actor: { + readonly displayName: string | null; + } | null; + readonly " $fragmentType": "MoreOptions_viewer"; +}; +export type MoreOptions_viewer$key = { + readonly " $data"?: MoreOptions_viewer$data; + readonly " $fragmentSpreads": FragmentRefs<"MoreOptions_viewer">; +}; + +const node: ReaderFragment = { + "argumentDefinitions": [], + "kind": "Fragment", + "metadata": null, + "name": "MoreOptions_viewer", + "selections": [ + { + "alias": null, + "args": null, + "concreteType": null, + "kind": "LinkedField", + "name": "actor", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "displayName", + "storageKey": null + } + ], + "storageKey": null + } + ], + "type": "Viewer", + "abstractKey": null +}; + +(node as any).hash = "335429bfb4234ab199c74e1828e9bfe2"; + +export default node; diff --git a/apps/kampus/app/pano/features/post-list/__generated__/PostItem_post.graphql.ts b/apps/kampus/app/pano/features/post-list/__generated__/PostItem_post.graphql.ts index a1c7259d..d7bae815 100644 --- a/apps/kampus/app/pano/features/post-list/__generated__/PostItem_post.graphql.ts +++ b/apps/kampus/app/pano/features/post-list/__generated__/PostItem_post.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<> + * @generated SignedSource<> * @lightSyntaxTransform * @nogrep */ @@ -20,7 +20,7 @@ export type PostItem_post$data = { readonly site: string | null; readonly title: string; readonly url: string | null; - readonly " $fragmentSpreads": FragmentRefs<"PostUpvoteButton_post">; + readonly " $fragmentSpreads": FragmentRefs<"MoreOptions_post" | "PostUpvoteButton_post">; readonly " $fragmentType": "PostItem_post"; } | null; export type PostItem_post$key = { @@ -108,12 +108,17 @@ const node: ReaderFragment = { }, "action": "LOG", "path": "owner" + }, + { + "args": null, + "kind": "FragmentSpread", + "name": "MoreOptions_post" } ], "type": "PanoPost", "abstractKey": null }; -(node as any).hash = "2722b74002976e15c158a0be92853b78"; +(node as any).hash = "40952525253258c86b4d4320cf4279a0"; export default node; diff --git a/apps/kampus/app/pano/features/post-list/__generated__/PostItem_viewer.graphql.ts b/apps/kampus/app/pano/features/post-list/__generated__/PostItem_viewer.graphql.ts new file mode 100644 index 00000000..3a5b3b4f --- /dev/null +++ b/apps/kampus/app/pano/features/post-list/__generated__/PostItem_viewer.graphql.ts @@ -0,0 +1,61 @@ +/** + * @generated SignedSource<<4b69c454a3a58b7052f9e79ba03b1bec>> + * @lightSyntaxTransform + * @nogrep + */ + +/* tslint:disable */ +/* eslint-disable */ +// @ts-nocheck + +import { Fragment, ReaderFragment } from 'relay-runtime'; +import { FragmentRefs } from "relay-runtime"; +export type PostItem_viewer$data = { + readonly actor: { + readonly displayName: string | null; + } | null; + readonly " $fragmentSpreads": FragmentRefs<"MoreOptions_viewer">; + readonly " $fragmentType": "PostItem_viewer"; +}; +export type PostItem_viewer$key = { + readonly " $data"?: PostItem_viewer$data; + readonly " $fragmentSpreads": FragmentRefs<"PostItem_viewer">; +}; + +const node: ReaderFragment = { + "argumentDefinitions": [], + "kind": "Fragment", + "metadata": null, + "name": "PostItem_viewer", + "selections": [ + { + "args": null, + "kind": "FragmentSpread", + "name": "MoreOptions_viewer" + }, + { + "alias": null, + "args": null, + "concreteType": null, + "kind": "LinkedField", + "name": "actor", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "displayName", + "storageKey": null + } + ], + "storageKey": null + } + ], + "type": "Viewer", + "abstractKey": null +}; + +(node as any).hash = "08a45a50da6ade7e46c243f7477d30ac"; + +export default node; From 0b98b05bcd5004666ec402ca63548cc2fb23e8e9 Mon Sep 17 00:00:00 2001 From: Murat-tunca <121015513+Murat-tunca@users.noreply.github.com> Date: Mon, 14 Aug 2023 13:04:20 +0300 Subject: [PATCH 2/4] (@apps/ui): add typography components (#648) # Description Please describe your changes. Be descriptive enough to reduce churn for review process. ### Checklist - [x] discord username: `Vlad` - [x] Closes #646 - [x] PR must be created for an issue from issues under "In progress" column from [our project board](https://github.com/orgs/kamp-us/projects/2/views/1). - [x] A descriptive and understandable title: The PR title should clearly describe the nature and purpose of the changes. The PR title should be the first thing displayed when the PR is opened. And it should follow the semantic commit rules, and should include the app/package/service name in the title. For example, a title like "docs(@kampus-apps/pano): Add README.md" can be used. - [x] Related file selection: Only relevant files should be touched and no other files should be affected. - [x] I ran `npx turbo run` at the root of the repository, and build was successful. - [x] I installed the npm packages using `npm install --save-exact ` so my package is pinned to a specific npm version. Leave empty if no package was installed. Leave empty if no package was installed with this PR. ### How were these changes tested? Please describe the tests you did to test the changes you made. Please also specify your test configuration. --- packages/ui/components/index.ts | 1 + packages/ui/components/typography/blockquote.tsx | 5 +++++ packages/ui/components/typography/h1.tsx | 9 +++++++++ packages/ui/components/typography/h2.tsx | 9 +++++++++ packages/ui/components/typography/h3.tsx | 5 +++++ packages/ui/components/typography/h4.tsx | 5 +++++ packages/ui/components/typography/index.ts | 12 ++++++++++++ packages/ui/components/typography/inline-code.tsx | 9 +++++++++ packages/ui/components/typography/large.tsx | 5 +++++ packages/ui/components/typography/lead.tsx | 5 +++++ packages/ui/components/typography/list.tsx | 5 +++++ packages/ui/components/typography/muted.tsx | 5 +++++ packages/ui/components/typography/p.tsx | 5 +++++ packages/ui/components/typography/small.tsx | 5 +++++ 14 files changed, 85 insertions(+) create mode 100644 packages/ui/components/typography/blockquote.tsx create mode 100644 packages/ui/components/typography/h1.tsx create mode 100644 packages/ui/components/typography/h2.tsx create mode 100644 packages/ui/components/typography/h3.tsx create mode 100644 packages/ui/components/typography/h4.tsx create mode 100644 packages/ui/components/typography/index.ts create mode 100644 packages/ui/components/typography/inline-code.tsx create mode 100644 packages/ui/components/typography/large.tsx create mode 100644 packages/ui/components/typography/lead.tsx create mode 100644 packages/ui/components/typography/list.tsx create mode 100644 packages/ui/components/typography/muted.tsx create mode 100644 packages/ui/components/typography/p.tsx create mode 100644 packages/ui/components/typography/small.tsx diff --git a/packages/ui/components/index.ts b/packages/ui/components/index.ts index dc079d7c..252473e0 100644 --- a/packages/ui/components/index.ts +++ b/packages/ui/components/index.ts @@ -21,3 +21,4 @@ export * from "./checkbox"; export * from "./toaster"; export * from "./card"; export * from "./form"; +export * from "./typography"; diff --git a/packages/ui/components/typography/blockquote.tsx b/packages/ui/components/typography/blockquote.tsx new file mode 100644 index 00000000..b5fd7f27 --- /dev/null +++ b/packages/ui/components/typography/blockquote.tsx @@ -0,0 +1,5 @@ +import { PropsWithChildren } from "react"; + +export function TypographyBlockquote(props: PropsWithChildren) { + return
{props.children}
; +} diff --git a/packages/ui/components/typography/h1.tsx b/packages/ui/components/typography/h1.tsx new file mode 100644 index 00000000..0f2e6664 --- /dev/null +++ b/packages/ui/components/typography/h1.tsx @@ -0,0 +1,9 @@ +import { PropsWithChildren } from "react"; + +export function TypographyH1(props: PropsWithChildren) { + return ( +

+ {props.children} +

+ ); +} diff --git a/packages/ui/components/typography/h2.tsx b/packages/ui/components/typography/h2.tsx new file mode 100644 index 00000000..f68cb27e --- /dev/null +++ b/packages/ui/components/typography/h2.tsx @@ -0,0 +1,9 @@ +import { PropsWithChildren } from "react"; + +export function TypographyH2(props: PropsWithChildren) { + return ( +

+ {props.children} +

+ ); +} diff --git a/packages/ui/components/typography/h3.tsx b/packages/ui/components/typography/h3.tsx new file mode 100644 index 00000000..dcc61f56 --- /dev/null +++ b/packages/ui/components/typography/h3.tsx @@ -0,0 +1,5 @@ +import { PropsWithChildren } from "react"; + +export function TypographyH3(props: PropsWithChildren) { + return

{props.children}

; +} diff --git a/packages/ui/components/typography/h4.tsx b/packages/ui/components/typography/h4.tsx new file mode 100644 index 00000000..a00b06ed --- /dev/null +++ b/packages/ui/components/typography/h4.tsx @@ -0,0 +1,5 @@ +import { PropsWithChildren } from "react"; + +export function TypographyH4(props: PropsWithChildren) { + return

{props.children}

; +} diff --git a/packages/ui/components/typography/index.ts b/packages/ui/components/typography/index.ts new file mode 100644 index 00000000..db3d0c23 --- /dev/null +++ b/packages/ui/components/typography/index.ts @@ -0,0 +1,12 @@ +export * from "./h1"; +export * from "./h2"; +export * from "./h3"; +export * from "./h4"; +export * from "./inline-code"; +export * from "./large"; +export * from "./lead"; +export * from "./list"; +export * from "./muted"; +export * from "./p"; +export * from "./small"; +export * from "./blockquote"; diff --git a/packages/ui/components/typography/inline-code.tsx b/packages/ui/components/typography/inline-code.tsx new file mode 100644 index 00000000..259caeff --- /dev/null +++ b/packages/ui/components/typography/inline-code.tsx @@ -0,0 +1,9 @@ +import { PropsWithChildren } from "react"; + +export function TypographyInlineCode(props: PropsWithChildren) { + return ( + + {props.children} + + ); +} diff --git a/packages/ui/components/typography/large.tsx b/packages/ui/components/typography/large.tsx new file mode 100644 index 00000000..869256b0 --- /dev/null +++ b/packages/ui/components/typography/large.tsx @@ -0,0 +1,5 @@ +import { PropsWithChildren } from "react"; + +export function TypographyLarge(props: PropsWithChildren) { + return
{props.children}
; +} diff --git a/packages/ui/components/typography/lead.tsx b/packages/ui/components/typography/lead.tsx new file mode 100644 index 00000000..75e467f6 --- /dev/null +++ b/packages/ui/components/typography/lead.tsx @@ -0,0 +1,5 @@ +import { PropsWithChildren } from "react"; + +export function TypographyLead(props: PropsWithChildren) { + return

{props.children}

; +} diff --git a/packages/ui/components/typography/list.tsx b/packages/ui/components/typography/list.tsx new file mode 100644 index 00000000..12cdd87b --- /dev/null +++ b/packages/ui/components/typography/list.tsx @@ -0,0 +1,5 @@ +import { PropsWithChildren } from "react"; + +export function TypographyList(props: PropsWithChildren) { + return
    {props.children}
; +} diff --git a/packages/ui/components/typography/muted.tsx b/packages/ui/components/typography/muted.tsx new file mode 100644 index 00000000..b4737680 --- /dev/null +++ b/packages/ui/components/typography/muted.tsx @@ -0,0 +1,5 @@ +import { PropsWithChildren } from "react"; + +export function TypographyMuted(props: PropsWithChildren) { + return

{props.children}

; +} diff --git a/packages/ui/components/typography/p.tsx b/packages/ui/components/typography/p.tsx new file mode 100644 index 00000000..77348b93 --- /dev/null +++ b/packages/ui/components/typography/p.tsx @@ -0,0 +1,5 @@ +import { PropsWithChildren } from "react"; + +export function TypographyP(props: PropsWithChildren) { + return

{props.children}

; +} diff --git a/packages/ui/components/typography/small.tsx b/packages/ui/components/typography/small.tsx new file mode 100644 index 00000000..118056eb --- /dev/null +++ b/packages/ui/components/typography/small.tsx @@ -0,0 +1,5 @@ +import { PropsWithChildren } from "react"; + +export function TypographySmall(props: PropsWithChildren) { + return {props.children}; +} From ab2f153db3b771fcd4f76535c03bc45654d2e4d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Muhammed=20G=C3=BCm=C3=BC=C5=9F?= <86381278+muhammed-gumus@users.noreply.github.com> Date: Mon, 14 Aug 2023 23:26:30 +0300 Subject: [PATCH 3/4] feat(apps/ui): add typography stories (#649) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description Created typography storybook. ### Checklist - [x] discord username: `muhammed-gumus` - [x] Closes #647 - [x] PR must be created for an issue from issues under "In progress" column from [our project board](https://github.com/orgs/kamp-us/projects/2/views/1). - [x] A descriptive and understandable title: The PR title should clearly describe the nature and purpose of the changes. The PR title should be the first thing displayed when the PR is opened. And it should follow the semantic commit rules, and should include the app/package/service name in the title. For example, a title like "docs(@kampus-apps/pano): Add README.md" can be used. - [x] Related file selection: Only relevant files should be touched and no other files should be affected. - [x] I ran `npx turbo run` at the root of the repository, and build was successful. - [ ] I installed the npm packages using `npm install --save-exact ` so my package is pinned to a specific npm version. Leave empty if no package was installed. Leave empty if no package was installed with this PR. ### How were these changes tested? Please describe the tests you did to test the changes you made. Please also specify your test configuration. --------- Co-authored-by: Muhammed Gümüş Co-authored-by: Can Sirin Co-authored-by: Umut Sirin --- .../TypographyBlockquote.stories.tsx | 21 ++++++++++++++++++ .../Typography/TypographyH1.stories.tsx | 21 ++++++++++++++++++ .../Typography/TypographyH2.stories.tsx | 21 ++++++++++++++++++ .../Typography/TypographyH3.stories.tsx | 21 ++++++++++++++++++ .../Typography/TypographyH4.stories.tsx | 21 ++++++++++++++++++ .../TypographyInlineCode.stories.tsx | 21 ++++++++++++++++++ .../Typography/TypographyLarge.stories.tsx | 21 ++++++++++++++++++ .../Typography/TypographyLead.stories.tsx | 21 ++++++++++++++++++ .../Typography/TypographyList.stories.tsx | 22 +++++++++++++++++++ .../Typography/TypographyMuted.stories.tsx | 21 ++++++++++++++++++ .../Typography/TypographyP.stories.tsx | 21 ++++++++++++++++++ .../Typography/TypographySmall.stories.tsx | 21 ++++++++++++++++++ 12 files changed, 253 insertions(+) create mode 100644 apps/ui/stories/Typography/TypographyBlockquote.stories.tsx create mode 100644 apps/ui/stories/Typography/TypographyH1.stories.tsx create mode 100644 apps/ui/stories/Typography/TypographyH2.stories.tsx create mode 100644 apps/ui/stories/Typography/TypographyH3.stories.tsx create mode 100644 apps/ui/stories/Typography/TypographyH4.stories.tsx create mode 100644 apps/ui/stories/Typography/TypographyInlineCode.stories.tsx create mode 100644 apps/ui/stories/Typography/TypographyLarge.stories.tsx create mode 100644 apps/ui/stories/Typography/TypographyLead.stories.tsx create mode 100644 apps/ui/stories/Typography/TypographyList.stories.tsx create mode 100644 apps/ui/stories/Typography/TypographyMuted.stories.tsx create mode 100644 apps/ui/stories/Typography/TypographyP.stories.tsx create mode 100644 apps/ui/stories/Typography/TypographySmall.stories.tsx diff --git a/apps/ui/stories/Typography/TypographyBlockquote.stories.tsx b/apps/ui/stories/Typography/TypographyBlockquote.stories.tsx new file mode 100644 index 00000000..3a69e88b --- /dev/null +++ b/apps/ui/stories/Typography/TypographyBlockquote.stories.tsx @@ -0,0 +1,21 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import { TypographyBlockquote } from "@kampus/ui-next"; + +const meta = { + component: TypographyBlockquote, + title: "Typography/Blockquote", + args: { + children: "Typography Blockquote", + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default = { + args: { + children: "Kamp.us", + }, + render: (args) => {args.children}, +} satisfies Story; diff --git a/apps/ui/stories/Typography/TypographyH1.stories.tsx b/apps/ui/stories/Typography/TypographyH1.stories.tsx new file mode 100644 index 00000000..bb607358 --- /dev/null +++ b/apps/ui/stories/Typography/TypographyH1.stories.tsx @@ -0,0 +1,21 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import { TypographyH1 } from "@kampus/ui-next"; + +const meta = { + component: TypographyH1, + title: "Typography/H1", + args: { + children: "Typography H1", + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default = { + args: { + children: "Kamp.us", + }, + render: (args) => {args.children}, +} satisfies Story; diff --git a/apps/ui/stories/Typography/TypographyH2.stories.tsx b/apps/ui/stories/Typography/TypographyH2.stories.tsx new file mode 100644 index 00000000..8f4ea4d3 --- /dev/null +++ b/apps/ui/stories/Typography/TypographyH2.stories.tsx @@ -0,0 +1,21 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import { TypographyH2 } from "@kampus/ui-next"; + +const meta = { + component: TypographyH2, + title: "Typography/H2", + args: { + children: "Typography H2", + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default = { + args: { + children: "Kamp.us", + }, + render: (args) => {args.children}, +} satisfies Story; diff --git a/apps/ui/stories/Typography/TypographyH3.stories.tsx b/apps/ui/stories/Typography/TypographyH3.stories.tsx new file mode 100644 index 00000000..9a1990dd --- /dev/null +++ b/apps/ui/stories/Typography/TypographyH3.stories.tsx @@ -0,0 +1,21 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import { TypographyH3 } from "@kampus/ui-next"; + +const meta = { + component: TypographyH3, + title: "Typography/H3", + args: { + children: "Typography H3", + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default = { + args: { + children: "Kamp.us", + }, + render: (args) => {args.children}, +} satisfies Story; diff --git a/apps/ui/stories/Typography/TypographyH4.stories.tsx b/apps/ui/stories/Typography/TypographyH4.stories.tsx new file mode 100644 index 00000000..c38e43fd --- /dev/null +++ b/apps/ui/stories/Typography/TypographyH4.stories.tsx @@ -0,0 +1,21 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import { TypographyH4 } from "@kampus/ui-next"; + +const meta = { + component: TypographyH4, + title: "Typography/H4", + args: { + children: "Typography H4", + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default = { + args: { + children: "Kamp.us", + }, + render: (args) => {args.children}, +} satisfies Story; diff --git a/apps/ui/stories/Typography/TypographyInlineCode.stories.tsx b/apps/ui/stories/Typography/TypographyInlineCode.stories.tsx new file mode 100644 index 00000000..904b8ad9 --- /dev/null +++ b/apps/ui/stories/Typography/TypographyInlineCode.stories.tsx @@ -0,0 +1,21 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import { TypographyInlineCode } from "@kampus/ui-next"; + +const meta = { + component: TypographyInlineCode, + title: "Typography/InlineCode", + args: { + children: "Typography Inline Code", + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default = { + args: { + children: "Kamp.us", + }, + render: (args) => {args.children}, +} satisfies Story; diff --git a/apps/ui/stories/Typography/TypographyLarge.stories.tsx b/apps/ui/stories/Typography/TypographyLarge.stories.tsx new file mode 100644 index 00000000..7ff69756 --- /dev/null +++ b/apps/ui/stories/Typography/TypographyLarge.stories.tsx @@ -0,0 +1,21 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import { TypographyLarge } from "@kampus/ui-next"; + +const meta = { + component: TypographyLarge, + title: "Typography/Large", + args: { + children: "Typography Large", + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default = { + args: { + children: "Kamp.us", + }, + render: (args) => {args.children}, +} satisfies Story; diff --git a/apps/ui/stories/Typography/TypographyLead.stories.tsx b/apps/ui/stories/Typography/TypographyLead.stories.tsx new file mode 100644 index 00000000..4b1c583e --- /dev/null +++ b/apps/ui/stories/Typography/TypographyLead.stories.tsx @@ -0,0 +1,21 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import { TypographyLead } from "@kampus/ui-next"; + +const meta = { + component: TypographyLead, + title: "Typography/Lead", + args: { + children: "Typography Lead", + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default = { + args: { + children: "Kamp.us", + }, + render: (args) => {args.children}, +} satisfies Story; diff --git a/apps/ui/stories/Typography/TypographyList.stories.tsx b/apps/ui/stories/Typography/TypographyList.stories.tsx new file mode 100644 index 00000000..3f3d2bc9 --- /dev/null +++ b/apps/ui/stories/Typography/TypographyList.stories.tsx @@ -0,0 +1,22 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import { TypographyList } from "@kampus/ui-next"; + +const meta = { + component: TypographyList, + title: "Typography/List", + args: { + children: "Typography List", + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default = { + render: () => ( + +
  • Kamp.us/Pano
  • Kamp.us/Sozluk
  • Kamp.us/Pasaport
  • +
    + ), +} satisfies Story; diff --git a/apps/ui/stories/Typography/TypographyMuted.stories.tsx b/apps/ui/stories/Typography/TypographyMuted.stories.tsx new file mode 100644 index 00000000..15f1f9d0 --- /dev/null +++ b/apps/ui/stories/Typography/TypographyMuted.stories.tsx @@ -0,0 +1,21 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import { TypographyLarge, TypographyMuted } from "@kampus/ui-next"; + +const meta = { + component: TypographyMuted, + title: "Typography/Muted", + args: { + children: "Typography Muted", + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default = { + args: { + children: "Kamp.us", + }, + render: (args) => {args.children}, +} satisfies Story; diff --git a/apps/ui/stories/Typography/TypographyP.stories.tsx b/apps/ui/stories/Typography/TypographyP.stories.tsx new file mode 100644 index 00000000..b19c9b2a --- /dev/null +++ b/apps/ui/stories/Typography/TypographyP.stories.tsx @@ -0,0 +1,21 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import { TypographyP } from "@kampus/ui-next"; + +const meta = { + component: TypographyP, + title: "Typography/P", + args: { + children: "Typography P", + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default = { + args: { + children: "Kamp.us", + }, + render: (args) => {args.children}, +} satisfies Story; diff --git a/apps/ui/stories/Typography/TypographySmall.stories.tsx b/apps/ui/stories/Typography/TypographySmall.stories.tsx new file mode 100644 index 00000000..3a24bb90 --- /dev/null +++ b/apps/ui/stories/Typography/TypographySmall.stories.tsx @@ -0,0 +1,21 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import { TypographySmall } from "@kampus/ui-next"; + +const meta = { + component: TypographySmall, + title: "Typography/Small", + args: { + children: "Typography Small", + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default = { + args: { + children: "Kamp.us", + }, + render: (args) => {args.children}, +} satisfies Story; From 8484e3e8511ddbca4673e93805e8eb6360b4ae0b Mon Sep 17 00:00:00 2001 From: Rasit <12167194+durmusrasit@users.noreply.github.com> Date: Tue, 15 Aug 2023 01:12:29 +0300 Subject: [PATCH 4/4] feat(apps/gql): add comment upvote create & remove resolvers (#651) # Description This pr includes the create and remove actions & resolvers for comment upvote --------- Co-authored-by: usirin --- apps/gql/features/pano/commentUpvote.ts | 35 +++++++++++++ apps/gql/features/pano/index.ts | 2 + apps/gql/loaders/pano.ts | 18 ++++++- apps/gql/schema/resolvers/index.ts | 70 ++++++++++++++++++++++--- apps/gql/schema/schema.graphql | 2 +- apps/gql/schema/types.generated.ts | 33 ++++++------ 6 files changed, 135 insertions(+), 25 deletions(-) create mode 100644 apps/gql/features/pano/commentUpvote.ts diff --git a/apps/gql/features/pano/commentUpvote.ts b/apps/gql/features/pano/commentUpvote.ts new file mode 100644 index 00000000..a6cd3f28 --- /dev/null +++ b/apps/gql/features/pano/commentUpvote.ts @@ -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 }; +} diff --git a/apps/gql/features/pano/index.ts b/apps/gql/features/pano/index.ts index cc649038..6c90f10f 100644 --- a/apps/gql/features/pano/index.ts +++ b/apps/gql/features/pano/index.ts @@ -1,6 +1,7 @@ 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) { @@ -8,5 +9,6 @@ export function createPanoActions(clients: Clients) { post: createPanoPostActions(clients), comment: createPanoCommentActions(clients), postUpvote: createPostUpvoteActions(clients), + commentUpvote: createCommentUpvoteActions(clients), }; } diff --git a/apps/gql/loaders/pano.ts b/apps/gql/loaders/pano.ts index 8a6b92fc..1b2679af 100644 --- a/apps/gql/loaders/pano.ts +++ b/apps/gql/loaders/pano.ts @@ -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 { @@ -101,6 +102,7 @@ const createPanoUpvoteLoaders = ({ prisma }: Clients) => { return { byPostID, + byCommentID, byUserAndPostID, byUserAndCommentID, countByPostID, @@ -200,9 +202,21 @@ export const transformPanoCommentConnection = (connection: Connection) } 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, diff --git a/apps/gql/schema/resolvers/index.ts b/apps/gql/schema/resolvers/index.ts index 04e14a80..786eef35 100644 --- a/apps/gql/schema/resolvers/index.ts +++ b/apps/gql/schema/resolvers/index.ts @@ -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(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(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); + } + } }, }, @@ -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 }; } } @@ -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); } diff --git a/apps/gql/schema/schema.graphql b/apps/gql/schema/schema.graphql index 3441260f..9fabae12 100644 --- a/apps/gql/schema/schema.graphql +++ b/apps/gql/schema/schema.graphql @@ -142,7 +142,7 @@ type PanoPostEdge { node: PanoPost } -type PanoComment implements Node { +type PanoComment implements Node & Upvotable { id: ID! content: String! owner: User diff --git a/apps/gql/schema/types.generated.ts b/apps/gql/schema/types.generated.ts index 03b87b70..6ffba627 100644 --- a/apps/gql/schema/types.generated.ts +++ b/apps/gql/schema/types.generated.ts @@ -131,19 +131,20 @@ export type PageInfo = { startCursor: Maybe; }; -export type PanoComment = Node & { - __typename?: "PanoComment"; - commentCount: Maybe; - comments: Maybe; - content: Scalars["String"]["output"]; - createdAt: Scalars["DateTime"]["output"]; - id: Scalars["ID"]["output"]; - isUpvotedByViewer: Scalars["Boolean"]["output"]; - owner: Maybe; - parent: Maybe; - post: Maybe; - upvoteCount: Maybe; -}; +export type PanoComment = Node & + Upvotable & { + __typename?: "PanoComment"; + commentCount: Maybe; + comments: Maybe; + content: Scalars["String"]["output"]; + createdAt: Scalars["DateTime"]["output"]; + id: Scalars["ID"]["output"]; + isUpvotedByViewer: Scalars["Boolean"]["output"]; + owner: Maybe; + parent: Maybe; + post: Maybe; + upvoteCount: Maybe; + }; export type PanoCommentCommentsArgs = { after: InputMaybe; @@ -503,7 +504,9 @@ export type ResolversInterfaceTypes> = 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" }); @@ -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<