Batch of fixes from the automated QA pass on develop. Each was reproduced and then verified fixed live (browser/curl); logic-bearing fixes have unit tests. Functional bugs: - #122 collab-token was capped by the anonymous public-share-AI throttler (5/min); skip all non-AUTH named throttlers on this auth-guarded, client-cached route. - #123 editor onAuthenticationFailed threw `jwtDecode(undefined)` and never reconnected; read the token via a ref, guard the decode (incl. missing exp), and refetch+reconnect on any auth failure. - #124 a slash command containing a space ("/Heading 1") inserted literal text; enable allowSpaces and close the menu when the query matches no items. - #125 space slug auto-gen produced uppercase initials for multi-word names; computeSpaceSlug now yields a lowercase alphanumeric slug. - #126 AI chat window position/size now persisted (atomWithStorage) across reload; also fixes a latent ResizeObserver-attach bug on first open. - #127 workspace name update accepted URLs; add @NoUrls (parity with setup). - #132 icon-columns 4/5 passed calc() into SVG width/height attrs (console spam); size via style. share-for-page query returns null instead of undefined. - #134 "Reindex now" counter looked stuck: reindex runs async; the client now polls coverage (bounded) so the counter climbs live; misleading server comment reworded. UX / consistency: - #128 add success toasts to favorite/label/avatar/member-(de)activate. - #129 "1 result found" pluralization; hide the single-option Type filter. - #130 replace raw Zod strings with friendly messages (name/password/group). - #131 unify "Untitled" casing in tree/breadcrumb/tab; stop force-uppercasing space-name chips; fix confirm-dialog labels (Cancel / Remove), invite placeholder typo, Export/Move-to-space labels. - #133 disable profile Save when clean; toast on unsupported avatar image; style the invalid-invitation page with a CTA; hide Share for read-only users; align the dictation "not configured" message; "Go to login page" typo. Tests: computeSpaceSlug, workspace-name NoUrls DTO, share-query null normalization, slash getSuggestionItems empty-close. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
61 lines
1.6 KiB
TypeScript
61 lines
1.6 KiB
TypeScript
import { Helmet } from "react-helmet-async";
|
|
import { PasswordResetForm } from "@/features/auth/components/password-reset-form";
|
|
import { Link, useSearchParams } from "react-router-dom";
|
|
import { useVerifyUserTokenQuery } from "@/features/auth/queries/auth-query";
|
|
import { Button, Container, Group, Text } from "@mantine/core";
|
|
import APP_ROUTE from "@/lib/app-route";
|
|
import { getAppName } from "@/lib/config.ts";
|
|
import { useTranslation } from "react-i18next";
|
|
|
|
export default function PasswordReset() {
|
|
const { t } = useTranslation();
|
|
const [searchParams] = useSearchParams();
|
|
const { data, isLoading, isError } = useVerifyUserTokenQuery({
|
|
token: searchParams.get("token"),
|
|
type: "forgot-password",
|
|
});
|
|
const resetToken = searchParams.get("token");
|
|
|
|
if (isLoading) {
|
|
return <div></div>;
|
|
}
|
|
|
|
if (isError || !resetToken) {
|
|
return (
|
|
<>
|
|
<Helmet>
|
|
<title>
|
|
{t("Password Reset")} - {getAppName()}
|
|
</title>
|
|
</Helmet>
|
|
<Container my={40}>
|
|
<Text size="lg" ta="center">
|
|
{t("Invalid or expired password reset link")}
|
|
</Text>
|
|
<Group justify="center">
|
|
<Button
|
|
component={Link}
|
|
to={APP_ROUTE.AUTH.LOGIN}
|
|
variant="subtle"
|
|
size="md"
|
|
>
|
|
{t("Go to login page")}
|
|
</Button>
|
|
</Group>
|
|
</Container>
|
|
</>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<Helmet>
|
|
<title>
|
|
{t("Password Reset")} - {getAppName()}
|
|
</title>
|
|
</Helmet>
|
|
<PasswordResetForm resetToken={resetToken} />
|
|
</>
|
|
);
|
|
}
|