Merge pull request #1204 from ONLYOFFICE/bugfix/login-confirm-style

Bugfix/login confirm style
This commit is contained in:
Alexey Safronov 2023-02-15 12:16:36 +03:00 committed by GitHub
commit f48b2b040e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 979 additions and 984 deletions

View File

@ -3,6 +3,7 @@ import styled, { css } from "styled-components";
import { isIOS, isFirefox, isMobileOnly } from "react-device-detect";
import { inject, observer } from "mobx-react";
import { getBgPattern } from "@docspace/common/utils";
import { hugeMobile } from "@docspace/components/utils/device";
const StyledWrapper = styled.div`
height: ${isIOS && !isFirefox ? "calc(var(--vh, 1vh) * 100)" : "100vh"};
@ -18,17 +19,21 @@ const StyledWrapper = styled.div`
min-height: 100%;
width: 100%;
`}
`;
const BgBlock = styled.div`
background-image: ${(props) => props.bgPattern};
background-repeat: no-repeat;
background-attachment: fixed;
background-size: 100% 100%;
background-size: cover;
position: fixed;
top: 0;
right: 0;
left: 0;
bottom: 0;
z-index: -1;
@media (max-width: 1024px) {
background-size: cover;
}
@media (max-width: 428px) {
@media ${hugeMobile} {
background-image: none;
}
`;
@ -37,7 +42,12 @@ const ConfirmWrapper = (props) => {
const { children, currentColorScheme } = props;
const bgPattern = getBgPattern(currentColorScheme?.id);
return <StyledWrapper bgPattern={bgPattern}>{children}</StyledWrapper>;
return (
<StyledWrapper>
<BgBlock bgPattern={bgPattern} />
{children}
</StyledWrapper>
);
};
export default inject(({ auth }) => {

View File

@ -1,12 +1,13 @@
import styled from "styled-components";
import { mobile, tablet } from "@docspace/components/utils/device";
import { hugeMobile, mobile, tablet } from "@docspace/components/utils/device";
export const StyledPage = styled.div`
display: flex;
flex-direction: column;
align-items: center;
margin: 56px auto 0 auto;
margin: 0 auto;
max-width: 960px;
box-sizing: border-box;
@media ${tablet} {
padding: 0 16px;
@ -30,6 +31,23 @@ export const StyledPage = styled.div`
}
`;
export const StyledContent = styled.div`
min-height: 100vh;
flex: 1 0 auto;
flex-direction: column;
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
@media ${hugeMobile} {
justify-content: start;
min-height: 100%;
}
`;
export const StyledHeader = styled.div`
.title {
margin-bottom: 32px;
@ -44,7 +62,11 @@ export const StyledHeader = styled.div`
display: flex;
align-items: center;
justify-content: center;
padding-bottom: 64px;
padding-bottom: 40px;
}
@media ${hugeMobile} {
margin-top: 0;
}
`;
@ -52,9 +74,27 @@ export const StyledBody = styled.div`
display: flex;
flex-direction: column;
align-items: center;
margin: 56px auto;
@media ${mobile} {
@media ${hugeMobile} {
width: 100%;
margin: 0 auto;
}
.title {
margin-bottom: 32px;
text-align: center;
}
.subtitle {
margin-bottom: 32px;
}
.docspace-logo {
display: flex;
align-items: center;
justify-content: center;
padding-bottom: 40px;
}
.password-field-wrapper {

View File

@ -5,7 +5,6 @@ import Text from "@docspace/components/text";
import TextInput from "@docspace/components/text-input";
import PasswordInput from "@docspace/components/password-input";
import Button from "@docspace/components/button";
import Section from "@docspace/common/components/Section";
import FieldContainer from "@docspace/components/field-container";
import { inject, observer } from "mobx-react";
import { EmployeeActivationStatus } from "@docspace/common/constants";
@ -16,7 +15,12 @@ import {
} from "@docspace/common/api/people";
import { createPasswordHash } from "@docspace/common/utils";
import toastr from "@docspace/components/toast/toastr";
import { StyledPage, StyledBody, StyledHeader } from "./StyledConfirm";
import {
StyledPage,
StyledContent,
StyledBody,
StyledHeader,
} from "./StyledConfirm";
import withLoader from "../withLoader";
import { getPasswordErrorMessage } from "SRC_DIR/helpers/utils";
@ -135,123 +139,115 @@ const ActivateUserForm = (props) => {
return (
<StyledPage>
<StyledBody>
<StyledHeader>
<Text fontSize="23px" fontWeight="700" className="title">
{greetingTitle}
</Text>
<StyledContent>
<StyledBody>
<StyledHeader>
<Text fontSize="23px" fontWeight="700" className="title">
{greetingTitle}
</Text>
<Text className="subtitle">{t("InviteTitle")}</Text>
</StyledHeader>
<Text className="subtitle">{t("InviteTitle")}</Text>
</StyledHeader>
<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}
<FieldContainer
className="form-field"
isVertical={true}
labelVisible={false}
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")
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}
/>
</FieldContainer>
<Button
className="confirm-button"
primary
size="normal"
label={t("LoginRegistryButton")}
tabIndex={5}
onClick={onSubmit}
isDisabled={isLoading}
/>
</StyledBody>
</StyledBody>
</StyledContent>
</StyledPage>
);
};
const ActivateUserFormWrapper = (props) => {
return (
<Section>
<Section.SectionBody>
<ActivateUserForm {...props} />
</Section.SectionBody>
</Section>
);
};
export default inject(({ auth }) => {
const {
greetingSettings,
@ -272,7 +268,7 @@ export default inject(({ auth }) => {
})(
withRouter(
withTranslation(["Confirm", "Common", "Wizard"])(
withLoader(observer(ActivateUserFormWrapper))
withLoader(observer(ActivateUserForm))
)
)
);

View File

@ -3,13 +3,12 @@ import { withRouter } from "react-router";
import { withTranslation } from "react-i18next";
import Text from "@docspace/components/text";
import Button from "@docspace/components/button";
import Section from "@docspace/common/components/Section";
import { inject, observer } from "mobx-react";
import {
StyledPage,
StyledBody,
StyledHeader,
ButtonsWrapper,
StyledContent,
} from "./StyledConfirm";
import withLoader from "../withLoader";
import FormWrapper from "@docspace/components/form-wrapper";
@ -20,60 +19,50 @@ const ChangeOwnerForm = (props) => {
console.log(props.linkData);
return (
<StyledPage>
<StyledBody>
<StyledHeader>
<StyledContent>
<StyledBody>
<DocspaceLogo className="docspace-logo" />
<Text fontSize="23px" fontWeight="700" className="title">
{greetingTitle}
</Text>
</StyledHeader>
<FormWrapper>
<Text className="subtitle">
{t("ConfirmOwnerPortalTitle", { newOwner: "NEW OWNER" })}
</Text>
<ButtonsWrapper>
<Button
primary
scale
size="medium"
label={t("Common:SaveButton")}
tabIndex={2}
isDisabled={false}
//onClick={this.onAcceptClick} // call toast with t("ConfirmOwnerPortalSuccessMessage")
/>
<Button
scale
size="medium"
label={t("Common:CancelButton")}
tabIndex={2}
isDisabled={false}
//onClick={this.onCancelClick}
/>
</ButtonsWrapper>
</FormWrapper>
</StyledBody>
<FormWrapper>
<Text className="subtitle">
{t("ConfirmOwnerPortalTitle", { newOwner: "NEW OWNER" })}
</Text>
<ButtonsWrapper>
<Button
primary
scale
size="medium"
label={t("Common:SaveButton")}
tabIndex={2}
isDisabled={false}
//onClick={this.onAcceptClick} // call toast with t("ConfirmOwnerPortalSuccessMessage")
/>
<Button
scale
size="medium"
label={t("Common:CancelButton")}
tabIndex={2}
isDisabled={false}
//onClick={this.onCancelClick}
/>
</ButtonsWrapper>
</FormWrapper>
</StyledBody>
</StyledContent>
</StyledPage>
);
};
const ChangeOwnerFormWrapper = (props) => {
return (
<Section>
<Section.SectionBody>
<ChangeOwnerForm {...props} />
</Section.SectionBody>
</Section>
);
};
export default inject(({ auth }) => ({
greetingTitle: auth.settingsStore.greetingSettings,
defaultPage: auth.settingsStore.defaultPage,
}))(
withRouter(
withTranslation(["Confirm", "Common"])(
withLoader(observer(ChangeOwnerFormWrapper))
withLoader(observer(ChangeOwnerForm))
)
)
);

View File

@ -1,13 +1,12 @@
import React, { useState } from "react";
import React, { useState, useEffect } from "react";
import { withRouter } from "react-router";
import { withTranslation } from "react-i18next";
import Text from "@docspace/components/text";
import PasswordInput from "@docspace/components/password-input";
import Button from "@docspace/components/button";
import Section from "@docspace/common/components/Section";
import FieldContainer from "@docspace/components/field-container";
import { inject, observer } from "mobx-react";
import { StyledPage, StyledBody, StyledHeader } from "./StyledConfirm";
import { StyledPage, StyledBody, StyledContent } from "./StyledConfirm";
import withLoader from "../withLoader";
import { getPasswordErrorMessage } from "../../../helpers/utils";
import { createPasswordHash } from "@docspace/common/utils";
@ -26,6 +25,7 @@ const ChangePasswordForm = (props) => {
logout,
changePassword,
linkData,
getSettings,
} = props;
const [password, setPassword] = useState("");
@ -33,6 +33,10 @@ const ChangePasswordForm = (props) => {
const [isPasswordErrorShow, setIsPasswordErrorShow] = useState(false);
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
if (!hashSettings) getSettings(true);
}, []);
const onChangePassword = (e) => {
setPassword(e.target.value);
};
@ -45,7 +49,7 @@ const ChangePasswordForm = (props) => {
setIsPasswordErrorShow(true);
};
const onSubmit = () => {
const onSubmit = async () => {
setIsLoading(true);
if (!password.trim()) {
@ -57,30 +61,34 @@ const ChangePasswordForm = (props) => {
return;
}
const hash = createPasswordHash(password, hashSettings);
const { uid, confirmHeader } = linkData;
changePassword(uid, hash, confirmHeader)
.then(() => logout())
.then(() => {
setIsLoading(false);
toastr.success(t("ChangePasswordSuccess"));
tryRedirectTo(defaultPage);
})
.catch((error) => {
let errorMessage = "";
if (typeof error === "object") {
errorMessage =
error?.response?.data?.error?.message ||
error?.statusText ||
error?.message ||
"";
} else {
errorMessage = error;
}
try {
const hash = createPasswordHash(password, hashSettings);
const { uid, confirmHeader } = linkData;
await changePassword(uid, hash, confirmHeader);
logout();
setIsLoading(false);
toastr.success(t("ChangePasswordSuccess"));
tryRedirectTo(defaultPage);
} catch (error) {
let errorMessage = "";
if (typeof error === "object") {
errorMessage =
error?.response?.data?.error?.message ||
error?.statusText ||
error?.message ||
"";
} else {
errorMessage = error;
}
console.error(errorMessage);
if (errorMessage === "Invalid params") {
toastr.error(t("Common:SomethingWentWrong"));
} else {
toastr.error(t(`${errorMessage}`));
setIsLoading(false);
});
}
setIsLoading(false);
}
};
const onKeyPress = (event) => {
@ -91,83 +99,75 @@ const ChangePasswordForm = (props) => {
return (
<StyledPage>
<StyledBody>
<StyledHeader>
<StyledContent>
<StyledBody>
<DocspaceLogo className="docspace-logo" />
<Text fontSize="23px" fontWeight="700" className="title">
{greetingTitle}
</Text>
</StyledHeader>
<FormWrapper>
<div className="password-form">
<Text fontSize="16px" fontWeight="600" className="subtitle">
{t("PassworResetTitle")}
</Text>
<FieldContainer
isVertical={true}
labelVisible={false}
hasError={isPasswordErrorShow && !passwordValid}
errorMessage={`${t(
"Common:PasswordLimitMessage"
)}: ${getPasswordErrorMessage(t, settings)}`}
>
<PasswordInput
simpleView={false}
passwordSettings={settings}
id="password"
inputName="password"
placeholder={t("Common:Password")}
type="password"
inputValue={password}
<FormWrapper>
<div className="password-form">
<Text fontSize="16px" fontWeight="600" className="subtitle">
{t("PassworResetTitle")}
</Text>
<FieldContainer
isVertical={true}
labelVisible={false}
hasError={isPasswordErrorShow && !passwordValid}
size="large"
scale
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")}
/>
</FieldContainer>
</div>
errorMessage={`${t(
"Common:PasswordLimitMessage"
)}: ${getPasswordErrorMessage(t, settings)}`}
>
<PasswordInput
simpleView={false}
passwordSettings={settings}
id="password"
inputName="password"
placeholder={t("Common:Password")}
type="password"
inputValue={password}
hasError={isPasswordErrorShow && !passwordValid}
size="large"
scale
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")}
/>
</FieldContainer>
</div>
<Button
primary
size="medium"
scale
label={t("Common:Create")}
tabIndex={5}
onClick={onSubmit}
isDisabled={isLoading}
/>
</FormWrapper>
</StyledBody>
<Button
primary
size="medium"
scale
label={t("Common:Create")}
tabIndex={5}
onClick={onSubmit}
isDisabled={isLoading}
/>
</FormWrapper>
</StyledBody>
</StyledContent>
</StyledPage>
);
};
const ChangePasswordFormWrapper = (props) => {
return (
<Section>
<Section.SectionBody>
<ChangePasswordForm {...props} />
</Section.SectionBody>
</Section>
);
};
export default inject(({ auth, setup }) => {
const {
greetingSettings,
@ -175,6 +175,7 @@ export default inject(({ auth, setup }) => {
defaultPage,
passwordSettings,
theme,
getSettings,
} = auth.settingsStore;
const { changePassword } = setup;
@ -187,11 +188,12 @@ export default inject(({ auth, setup }) => {
logout: auth.logout,
changePassword,
isAuthenticated: auth.isAuthenticated,
getSettings,
};
})(
withRouter(
withTranslation(["Confirm", "Common", "Wizard"])(
withLoader(observer(ChangePasswordFormWrapper))
withLoader(observer(ChangePasswordForm))
)
)
);

View File

@ -4,9 +4,8 @@ import { withTranslation } from "react-i18next";
import Text from "@docspace/components/text";
import TextInput from "@docspace/components/text-input";
import Button from "@docspace/components/button";
import Section from "@docspace/common/components/Section";
import { inject, observer } from "mobx-react";
import { StyledPage, StyledBody, StyledHeader } from "./StyledConfirm";
import { StyledPage, StyledBody, StyledContent } from "./StyledConfirm";
import withLoader from "../withLoader";
import FormWrapper from "@docspace/components/form-wrapper";
import DocspaceLogo from "../../../DocspaceLogo";
@ -17,66 +16,54 @@ const ChangePhoneForm = (props) => {
return (
<StyledPage>
<StyledBody>
<StyledHeader>
<StyledContent>
<StyledBody>
<DocspaceLogo className="docspace-logo" />
<Text fontSize="23px" fontWeight="700" className="title">
{greetingTitle}
</Text>
</StyledHeader>
<FormWrapper>
<div className="subtitle">
<Text fontSize="16px" fontWeight="600" className="phone-title">
{t("EnterPhone")}
</Text>
<Text>
{t("CurrentNumber")}: {currentNumber}
</Text>
<Text>{t("PhoneSubtitle")}</Text>
</div>
<FormWrapper>
<div className="subtitle">
<Text fontSize="16px" fontWeight="600" className="phone-title">
{t("EnterPhone")}
</Text>
<Text>
{t("CurrentNumber")}: {currentNumber}
</Text>
<Text>{t("PhoneSubtitle")}</Text>
</div>
<TextInput
className="phone-input"
id="phone"
name="phone"
type="phone"
size="large"
scale={true}
isAutoFocussed={true}
tabIndex={1}
hasError={false}
guide={false}
/>
<TextInput
className="phone-input"
id="phone"
name="phone"
type="phone"
size="large"
scale={true}
isAutoFocussed={true}
tabIndex={1}
hasError={false}
guide={false}
/>
<Button
primary
scale
size="medium"
label={t("GetCode")}
tabIndex={2}
isDisabled={false}
/>
</FormWrapper>
</StyledBody>
<Button
primary
scale
size="medium"
label={t("GetCode")}
tabIndex={2}
isDisabled={false}
/>
</FormWrapper>
</StyledBody>
</StyledContent>
</StyledPage>
);
};
const ChangePhoneFormWrapper = (props) => {
return (
<Section>
<Section.SectionBody>
<ChangePhoneForm {...props} />
</Section.SectionBody>
</Section>
);
};
export default inject(({ auth }) => ({
greetingTitle: auth.settingsStore.greetingSettings,
}))(
withRouter(
withTranslation("Confirm")(withLoader(observer(ChangePhoneFormWrapper)))
)
withRouter(withTranslation("Confirm")(withLoader(observer(ChangePhoneForm))))
);

View File

@ -2,7 +2,6 @@ import React, { useState } from "react";
import { withRouter } from "react-router";
import { Trans, withTranslation } from "react-i18next";
import { inject, observer } from "mobx-react";
import Section from "@docspace/common/components/Section";
import Text from "@docspace/components/text";
import Button from "@docspace/components/button";
import Link from "@docspace/components/link";
@ -11,7 +10,7 @@ import { continuePortal } from "@docspace/common/api/portal";
import {
StyledPage,
StyledBody,
StyledHeader,
StyledContent,
ButtonsWrapper,
} from "./StyledConfirm";
@ -40,68 +39,56 @@ const ContinuePortal = (props) => {
return (
<StyledPage>
<StyledBody>
<StyledHeader>
<StyledContent>
<StyledBody>
<DocspaceLogo className="docspace-logo" />
<Text fontSize="23px" fontWeight="700" className="title">
{greetingTitle}
</Text>
</StyledHeader>
<FormWrapper>
{isReactivate ? (
<Trans t={t} i18nKey="SuccessReactivate" ns="Confirm">
Your account has been successfully reactivated. In 10 seconds you
will be redirected to the
<Link isHovered href="/">
portal
</Link>
</Trans>
) : (
<>
<Text className="subtitle">{t("PortalContinueTitle")}</Text>
<ButtonsWrapper>
<Button
primary
scale
size="medium"
label={t("Reactivate")}
tabIndex={1}
onClick={onRestoreClick}
/>
<Button
scale
size="medium"
label={t("Common:CancelButton")}
tabIndex={1}
onClick={onCancelClick}
/>
</ButtonsWrapper>
</>
)}
</FormWrapper>
</StyledBody>
<FormWrapper>
{isReactivate ? (
<Trans t={t} i18nKey="SuccessReactivate" ns="Confirm">
Your account has been successfully reactivated. In 10 seconds
you will be redirected to the
<Link isHovered href="/">
portal
</Link>
</Trans>
) : (
<>
<Text className="subtitle">{t("PortalContinueTitle")}</Text>
<ButtonsWrapper>
<Button
primary
scale
size="medium"
label={t("Reactivate")}
tabIndex={1}
onClick={onRestoreClick}
/>
<Button
scale
size="medium"
label={t("Common:CancelButton")}
tabIndex={1}
onClick={onCancelClick}
/>
</ButtonsWrapper>
</>
)}
</FormWrapper>
</StyledBody>
</StyledContent>
</StyledPage>
);
};
const ContinuePortalWrapper = (props) => {
return (
<Section>
<Section.SectionBody>
<ContinuePortal {...props} />
</Section.SectionBody>
</Section>
);
};
export default inject(({ auth }) => ({
greetingTitle: auth.settingsStore.greetingSettings,
theme: auth.settingsStore.theme,
}))(
withRouter(
withTranslation(["Confirm", "Common"])(
withLoader(observer(ContinuePortalWrapper))
)
withTranslation(["Confirm", "Common"])(withLoader(observer(ContinuePortal)))
)
);

View File

@ -16,7 +16,6 @@ import FieldContainer from "@docspace/components/field-container";
import toastr from "@docspace/components/toast/toastr";
import SocialButton from "@docspace/components/social-button";
import { getUserFromConfirm } from "@docspace/common/api/people";
import Section from "@docspace/common/components/Section";
import {
createPasswordHash,
getProviderTranslation,
@ -33,6 +32,7 @@ import FormWrapper from "@docspace/components/form-wrapper";
import DocspaceLogo from "../../../DocspaceLogo";
import Box from "@docspace/components/box";
import DefaultUserPhoto from "PUBLIC_DIR/images/default_user_photo_size_82-82.png";
import { StyledPage, StyledContent } from "./StyledConfirm";
export const ButtonsWrapper = styled.div`
display: flex;
@ -46,7 +46,7 @@ export const ButtonsWrapper = styled.div`
`;
const ConfirmContainer = styled(Box)`
margin-top: 80px;
margin: 56px auto;
display: flex;
flex: 1fr 1fr;
gap: 80px;
@ -54,7 +54,6 @@ const ConfirmContainer = styled(Box)`
justify-content: center;
@media ${tablet} {
margin: 100px auto 0 auto;
display: flex;
flex: 1fr;
flex-direction: column;
@ -63,7 +62,7 @@ const ConfirmContainer = styled(Box)`
}
@media ${hugeMobile} {
margin-top: 32px;
margin: 0 auto;
width: 100%;
flex: 1fr;
flex-direction: column;
@ -132,6 +131,7 @@ const GreetingContainer = styled.div`
}
.docspace-logo {
width: 100%;
padding-bottom: 32px;
.injected-svg {
@ -142,7 +142,7 @@ const GreetingContainer = styled.div`
display: flex;
align-items: center;
justify-content: center;
padding-bottom: 64px;
padding-bottom: 40px;
}
}
`;
@ -187,12 +187,12 @@ const RegisterContainer = styled.div`
//margin-top: 32px;
width: 100%;
@media (max-width: 768px) {
margin: 32px 0 0 0;
@media ${tablet} {
//margin: 32px 0 0 0;
width: 100%;
}
@media (max-width: 375px) {
margin: 32px 0 0 0;
@media ${hugeMobile} {
//margin: 32px 0 0 0;
width: 100%;
}
}
@ -211,10 +211,9 @@ const RegisterContainer = styled.div`
.password-field-wrapper {
width: 100%;
}
}
`;
}`;
const Confirm = (props) => {
const CreateUserForm = (props) => {
const { settings, t, greetingTitle, providers, isDesktop, linkData } = props;
const inputRef = React.useRef(null);
@ -553,233 +552,238 @@ const Confirm = (props) => {
const userAvatar = user.hasAvatar ? user.avatar : DefaultUserPhoto;
return (
<ConfirmContainer>
<GreetingContainer isGreetingMode={isGreetingMode}>
<DocspaceLogo className="docspace-logo" />
<Text
fontSize="23px"
fontWeight={700}
textAlign="left"
className="greeting-title"
>
{greetingTitle}
</Text>
<div className="greeting-block">
<Avatar className="avatar" role="user" source={user.avatar} />
<div className="user-info">
<Text fontSize="15px" fontWeight={600}>
{user.firstName} {user.lastName}
<StyledPage>
<StyledContent>
<ConfirmContainer>
<GreetingContainer isGreetingMode={isGreetingMode}>
<DocspaceLogo className="docspace-logo" />
<Text
fontSize="23px"
fontWeight={700}
textAlign="left"
className="greeting-title"
>
{greetingTitle}
</Text>
<Text fontSize="12px" fontWeight={600} color="#A3A9AE">
{user.department}
</Text>
</div>
</div>
<div className="tooltip">
<span className="tooltiptext">{t("WelcomeUser")}</span>
</div>
</GreetingContainer>
<div className="greeting-block">
<Avatar className="avatar" role="user" source={user.avatar} />
<div className="user-info">
<Text fontSize="15px" fontWeight={600}>
{user.firstName} {user.lastName}
</Text>
<Text fontSize="12px" fontWeight={600} color="#A3A9AE">
{user.department}
</Text>
</div>
</div>
<FormWrapper>
<RegisterContainer isGreetingMode={isGreetingMode}>
{ssoExists() && <ButtonsWrapper>{ssoButton()}</ButtonsWrapper>}
<div className="tooltip">
<span className="tooltiptext">{t("WelcomeUser")}</span>
</div>
</GreetingContainer>
{oauthDataExists() && (
<>
<ButtonsWrapper>{providerButtons()}</ButtonsWrapper>
{providers && providers.length > 2 && (
<Link
isHovered
type="action"
fontSize="13px"
fontWeight="600"
color="#3B72A7"
className="more-label"
onClick={moreAuthOpen}
>
{t("Common:ShowMore")}
</Link>
<FormWrapper>
<RegisterContainer isGreetingMode={isGreetingMode}>
{ssoExists() && <ButtonsWrapper>{ssoButton()}</ButtonsWrapper>}
{oauthDataExists() && (
<>
<ButtonsWrapper>{providerButtons()}</ButtonsWrapper>
{providers && providers.length > 2 && (
<Link
isHovered
type="action"
fontSize="13px"
fontWeight="600"
color="#3B72A7"
className="more-label"
onClick={moreAuthOpen}
>
{t("Common:ShowMore")}
</Link>
)}
</>
)}
</>
)}
{(oauthDataExists() || ssoExists()) && (
<div className="line">
<Text color="#A3A9AE" className="or-label">
{t("Common:Or")}
</Text>
</div>
)}
{(oauthDataExists() || ssoExists()) && (
<div className="line">
<Text color="#A3A9AE" className="or-label">
{t("Common:Or")}
</Text>
</div>
)}
<form className="auth-form-container">
<div className="auth-form-fields">
<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}
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}
/>
</FieldContainer>
<form className="auth-form-container">
<div className="auth-form-fields">
<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}
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}
/>
</FieldContainer>
<FieldContainer
className="form-field"
isVertical={true}
labelVisible={false}
hasError={!fnameValid}
errorMessage={errorText ? errorText : t("Common:RequiredField")}
>
<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}
/>
</FieldContainer>
<FieldContainer
className="form-field"
isVertical={true}
labelVisible={false}
hasError={!fnameValid}
errorMessage={
errorText ? errorText : t("Common:RequiredField")
}
>
<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}
/>
</FieldContainer>
<FieldContainer
className="form-field"
isVertical={true}
labelVisible={false}
hasError={!snameValid}
errorMessage={errorText ? errorText : t("Common:RequiredField")}
>
<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"
isVertical={true}
labelVisible={false}
hasError={!snameValid}
errorMessage={
errorText ? errorText : t("Common:RequiredField")
}
>
<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"
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>
<FieldContainer
className="form-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("LoginRegistryButton")
}
tabIndex={1}
isDisabled={isLoading}
isLoading={isLoading}
onClick={onSubmit}
<Button
className="login-button"
primary
size="medium"
scale={true}
label={
isLoading
? t("Common:LoadingProcessing")
: t("LoginRegistryButton")
}
tabIndex={1}
isDisabled={isLoading}
isLoading={isLoading}
onClick={onSubmit}
/>
</div>
</form>
<MoreLoginModal
t={t}
visible={moreAuthVisible}
onClose={moreAuthClose}
providers={providers}
onSocialLoginClick={onSocialButtonClick}
ssoLabel={ssoLabel}
ssoUrl={ssoUrl}
/>
</div>
</form>
<MoreLoginModal
t={t}
visible={moreAuthVisible}
onClose={moreAuthClose}
providers={providers}
onSocialLoginClick={onSocialButtonClick}
ssoLabel={ssoLabel}
ssoUrl={ssoUrl}
/>
</RegisterContainer>
</FormWrapper>
</ConfirmContainer>
</RegisterContainer>
</FormWrapper>
</ConfirmContainer>
</StyledContent>
</StyledPage>
);
};
Confirm.propTypes = {
CreateUserForm.propTypes = {
location: PropTypes.object.isRequired,
history: PropTypes.object.isRequired,
};
const CreateUserForm = (props) => (
<Section>
<Section.SectionBody>
<Confirm {...props} />
</Section.SectionBody>
</Section>
);
export default inject(({ auth }) => {
const {

View File

@ -2,7 +2,6 @@ import React, { useState } from "react";
import { withRouter } from "react-router";
import { Trans, withTranslation } from "react-i18next";
import { inject, observer } from "mobx-react";
import Section from "@docspace/common/components/Section";
import Text from "@docspace/components/text";
import Button from "@docspace/components/button";
import Link from "@docspace/components/link";
@ -11,7 +10,7 @@ import { suspendPortal } from "@docspace/common/api/portal";
import {
StyledPage,
StyledBody,
StyledHeader,
StyledContent,
ButtonsWrapper,
} from "./StyledConfirm";
@ -50,61 +49,51 @@ const DeactivatePortal = (props) => {
return (
<StyledPage>
<StyledBody>
<StyledHeader>
<StyledContent>
<StyledBody>
<DocspaceLogo className="docspace-logo" />
<Text fontSize="23px" fontWeight="700" className="title">
{greetingTitle}
</Text>
</StyledHeader>
<FormWrapper>
{isDeactivate ? (
<Trans t={t} i18nKey="SuccessDeactivate" ns="Confirm">
Your account has been successfully deactivated. In 10 seconds you
will be redirected to the
<Link isHovered href={url}>
site
</Link>
</Trans>
) : (
<>
<Text className="subtitle">{t("PortalDeactivateTitle")}</Text>
<ButtonsWrapper>
<Button
scale
primary
size="medium"
label={t("Settings:Deactivate")}
tabIndex={1}
onClick={onDeactivateClick}
/>
<Button
scale
size="medium"
label={t("Common:CancelButton")}
tabIndex={1}
onClick={onCancelClick}
/>
</ButtonsWrapper>
</>
)}
</FormWrapper>
</StyledBody>
<FormWrapper>
{isDeactivate ? (
<Trans t={t} i18nKey="SuccessDeactivate" ns="Confirm">
Your account has been successfully deactivated. In 10 seconds
you will be redirected to the
<Link isHovered href={url}>
site
</Link>
</Trans>
) : (
<>
<Text className="subtitle">{t("PortalDeactivateTitle")}</Text>
<ButtonsWrapper>
<Button
scale
primary
size="medium"
label={t("Settings:Deactivate")}
tabIndex={1}
onClick={onDeactivateClick}
/>
<Button
scale
size="medium"
label={t("Common:CancelButton")}
tabIndex={1}
onClick={onCancelClick}
/>
</ButtonsWrapper>
</>
)}
</FormWrapper>
</StyledBody>
</StyledContent>
</StyledPage>
);
};
const DeactivatePortalWrapper = (props) => {
return (
<Section>
<Section.SectionBody>
<DeactivatePortal {...props} />
</Section.SectionBody>
</Section>
);
};
export default inject(({ auth }) => ({
greetingTitle: auth.settingsStore.greetingSettings,
theme: auth.settingsStore.theme,
@ -112,7 +101,7 @@ export default inject(({ auth }) => ({
}))(
withRouter(
withTranslation(["Confirm", "Settings", "Common"])(
withLoader(observer(DeactivatePortalWrapper))
withLoader(observer(DeactivatePortal))
)
)
);

View File

@ -7,7 +7,7 @@ import Section from "@docspace/common/components/Section";
import { inject, observer } from "mobx-react";
import { deleteSelf } from "@docspace/common/api/people";
import toastr from "@docspace/components/toast/toastr";
import { StyledPage, StyledBody, StyledHeader } from "./StyledConfirm";
import { StyledPage, StyledBody, StyledContent } from "./StyledConfirm";
import withLoader from "../withLoader";
import FormWrapper from "@docspace/components/form-wrapper";
import DocspaceLogo from "../../../DocspaceLogo";
@ -35,8 +35,8 @@ const ProfileRemoveForm = (props) => {
if (isProfileDeleted) {
return (
<StyledPage>
<StyledBody>
<StyledHeader>
<StyledContent>
<StyledBody>
<DocspaceLogo className="docspace-logo" />
<Text fontSize="23px" fontWeight="700" className="title">
{t("DeleteProfileSuccessMessage")}
@ -44,65 +44,55 @@ const ProfileRemoveForm = (props) => {
<Text fontSize="16px" fontWeight="600" className="confirm-subtitle">
{t("DeleteProfileSuccessMessageInfo")}
</Text>
</StyledHeader>
</StyledBody>
</StyledBody>
</StyledContent>
</StyledPage>
);
}
return (
<StyledPage>
<StyledBody>
<StyledHeader>
<StyledContent>
<StyledBody>
<DocspaceLogo className="docspace-logo" />
<Text fontSize="23px" fontWeight="700" className="title">
{greetingTitle}
</Text>
</StyledHeader>
<FormWrapper>
<div className="subtitle">
<Text
fontSize="16px"
fontWeight="600"
className="delete-profile-confirm"
>
{t("DeleteProfileConfirmation")}
</Text>
<Text>{t("DeleteProfileConfirmationInfo")}</Text>
</div>
<FormWrapper>
<div className="subtitle">
<Text
fontSize="16px"
fontWeight="600"
className="delete-profile-confirm"
>
{t("DeleteProfileConfirmation")}
</Text>
<Text>{t("DeleteProfileConfirmationInfo")}</Text>
</div>
<Button
primary
scale
size="medium"
label={t("DeleteProfileBtn")}
tabIndex={1}
isDisabled={isLoading}
onClick={onDeleteProfile}
/>
</FormWrapper>
</StyledBody>
<Button
primary
scale
size="medium"
label={t("DeleteProfileBtn")}
tabIndex={1}
isDisabled={isLoading}
onClick={onDeleteProfile}
/>
</FormWrapper>
</StyledBody>
</StyledContent>
</StyledPage>
);
};
const ProfileRemoveFormWrapper = (props) => {
return (
<Section>
<Section.SectionBody>
<ProfileRemoveForm {...props} />
</Section.SectionBody>
</Section>
);
};
export default inject(({ auth }) => ({
greetingTitle: auth.settingsStore.greetingSettings,
theme: auth.settingsStore.theme,
logout: auth.logout,
}))(
withRouter(
withTranslation("Confirm")(withLoader(observer(ProfileRemoveFormWrapper)))
withTranslation("Confirm")(withLoader(observer(ProfileRemoveForm)))
)
);

View File

@ -2,7 +2,6 @@ import React, { useState } from "react";
import { withRouter } from "react-router";
import { withTranslation } from "react-i18next";
import { inject, observer } from "mobx-react";
import Section from "@docspace/common/components/Section";
import Text from "@docspace/components/text";
import Button from "@docspace/components/button";
import toastr from "@docspace/components/toast/toastr";
@ -10,7 +9,7 @@ import { deletePortal } from "@docspace/common/api/portal";
import {
StyledPage,
StyledBody,
StyledHeader,
StyledContent,
ButtonsWrapper,
} from "./StyledConfirm";
@ -36,56 +35,44 @@ const RemovePortal = (props) => {
return (
<StyledPage>
<StyledBody>
<StyledHeader>
<StyledContent>
<StyledBody>
<DocspaceLogo className="docspace-logo" />
<Text fontSize="23px" fontWeight="700" className="title">
{greetingTitle}
</Text>
</StyledHeader>
<FormWrapper>
<Text className="subtitle">{t("PortalRemoveTitle")}</Text>
<ButtonsWrapper>
<Button
primary
scale
size="medium"
label={t("Common:Delete")}
tabIndex={1}
onClick={onDeleteClick}
/>
<Button
scale
size="medium"
label={t("Common:CancelButton")}
tabIndex={1}
onClick={onCancelClick}
/>
</ButtonsWrapper>
</FormWrapper>
</StyledBody>
<FormWrapper>
<Text className="subtitle">{t("PortalRemoveTitle")}</Text>
<ButtonsWrapper>
<Button
primary
scale
size="medium"
label={t("Common:Delete")}
tabIndex={1}
onClick={onDeleteClick}
/>
<Button
scale
size="medium"
label={t("Common:CancelButton")}
tabIndex={1}
onClick={onCancelClick}
/>
</ButtonsWrapper>
</FormWrapper>
</StyledBody>
</StyledContent>
</StyledPage>
);
};
const RemovePortalWrapper = (props) => {
return (
<Section>
<Section.SectionBody>
<RemovePortal {...props} />
</Section.SectionBody>
</Section>
);
};
export default inject(({ auth }) => ({
greetingTitle: auth.settingsStore.greetingSettings,
theme: auth.settingsStore.theme,
}))(
withRouter(
withTranslation(["Confirm", "Common"])(
withLoader(observer(RemovePortalWrapper))
)
withTranslation(["Confirm", "Common"])(withLoader(observer(RemovePortal)))
)
);

View File

@ -6,7 +6,6 @@ import Button from "@docspace/components/button";
import TextInput from "@docspace/components/text-input";
import FieldContainer from "@docspace/components/field-container";
import Text from "@docspace/components/text";
import Section from "@docspace/common/components/Section";
import { inject, observer } from "mobx-react";
import Box from "@docspace/components/box";
import withLoader from "../withLoader";
@ -16,9 +15,10 @@ import { hugeMobile, tablet } from "@docspace/components/utils/device";
import Link from "@docspace/components/link";
import FormWrapper from "@docspace/components/form-wrapper";
import DocspaceLogo from "../../../DocspaceLogo";
import { StyledPage, StyledContent } from "./StyledConfirm";
const StyledForm = styled(Box)`
margin-top: 63px;
margin: 56px auto;
display: flex;
flex: 1fr 1fr;
gap: 80px;
@ -26,18 +26,14 @@ const StyledForm = styled(Box)`
justify-content: center;
@media ${tablet} {
margin: 100px auto 0 auto;
display: flex;
flex: 1fr;
flex-direction: column;
align-items: center;
gap: 32px;
}
@media ${hugeMobile} {
margin-top: 32px;
width: 100%;
flex: 1fr;
margin: 0 auto;
flex-direction: column;
gap: 0px;
padding-right: 8px;
@ -52,7 +48,7 @@ const StyledForm = styled(Box)`
}
.docspace-logo {
padding-bottom: 64px;
padding-bottom: 40px;
@media ${tablet} {
display: flex;
@ -142,97 +138,109 @@ const TfaActivationForm = withLoader((props) => {
};
return (
<StyledForm className="set-app-container">
<Box className="set-app-description" marginProp="0 0 32px 0">
<DocspaceLogo className="docspace-logo" />
<Text isBold fontSize="14px" className="set-app-title">
{t("SetAppTitle")}
</Text>
<StyledPage>
<StyledContent>
<StyledForm className="set-app-container">
<Box className="set-app-description" marginProp="0 0 32px 0">
<DocspaceLogo className="docspace-logo" />
<Text isBold fontSize="14px" className="set-app-title">
{t("SetAppTitle")}
</Text>
<Trans t={t} i18nKey="SetAppDescription" ns="Confirm">
The two-factor authentication is enabled to provide additional portal
security. Configure your authenticator application to continue work on
the portal. For example you could use Google Authenticator for
<Link isHovered href={props.tfaAndroidAppUrl} target="_blank">
Android
</Link>
and{" "}
<Link isHovered href={props.tfaIosAppUrl} target="_blank">
iOS
</Link>{" "}
or Authenticator for{" "}
<Link isHovered href={props.tfaWinAppUrl} target="_blank">
Windows Phone
</Link>{" "}
.
</Trans>
<Trans t={t} i18nKey="SetAppDescription" ns="Confirm">
The two-factor authentication is enabled to provide additional
portal security. Configure your authenticator application to
continue work on the portal. For example you could use Google
Authenticator for
<Link isHovered href={props.tfaAndroidAppUrl} target="_blank">
Android
</Link>
and{" "}
<Link isHovered href={props.tfaIosAppUrl} target="_blank">
iOS
</Link>{" "}
or Authenticator for{" "}
<Link isHovered href={props.tfaWinAppUrl} target="_blank">
Windows Phone
</Link>{" "}
.
</Trans>
<Text className="set-app-text">
<Trans
t={t}
i18nKey="SetAppInstallDescription"
ns="Confirm"
key={secretKey}
>
To connect your apllication scan the QR code or manually enter your
secret key <strong>{{ secretKey }}</strong> then enter 6-digit code
from your application in the field below.
</Trans>
</Text>
</Box>
<FormWrapper>
<Box
displayProp="flex"
flexDirection="column"
className="app-code-wrapper"
>
<div className="qrcode-wrapper">
<img src={qrCode} height="180px" width="180px" alt="QR-code"></img>
</div>
<Box className="app-code-input">
<FieldContainer
labelVisible={false}
hasError={error ? true : false}
errorMessage={error}
<Text className="set-app-text">
<Trans
t={t}
i18nKey="SetAppInstallDescription"
ns="Confirm"
key={secretKey}
>
To connect your apllication scan the QR code or manually enter
your secret key <strong>{{ secretKey }}</strong> then enter
6-digit code from your application in the field below.
</Trans>
</Text>
</Box>
<FormWrapper>
<Box
displayProp="flex"
flexDirection="column"
className="app-code-wrapper"
>
<TextInput
id="code"
name="code"
type="text"
size="large"
scale
isAutoFocussed
tabIndex={1}
placeholder={t("EnterCodePlaceholder")}
isDisabled={isLoading}
maxLength={6}
onChange={(e) => {
setCode(e.target.value);
setError("");
}}
value={code}
hasError={error ? true : false}
onKeyDown={onKeyPress}
/>
</FieldContainer>
</Box>
<Box className="app-code-continue-btn">
<Button
scale
primary
size="medium"
tabIndex={3}
label={
isLoading ? t("Common:LoadingProcessing") : t("SetAppButton")
}
isDisabled={!code.length || isLoading}
isLoading={isLoading}
onClick={onSubmit}
/>
</Box>
</Box>
</FormWrapper>
</StyledForm>
<div className="qrcode-wrapper">
<img
src={qrCode}
height="180px"
width="180px"
alt="QR-code"
></img>
</div>
<Box className="app-code-input">
<FieldContainer
labelVisible={false}
hasError={error ? true : false}
errorMessage={error}
>
<TextInput
id="code"
name="code"
type="text"
size="large"
scale
isAutoFocussed
tabIndex={1}
placeholder={t("EnterCodePlaceholder")}
isDisabled={isLoading}
maxLength={6}
onChange={(e) => {
setCode(e.target.value);
setError("");
}}
value={code}
hasError={error ? true : false}
onKeyDown={onKeyPress}
/>
</FieldContainer>
</Box>
<Box className="app-code-continue-btn">
<Button
scale
primary
size="medium"
tabIndex={3}
label={
isLoading
? t("Common:LoadingProcessing")
: t("SetAppButton")
}
isDisabled={!code.length || isLoading}
isLoading={isLoading}
onClick={onSubmit}
/>
</Box>
</Box>
</FormWrapper>
</StyledForm>
</StyledContent>
</StyledPage>
);
});
@ -264,11 +272,7 @@ const TfaActivationWrapper = (props) => {
return error ? (
<ErrorContainer bodyText={error} />
) : (
<Section>
<Section.SectionBody>
<TfaActivationForm secretKey={secretKey} qrCode={qrCode} {...props} />
</Section.SectionBody>
</Section>
<TfaActivationForm secretKey={secretKey} qrCode={qrCode} {...props} />
);
};

View File

@ -6,46 +6,32 @@ import Button from "@docspace/components/button";
import TextInput from "@docspace/components/text-input";
import FieldContainer from "@docspace/components/field-container";
import Text from "@docspace/components/text";
import Section from "@docspace/common/components/Section";
import { inject, observer } from "mobx-react";
import Box from "@docspace/components/box";
import toastr from "@docspace/components/toast/toastr";
import withLoader from "../withLoader";
import {
hugeMobile,
smallTablet,
tablet,
} from "@docspace/components/utils/device";
import { hugeMobile } from "@docspace/components/utils/device";
import FormWrapper from "@docspace/components/form-wrapper";
import DocspaceLogo from "../../../DocspaceLogo";
import { StyledPage, StyledContent } from "./StyledConfirm";
const StyledForm = styled(Box)`
margin: 63px auto;
width: 320px;
margin: 56px auto;
display: flex;
flex-direction: column;
flex: 1fr;
@media ${tablet} {
margin: 120px auto;
width: 480px;
}
@media ${smallTablet} {
width: 400px;
}
@media ${hugeMobile} {
margin: 32px 8px auto 8px;
padding-left: 8px;
margin: 0 auto;
width: 100%;
}
.docspace-logo {
width: 100%;
display: flex;
align-items: center;
justify-content: center;
padding-bottom: 64px;
padding-bottom: 40px;
}
.app-code-wrapper {
@ -94,66 +80,70 @@ const TfaAuthForm = withLoader((props) => {
};
return (
<StyledForm className="app-code-container">
<DocspaceLogo className="docspace-logo" />
<FormWrapper>
<Box className="app-code-description" marginProp="0 0 32px 0">
<Text isBold fontSize="14px" className="app-code-text">
{t("EnterAppCodeTitle")}
</Text>
<Text>{t("EnterAppCodeDescription")}</Text>
</Box>
<Box
displayProp="flex"
flexDirection="column"
className="app-code-wrapper"
>
<Box className="app-code-input">
<FieldContainer
labelVisible={false}
hasError={error ? true : false}
errorMessage={error}
<StyledPage>
<StyledContent>
<StyledForm className="app-code-container">
<DocspaceLogo className="docspace-logo" />
<FormWrapper>
<Box className="app-code-description" marginProp="0 0 32px 0">
<Text isBold fontSize="14px" className="app-code-text">
{t("EnterAppCodeTitle")}
</Text>
<Text>{t("EnterAppCodeDescription")}</Text>
</Box>
<Box
displayProp="flex"
flexDirection="column"
className="app-code-wrapper"
>
<TextInput
id="code"
name="code"
type="text"
size="huge"
scale
isAutoFocussed
tabIndex={1}
placeholder={t("EnterCodePlaceholder")}
isDisabled={isLoading}
maxLength={6}
onChange={(e) => {
setCode(e.target.value);
setError("");
}}
value={code}
hasError={error ? true : false}
onKeyDown={onKeyPress}
/>
</FieldContainer>
</Box>
<Box className="app-code-continue-btn">
<Button
scale
primary
size="medium"
tabIndex={3}
label={
isLoading
? t("Common:LoadingProcessing")
: t("Common:ContinueButton")
}
isDisabled={!code.length || isLoading}
isLoading={isLoading}
onClick={onSubmit}
/>
</Box>
</Box>
</FormWrapper>
</StyledForm>
<Box className="app-code-input">
<FieldContainer
labelVisible={false}
hasError={error ? true : false}
errorMessage={error}
>
<TextInput
id="code"
name="code"
type="text"
size="huge"
scale
isAutoFocussed
tabIndex={1}
placeholder={t("EnterCodePlaceholder")}
isDisabled={isLoading}
maxLength={6}
onChange={(e) => {
setCode(e.target.value);
setError("");
}}
value={code}
hasError={error ? true : false}
onKeyDown={onKeyPress}
/>
</FieldContainer>
</Box>
<Box className="app-code-continue-btn">
<Button
scale
primary
size="medium"
tabIndex={3}
label={
isLoading
? t("Common:LoadingProcessing")
: t("Common:ContinueButton")
}
isDisabled={!code.length || isLoading}
isLoading={isLoading}
onClick={onSubmit}
/>
</Box>
</Box>
</FormWrapper>
</StyledForm>
</StyledContent>
</StyledPage>
);
});
@ -165,13 +155,7 @@ const TfaAuthFormWrapper = (props) => {
setIsLoading(false);
}, []);
return (
<Section>
<Section.SectionBody>
<TfaAuthForm {...props} />
</Section.SectionBody>
</Section>
);
return <TfaAuthForm {...props} />;
};
export default inject(({ auth, confirm }) => ({

View File

@ -1,10 +1,10 @@
import { request } from "../client";
import axios from "axios";
export function getSettings() {
export function getSettings(withPassword = false) {
return request({
method: "get",
url: "/settings.json",
url: `/settings.json?withPassword=${withPassword}`,
});
}

View File

@ -6,8 +6,9 @@ const LoginContainer = styled.div`
display: flex;
flex-direction: column;
align-items: center;
margin: 56px auto 0 auto;
margin: 56px auto;
max-width: 960px;
z-index: 0;
.remember-wrapper {
max-width: 142px;
@ -236,7 +237,7 @@ const LoginContainer = styled.div`
justify-content: center;
width: 100%;
height: 46px;
padding-bottom: 64px;
padding-bottom: 40px;
svg {
path:last-child {

View File

@ -188,12 +188,12 @@ class SettingsStore {
this.greetingSettings = greetingSettings;
};
getSettings = async () => {
getSettings = async (withPassword) => {
let newSettings = null;
if (window?.__ASC_INITIAL_EDITOR_STATE__?.portalSettings)
newSettings = window.__ASC_INITIAL_EDITOR_STATE__.portalSettings;
else newSettings = await api.settings.getSettings();
else newSettings = await api.settings.getSettings(withPassword);
if (window["AscDesktopEditor"] !== undefined || this.personal) {
const dp = combineUrl(

View File

@ -1,7 +1,7 @@
import React, { useState, useCallback, useEffect } from "react";
import { useTranslation } from "react-i18next";
import { inject, observer } from "mobx-react";
import { ButtonsWrapper, LoginFormWrapper } from "./StyledLogin";
import { ButtonsWrapper, LoginFormWrapper, LoginContent } from "./StyledLogin";
import Text from "@docspace/components/text";
import SocialButton from "@docspace/components/social-button";
import {
@ -210,77 +210,80 @@ const Login: React.FC<ILoginProps> = ({
isDesktop={isDesktopEditor}
bgPattern={bgPattern}
>
<ColorTheme themeId={ThemeType.LinkForgotPassword} theme={theme}>
<img src={logoUrl} className="logo-wrapper" />
<Text
fontSize="23px"
fontWeight={700}
textAlign="center"
className="greeting-title"
>
{greetingSettings}
</Text>
<FormWrapper id="login-form" theme={theme}>
{ssoExists() && <ButtonsWrapper>{ssoButton()}</ButtonsWrapper>}
{oauthDataExists() && (
<>
<ButtonsWrapper>{providerButtons()}</ButtonsWrapper>
{providers && providers.length > 2 && (
<Link
isHovered
type="action"
fontSize="13px"
fontWeight="600"
color="#3B72A7"
className="more-label"
onClick={moreAuthOpen}
>
{t("Common:ShowMore")}
</Link>
)}
</>
)}
{(oauthDataExists() || ssoExists()) && (
<div className="line">
<Text className="or-label">{t("Or")}</Text>
</div>
)}
<LoginForm
isDesktop={!!isDesktopEditor}
isLoading={isLoading}
hashSettings={portalSettings?.passwordHash}
setIsLoading={setIsLoading}
onRecoverDialogVisible={onRecoverDialogVisible}
match={match}
enableAdmMess={enableAdmMess}
<div className="bg-cover"></div>
<LoginContent>
<ColorTheme themeId={ThemeType.LinkForgotPassword} theme={theme}>
<img src={logoUrl} className="logo-wrapper" />
<Text
fontSize="23px"
fontWeight={700}
textAlign="center"
className="greeting-title"
>
{greetingSettings}
</Text>
<FormWrapper id="login-form" theme={theme}>
{ssoExists() && <ButtonsWrapper>{ssoButton()}</ButtonsWrapper>}
{oauthDataExists() && (
<>
<ButtonsWrapper>{providerButtons()}</ButtonsWrapper>
{providers && providers.length > 2 && (
<Link
isHovered
type="action"
fontSize="13px"
fontWeight="600"
color="#3B72A7"
className="more-label"
onClick={moreAuthOpen}
>
{t("Common:ShowMore")}
</Link>
)}
</>
)}
{(oauthDataExists() || ssoExists()) && (
<div className="line">
<Text className="or-label">{t("Or")}</Text>
</div>
)}
<LoginForm
isDesktop={!!isDesktopEditor}
isLoading={isLoading}
hashSettings={portalSettings?.passwordHash}
setIsLoading={setIsLoading}
onRecoverDialogVisible={onRecoverDialogVisible}
match={match}
enableAdmMess={enableAdmMess}
/>
</FormWrapper>
<Toast />
<MoreLoginModal
visible={moreAuthVisible}
onClose={moreAuthClose}
providers={providers}
onSocialLoginClick={onSocialButtonClick}
ssoLabel={ssoLabel}
ssoUrl={ssoUrl}
t={t}
/>
</FormWrapper>
<Toast />
<MoreLoginModal
visible={moreAuthVisible}
onClose={moreAuthClose}
providers={providers}
onSocialLoginClick={onSocialButtonClick}
ssoLabel={ssoLabel}
ssoUrl={ssoUrl}
t={t}
/>
<RecoverAccessModalDialog
visible={recoverDialogVisible}
onClose={onRecoverDialogVisible}
textBody={t("RecoverTextBody")}
emailPlaceholderText={t("RecoverContactEmailPlaceholder")}
id="recover-access-modal"
/>
</ColorTheme>
{!checkIsSSR() && enabledJoin && (
<Register
id="login_register"
enabledJoin={enabledJoin}
currentColorScheme={currentColorScheme}
/>
)}
<RecoverAccessModalDialog
visible={recoverDialogVisible}
onClose={onRecoverDialogVisible}
textBody={t("RecoverTextBody")}
emailPlaceholderText={t("RecoverContactEmailPlaceholder")}
id="recover-access-modal"
/>
</ColorTheme>
{!checkIsSSR() && enabledJoin && (
<Register
id="login_register"
enabledJoin={enabledJoin}
currentColorScheme={currentColorScheme}
/>
)}
</LoginContent>{" "}
</LoginFormWrapper>
);
};

View File

@ -1,5 +1,5 @@
import styled, { css } from "styled-components";
import { tablet } from "@docspace/components/utils/device";
import { tablet, hugeMobile } from "@docspace/components/utils/device";
export const ButtonsWrapper = styled.div`
display: flex;
@ -12,8 +12,6 @@ export const ButtonsWrapper = styled.div`
}
`;
interface ILoginFormWrapperProps {
enabledJoin?: boolean;
isDesktop?: boolean;
@ -29,20 +27,44 @@ export const LoginFormWrapper = styled.div`
: css`1fr 68px`
: css`1fr`};
width: 100%;
height: 100vh;
box-sizing: border-box;
background-image: ${props => props.bgPattern};
background-repeat: no-repeat;
background-attachment: fixed;
background-size: 100% 100%;
@media (max-width: 1024px) {
background-size: cover;
}
@media (max-width: 428px) {
background-image: none;
@media ${hugeMobile} {
height: calc(100vh - 48px);
}
.bg-cover {
background-image: ${props => props.bgPattern};
background-repeat: no-repeat;
background-attachment: fixed;
background-size: cover;
position: fixed;
top: 0;
right: 0;
left: 0;
bottom: 0;
@media ${hugeMobile} {
background-image: none;
}
}
`;
export const LoginContent = styled.div`
min-height: 100vh;
flex: 1 0 auto;
flex-direction: column;
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
@media ${hugeMobile} {
min-height: 100%;
justify-content: start;
}
`;