diff --git a/public/co-logo-orchestrating.png b/public/co-logo-orchestrating.png deleted file mode 100644 index 93addb7e..00000000 Binary files a/public/co-logo-orchestrating.png and /dev/null differ diff --git a/public/locales/en.json b/public/locales/en.json index 1db60e95..2c3941d7 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -1,9 +1,9 @@ { - "Login": { - "welcomeMessage": "Welcome to openMCP UI", - "description": "Your place to manage your openMCPs, see your installed components and managed resources!", - "learnMore": "Learn more in our documentation", - "signInButton": "Sign in" + "SignInPage": { + "welcomeMessage": "Welcome to ManagedControlPlane UI", + "subtitle": "Your central hub to orchestrate control planes, components, and managed resources", + "learnMoreLink": "Learn about ManagedControlPlanes", + "signInButton": "Sign In" }, "Entities": { "ManagedControlPlane": "ManagedControlPlane", diff --git a/src/App.tsx b/src/App.tsx index 1d2a4920..c8efae23 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -3,7 +3,7 @@ import { useAuthOnboarding } from './spaces/onboarding/auth/AuthContextOnboardin import '@ui5/webcomponents-icons/dist/AllIcons.d.ts'; import { useEffect } from 'react'; import { useFrontendConfig } from './context/FrontendConfigContext.tsx'; -import LoginView from './views/Login.tsx'; +import { SignInPage } from './spaces/onboarding/pages/SignInPage/SignInPage.tsx'; import { BusyIndicator } from '@ui5/webcomponents-react'; import * as Sentry from '@sentry/react'; @@ -22,7 +22,7 @@ function App() { } if (!auth.isAuthenticated) { - return ; + return ; } Sentry.setUser({ diff --git a/src/assets/images/co-logo-orchestrating-dark.png b/src/assets/images/co-logo-orchestrating-dark.png new file mode 100644 index 00000000..a288ac7e Binary files /dev/null and b/src/assets/images/co-logo-orchestrating-dark.png differ diff --git a/src/assets/images/co-logo-orchestrating.png b/src/assets/images/co-logo-orchestrating.png new file mode 100644 index 00000000..3f34dcf1 Binary files /dev/null and b/src/assets/images/co-logo-orchestrating.png differ diff --git a/src/spaces/onboarding/pages/SignInPage/SignInPage.cy.tsx b/src/spaces/onboarding/pages/SignInPage/SignInPage.cy.tsx new file mode 100644 index 00000000..03123d98 --- /dev/null +++ b/src/spaces/onboarding/pages/SignInPage/SignInPage.cy.tsx @@ -0,0 +1,49 @@ +import { SignInPage } from './SignInPage.tsx'; +import { useAuthOnboarding } from '../../auth/AuthContextOnboarding.tsx'; +import { useLink } from '../../../../lib/shared/useLink.ts'; // if useLink relies on router + +describe('SignInPage', () => { + let logInCalled = false; + const fakeUseAuthOnboarding = (() => ({ + login: () => { + logInCalled = true; + }, + })) as typeof useAuthOnboarding; + + beforeEach(() => { + logInCalled = false; + }); + + it('renders the SignInPage', () => { + cy.mount(); + + cy.get('ui5-title').should('exist'); + }); + + it('calls the login function when the user clicks the "Sign In" button', () => { + cy.mount(); + + cy.wrap(null).then(() => { + expect(logInCalled).to.equal(false); + }); + + cy.get('ui5-button').eq(0).should('contain', 'Sign In').click(); + + cy.wrap(null).then(() => { + expect(logInCalled).to.equal(true); + }); + }); + + it('contains a link to the documentation', () => { + const fakeUseLink = (() => ({ + documentationHomepage: 'https://link-to-documentation.com', + })) as typeof useLink; + + cy.mount(); + + cy.get('a') + .should('have.attr', 'target', '_blank') + .and('have.attr', 'rel', 'noreferrer') + .and('have.attr', 'href', 'https://link-to-documentation.com'); + }); +}); diff --git a/src/spaces/onboarding/pages/SignInPage/SignInPage.module.css b/src/spaces/onboarding/pages/SignInPage/SignInPage.module.css new file mode 100644 index 00000000..c6d6ebe9 --- /dev/null +++ b/src/spaces/onboarding/pages/SignInPage/SignInPage.module.css @@ -0,0 +1,21 @@ +.container { + height: 100vh; +} + +.cardContent { + padding: 2rem 3rem; +} + +.heading { + margin-bottom: 0.75rem; +} + +.description { + font-size: 1.25em; +} + +.logo { + width: 240px; + height: 290px; + margin: 3rem; +} diff --git a/src/spaces/onboarding/pages/SignInPage/SignInPage.tsx b/src/spaces/onboarding/pages/SignInPage/SignInPage.tsx new file mode 100644 index 00000000..a4b4c030 --- /dev/null +++ b/src/spaces/onboarding/pages/SignInPage/SignInPage.tsx @@ -0,0 +1,64 @@ +import { useEffect } from 'react'; +import { useTranslation } from 'react-i18next'; +import * as Sentry from '@sentry/react'; + +import { Button, Card, FlexBox, Text, Title } from '@ui5/webcomponents-react'; +import ButtonDesign from '@ui5/webcomponents/dist/types/ButtonDesign.js'; + +import { useAuthOnboarding as _useAuthOnboarding } from '../../auth/AuthContextOnboarding'; +import { useLink as _useLink } from '../../../../lib/shared/useLink'; +import { useTheme } from '../../../../hooks/useTheme'; + +import LogoLight from '../../../../assets/images/co-logo-orchestrating.png'; +import LogoDark from '../../../../assets/images/co-logo-orchestrating-dark.png'; + +import styles from './SignInPage.module.css'; + +export interface SignInPageProps { + useAuthOnboarding?: typeof _useAuthOnboarding; + useLink?: typeof _useLink; +} +export function SignInPage({ useAuthOnboarding = _useAuthOnboarding, useLink = _useLink }: SignInPageProps) { + const { login } = useAuthOnboarding(); + const { documentationHomepage } = useLink(); + const { t } = useTranslation(); + const { isDarkTheme } = useTheme(); + + useEffect(() => { + Sentry.addBreadcrumb({ + category: 'auth', + message: 'Visit SignInPage', + level: 'info', + }); + }, []); + return ( + + + + + + {t('SignInPage.welcomeMessage')} + + + {t('SignInPage.subtitle')} + + + + + void login()}> + {t('SignInPage.signInButton')} + + + + + + + + {t('SignInPage.learnMoreLink')} + + + + + + ); +} diff --git a/src/views/Login.tsx b/src/views/Login.tsx deleted file mode 100644 index 5317a3bc..00000000 --- a/src/views/Login.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import { useAuthOnboarding } from '../spaces/onboarding/auth/AuthContextOnboarding.tsx'; -import { Button, Card, FlexBox, Link, Text } from '@ui5/webcomponents-react'; -import ButtonDesign from '@ui5/webcomponents/dist/types/ButtonDesign.js'; -import './login.css'; -import { ThemingParameters } from '@ui5/webcomponents-react-base'; -import { useLink } from '../lib/shared/useLink.ts'; -import { useTranslation } from 'react-i18next'; -import * as Sentry from '@sentry/react'; -import { useEffect } from 'react'; - -export default function LoginView() { - const auth = useAuthOnboarding(); - const { documentationHomepage } = useLink(); - const { t } = useTranslation(); - useEffect(() => { - Sentry.addBreadcrumb({ - category: 'auth', - message: 'Visit Login Page', - level: 'info', - }); - }, []); - return ( - - - - - {t('Login.welcomeMessage')} - - {t('Login.description')} - - - - - {t('Login.learnMore')} - - - - - void auth.login()}> - {t('Login.signInButton')} - - - - - - ); -} diff --git a/src/views/login.css b/src/views/login.css deleted file mode 100644 index 11531f82..00000000 --- a/src/views/login.css +++ /dev/null @@ -1,26 +0,0 @@ -.headline { - font-size: 2rem; - font-weight: bold; - margin-bottom: 8px; -} - -.description { - max-width: 50ch; - text-align: center; - margin: 0 auto; -} - -.logo { - width: 400px; -} - -.box { - height: 100vh; - background-color: #f5f5f5; - text-align: center; -} - -.signinBtn { - font-size: 1rem; - padding: 10px 20px; -}
- - {t('Login.learnMore')} - -