From ecd38674b189813a508187c3142221401f3634d4 Mon Sep 17 00:00:00 2001 From: Sergio Betanzos Date: Wed, 18 May 2022 12:48:31 +0200 Subject: [PATCH] F #5422: Add other app links to login (#2050) --- .../src/client/components/Header/index.js | 3 +- src/fireedge/src/client/constants/index.js | 2 + .../src/client/constants/translates.js | 3 +- .../src/client/containers/Login/Form.js | 25 ++-- .../src/client/containers/Login/index.js | 109 +++++++++++++----- .../src/client/containers/Login/styles.js | 67 ----------- 6 files changed, 97 insertions(+), 112 deletions(-) delete mode 100644 src/fireedge/src/client/containers/Login/styles.js diff --git a/src/fireedge/src/client/components/Header/index.js b/src/fireedge/src/client/components/Header/index.js index 0da7326598..c8f6381c03 100644 --- a/src/fireedge/src/client/components/Header/index.js +++ b/src/fireedge/src/client/components/Header/index.js @@ -37,6 +37,7 @@ import Group from 'client/components/Header/Group' import Zone from 'client/components/Header/Zone' import { Translate } from 'client/components/HOC' import { sentenceCase } from 'client/utils' +import { APPS_WITH_ONE_PREFIX } from 'client/constants' const Header = memo(({ route: { title, description } = {} }) => { const { isOneAdmin } = useAuth() @@ -77,7 +78,7 @@ const Header = memo(({ route: { title, description } = {} }) => { sx={{ userSelect: 'none' }} > - {'One'} + {APPS_WITH_ONE_PREFIX.includes(appTitle) && 'One'} { // should be equal to the apps in src/server/utils/constants/defaults.js export const _APPS = { sunstone: 'sunstone', provision: 'provision' } export const APPS = Object.keys(_APPS) + export const APPS_IN_BETA = [] export const APPS_WITH_SWITCHER = [_APPS.sunstone] +export const APPS_WITH_ONE_PREFIX = [_APPS.provision] export const APP_URL = '/fireedge' export const WEBSOCKET_URL = `${APP_URL}/websockets` diff --git a/src/fireedge/src/client/constants/translates.js b/src/fireedge/src/client/constants/translates.js index bea8c963a9..186d8a750e 100644 --- a/src/fireedge/src/client/constants/translates.js +++ b/src/fireedge/src/client/constants/translates.js @@ -209,7 +209,7 @@ module.exports = { HoursBetween0_168: 'Hours should be between 0 and 168', WhenYouWantThatTheActionFinishes: 'When you want that the action finishes', - /* dashboard */ + /* footer */ MadeWith: 'Made with', /* dashboard */ @@ -224,6 +224,7 @@ module.exports = { Credentials: 'Credentials', SwitchView: 'Switch view', SwitchGroup: 'Switch group', + TakeMeToTheAppGui: 'Take me to the %s GUI', /* errors */ SessionExpired: 'Sorry, your session has expired', diff --git a/src/fireedge/src/client/containers/Login/Form.js b/src/fireedge/src/client/containers/Login/Form.js index fd467c5627..3ba4e28bf8 100644 --- a/src/fireedge/src/client/containers/Login/Form.js +++ b/src/fireedge/src/client/containers/Login/Form.js @@ -17,16 +17,13 @@ import { useEffect } from 'react' import PropTypes from 'prop-types' -import clsx from 'clsx' import { Button, Box, Slide, Stack } from '@mui/material' import { useForm, FormProvider } from 'react-hook-form' import { yupResolver } from '@hookform/resolvers/yup' -import loginStyles from 'client/containers/Login/styles' - import FormWithSchema from 'client/components/Forms/FormWithSchema' import { SubmitButton } from 'client/components/FormControl' -import { Tr } from 'client/components/HOC' +import { Translate } from 'client/components/HOC' import { T } from 'client/constants' const Form = ({ @@ -38,12 +35,9 @@ const Form = ({ isLoading, transitionProps, }) => { - const defaultValues = resolver.default() - const classes = loginStyles() - const { handleSubmit, setError, ...methods } = useForm({ reValidateMode: 'onSubmit', - defaultValues, + defaultValues: resolver.default(), resolver: yupResolver(resolver), }) @@ -61,23 +55,28 @@ const Form = ({ - + {onBack && ( )} } /> diff --git a/src/fireedge/src/client/containers/Login/index.js b/src/fireedge/src/client/containers/Login/index.js index 8a19acd2d1..4c9ee034c2 100644 --- a/src/fireedge/src/client/containers/Login/index.js +++ b/src/fireedge/src/client/containers/Login/index.js @@ -13,26 +13,30 @@ * See the License for the specific language governing permissions and * * limitations under the License. * * ------------------------------------------------------------------------- */ -/* eslint-disable jsdoc/require-jsdoc */ -import { useMemo, useState } from 'react' + +import { ReactElement, useState, memo } from 'react' +import PropTypes from 'prop-types' import { Box, Container, LinearProgress, - Paper, + Link, useMediaQuery, } from '@mui/material' -import { useAuth, useAuthApi } from 'client/features/Auth' import { useLoginMutation, useChangeAuthGroupMutation, } from 'client/features/AuthApi' +import { useAuth, useAuthApi } from 'client/features/Auth' +import { useGeneral } from 'client/features/General' import Form from 'client/containers/Login/Form' import * as FORMS from 'client/containers/Login/schema' -import loginStyles from 'client/containers/Login/styles' import { OpenNebulaLogo } from 'client/components/Icons' +import { Translate } from 'client/components/HOC' +import { sentenceCase } from 'client/utils' +import { T, APPS, APP_URL, APPS_WITH_ONE_PREFIX } from 'client/constants' const STEPS = { USER_FORM: 0, @@ -40,18 +44,23 @@ const STEPS = { GROUP_FORM: 2, } +/** + * Displays the login form and handles the login process. + * + * @returns {ReactElement} The login form. + */ function Login() { - const classes = loginStyles() const isMobile = useMediaQuery((theme) => theme.breakpoints.only('xs')) const { logout } = useAuthApi() - const { error: otherError, isLoginInProgress: needGroupToContinue } = - useAuth() + const { error: authError, isLoginInProgress: needGroupToContinue } = useAuth() + + const { appTitle } = useGeneral() const [changeAuthGroup, changeAuthGroupState] = useChangeAuthGroupMutation() const [login, loginState] = useLoginMutation() const isLoading = loginState.isLoading || changeAuthGroupState.isLoading - const errorMessage = loginState.error?.data?.message ?? otherError + const errorMessage = loginState.error?.data?.message ?? authError const [dataUserForm, setDataUserForm] = useState(undefined) const [step, setStep] = useState(() => @@ -72,7 +81,9 @@ function Login() { } catch {} } - const handleSubmitGroup = (dataForm) => changeAuthGroup(dataForm) + const handleSubmitGroup = (dataForm) => { + changeAuthGroup(dataForm) + } const handleBack = () => { logout() @@ -85,24 +96,39 @@ function Login() { component="main" disableGutters={isMobile} maxWidth={isMobile ? 'lg' : 'xs'} - className={classes.root} + sx={{ + display: 'flex', + flexDirection: 'column', + justifyContent: 'center', + height: '100vh', + }} > - {isLoading && ( - - )} - - {useMemo( - () => ( - - ), - [] - )} - + + ({ + xs: 'none', + sm: `1px solid ${palette.divider}`, + }), + borderRadius: ({ shape }) => shape.borderRadius / 2, + height: { xs: 'calc(100vh - 4px)', sm: 'auto' }, + backgroundColor: { xs: 'transparent', sm: 'background.paper' }, + }} + > + + + {step === STEPS.USER_FORM && (
)} - + + {APPS?.filter((app) => app !== `${appTitle}`.toLowerCase())?.map( + (app) => ( + + ) + )} + ) } -Login.propTypes = {} +const AppLink = memo(({ app }) => { + const name = APPS_WITH_ONE_PREFIX.includes(app) + ? `One${sentenceCase(app)}` + : sentenceCase(app) -Login.defaultProps = {} + return ( + + + + ) +}) + +AppLink.displayName = 'AppLink' +AppLink.propTypes = { app: PropTypes.string.isRequired } export default Login diff --git a/src/fireedge/src/client/containers/Login/styles.js b/src/fireedge/src/client/containers/Login/styles.js deleted file mode 100644 index 5b4ee7fbe1..0000000000 --- a/src/fireedge/src/client/containers/Login/styles.js +++ /dev/null @@ -1,67 +0,0 @@ -/* ------------------------------------------------------------------------- * - * Copyright 2002-2022, OpenNebula Project, OpenNebula Systems * - * * - * Licensed under the Apache License, Version 2.0 (the "License"); you may * - * not use this file except in compliance with the License. You may obtain * - * a copy of the License at * - * * - * http://www.apache.org/licenses/LICENSE-2.0 * - * * - * Unless required by applicable law or agreed to in writing, software * - * distributed under the License is distributed on an "AS IS" BASIS, * - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * - * See the License for the specific language governing permissions and * - * limitations under the License. * - * ------------------------------------------------------------------------- */ -import makeStyles from '@mui/styles/makeStyles' - -export default makeStyles((theme) => ({ - root: { - display: 'flex', - flexDirection: 'column', - justifyContent: 'center', - height: '100vh', - }, - progress: { - height: 4, - width: '100%', - [theme.breakpoints.only('xs')]: { - top: 0, - position: 'fixed', - }, - }, - paper: { - overflow: 'hidden', - padding: theme.spacing(2), - minHeight: 440, - [theme.breakpoints.up('xs')]: { - display: 'flex', - flexDirection: 'column', - }, - [theme.breakpoints.only('xs')]: { - border: 'none', - height: 'calc(100vh - 4px)', - backgroundColor: 'transparent', - }, - }, - wrapperForm: { - padding: theme.spacing(2, 1), - display: 'flex', - overflow: 'hidden', - }, - form: { - width: '100%', - flexShrink: 0, - display: 'flex', - flexDirection: 'column', - [theme.breakpoints.up('xs')]: { - justifyContent: 'center', - }, - }, - loading: { - opacity: 0.7, - }, - helper: { - animation: '1s ease-out 0s 1', - }, -}))