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
split browser sessions section into own component
This commit is contained in:
committed by
Quentin Gliech
parent
58b235e9de
commit
e646319f5a
@@ -0,0 +1,27 @@
|
||||
/* 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-block {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
gap: var(--cpd-space-1x);
|
||||
}
|
||||
|
||||
.session-list-block-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
// Copyright 2022 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 type { Meta, StoryObj } from "@storybook/react";
|
||||
import { Provider } from "jotai";
|
||||
import { useHydrateAtoms } from "jotai/utils";
|
||||
|
||||
import { makeFragmentData } from "../../gql";
|
||||
import { appConfigAtom, locationAtom } from "../../routing";
|
||||
|
||||
import BrowserSessionsOverview, { FRAGMENT } from "./BrowserSessionsOverview";
|
||||
|
||||
type Props = {
|
||||
browserSessions: number;
|
||||
};
|
||||
|
||||
const WithHomePage: React.FC<React.PropsWithChildren<{}>> = ({ children }) => {
|
||||
useHydrateAtoms([
|
||||
[appConfigAtom, { root: "/" }],
|
||||
[locationAtom, { pathname: "/" }],
|
||||
]);
|
||||
return <>{children}</>;
|
||||
};
|
||||
|
||||
const Template: React.FC<Props> = ({ browserSessions }) => {
|
||||
const data = makeFragmentData(
|
||||
{
|
||||
id: "user:123",
|
||||
browserSessions: {
|
||||
totalCount: browserSessions,
|
||||
},
|
||||
},
|
||||
FRAGMENT,
|
||||
);
|
||||
return (
|
||||
<Provider>
|
||||
<WithHomePage>
|
||||
<BrowserSessionsOverview user={data} />
|
||||
</WithHomePage>
|
||||
</Provider>
|
||||
);
|
||||
};
|
||||
|
||||
const meta = {
|
||||
title: "Pages/User Sessions Overview/Browser Sessions",
|
||||
component: Template,
|
||||
tags: ["autodocs"],
|
||||
} satisfies Meta<typeof Template>;
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof Template>;
|
||||
|
||||
export const Basic: Story = {
|
||||
args: {
|
||||
browserSessions: 2,
|
||||
},
|
||||
};
|
||||
|
||||
export const Empty: Story = {
|
||||
args: {
|
||||
browserSessions: 0,
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,64 @@
|
||||
// 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.
|
||||
|
||||
// @vitest-environment happy-dom
|
||||
|
||||
import { render, cleanup } from "@testing-library/react";
|
||||
import { describe, expect, it, afterEach } from "vitest";
|
||||
|
||||
import { makeFragmentData } from "../../gql";
|
||||
import { WithLocation } from "../../test-utils/WithLocation";
|
||||
|
||||
import BrowserSessionsOverview, { FRAGMENT } from "./BrowserSessionsOverview";
|
||||
|
||||
describe("BrowserSessionsOverview", () => {
|
||||
afterEach(cleanup);
|
||||
|
||||
it("renders with no browser sessions", async () => {
|
||||
const user = makeFragmentData(
|
||||
{
|
||||
id: "user:123",
|
||||
browserSessions: {
|
||||
totalCount: 0,
|
||||
},
|
||||
},
|
||||
FRAGMENT,
|
||||
);
|
||||
const { container } = render(
|
||||
<WithLocation>
|
||||
<BrowserSessionsOverview user={user} />
|
||||
</WithLocation>,
|
||||
);
|
||||
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("renders with sessions", () => {
|
||||
const user = makeFragmentData(
|
||||
{
|
||||
id: "user:123",
|
||||
browserSessions: {
|
||||
totalCount: 2,
|
||||
},
|
||||
},
|
||||
FRAGMENT,
|
||||
);
|
||||
const { container } = render(
|
||||
<WithLocation>
|
||||
<BrowserSessionsOverview user={user} />
|
||||
</WithLocation>,
|
||||
);
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,58 @@
|
||||
// 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 { Body, H5 } from "@vector-im/compound-web";
|
||||
|
||||
import { FragmentType, graphql, useFragment } from "../../gql";
|
||||
import { Link } from "../../routing";
|
||||
import Block from "../Block";
|
||||
|
||||
import styles from "./BrowserSessionsOverview.module.css";
|
||||
|
||||
export const FRAGMENT = graphql(/* GraphQL */ `
|
||||
fragment BrowserSessionsOverview_user on User {
|
||||
id
|
||||
|
||||
browserSessions(first: 0, state: ACTIVE) {
|
||||
totalCount
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
const BrowserSessionsOverview: React.FC<{
|
||||
user: FragmentType<typeof FRAGMENT>;
|
||||
}> = ({ user }) => {
|
||||
const data = useFragment(FRAGMENT, user);
|
||||
|
||||
// allow this until we get i18n
|
||||
const pluraliseSession = (count: number): string =>
|
||||
count === 1 ? "session" : "sessions";
|
||||
|
||||
return (
|
||||
<Block className={styles.sessionListBlock}>
|
||||
<div className={styles.sessionListBlockInfo}>
|
||||
<H5>Browsers</H5>
|
||||
<Body>
|
||||
{data.browserSessions.totalCount} active{" "}
|
||||
{pluraliseSession(data.browserSessions.totalCount)}
|
||||
</Body>
|
||||
</div>
|
||||
<Link kind="button" route={{ type: "browser-session-list" }}>
|
||||
View all
|
||||
</Link>
|
||||
</Block>
|
||||
);
|
||||
};
|
||||
|
||||
export default BrowserSessionsOverview;
|
||||
Reference in New Issue
Block a user