1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2025-11-20 12:02:22 +03:00

Make Profile page the default route (#1653)

* make profile the default route

* src/pages/Home.tsx -> src/pages/SessionsOverview.tsx

* UserHome -> UserSessionsOverview

* update snapshots, fix session overview button alignment
This commit is contained in:
Kerry
2023-08-31 11:27:39 +12:00
committed by GitHub
parent bea4d57124
commit da8a489748
19 changed files with 189 additions and 184 deletions

View File

@@ -18,18 +18,13 @@ import { segmentsToRoute } from "./Router";
describe("Router", () => { describe("Router", () => {
describe("segmentsToRoute", () => { describe("segmentsToRoute", () => {
it("returns home for route with no segments", () => { it("returns profile for route with no segments", () => {
const segments: string[] = []; const segments: string[] = [];
expect(segmentsToRoute(segments)).toEqual({ type: "home" }); expect(segmentsToRoute(segments)).toEqual({ type: "profile" });
}); });
it("returns home for route with and empty string segment", () => { it("returns profile for route with and empty string segment", () => {
const segments: string[] = [""]; const segments: string[] = [""];
expect(segmentsToRoute(segments)).toEqual({ type: "home" });
});
it("returns profile for route with profile", () => {
const segments: string[] = ["profile"];
expect(segmentsToRoute(segments)).toEqual({ type: "profile" }); expect(segmentsToRoute(segments)).toEqual({ type: "profile" });
}); });

View File

@@ -25,8 +25,8 @@ type Location = {
searchParams?: URLSearchParams; searchParams?: URLSearchParams;
}; };
type HomeRoute = { type: "home" };
type ProfileRoute = { type: "profile" }; type ProfileRoute = { type: "profile" };
type SessionOverviewRoute = { type: "sessions-overview" };
type OAuth2ClientRoute = { type: "client"; id: string }; type OAuth2ClientRoute = { type: "client"; id: string };
type OAuth2SessionList = { type: "oauth2-session-list" }; type OAuth2SessionList = { type: "oauth2-session-list" };
type BrowserSessionRoute = { type: "session"; id: string }; type BrowserSessionRoute = { type: "session"; id: string };
@@ -36,7 +36,7 @@ type VerifyEmailRoute = { type: "verify-email"; id: string };
type UnknownRoute = { type: "unknown"; segments: string[] }; type UnknownRoute = { type: "unknown"; segments: string[] };
export type Route = export type Route =
| HomeRoute | SessionOverviewRoute
| ProfileRoute | ProfileRoute
| OAuth2ClientRoute | OAuth2ClientRoute
| OAuth2SessionList | OAuth2SessionList
@@ -48,10 +48,10 @@ export type Route =
const routeToSegments = (route: Route): string[] => { const routeToSegments = (route: Route): string[] => {
switch (route.type) { switch (route.type) {
case "home":
return [];
case "profile": case "profile":
return ["profile"]; return [];
case "sessions-overview":
return ["sessions-overview"];
case "verify-email": case "verify-email":
return ["emails", route.id, "verify"]; return ["emails", route.id, "verify"];
case "client": case "client":
@@ -97,11 +97,11 @@ export const segmentsToRoute = (segments: string[]): Route => {
// Special case for the home page // Special case for the home page
if (segments.length === 0 || (segments.length === 1 && segments[0] === "")) { if (segments.length === 0 || (segments.length === 1 && segments[0] === "")) {
return { type: "home" }; return { type: "profile" };
} }
if (matches("profile")) { if (matches("sessions-overview")) {
return { type: "profile" }; return { type: "sessions-overview" };
} }
if (matches("sessions")) { if (matches("sessions")) {
@@ -169,7 +169,7 @@ export const routeAtom = atom(
}, },
); );
const Home = lazy(() => import("./pages/Home")); const SessionsOverview = lazy(() => import("./pages/SessionsOverview"));
const Profile = lazy(() => import("./pages/Profile")); const Profile = lazy(() => import("./pages/Profile"));
const OAuth2Client = lazy(() => import("./pages/OAuth2Client")); const OAuth2Client = lazy(() => import("./pages/OAuth2Client"));
const BrowserSession = lazy(() => import("./pages/BrowserSession")); const BrowserSession = lazy(() => import("./pages/BrowserSession"));
@@ -182,10 +182,10 @@ const InnerRouter: React.FC = () => {
const route = useAtomValue(routeAtom); const route = useAtomValue(routeAtom);
switch (route.type) { switch (route.type) {
case "home":
return <Home />;
case "profile": case "profile":
return <Profile />; return <Profile />;
case "sessions-overview":
return <SessionsOverview />;
case "oauth2-session-list": case "oauth2-session-list":
return <OAuth2SessionList />; return <OAuth2SessionList />;
case "browser-session-list": case "browser-session-list":

View File

@@ -42,8 +42,8 @@ const Layout: React.FC<{ children?: React.ReactNode }> = ({ children }) => {
<UserGreeting userId={userId} /> <UserGreeting userId={userId} />
<NavBar> <NavBar>
<NavItem route={{ type: "home" }}>Sessions</NavItem>
<NavItem route={{ type: "profile" }}>Profile</NavItem> <NavItem route={{ type: "profile" }}>Profile</NavItem>
<NavItem route={{ type: "sessions-overview" }}>Sessions</NavItem>
</NavBar> </NavBar>
<main>{children}</main> <main>{children}</main>

View File

@@ -29,8 +29,8 @@ const meta = {
<Provider> <Provider>
<WithHomePage> <WithHomePage>
<NavBar {...props}> <NavBar {...props}>
<NavItem route={{ type: "home" }}>Home</NavItem> <NavItem route={{ type: "sessions-overview" }}>Sessions</NavItem>
<NavItem route={{ type: "profile" }}>Emails</NavItem> <NavItem route={{ type: "profile" }}>Profile</NavItem>
<ExternalLink href="https://example.com">External</ExternalLink> <ExternalLink href="https://example.com">External</ExternalLink>
</NavBar> </NavBar>
</WithHomePage> </WithHomePage>

View File

@@ -46,8 +46,8 @@ type Story = StoryObj<typeof NavItem>;
export const Active: Story = { export const Active: Story = {
args: { args: {
route: { type: "home" }, route: { type: "sessions-overview" },
children: "Home", children: "Sessions",
}, },
}; };

View File

@@ -59,7 +59,7 @@ describe("NavItem", () => {
it("render an active <NavItem />", () => { it("render an active <NavItem />", () => {
const component = create( const component = create(
<WithLocation path="/"> <WithLocation path="/">
<NavItem route={{ type: "home" }}>Active</NavItem> <NavItem route={{ type: "profile" }}>Active</NavItem>
</WithLocation>, </WithLocation>,
); );
const tree = component.toJSON(); const tree = component.toJSON();
@@ -69,7 +69,7 @@ describe("NavItem", () => {
it("render an inactive <NavItem />", () => { it("render an inactive <NavItem />", () => {
const component = create( const component = create(
<WithLocation path="/account"> <WithLocation path="/account">
<NavItem route={{ type: "home" }}>Inactive</NavItem> <NavItem route={{ type: "sessions-overview" }}>Inactive</NavItem>
</WithLocation>, </WithLocation>,
); );
const tree = component.toJSON(); const tree = component.toJSON();
@@ -79,7 +79,7 @@ describe("NavItem", () => {
it("renders a different route", () => { it("renders a different route", () => {
const component = create( const component = create(
<WithLocation path="/"> <WithLocation path="/">
<NavItem route={{ type: "profile" }}>Emails</NavItem> <NavItem route={{ type: "sessions-overview" }}>Sessions</NavItem>
</WithLocation>, </WithLocation>,
); );
const tree = component.toJSON(); const tree = component.toJSON();

View File

@@ -22,7 +22,7 @@ exports[`NavItem > render an inactive <NavItem /> 1`] = `
> >
<a <a
className="_navItem_8603fc" className="_navItem_8603fc"
href="/" href="/sessions-overview"
onClick={[Function]} onClick={[Function]}
> >
Inactive Inactive
@@ -36,10 +36,10 @@ exports[`NavItem > renders a different route 1`] = `
> >
<a <a
className="_navItem_8603fc" className="_navItem_8603fc"
href="/profile" href="/sessions-overview"
onClick={[Function]} onClick={[Function]}
> >
Emails Sessions
</a> </a>
</li> </li>
`; `;

View File

@@ -35,7 +35,7 @@ exports[`<UnverifiedEmailAlert /> > renders a warning when there are unverified
<a <a
class="_linkButton_4f14fc" class="_linkButton_4f14fc"
href="/profile" href="/"
> >
Review and verify Review and verify
</a> </a>

View File

@@ -17,7 +17,7 @@
display: flex; display: flex;
flex-direction: row; flex-direction: row;
justify-content: space-between; justify-content: space-between;
align-content: center; align-items: flex-start;
gap: var(--cpd-space-1x); gap: var(--cpd-space-1x);
} }

View File

@@ -20,7 +20,7 @@ import { appConfigAtom, locationAtom } from "../../Router";
import { makeFragmentData } from "../../gql"; import { makeFragmentData } from "../../gql";
import { FRAGMENT as EMAIL_FRAGMENT } from "../UserEmail"; import { FRAGMENT as EMAIL_FRAGMENT } from "../UserEmail";
import UserHome, { FRAGMENT } from "./UserHome"; import UserSessionsOverview, { FRAGMENT } from "./UserSessionsOverview";
type Props = { type Props = {
primaryEmail: string | null; primaryEmail: string | null;
@@ -86,14 +86,14 @@ const Template: React.FC<Props> = ({
return ( return (
<Provider> <Provider>
<WithHomePage> <WithHomePage>
<UserHome user={data} /> <UserSessionsOverview user={data} />
</WithHomePage> </WithHomePage>
</Provider> </Provider>
); );
}; };
const meta = { const meta = {
title: "Pages/User Home", title: "Pages/User Sessions Overview",
component: Template, component: Template,
tags: ["autodocs"], tags: ["autodocs"],
} satisfies Meta<typeof Template>; } satisfies Meta<typeof Template>;

View File

@@ -18,10 +18,10 @@ import { describe, expect, it } from "vitest";
import { makeFragmentData } from "../../gql"; import { makeFragmentData } from "../../gql";
import { FRAGMENT as EMAIL_FRAGMENT } from "../UserEmail"; import { FRAGMENT as EMAIL_FRAGMENT } from "../UserEmail";
import UserHome, { FRAGMENT } from "./"; import UserSessionsOverview, { FRAGMENT } from "./";
describe("UserHome", () => { describe("UserSessionsOverview", () => {
it("render an simple <UserHome />", () => { it("render an simple <UserSessionsOverview />", () => {
const primaryEmail = makeFragmentData( const primaryEmail = makeFragmentData(
{ {
id: "email:123", id: "email:123",
@@ -56,12 +56,12 @@ describe("UserHome", () => {
}, },
FRAGMENT, FRAGMENT,
); );
const component = create(<UserHome user={user} />); const component = create(<UserSessionsOverview user={user} />);
const tree = component.toJSON(); const tree = component.toJSON();
expect(tree).toMatchSnapshot(); expect(tree).toMatchSnapshot();
}); });
it("render a <UserHome /> with sessions", () => { it("render a <UserSessionsOverview /> with sessions", () => {
const primaryEmail = makeFragmentData( const primaryEmail = makeFragmentData(
{ {
id: "email:123", id: "email:123",
@@ -96,7 +96,7 @@ describe("UserHome", () => {
}, },
FRAGMENT, FRAGMENT,
); );
const component = create(<UserHome user={user} />); const component = create(<UserSessionsOverview user={user} />);
const tree = component.toJSON(); const tree = component.toJSON();
expect(tree).toMatchSnapshot(); expect(tree).toMatchSnapshot();
}); });

View File

@@ -19,10 +19,10 @@ import { FragmentType, graphql, useFragment } from "../../gql";
import Block from "../Block/Block"; import Block from "../Block/Block";
import BlockList from "../BlockList/BlockList"; import BlockList from "../BlockList/BlockList";
import styles from "./UserHome.module.css"; import styles from "./UserSessionsOverview.module.css";
export const FRAGMENT = graphql(/* GraphQL */ ` export const FRAGMENT = graphql(/* GraphQL */ `
fragment UserHome_user on User { fragment UserSessionsOverview_user on User {
id id
primaryEmail { primaryEmail {
@@ -48,7 +48,7 @@ export const FRAGMENT = graphql(/* GraphQL */ `
} }
`); `);
const UserHome: React.FC<{ const UserSessionsOverview: React.FC<{
user: FragmentType<typeof FRAGMENT>; user: FragmentType<typeof FRAGMENT>;
}> = ({ user }) => { }> = ({ user }) => {
const data = useFragment(FRAGMENT, user); const data = useFragment(FRAGMENT, user);
@@ -106,4 +106,4 @@ const UserHome: React.FC<{
); );
}; };
export default UserHome; export default UserSessionsOverview;

View File

@@ -1,6 +1,6 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`UserHome > render a <UserHome /> with sessions 1`] = ` exports[`UserSessionsOverview > render a <UserSessionsOverview /> with sessions 1`] = `
<div <div
className="_blockList_f8cc7f" className="_blockList_f8cc7f"
> >
@@ -10,10 +10,10 @@ exports[`UserHome > render a <UserHome /> with sessions 1`] = `
Where you're signed in Where you're signed in
</h3> </h3>
<div <div
className="_block_17898c _sessionListBlock_5d2854" className="_block_17898c _sessionListBlock_1c0f31"
> >
<div <div
className="_sessionListBlockInfo_5d2854" className="_sessionListBlockInfo_1c0f31"
> >
<h6 <h6
className="_font-body-md-semibold_1g2sj_69" className="_font-body-md-semibold_1g2sj_69"
@@ -38,10 +38,10 @@ exports[`UserHome > render a <UserHome /> with sessions 1`] = `
</a> </a>
</div> </div>
<div <div
className="_block_17898c _sessionListBlock_5d2854" className="_block_17898c _sessionListBlock_1c0f31"
> >
<div <div
className="_sessionListBlockInfo_5d2854" className="_sessionListBlockInfo_1c0f31"
> >
<h6 <h6
className="_font-body-md-semibold_1g2sj_69" className="_font-body-md-semibold_1g2sj_69"
@@ -66,10 +66,10 @@ exports[`UserHome > render a <UserHome /> with sessions 1`] = `
</a> </a>
</div> </div>
<div <div
className="_block_17898c _sessionListBlock_5d2854" className="_block_17898c _sessionListBlock_1c0f31"
> >
<div <div
className="_sessionListBlockInfo_5d2854" className="_sessionListBlockInfo_1c0f31"
> >
<h6 <h6
className="_font-body-md-semibold_1g2sj_69" className="_font-body-md-semibold_1g2sj_69"
@@ -96,7 +96,7 @@ exports[`UserHome > render a <UserHome /> with sessions 1`] = `
</div> </div>
`; `;
exports[`UserHome > render an simple <UserHome /> 1`] = ` exports[`UserSessionsOverview > render an simple <UserSessionsOverview /> 1`] = `
<div <div
className="_blockList_f8cc7f" className="_blockList_f8cc7f"
> >
@@ -106,10 +106,10 @@ exports[`UserHome > render an simple <UserHome /> 1`] = `
Where you're signed in Where you're signed in
</h3> </h3>
<div <div
className="_block_17898c _sessionListBlock_5d2854" className="_block_17898c _sessionListBlock_1c0f31"
> >
<div <div
className="_sessionListBlockInfo_5d2854" className="_sessionListBlockInfo_1c0f31"
> >
<h6 <h6
className="_font-body-md-semibold_1g2sj_69" className="_font-body-md-semibold_1g2sj_69"
@@ -134,10 +134,10 @@ exports[`UserHome > render an simple <UserHome /> 1`] = `
</a> </a>
</div> </div>
<div <div
className="_block_17898c _sessionListBlock_5d2854" className="_block_17898c _sessionListBlock_1c0f31"
> >
<div <div
className="_sessionListBlockInfo_5d2854" className="_sessionListBlockInfo_1c0f31"
> >
<h6 <h6
className="_font-body-md-semibold_1g2sj_69" className="_font-body-md-semibold_1g2sj_69"
@@ -162,10 +162,10 @@ exports[`UserHome > render an simple <UserHome /> 1`] = `
</a> </a>
</div> </div>
<div <div
className="_block_17898c _sessionListBlock_5d2854" className="_block_17898c _sessionListBlock_1c0f31"
> >
<div <div
className="_sessionListBlockInfo_5d2854" className="_sessionListBlockInfo_1c0f31"
> >
<h6 <h6
className="_font-body-md-semibold_1g2sj_69" className="_font-body-md-semibold_1g2sj_69"

View File

@@ -12,4 +12,4 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
export { default, FRAGMENT } from "./UserHome"; export { default, FRAGMENT } from "./UserSessionsOverview";

View File

@@ -2,8 +2,9 @@
exports[`<Layout /> > renders app navigation correctly 1`] = ` exports[`<Layout /> > renders app navigation correctly 1`] = `
<a <a
aria-current="page"
class="_navItem_8603fc" class="_navItem_8603fc"
href="/profile" href="/"
> >
Profile Profile
</a> </a>
@@ -11,9 +12,8 @@ exports[`<Layout /> > renders app navigation correctly 1`] = `
exports[`<Layout /> > renders app navigation correctly 2`] = ` exports[`<Layout /> > renders app navigation correctly 2`] = `
<a <a
aria-current="page"
class="_navItem_8603fc" class="_navItem_8603fc"
href="/" href="/sessions-overview"
> >
Sessions Sessions
</a> </a>

View File

@@ -47,8 +47,6 @@ const documents = {
types.SetPrimaryEmailDocument, types.SetPrimaryEmailDocument,
"\n query UserGreeting($userId: ID!) {\n user(id: $userId) {\n id\n username\n matrix {\n mxid\n displayName\n }\n }\n viewer {\n __typename\n\n ... on User {\n id\n ...UnverifiedEmailAlert\n }\n }\n }\n": "\n query UserGreeting($userId: ID!) {\n user(id: $userId) {\n id\n username\n matrix {\n mxid\n displayName\n }\n }\n viewer {\n __typename\n\n ... on User {\n id\n ...UnverifiedEmailAlert\n }\n }\n }\n":
types.UserGreetingDocument, types.UserGreetingDocument,
"\n fragment UserHome_user on User {\n id\n\n primaryEmail {\n id\n ...UserEmail_email\n }\n\n confirmedEmails: emails(first: 0, state: CONFIRMED) {\n totalCount\n }\n\n browserSessions(first: 0, state: ACTIVE) {\n totalCount\n }\n\n oauth2Sessions(first: 0, state: ACTIVE) {\n totalCount\n }\n\n compatSessions(first: 0, state: ACTIVE) {\n totalCount\n }\n }\n":
types.UserHome_UserFragmentDoc,
"\n mutation AddEmail($userId: ID!, $email: String!) {\n addEmail(input: { userId: $userId, email: $email }) {\n status\n violations\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 violations\n email {\n id\n ...UserEmail_email\n }\n }\n }\n":
types.AddEmailDocument, types.AddEmailDocument,
"\n query UserEmailListQuery(\n $userId: ID!\n $first: Int\n $after: String\n $last: Int\n $before: String\n ) {\n user(id: $userId) {\n id\n\n emails(first: $first, after: $after, last: $last, before: $before) {\n edges {\n cursor\n node {\n id\n ...UserEmail_email\n }\n }\n totalCount\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n }\n }\n": "\n query UserEmailListQuery(\n $userId: ID!\n $first: Int\n $after: String\n $last: Int\n $before: String\n ) {\n user(id: $userId) {\n id\n\n emails(first: $first, after: $after, last: $last, before: $before) {\n edges {\n cursor\n node {\n id\n ...UserEmail_email\n }\n }\n totalCount\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n }\n }\n":
@@ -57,6 +55,8 @@ const documents = {
types.UserPrimaryEmailDocument, types.UserPrimaryEmailDocument,
"\n mutation SetDisplayName($userId: ID!, $displayName: String) {\n setDisplayName(input: { userId: $userId, displayName: $displayName }) {\n status\n user {\n id\n matrix {\n displayName\n }\n }\n }\n }\n": "\n mutation SetDisplayName($userId: ID!, $displayName: String) {\n setDisplayName(input: { userId: $userId, displayName: $displayName }) {\n status\n user {\n id\n matrix {\n displayName\n }\n }\n }\n }\n":
types.SetDisplayNameDocument, types.SetDisplayNameDocument,
"\n fragment UserSessionsOverview_user on User {\n id\n\n primaryEmail {\n id\n ...UserEmail_email\n }\n\n confirmedEmails: emails(first: 0, state: CONFIRMED) {\n totalCount\n }\n\n browserSessions(first: 0, state: ACTIVE) {\n totalCount\n }\n\n oauth2Sessions(first: 0, state: ACTIVE) {\n totalCount\n }\n\n compatSessions(first: 0, state: ACTIVE) {\n totalCount\n }\n }\n":
types.UserSessionsOverview_UserFragmentDoc,
"\n fragment UserEmail_verifyEmail on UserEmail {\n id\n email\n }\n": "\n fragment UserEmail_verifyEmail on UserEmail {\n id\n email\n }\n":
types.UserEmail_VerifyEmailFragmentDoc, types.UserEmail_VerifyEmailFragmentDoc,
"\n mutation VerifyEmail($id: ID!, $code: String!) {\n verifyEmail(input: { userEmailId: $id, code: $code }) {\n status\n\n user {\n id\n primaryEmail {\n id\n }\n }\n\n email {\n id\n ...UserEmail_email\n }\n }\n }\n": "\n mutation VerifyEmail($id: ID!, $code: String!) {\n verifyEmail(input: { userEmailId: $id, code: $code }) {\n status\n\n user {\n id\n primaryEmail {\n id\n }\n }\n\n email {\n id\n ...UserEmail_email\n }\n }\n }\n":
@@ -65,10 +65,10 @@ const documents = {
types.ResendVerificationEmailDocument, types.ResendVerificationEmailDocument,
"\n query BrowserSessionQuery($id: ID!) {\n browserSession(id: $id) {\n id\n createdAt\n lastAuthentication {\n id\n createdAt\n }\n user {\n id\n username\n }\n }\n }\n": "\n query BrowserSessionQuery($id: ID!) {\n browserSession(id: $id) {\n id\n createdAt\n lastAuthentication {\n id\n createdAt\n }\n user {\n id\n username\n }\n }\n }\n":
types.BrowserSessionQueryDocument, types.BrowserSessionQueryDocument,
"\n query HomeQuery {\n viewer {\n __typename\n\n ... on User {\n id\n ...UserHome_user\n }\n }\n }\n":
types.HomeQueryDocument,
"\n query OAuth2ClientQuery($id: ID!) {\n oauth2Client(id: $id) {\n id\n clientId\n clientName\n clientUri\n tosUri\n policyUri\n redirectUris\n }\n }\n": "\n query OAuth2ClientQuery($id: ID!) {\n oauth2Client(id: $id) {\n id\n clientId\n clientName\n clientUri\n tosUri\n policyUri\n redirectUris\n }\n }\n":
types.OAuth2ClientQueryDocument, types.OAuth2ClientQueryDocument,
"\n query SessionsOverviewQuery {\n viewer {\n __typename\n\n ... on User {\n id\n ...UserSessionsOverview_user\n }\n }\n }\n":
types.SessionsOverviewQueryDocument,
"\n query VerifyEmailQuery($id: ID!) {\n userEmail(id: $id) {\n ...UserEmail_verifyEmail\n }\n }\n": "\n query VerifyEmailQuery($id: ID!) {\n userEmail(id: $id) {\n ...UserEmail_verifyEmail\n }\n }\n":
types.VerifyEmailQueryDocument, types.VerifyEmailQueryDocument,
}; };
@@ -189,12 +189,6 @@ export function graphql(
export function graphql( export function graphql(
source: "\n query UserGreeting($userId: ID!) {\n user(id: $userId) {\n id\n username\n matrix {\n mxid\n displayName\n }\n }\n viewer {\n __typename\n\n ... on User {\n id\n ...UnverifiedEmailAlert\n }\n }\n }\n", source: "\n query UserGreeting($userId: ID!) {\n user(id: $userId) {\n id\n username\n matrix {\n mxid\n displayName\n }\n }\n viewer {\n __typename\n\n ... on User {\n id\n ...UnverifiedEmailAlert\n }\n }\n }\n",
): (typeof documents)["\n query UserGreeting($userId: ID!) {\n user(id: $userId) {\n id\n username\n matrix {\n mxid\n displayName\n }\n }\n viewer {\n __typename\n\n ... on User {\n id\n ...UnverifiedEmailAlert\n }\n }\n }\n"]; ): (typeof documents)["\n query UserGreeting($userId: ID!) {\n user(id: $userId) {\n id\n username\n matrix {\n mxid\n displayName\n }\n }\n viewer {\n __typename\n\n ... on User {\n id\n ...UnverifiedEmailAlert\n }\n }\n }\n"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(
source: "\n fragment UserHome_user on User {\n id\n\n primaryEmail {\n id\n ...UserEmail_email\n }\n\n confirmedEmails: emails(first: 0, state: CONFIRMED) {\n totalCount\n }\n\n browserSessions(first: 0, state: ACTIVE) {\n totalCount\n }\n\n oauth2Sessions(first: 0, state: ACTIVE) {\n totalCount\n }\n\n compatSessions(first: 0, state: ACTIVE) {\n totalCount\n }\n }\n",
): (typeof documents)["\n fragment UserHome_user on User {\n id\n\n primaryEmail {\n id\n ...UserEmail_email\n }\n\n confirmedEmails: emails(first: 0, state: CONFIRMED) {\n totalCount\n }\n\n browserSessions(first: 0, state: ACTIVE) {\n totalCount\n }\n\n oauth2Sessions(first: 0, state: ACTIVE) {\n totalCount\n }\n\n compatSessions(first: 0, state: ACTIVE) {\n totalCount\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.
*/ */
@@ -219,6 +213,12 @@ export function graphql(
export function graphql( export function graphql(
source: "\n mutation SetDisplayName($userId: ID!, $displayName: String) {\n setDisplayName(input: { userId: $userId, displayName: $displayName }) {\n status\n user {\n id\n matrix {\n displayName\n }\n }\n }\n }\n", source: "\n mutation SetDisplayName($userId: ID!, $displayName: String) {\n setDisplayName(input: { userId: $userId, displayName: $displayName }) {\n status\n user {\n id\n matrix {\n displayName\n }\n }\n }\n }\n",
): (typeof documents)["\n mutation SetDisplayName($userId: ID!, $displayName: String) {\n setDisplayName(input: { userId: $userId, displayName: $displayName }) {\n status\n user {\n id\n matrix {\n displayName\n }\n }\n }\n }\n"]; ): (typeof documents)["\n mutation SetDisplayName($userId: ID!, $displayName: String) {\n setDisplayName(input: { userId: $userId, displayName: $displayName }) {\n status\n user {\n id\n matrix {\n displayName\n }\n }\n }\n }\n"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(
source: "\n fragment UserSessionsOverview_user on User {\n id\n\n primaryEmail {\n id\n ...UserEmail_email\n }\n\n confirmedEmails: emails(first: 0, state: CONFIRMED) {\n totalCount\n }\n\n browserSessions(first: 0, state: ACTIVE) {\n totalCount\n }\n\n oauth2Sessions(first: 0, state: ACTIVE) {\n totalCount\n }\n\n compatSessions(first: 0, state: ACTIVE) {\n totalCount\n }\n }\n",
): (typeof documents)["\n fragment UserSessionsOverview_user on User {\n id\n\n primaryEmail {\n id\n ...UserEmail_email\n }\n\n confirmedEmails: emails(first: 0, state: CONFIRMED) {\n totalCount\n }\n\n browserSessions(first: 0, state: ACTIVE) {\n totalCount\n }\n\n oauth2Sessions(first: 0, state: ACTIVE) {\n totalCount\n }\n\n compatSessions(first: 0, state: ACTIVE) {\n totalCount\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.
*/ */
@@ -247,14 +247,14 @@ 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 HomeQuery {\n viewer {\n __typename\n\n ... on User {\n id\n ...UserHome_user\n }\n }\n }\n", source: "\n query OAuth2ClientQuery($id: ID!) {\n oauth2Client(id: $id) {\n id\n clientId\n clientName\n clientUri\n tosUri\n policyUri\n redirectUris\n }\n }\n",
): (typeof documents)["\n query HomeQuery {\n viewer {\n __typename\n\n ... on User {\n id\n ...UserHome_user\n }\n }\n }\n"]; ): (typeof documents)["\n query OAuth2ClientQuery($id: ID!) {\n oauth2Client(id: $id) {\n id\n clientId\n clientName\n clientUri\n tosUri\n policyUri\n redirectUris\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.
*/ */
export function graphql( export function graphql(
source: "\n query OAuth2ClientQuery($id: ID!) {\n oauth2Client(id: $id) {\n id\n clientId\n clientName\n clientUri\n tosUri\n policyUri\n redirectUris\n }\n }\n", source: "\n query SessionsOverviewQuery {\n viewer {\n __typename\n\n ... on User {\n id\n ...UserSessionsOverview_user\n }\n }\n }\n",
): (typeof documents)["\n query OAuth2ClientQuery($id: ID!) {\n oauth2Client(id: $id) {\n id\n clientId\n clientName\n clientUri\n tosUri\n policyUri\n redirectUris\n }\n }\n"]; ): (typeof documents)["\n query SessionsOverviewQuery {\n viewer {\n __typename\n\n ... on User {\n id\n ...UserSessionsOverview_user\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.
*/ */

View File

@@ -1214,29 +1214,6 @@ export type UserGreetingQuery = {
}); });
}; };
export type UserHome_UserFragment = {
__typename?: "User";
id: string;
primaryEmail?:
| ({ __typename?: "UserEmail"; id: string } & {
" $fragmentRefs"?: { UserEmail_EmailFragment: UserEmail_EmailFragment };
})
| null;
confirmedEmails: { __typename?: "UserEmailConnection"; totalCount: number };
browserSessions: {
__typename?: "BrowserSessionConnection";
totalCount: number;
};
oauth2Sessions: {
__typename?: "Oauth2SessionConnection";
totalCount: number;
};
compatSessions: {
__typename?: "CompatSessionConnection";
totalCount: number;
};
} & { " $fragmentName"?: "UserHome_UserFragment" };
export type AddEmailMutationVariables = Exact<{ export type AddEmailMutationVariables = Exact<{
userId: Scalars["ID"]["input"]; userId: Scalars["ID"]["input"];
email: Scalars["String"]["input"]; email: Scalars["String"]["input"];
@@ -1325,6 +1302,29 @@ export type SetDisplayNameMutation = {
}; };
}; };
export type UserSessionsOverview_UserFragment = {
__typename?: "User";
id: string;
primaryEmail?:
| ({ __typename?: "UserEmail"; id: string } & {
" $fragmentRefs"?: { UserEmail_EmailFragment: UserEmail_EmailFragment };
})
| null;
confirmedEmails: { __typename?: "UserEmailConnection"; totalCount: number };
browserSessions: {
__typename?: "BrowserSessionConnection";
totalCount: number;
};
oauth2Sessions: {
__typename?: "Oauth2SessionConnection";
totalCount: number;
};
compatSessions: {
__typename?: "CompatSessionConnection";
totalCount: number;
};
} & { " $fragmentName"?: "UserSessionsOverview_UserFragment" };
export type UserEmail_VerifyEmailFragment = { export type UserEmail_VerifyEmailFragment = {
__typename?: "UserEmail"; __typename?: "UserEmail";
id: string; id: string;
@@ -1395,17 +1395,6 @@ export type BrowserSessionQueryQuery = {
} | null; } | null;
}; };
export type HomeQueryQueryVariables = Exact<{ [key: string]: never }>;
export type HomeQueryQuery = {
__typename?: "Query";
viewer:
| { __typename: "Anonymous" }
| ({ __typename: "User"; id: string } & {
" $fragmentRefs"?: { UserHome_UserFragment: UserHome_UserFragment };
});
};
export type OAuth2ClientQueryQueryVariables = Exact<{ export type OAuth2ClientQueryQueryVariables = Exact<{
id: Scalars["ID"]["input"]; id: Scalars["ID"]["input"];
}>; }>;
@@ -1424,6 +1413,21 @@ export type OAuth2ClientQueryQuery = {
} | null; } | null;
}; };
export type SessionsOverviewQueryQueryVariables = Exact<{
[key: string]: never;
}>;
export type SessionsOverviewQueryQuery = {
__typename?: "Query";
viewer:
| { __typename: "Anonymous" }
| ({ __typename: "User"; id: string } & {
" $fragmentRefs"?: {
UserSessionsOverview_UserFragment: UserSessionsOverview_UserFragment;
};
});
};
export type VerifyEmailQueryQueryVariables = Exact<{ export type VerifyEmailQueryQueryVariables = Exact<{
id: Scalars["ID"]["input"]; id: Scalars["ID"]["input"];
}>; }>;
@@ -1640,12 +1644,12 @@ export const UserEmail_EmailFragmentDoc = {
}, },
], ],
} as unknown as DocumentNode<UserEmail_EmailFragment, unknown>; } as unknown as DocumentNode<UserEmail_EmailFragment, unknown>;
export const UserHome_UserFragmentDoc = { export const UserSessionsOverview_UserFragmentDoc = {
kind: "Document", kind: "Document",
definitions: [ definitions: [
{ {
kind: "FragmentDefinition", kind: "FragmentDefinition",
name: { kind: "Name", value: "UserHome_user" }, name: { kind: "Name", value: "UserSessionsOverview_user" },
typeCondition: { typeCondition: {
kind: "NamedType", kind: "NamedType",
name: { kind: "Name", value: "User" }, name: { kind: "Name", value: "User" },
@@ -1777,7 +1781,7 @@ export const UserHome_UserFragmentDoc = {
}, },
}, },
], ],
} as unknown as DocumentNode<UserHome_UserFragment, unknown>; } as unknown as DocumentNode<UserSessionsOverview_UserFragment, unknown>;
export const UserEmail_VerifyEmailFragmentDoc = { export const UserEmail_VerifyEmailFragmentDoc = {
kind: "Document", kind: "Document",
definitions: [ definitions: [
@@ -3942,13 +3946,70 @@ export const BrowserSessionQueryDocument = {
BrowserSessionQueryQuery, BrowserSessionQueryQuery,
BrowserSessionQueryQueryVariables BrowserSessionQueryQueryVariables
>; >;
export const HomeQueryDocument = { export const OAuth2ClientQueryDocument = {
kind: "Document", kind: "Document",
definitions: [ definitions: [
{ {
kind: "OperationDefinition", kind: "OperationDefinition",
operation: "query", operation: "query",
name: { kind: "Name", value: "HomeQuery" }, name: { kind: "Name", value: "OAuth2ClientQuery" },
variableDefinitions: [
{
kind: "VariableDefinition",
variable: { kind: "Variable", name: { kind: "Name", value: "id" } },
type: {
kind: "NonNullType",
type: { kind: "NamedType", name: { kind: "Name", value: "ID" } },
},
},
],
selectionSet: {
kind: "SelectionSet",
selections: [
{
kind: "Field",
name: { kind: "Name", value: "oauth2Client" },
arguments: [
{
kind: "Argument",
name: { kind: "Name", value: "id" },
value: {
kind: "Variable",
name: { kind: "Name", value: "id" },
},
},
],
selectionSet: {
kind: "SelectionSet",
selections: [
{ kind: "Field", name: { kind: "Name", value: "id" } },
{ kind: "Field", name: { kind: "Name", value: "clientId" } },
{ kind: "Field", name: { kind: "Name", value: "clientName" } },
{ kind: "Field", name: { kind: "Name", value: "clientUri" } },
{ kind: "Field", name: { kind: "Name", value: "tosUri" } },
{ kind: "Field", name: { kind: "Name", value: "policyUri" } },
{
kind: "Field",
name: { kind: "Name", value: "redirectUris" },
},
],
},
},
],
},
},
],
} as unknown as DocumentNode<
OAuth2ClientQueryQuery,
OAuth2ClientQueryQueryVariables
>;
export const SessionsOverviewQueryDocument = {
kind: "Document",
definitions: [
{
kind: "OperationDefinition",
operation: "query",
name: { kind: "Name", value: "SessionsOverviewQuery" },
selectionSet: { selectionSet: {
kind: "SelectionSet", kind: "SelectionSet",
selections: [ selections: [
@@ -3971,7 +4032,10 @@ export const HomeQueryDocument = {
{ kind: "Field", name: { kind: "Name", value: "id" } }, { kind: "Field", name: { kind: "Name", value: "id" } },
{ {
kind: "FragmentSpread", kind: "FragmentSpread",
name: { kind: "Name", value: "UserHome_user" }, name: {
kind: "Name",
value: "UserSessionsOverview_user",
},
}, },
], ],
}, },
@@ -4000,7 +4064,7 @@ export const HomeQueryDocument = {
}, },
{ {
kind: "FragmentDefinition", kind: "FragmentDefinition",
name: { kind: "Name", value: "UserHome_user" }, name: { kind: "Name", value: "UserSessionsOverview_user" },
typeCondition: { typeCondition: {
kind: "NamedType", kind: "NamedType",
name: { kind: "Name", value: "User" }, name: { kind: "Name", value: "User" },
@@ -4116,63 +4180,9 @@ export const HomeQueryDocument = {
}, },
}, },
], ],
} as unknown as DocumentNode<HomeQueryQuery, HomeQueryQueryVariables>;
export const OAuth2ClientQueryDocument = {
kind: "Document",
definitions: [
{
kind: "OperationDefinition",
operation: "query",
name: { kind: "Name", value: "OAuth2ClientQuery" },
variableDefinitions: [
{
kind: "VariableDefinition",
variable: { kind: "Variable", name: { kind: "Name", value: "id" } },
type: {
kind: "NonNullType",
type: { kind: "NamedType", name: { kind: "Name", value: "ID" } },
},
},
],
selectionSet: {
kind: "SelectionSet",
selections: [
{
kind: "Field",
name: { kind: "Name", value: "oauth2Client" },
arguments: [
{
kind: "Argument",
name: { kind: "Name", value: "id" },
value: {
kind: "Variable",
name: { kind: "Name", value: "id" },
},
},
],
selectionSet: {
kind: "SelectionSet",
selections: [
{ kind: "Field", name: { kind: "Name", value: "id" } },
{ kind: "Field", name: { kind: "Name", value: "clientId" } },
{ kind: "Field", name: { kind: "Name", value: "clientName" } },
{ kind: "Field", name: { kind: "Name", value: "clientUri" } },
{ kind: "Field", name: { kind: "Name", value: "tosUri" } },
{ kind: "Field", name: { kind: "Name", value: "policyUri" } },
{
kind: "Field",
name: { kind: "Name", value: "redirectUris" },
},
],
},
},
],
},
},
],
} as unknown as DocumentNode< } as unknown as DocumentNode<
OAuth2ClientQueryQuery, SessionsOverviewQueryQuery,
OAuth2ClientQueryQueryVariables SessionsOverviewQueryQueryVariables
>; >;
export const VerifyEmailQueryDocument = { export const VerifyEmailQueryDocument = {
kind: "Document", kind: "Document",

View File

@@ -18,28 +18,28 @@ import { atomWithQuery } from "jotai-urql";
import { mapQueryAtom } from "../atoms"; import { mapQueryAtom } from "../atoms";
import GraphQLError from "../components/GraphQLError"; import GraphQLError from "../components/GraphQLError";
import NotLoggedIn from "../components/NotLoggedIn"; import NotLoggedIn from "../components/NotLoggedIn";
import UserHome from "../components/UserHome"; import UserSessionsOverview from "../components/UserSessionsOverview";
import { graphql } from "../gql"; import { graphql } from "../gql";
import { isErr, unwrapErr, unwrapOk } from "../result"; import { isErr, unwrapErr, unwrapOk } from "../result";
const QUERY = graphql(/* GraphQL */ ` const QUERY = graphql(/* GraphQL */ `
query HomeQuery { query SessionsOverviewQuery {
viewer { viewer {
__typename __typename
... on User { ... on User {
id id
...UserHome_user ...UserSessionsOverview_user
} }
} }
} }
`); `);
const homeQueryAtom = atomWithQuery({ const sessionsOverviewQueryAtom = atomWithQuery({
query: QUERY, query: QUERY,
}); });
const homeAtom = mapQueryAtom(homeQueryAtom, (data) => { const sessionsOverviewAtom = mapQueryAtom(sessionsOverviewQueryAtom, (data) => {
if (data.viewer?.__typename === "User") { if (data.viewer?.__typename === "User") {
return data.viewer; return data.viewer;
} }
@@ -47,14 +47,14 @@ const homeAtom = mapQueryAtom(homeQueryAtom, (data) => {
return null; return null;
}); });
const Home: React.FC = () => { const SessionsOverview: React.FC = () => {
const result = useAtomValue(homeAtom); const result = useAtomValue(sessionsOverviewAtom);
if (isErr(result)) return <GraphQLError error={unwrapErr(result)} />; if (isErr(result)) return <GraphQLError error={unwrapErr(result)} />;
const data = unwrapOk(result); const data = unwrapOk(result);
if (data === null) return <NotLoggedIn />; if (data === null) return <NotLoggedIn />;
return <UserHome user={data} />; return <UserSessionsOverview user={data} />;
}; };
export default Home; export default SessionsOverview;

View File

@@ -37,7 +37,7 @@ const HydrateLocation: React.FC<React.PropsWithChildren<{ path: string }>> = ({
* ``` * ```
* const component = create( * const component = create(
<WithLocation path="/"> <WithLocation path="/">
<NavItem route={{ type: "home" }}>Active</NavItem> <NavItem route={{ type: "profile" }}>Active</NavItem>
</WithLocation>, </WithLocation>,
); );
* ``` * ```