Web: Added activation page redesign.

This commit is contained in:
Tatiana Lopaeva 2024-02-29 16:45:15 +03:00
parent 854c9ed627
commit 171e2e6a06
4 changed files with 397 additions and 394 deletions

View File

@ -0,0 +1,55 @@
import { useTranslation, Trans } from "react-i18next";
import { ColorTheme, ThemeId } from "@docspace/shared/components/color-theme";
import { IconButton } from "@docspace/shared/components/icon-button";
import { Text } from "@docspace/shared/components/text";
import ArrowIcon from "PUBLIC_DIR/images/arrow.left.react.svg?url";
const DEFAULT_CREATION_TEXT =
"A DocSpace account will be created for {{email}}. Please, complete your registration:";
const GreetingUserContainer = ({
email,
onClickBack,
emailFromLink,
type,
defaultText,
}) => {
const { t } = useTranslation(["Confirm", "Common"]);
return (
<div className="greeting-container">
<div className="back-sign-in-container">
{type === "LinkInvite" && !emailFromLink && (
<div className="back-button">
<IconButton size={16} iconName={ArrowIcon} onClick={onClickBack} />
<Text fontWeight={600} onClick={onClickBack}>
{t("Back")}
</Text>
</div>
)}
<Text fontWeight={600} fontSize={"16px"}>
{t("SignUp")}
</Text>
</div>
<Text>
<Trans
t={t}
i18nKey={"AccountWillBeCreated"}
ns="Confirm"
defaults={DEFAULT_CREATION_TEXT}
values={{
email,
}}
components={{
1: <ColorTheme tag="a" themeId={ThemeId.Link} isHovered={false} />,
}}
/>
</Text>
</div>
);
};
export default GreetingUserContainer;

View File

@ -13,21 +13,6 @@ export const StyledCreateUserContent = styled.div`
}
`;
export const ConfirmContainer = styled(Box)`
width: 100%;
margin: 0px auto;
display: flex;
flex: 1fr;
flex-direction: column;
align-items: center;
gap: 32px;
@media ${mobile} {
margin-top: 0;
}
`;
export const GreetingContainer = styled.div`
display: flex;
flex-direction: column;
@ -35,6 +20,8 @@ export const GreetingContainer = styled.div`
height: 100%;
width: ${DESKTOP_WIDTH}px;
margin-bottom: 32px;
@media ${tablet} {
width: 100%;
max-width: ${TABLET_WIDTH}px;
@ -65,9 +52,7 @@ export const GreetingContainer = styled.div`
`;
export const RegisterContainer = styled.div`
display: flex;
flex-direction: column;
align-items: center;
height: 100%;
width: 100%;
@ -75,9 +60,6 @@ export const RegisterContainer = styled.div`
margin: 0 8px;
}
.more-label {
padding-top: 18px;
}
.line {
display: flex;
@ -118,11 +100,6 @@ export const RegisterContainer = styled.div`
width: 100%;
}
.signin-container {
width: 100%;
margin-top: 24px;
text-align: center;
}
.greeting-container{
margin-bottom: 32px;
p{

View File

@ -1,6 +1,5 @@
import React, { useState } from "react";
import { withTranslation } from "react-i18next";
import { Text } from "@docspace/shared/components/text";
import { TextInput } from "@docspace/shared/components/text-input";
import { PasswordInput } from "@docspace/shared/components/password-input";
import { Button } from "@docspace/shared/components/button";
@ -15,26 +14,23 @@ import {
import { createPasswordHash } from "@docspace/shared/utils/common";
import { toastr } from "@docspace/shared/components/toast";
import { getPasswordErrorMessage } from "@docspace/shared/utils/getPasswordErrorMessage";
import { FormWrapper } from "@docspace/shared/components/form-wrapper";
import {
StyledPage,
StyledContent,
StyledBody,
StyledHeader,
} from "./StyledConfirm";
import { StyledPage, StyledHeader } from "./StyledConfirm";
import withLoader from "../withLoader";
const ActivateUserForm = (props) => {
const {
t,
greetingTitle,
settings,
linkData,
hashSettings,
defaultPage,
login,
} = props;
import {
GreetingContainer,
RegisterContainer,
StyledCreateUserContent,
} from "./StyledCreateUser";
import DocspaceLogo from "SRC_DIR/components/DocspaceLogoWrapper";
import GreetingUserContainer from "./GreetingUserContainer";
const ActivateUserForm = (props) => {
const { t, settings, linkData, hashSettings, defaultPage, login } = props;
const emailFromLink = linkData?.email ? linkData.email : "";
const [name, setName] = useState(linkData.firstname);
const [nameValid, setNameValid] = useState(true);
const [surName, setSurName] = useState(linkData.lastname);
@ -139,111 +135,119 @@ const ActivateUserForm = (props) => {
return (
<StyledPage>
<StyledContent>
<StyledBody>
<StyledHeader>
<Text fontSize="23px" fontWeight="700" className="title">
{greetingTitle}
</Text>
<StyledCreateUserContent>
<StyledHeader>
<GreetingContainer>
<DocspaceLogo className="docspace-logo" />
</GreetingContainer>
</StyledHeader>
<Text className="subtitle">{t("InviteTitle")}</Text>
</StyledHeader>
<FormWrapper>
<RegisterContainer>
<form className="auth-form-container">
<GreetingUserContainer
emailFromLink={!!emailFromLink}
email={emailFromLink}
/>
<FieldContainer
className="form-field"
isVertical={true}
labelVisible={false}
hasError={!nameValid}
errorMessage={t("Common:RequiredField")}
>
<TextInput
id="name"
name="name"
value={name}
placeholder={t("Common:FirstName")}
size="large"
scale={true}
tabIndex={1}
isAutoFocussed={true}
autoComplete="given-name"
onChange={onChangeName}
onKeyDown={onKeyPress}
/>
</FieldContainer>
<FieldContainer
className="form-field"
isVertical={true}
labelVisible={false}
hasError={!nameValid}
errorMessage={t("Common:RequiredField")}
>
<TextInput
id="name"
name="name"
value={name}
placeholder={t("Common:FirstName")}
size="large"
scale={true}
tabIndex={1}
isAutoFocussed={true}
autoComplete="given-name"
onChange={onChangeName}
onKeyDown={onKeyPress}
/>
</FieldContainer>
<FieldContainer
className="form-field"
isVertical={true}
labelVisible={false}
hasError={!surNameValid}
errorMessage={t("Common:RequiredField")}
>
<TextInput
id="surname"
name="surname"
value={surName}
placeholder={t("Common:LastName")}
size="large"
scale={true}
tabIndex={2}
autoComplete="family-name"
onChange={onChangeSurName}
onKeyDown={onKeyPress}
/>
</FieldContainer>
<FieldContainer
className="form-field"
isVertical={true}
labelVisible={false}
hasError={!surNameValid}
errorMessage={t("Common:RequiredField")}
>
<TextInput
id="surname"
name="surname"
value={surName}
placeholder={t("Common:LastName")}
size="large"
scale={true}
tabIndex={2}
autoComplete="family-name"
onChange={onChangeSurName}
onKeyDown={onKeyPress}
/>
</FieldContainer>
<FieldContainer
className="form-field"
isVertical={true}
labelVisible={false}
hasError={isPasswordErrorShow && !passwordValid}
errorMessage={`${t(
"Common:PasswordLimitMessage",
)}: ${getPasswordErrorMessage(t, settings)}`}
>
<PasswordInput
className="confirm-input"
simpleView={false}
passwordSettings={settings}
id="password"
inputName="password"
placeholder={t("Common:Password")}
type="password"
inputValue={password}
hasError={isPasswordErrorShow && !passwordValid}
size="large"
scale={true}
tabIndex={1}
autoComplete="current-password"
onChange={onChangePassword}
onValidateInput={onValidatePassword}
onBlur={onBlurPassword}
onKeyDown={onKeyPress}
tooltipPasswordTitle={`${t("Common:PasswordLimitMessage")}:`}
tooltipPasswordLength={`${t("Common:PasswordMinimumLength")}: ${
settings ? settings.minLength : 8
}`}
tooltipPasswordDigits={`${t("Common:PasswordLimitDigits")}`}
tooltipPasswordCapital={`${t("Common:PasswordLimitUpperCase")}`}
tooltipPasswordSpecial={`${t(
"Common:PasswordLimitSpecialSymbols",
)}`}
generatePasswordTitle={t("Wizard:GeneratePassword")}
// If need copy credentials use t("EmailAndPasswordCopiedToClipboard")
/>
</FieldContainer>
<FieldContainer
className="form-field password-field"
isVertical={true}
labelVisible={false}
hasError={isPasswordErrorShow && !passwordValid}
errorMessage={`${t(
"Common:PasswordLimitMessage",
)}: ${getPasswordErrorMessage(t, settings)}`}
>
<PasswordInput
className="confirm-input"
simpleView={false}
passwordSettings={settings}
id="password"
inputName="password"
placeholder={t("Common:Password")}
type="password"
inputValue={password}
hasError={isPasswordErrorShow && !passwordValid}
size="large"
scale={true}
tabIndex={1}
autoComplete="current-password"
onChange={onChangePassword}
onValidateInput={onValidatePassword}
onBlur={onBlurPassword}
onKeyDown={onKeyPress}
tooltipPasswordTitle={`${t("Common:PasswordLimitMessage")}:`}
tooltipPasswordLength={`${t("Common:PasswordMinimumLength")}: ${
settings ? settings.minLength : 8
}`}
tooltipPasswordDigits={`${t("Common:PasswordLimitDigits")}`}
tooltipPasswordCapital={`${t("Common:PasswordLimitUpperCase")}`}
tooltipPasswordSpecial={`${t(
"Common:PasswordLimitSpecialSymbols",
)}`}
generatePasswordTitle={t("Wizard:GeneratePassword")}
// If need copy credentials use t("EmailAndPasswordCopiedToClipboard")
/>
</FieldContainer>
<Button
className="confirm-button"
primary
size="normal"
label={t("LoginRegistryButton")}
tabIndex={5}
onClick={onSubmit}
isDisabled={isLoading}
/>
</StyledBody>
</StyledContent>
<Button
scale
className="confirm-button"
primary
size="medium"
label={t("LoginRegistryButton")}
tabIndex={5}
onClick={onSubmit}
isDisabled={isLoading}
/>
</form>
</RegisterContainer>
</FormWrapper>
</StyledCreateUserContent>
</StyledPage>
);
};
@ -260,7 +264,6 @@ export default inject(({ authStore, settingsStore }) => {
return {
theme,
settings: passwordSettings,
greetingTitle: greetingSettings,
hashSettings,
defaultPage,
login: authStore.login,

View File

@ -1,5 +1,4 @@
import SsoReactSvgUrl from "PUBLIC_DIR/images/sso.react.svg?url";
import ArrowIcon from "PUBLIC_DIR/images/arrow.left.react.svg?url";
import React, { useEffect, useState, useCallback } from "react";
import { withTranslation, Trans } from "react-i18next";
@ -38,23 +37,19 @@ import withLoader from "../withLoader";
import { StyledPage } from "./StyledConfirm";
import {
ConfirmContainer,
GreetingContainer,
RegisterContainer,
StyledCreateUserContent,
} from "./StyledCreateUser";
import GreetingUserContainer from "./GreetingUserContainer";
const DEFAULT_ROOM_TEXT =
"<strong>{{firstName}} {{lastName}}</strong> invites you to join the room <strong>{{roomName}}</strong> for secure document collaboration.";
const DEFAULT_PORTAL_TEXT =
"<strong>{{firstName}} {{lastName}}</strong> invites you to join the room <strong>{{roomName}}</strong> for secure document collaboration.";
const DEFAULT_CREATION_TEXT =
"A DocSpace account will be created for {{email}}. Please, complete your registration:";
const RegistrationFormGreeting = ({
email,
t,
setRegistrationForm,
type,
emailFromLink,
@ -64,36 +59,12 @@ const RegistrationFormGreeting = ({
};
return (
<div className="greeting-container">
<div className="back-sign-in-container">
{type === "LinkInvite" && !emailFromLink && (
<div className="back-button">
<IconButton size={16} iconName={ArrowIcon} onClick={onClickBack} />
<Text fontWeight={600} onClick={onClickBack}>
{t("Back")}
</Text>
</div>
)}
<Text fontWeight={600} fontSize={"16px"}>
{t("SignUp")}
</Text>
</div>
<Text>
<Trans
t={t}
i18nKey={"AccountWillBeCreated"}
ns="Confirm"
defaults={DEFAULT_CREATION_TEXT}
values={{
email,
}}
components={{
1: <ColorTheme tag="a" themeId={ThemeId.Link} isHovered={false} />,
}}
/>
</Text>
</div>
<GreetingUserContainer
type={type}
emailFromLink={!!emailFromLink}
email={email}
onClickBack={onClickBack}
/>
);
};
const CreateUserForm = (props) => {
@ -461,14 +432,13 @@ const CreateUserForm = (props) => {
return (
<StyledPage>
<StyledCreateUserContent>
<ConfirmContainer>
<GreetingContainer>
<DocspaceLogo className="docspace-logo" />
{linkData.type === "LinkInvite" && (
<div className="tooltip">
<Text fontSize="16px">
<Trans
t={t}
<GreetingContainer>
<DocspaceLogo className="docspace-logo" />
{linkData.type === "LinkInvite" && (
<div className="tooltip">
<Text fontSize="16px">
<Trans
t={t}
i18nKey={
roomName ? "InvitationToRoom" : "InvitationToPortal"
}
@ -476,226 +446,224 @@ const CreateUserForm = (props) => {
defaults={
roomName ? DEFAULT_ROOM_TEXT : DEFAULT_PORTAL_TEXT
}
values={{
firstName: user.firstName,
lastName: user.lastName,
...(roomName
? { roomName }
: { spaceAddress: window.location.host }),
}}
components={{
1: <Text fontWeight={600} as="strong" fontSize="16px" />,
}}
/>
</Text>
</div>
)}
</GreetingContainer>
values={{
firstName: user.firstName,
lastName: user.lastName,
...(roomName
? { roomName }
: { spaceAddress: window.location.host }),
}}
components={{
1: <Text fontWeight={600} as="strong" fontSize="16px" />,
}}
/>
</Text>
</div>
)}
</GreetingContainer>
<FormWrapper>
<FormWrapper>
<RegisterContainer>
<form className="auth-form-container">
<div className="auth-form-fields">
{!registrationForm && (
<>
<FieldContainer
className="form-field"
isVertical={true}
labelVisible={false}
<form className="auth-form-container">
<div className="auth-form-fields">
{!registrationForm && (
<>
<FieldContainer
className="form-field"
isVertical={true}
labelVisible={false}
hasError={isEmailErrorShow && !emailValid}
errorMessage={
emailErrorText
? t(`Common:${emailErrorText}`)
: t("Common:RequiredField")
}
>
<EmailInput
id="login"
name="login"
type="email"
hasError={isEmailErrorShow && !emailValid}
errorMessage={
emailErrorText
? t(`Common:${emailErrorText}`)
: t("Common:RequiredField")
}
>
<EmailInput
id="login"
name="login"
type="email"
hasError={isEmailErrorShow && !emailValid}
value={email}
placeholder={t("Common:Email")}
size="large"
scale={true}
isAutoFocussed={true}
tabIndex={1}
isDisabled={isLoading || !!emailFromLink}
autoComplete="username"
onChange={onChangeEmail}
onBlur={onBlurEmail}
onValidateInput={onValidateEmail}
forwardedRef={inputRef}
onKeyDown={onKeyPress}
/>
</FieldContainer>
<Button
className="login-button"
primary
size="medium"
value={email}
placeholder={t("Common:Email")}
size="large"
scale={true}
isAutoFocussed={true}
tabIndex={1}
isDisabled={isLoading || !!emailFromLink}
autoComplete="username"
onChange={onChangeEmail}
onBlur={onBlurEmail}
onValidateInput={onValidateEmail}
forwardedRef={inputRef}
onKeyDown={onKeyPress}
/>
</FieldContainer>
<Button
className="login-button"
primary
size="medium"
scale={true}
label={t("Common:ContinueButton")}
tabIndex={1}
isDisabled={isLoading}
isLoading={isLoading}
onClick={onContinue}
/>
</>
)}
{registrationForm && (
<div>
<RegistrationFormGreeting
email={email}
setRegistrationForm={setRegistrationForm}
type={linkData.type}
emailFromLink={emailFromLink}
/>
<FieldContainer
className="form-field"
isVertical={true}
labelVisible={false}
hasError={!fnameValid}
errorMessage={
errorText
? errorText
: fname.trim().length === 0
? t("Common:RequiredField")
: t("Common:IncorrectFirstName")
}
>
<TextInput
id="first-name"
name="first-name"
type="text"
hasError={!fnameValid}
value={fname}
placeholder={t("Common:FirstName")}
size="large"
scale={true}
label={t("Common:ContinueButton")}
tabIndex={1}
isDisabled={isLoading}
isLoading={isLoading}
onClick={onContinue}
onChange={onChangeFname}
onKeyDown={onKeyPress}
isAutoFocussed
/>
</>
)}
{registrationForm && (
<div>
<RegistrationFormGreeting
email={email}
t={t}
setRegistrationForm={setRegistrationForm}
type={linkData.type}
emailFromLink={emailFromLink}
/>
<FieldContainer
className="form-field"
isVertical={true}
labelVisible={false}
hasError={!fnameValid}
errorMessage={
errorText
? errorText
: fname.trim().length === 0
? t("Common:RequiredField")
: t("Common:IncorrectFirstName")
}
>
<TextInput
id="first-name"
name="first-name"
type="text"
hasError={!fnameValid}
value={fname}
placeholder={t("Common:FirstName")}
size="large"
scale={true}
tabIndex={1}
isDisabled={isLoading}
onChange={onChangeFname}
onKeyDown={onKeyPress}
isAutoFocussed
/>
</FieldContainer>
<FieldContainer
className="form-field"
isVertical={true}
labelVisible={false}
</FieldContainer>
<FieldContainer
className="form-field"
isVertical={true}
labelVisible={false}
hasError={!snameValid}
errorMessage={
errorText
? errorText
: sname.trim().length === 0
? t("Common:RequiredField")
: t("Common:IncorrectLastName")
}
>
<TextInput
id="last-name"
name="last-name"
type="text"
hasError={!snameValid}
errorMessage={
errorText
? errorText
: sname.trim().length === 0
? t("Common:RequiredField")
: t("Common:IncorrectLastName")
}
>
<TextInput
id="last-name"
name="last-name"
type="text"
hasError={!snameValid}
value={sname}
placeholder={t("Common:LastName")}
size="large"
scale={true}
tabIndex={1}
isDisabled={isLoading}
onChange={onChangeSname}
onKeyDown={onKeyPress}
/>
</FieldContainer>
<FieldContainer
className="form-field password-field"
isVertical={true}
labelVisible={false}
hasError={isPasswordErrorShow && !passwordValid}
errorMessage={`${t(
"Common:PasswordLimitMessage",
)}: ${getPasswordErrorMessage(t, settings)}`}
>
<PasswordInput
simpleView={false}
hideNewPasswordButton
showCopyLink={false}
passwordSettings={settings}
id="password"
inputName="password"
placeholder={t("Common:Password")}
type="password"
hasError={isPasswordErrorShow && !passwordValid}
inputValue={password}
size="large"
scale={true}
tabIndex={1}
isDisabled={isLoading}
autoComplete="current-password"
onChange={onChangePassword}
onBlur={onBlurPassword}
onKeyDown={onKeyPress}
onValidateInput={onValidatePassword}
tooltipPasswordTitle={`${t(
"Common:PasswordLimitMessage",
)}:`}
tooltipPasswordLength={`${t(
"Common:PasswordMinimumLength",
)}: ${settings ? settings.minLength : 8}`}
tooltipPasswordDigits={`${t(
"Common:PasswordLimitDigits",
)}`}
tooltipPasswordCapital={`${t(
"Common:PasswordLimitUpperCase",
)}`}
tooltipPasswordSpecial={`${t(
"Common:PasswordLimitSpecialSymbols",
)}`}
generatePasswordTitle={t("Wizard:GeneratePassword")}
/>
</FieldContainer>
<Button
className="login-button"
primary
size="medium"
value={sname}
placeholder={t("Common:LastName")}
size="large"
scale={true}
tabIndex={1}
isDisabled={isLoading}
onChange={onChangeSname}
onKeyDown={onKeyPress}
/>
</FieldContainer>
<FieldContainer
className="form-field password-field"
isVertical={true}
labelVisible={false}
hasError={isPasswordErrorShow && !passwordValid}
errorMessage={`${t(
"Common:PasswordLimitMessage",
)}: ${getPasswordErrorMessage(t, settings)}`}
>
<PasswordInput
simpleView={false}
hideNewPasswordButton
showCopyLink={false}
passwordSettings={settings}
id="password"
inputName="password"
placeholder={t("Common:Password")}
type="password"
hasError={isPasswordErrorShow && !passwordValid}
inputValue={password}
size="large"
scale={true}
tabIndex={1}
isDisabled={isLoading}
autoComplete="current-password"
onChange={onChangePassword}
onBlur={onBlurPassword}
onKeyDown={onKeyPress}
onValidateInput={onValidatePassword}
tooltipPasswordTitle={`${t(
"Common:PasswordLimitMessage",
)}:`}
tooltipPasswordLength={`${t(
"Common:PasswordMinimumLength",
)}: ${settings ? settings.minLength : 8}`}
tooltipPasswordDigits={`${t(
"Common:PasswordLimitDigits",
)}`}
tooltipPasswordCapital={`${t(
"Common:PasswordLimitUpperCase",
)}`}
tooltipPasswordSpecial={`${t(
"Common:PasswordLimitSpecialSymbols",
)}`}
generatePasswordTitle={t("Wizard:GeneratePassword")}
/>
</FieldContainer>
<Button
className="login-button"
primary
size="medium"
scale={true}
label={
isLoading
? t("Common:LoadingProcessing")
: t("SignUp")
}
tabIndex={1}
isDisabled={isLoading}
isLoading={isLoading}
onClick={onSubmit}
/>
</div>
)}
</div>
</form>
{!emailFromLink && (oauthDataExists() || ssoExists()) && (
<>
<div className="line">
<Text color="#A3A9AE" className="or-label">
{t("Common:orContinueWith")}
</Text>
}
tabIndex={1}
isDisabled={isLoading}
isLoading={isLoading}
onClick={onSubmit}
/>
</div>
<SocialButtonsGroup
providers={providers}
onClick={onSocialButtonClick}
t={t}
isDisabled={isLoading}
{...ssoProps}
/>
</>
)}
</RegisterContainer>
</FormWrapper>
</ConfirmContainer>
)}
</div>
</form>
{!emailFromLink && (oauthDataExists() || ssoExists()) && (
<>
<div className="line">
<Text color="#A3A9AE" className="or-label">
{t("Common:orContinueWith")}
</Text>
</div>
<SocialButtonsGroup
providers={providers}
onClick={onSocialButtonClick}
t={t}
isDisabled={isLoading}
{...ssoProps}
/>
</>
)}
</RegisterContainer>
</FormWrapper>
</StyledCreateUserContent>
</StyledPage>
);