Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 11 additions & 9 deletions apps/space/app/error.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,36 @@
*/

// ui
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";

const handleRetry = () => {
window.location.reload();
};

function ErrorPage() {
const handleRetry = () => {
window.location.reload();
};
const { t } = useTranslation();

return (
<div className="grid h-screen place-items-center bg-surface-1 p-4">
<div className="space-y-8 text-center">
<div className="space-y-2">
<h3 className="text-16 font-semibold">Yikes! That doesn{"'"}t look good.</h3>
<h3 className="text-16 font-semibold">{t("space_public.error_title")}</h3>
<p className="mx-auto text-13 text-secondary md:w-1/2">
That crashed Plane, pun intended. No worries, though. Our engineers have been notified. If you have more
details, please write to{" "}
{t("space_public.error_description_prefix")}{" "}
<a href="mailto:support@plane.so" className="text-accent-primary">
support@plane.so
</a>{" "}
or on our{" "}
{t("space_public.error_description_middle")}{" "}
<a href="https://forum.plane.so" target="_blank" className="text-accent-primary" rel="noopener noreferrer">
Forum
{t("space_public.forum")}
</a>
.
</p>
</div>
<div className="flex items-center justify-center gap-2">
<Button variant="primary" size="lg" onClick={handleRetry}>
Refresh
{t("space_public.refresh")}
</Button>
{/* <Button variant="secondary" size="lg" onClick={() => {}}>
Sign out
Expand Down
10 changes: 5 additions & 5 deletions apps/space/app/not-found.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,22 @@
* See the LICENSE file for details.
*/

import { useTranslation } from "@plane/i18n";
// assets
import SomethingWentWrongImage from "@/app/assets/something-went-wrong.svg?url";

function NotFound() {
const { t } = useTranslation();
return (
<div className="grid h-screen w-screen place-items-center bg-surface-1">
<div className="text-center">
<div className="mx-auto grid size-32 place-items-center rounded-full md:size-52">
<div className="grid size-16 place-items-center md:size-32">
<img src={SomethingWentWrongImage} alt="Something went wrong" width={128} height={128} />
<img src={SomethingWentWrongImage} alt={t("space_public.something_went_wrong")} width={128} height={128} />
</div>
</div>
<h1 className="mt-8 text-18 font-semibold md:mt-12 md:text-24">That didn{"'"}t work</h1>
<p className="mt-2 text-13 md:mt-4 md:text-14">
Check the URL you are entering in the browser{"'"}s address bar and try again.
</p>
<h1 className="mt-8 text-18 font-semibold md:mt-12 md:text-24">{t("space_public.not_found_title")}</h1>
<p className="mt-2 text-13 md:mt-4 md:text-14">{t("space_public.not_found_hint")}</p>
</div>
</div>
);
Expand Down
42 changes: 9 additions & 33 deletions apps/space/components/account/auth-forms/auth-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,48 +4,24 @@
* See the LICENSE file for details.
*/

import { useTranslation } from "@plane/i18n";
// helpers
import { EAuthModes } from "@/types/auth";

type TAuthHeader = {
authMode: EAuthModes;
};

type TAuthHeaderContent = {
header: string;
subHeader: string;
};

type TAuthHeaderDetails = {
[mode in EAuthModes]: TAuthHeaderContent;
};

const Titles: TAuthHeaderDetails = {
[EAuthModes.SIGN_IN]: {
header: "Sign in to upvote or comment",
subHeader: "Contribute in nudging the features you want to get built.",
},
[EAuthModes.SIGN_UP]: {
header: "View, comment, and do more",
subHeader: "Sign up or log in to work with Plane work items and Pages.",
},
};

export function AuthHeader(props: TAuthHeader) {
const { authMode } = props;

const getHeaderSubHeader = (mode: EAuthModes | null): TAuthHeaderContent => {
if (mode) {
return Titles[mode];
}

return {
header: "Comment or react to work items",
subHeader: "Use plane to add your valuable inputs to features.",
};
};

const { header, subHeader } = getHeaderSubHeader(authMode);
const { t } = useTranslation();

const header =
authMode === EAuthModes.SIGN_IN ? t("space_public.auth.sign_in_header") : t("space_public.auth.sign_up_header");
const subHeader =
authMode === EAuthModes.SIGN_IN
? t("space_public.auth.sign_in_subheader")
: t("space_public.auth.sign_up_subheader");

return (
<>
Expand Down
10 changes: 6 additions & 4 deletions apps/space/components/account/auth-forms/auth-root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { useEffect, useState } from "react";
import { observer } from "mobx-react";
import { useSearchParams } from "next/navigation";
// plane imports
import { useTranslation } from "@plane/i18n";
import { SitesAuthService } from "@plane/services";
import type { IEmailCheckData } from "@plane/types";
import { OAuthOptions } from "@plane/ui";
Expand Down Expand Up @@ -43,6 +44,7 @@ export const AuthRoot = observer(function AuthRoot() {
const [isPasswordAutoset, setIsPasswordAutoset] = useState(true);
// hooks
const { config } = useInstance();
const { t } = useTranslation();

useEffect(() => {
if (error_code) {
Expand Down Expand Up @@ -84,7 +86,7 @@ export const AuthRoot = observer(function AuthRoot() {
const isSMTPConfigured = config?.is_smtp_configured || false;
const isMagicLoginEnabled = config?.is_magic_login_enabled || false;
const isEmailPasswordEnabled = config?.is_email_password_enabled || false;
const oAuthActionText = authMode === EAuthModes.SIGN_UP ? "Sign up" : "Sign in";
const oAuthActionText = authMode === EAuthModes.SIGN_UP ? t("space_public.sign_up") : t("space_public.sign_in");
const { isOAuthEnabled, oAuthOptions } = useOAuthConfig(oAuthActionText);

// submit handler- email verification
Expand Down Expand Up @@ -134,8 +136,8 @@ export const AuthRoot = observer(function AuthRoot() {
};

// generating the unique code
const generateEmailUniqueCode = async (email: string): Promise<{ code: string } | undefined> => {
const payload = { email: email };
const generateEmailUniqueCode = async (emailId: string): Promise<{ code: string } | undefined> => {
const payload = { email: emailId };
return await authService
.generateUniqueCode(payload)
.then(() => ({ code: "" }))
Expand Down Expand Up @@ -185,7 +187,7 @@ export const AuthRoot = observer(function AuthRoot() {
}}
/>
)}
<TermsAndConditions isSignUp={authMode === EAuthModes.SIGN_UP ? true : false} />
<TermsAndConditions isSignUp={authMode === EAuthModes.SIGN_UP} />
</div>
</div>
);
Expand Down
19 changes: 12 additions & 7 deletions apps/space/components/account/auth-forms/email.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@
*/

import type { FormEvent } from "react";
import { useMemo, useRef, useState } from "react";
import { useEffect, useMemo, useRef, useState } from "react";
import { observer } from "mobx-react";
// icons
import { CircleAlert, XCircle } from "lucide-react";
// types
import { Button } from "@plane/propel/button";
import { useTranslation } from "@plane/i18n";
import type { IEmailCheckData } from "@plane/types";
// ui
import { Input, Spinner } from "@plane/ui";
Expand All @@ -25,13 +26,14 @@ type TAuthEmailForm = {

export const AuthEmailForm = observer(function AuthEmailForm(props: TAuthEmailForm) {
const { onSubmit, defaultEmail } = props;
const { t } = useTranslation();
// states
const [isSubmitting, setIsSubmitting] = useState(false);
const [email, setEmail] = useState(defaultEmail);

const emailError = useMemo(
() => (email && !checkEmailValidity(email) ? { email: "Email is invalid" } : undefined),
[email]
() => (email && !checkEmailValidity(email) ? { email: t("space_auth.email_invalid") } : undefined),
[email, t]
);

const handleFormSubmit = async (event: FormEvent<HTMLFormElement>) => {
Expand All @@ -49,11 +51,15 @@ export const AuthEmailForm = observer(function AuthEmailForm(props: TAuthEmailFo
const [isFocused, setIsFocused] = useState(true);
const inputRef = useRef<HTMLInputElement>(null);

useEffect(() => {
inputRef.current?.focus();
}, []);

return (
<form onSubmit={handleFormSubmit} className="mt-5 space-y-4">
<div className="space-y-1">
<label className="text-13 font-medium text-tertiary" htmlFor="email">
Email
{t("space_auth.email")}
</label>
<div
className={cn(
Expand All @@ -76,13 +82,12 @@ export const AuthEmailForm = observer(function AuthEmailForm(props: TAuthEmailFo
placeholder="name@company.com"
className={`h-10 w-full border-0 disable-autofill-style placeholder:text-placeholder autofill:bg-danger-subtle focus:bg-none active:bg-transparent`}
autoComplete="off"
autoFocus
ref={inputRef}
/>
{email.length > 0 && (
<button
type="button"
aria-label="Clear email"
aria-label={t("space_auth.clear_email")}
onClick={() => {
setEmail("");
inputRef.current?.focus();
Expand All @@ -101,7 +106,7 @@ export const AuthEmailForm = observer(function AuthEmailForm(props: TAuthEmailFo
)}
</div>
<Button type="submit" variant="primary" className="w-full" size="xl" disabled={isButtonDisabled}>
{isSubmitting ? <Spinner height="20px" width="20px" /> : "Continue"}
{isSubmitting ? <Spinner height="20px" width="20px" /> : t("space_auth.continue")}
</Button>
</form>
);
Expand Down
38 changes: 19 additions & 19 deletions apps/space/components/account/auth-forms/password.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { observer } from "mobx-react";
import { Eye, EyeOff, XCircle } from "lucide-react";
// plane imports
import { API_BASE_URL, E_PASSWORD_STRENGTH } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { AuthService } from "@plane/services";
import { Input, Spinner, PasswordStrengthIndicator } from "@plane/ui";
Expand Down Expand Up @@ -41,6 +42,7 @@ const authService = new AuthService();

export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props) {
const { email, nextPath, isSMTPConfigured, handleAuthStep, handleEmailClear, mode } = props;
const { t } = useTranslation();
// ref
const formRef = useRef<HTMLFormElement>(null);
// states
Expand Down Expand Up @@ -79,14 +81,11 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props)

const isButtonDisabled = useMemo(
() =>
!isSubmitting &&
!!passwordFormData.password &&
(mode === EAuthModes.SIGN_UP
? getPasswordStrength(passwordFormData.password) === E_PASSWORD_STRENGTH.STRENGTH_VALID &&
passwordFormData.password === passwordFormData.confirm_password
: true)
? false
: true,
isSubmitting ||
!passwordFormData.password ||
(mode === EAuthModes.SIGN_UP &&
(getPasswordStrength(passwordFormData.password) !== E_PASSWORD_STRENGTH.STRENGTH_VALID ||
passwordFormData.password !== passwordFormData.confirm_password)),
[isSubmitting, mode, passwordFormData.confirm_password, passwordFormData.password]
);

Expand Down Expand Up @@ -123,7 +122,7 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props)
<input type="hidden" value={nextPath} name="next_path" />
<div className="space-y-1">
<label className="text-13 font-medium text-tertiary" htmlFor="email">
Email
{t("space_auth.email")}
</label>
<div className={`relative flex items-center rounded-md border border-subtle bg-surface-1`}>
<Input
Expand All @@ -147,20 +146,19 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props)

<div className="space-y-1">
<label className="text-13 font-medium text-tertiary" htmlFor="password">
{mode === EAuthModes.SIGN_IN ? "Password" : "Set a password"}
{mode === EAuthModes.SIGN_IN ? t("space_auth.password") : t("space_auth.set_password")}
</label>
<div className="relative flex items-center rounded-md bg-surface-1">
<Input
type={showPassword?.password ? "text" : "password"}
name="password"
value={passwordFormData.password}
onChange={(e) => handleFormChange("password", e.target.value)}
placeholder="Enter password"
placeholder={t("space_auth.enter_password")}
className="h-10 w-full border border-subtle !bg-surface-1 pr-12 disable-autofill-style placeholder:text-placeholder"
onFocus={() => setIsPasswordInputFocused(true)}
onBlur={() => setIsPasswordInputFocused(false)}
autoComplete="off"
autoFocus
/>
{showPassword?.password ? (
<EyeOff
Expand All @@ -180,15 +178,15 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props)
{mode === EAuthModes.SIGN_UP && (
<div className="space-y-1">
<label className="text-13 font-medium text-tertiary" htmlFor="confirm_password">
Confirm password
{t("space_auth.confirm_password")}
</label>
<div className="relative flex items-center rounded-md bg-surface-1">
<Input
type={showPassword?.retypePassword ? "text" : "password"}
name="confirm_password"
value={passwordFormData.confirm_password}
onChange={(e) => handleFormChange("confirm_password", e.target.value)}
placeholder="Confirm password"
placeholder={t("space_auth.confirm_password")}
className="h-10 w-full border border-subtle !bg-surface-1 pr-12 disable-autofill-style placeholder:text-placeholder"
onFocus={() => setIsRetryPasswordInputFocused(true)}
onBlur={() => setIsRetryPasswordInputFocused(false)}
Expand All @@ -208,7 +206,9 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props)
</div>
{!!passwordFormData.confirm_password &&
passwordFormData.password !== passwordFormData.confirm_password &&
renderPasswordMatchError && <span className="text-13 text-danger-primary">Passwords don{"'"}t match</span>}
renderPasswordMatchError && (
<span className="text-13 text-danger-primary">{t("space_auth.passwords_dont_match")}</span>
)}
</div>
)}

Expand All @@ -219,9 +219,9 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props)
{isSubmitting ? (
<Spinner height="20px" width="20px" />
) : isSMTPConfigured ? (
"Continue"
t("space_auth.continue")
) : (
"Go to workspace"
t("space_auth.go_to_workspace")
)}
</Button>
{isSMTPConfigured && (
Expand All @@ -232,13 +232,13 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props)
className="w-full"
size="xl"
>
Sign in with unique code
{t("space_auth.sign_in_with_unique_code")}
</Button>
)}
</>
) : (
<Button type="submit" variant="primary" className="w-full" size="xl" disabled={isButtonDisabled}>
{isSubmitting ? <Spinner height="20px" width="20px" /> : "Create account"}
{isSubmitting ? <Spinner height="20px" width="20px" /> : t("space_auth.create_account")}
</Button>
)}
</div>
Expand Down
Loading