Rename Home tab to Sessions (#1568)

* rename /account/emails route to profile

* rename tab to sessions

* quick design pass and new session labels

* align copy on list pages with home page

* comment

* remove support for /emails

* bad unit test for Layout

* update snapshots, fix layout test

* fix snapshots from old version of compound

* better layout test

* coverage?

* userhome styles

* move no primary email alert to email list

* update snapshots

* Remove obselete snapshot & remove unnecessary logs

---------

Co-authored-by: Quentin Gliech <quenting@element.io>
This commit is contained in:
Kerry
2023-08-26 02:17:46 +12:00
committed by GitHub
parent bd2c138753
commit 8d7205bc5b
13 changed files with 225 additions and 451 deletions

View File

@@ -1,3 +0,0 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`Router > routes 1`] = `"Loading..."`;

View File

@@ -146,7 +146,7 @@ const BrowserSessionList: React.FC<{ userId: string }> = ({ userId }) => {
return (
<BlockList>
<Title>List of browser sessions:</Title>
<Title>Browser:</Title>
<PaginationControls
onPrev={prevPage ? (): void => paginate(prevPage) : null}
onNext={nextPage ? (): void => paginate(nextPage) : null}

View File

@@ -118,8 +118,7 @@ const CompatSessionList: React.FC<{ userId: string }> = ({ userId }) => {
if (isErr(result)) return <GraphQLError error={unwrapErr(result)} />;
const compatSessionList = unwrapOk(result);
if (compatSessionList === null)
return <>Failed to load list of compatibility sessions.</>;
if (compatSessionList === null) return <>Failed to load sessions.</>;
const paginate = (pagination: Pagination): void => {
startTransition(() => {
@@ -138,7 +137,7 @@ const CompatSessionList: React.FC<{ userId: string }> = ({ userId }) => {
return (
<BlockList>
<Title>List of compatibility sessions:</Title>
<Title>Regular apps</Title>
<label>
<input
type="checkbox"

View File

@@ -74,6 +74,6 @@ describe("<Layout />", () => {
);
expect(await component.findByText("Profile")).toMatchSnapshot();
expect(await component.findByText("Home")).toMatchSnapshot();
expect(await component.findByText("Sessions")).toMatchSnapshot();
});
});

View File

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

View File

@@ -123,8 +123,7 @@ const OAuth2SessionList: React.FC<Props> = ({ userId }) => {
if (isErr(result)) return <GraphQLError error={unwrapErr(result)} />;
const oauth2Sessions = unwrapOk(result);
if (oauth2Sessions === null)
return <>Failed to load OAuth 2.0 session list</>;
if (oauth2Sessions === null) return <>Failed to load sessions.</>;
const paginate = (pagination: Pagination): void => {
startTransition(() => {
@@ -143,7 +142,7 @@ const OAuth2SessionList: React.FC<Props> = ({ userId }) => {
return (
<BlockList>
<Title>List of OAuth 2.0 sessions:</Title>
<Title>New apps:</Title>
<label>
<input
type="checkbox"

View File

@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { Alert } from "@vector-im/compound-web";
import { atom, useAtom, useAtomValue, useSetAtom } from "jotai";
import { atomFamily } from "jotai/utils";
import { atomWithQuery } from "jotai-urql";
@@ -154,6 +155,8 @@ const UserEmailList: React.FC<{
setRoute({ type: "verify-email", id });
};
const showNoPrimaryEmailAlert = !!result && !primaryEmailId;
return (
<BlockList>
<PaginationControls
@@ -162,6 +165,9 @@ const UserEmailList: React.FC<{
onNext={nextPage ? (): void => paginate(nextPage) : null}
disabled={pending}
/>
{showNoPrimaryEmailAlert && (
<Alert type="critical" title="No primary email address" />
)}
{result.data?.user?.emails?.edges?.map((edge) => (
<UserEmail
email={edge.node}

View File

@@ -0,0 +1,34 @@
/* 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.
*/
.session-list {
margin-top: var(--cpd-space-4x);
display: flex;
flex-direction: column;
gap: var(--cpd-space-2x);
}
.session-list-block {
display: flex;
flex-direction: row;
justify-content: space-between;
align-content: center;
gap: var(--cpd-space-1x);
}
.session-list-block-info {
display: flex;
flex-direction: column;
}

View File

@@ -123,17 +123,6 @@ export const Empty: Story = {
},
};
export const NoPrimaryEmail: Story = {
args: {
primaryEmail: null,
unverifiedEmails: 0,
confirmedEmails: 0,
oauth2Sessions: 0,
compatSessions: 0,
browserSessions: 0,
},
};
export const UnverifiedEmails: Story = {
args: {
primaryEmail: "hello@example.com",

View File

@@ -61,7 +61,7 @@ describe("UserHome", () => {
expect(tree).toMatchSnapshot();
});
it("render a <UserHome /> with additional emails", () => {
it("render a <UserHome /> with sessions", () => {
const primaryEmail = makeFragmentData(
{
id: "email:123",
@@ -79,85 +79,17 @@ describe("UserHome", () => {
...primaryEmail,
},
compatSessions: {
totalCount: 0,
},
browserSessions: {
totalCount: 0,
},
oauth2Sessions: {
totalCount: 0,
},
unverifiedEmails: {
totalCount: 0,
},
confirmedEmails: {
totalCount: 4,
},
},
FRAGMENT,
);
const component = create(<UserHome user={user} />);
const tree = component.toJSON();
expect(tree).toMatchSnapshot();
});
it("render a <UserHome /> without primary email", () => {
const user = makeFragmentData(
{
id: "user:123",
primaryEmail: null,
compatSessions: {
totalCount: 0,
},
browserSessions: {
totalCount: 0,
},
oauth2Sessions: {
totalCount: 0,
},
unverifiedEmails: {
totalCount: 0,
},
confirmedEmails: {
totalCount: 0,
},
},
FRAGMENT,
);
const component = create(<UserHome user={user} />);
const tree = component.toJSON();
expect(tree).toMatchSnapshot();
});
it("render a <UserHome /> with an unverified email", () => {
const primaryEmail = makeFragmentData(
{
id: "email:123",
email: "hello@example.com",
confirmedAt: new Date(),
},
EMAIL_FRAGMENT,
);
const user = makeFragmentData(
{
id: "user:123",
primaryEmail: {
id: "email:123",
...primaryEmail,
},
compatSessions: {
totalCount: 0,
},
browserSessions: {
totalCount: 0,
},
oauth2Sessions: {
totalCount: 0,
},
unverifiedEmails: {
totalCount: 1,
},
browserSessions: {
totalCount: 2,
},
oauth2Sessions: {
totalCount: 3,
},
unverifiedEmails: {
totalCount: 0,
},
confirmedEmails: {
totalCount: 1,
},

View File

@@ -12,12 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { Alert, Body } from "@vector-im/compound-web";
import { Alert, Body, H3, H6 } from "@vector-im/compound-web";
import { useState } from "react";
import { Link } from "../../Router";
import { FragmentType, graphql, useFragment } from "../../gql";
import UserEmail from "../UserEmail";
import Block from "../Block/Block";
import styles from "./UserHome.module.css";
export const FRAGMENT = graphql(/* GraphQL */ `
fragment UserHome_user on User {
@@ -60,6 +62,15 @@ const UserHome: React.FC<{
setDismiss(true);
};
// allow this until we get i18n
const pluraliseSession = (count: number): string =>
count === 1 ? "session" : "sessions";
// user friendly description of sessions is:
// browser -> browser
// oauth2 sessions -> New apps
// compatibility sessions -> Regular apps
return (
<>
{data.unverifiedEmails.totalCount > 0 && !dismiss && (
@@ -68,32 +79,40 @@ const UserHome: React.FC<{
address(es). <Link route={{ type: "profile" }}>Check</Link>
</Alert>
)}
{data.primaryEmail ? (
<UserEmail email={data.primaryEmail} isPrimary />
) : (
<Alert type="critical" title="No primary email adress" />
)}
{data.confirmedEmails.totalCount > 1 && (
<Body>
{data.confirmedEmails.totalCount - 1} additional emails.{" "}
<Link route={{ type: "profile" }}>View all</Link>
</Body>
)}
<Body>
{data.browserSessions.totalCount} active browser session(s).{" "}
<Link route={{ type: "browser-session-list" }}>View all</Link>
</Body>
<Body>
{data.oauth2Sessions.totalCount} active OAuth2 session(s).{" "}
<Link route={{ type: "oauth2-session-list" }}>View all</Link>
</Body>
<Body>
{data.compatSessions.totalCount} active compatibility layer session(s).{" "}
<Link route={{ type: "compat-session-list" }}>View all</Link>
</Body>
{/* This is a short term solution, so I won't bother extracting these blocks into components */}
<section className={styles.sessionList}>
<H3>Where you're signed in</H3>
<Block className={styles.sessionListBlock}>
<div className={styles.sessionListBlockInfo}>
<H6>Browser</H6>
<Body>
{data.browserSessions.totalCount} active{" "}
{pluraliseSession(data.browserSessions.totalCount)}
</Body>
</div>
<Link route={{ type: "browser-session-list" }}>View all</Link>
</Block>
<Block className={styles.sessionListBlock}>
<div className={styles.sessionListBlockInfo}>
<H6>New apps</H6>
<Body>
{data.oauth2Sessions.totalCount} active{" "}
{pluraliseSession(data.oauth2Sessions.totalCount)}
</Body>
</div>
<Link route={{ type: "oauth2-session-list" }}>View all</Link>
</Block>
<Block className={styles.sessionListBlock}>
<div className={styles.sessionListBlockInfo}>
<H6>Regular apps</H6>
<Body>
{data.compatSessions.totalCount} active{" "}
{pluraliseSession(data.compatSessions.totalCount)}
</Body>
</div>
<Link route={{ type: "compat-session-list" }}>View all</Link>
</Block>
</section>
</>
);
};

View File

@@ -1,388 +1,187 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`UserHome > render a <UserHome /> with additional emails 1`] = `
[
exports[`UserHome > render a <UserHome /> with sessions 1`] = `
<section
className="_sessionList_5d2854"
>
<h3
className="_font-heading-md-semibold_1g2sj_129"
>
Where you're signed in
</h3>
<div
className="_userEmail_e2a518"
className="_block_17898c _sessionListBlock_5d2854"
>
<p
className="_font-body-md-regular_1g2sj_65"
>
Primary email
</p>
<div
className="_userEmailLine_e2a518"
className="_sessionListBlockInfo_5d2854"
>
<div
className="_userEmailField_e2a518"
<h6
className="_font-body-md-semibold_1g2sj_69"
>
hello@example.com
</div>
<button
className="_userEmailDelete_e2a518"
disabled={true}
onClick={[Function]}
title="Remove email address"
Browser
</h6>
<p
className="_font-body-md-regular_1g2sj_65"
>
<svg
className="_userEmailDeleteIcon_e2a518"
fill="currentColor"
height="1em"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M7 21c-.55 0-1.02-.196-1.412-.587A1.926 1.926 0 0 1 5 19V6a.968.968 0 0 1-.713-.287A.968.968 0 0 1 4 5c0-.283.096-.52.287-.713A.968.968 0 0 1 5 4h4a.97.97 0 0 1 .287-.712A.968.968 0 0 1 10 3h4a.97.97 0 0 1 .713.288A.968.968 0 0 1 15 4h4a.97.97 0 0 1 .712.287c.192.192.288.43.288.713s-.096.52-.288.713A.968.968 0 0 1 19 6v13c0 .55-.196 1.02-.587 1.413A1.926 1.926 0 0 1 17 21H7Zm2-5c0 .283.096.52.287.712.192.192.43.288.713.288s.52-.096.713-.288A.968.968 0 0 0 11 16V9a.967.967 0 0 0-.287-.713A.968.968 0 0 0 10 8a.968.968 0 0 0-.713.287A.968.968 0 0 0 9 9v7Zm4 0c0 .283.096.52.287.712.192.192.43.288.713.288s.52-.096.713-.288A.968.968 0 0 0 15 16V9a.967.967 0 0 0-.287-.713A.968.968 0 0 0 14 8a.968.968 0 0 0-.713.287A.967.967 0 0 0 13 9v7Z"
fill="currentColor"
/>
</svg>
</button>
2
active
sessions
</p>
</div>
</div>,
<p
className="_font-body-md-regular_1g2sj_65"
>
3
additional emails.
<a
href="/profile"
onClick={[Function]}
>
View all
</a>
</p>,
<p
className="_font-body-md-regular_1g2sj_65"
>
0
active browser session(s).
<a
href="/sessions"
onClick={[Function]}
>
View all
</a>
</p>,
<p
className="_font-body-md-regular_1g2sj_65"
</div>
<div
className="_block_17898c _sessionListBlock_5d2854"
>
0
active OAuth2 session(s).
<div
className="_sessionListBlockInfo_5d2854"
>
<h6
className="_font-body-md-semibold_1g2sj_69"
>
New apps
</h6>
<p
className="_font-body-md-regular_1g2sj_65"
>
3
active
sessions
</p>
</div>
<a
href="/oauth2-sessions"
onClick={[Function]}
>
View all
</a>
</p>,
<p
className="_font-body-md-regular_1g2sj_65"
>
0
active compatibility layer session(s).
<a
href="/compat-sessions"
onClick={[Function]}
>
View all
</a>
</p>,
]
`;
exports[`UserHome > render a <UserHome /> with an unverified email 1`] = `
[
</div>
<div
className="_alert_fxw8y_19"
data-type="critical"
className="_block_17898c _sessionListBlock_5d2854"
>
<svg
aria-hidden={true}
className="_icon_fxw8y_52"
fill="currentColor"
height={24}
viewBox="0 0 24 24"
width={24}
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M12 17a.97.97 0 0 0 .713-.288A.968.968 0 0 0 13 16a.968.968 0 0 0-.287-.713A.968.968 0 0 0 12 15a.968.968 0 0 0-.713.287A.968.968 0 0 0 11 16c0 .283.096.52.287.712.192.192.43.288.713.288Zm0-4c.283 0 .52-.096.713-.287A.968.968 0 0 0 13 12V8a.967.967 0 0 0-.287-.713A.968.968 0 0 0 12 7a.968.968 0 0 0-.713.287A.967.967 0 0 0 11 8v4c0 .283.096.52.287.713.192.191.43.287.713.287Zm0 9a9.738 9.738 0 0 1-3.9-.788 10.099 10.099 0 0 1-3.175-2.137c-.9-.9-1.612-1.958-2.137-3.175A9.738 9.738 0 0 1 2 12a9.74 9.74 0 0 1 .788-3.9 10.099 10.099 0 0 1 2.137-3.175c.9-.9 1.958-1.612 3.175-2.137A9.738 9.738 0 0 1 12 2a9.74 9.74 0 0 1 3.9.788 10.098 10.098 0 0 1 3.175 2.137c.9.9 1.613 1.958 2.137 3.175A9.738 9.738 0 0 1 22 12a9.738 9.738 0 0 1-.788 3.9 10.098 10.098 0 0 1-2.137 3.175c-.9.9-1.958 1.613-3.175 2.137A9.738 9.738 0 0 1 12 22Z"
fill="currentColor"
/>
</svg>
<div
className="_content_fxw8y_44"
className="_sessionListBlockInfo_5d2854"
>
<p
className="_title_fxw8y_48"
<h6
className="_font-body-md-semibold_1g2sj_69"
>
Regular apps
</h6>
<p
className="_font-body-md-regular_1g2sj_65"
>
Unverified email
</p>
<p>
You have
1
unverified email address(es).
<a
href="/profile"
onClick={[Function]}
>
Check
</a>
active
session
</p>
</div>
<svg
aria-label="Close"
className="_close_fxw8y_68"
fill="currentColor"
height={16}
onClick={[Function]}
role="button"
viewBox="0 0 24 24"
width={16}
xmlns="http://www.w3.org/2000/svg"
>
<path
d="m12 13.4-4.9 4.9a.948.948 0 0 1-.7.275.948.948 0 0 1-.7-.275.948.948 0 0 1-.275-.7.95.95 0 0 1 .275-.7l4.9-4.9-4.9-4.9a.948.948 0 0 1-.275-.7.95.95 0 0 1 .275-.7.948.948 0 0 1 .7-.275.95.95 0 0 1 .7.275l4.9 4.9 4.9-4.9a.948.948 0 0 1 .7-.275.95.95 0 0 1 .7.275.948.948 0 0 1 .275.7.948.948 0 0 1-.275.7L13.4 12l4.9 4.9a.948.948 0 0 1 .275.7.948.948 0 0 1-.275.7.948.948 0 0 1-.7.275.948.948 0 0 1-.7-.275L12 13.4Z"
fill="currentColor"
/>
</svg>
</div>,
<div
className="_userEmail_e2a518"
>
<p
className="_font-body-md-regular_1g2sj_65"
>
Primary email
</p>
<div
className="_userEmailLine_e2a518"
>
<div
className="_userEmailField_e2a518"
>
hello@example.com
</div>
<button
className="_userEmailDelete_e2a518"
disabled={true}
onClick={[Function]}
title="Remove email address"
>
<svg
className="_userEmailDeleteIcon_e2a518"
fill="currentColor"
height="1em"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M7 21c-.55 0-1.02-.196-1.412-.587A1.926 1.926 0 0 1 5 19V6a.968.968 0 0 1-.713-.287A.968.968 0 0 1 4 5c0-.283.096-.52.287-.713A.968.968 0 0 1 5 4h4a.97.97 0 0 1 .287-.712A.968.968 0 0 1 10 3h4a.97.97 0 0 1 .713.288A.968.968 0 0 1 15 4h4a.97.97 0 0 1 .712.287c.192.192.288.43.288.713s-.096.52-.288.713A.968.968 0 0 1 19 6v13c0 .55-.196 1.02-.587 1.413A1.926 1.926 0 0 1 17 21H7Zm2-5c0 .283.096.52.287.712.192.192.43.288.713.288s.52-.096.713-.288A.968.968 0 0 0 11 16V9a.967.967 0 0 0-.287-.713A.968.968 0 0 0 10 8a.968.968 0 0 0-.713.287A.968.968 0 0 0 9 9v7Zm4 0c0 .283.096.52.287.712.192.192.43.288.713.288s.52-.096.713-.288A.968.968 0 0 0 15 16V9a.967.967 0 0 0-.287-.713A.968.968 0 0 0 14 8a.968.968 0 0 0-.713.287A.967.967 0 0 0 13 9v7Z"
fill="currentColor"
/>
</svg>
</button>
</div>
</div>,
<p
className="_font-body-md-regular_1g2sj_65"
>
0
active browser session(s).
<a
href="/sessions"
onClick={[Function]}
>
View all
</a>
</p>,
<p
className="_font-body-md-regular_1g2sj_65"
>
0
active OAuth2 session(s).
<a
href="/oauth2-sessions"
onClick={[Function]}
>
View all
</a>
</p>,
<p
className="_font-body-md-regular_1g2sj_65"
>
0
active compatibility layer session(s).
<a
href="/compat-sessions"
onClick={[Function]}
>
View all
</a>
</p>,
]
`;
exports[`UserHome > render a <UserHome /> without primary email 1`] = `
[
<div
className="_alert_fxw8y_19"
data-type="critical"
>
<svg
aria-hidden={true}
className="_icon_fxw8y_52"
fill="currentColor"
height={24}
viewBox="0 0 24 24"
width={24}
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M12 17a.97.97 0 0 0 .713-.288A.968.968 0 0 0 13 16a.968.968 0 0 0-.287-.713A.968.968 0 0 0 12 15a.968.968 0 0 0-.713.287A.968.968 0 0 0 11 16c0 .283.096.52.287.712.192.192.43.288.713.288Zm0-4c.283 0 .52-.096.713-.287A.968.968 0 0 0 13 12V8a.967.967 0 0 0-.287-.713A.968.968 0 0 0 12 7a.968.968 0 0 0-.713.287A.967.967 0 0 0 11 8v4c0 .283.096.52.287.713.192.191.43.287.713.287Zm0 9a9.738 9.738 0 0 1-3.9-.788 10.099 10.099 0 0 1-3.175-2.137c-.9-.9-1.612-1.958-2.137-3.175A9.738 9.738 0 0 1 2 12a9.74 9.74 0 0 1 .788-3.9 10.099 10.099 0 0 1 2.137-3.175c.9-.9 1.958-1.612 3.175-2.137A9.738 9.738 0 0 1 12 2a9.74 9.74 0 0 1 3.9.788 10.098 10.098 0 0 1 3.175 2.137c.9.9 1.613 1.958 2.137 3.175A9.738 9.738 0 0 1 22 12a9.738 9.738 0 0 1-.788 3.9 10.098 10.098 0 0 1-2.137 3.175c-.9.9-1.958 1.613-3.175 2.137A9.738 9.738 0 0 1 12 22Z"
fill="currentColor"
/>
</svg>
<div
className="_content_fxw8y_44"
>
<p
className="_title_fxw8y_48"
>
No primary email adress
</p>
<p />
</div>
</div>,
<p
className="_font-body-md-regular_1g2sj_65"
>
0
active browser session(s).
<a
href="/sessions"
onClick={[Function]}
>
View all
</a>
</p>,
<p
className="_font-body-md-regular_1g2sj_65"
>
0
active OAuth2 session(s).
<a
href="/oauth2-sessions"
onClick={[Function]}
>
View all
</a>
</p>,
<p
className="_font-body-md-regular_1g2sj_65"
>
0
active compatibility layer session(s).
<a
href="/compat-sessions"
onClick={[Function]}
>
View all
</a>
</p>,
]
</div>
</section>
`;
exports[`UserHome > render an simple <UserHome /> 1`] = `
[
<section
className="_sessionList_5d2854"
>
<h3
className="_font-heading-md-semibold_1g2sj_129"
>
Where you're signed in
</h3>
<div
className="_userEmail_e2a518"
className="_block_17898c _sessionListBlock_5d2854"
>
<p
className="_font-body-md-regular_1g2sj_65"
>
Primary email
</p>
<div
className="_userEmailLine_e2a518"
className="_sessionListBlockInfo_5d2854"
>
<div
className="_userEmailField_e2a518"
<h6
className="_font-body-md-semibold_1g2sj_69"
>
hello@example.com
</div>
<button
className="_userEmailDelete_e2a518"
disabled={true}
onClick={[Function]}
title="Remove email address"
Browser
</h6>
<p
className="_font-body-md-regular_1g2sj_65"
>
<svg
className="_userEmailDeleteIcon_e2a518"
fill="currentColor"
height="1em"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M7 21c-.55 0-1.02-.196-1.412-.587A1.926 1.926 0 0 1 5 19V6a.968.968 0 0 1-.713-.287A.968.968 0 0 1 4 5c0-.283.096-.52.287-.713A.968.968 0 0 1 5 4h4a.97.97 0 0 1 .287-.712A.968.968 0 0 1 10 3h4a.97.97 0 0 1 .713.288A.968.968 0 0 1 15 4h4a.97.97 0 0 1 .712.287c.192.192.288.43.288.713s-.096.52-.288.713A.968.968 0 0 1 19 6v13c0 .55-.196 1.02-.587 1.413A1.926 1.926 0 0 1 17 21H7Zm2-5c0 .283.096.52.287.712.192.192.43.288.713.288s.52-.096.713-.288A.968.968 0 0 0 11 16V9a.967.967 0 0 0-.287-.713A.968.968 0 0 0 10 8a.968.968 0 0 0-.713.287A.968.968 0 0 0 9 9v7Zm4 0c0 .283.096.52.287.712.192.192.43.288.713.288s.52-.096.713-.288A.968.968 0 0 0 15 16V9a.967.967 0 0 0-.287-.713A.968.968 0 0 0 14 8a.968.968 0 0 0-.713.287A.967.967 0 0 0 13 9v7Z"
fill="currentColor"
/>
</svg>
</button>
0
active
sessions
</p>
</div>
</div>,
<p
className="_font-body-md-regular_1g2sj_65"
>
0
active browser session(s).
<a
href="/sessions"
onClick={[Function]}
>
View all
</a>
</p>,
<p
className="_font-body-md-regular_1g2sj_65"
</div>
<div
className="_block_17898c _sessionListBlock_5d2854"
>
0
active OAuth2 session(s).
<div
className="_sessionListBlockInfo_5d2854"
>
<h6
className="_font-body-md-semibold_1g2sj_69"
>
New apps
</h6>
<p
className="_font-body-md-regular_1g2sj_65"
>
0
active
sessions
</p>
</div>
<a
href="/oauth2-sessions"
onClick={[Function]}
>
View all
</a>
</p>,
<p
className="_font-body-md-regular_1g2sj_65"
</div>
<div
className="_block_17898c _sessionListBlock_5d2854"
>
0
active compatibility layer session(s).
<div
className="_sessionListBlockInfo_5d2854"
>
<h6
className="_font-body-md-semibold_1g2sj_69"
>
Regular apps
</h6>
<p
className="_font-body-md-regular_1g2sj_65"
>
0
active
sessions
</p>
</div>
<a
href="/compat-sessions"
onClick={[Function]}
>
View all
</a>
</p>,
]
</div>
</section>
`;

View File

@@ -15,6 +15,6 @@ exports[`<Layout /> > renders app navigation correctly 2`] = `
class="_navItem_8603fc"
href="/"
>
Home
Sessions
</a>
`;