diff --git a/packages/login-next/package.json b/packages/login-next/package.json index 2cf559a6ca..a79f81b3d9 100644 --- a/packages/login-next/package.json +++ b/packages/login-next/package.json @@ -24,6 +24,7 @@ "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", + "babel-plugin-styled-components": "^2.1.4", "eslint": "^8", "eslint-config-next": "14.0.4", "prettier": "^3.2.4", diff --git a/packages/login-next/src/app/global-error.tsx b/packages/login-next/src/app/global-error.tsx index 135b92dd04..74e8383bde 100644 --- a/packages/login-next/src/app/global-error.tsx +++ b/packages/login-next/src/app/global-error.tsx @@ -30,7 +30,6 @@ import { useCallback, useState, useLayoutEffect, useMemo } from "react"; import { ThemeProvider } from "@docspace/shared/components/theme-provider"; import { Error520SSR } from "@docspace/shared/components/errors/Error520"; -import { getUser } from "@docspace/shared/api/people"; import { getSettings } from "@docspace/shared/api/settings"; import type { TUser } from "@docspace/shared/api/people/types"; import type { @@ -47,15 +46,14 @@ import FirebaseHelper from "@docspace/shared/utils/firebase"; import pkg from "../../package.json"; export default function GlobalError({ error }: { error: Error }) { - const [user, setUser] = useState(); const [settings, setSettings] = useState(); const [isLoading, setIsLoading] = useState(true); const [isError, setError] = useState(false); - const { i18n } = useI18N({ settings, user }); + const { i18n } = useI18N({ settings }); const { currentDeviceType } = useDeviceType(); const { logoUrls } = useWhiteLabel(); - const { theme } = useTheme({ user }); + const { theme } = useTheme({}); const firebaseHelper = useMemo(() => { return new FirebaseHelper(settings?.firebase ?? ({} as TFirebaseSettings)); }, [settings?.firebase]); @@ -63,13 +61,9 @@ export default function GlobalError({ error }: { error: Error }) { const getData = useCallback(async () => { try { setIsLoading(true); - const [userData, settingsData] = await Promise.all([ - getUser(), - getSettings(), - ]); + const settingsData = await getSettings(); setSettings(settingsData); - setUser(userData); } catch (error) { setError(true); console.error(error); @@ -93,7 +87,7 @@ export default function GlobalError({ error }: { error: Error }) { i18nProp={i18n} errorLog={error} version={pkg.version} - user={user ?? ({} as TUser)} + user={{} as TUser} whiteLabelLogoUrls={logoUrls} firebaseHelper={firebaseHelper} currentDeviceType={currentDeviceType} diff --git a/packages/login-next/src/app/layout.tsx b/packages/login-next/src/app/layout.tsx index 39d5dc1c69..98b6772a0b 100644 --- a/packages/login-next/src/app/layout.tsx +++ b/packages/login-next/src/app/layout.tsx @@ -24,21 +24,93 @@ // content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0 // International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode -import "../styles/globals.scss"; +import { cookies } from "next/headers"; +import { redirect } from "next/navigation"; -// import StyledComponentsRegistry from "@/utils/registry"; +import { COOKIE_EXPIRATION_YEAR, LANGUAGE } from "@docspace/shared/constants"; +import { getLanguage } from "@docspace/shared/utils/banner"; + +import StyledComponentsRegistry from "@/utils/registry"; +import { DataContextProvider } from "@/providers/DataProvider"; +import { checkIsAuthenticated, getData, updateCookie } from "@/utils/actions"; +import SimpleNav from "@/components/SimpleNav"; + +import "../styles/globals.scss"; +import { Toast } from "@docspace/shared/components/toast"; export default async function RootLayout({ children, }: { children: React.ReactNode; }) { + const cookieStore = cookies(); + + const isAuth = await checkIsAuthenticated(); + + if (isAuth) redirect("/"); + + const [ + settings, + versionBuild, + colorTheme, + whiteLabel, + thirdPartyProvider, + capabilities, + ssoSettings, + ] = await getData(); + + const ssoUrl = capabilities ? capabilities.ssoUrl : ""; + const hideAuthPage = ssoSettings ? ssoSettings.hideAuthPage : false; + + if (ssoUrl && hideAuthPage) { + redirect(ssoUrl); + } + + if (settings.wizardToken) { + redirect("/wizard"); + } + + let currentLanguage: string = settings.culture ?? "en"; + let standalone: boolean = settings.standalone ? true : false; + + const cookieLang = cookieStore.get(LANGUAGE) as string | undefined; + + if (cookieLang) { + currentLanguage = cookieLang; + } else { + // updateCookie(LANGUAGE, currentLanguage, { + // maxAge: COOKIE_EXPIRATION_YEAR, + // }); + } + + currentLanguage = getLanguage(currentLanguage); + return ( - {children} + + + + + + {children} + + + ); } diff --git a/packages/login-next/src/app/page.tsx b/packages/login-next/src/app/page.tsx index 4c7903e2cd..c6c3167824 100644 --- a/packages/login-next/src/app/page.tsx +++ b/packages/login-next/src/app/page.tsx @@ -24,18 +24,16 @@ // content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0 // International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode -import { redirect } from "next/navigation"; +"use server"; -import { checkIsAuthenticated, getData } from "@/utils/actions"; +import Login from "@/components/Login"; -async function Page({}) { - const isAuth = await checkIsAuthenticated(); - - if (isAuth) redirect("/"); - - getData(); - - return

MAIN

; +async function Page({ + searchParams, +}: { + searchParams: { [key: string]: string }; +}) { + return ; } export default Page; diff --git a/packages/login-next/src/components/GreetingContainer.tsx b/packages/login-next/src/components/GreetingContainer.tsx new file mode 100644 index 0000000000..344eda2689 --- /dev/null +++ b/packages/login-next/src/components/GreetingContainer.tsx @@ -0,0 +1,86 @@ +/* eslint-disable @next/next/no-img-element */ +// (c) Copyright Ascensio System SIA 2009-2024 +// +// This program is a free software product. +// You can redistribute it and/or modify it under the terms +// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software +// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended +// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of +// any third-party rights. +// +// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see +// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html +// +// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021. +// +// The interactive user interfaces in modified source and object code versions of the Program must +// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3. +// +// Pursuant to Section 7(b) of the License you must retain the original Product logo when +// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under +// trademark law for use of our trademarks. +// +// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing +// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0 +// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode + +import React from "react"; +import { Trans, useTranslation } from "react-i18next"; + +import { Text } from "@docspace/shared/components/text"; + +import { GreetingContainersProps } from "@/types"; +import { DEFAULT_PORTAL_TEXT, DEFAULT_ROOM_TEXT } from "@/utils/constants"; + +const GreetingContainer = ({ + roomName, + firstName, + lastName, + greetingSettings, + logoUrl, + type, +}: GreetingContainersProps) => { + const { t } = useTranslation(); + + return ( + <> + greeting-logo + {type !== "invitation" && ( + + {greetingSettings} + + )} + + {type === "invitation" && ( +
+ + , + }} + /> + +
+ )} + + ); +}; + +export default GreetingContainer; diff --git a/packages/login-next/src/components/Login/Login.styled.ts b/packages/login-next/src/components/Login/Login.styled.ts new file mode 100644 index 0000000000..a17b7fe82f --- /dev/null +++ b/packages/login-next/src/components/Login/Login.styled.ts @@ -0,0 +1,143 @@ +// (c) Copyright Ascensio System SIA 2009-2024 +// +// This program is a free software product. +// You can redistribute it and/or modify it under the terms +// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software +// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended +// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of +// any third-party rights. +// +// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see +// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html +// +// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021. +// +// The interactive user interfaces in modified source and object code versions of the Program must +// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3. +// +// Pursuant to Section 7(b) of the License you must retain the original Product logo when +// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under +// trademark law for use of our trademarks. +// +// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing +// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0 +// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode + +import styled, { css } from "styled-components"; + +import { Base } from "@docspace/shared/themes"; +import { mobile, tablet } from "@docspace/shared/utils/device"; + +export const LoginFormWrapper = styled.div<{ bgPattern: string }>` + width: 100%; + height: 100vh; + + box-sizing: border-box; + + @media ${mobile} { + height: calc(100% - 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 ${mobile} { + background-image: none; + } + } + + .greeting-container { + margin-bottom: 40px; + max-width: 380px; + min-width: 380px; + + @media ${tablet} { + max-width: 480px; + min-width: 480px; + } + + @media ${mobile} { + max-width: 100%; + min-width: 100%; + } + p { + text-align: center; + } + } + .invitation-info-container { + margin-bottom: 16px; + .sign-in-container { + display: flex; + align-items: center; + justify-content: center; + position: relative; + + margin-bottom: 16px; + .back-title { + position: absolute; + max-width: 60px; + text-overflow: ellipsis; + overflow: hidden; + + ${(props) => + props.theme.interfaceDirection === "rtl" + ? css` + right: 0; + ` + : css` + left: 0; + `}; + + display: flex; + gap: 4px; + + svg { + ${(props) => + props.theme.interfaceDirection === "rtl" && + " transform: rotate(180deg)"}; + } + + p { + color: ${(props) => props.theme.login.backTitle.color}; + } + + p:hover { + cursor: pointer; + } + } + } + } +`; + +LoginFormWrapper.defaultProps = { theme: Base }; + +export const LoginContent = styled.div` + 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; + height: 100%; + + margin-top: 88px; + + @media ${mobile} { + width: 100%; + justify-content: start; + margin-top: 34px; + } +`; + +LoginContent.defaultProps = { theme: Base }; diff --git a/packages/login-next/src/components/Login/index.tsx b/packages/login-next/src/components/Login/index.tsx new file mode 100644 index 0000000000..c5c7f1ea82 --- /dev/null +++ b/packages/login-next/src/components/Login/index.tsx @@ -0,0 +1,199 @@ +// (c) Copyright Ascensio System SIA 2009-2024 +// +// This program is a free software product. +// You can redistribute it and/or modify it under the terms +// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software +// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended +// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of +// any third-party rights. +// +// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see +// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html +// +// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021. +// +// The interactive user interfaces in modified source and object code versions of the Program must +// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3. +// +// Pursuant to Section 7(b) of the License you must retain the original Product logo when +// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under +// trademark law for use of our trademarks. +// +// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing +// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0 +// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode + +"use client"; + +import { useContext, useState, useCallback } from "react"; +import { useTheme } from "styled-components"; + +import { TenantStatus } from "@docspace/shared/enums"; +import { PROVIDERS_DATA } from "@docspace/shared/constants"; +import { + getBgPattern, + getLoginLink, + getLogoFromPath, + getOAuthToken, +} from "@docspace/shared/utils/common"; +import { checkIsSSR } from "@docspace/shared/utils/device"; +import RecoverAccessModalDialog from "@docspace/shared/components/recover-access-modal-dialog/RecoverAccessModalDialog"; +import { Scrollbar } from "@docspace/shared/components/scrollbar"; +import { ColorTheme, ThemeId } from "@docspace/shared/components/color-theme"; +import { FormWrapper } from "@docspace/shared/components/form-wrapper"; + +import { DataContext } from "@/providers/DataProvider"; +import { LoginProps } from "@/types"; +import useRecoverDialog from "@/hooks/useRecoverDialog"; + +import GreetingContainer from "../GreetingContainer"; + +import { LoginContent, LoginFormWrapper } from "./Login.styled"; + +const Login = ({ searchParams }: LoginProps) => { + const [isLoading, setIsLoading] = useState(false); + + const [invitationLinkData, setInvitationLinkData] = useState({ + email: "", + roomName: "", + firstName: "", + lastName: "", + type: "", + }); + + const theme = useTheme(); + + const { settings, capabilities, thirdPartyProvider, whiteLabel } = + useContext(DataContext); + const { + recoverDialogVisible, + recoverDialogEmailPlaceholder, + recoverDialogTextBody, + openRecoverDialog, + closeRecoverDialog, + } = useRecoverDialog({}); + + const isRestoringPortal = + settings?.tenantStatus === TenantStatus.PortalRestore; + + const ssoExists = () => { + if (capabilities?.ssoUrl) return true; + else return false; + }; + + const oauthDataExists = () => { + if (!capabilities?.oauthEnabled) return false; + + let existProviders = 0; + if (thirdPartyProvider && thirdPartyProvider.length > 0) + thirdPartyProvider?.map((item) => { + if (!(item.provider in PROVIDERS_DATA)) return; + existProviders++; + }); + + return !!existProviders; + }; + + const onSocialButtonClick = useCallback( + async (e: React.MouseEvent) => { + const target = e.target as HTMLElement; + let targetElement = target; + + if ( + !(targetElement instanceof HTMLButtonElement) && + target.parentElement + ) { + targetElement = target.parentElement; + } + const providerName = targetElement.dataset.providername; + let url = targetElement.dataset.url || ""; + + try { + //Lifehack for Twitter + if (providerName == "twitter") { + url += "authCallback"; + } + + const tokenGetterWin = + window["AscDesktopEditor"] !== undefined + ? (window.location.href = url) + : window.open( + url, + "login", + "width=800,height=500,status=no,toolbar=no,menubar=no,resizable=yes,scrollbars=no", + ); + + const code: string = await getOAuthToken(tokenGetterWin); + + const token = window.btoa( + JSON.stringify({ + auth: providerName, + mode: "popup", + callback: "authCallback", + }), + ); + + if (tokenGetterWin && typeof tokenGetterWin !== "string") + tokenGetterWin.location.href = getLoginLink(token, code); + } catch (err) { + console.log(err); + } + }, + [], + ); + + const bgPattern = getBgPattern(theme.currentColorScheme?.id); + const isRegisterContainerVisible = !checkIsSSR() && settings.enabledJoin; + + const logo = whiteLabel && Object.values(whiteLabel)[1]; + const logoUrl = !logo + ? undefined + : !theme?.isBase + ? getLogoFromPath(logo.path.dark) + : getLogoFromPath(logo.path.light); + + return ( + +
+ + + + + asd + + + {isRegisterContainerVisible && ( + + )} + + {recoverDialogVisible && ( + + )} + + ); +}; + +export default Login; diff --git a/packages/login-next/src/components/ModalDialogContainer.tsx b/packages/login-next/src/components/ModalDialogContainer.tsx new file mode 100644 index 0000000000..9b33850ebd --- /dev/null +++ b/packages/login-next/src/components/ModalDialogContainer.tsx @@ -0,0 +1,59 @@ +// (c) Copyright Ascensio System SIA 2009-2024 +// +// This program is a free software product. +// You can redistribute it and/or modify it under the terms +// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software +// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended +// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of +// any third-party rights. +// +// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see +// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html +// +// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021. +// +// The interactive user interfaces in modified source and object code versions of the Program must +// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3. +// +// Pursuant to Section 7(b) of the License you must retain the original Product logo when +// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under +// trademark law for use of our trademarks. +// +// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing +// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0 +// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode + +import styled from "styled-components"; + +import { ModalDialog } from "@docspace/shared/components/modal-dialog"; +import { tablet } from "@docspace/shared/utils"; + +const ModalDialogContainer = styled(ModalDialog)` + .modal-dialog-aside { + padding: 0; + } + + .modal-dialog-aside-body { + padding: 0; + margin: 0; + } + + .modal-dialog-aside-footer { + @media ${tablet} { + width: 90%; + } + } + .modal-dialog-button { + display: inline-block; + } + .field-body { + margin-top: 16px; + } + + .email-reg-field { + margin: 0; + } +`; + +export default ModalDialogContainer; diff --git a/packages/login-next/src/components/Register/Register.styled.ts b/packages/login-next/src/components/Register/Register.styled.ts new file mode 100644 index 0000000000..6f3e570e7e --- /dev/null +++ b/packages/login-next/src/components/Register/Register.styled.ts @@ -0,0 +1,49 @@ +// (c) Copyright Ascensio System SIA 2009-2024 +// +// This program is a free software product. +// You can redistribute it and/or modify it under the terms +// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software +// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended +// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of +// any third-party rights. +// +// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see +// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html +// +// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021. +// +// The interactive user interfaces in modified source and object code versions of the Program must +// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3. +// +// Pursuant to Section 7(b) of the License you must retain the original Product logo when +// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under +// trademark law for use of our trademarks. +// +// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing +// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0 +// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode + +import styled from "styled-components"; + +import { Box } from "@docspace/shared/components/box"; +import { Base } from "@docspace/shared/themes"; + +export const StyledRegister = styled(Box)` + position: absolute; + display: flex; + align-items: center; + justify-content: center; + z-index: 184; + width: 100%; + height: 68px; + padding: 1.5em; + bottom: 0; + + ${({ theme }) => + theme.interfaceDirection === "rtl" ? `left: 0;` : `right: 0;`} + background-color: ${(props) => props.theme.login.register.backgroundColor}; + cursor: pointer; +`; + +StyledRegister.defaultProps = { theme: Base }; diff --git a/packages/login-next/src/components/Register/index.tsx b/packages/login-next/src/components/Register/index.tsx new file mode 100644 index 0000000000..10ae67e5f3 --- /dev/null +++ b/packages/login-next/src/components/Register/index.tsx @@ -0,0 +1,149 @@ +// (c) Copyright Ascensio System SIA 2009-2024 +// +// This program is a free software product. +// You can redistribute it and/or modify it under the terms +// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software +// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended +// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of +// any third-party rights. +// +// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see +// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html +// +// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021. +// +// The interactive user interfaces in modified source and object code versions of the Program must +// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3. +// +// Pursuant to Section 7(b) of the License you must retain the original Product logo when +// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under +// trademark law for use of our trademarks. +// +// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing +// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0 +// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode + +import React, { useState } from "react"; +import { useTranslation } from "react-i18next"; +import { useTheme } from "styled-components"; + +import { Text } from "@docspace/shared/components/text"; +import { toastr } from "@docspace/shared/components/toast"; +import { TValidate } from "@docspace/shared/components/email-input/EmailInput.types"; +import { sendRegisterRequest } from "@docspace/shared/api/settings"; + +import { RegisterProps } from "@/types"; + +import RegisterModalDialog from "./sub-components/RegisterModalDialog"; + +import { StyledRegister } from "./Register.styled"; + +const Register = (props: RegisterProps) => { + const { + enabledJoin, + isAuthenticated, + trustedDomainsType, + trustedDomains, + + id, + } = props; + const [visible, setVisible] = useState(false); + const [loading, setLoading] = useState(false); + + const [email, setEmail] = useState(""); + const [emailErr, setEmailErr] = useState(false); + const [errorText, setErrorText] = useState(""); + const [isShowError, setIsShowError] = useState(false); + + const theme = useTheme(); + + const { t } = useTranslation("Login"); + + const onRegisterClick = () => { + setVisible(true); + }; + + const onRegisterModalClose = () => { + setVisible(false); + setEmail(""); + setEmailErr(false); + }; + + const onChangeEmail = (e: React.ChangeEvent) => { + if (e) { + setEmail(e.currentTarget.value); + setEmailErr(false); + setIsShowError(false); + } + }; + + const onValidateEmail = (res: TValidate) => { + setEmailErr(!res.isValid); + setErrorText(res.errors ? res.errors[0] : ""); + return undefined; + }; + + const onBlurEmail = () => { + setIsShowError(true); + }; + + const onSendRegisterRequest = async () => { + if (!email.trim() || emailErr) { + setEmailErr(true); + setIsShowError(true); + } else { + setLoading(true); + try { + const res = await sendRegisterRequest(email); + setLoading(false); + toastr.success(res as string); + } catch (e) { + setLoading(false); + toastr.error(e as string); + } finally { + onRegisterModalClose(); + } + } + }; + + const onKeyDown = (e: KeyboardEvent) => { + if (e.key === "Enter") { + onSendRegisterRequest(); + e.preventDefault(); + } + }; + + return enabledJoin && !isAuthenticated ? ( + <> + + + {t("Register")} + + + + {visible && ( + + )} + + ) : ( + <> + ); +}; + +export default Register; diff --git a/packages/login-next/src/components/Register/sub-components/RegisterModalDialog.tsx b/packages/login-next/src/components/Register/sub-components/RegisterModalDialog.tsx new file mode 100644 index 0000000000..c16e60067f --- /dev/null +++ b/packages/login-next/src/components/Register/sub-components/RegisterModalDialog.tsx @@ -0,0 +1,173 @@ +// (c) Copyright Ascensio System SIA 2009-2024 +// +// This program is a free software product. +// You can redistribute it and/or modify it under the terms +// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software +// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended +// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of +// any third-party rights. +// +// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see +// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html +// +// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021. +// +// The interactive user interfaces in modified source and object code versions of the Program must +// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3. +// +// Pursuant to Section 7(b) of the License you must retain the original Product logo when +// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under +// trademark law for use of our trademarks. +// +// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing +// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0 +// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode + +import React from "react"; +import { useTranslation } from "react-i18next"; + +import { Button, ButtonSize } from "@docspace/shared/components/button"; +import { EmailInput } from "@docspace/shared/components/email-input"; +import { Text } from "@docspace/shared/components/text"; +import { + ModalDialog, + ModalDialogType, +} from "@docspace/shared/components/modal-dialog"; +import { FieldContainer } from "@docspace/shared/components/field-container"; + +import { TenantTrustedDomainsType } from "@docspace/shared/enums"; + +import ModalDialogContainer from "../../ModalDialogContainer"; +import { RegisterModalDialogProps } from "@/types"; +import { InputSize, InputType } from "@docspace/shared/components/text-input"; + +const RegisterModalDialog = ({ + visible, + loading, + email, + emailErr, + onChangeEmail, + onValidateEmail, + onBlurEmail, + onRegisterModalClose, + onSendRegisterRequest, + onKeyDown, + trustedDomainsType, + trustedDomains, + errorText, + isShowError, +}: RegisterModalDialogProps) => { + const { t } = useTranslation(["Login", "Common"]); + + React.useEffect(() => { + window.addEventListener("keydown", onKeyDown); + return () => { + window.removeEventListener("keydown", onKeyDown); + }; + }, [onKeyDown]); + + const getDomains = () => { + if (trustedDomains) + return trustedDomains.map((domain, i) => ( + + + {domain} + {i === trustedDomains.length - 1 ? "." : ", "} + + + )); + }; + + const getDomainsBlock = () => { + return trustedDomainsType === TenantTrustedDomainsType.Custom ? ( + <> + {t("RegisterTextBodyBeforeDomainsList")} {getDomains()}{" "} + + ) : ( + <> + ); + }; + + return ( + + + + {t("RegisterTitle")} + + + + + {getDomainsBlock()} + {t("RegisterTextBodyAfterDomainsList")} + + + + + + + +