From 6d5a2eebb609da67239ea37d12d6b2d3bbfef76e Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Wed, 28 Oct 2020 16:41:53 +0100 Subject: ui: Do not clutter component tree with Redux connects This change refactors the frontend to use hooks for obtaining state within the Redux store as opposed to using Higher-Order Components (HOCs). This eliminates a lot of clutter in the components. --- .../opendc-web-ui/src/containers/auth/Login.js | 64 ++++++++-------------- .../opendc-web-ui/src/containers/auth/Logout.js | 12 ++-- .../src/containers/auth/ProfileName.js | 13 ++--- 3 files changed, 32 insertions(+), 57 deletions(-) (limited to 'opendc-web/opendc-web-ui/src/containers/auth') diff --git a/opendc-web/opendc-web-ui/src/containers/auth/Login.js b/opendc-web/opendc-web-ui/src/containers/auth/Login.js index bebe015c..54605775 100644 --- a/opendc-web/opendc-web-ui/src/containers/auth/Login.js +++ b/opendc-web/opendc-web-ui/src/containers/auth/Login.js @@ -1,18 +1,16 @@ -import PropTypes from 'prop-types' import React from 'react' import GoogleLogin from 'react-google-login' -import { connect } from 'react-redux' +import { useDispatch } from 'react-redux' import { logIn } from '../../actions/auth' import config from '../../config' -class LoginContainer extends React.Component { - static propTypes = { - visible: PropTypes.bool.isRequired, - onLogin: PropTypes.func.isRequired, - } +const Login = (props) => { + const { visible } = props + const dispatch = useDispatch() - onAuthResponse(response) { - this.props.onLogin({ + const onLogin = (payload) => dispatch(logIn(payload)) + const onAuthResponse = (response) => { + onLogin({ email: response.getBasicProfile().getEmail(), givenName: response.getBasicProfile().getGivenName(), familyName: response.getBasicProfile().getFamilyName(), @@ -21,43 +19,27 @@ class LoginContainer extends React.Component { expiresAt: response.getAuthResponse().expires_at, }) } - - onAuthFailure(error) { + const onAuthFailure = (error) => { + // TODO Show error alert console.error(error) } - render() { - if (!this.props.visible) { - return - } - - return ( - ( - - Login with Google - - )} - /> - ) + if (!visible) { + return } -} -const mapStateToProps = (state, ownProps) => { - return { - visible: ownProps.visible, - } + return ( + ( + + Login with Google + + )} + /> + ) } -const mapDispatchToProps = (dispatch) => { - return { - onLogin: (payload) => dispatch(logIn(payload)), - } -} - -const Login = connect(mapStateToProps, mapDispatchToProps)(LoginContainer) - export default Login diff --git a/opendc-web/opendc-web-ui/src/containers/auth/Logout.js b/opendc-web/opendc-web-ui/src/containers/auth/Logout.js index 22400381..66f0f6db 100644 --- a/opendc-web/opendc-web-ui/src/containers/auth/Logout.js +++ b/opendc-web/opendc-web-ui/src/containers/auth/Logout.js @@ -1,13 +1,11 @@ -import { connect } from 'react-redux' +import React from 'react' +import { useDispatch } from 'react-redux' import { logOut } from '../../actions/auth' import LogoutButton from '../../components/navigation/LogoutButton' -const mapDispatchToProps = (dispatch) => { - return { - onLogout: () => dispatch(logOut()), - } +const Logout = (props) => { + const dispatch = useDispatch() + return dispatch(logOut())} /> } -const Logout = connect(undefined, mapDispatchToProps)(LogoutButton) - export default Logout diff --git a/opendc-web/opendc-web-ui/src/containers/auth/ProfileName.js b/opendc-web/opendc-web-ui/src/containers/auth/ProfileName.js index 06da75ab..291c0068 100644 --- a/opendc-web/opendc-web-ui/src/containers/auth/ProfileName.js +++ b/opendc-web/opendc-web-ui/src/containers/auth/ProfileName.js @@ -1,14 +1,9 @@ import React from 'react' -import { connect } from 'react-redux' +import { useSelector } from 'react-redux' -const mapStateToProps = (state) => { - return { - text: state.auth.givenName + ' ' + state.auth.familyName, - } +function ProfileName() { + const name = useSelector((state) => `${state.auth.givenName} ${state.auth.familyName}`) + return {name} } -const SpanElement = ({ text }) => {text} - -const ProfileName = connect(mapStateToProps)(SpanElement) - export default ProfileName -- cgit v1.2.3 From 873ddacf5abafe43fbc2b6c1033e473c3366dc62 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Tue, 11 May 2021 15:40:11 +0200 Subject: ui: Move component styling into CSS modules This change updates the frontend codebase by moving the component styling into CSS module files as opposed to the global styles which we used before. In addition, I have changed the syntax to the newer SCSS syntax, which is more similar to CSS. These changes reduces the styling conflicts that can occur between components and allows us to migrate to systems that do not support importing global styles in components. Moreover, we can benefit from treeshaking using CSS modules. --- opendc-web/opendc-web-ui/src/containers/auth/Login.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'opendc-web/opendc-web-ui/src/containers/auth') diff --git a/opendc-web/opendc-web-ui/src/containers/auth/Login.js b/opendc-web/opendc-web-ui/src/containers/auth/Login.js index 54605775..f652429d 100644 --- a/opendc-web/opendc-web-ui/src/containers/auth/Login.js +++ b/opendc-web/opendc-web-ui/src/containers/auth/Login.js @@ -2,10 +2,10 @@ import React from 'react' import GoogleLogin from 'react-google-login' import { useDispatch } from 'react-redux' import { logIn } from '../../actions/auth' +import { Button } from 'reactstrap' import config from '../../config' -const Login = (props) => { - const { visible } = props +function Login({ visible, className }) { const dispatch = useDispatch() const onLogin = (payload) => dispatch(logIn(payload)) @@ -34,9 +34,9 @@ const Login = (props) => { onSuccess={onAuthResponse} onFailure={onAuthFailure} render={(renderProps) => ( - + )} /> ) -- cgit v1.2.3 From 4397a959e806bf476be4c81bc804616adf58b969 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Wed, 12 May 2021 22:42:12 +0200 Subject: ui: Migrate from CRA to Next.js This change updates the web frontend to use Next.js instead of Create React App (CRA). Next.js enables the possibility of rendering pages on the server side (which reduces the time to first frame) and overall provides a better development experience. Future commits will try to futher optimize the implementation for Next.js. --- opendc-web/opendc-web-ui/src/containers/auth/Login.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'opendc-web/opendc-web-ui/src/containers/auth') diff --git a/opendc-web/opendc-web-ui/src/containers/auth/Login.js b/opendc-web/opendc-web-ui/src/containers/auth/Login.js index f652429d..178f269e 100644 --- a/opendc-web/opendc-web-ui/src/containers/auth/Login.js +++ b/opendc-web/opendc-web-ui/src/containers/auth/Login.js @@ -3,7 +3,6 @@ import GoogleLogin from 'react-google-login' import { useDispatch } from 'react-redux' import { logIn } from '../../actions/auth' import { Button } from 'reactstrap' -import config from '../../config' function Login({ visible, className }) { const dispatch = useDispatch() @@ -30,12 +29,12 @@ function Login({ visible, className }) { return ( ( )} /> -- cgit v1.2.3 From 24147cba0f5723be3525e8f40d1954144841629b Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Thu, 13 May 2021 13:00:00 +0200 Subject: ui: Address technical dept in frontend --- opendc-web/opendc-web-ui/src/containers/auth/ProfileName.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'opendc-web/opendc-web-ui/src/containers/auth') diff --git a/opendc-web/opendc-web-ui/src/containers/auth/ProfileName.js b/opendc-web/opendc-web-ui/src/containers/auth/ProfileName.js index 291c0068..cbbe42b4 100644 --- a/opendc-web/opendc-web-ui/src/containers/auth/ProfileName.js +++ b/opendc-web/opendc-web-ui/src/containers/auth/ProfileName.js @@ -1,9 +1,13 @@ import React from 'react' -import { useSelector } from 'react-redux' +import { useUser } from '../../auth/hook' function ProfileName() { - const name = useSelector((state) => `${state.auth.givenName} ${state.auth.familyName}`) - return {name} + const user = useUser() + return ( + + {user.givenName} {user.familyName} + + ) } export default ProfileName -- cgit v1.2.3 From d9e65dceb38cdb8dc4e464d388755f9456620566 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Sun, 16 May 2021 17:07:58 +0200 Subject: ui: Restructure OpenDC frontend This change updates the structure of the OpenDC frontend in order to improve the maintainability of the frontend. --- opendc-web/opendc-web-ui/src/containers/auth/Login.js | 2 +- opendc-web/opendc-web-ui/src/containers/auth/Logout.js | 2 +- opendc-web/opendc-web-ui/src/containers/auth/ProfileName.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'opendc-web/opendc-web-ui/src/containers/auth') diff --git a/opendc-web/opendc-web-ui/src/containers/auth/Login.js b/opendc-web/opendc-web-ui/src/containers/auth/Login.js index 178f269e..b0da0d0e 100644 --- a/opendc-web/opendc-web-ui/src/containers/auth/Login.js +++ b/opendc-web/opendc-web-ui/src/containers/auth/Login.js @@ -1,7 +1,7 @@ import React from 'react' import GoogleLogin from 'react-google-login' import { useDispatch } from 'react-redux' -import { logIn } from '../../actions/auth' +import { logIn } from '../../redux/actions/auth' import { Button } from 'reactstrap' function Login({ visible, className }) { diff --git a/opendc-web/opendc-web-ui/src/containers/auth/Logout.js b/opendc-web/opendc-web-ui/src/containers/auth/Logout.js index 66f0f6db..94d4d061 100644 --- a/opendc-web/opendc-web-ui/src/containers/auth/Logout.js +++ b/opendc-web/opendc-web-ui/src/containers/auth/Logout.js @@ -1,6 +1,6 @@ import React from 'react' import { useDispatch } from 'react-redux' -import { logOut } from '../../actions/auth' +import { logOut } from '../../redux/actions/auth' import LogoutButton from '../../components/navigation/LogoutButton' const Logout = (props) => { diff --git a/opendc-web/opendc-web-ui/src/containers/auth/ProfileName.js b/opendc-web/opendc-web-ui/src/containers/auth/ProfileName.js index cbbe42b4..3992c00f 100644 --- a/opendc-web/opendc-web-ui/src/containers/auth/ProfileName.js +++ b/opendc-web/opendc-web-ui/src/containers/auth/ProfileName.js @@ -1,5 +1,5 @@ import React from 'react' -import { useUser } from '../../auth/hook' +import { useUser } from '../../auth' function ProfileName() { const user = useUser() -- cgit v1.2.3 From a6865b86cc8d710374fc0b6cfcbd2b863f1942a9 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Sun, 16 May 2021 23:18:02 +0200 Subject: ui: Migrate to Auth0 as Identity Provider This change updates the frontend codebase to move away from the Google login and instead use Auth0 as generic Identity Provider. This allows users to login with other accounts as well. Since Auth0 has a free tier, users can experiment themselves with OpenDC locally without having to pay for the login functionality. The code has been written so that we should be able to migrate away from Auth0 once it is not a suitable Identity Provider for OpenDC anymore. --- .../opendc-web-ui/src/containers/auth/Login.js | 35 ++++------------------ .../opendc-web-ui/src/containers/auth/Logout.js | 7 ++--- .../src/containers/auth/ProfileName.js | 10 ++----- 3 files changed, 11 insertions(+), 41 deletions(-) (limited to 'opendc-web/opendc-web-ui/src/containers/auth') diff --git a/opendc-web/opendc-web-ui/src/containers/auth/Login.js b/opendc-web/opendc-web-ui/src/containers/auth/Login.js index b0da0d0e..8459ef5f 100644 --- a/opendc-web/opendc-web-ui/src/containers/auth/Login.js +++ b/opendc-web/opendc-web-ui/src/containers/auth/Login.js @@ -1,43 +1,18 @@ import React from 'react' -import GoogleLogin from 'react-google-login' -import { useDispatch } from 'react-redux' -import { logIn } from '../../redux/actions/auth' import { Button } from 'reactstrap' +import { useAuth } from '../../auth' function Login({ visible, className }) { - const dispatch = useDispatch() - - const onLogin = (payload) => dispatch(logIn(payload)) - const onAuthResponse = (response) => { - onLogin({ - email: response.getBasicProfile().getEmail(), - givenName: response.getBasicProfile().getGivenName(), - familyName: response.getBasicProfile().getFamilyName(), - googleId: response.googleId, - authToken: response.getAuthResponse().id_token, - expiresAt: response.getAuthResponse().expires_at, - }) - } - const onAuthFailure = (error) => { - // TODO Show error alert - console.error(error) - } + const { loginWithRedirect } = useAuth() if (!visible) { return } return ( - ( - - )} - /> + ) } diff --git a/opendc-web/opendc-web-ui/src/containers/auth/Logout.js b/opendc-web/opendc-web-ui/src/containers/auth/Logout.js index 94d4d061..37705c5d 100644 --- a/opendc-web/opendc-web-ui/src/containers/auth/Logout.js +++ b/opendc-web/opendc-web-ui/src/containers/auth/Logout.js @@ -1,11 +1,10 @@ import React from 'react' -import { useDispatch } from 'react-redux' -import { logOut } from '../../redux/actions/auth' import LogoutButton from '../../components/navigation/LogoutButton' +import { useAuth } from '../../auth' const Logout = (props) => { - const dispatch = useDispatch() - return dispatch(logOut())} /> + const { logout } = useAuth() + return logout({ returnTo: window.location.origin })} /> } export default Logout diff --git a/opendc-web/opendc-web-ui/src/containers/auth/ProfileName.js b/opendc-web/opendc-web-ui/src/containers/auth/ProfileName.js index 3992c00f..70f5b884 100644 --- a/opendc-web/opendc-web-ui/src/containers/auth/ProfileName.js +++ b/opendc-web/opendc-web-ui/src/containers/auth/ProfileName.js @@ -1,13 +1,9 @@ import React from 'react' -import { useUser } from '../../auth' +import { useAuth } from '../../auth' function ProfileName() { - const user = useUser() - return ( - - {user.givenName} {user.familyName} - - ) + const { isLoading, user } = useAuth() + return isLoading ? Loading... : {user.name} } export default ProfileName -- cgit v1.2.3 From 53623fad76274e39206b8e073e371775ea96946b Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Mon, 17 May 2021 12:16:10 +0200 Subject: ui: Migrate to FontAwesome 5 React library This change updates the frontend to use the FontAwesome 5 React library that renders SVG icons as opposed to CSS icon fonts. This migration resolves a couple of issues we had with server-side rendering of the previous FontAwesome icons. --- opendc-web/opendc-web-ui/src/containers/auth/Login.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'opendc-web/opendc-web-ui/src/containers/auth') diff --git a/opendc-web/opendc-web-ui/src/containers/auth/Login.js b/opendc-web/opendc-web-ui/src/containers/auth/Login.js index 8459ef5f..d8083d89 100644 --- a/opendc-web/opendc-web-ui/src/containers/auth/Login.js +++ b/opendc-web/opendc-web-ui/src/containers/auth/Login.js @@ -1,6 +1,8 @@ import React from 'react' import { Button } from 'reactstrap' import { useAuth } from '../../auth' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import { faSignInAlt } from '@fortawesome/free-solid-svg-icons' function Login({ visible, className }) { const { loginWithRedirect } = useAuth() @@ -11,7 +13,7 @@ function Login({ visible, className }) { return ( ) } -- cgit v1.2.3 From 803e13b32cf0ff8b496649fb0a4d6e32400e98a4 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Wed, 14 Jul 2021 22:23:40 +0200 Subject: feat(ui): Migrate to PatternFly 4 design framework This change is a rewrite of the existing OpenDC frontend in order to migrate to the PatternFly 4 design framework. PatternFly is used by Red Hat for various computing related services such as OpenShift, Red Hat Virtualization and Cockpit. Since their design requirements are very similar to those of OpenDC (modeling computing services), migrating to PatternFly 4 allows us to re-use design choices from these services. See https://www.patternfly.org/v4/ for more information about PatternFly. --- .../opendc-web-ui/src/containers/auth/Login.js | 21 --------------------- .../opendc-web-ui/src/containers/auth/Logout.js | 10 ---------- .../src/containers/auth/ProfileName.js | 9 --------- 3 files changed, 40 deletions(-) delete mode 100644 opendc-web/opendc-web-ui/src/containers/auth/Login.js delete mode 100644 opendc-web/opendc-web-ui/src/containers/auth/Logout.js delete mode 100644 opendc-web/opendc-web-ui/src/containers/auth/ProfileName.js (limited to 'opendc-web/opendc-web-ui/src/containers/auth') diff --git a/opendc-web/opendc-web-ui/src/containers/auth/Login.js b/opendc-web/opendc-web-ui/src/containers/auth/Login.js deleted file mode 100644 index d8083d89..00000000 --- a/opendc-web/opendc-web-ui/src/containers/auth/Login.js +++ /dev/null @@ -1,21 +0,0 @@ -import React from 'react' -import { Button } from 'reactstrap' -import { useAuth } from '../../auth' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' -import { faSignInAlt } from '@fortawesome/free-solid-svg-icons' - -function Login({ visible, className }) { - const { loginWithRedirect } = useAuth() - - if (!visible) { - return - } - - return ( - - ) -} - -export default Login diff --git a/opendc-web/opendc-web-ui/src/containers/auth/Logout.js b/opendc-web/opendc-web-ui/src/containers/auth/Logout.js deleted file mode 100644 index 37705c5d..00000000 --- a/opendc-web/opendc-web-ui/src/containers/auth/Logout.js +++ /dev/null @@ -1,10 +0,0 @@ -import React from 'react' -import LogoutButton from '../../components/navigation/LogoutButton' -import { useAuth } from '../../auth' - -const Logout = (props) => { - const { logout } = useAuth() - return logout({ returnTo: window.location.origin })} /> -} - -export default Logout diff --git a/opendc-web/opendc-web-ui/src/containers/auth/ProfileName.js b/opendc-web/opendc-web-ui/src/containers/auth/ProfileName.js deleted file mode 100644 index 70f5b884..00000000 --- a/opendc-web/opendc-web-ui/src/containers/auth/ProfileName.js +++ /dev/null @@ -1,9 +0,0 @@ -import React from 'react' -import { useAuth } from '../../auth' - -function ProfileName() { - const { isLoading, user } = useAuth() - return isLoading ? Loading... : {user.name} -} - -export default ProfileName -- cgit v1.2.3