You've already forked authentication-service
mirror of
https://github.com/matrix-org/matrix-authentication-service.git
synced 2025-11-20 12:02:22 +03:00
WIP my account page
This commit is contained in:
@@ -26,9 +26,6 @@ const ADD_EMAIL_MUTATION = graphql(/* GraphQL */ `
|
|||||||
mutation AddEmail($userId: ID!, $email: String!) {
|
mutation AddEmail($userId: ID!, $email: String!) {
|
||||||
addEmail(input: { userId: $userId, email: $email }) {
|
addEmail(input: { userId: $userId, email: $email }) {
|
||||||
status
|
status
|
||||||
user {
|
|
||||||
id
|
|
||||||
}
|
|
||||||
email {
|
email {
|
||||||
id
|
id
|
||||||
...UserEmail_email
|
...UserEmail_email
|
||||||
|
|||||||
@@ -33,6 +33,13 @@ const QUERY = graphql(/* GraphQL */ `
|
|||||||
...BrowserSession_session
|
...BrowserSession_session
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pageInfo {
|
||||||
|
hasNextPage
|
||||||
|
hasPreviousPage
|
||||||
|
startCursor
|
||||||
|
endCursor
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
54
frontend/src/components/Pagination.tsx
Normal file
54
frontend/src/components/Pagination.tsx
Normal file
@@ -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<Props> = ({ onNext, onPrev, count, disabled }) => {
|
||||||
|
return (
|
||||||
|
<div className="grid items-center grid-cols-3 gap-2">
|
||||||
|
{onPrev ? (
|
||||||
|
<Button compact disabled={disabled} ghost onClick={onPrev}>
|
||||||
|
Previous
|
||||||
|
</Button>
|
||||||
|
) : (
|
||||||
|
<Button compact disabled ghost>
|
||||||
|
Previous
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
{count !== undefined ? (
|
||||||
|
<div className="text-center">Total: {count}</div>
|
||||||
|
) : (
|
||||||
|
<div></div>
|
||||||
|
)}
|
||||||
|
{onNext ? (
|
||||||
|
<Button compact disabled={disabled} ghost onClick={onNext}>
|
||||||
|
Next
|
||||||
|
</Button>
|
||||||
|
) : (
|
||||||
|
<Button compact disabled ghost>
|
||||||
|
Next
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Pagination;
|
||||||
@@ -18,9 +18,9 @@ import { atomFamily, atomWithDefault } from "jotai/utils";
|
|||||||
|
|
||||||
import { graphql } from "../gql";
|
import { graphql } from "../gql";
|
||||||
import { useTransition } from "react";
|
import { useTransition } from "react";
|
||||||
import Button from "./Button";
|
|
||||||
import UserEmail from "./UserEmail";
|
import UserEmail from "./UserEmail";
|
||||||
import BlockList from "./BlockList";
|
import BlockList from "./BlockList";
|
||||||
|
import Pagination from "./Pagination";
|
||||||
|
|
||||||
const QUERY = graphql(/* GraphQL */ `
|
const QUERY = graphql(/* GraphQL */ `
|
||||||
query UserEmailListQuery(
|
query UserEmailListQuery(
|
||||||
@@ -151,46 +151,17 @@ const UserEmailList: React.FC<{ userId: string }> = ({ userId }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
|
||||||
<div className="grid items-center grid-cols-3 gap-2 mb-2">
|
|
||||||
{prevPagePagination ? (
|
|
||||||
<Button
|
|
||||||
compact
|
|
||||||
disabled={pending}
|
|
||||||
ghost
|
|
||||||
onClick={() => paginate(prevPagePagination)}
|
|
||||||
>
|
|
||||||
Previous
|
|
||||||
</Button>
|
|
||||||
) : (
|
|
||||||
<Button compact disabled ghost>
|
|
||||||
Previous
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
<div className="text-center">
|
|
||||||
Total: {result.data?.user?.emails?.totalCount}
|
|
||||||
</div>
|
|
||||||
{nextPagePagination ? (
|
|
||||||
<Button
|
|
||||||
compact
|
|
||||||
disabled={pending}
|
|
||||||
ghost
|
|
||||||
onClick={() => paginate(nextPagePagination)}
|
|
||||||
>
|
|
||||||
Next
|
|
||||||
</Button>
|
|
||||||
) : (
|
|
||||||
<Button compact disabled ghost>
|
|
||||||
Next
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<BlockList>
|
<BlockList>
|
||||||
|
<Pagination
|
||||||
|
count={result.data?.user?.emails?.totalCount ?? 0}
|
||||||
|
onPrev={prevPagePagination ? () => paginate(prevPagePagination) : null}
|
||||||
|
onNext={nextPagePagination ? () => paginate(nextPagePagination) : null}
|
||||||
|
disabled={pending}
|
||||||
|
/>
|
||||||
{result.data?.user?.emails?.edges?.map((edge) => (
|
{result.data?.user?.emails?.edges?.map((edge) => (
|
||||||
<UserEmail email={edge.node} key={edge.cursor} />
|
<UserEmail email={edge.node} key={edge.cursor} />
|
||||||
))}
|
))}
|
||||||
</BlockList>
|
</BlockList>
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -17,11 +17,11 @@ const documents = {
|
|||||||
types.CurrentViewerQueryDocument,
|
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":
|
"\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,
|
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,
|
types.AddEmailDocument,
|
||||||
"\n fragment BrowserSession_session on BrowserSession {\n id\n createdAt\n lastAuthentication {\n id\n createdAt\n }\n }\n":
|
"\n fragment BrowserSession_session on BrowserSession {\n id\n createdAt\n lastAuthentication {\n id\n createdAt\n }\n }\n":
|
||||||
types.BrowserSession_SessionFragmentDoc,
|
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,
|
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":
|
"\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,
|
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.
|
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||||
*/
|
*/
|
||||||
export function graphql(
|
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"
|
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 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 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.
|
* 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.
|
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||||
*/
|
*/
|
||||||
export function graphql(
|
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"
|
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 }\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.
|
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -607,7 +607,6 @@ export type AddEmailMutation = {
|
|||||||
addEmail: {
|
addEmail: {
|
||||||
__typename?: "AddEmailPayload";
|
__typename?: "AddEmailPayload";
|
||||||
status: AddEmailStatus;
|
status: AddEmailStatus;
|
||||||
user: { __typename?: "User"; id: string };
|
|
||||||
email: { __typename?: "UserEmail"; id: string } & {
|
email: { __typename?: "UserEmail"; id: string } & {
|
||||||
" $fragmentRefs"?: { UserEmail_EmailFragment: UserEmail_EmailFragment };
|
" $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;
|
} | null;
|
||||||
};
|
};
|
||||||
@@ -1112,16 +1118,6 @@ export const AddEmailDocument = {
|
|||||||
kind: "SelectionSet",
|
kind: "SelectionSet",
|
||||||
selections: [
|
selections: [
|
||||||
{ kind: "Field", name: { kind: "Name", value: "status" } },
|
{ 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",
|
kind: "Field",
|
||||||
name: { kind: "Name", value: "email" },
|
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" },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user