diff --git a/client/src/App.css b/client/src/App.css index 87e7dde2..1ce0c782 100644 --- a/client/src/App.css +++ b/client/src/App.css @@ -7,8 +7,72 @@ --main-cardBackground-color: #D8E9FD !important } +/* image CSS */ +.centered-image { + display: block; + margin-left: auto; + margin-right: auto; +} + + +.inline-content img { + margin-right: 10px; /* Space between image and text */ +} + +.loading-icon { + display: inline-block; + animation: spin 1s linear infinite; + width: 50px; + height: 50px; + background: transparent; +} + +/* content/text CSS */ +.inline-content { + display: flex; + align-items: center; /* Align items vertically center */ +} /* About page- BCOnexus.js CSS Components */ +.About-half-width-box{ + min-height: 650px; /* Ensure both boxes have a minimum height */ + min-width: 350px;/* min-width: 275px; Ensure both boxes have a minimum width */ + width: 90%; /* Half the width of the container minus spacing */ + margin: 0 auto; /* Add spacing between the boxes */ + border: 1px solid #ccc; /* Add a border for visual separation */ + border-radius: 8px; /* Add border radius for rounded corners */ + display: flex; /* Use flexbox */ + justify-content: center !important; + align-items: center; /* Center content horizontally */ + text-align: left; + padding: 16px; +} + +.centered-title { + text-align: center; +} + +.About-Full-Width-Box{ + width: 100%; + min-width: 275px; + border: 1px #ccc; + border-radius: 5%; + display: flex; + justify-content: flex-start; + align-items: flex-start; + align-content: flex-start; + text-align: left; + margin-bottom: 50px; + margin-top: 20px; +} + +.about-text { + font-family:"lato", sans-serif !important; + font-size: x-large !important; + margin: left 80px !important; + /* color: red; */ +} + .About-bullet { /* display: "inline-block"; margin: "0 2px"; @@ -45,7 +109,10 @@ /* about pages */ .about-main { - margin: 2%; + margin-top: 3%; + margin-left: 20%; + margin-right: 20%; + margin-bottom: 2%; } .member-image { @@ -274,6 +341,7 @@ .home-intro-title { font-size: 28px !important; font-weight: bold !important; + text-align: center !important; } .home-position { diff --git a/client/src/components/FullWidthBox.js b/client/src/components/FullWidthBox.js index f786db79..17607f2e 100644 --- a/client/src/components/FullWidthBox.js +++ b/client/src/components/FullWidthBox.js @@ -1,4 +1,4 @@ -// src/views/home/HomeView/FdaBox.js +// import React from "react"; import { @@ -8,28 +8,51 @@ import { CardContent, Typography } from "@mui/material"; +import PropTypes from 'prop-types'; -export default function FullWidthBox({link, title, content, image, imageAlt, cssClass}) { +export default function FullWidthBox({ link, title, content, image, imageAlt, cssClass }) { const handleClickOpen = () => { if (link !== "") { - global.window.open(link) + global.window.open(link); } }; return ( - + - + {title} - {image && {imageAlt}} - {content} +

+
+ + {image && {imageAlt}} + +
+ {/* {image && {imageAlt}} + */}
); } + +FullWidthBox.propTypes = { + link: PropTypes.string, + title: PropTypes.string.isRequired, + content: PropTypes.string.isRequired, + image: PropTypes.string, + imageAlt: PropTypes.string, + cssClass: PropTypes.string +}; + +FullWidthBox.defaultProps = { + link: '', + image: '', + imageAlt: 'Image', + cssClass: '' +}; \ No newline at end of file diff --git a/client/src/components/HalfWidthBox.js b/client/src/components/HalfWidthBox.js new file mode 100644 index 00000000..f6702661 --- /dev/null +++ b/client/src/components/HalfWidthBox.js @@ -0,0 +1,42 @@ +import React from "react"; +import { Card, CardActionArea, CardContent, Typography } from "@mui/material"; +import PropTypes from 'prop-types'; + +export default function HalfWidthBox({ link, title, content, image, imageAlt, cssClass }) { + const handleClickOpen = () => { + if (link !== "") { + global.window.open(link); + } + }; + + return ( + {/* Define a CSS class for half-width box */} + + + + {title} + +

+ {image && {imageAlt}} + +
+
+
+ ); +} + +HalfWidthBox.propTypes = { + link: PropTypes.string, + title: PropTypes.string.isRequired, + content: PropTypes.string.isRequired, + image: PropTypes.string, + imageAlt: PropTypes.string, + cssClass: PropTypes.string +}; + +HalfWidthBox.defaultProps = { + link: '', + image: '', + imageAlt: 'Image', + cssClass: '' +}; \ No newline at end of file diff --git a/client/src/components/LoadingComponent.js b/client/src/components/LoadingComponent.js new file mode 100644 index 00000000..48cfdc0a --- /dev/null +++ b/client/src/components/LoadingComponent.js @@ -0,0 +1,14 @@ +import React from 'react'; +import biocomputing from "../images/biocomputing.gif" +import '../App.css'; // Ensure you have styles for the loading icon + + +const LoadingIcon = () => { + return ( +
+ loading... +
+ ); +}; + +export default LoadingIcon; diff --git a/client/src/components/auth/Login.js b/client/src/components/auth/Login.js index fab67234..7739cf30 100644 --- a/client/src/components/auth/Login.js +++ b/client/src/components/auth/Login.js @@ -1,6 +1,6 @@ // src/components/auth/Login.js -import React, { useEffect, useState } from "react"; +import React, { useEffect, useState } from "react"; import { useDispatch, useSelector } from "react-redux"; import { Navigate, useNavigate } from "react-router-dom"; import { Formik, Form } from "formik"; @@ -11,11 +11,13 @@ import { Box, Button, Container, Dialog, DialogActions, DialogContent, DialogCon import { Link } from "react-router-dom"; import { forgotPassword, login, googleLogin, orcidLogIn } from "../../slices/accountSlice"; import { useSearchParams } from "react-router-dom"; +import LoadingComponent from '../LoadingComponent'; // Import the LoadingComponent component + +const googleClientId = process.env.REACT_APP_GOOGLE_CLIENT_ID; +const orcid_id = process.env.REACT_APP_ORCID_CLIENT_ID; +const orcidUrl = process.env.REACT_APP_ORCID_URL; +const serverUrl = process.env.REACT_APP_SERVER_URL; -const googleClientId = process.env.REACT_APP_GOOGLE_CLIENT_ID -const orcid_id = process.env.REACT_APP_ORCID_CLIENT_ID -const orcidUrl = process.env.REACT_APP_ORCID_URL -const serverUrl = process.env.REACT_APP_SERVER_URL const onGoogleLoginFailure = (response) => { console.log(response); } @@ -24,11 +26,11 @@ const Login = () => { let navigate = useNavigate(); const dispatch = useDispatch(); const [searchParams, setSearchParams] = useSearchParams(); - const [open, setOpen] = React.useState(false); + const [open, setOpen] = useState(false); const [loading, setLoading] = useState(false); - const [resetEmail, setResetEmail] = React.useState(""); + const [resetEmail, setResetEmail] = useState(""); const { isLoggedIn } = useSelector((state) => state.account); - const code = searchParams.get("code") + const code = searchParams.get("code"); const initialValues = { username: "", password: "", @@ -44,7 +46,7 @@ const Login = () => { navigate("/login"); }) } - }, []) + }, [code, dispatch, navigate]); const validationSchema = Yup.object().shape({ username: Yup.string().required("This field is required!"), @@ -59,7 +61,9 @@ const Login = () => { ) .required("This field is required!"), }); - + + const minimumLoadingTime = 5000; //minimum loading tim 3 seconds + const onGoogleLoginSuccess = (response) => { setLoading(true); const idToken = response.tokenId; @@ -67,12 +71,13 @@ const Login = () => { dispatch(googleLogin(idToken)) .unwrap() .then(() => { - navigate("/"); + setTimeout(() => { + navigate("/"); + }, minimumLoadingTime); }) .catch(() => { setLoading(false); }); - setLoading(false); } const handleLogin = (formValue) => { @@ -85,7 +90,7 @@ const Login = () => { navigate("/"); global.window.location.reload(); }) - .catch((error) => { + .catch(() => { setLoading(false); }); }; @@ -99,7 +104,7 @@ const Login = () => { }) .catch((error) => { console.log(error) - }) + }); setLoading(false); } @@ -113,100 +118,99 @@ const Login = () => { return ( - - - - Sign in - Sign in using your Portal credentials - Don't have an account? Sign up here - -
-

- - + + Or + - ORCID Sign in + + + + + + + + +
+ +
+ + +
+
+ + + Password Reset + + Enter your email address. If there is an account associated with that address we will provide you a link to reset your password. + + { setResetEmail(e.target.value) }} /> - Sign in with ORCID - - - Or - -
- - - - - - - - -
- -
- -
-
-
- - - Password Reset - - Enter your email address. - If there is an account associated with that address we will provide you a link to - reset your password. - - {setResetEmail(e.target.value)}} - /> - - - - - - - + + + + + + + + )} ); }; diff --git a/client/src/images/audience.png b/client/src/images/audience.png new file mode 100644 index 00000000..0a69df56 Binary files /dev/null and b/client/src/images/audience.png differ diff --git a/client/src/pages/About.js b/client/src/pages/About.js index 80d9b033..b5e5f341 100644 --- a/client/src/pages/About.js +++ b/client/src/pages/About.js @@ -1,24 +1,26 @@ import React from "react"; -import { Card, CardHeader, Container, Grid } from "@mui/material"; +import { Card, CardHeader, Container, Grid, Typography } from "@mui/material"; import FullWidthBox from "../components/FullWidthBox"; import ThirdBox from "../components/ThirdBox"; +import HalfWidthBox from "../components/HalfWidthBox"; import logoWithName from "../images/biocompute.png"; +import audiencepic from "../images/audience.png" import "../App.css"; export default function About() { return ( + - +

+ + + + + + + + + + { state.isLoggedIn = false; }) + .addCase(login.pending, (state) => { + state.loading = true; // Set loading to true when login is pending + }) .addCase(login.fulfilled, (state, action) => { + state.loading = false; // Set loading to false when login is fulfilled state.isLoggedIn = true; state.user = action.payload.user; }) .addCase(login.rejected, (state) => { + state.loading = false; // Set loading to false when login is rejected state.isLoggedIn = false; state.user = null; }) diff --git a/server/.secrets.example b/server/.secrets.example index 280086e6..a44f7bca 100644 --- a/server/.secrets.example +++ b/server/.secrets.example @@ -15,5 +15,6 @@ DJANGO_ORCID_OAUTH2_URL= SERVER_VERSION= SERVER_URL= SERVER_DB_URL= +USERDB_URL= DATABASE= EMAIL_BACKEND= \ No newline at end of file