Reformat frontend code, fix a few new linting errors

This commit is contained in:
Quentin Gliech
2025-07-07 15:07:57 +02:00
parent f08f3bd786
commit 4cfd61c367
31 changed files with 146 additions and 132 deletions

View File

@@ -46,7 +46,8 @@
"noUnusedTemplateLiteral": "error", "noUnusedTemplateLiteral": "error",
"useNumberNamespace": "error", "useNumberNamespace": "error",
"noInferrableTypes": "error", "noInferrableTypes": "error",
"noUselessElse": "error" "noUselessElse": "error",
"noDescendingSpecificity": "off"
} }
} }
} }

View File

@@ -70,7 +70,10 @@ const AccountDeleteButton: React.FC<Props> = (props) => {
mutationFn: ({ mutationFn: ({
password, password,
hsErase, hsErase,
}: { password: string | null; hsErase: boolean }) => }: {
password: string | null;
hsErase: boolean;
}) =>
graphqlRequest({ graphqlRequest({
query: MUTATION, query: MUTATION,
variables: { password, hsErase }, variables: { password, hsErase },

View File

@@ -7,7 +7,7 @@
import { createLink } from "@tanstack/react-router"; import { createLink } from "@tanstack/react-router";
import { Button } from "@vector-im/compound-web"; import { Button } from "@vector-im/compound-web";
import cx from "classnames"; import cx from "classnames";
import { type PropsWithChildren, forwardRef } from "react"; import { forwardRef, type PropsWithChildren } from "react";
import styles from "./ButtonLink.module.css"; import styles from "./ButtonLink.module.css";
type Props = { type Props = {

View File

@@ -95,6 +95,7 @@
/* Cap the block size */ /* Cap the block size */
max-block-size: calc(100vh - var(--cpd-space-4x)); max-block-size: calc(100vh - var(--cpd-space-4x));
/* biome-ignore lint/suspicious/noDuplicateProperties: this isn't a real duplicate */
max-block-size: calc(100svh - var(--cpd-space-4x)); max-block-size: calc(100svh - var(--cpd-space-4x));
/* Drawer comes in the Android style by default */ /* Drawer comes in the Android style by default */

View File

@@ -102,4 +102,4 @@ export const Title: React.FC<PropsWithChildren> = ({ children }) => (
<DialogTitle className={styles.title}>{children}</DialogTitle> <DialogTitle className={styles.title}>{children}</DialogTitle>
); );
export { Description, Close } from "@radix-ui/react-dialog"; export { Close, Description } from "@radix-ui/react-dialog";

View File

@@ -4,4 +4,4 @@
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial // SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
// Please see LICENSE files in the repository root for full details. // Please see LICENSE files in the repository root for full details.
export { Close, Dialog, Title, Description } from "./Dialog"; export { Close, Description, Dialog, Title } from "./Dialog";

View File

@@ -16,6 +16,7 @@
/* Fallback for browsers that do not support 100svh */ /* Fallback for browsers that do not support 100svh */
min-height: 100vh; min-height: 100vh;
/* biome-ignore lint/suspicious/noDuplicateProperties: this isn't a real duplicate */
min-height: 100svh; min-height: 100svh;
margin: 0 auto; margin: 0 auto;

View File

@@ -10,6 +10,7 @@
/* Fallback for browsers that do not support 100svh */ /* Fallback for browsers that do not support 100svh */
min-height: 100vh; min-height: 100vh;
/* biome-ignore lint/suspicious/noDuplicateProperties: this isn't a real duplicate */
min-height: 100svh; min-height: 100svh;
justify-content: center; justify-content: center;

View File

@@ -39,9 +39,9 @@ const PaginationControls: React.FC<Props> = ({
{t("common.previous")} {t("common.previous")}
</Button> </Button>
<div className="text-center"> <div className="text-center">
{count !== undefined ? ( {count !== undefined
<>{t("frontend.pagination_controls.total", { totalCount: count })}</> ? t("frontend.pagination_controls.total", { totalCount: count })
) : null} : null}
</div> </div>
<Button <Button
kind="secondary" kind="secondary"

View File

@@ -3,6 +3,9 @@
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial // SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
// Please see LICENSE files in the repository root for full details. // Please see LICENSE files in the repository root for full details.
// biome-ignore-all lint/a11y/useFocusableInteractive: this is a false positive
// biome-ignore-all lint/a11y/useAriaPropsForRole: this is a false positive
import cx from "classnames"; import cx from "classnames";
import { forwardRef } from "react"; import { forwardRef } from "react";
@@ -14,7 +17,6 @@ type Props = {
const Separator = forwardRef<HTMLDivElement, Props>( const Separator = forwardRef<HTMLDivElement, Props>(
({ kind, className, ...props }: Props, ref) => ( ({ kind, className, ...props }: Props, ref) => (
// biome-ignore lint/a11y/useFocusableInteractive: this is a false positive
<div <div
aria-orientation="horizontal" aria-orientation="horizontal"
role="separator" role="separator"

View File

@@ -10,7 +10,7 @@ import { composeStory } from "@storybook/react-vite";
import { render } from "@testing-library/react"; import { render } from "@testing-library/react";
import { describe, expect, it } from "vitest"; import { describe, expect, it } from "vitest";
import Meta, { Unknown, Pc, Mobile, Tablet } from "./DeviceTypeIcon.stories"; import Meta, { Mobile, Pc, Tablet, Unknown } from "./DeviceTypeIcon.stories";
describe("<DeviceTypeIcon />", () => { describe("<DeviceTypeIcon />", () => {
it("renders unknown device type", () => { it("renders unknown device type", () => {

View File

@@ -5,13 +5,13 @@
// Please see LICENSE files in the repository root for full details. // Please see LICENSE files in the repository root for full details.
export { export {
Root,
LinkBody,
Body,
Header,
Name,
Client,
Metadata,
Info,
Action, Action,
Body,
Client,
Header,
Info,
LinkBody,
Metadata,
Name,
Root,
} from "./SessionCard"; } from "./SessionCard";

View File

@@ -3,6 +3,7 @@
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial // SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
// Please see LICENSE files in the repository root for full details. // Please see LICENSE files in the repository root for full details.
import type { UseMutationResult } from "@tanstack/react-query";
import IconEdit from "@vector-im/compound-design-tokens/assets/web/icons/edit"; import IconEdit from "@vector-im/compound-design-tokens/assets/web/icons/edit";
import { Button, Form, IconButton, Tooltip } from "@vector-im/compound-web"; import { Button, Form, IconButton, Tooltip } from "@vector-im/compound-web";
import { import {
@@ -11,12 +12,10 @@ import {
useRef, useRef,
useState, useState,
} from "react"; } from "react";
import { useTranslation } from "react-i18next";
import * as Dialog from "../Dialog"; import * as Dialog from "../Dialog";
import LoadingSpinner from "../LoadingSpinner"; import LoadingSpinner from "../LoadingSpinner";
import type { UseMutationResult } from "@tanstack/react-query";
import { useTranslation } from "react-i18next";
// This needs to be its own component because else props and refs aren't passed properly in the trigger // This needs to be its own component because else props and refs aren't passed properly in the trigger
const EditButton = forwardRef< const EditButton = forwardRef<
HTMLButtonElement, HTMLButtonElement,

View File

@@ -6,12 +6,10 @@
// @vitest-environment happy-dom // @vitest-environment happy-dom
import { TooltipProvider } from "@vector-im/compound-web";
import { beforeAll, describe, expect, it } from "vitest"; import { beforeAll, describe, expect, it } from "vitest";
import { makeFragmentData } from "../../gql"; import { makeFragmentData } from "../../gql";
import { mockLocale } from "../../test-utils/mockLocale"; import { mockLocale } from "../../test-utils/mockLocale";
import { TooltipProvider } from "@vector-im/compound-web";
import render from "../../test-utils/render"; import render from "../../test-utils/render";
import OAuth2SessionDetail, { FRAGMENT } from "./OAuth2SessionDetail"; import OAuth2SessionDetail, { FRAGMENT } from "./OAuth2SessionDetail";

View File

@@ -105,7 +105,7 @@ const UserEmail: React.FC<{
const onRemoveClick = useCallback( const onRemoveClick = useCallback(
async (_e: React.MouseEvent<HTMLButtonElement>): Promise<void> => { async (_e: React.MouseEvent<HTMLButtonElement>): Promise<void> => {
let password = undefined; let password: string | undefined;
if (shouldPromptPassword) { if (shouldPromptPassword) {
password = await promptPassword(); password = await promptPassword();
} }

View File

@@ -32,11 +32,9 @@ export const CONFIG_FRAGMENT = graphql(/* GraphQL */ `
const ADD_EMAIL_MUTATION = graphql(/* GraphQL */ ` const ADD_EMAIL_MUTATION = graphql(/* GraphQL */ `
mutation AddEmail($email: String!, $password: String, $language: String!) { mutation AddEmail($email: String!, $password: String, $language: String!) {
startEmailAuthentication(input: { startEmailAuthentication(
email: $email, input: { email: $email, password: $password, language: $language }
password: $password, ) {
language: $language
}) {
status status
violations violations
authentication { authentication {
@@ -64,7 +62,11 @@ const AddEmailForm: React.FC<{
email, email,
password, password,
language, language,
}: { email: string; password?: string; language: string }) => }: {
email: string;
password?: string;
language: string;
}) =>
graphqlRequest({ graphqlRequest({
query: ADD_EMAIL_MUTATION, query: ADD_EMAIL_MUTATION,
variables: { email, password, language }, variables: { email, password, language },
@@ -92,7 +94,7 @@ const AddEmailForm: React.FC<{
const formData = new FormData(e.currentTarget); const formData = new FormData(e.currentTarget);
const email = formData.get("input") as string; const email = formData.get("input") as string;
let password = undefined; let password: string | undefined;
if (shouldPromptPassword) { if (shouldPromptPassword) {
password = await promptPassword(); password = await promptPassword();
} }

View File

@@ -44,7 +44,7 @@ type Documents = {
"\n mutation SetDisplayName($userId: ID!, $displayName: String) {\n setDisplayName(input: { userId: $userId, displayName: $displayName }) {\n status\n }\n }\n": typeof types.SetDisplayNameDocument, "\n mutation SetDisplayName($userId: ID!, $displayName: String) {\n setDisplayName(input: { userId: $userId, displayName: $displayName }) {\n status\n }\n }\n": typeof types.SetDisplayNameDocument,
"\n fragment AddEmailForm_user on User {\n hasPassword\n }\n": typeof types.AddEmailForm_UserFragmentDoc, "\n fragment AddEmailForm_user on User {\n hasPassword\n }\n": typeof types.AddEmailForm_UserFragmentDoc,
"\n fragment AddEmailForm_siteConfig on SiteConfig {\n passwordLoginEnabled\n }\n": typeof types.AddEmailForm_SiteConfigFragmentDoc, "\n fragment AddEmailForm_siteConfig on SiteConfig {\n passwordLoginEnabled\n }\n": typeof types.AddEmailForm_SiteConfigFragmentDoc,
"\n mutation AddEmail($email: String!, $password: String, $language: String!) {\n startEmailAuthentication(input: {\n email: $email,\n password: $password,\n language: $language\n }) {\n status\n violations\n authentication {\n id\n }\n }\n }\n": typeof types.AddEmailDocument, "\n mutation AddEmail($email: String!, $password: String, $language: String!) {\n startEmailAuthentication(\n input: { email: $email, password: $password, language: $language }\n ) {\n status\n violations\n authentication {\n id\n }\n }\n }\n": typeof types.AddEmailDocument,
"\n query UserEmailList(\n $first: Int\n $after: String\n $last: Int\n $before: String\n ) {\n viewer {\n __typename\n ... on User {\n emails(first: $first, after: $after, last: $last, before: $before) {\n edges {\n cursor\n node {\n ...UserEmail_email\n }\n }\n totalCount\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n }\n }\n }\n": typeof types.UserEmailListDocument, "\n query UserEmailList(\n $first: Int\n $after: String\n $last: Int\n $before: String\n ) {\n viewer {\n __typename\n ... on User {\n emails(first: $first, after: $after, last: $last, before: $before) {\n edges {\n cursor\n node {\n ...UserEmail_email\n }\n }\n totalCount\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n }\n }\n }\n": typeof types.UserEmailListDocument,
"\n fragment UserEmailList_user on User {\n hasPassword\n }\n": typeof types.UserEmailList_UserFragmentDoc, "\n fragment UserEmailList_user on User {\n hasPassword\n }\n": typeof types.UserEmailList_UserFragmentDoc,
"\n fragment UserEmailList_siteConfig on SiteConfig {\n emailChangeAllowed\n passwordLoginEnabled\n }\n": typeof types.UserEmailList_SiteConfigFragmentDoc, "\n fragment UserEmailList_siteConfig on SiteConfig {\n emailChangeAllowed\n passwordLoginEnabled\n }\n": typeof types.UserEmailList_SiteConfigFragmentDoc,
@@ -101,7 +101,7 @@ const documents: Documents = {
"\n mutation SetDisplayName($userId: ID!, $displayName: String) {\n setDisplayName(input: { userId: $userId, displayName: $displayName }) {\n status\n }\n }\n": types.SetDisplayNameDocument, "\n mutation SetDisplayName($userId: ID!, $displayName: String) {\n setDisplayName(input: { userId: $userId, displayName: $displayName }) {\n status\n }\n }\n": types.SetDisplayNameDocument,
"\n fragment AddEmailForm_user on User {\n hasPassword\n }\n": types.AddEmailForm_UserFragmentDoc, "\n fragment AddEmailForm_user on User {\n hasPassword\n }\n": types.AddEmailForm_UserFragmentDoc,
"\n fragment AddEmailForm_siteConfig on SiteConfig {\n passwordLoginEnabled\n }\n": types.AddEmailForm_SiteConfigFragmentDoc, "\n fragment AddEmailForm_siteConfig on SiteConfig {\n passwordLoginEnabled\n }\n": types.AddEmailForm_SiteConfigFragmentDoc,
"\n mutation AddEmail($email: String!, $password: String, $language: String!) {\n startEmailAuthentication(input: {\n email: $email,\n password: $password,\n language: $language\n }) {\n status\n violations\n authentication {\n id\n }\n }\n }\n": types.AddEmailDocument, "\n mutation AddEmail($email: String!, $password: String, $language: String!) {\n startEmailAuthentication(\n input: { email: $email, password: $password, language: $language }\n ) {\n status\n violations\n authentication {\n id\n }\n }\n }\n": types.AddEmailDocument,
"\n query UserEmailList(\n $first: Int\n $after: String\n $last: Int\n $before: String\n ) {\n viewer {\n __typename\n ... on User {\n emails(first: $first, after: $after, last: $last, before: $before) {\n edges {\n cursor\n node {\n ...UserEmail_email\n }\n }\n totalCount\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n }\n }\n }\n": types.UserEmailListDocument, "\n query UserEmailList(\n $first: Int\n $after: String\n $last: Int\n $before: String\n ) {\n viewer {\n __typename\n ... on User {\n emails(first: $first, after: $after, last: $last, before: $before) {\n edges {\n cursor\n node {\n ...UserEmail_email\n }\n }\n totalCount\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n }\n }\n }\n": types.UserEmailListDocument,
"\n fragment UserEmailList_user on User {\n hasPassword\n }\n": types.UserEmailList_UserFragmentDoc, "\n fragment UserEmailList_user on User {\n hasPassword\n }\n": types.UserEmailList_UserFragmentDoc,
"\n fragment UserEmailList_siteConfig on SiteConfig {\n emailChangeAllowed\n passwordLoginEnabled\n }\n": types.UserEmailList_SiteConfigFragmentDoc, "\n fragment UserEmailList_siteConfig on SiteConfig {\n emailChangeAllowed\n passwordLoginEnabled\n }\n": types.UserEmailList_SiteConfigFragmentDoc,
@@ -248,7 +248,7 @@ export function graphql(source: "\n fragment AddEmailForm_siteConfig on SiteCon
/** /**
* 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(source: "\n mutation AddEmail($email: String!, $password: String, $language: String!) {\n startEmailAuthentication(input: {\n email: $email,\n password: $password,\n language: $language\n }) {\n status\n violations\n authentication {\n id\n }\n }\n }\n"): typeof import('./graphql').AddEmailDocument; export function graphql(source: "\n mutation AddEmail($email: String!, $password: String, $language: String!) {\n startEmailAuthentication(\n input: { email: $email, password: $password, language: $language }\n ) {\n status\n violations\n authentication {\n id\n }\n }\n }\n"): typeof import('./graphql').AddEmailDocument;
/** /**
* 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

@@ -7,10 +7,10 @@
import { import {
type BackendModule, type BackendModule,
type InitOptions, type InitOptions,
default as i18n,
type LanguageDetectorModule, type LanguageDetectorModule,
type ReadCallback, type ReadCallback,
type ResourceKey, type ResourceKey,
default as i18n,
} from "i18next"; } from "i18next";
import { initReactI18next } from "react-i18next"; import { initReactI18next } from "react-i18next";

View File

@@ -7,9 +7,9 @@
import type { QueryClient } from "@tanstack/react-query"; import type { QueryClient } from "@tanstack/react-query";
import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
import { import {
createRootRouteWithContext,
type ErrorRouteComponent, type ErrorRouteComponent,
Outlet, Outlet,
createRootRouteWithContext,
} from "@tanstack/react-router"; } from "@tanstack/react-router";
import { TanStackRouterDevtools } from "@tanstack/react-router-devtools"; import { TanStackRouterDevtools } from "@tanstack/react-router-devtools";
import GenericError from "../components/GenericError"; import GenericError from "../components/GenericError";

View File

@@ -188,7 +188,6 @@ function Index(): React.ReactElement {
}; };
return ( return (
<>
<div className="flex flex-col gap-6"> <div className="flex flex-col gap-6">
{/* Only display this section if the user can add email addresses to their {/* Only display this section if the user can add email addresses to their
account *or* if they have any existing email addresses */} account *or* if they have any existing email addresses */}
@@ -199,10 +198,7 @@ function Index(): React.ReactElement {
defaultOpen defaultOpen
title={t("frontend.account.contact_info")} title={t("frontend.account.contact_info")}
> >
<UserEmailList <UserEmailList user={viewerSession.user} siteConfig={siteConfig} />
user={viewerSession.user}
siteConfig={siteConfig}
/>
{siteConfig.emailChangeAllowed && ( {siteConfig.emailChangeAllowed && (
<AddEmailForm <AddEmailForm
@@ -255,6 +251,5 @@ function Index(): React.ReactElement {
<Separator /> <Separator />
</div> </div>
</>
); );
} }

View File

@@ -33,10 +33,10 @@ export const Route = createFileRoute({
preload(planManagementIframeUri, { as: "document" }); preload(planManagementIframeUri, { as: "document" });
}, },
component: Plan, component: RouteComponent,
}); });
function Plan(): React.ReactElement { function RouteComponent(): React.ReactElement {
const result = useSuspenseQuery(query); const result = useSuspenseQuery(query);
const { planManagementIframeUri } = result.data.siteConfig; const { planManagementIframeUri } = result.data.siteConfig;
@@ -45,6 +45,14 @@ function Plan(): React.ReactElement {
return <Navigate to="/" replace />; return <Navigate to="/" replace />;
} }
return <Plan planManagementIframeUri={planManagementIframeUri} />;
}
function Plan({
planManagementIframeUri,
}: {
planManagementIframeUri: string;
}): React.ReactElement {
const ref = useRef<HTMLIFrameElement>(null); const ref = useRef<HTMLIFrameElement>(null);
// Query the size of the iframe content and set the height // Query the size of the iframe content and set the height
@@ -79,16 +87,8 @@ function Plan(): React.ReactElement {
[calculateHeight], [calculateHeight],
); );
useEffect(() => { const attachObserver = useCallback(
const iframe = ref.current; (iframe: HTMLIFrameElement) => {
if (iframe) {
attachObserver(iframe);
}
// Cleanup observer when the component unmounts
return () => observer.disconnect();
}, [observer]);
const attachObserver = (iframe: HTMLIFrameElement) => {
const iframeBody = iframe.contentWindow?.document.body; const iframeBody = iframe.contentWindow?.document.body;
if (!iframeBody) { if (!iframeBody) {
return; return;
@@ -101,7 +101,18 @@ function Plan(): React.ReactElement {
subtree: true, subtree: true,
attributes: true, attributes: true,
}); });
}; },
[calculateHeight, observer],
);
useEffect(() => {
const iframe = ref.current;
if (iframe) {
attachObserver(iframe);
}
// Cleanup observer when the component unmounts
return () => observer.disconnect();
}, [observer, attachObserver]);
return ( return (
<iframe <iframe

View File

@@ -4,8 +4,7 @@
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial // SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
// Please see LICENSE files in the repository root for full details. // Please see LICENSE files in the repository root for full details.
import { useSuspenseQuery } from "@tanstack/react-query"; import { queryOptions, useSuspenseQuery } from "@tanstack/react-query";
import { queryOptions } from "@tanstack/react-query";
import { notFound } from "@tanstack/react-router"; import { notFound } from "@tanstack/react-router";
import { H3 } from "@vector-im/compound-web"; import { H3 } from "@vector-im/compound-web";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -19,11 +18,11 @@ import Separator from "../components/Separator";
import BrowserSessionsOverview from "../components/UserSessionsOverview/BrowserSessionsOverview"; import BrowserSessionsOverview from "../components/UserSessionsOverview/BrowserSessionsOverview";
import { graphql } from "../gql"; import { graphql } from "../gql";
import { graphqlRequest } from "../graphql"; import { graphqlRequest } from "../graphql";
import { usePages } from "../pagination";
import { import {
type AnyPagination, type AnyPagination,
anyPaginationSchema, anyPaginationSchema,
normalizePagination, normalizePagination,
usePages,
} from "../pagination"; } from "../pagination";
import { getNinetyDaysAgo } from "../utils/dates"; import { getNinetyDaysAgo } from "../utils/dates";

View File

@@ -5,7 +5,7 @@
// Please see LICENSE files in the repository root for full details. // Please see LICENSE files in the repository root for full details.
import { queryOptions, useSuspenseQuery } from "@tanstack/react-query"; import { queryOptions, useSuspenseQuery } from "@tanstack/react-query";
import { Outlet, notFound } from "@tanstack/react-router"; import { notFound, Outlet } from "@tanstack/react-router";
import { Heading } from "@vector-im/compound-web"; import { Heading } from "@vector-im/compound-web";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import Layout from "../components/Layout"; import Layout from "../components/Layout";

View File

@@ -4,8 +4,7 @@
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial // SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
// Please see LICENSE files in the repository root for full details. // Please see LICENSE files in the repository root for full details.
import { useSuspenseQuery } from "@tanstack/react-query"; import { queryOptions, useSuspenseQuery } from "@tanstack/react-query";
import { queryOptions } from "@tanstack/react-query";
import { notFound } from "@tanstack/react-router"; import { notFound } from "@tanstack/react-router";
import OAuth2ClientDetail from "../components/Client/OAuth2ClientDetail"; import OAuth2ClientDetail from "../components/Client/OAuth2ClientDetail";
import Layout from "../components/Layout"; import Layout from "../components/Layout";

View File

@@ -4,11 +4,10 @@
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial // SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
// Please see LICENSE files in the repository root for full details. // Please see LICENSE files in the repository root for full details.
import { queryOptions } from "@tanstack/react-query";
import { notFound, redirect } from "@tanstack/react-router"; import { notFound, redirect } from "@tanstack/react-router";
import { Alert } from "@vector-im/compound-web"; import { Alert } from "@vector-im/compound-web";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { queryOptions } from "@tanstack/react-query";
import Layout from "../components/Layout"; import Layout from "../components/Layout";
import { Link } from "../components/Link"; import { Link } from "../components/Link";
import { graphql } from "../gql"; import { graphql } from "../gql";

View File

@@ -4,10 +4,12 @@
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial // SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
// Please see LICENSE files in the repository root for full details. // Please see LICENSE files in the repository root for full details.
import { useMutation, useSuspenseQuery } from "@tanstack/react-query"; import {
import { queryOptions } from "@tanstack/react-query"; queryOptions,
import { useNavigate, useSearch } from "@tanstack/react-router"; useMutation,
import { notFound } from "@tanstack/react-router"; useSuspenseQuery,
} from "@tanstack/react-query";
import { notFound, useNavigate, useSearch } from "@tanstack/react-router";
import IconErrorSolid from "@vector-im/compound-design-tokens/assets/web/icons/error-solid"; import IconErrorSolid from "@vector-im/compound-design-tokens/assets/web/icons/error-solid";
import IconLockSolid from "@vector-im/compound-design-tokens/assets/web/icons/lock-solid"; import IconLockSolid from "@vector-im/compound-design-tokens/assets/web/icons/lock-solid";
import { Alert, Button, Form } from "@vector-im/compound-web"; import { Alert, Button, Form } from "@vector-im/compound-web";
@@ -19,8 +21,7 @@ import Layout from "../components/Layout";
import LoadingSpinner from "../components/LoadingSpinner"; import LoadingSpinner from "../components/LoadingSpinner";
import PageHeading from "../components/PageHeading"; import PageHeading from "../components/PageHeading";
import PasswordCreationDoubleInput from "../components/PasswordCreationDoubleInput"; import PasswordCreationDoubleInput from "../components/PasswordCreationDoubleInput";
import { type FragmentType, useFragment } from "../gql"; import { type FragmentType, graphql, useFragment } from "../gql";
import { graphql } from "../gql";
import { graphqlRequest } from "../graphql"; import { graphqlRequest } from "../graphql";
import { translateSetPasswordError } from "../i18n/password_changes"; import { translateSetPasswordError } from "../i18n/password_changes";

View File

@@ -6,9 +6,8 @@
import { type ErrorComponentProps, Outlet } from "@tanstack/react-router"; import { type ErrorComponentProps, Outlet } from "@tanstack/react-router";
import IconErrorSolid from "@vector-im/compound-design-tokens/assets/web/icons/error-solid"; import IconErrorSolid from "@vector-im/compound-design-tokens/assets/web/icons/error-solid";
import { Button, Text } from "@vector-im/compound-web"; import { Button, Text } from "@vector-im/compound-web";
import * as v from "valibot";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import * as v from "valibot";
import Layout from "../components/Layout"; import Layout from "../components/Layout";
import PageHeading from "../components/PageHeading"; import PageHeading from "../components/PageHeading";

View File

@@ -5,12 +5,12 @@
// Please see LICENSE files in the repository root for full details. // Please see LICENSE files in the repository root for full details.
import { import {
RouterContextProvider,
createMemoryHistory, createMemoryHistory,
createRootRoute, createRootRoute,
createRoute, createRoute,
createRouter, createRouter,
matchContext, matchContext,
RouterContextProvider,
useRouterState, useRouterState,
} from "@tanstack/react-router"; } from "@tanstack/react-router";

View File

@@ -5,9 +5,9 @@
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { import {
RouterProvider,
createHashHistory, createHashHistory,
createRouter, createRouter,
RouterProvider,
} from "@tanstack/react-router"; } from "@tanstack/react-router";
import { TooltipProvider } from "@vector-im/compound-web"; import { TooltipProvider } from "@vector-im/compound-web";
import i18n from "i18next"; import i18n from "i18next";

View File

@@ -4,7 +4,7 @@
// Please see LICENSE files in the repository root for full details. // Please see LICENSE files in the repository root for full details.
import type { Meta, StoryObj } from "@storybook/react-vite"; import type { Meta, StoryObj } from "@storybook/react-vite";
import { HttpResponse, delay } from "msw"; import { delay, HttpResponse } from "msw";
import { import {
mockAllowCrossSigningResetMutation, mockAllowCrossSigningResetMutation,
mockCurrentViewerQuery, mockCurrentViewerQuery,

View File

@@ -4,8 +4,11 @@
// Please see LICENSE files in the repository root for full details. // Please see LICENSE files in the repository root for full details.
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { RouterProvider, createMemoryHistory } from "@tanstack/react-router"; import {
import { createRouter } from "@tanstack/react-router"; createMemoryHistory,
createRouter,
RouterProvider,
} from "@tanstack/react-router";
import { type RenderResult, render } from "@testing-library/react"; import { type RenderResult, render } from "@testing-library/react";
import { TooltipProvider } from "@vector-im/compound-web"; import { TooltipProvider } from "@vector-im/compound-web";
import i18n from "i18next"; import i18n from "i18next";