diff --git a/frontend/src/components/AddEmailForm.tsx b/frontend/src/components/AddEmailForm.tsx index bd7c16979..01c6e854f 100644 --- a/frontend/src/components/AddEmailForm.tsx +++ b/frontend/src/components/AddEmailForm.tsx @@ -26,9 +26,6 @@ const ADD_EMAIL_MUTATION = graphql(/* GraphQL */ ` mutation AddEmail($userId: ID!, $email: String!) { addEmail(input: { userId: $userId, email: $email }) { status - user { - id - } email { id ...UserEmail_email diff --git a/frontend/src/components/BrowserSessionList.tsx b/frontend/src/components/BrowserSessionList.tsx index dc9cd570d..0ad37427b 100644 --- a/frontend/src/components/BrowserSessionList.tsx +++ b/frontend/src/components/BrowserSessionList.tsx @@ -33,6 +33,13 @@ const QUERY = graphql(/* GraphQL */ ` ...BrowserSession_session } } + + pageInfo { + hasNextPage + hasPreviousPage + startCursor + endCursor + } } } } diff --git a/frontend/src/components/Pagination.tsx b/frontend/src/components/Pagination.tsx new file mode 100644 index 000000000..6f48e7fdf --- /dev/null +++ b/frontend/src/components/Pagination.tsx @@ -0,0 +1,54 @@ +// Copyright 2023 The Matrix.org Foundation C.I.C. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import Button from "./Button"; + +type Props = { + onNext: (() => void) | null; + onPrev: (() => void) | null; + count?: number; + disabled?: boolean; +}; + +const Pagination: React.FC = ({ onNext, onPrev, count, disabled }) => { + return ( +
+ {onPrev ? ( + + ) : ( + + )} + {count !== undefined ? ( +
Total: {count}
+ ) : ( +
+ )} + {onNext ? ( + + ) : ( + + )} +
+ ); +}; + +export default Pagination; diff --git a/frontend/src/components/UserEmailList.tsx b/frontend/src/components/UserEmailList.tsx index 387b71e94..5611cd9e0 100644 --- a/frontend/src/components/UserEmailList.tsx +++ b/frontend/src/components/UserEmailList.tsx @@ -18,9 +18,9 @@ import { atomFamily, atomWithDefault } from "jotai/utils"; import { graphql } from "../gql"; import { useTransition } from "react"; -import Button from "./Button"; import UserEmail from "./UserEmail"; import BlockList from "./BlockList"; +import Pagination from "./Pagination"; const QUERY = graphql(/* GraphQL */ ` query UserEmailListQuery( @@ -151,46 +151,17 @@ const UserEmailList: React.FC<{ userId: string }> = ({ userId }) => { }; return ( -
-
- {prevPagePagination ? ( - - ) : ( - - )} -
- Total: {result.data?.user?.emails?.totalCount} -
- {nextPagePagination ? ( - - ) : ( - - )} -
- - {result.data?.user?.emails?.edges?.map((edge) => ( - - ))} - -
+ + paginate(prevPagePagination) : null} + onNext={nextPagePagination ? () => paginate(nextPagePagination) : null} + disabled={pending} + /> + {result.data?.user?.emails?.edges?.map((edge) => ( + + ))} + ); }; diff --git a/frontend/src/gql/gql.ts b/frontend/src/gql/gql.ts index 928228829..9b0c02665 100644 --- a/frontend/src/gql/gql.ts +++ b/frontend/src/gql/gql.ts @@ -17,11 +17,11 @@ const documents = { types.CurrentViewerQueryDocument, "\n query CurrentViewerSessionQuery {\n viewerSession {\n __typename\n ... on BrowserSession {\n id\n }\n\n ... on Anonymous {\n id\n }\n }\n }\n": types.CurrentViewerSessionQueryDocument, - "\n mutation AddEmail($userId: ID!, $email: String!) {\n addEmail(input: { userId: $userId, email: $email }) {\n status\n user {\n id\n }\n email {\n id\n ...UserEmail_email\n }\n }\n }\n": + "\n mutation AddEmail($userId: ID!, $email: String!) {\n addEmail(input: { userId: $userId, email: $email }) {\n status\n email {\n id\n ...UserEmail_email\n }\n }\n }\n": types.AddEmailDocument, "\n fragment BrowserSession_session on BrowserSession {\n id\n createdAt\n lastAuthentication {\n id\n createdAt\n }\n }\n": types.BrowserSession_SessionFragmentDoc, - "\n query BrowserSessionList($userId: ID!) {\n user(id: $userId) {\n id\n browserSessions(first: 10) {\n edges {\n cursor\n node {\n id\n ...BrowserSession_session\n }\n }\n }\n }\n }\n": + "\n query BrowserSessionList($userId: ID!) {\n user(id: $userId) {\n id\n browserSessions(first: 10) {\n edges {\n cursor\n node {\n id\n ...BrowserSession_session\n }\n }\n\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n }\n }\n": types.BrowserSessionListDocument, "\n fragment CompatSsoLogin_login on CompatSsoLogin {\n id\n redirectUri\n createdAt\n session {\n id\n createdAt\n deviceId\n finishedAt\n }\n }\n": types.CompatSsoLogin_LoginFragmentDoc, @@ -73,8 +73,8 @@ export function graphql( * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ export function graphql( - source: "\n mutation AddEmail($userId: ID!, $email: String!) {\n addEmail(input: { userId: $userId, email: $email }) {\n status\n user {\n id\n }\n email {\n id\n ...UserEmail_email\n }\n }\n }\n" -): (typeof documents)["\n mutation AddEmail($userId: ID!, $email: String!) {\n addEmail(input: { userId: $userId, email: $email }) {\n status\n user {\n id\n }\n email {\n id\n ...UserEmail_email\n }\n }\n }\n"]; + source: "\n mutation AddEmail($userId: ID!, $email: String!) {\n addEmail(input: { userId: $userId, email: $email }) {\n status\n email {\n id\n ...UserEmail_email\n }\n }\n }\n" +): (typeof documents)["\n mutation AddEmail($userId: ID!, $email: String!) {\n addEmail(input: { userId: $userId, email: $email }) {\n status\n email {\n id\n ...UserEmail_email\n }\n }\n }\n"]; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ @@ -85,8 +85,8 @@ export function graphql( * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ export function graphql( - source: "\n query BrowserSessionList($userId: ID!) {\n user(id: $userId) {\n id\n browserSessions(first: 10) {\n edges {\n cursor\n node {\n id\n ...BrowserSession_session\n }\n }\n }\n }\n }\n" -): (typeof documents)["\n query BrowserSessionList($userId: ID!) {\n user(id: $userId) {\n id\n browserSessions(first: 10) {\n edges {\n cursor\n node {\n id\n ...BrowserSession_session\n }\n }\n }\n }\n }\n"]; + source: "\n query BrowserSessionList($userId: ID!) {\n user(id: $userId) {\n id\n browserSessions(first: 10) {\n edges {\n cursor\n node {\n id\n ...BrowserSession_session\n }\n }\n\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n }\n }\n" +): (typeof documents)["\n query BrowserSessionList($userId: ID!) {\n user(id: $userId) {\n id\n browserSessions(first: 10) {\n edges {\n cursor\n node {\n id\n ...BrowserSession_session\n }\n }\n\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n }\n }\n"]; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ diff --git a/frontend/src/gql/graphql.ts b/frontend/src/gql/graphql.ts index 021d7a520..d8b0f1678 100644 --- a/frontend/src/gql/graphql.ts +++ b/frontend/src/gql/graphql.ts @@ -607,7 +607,6 @@ export type AddEmailMutation = { addEmail: { __typename?: "AddEmailPayload"; status: AddEmailStatus; - user: { __typename?: "User"; id: string }; email: { __typename?: "UserEmail"; id: string } & { " $fragmentRefs"?: { UserEmail_EmailFragment: UserEmail_EmailFragment }; }; @@ -645,6 +644,13 @@ export type BrowserSessionListQuery = { }; }; }>; + pageInfo: { + __typename?: "PageInfo"; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor?: string | null; + endCursor?: string | null; + }; }; } | null; }; @@ -1112,16 +1118,6 @@ export const AddEmailDocument = { kind: "SelectionSet", selections: [ { kind: "Field", name: { kind: "Name", value: "status" } }, - { - kind: "Field", - name: { kind: "Name", value: "user" }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { kind: "Field", name: { kind: "Name", value: "id" } }, - ], - }, - }, { kind: "Field", name: { kind: "Name", value: "email" }, @@ -1247,6 +1243,31 @@ export const BrowserSessionListDocument = { ], }, }, + { + kind: "Field", + name: { kind: "Name", value: "pageInfo" }, + selectionSet: { + kind: "SelectionSet", + selections: [ + { + kind: "Field", + name: { kind: "Name", value: "hasNextPage" }, + }, + { + kind: "Field", + name: { kind: "Name", value: "hasPreviousPage" }, + }, + { + kind: "Field", + name: { kind: "Name", value: "startCursor" }, + }, + { + kind: "Field", + name: { kind: "Name", value: "endCursor" }, + }, + ], + }, + }, ], }, },