import React, { useCallback, useEffect, useState } from "react"; import styled, { css } from "styled-components"; import PropTypes from "prop-types"; import { withRouter } from "react-router"; import Box from "@appserver/components/box"; import Button from "@appserver/components/button"; import Text from "@appserver/components/text"; import TextInput from "@appserver/components/text-input"; import Link from "@appserver/components/link"; import Checkbox from "@appserver/components/checkbox"; import Toast from "@appserver/components/toast"; import HelpButton from "@appserver/components/help-button"; import PasswordInput from "@appserver/components/password-input"; import FieldContainer from "@appserver/components/field-container"; import SocialButton from "@appserver/components/social-button"; import FacebookButton from "@appserver/components/facebook-button"; import PageLayout from "@appserver/common/components/PageLayout"; import ForgotPasswordModalDialog from "./sub-components/forgot-password-modal-dialog"; import Register from "./sub-components/register-container"; import { getAuthProviders } from "@appserver/common/api/settings"; import { checkPwd } from "@appserver/common/desktop"; import { createPasswordHash, getProviderTranslation, } from "@appserver/common/utils"; import { providersData } from "@appserver/common/constants"; import { inject, observer } from "mobx-react"; import i18n from "./i18n"; import { I18nextProvider, useTranslation, withTranslation, } from "react-i18next"; import toastr from "@appserver/components/toast/toastr"; const ButtonsWrapper = styled.div` display: table; margin: auto; `; const LoginContainer = styled.div` display: flex; flex-direction: column; align-items: center; margin: 120px auto 0 auto; max-width: 960px; .login-tooltip { padding-left: 4px; display: inline-block; } .buttonWrapper { margin: 6px; min-width: 225px; } .line { height: 1px; background-color: #eceef1; flex-basis: 100%; margin: 0 8px; } @media (max-width: 768px) { padding: 0 16px; max-width: 475px; } @media (max-width: 375px) { margin: 72px auto 0 auto; max-width: 311px; } .greeting-title { width: 100%; @media (max-width: 768px) { text-align: left; } @media (max-width: 375px) { font-size: 23px; } } .auth-form-container { margin: 32px 213px 0 213px; width: 311px; @media (max-width: 768px) { margin: 32px 0 0 0; width: 100%; } @media (max-width: 375px) { margin: 32px 0 0 0; width: 100%; } .login-forgot-wrapper { height: 36px; padding: 14px 0; .login-checkbox-wrapper { display: flex; .login-checkbox { float: left; span { font-size: 12px; } } } .login-link { line-height: 18px; margin-left: auto; } } .login-button { margin-bottom: 16px; } .login-button-dialog { margin-right: 8px; } .login-bottom-border { width: 100%; height: 1px; background: #eceef1; } .login-bottom-text { margin: 0 8px; } } `; const LoginFormWrapper = styled.div` display: grid; grid-template-rows: ${(props) => props.enabledJoin ? props.isDesktop ? css`1fr 10px` : css`1fr 66px` : css`1fr`}; width: 100%; height: calc(100vh-48px); `; const settings = { minLength: 6, upperCase: false, digits: false, specSymbols: false, }; const Form = (props) => { const inputRef = React.useRef(null); const [identifierValid, setIdentifierValid] = useState(true); const [identifier, setIdentifier] = useState(""); const [isLoading, setIsLoading] = useState(false); const [isDisabled, setIsDisabled] = useState(false); const [passwordValid, setPasswordValid] = useState(true); const [password, setPassword] = useState(""); const [isChecked, setIsChecked] = useState(false); const [isDialogVisible, setIsDialogVisible] = useState(false); const [errorText, setErrorText] = useState(""); const { t } = useTranslation("Login"); const { login, hashSettings, isDesktop, match, organizationName, greetingTitle, history, thirdPartyLogin, providers, } = props; const { error, confirmedEmail } = match.params; const oAuthLogin = async (profile) => { try { await thirdPartyLogin(profile); const redirectPath = localStorage.getItem("redirectPath"); if (redirectPath) { localStorage.removeItem("redirectPath"); window.location.href = redirectPath; } } catch (e) { toastr.error( t("Common:ProviderNotConnected"), t("Common:ProviderLoginError") ); } localStorage.removeItem("profile"); localStorage.removeItem("code"); }; useEffect(() => { const profile = localStorage.getItem("profile"); if (!profile) return; oAuthLogin(profile); }, []); const onKeyDown = (e) => { //console.log("onKeyDown", e.key); if (e.key === "Enter") { onClearErrors(e); !isDisabled && onSubmit(e); e.preventDefault(); } }; const onClearErrors = (e) => { //console.log("onClearErrors", e); !identifierValid && setIdentifierValid(true); !passwordValid && setPasswordValid(true); errorText && setErrorText(""); }; //const throttledKeyPress = throttle(onKeyPress, 500); const authCallback = (profile) => { oAuthLogin(profile); }; const setProviders = async () => { const { setProviders } = props; try { await getAuthProviders().then((providers) => { setProviders(providers); }); } catch (e) { console.error(e); } }; useEffect(async () => { document.title = `${t("Authorization")} – ${organizationName}`; //TODO: implement the setDocumentTitle() utility in ASC.Web.Common error && setErrorText(error); confirmedEmail && setIdentifier(confirmedEmail); focusInput(); window.authCallback = authCallback; await setProviders(); //window.addEventListener("keyup", throttledKeyPress, false); /*return () => { window.removeEventListener("keyup", throttledKeyPress, false); };*/ }, []); const focusInput = () => { if (inputRef) { inputRef.current.focus(); } }; const onChangeLogin = (e) => { //console.log("onChangeLogin", e.target.value); setIdentifier(e.target.value); onClearErrors(e); }; const onChangePassword = (e) => { //console.log("onChangePassword", e.target.value); setPassword(e.target.value); onClearErrors(e); }; const onChangeCheckbox = () => setIsChecked(!isChecked); const onClick = () => { setIsDialogVisible(true); setIsDisabled(true); }; const onDialogClose = () => { setIsDialogVisible(false); setIsDisabled(false); setIsLoading(false); }; const onSubmit = () => { errorText && setErrorText(""); let hasError = false; const userName = identifier.trim(); if (!userName) { hasError = true; setIdentifierValid(false); } const pass = password.trim(); if (!pass) { hasError = true; setPasswordValid(false); } if (hasError) return false; setIsLoading(true); const hash = createPasswordHash(pass, hashSettings); isDesktop && checkPwd(); const session = !isChecked; login(userName, hash, session) .then((res) => { const { url, user, hash } = res; const redirectPath = localStorage.getItem("redirectPath"); if (redirectPath) { localStorage.removeItem("redirectPath"); window.location.href = redirectPath; } else history.push(url, { user, hash }); }) .catch((error) => { setErrorText(error); setIdentifierValid(!error); setPasswordValid(!error); setIsLoading(false); focusInput(); }); }; const onSocialButtonClick = useCallback((e) => { const providerName = e.target.dataset.providername; const url = e.target.dataset.url; const { getOAuthToken, getLoginLink } = props; try { const tokenGetterWin = isDesktop ? (window.location.href = url) : window.open( url, "login", "width=800,height=500,status=no,toolbar=no,menubar=no,resizable=yes,scrollbars=no" ); getOAuthToken(tokenGetterWin).then((code) => { const token = window.btoa( JSON.stringify({ auth: providerName, mode: "popup", callback: "authCallback", }) ); tokenGetterWin.location.href = getLoginLink(token, code); }); } catch (err) { console.log(err); } }, []); const addFacebookToStart = (facebookIndex, providerButtons) => { const faceBookData = providers[facebookIndex]; const { icon, label, iconOptions } = providersData[faceBookData.provider]; providerButtons.unshift(
); }; const providerButtons = () => { let facebookIndex = null; const providerButtons = providers && providers.map((item, index) => { if (!providersData[item.provider]) return; const { icon, label, iconOptions, className } = providersData[ item.provider ]; if (item.provider === "facebook") { facebookIndex = index; return; } return (
); }); if (facebookIndex) addFacebookToStart(facebookIndex, providerButtons); return providerButtons; }; const oauthDataExists = () => { let existProviders = 0; providers && providers.length > 0; providers.map((item) => { if (!providersData[item.provider]) return; existProviders++; }); return !!existProviders; }; //console.log("Login render"); return ( {greetingTitle}
{t("Remember")}} /> {t("RememberHelper")} } /> {t("ForgotPassword")}
{isDialogVisible && ( )}