Login(nextjs): add some components
This commit is contained in:
parent
7c550614fd
commit
42ce320369
@ -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",
|
||||
|
@ -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<TUser>();
|
||||
const [settings, setSettings] = useState<TSettings>();
|
||||
const [isLoading, setIsLoading] = useState<boolean>(true);
|
||||
const [isError, setError] = useState<boolean>(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}
|
||||
|
@ -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 (
|
||||
<html lang="en">
|
||||
<head>
|
||||
<link id="favicon" rel="shortcut icon" type="image/x-icon" />
|
||||
</head>
|
||||
<body>{children}</body>
|
||||
<body>
|
||||
<StyledComponentsRegistry>
|
||||
<DataContextProvider
|
||||
value={{
|
||||
settings,
|
||||
versionBuild,
|
||||
colorTheme,
|
||||
whiteLabel,
|
||||
thirdPartyProvider,
|
||||
capabilities,
|
||||
ssoSettings,
|
||||
currentLanguage,
|
||||
standalone,
|
||||
}}
|
||||
>
|
||||
<SimpleNav logoUrls={whiteLabel} />
|
||||
<Toast isSSR />
|
||||
{children}
|
||||
</DataContextProvider>
|
||||
</StyledComponentsRegistry>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
|
@ -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 <p>MAIN</p>;
|
||||
async function Page({
|
||||
searchParams,
|
||||
}: {
|
||||
searchParams: { [key: string]: string };
|
||||
}) {
|
||||
return <Login searchParams={searchParams} />;
|
||||
}
|
||||
|
||||
export default Page;
|
||||
|
86
packages/login-next/src/components/GreetingContainer.tsx
Normal file
86
packages/login-next/src/components/GreetingContainer.tsx
Normal file
@ -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 (
|
||||
<>
|
||||
<img src={logoUrl} className="logo-wrapper" alt="greeting-logo" />
|
||||
{type !== "invitation" && (
|
||||
<Text
|
||||
fontSize="23px"
|
||||
fontWeight={700}
|
||||
textAlign="center"
|
||||
className="greeting-title"
|
||||
>
|
||||
{greetingSettings}
|
||||
</Text>
|
||||
)}
|
||||
|
||||
{type === "invitation" && (
|
||||
<div className="greeting-container">
|
||||
<Text fontSize="16px">
|
||||
<Trans
|
||||
t={t}
|
||||
i18nKey={roomName ? "InvitationToRoom" : "InvitationToPortal"}
|
||||
ns="Common"
|
||||
defaults={roomName ? DEFAULT_ROOM_TEXT : DEFAULT_PORTAL_TEXT}
|
||||
values={{
|
||||
firstName,
|
||||
lastName,
|
||||
...(roomName
|
||||
? { roomName }
|
||||
: { spaceAddress: window.location.host }),
|
||||
}}
|
||||
components={{
|
||||
1: <Text fontWeight={600} as="strong" fontSize="16px" />,
|
||||
}}
|
||||
/>
|
||||
</Text>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default GreetingContainer;
|
143
packages/login-next/src/components/Login/Login.styled.ts
Normal file
143
packages/login-next/src/components/Login/Login.styled.ts
Normal file
@ -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 };
|
199
packages/login-next/src/components/Login/index.tsx
Normal file
199
packages/login-next/src/components/Login/index.tsx
Normal file
@ -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<HTMLButtonElement | HTMLElement>) => {
|
||||
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 (
|
||||
<LoginFormWrapper id="login-page" bgPattern={bgPattern}>
|
||||
<div className="bg-cover" />
|
||||
<Scrollbar id="customScrollBar">
|
||||
<LoginContent>
|
||||
<ColorTheme
|
||||
themeId={ThemeId.LinkForgotPassword}
|
||||
isRegisterContainerVisible={isRegisterContainerVisible}
|
||||
>
|
||||
<GreetingContainer
|
||||
roomName={invitationLinkData.roomName}
|
||||
firstName={invitationLinkData.firstName}
|
||||
lastName={invitationLinkData.lastName}
|
||||
logoUrl={logoUrl}
|
||||
greetingSettings={settings.greetingSettings}
|
||||
type={invitationLinkData.type}
|
||||
/>
|
||||
<FormWrapper id="login-form">asd</FormWrapper>
|
||||
</ColorTheme>
|
||||
</LoginContent>
|
||||
{isRegisterContainerVisible && (
|
||||
<Register
|
||||
id="login_register"
|
||||
enabledJoin={enabledJoin}
|
||||
currentColorScheme={currentColorScheme}
|
||||
trustedDomains={portalSettings?.trustedDomains}
|
||||
trustedDomainsType={portalSettings?.trustedDomainsType}
|
||||
/>
|
||||
)}
|
||||
</Scrollbar>
|
||||
{recoverDialogVisible && (
|
||||
<RecoverAccessModalDialog
|
||||
visible={recoverDialogVisible}
|
||||
onClose={closeRecoverDialog}
|
||||
textBody={recoverDialogTextBody}
|
||||
emailPlaceholderText={recoverDialogEmailPlaceholder}
|
||||
id="recover-access-modal"
|
||||
/>
|
||||
)}
|
||||
</LoginFormWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export default Login;
|
59
packages/login-next/src/components/ModalDialogContainer.tsx
Normal file
59
packages/login-next/src/components/ModalDialogContainer.tsx
Normal file
@ -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;
|
@ -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 };
|
149
packages/login-next/src/components/Register/index.tsx
Normal file
149
packages/login-next/src/components/Register/index.tsx
Normal file
@ -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<HTMLInputElement>) => {
|
||||
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 ? (
|
||||
<>
|
||||
<StyledRegister id={id} onClick={onRegisterClick}>
|
||||
<Text as="span" color={theme.currentColorScheme?.main?.accent}>
|
||||
{t("Register")}
|
||||
</Text>
|
||||
</StyledRegister>
|
||||
|
||||
{visible && (
|
||||
<RegisterModalDialog
|
||||
visible={visible}
|
||||
loading={loading}
|
||||
email={email}
|
||||
emailErr={emailErr}
|
||||
trustedDomainsType={trustedDomainsType}
|
||||
trustedDomains={trustedDomains}
|
||||
onChangeEmail={onChangeEmail}
|
||||
onValidateEmail={onValidateEmail}
|
||||
onBlurEmail={onBlurEmail}
|
||||
onRegisterModalClose={onRegisterModalClose}
|
||||
onSendRegisterRequest={onSendRegisterRequest}
|
||||
onKeyDown={onKeyDown}
|
||||
errorText={errorText}
|
||||
isShowError={isShowError}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<></>
|
||||
);
|
||||
};
|
||||
|
||||
export default Register;
|
@ -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) => (
|
||||
<span key={i}>
|
||||
<b>
|
||||
{domain}
|
||||
{i === trustedDomains.length - 1 ? "." : ", "}
|
||||
</b>
|
||||
</span>
|
||||
));
|
||||
};
|
||||
|
||||
const getDomainsBlock = () => {
|
||||
return trustedDomainsType === TenantTrustedDomainsType.Custom ? (
|
||||
<>
|
||||
{t("RegisterTextBodyBeforeDomainsList")} {getDomains()}{" "}
|
||||
</>
|
||||
) : (
|
||||
<></>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<ModalDialogContainer
|
||||
id="registration-modal"
|
||||
displayType={ModalDialogType.modal}
|
||||
visible={visible}
|
||||
onClose={onRegisterModalClose}
|
||||
isLarge
|
||||
>
|
||||
<ModalDialog.Header>
|
||||
<Text isBold fontSize="21px">
|
||||
{t("RegisterTitle")}
|
||||
</Text>
|
||||
</ModalDialog.Header>
|
||||
<ModalDialog.Body>
|
||||
<Text key="text-body" isBold={false} fontSize="13px" noSelect>
|
||||
{getDomainsBlock()}
|
||||
{t("RegisterTextBodyAfterDomainsList")}
|
||||
</Text>
|
||||
|
||||
<FieldContainer
|
||||
className="email-reg-field"
|
||||
key="e-mail"
|
||||
isVertical
|
||||
hasError={isShowError && emailErr}
|
||||
labelVisible={false}
|
||||
errorMessage={
|
||||
errorText ? t(`Common:${errorText}`) : t("Common:RequiredField")
|
||||
}
|
||||
>
|
||||
<EmailInput
|
||||
hasError={isShowError && emailErr}
|
||||
placeholder={t("Common:RegistrationEmail")}
|
||||
isAutoFocussed
|
||||
id="registration-modal_email"
|
||||
name="e-mail"
|
||||
type={InputType.email}
|
||||
size={InputSize.base}
|
||||
scale
|
||||
tabIndex={1}
|
||||
isDisabled={loading}
|
||||
value={email}
|
||||
onChange={onChangeEmail}
|
||||
onValidateInput={onValidateEmail}
|
||||
onBlur={onBlurEmail}
|
||||
autoComplete="username"
|
||||
/>
|
||||
</FieldContainer>
|
||||
</ModalDialog.Body>
|
||||
<ModalDialog.Footer>
|
||||
<Button
|
||||
id="registration-modal_send"
|
||||
className="modal-dialog-button"
|
||||
key="RegisterSendBtn"
|
||||
label={loading ? t("Common:Sending") : t("Common:SendRequest")}
|
||||
size={ButtonSize.normal}
|
||||
scale={false}
|
||||
primary
|
||||
onClick={onSendRegisterRequest}
|
||||
isLoading={loading}
|
||||
isDisabled={loading}
|
||||
tabIndex={3}
|
||||
/>
|
||||
|
||||
<Button
|
||||
id="registration-modal_cancel"
|
||||
className="modal-dialog-button"
|
||||
key="CancelBtn"
|
||||
label={t("Common:CancelButton")}
|
||||
size={ButtonSize.normal}
|
||||
scale={false}
|
||||
primary={false}
|
||||
onClick={onRegisterModalClose}
|
||||
isLoading={loading}
|
||||
isDisabled={loading}
|
||||
tabIndex={2}
|
||||
/>
|
||||
</ModalDialog.Footer>
|
||||
</ModalDialogContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default RegisterModalDialog;
|
81
packages/login-next/src/components/SimpleNav.tsx
Normal file
81
packages/login-next/src/components/SimpleNav.tsx
Normal file
@ -0,0 +1,81 @@
|
||||
/* 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
|
||||
|
||||
"use client";
|
||||
|
||||
import React, { useContext } from "react";
|
||||
import styled from "styled-components";
|
||||
|
||||
import { mobile } from "@docspace/shared/utils/device";
|
||||
import { getLogoFromPath, getSystemTheme } from "@docspace/shared/utils/common";
|
||||
import { Base, Dark } from "@docspace/shared/themes";
|
||||
import { TWhiteLabel } from "@docspace/shared/utils/whiteLabelHelper";
|
||||
import { ThemeKeys } from "@docspace/shared/enums";
|
||||
import { DataContext } from "@/providers/DataProvider";
|
||||
|
||||
const StyledSimpleNav = styled.div`
|
||||
display: none;
|
||||
height: 48px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: ${(props) => props.theme?.login?.navBackground};
|
||||
|
||||
svg {
|
||||
path:last-child {
|
||||
fill: ${(props) => props.theme.client?.home?.logoColor};
|
||||
}
|
||||
}
|
||||
@media ${mobile} {
|
||||
display: flex;
|
||||
}
|
||||
`;
|
||||
|
||||
StyledSimpleNav.defaultProps = { theme: Base };
|
||||
|
||||
interface SimpleNavProps {
|
||||
logoUrls: TWhiteLabel[];
|
||||
}
|
||||
|
||||
const SimpleNav = ({ logoUrls }: SimpleNavProps) => {
|
||||
const { theme } = useContext(DataContext);
|
||||
|
||||
const logo = logoUrls && Object.values(logoUrls)[0];
|
||||
|
||||
const logoUrl = !logo
|
||||
? undefined
|
||||
: ThemeKeys.BaseStr !== theme
|
||||
? getLogoFromPath(logo.path.dark)
|
||||
: getLogoFromPath(logo.path.light);
|
||||
|
||||
return (
|
||||
<StyledSimpleNav id="login-header">
|
||||
<img src={logoUrl} alt="logo-url" />
|
||||
</StyledSimpleNav>
|
||||
);
|
||||
};
|
||||
|
||||
export default SimpleNav;
|
@ -27,17 +27,17 @@
|
||||
import React from "react";
|
||||
import { i18n } from "i18next";
|
||||
import { TSettings } from "@docspace/shared/api/settings/types";
|
||||
import { TUser } from "@docspace/shared/api/people/types";
|
||||
|
||||
import { getI18NInstance } from "@/utils/i18n";
|
||||
|
||||
interface UseI18NProps {
|
||||
settings?: TSettings;
|
||||
user?: TUser;
|
||||
}
|
||||
|
||||
const useI18N = ({ settings, user }: UseI18NProps) => {
|
||||
const [i18n, setI18N] = React.useState<i18n>({} as i18n);
|
||||
const useI18N = ({ settings }: UseI18NProps) => {
|
||||
const [i18n, setI18N] = React.useState<i18n>(
|
||||
getI18NInstance(settings?.culture ?? "en") ?? ({} as i18n),
|
||||
);
|
||||
|
||||
const isInit = React.useRef(false);
|
||||
|
||||
@ -52,7 +52,7 @@ const useI18N = ({ settings, user }: UseI18NProps) => {
|
||||
const instance = getI18NInstance(settings?.culture ?? "en");
|
||||
|
||||
if (instance) setI18N(instance);
|
||||
}, [settings?.culture, user?.cultureName]);
|
||||
}, [settings?.culture]);
|
||||
|
||||
return { i18n };
|
||||
};
|
||||
|
58
packages/login-next/src/hooks/useRecoverDialog.ts
Normal file
58
packages/login-next/src/hooks/useRecoverDialog.ts
Normal file
@ -0,0 +1,58 @@
|
||||
// (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 { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
const useRecoverDialog = ({}) => {
|
||||
const [recoverDialogVisible, setRecoverDialogVisible] = useState(false);
|
||||
|
||||
const { t } = useTranslation(["Login"]);
|
||||
|
||||
const openRecoverDialog = () => {
|
||||
setRecoverDialogVisible(true);
|
||||
};
|
||||
|
||||
const closeRecoverDialog = () => {
|
||||
setRecoverDialogVisible(false);
|
||||
};
|
||||
|
||||
const recoverDialogEmailPlaceholder = t(
|
||||
"Login:RecoverContactEmailPlaceholder",
|
||||
);
|
||||
|
||||
const recoverDialogTextBody = t("Login:RecoverTextBody");
|
||||
|
||||
return {
|
||||
recoverDialogVisible,
|
||||
recoverDialogEmailPlaceholder,
|
||||
recoverDialogTextBody,
|
||||
openRecoverDialog,
|
||||
closeRecoverDialog,
|
||||
};
|
||||
};
|
||||
|
||||
export default useRecoverDialog;
|
@ -30,15 +30,15 @@ import { Base, Dark, TColorScheme, TTheme } from "@docspace/shared/themes";
|
||||
import { getSystemTheme } from "@docspace/shared/utils";
|
||||
import { ThemeKeys } from "@docspace/shared/enums";
|
||||
import { getAppearanceTheme } from "@docspace/shared/api/settings";
|
||||
import { TUser } from "@docspace/shared/api/people/types";
|
||||
import { TGetColorTheme } from "@docspace/shared/api/settings/types";
|
||||
|
||||
const SYSTEM_THEME = getSystemTheme();
|
||||
|
||||
export interface UseThemeProps {
|
||||
user?: TUser;
|
||||
colorTheme?: TGetColorTheme;
|
||||
}
|
||||
|
||||
const useTheme = ({ user }: UseThemeProps) => {
|
||||
const useTheme = ({ colorTheme }: UseThemeProps) => {
|
||||
const [currentColorTheme, setCurrentColorTheme] =
|
||||
React.useState<TColorScheme>({} as TColorScheme);
|
||||
|
||||
@ -52,23 +52,18 @@ const useTheme = ({ user }: UseThemeProps) => {
|
||||
const getCurrentColorTheme = React.useCallback(async () => {
|
||||
if (isRequestRunning.current) return;
|
||||
isRequestRunning.current = true;
|
||||
const colorThemes = await getAppearanceTheme();
|
||||
const colorThemes = colorTheme ? colorTheme : await getAppearanceTheme();
|
||||
|
||||
const colorTheme = colorThemes.themes.find(
|
||||
const currColorTheme = colorThemes.themes.find(
|
||||
(t) => t.id === colorThemes.selected,
|
||||
);
|
||||
|
||||
isRequestRunning.current = false;
|
||||
if (colorTheme) setCurrentColorTheme(colorTheme);
|
||||
}, []);
|
||||
if (currColorTheme) setCurrentColorTheme(currColorTheme);
|
||||
}, [colorTheme]);
|
||||
|
||||
const getUserTheme = React.useCallback(() => {
|
||||
if (!user?.theme) return;
|
||||
let theme = user.theme;
|
||||
|
||||
if (user.theme === ThemeKeys.SystemStr) theme = SYSTEM_THEME;
|
||||
|
||||
if (theme === ThemeKeys.BaseStr) {
|
||||
if (SYSTEM_THEME === ThemeKeys.BaseStr) {
|
||||
setTheme({
|
||||
...Base,
|
||||
currentColorScheme: currentColorTheme,
|
||||
@ -83,7 +78,7 @@ const useTheme = ({ user }: UseThemeProps) => {
|
||||
currentColorScheme: currentColorTheme,
|
||||
interfaceDirection: "ltr",
|
||||
});
|
||||
}, [currentColorTheme, user?.theme]);
|
||||
}, [currentColorTheme]);
|
||||
|
||||
React.useEffect(() => {
|
||||
getCurrentColorTheme();
|
||||
|
66
packages/login-next/src/providers/DataProvider.tsx
Normal file
66
packages/login-next/src/providers/DataProvider.tsx
Normal file
@ -0,0 +1,66 @@
|
||||
// (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 React from "react";
|
||||
|
||||
import { createContext } from "react";
|
||||
import { I18nextProvider } from "react-i18next";
|
||||
import { i18n } from "i18next";
|
||||
|
||||
import { getSystemTheme } from "@docspace/shared/utils";
|
||||
import { ThemeProvider } from "@docspace/shared/components/theme-provider";
|
||||
import { Base, Dark } from "@docspace/shared/themes";
|
||||
import { ThemeKeys } from "@docspace/shared/enums";
|
||||
|
||||
import { TDataContext } from "@/types";
|
||||
import { getI18NInstance } from "@/utils/i18n";
|
||||
import useI18N from "@/hooks/useI18N";
|
||||
import useTheme from "@/hooks/useTheme";
|
||||
|
||||
export const DataContext = createContext<TDataContext>({} as TDataContext);
|
||||
|
||||
export const DataContextProvider = ({
|
||||
children,
|
||||
value,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
value: TDataContext;
|
||||
}) => {
|
||||
const { i18n } = useI18N({ settings: value.settings });
|
||||
|
||||
const { theme } = useTheme({ colorTheme: value.colorTheme });
|
||||
|
||||
return (
|
||||
<ThemeProvider theme={theme}>
|
||||
<I18nextProvider i18n={i18n}>
|
||||
<DataContext.Provider value={{ ...value, i18n }}>
|
||||
{children}
|
||||
</DataContext.Provider>
|
||||
</I18nextProvider>
|
||||
</ThemeProvider>
|
||||
);
|
||||
};
|
@ -41,6 +41,8 @@ body {
|
||||
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#root {
|
||||
@ -56,4 +58,3 @@ body {
|
||||
body.loading * {
|
||||
cursor: wait !important;
|
||||
}
|
||||
|
||||
|
@ -23,3 +23,69 @@
|
||||
// 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 { i18n } from "i18next";
|
||||
|
||||
import {
|
||||
TCapabilities,
|
||||
TGetColorTheme,
|
||||
TGetSsoSettings,
|
||||
TSettings,
|
||||
TThirdPartyProvider,
|
||||
TVersionBuild,
|
||||
} from "@docspace/shared/api/settings/types";
|
||||
import { TWhiteLabel } from "@docspace/shared/utils/whiteLabelHelper";
|
||||
import { TValidate } from "@docspace/shared/components/email-input/EmailInput.types";
|
||||
|
||||
export type TDataContext = {
|
||||
settings: TSettings;
|
||||
versionBuild: TVersionBuild;
|
||||
colorTheme: TGetColorTheme;
|
||||
whiteLabel: TWhiteLabel[];
|
||||
thirdPartyProvider: TThirdPartyProvider[] | undefined;
|
||||
capabilities: TCapabilities | undefined;
|
||||
ssoSettings: TGetSsoSettings | undefined;
|
||||
|
||||
currentLanguage: string;
|
||||
standalone: boolean;
|
||||
i18n?: i18n;
|
||||
};
|
||||
|
||||
export type GreetingContainersProps = {
|
||||
roomName?: string;
|
||||
firstName?: string;
|
||||
lastName?: string;
|
||||
greetingSettings?: string;
|
||||
logoUrl: string;
|
||||
type: string;
|
||||
};
|
||||
|
||||
export type LoginProps = {
|
||||
searchParams: { [key: string]: string };
|
||||
};
|
||||
|
||||
export type RegisterProps = {
|
||||
language?: string;
|
||||
isAuthenticated?: boolean;
|
||||
enabledJoin: boolean;
|
||||
trustedDomainsType?: number;
|
||||
trustedDomains?: string[];
|
||||
id?: string;
|
||||
};
|
||||
|
||||
export type RegisterModalDialogProps = {
|
||||
visible: boolean;
|
||||
loading: boolean;
|
||||
email?: string;
|
||||
emailErr: boolean;
|
||||
onChangeEmail: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
||||
onValidateEmail: (res: TValidate) => undefined;
|
||||
onBlurEmail: () => void;
|
||||
onSendRegisterRequest: () => void;
|
||||
onKeyDown: (e: KeyboardEvent) => void;
|
||||
onRegisterModalClose: () => void;
|
||||
trustedDomainsType?: number;
|
||||
trustedDomains?: string[];
|
||||
errorText?: string;
|
||||
isShowError?: boolean;
|
||||
};
|
||||
|
@ -26,11 +26,12 @@
|
||||
|
||||
"use server";
|
||||
|
||||
import { headers } from "next/headers";
|
||||
import { headers, cookies } from "next/headers";
|
||||
|
||||
import {
|
||||
TCapabilities,
|
||||
TGetColorTheme,
|
||||
TGetSsoSettings,
|
||||
TSettings,
|
||||
TThirdPartyProvider,
|
||||
TVersionBuild,
|
||||
@ -132,6 +133,14 @@ export const getData = async () => {
|
||||
TWhiteLabel[],
|
||||
TThirdPartyProvider[] | undefined,
|
||||
TCapabilities | undefined,
|
||||
any,
|
||||
TGetSsoSettings | undefined,
|
||||
];
|
||||
};
|
||||
|
||||
export const updateCookie = (name: string, value: string, options: object) => {
|
||||
"use server";
|
||||
|
||||
const cookieStore = cookies();
|
||||
|
||||
cookieStore.set(name, value, options);
|
||||
};
|
||||
|
30
packages/login-next/src/utils/constants.ts
Normal file
30
packages/login-next/src/utils/constants.ts
Normal file
@ -0,0 +1,30 @@
|
||||
// (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
|
||||
|
||||
export const DEFAULT_ROOM_TEXT =
|
||||
"<strong>{{firstName}} {{lastName}}</strong> invites you to join the room <strong>{{roomName}}</strong> for secure document collaboration.";
|
||||
export const DEFAULT_PORTAL_TEXT =
|
||||
"<strong>{{firstName}} {{lastName}}</strong> invites you to join the room <strong>{{roomName}}</strong> for secure document collaboration.";
|
49
packages/login-next/src/utils/enums.ts
Normal file
49
packages/login-next/src/utils/enums.ts
Normal file
@ -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
|
||||
|
||||
export enum MessageKey {
|
||||
"None",
|
||||
"Error",
|
||||
"ErrorUserNotFound",
|
||||
"ErrorExpiredActivationLink",
|
||||
"ErrorInvalidActivationLink",
|
||||
"ErrorConfirmURLError",
|
||||
"ErrorNotCorrectEmail",
|
||||
"LoginWithBruteForce",
|
||||
"RecaptchaInvalid",
|
||||
"LoginWithAccountNotFound",
|
||||
"InvalidUsernameOrPassword",
|
||||
"SsoSettingsDisabled",
|
||||
"ErrorNotAllowedOption",
|
||||
"SsoSettingsEmptyToken",
|
||||
"SsoSettingsNotValidToken",
|
||||
"SsoSettingsCantCreateUser",
|
||||
"SsoSettingsUserTerminated",
|
||||
"SsoError",
|
||||
"SsoAuthFailed",
|
||||
"SsoAttributesNotFound",
|
||||
"QuotaPaidUserLimitError",
|
||||
}
|
@ -33,10 +33,9 @@ import { translations } from "./autoGeneratedTranslations";
|
||||
export const getI18NInstance = (portalLng: string) => {
|
||||
if (typeof window === "undefined") return;
|
||||
|
||||
const currentLng = portalLng;
|
||||
|
||||
i18n.use(initReactI18next).init({
|
||||
lng: portalLng,
|
||||
// lng: portalLng,
|
||||
lng: "ru",
|
||||
fallbackLng: "en",
|
||||
load: "currentOnly",
|
||||
|
||||
|
105
packages/login-next/src/utils/index.ts
Normal file
105
packages/login-next/src/utils/index.ts
Normal file
@ -0,0 +1,105 @@
|
||||
// (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 { thirdPartyLogin } from "@docspace/shared/utils/loginUtils";
|
||||
import { TTranslation } from "@docspace/shared/types";
|
||||
|
||||
import { MessageKey } from "./enums";
|
||||
|
||||
export async function oAuthLogin(profile: string) {
|
||||
let isSuccess = false;
|
||||
try {
|
||||
await thirdPartyLogin(profile);
|
||||
isSuccess = true;
|
||||
const redirectPath = localStorage.getItem("redirectPath");
|
||||
|
||||
if (redirectPath) {
|
||||
localStorage.removeItem("redirectPath");
|
||||
window.location.href = redirectPath;
|
||||
}
|
||||
} catch (e) {
|
||||
isSuccess = false;
|
||||
return isSuccess;
|
||||
}
|
||||
|
||||
localStorage.removeItem("profile");
|
||||
localStorage.removeItem("code");
|
||||
|
||||
return isSuccess;
|
||||
}
|
||||
|
||||
export const getMessageFromKey = (messageKey: number) => {
|
||||
return MessageKey[messageKey];
|
||||
};
|
||||
|
||||
export const getMessageKeyTranslate = (t: TTranslation, message: string) => {
|
||||
switch (message) {
|
||||
case "Error":
|
||||
return t("Common:Error");
|
||||
case "None":
|
||||
return t("Common:UnknownError");
|
||||
case "ErrorUserNotFound":
|
||||
return t("Errors:ErrorUserNotFound");
|
||||
case "ErrorExpiredActivationLink":
|
||||
return t("Errors:ErrorExpiredActivationLink");
|
||||
case "ErrorInvalidActivationLink":
|
||||
return t("Errors:ErrorInvalidActivationLink");
|
||||
case "ErrorConfirmURLError":
|
||||
return t("Errors:ErrorConfirmURLError");
|
||||
case "ErrorNotCorrectEmail":
|
||||
return t("Common:IncorrectEmail");
|
||||
case "LoginWithBruteForce":
|
||||
return t("Errors:LoginWithBruteForce");
|
||||
case "RecaptchaInvalid":
|
||||
return t("Errors:RecaptchaInvalid");
|
||||
case "LoginWithAccountNotFound":
|
||||
return t("Errors:LoginWithAccountNotFound");
|
||||
case "InvalidUsernameOrPassword":
|
||||
return t("Errors:InvalidUsernameOrPassword");
|
||||
case "SsoSettingsDisabled":
|
||||
return t("Errors:SsoSettingsDisabled");
|
||||
case "ErrorNotAllowedOption":
|
||||
return t("Errors:ErrorNotAllowedOption");
|
||||
case "SsoSettingsEmptyToken":
|
||||
return t("Errors:SsoSettingsEmptyToken");
|
||||
case "SsoSettingsNotValidToken":
|
||||
return t("Errors:SsoSettingsNotValidToken");
|
||||
case "SsoSettingsCantCreateUser":
|
||||
return t("Errors:SsoSettingsCantCreateUser");
|
||||
case "SsoSettingsUserTerminated":
|
||||
return t("Errors:SsoSettingsUserTerminated");
|
||||
case "SsoError":
|
||||
return t("Errors:SsoError");
|
||||
case "SsoAuthFailed":
|
||||
return t("Errors:SsoAuthFailed");
|
||||
case "SsoAttributesNotFound":
|
||||
return t("Errors:SsoAttributesNotFound");
|
||||
case "QuotaPaidUserLimitError":
|
||||
return t("Common:QuotaPaidUserLimitError");
|
||||
default:
|
||||
return t("Common:Error");
|
||||
}
|
||||
};
|
56
packages/login-next/src/utils/registry.tsx
Normal file
56
packages/login-next/src/utils/registry.tsx
Normal file
@ -0,0 +1,56 @@
|
||||
// (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 React, { useState } from "react";
|
||||
import { ServerStyleSheet, StyleSheetManager } from "styled-components";
|
||||
import { useServerInsertedHTML } from "next/navigation";
|
||||
|
||||
export default function StyledComponentsRegistry({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
// Only create stylesheet once with lazy initial state
|
||||
// x-ref: https://reactjs.org/docs/hooks-reference.html#lazy-initial-state
|
||||
const [styledComponentsStyleSheet] = useState(() => new ServerStyleSheet());
|
||||
|
||||
useServerInsertedHTML(() => {
|
||||
const styles = styledComponentsStyleSheet.getStyleElement();
|
||||
styledComponentsStyleSheet.instance.clearTag();
|
||||
return <>{styles}</>;
|
||||
});
|
||||
|
||||
if (typeof window !== "undefined") return <>{children}</>;
|
||||
|
||||
return (
|
||||
<StyleSheetManager sheet={styledComponentsStyleSheet.instance}>
|
||||
{children}
|
||||
</StyleSheetManager>
|
||||
);
|
||||
}
|
||||
|
@ -3191,6 +3191,7 @@ __metadata:
|
||||
"@types/node": "npm:^20"
|
||||
"@types/react": "npm:^18"
|
||||
"@types/react-dom": "npm:^18"
|
||||
babel-plugin-styled-components: "npm:^2.1.4"
|
||||
eslint: "npm:^8"
|
||||
eslint-config-next: "npm:14.0.4"
|
||||
i18next: "npm:^20.6.1"
|
||||
@ -11244,7 +11245,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"babel-plugin-styled-components@npm:>= 1.12.0":
|
||||
"babel-plugin-styled-components@npm:>= 1.12.0, babel-plugin-styled-components@npm:^2.1.4":
|
||||
version: 2.1.4
|
||||
resolution: "babel-plugin-styled-components@npm:2.1.4"
|
||||
dependencies:
|
||||
|
Loading…
Reference in New Issue
Block a user