Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SignUp Page #2148

Merged
merged 25 commits into from
Apr 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
efb0954
SignUp Page
PedroFonsecaDEV Mar 19, 2021
4224200
Change request (#22)
DukeManh Apr 16, 2021
01a04e9
fix buttons and flow
PedroFonsecaDEV Apr 16, 2021
f02ac59
Reword overview
PedroFonsecaDEV Apr 16, 2021
780f6e1
Display Name: required
PedroFonsecaDEV Apr 16, 2021
55a7aba
change buttons position
PedroFonsecaDEV Apr 16, 2021
62844e3
fix button position
PedroFonsecaDEV Apr 16, 2021
acb9448
Update AuthProvider to use new register logic
humphd Apr 16, 2021
fb53950
auth service update on signup
PedroFonsecaDEV Apr 16, 2021
f6b99de
buttons working
PedroFonsecaDEV Apr 16, 2021
a82ad0d
Please squash all into 1 commit (#25)
DukeManh Apr 17, 2021
6a6f249
PopUp
PedroFonsecaDEV Apr 17, 2021
5fef63a
remove redirect from AuthProvider
PedroFonsecaDEV Apr 17, 2021
d378e8c
*fix vulnerability on PopUp
PedroFonsecaDEV Apr 17, 2021
5756524
sign up working
PedroFonsecaDEV Apr 17, 2021
8ad2e92
Update TelescopeAvatar component:
PedroFonsecaDEV Apr 17, 2021
579b2f7
Avatar Logout Landing page
PedroFonsecaDEV Apr 17, 2021
e4c2add
update banner buttons
PedroFonsecaDEV Apr 17, 2021
fe67e97
update PopUp logic
PedroFonsecaDEV Apr 17, 2021
9394b1a
update banner buttons
PedroFonsecaDEV Apr 17, 2021
f2a94d9
fix render behind pop up on signup
PedroFonsecaDEV Apr 17, 2021
bd6c12b
text
PedroFonsecaDEV Apr 17, 2021
ea3bba3
signup back to home button
PedroFonsecaDEV Apr 17, 2021
412368e
*github const rename
PedroFonsecaDEV Apr 18, 2021
ca9d71f
production.yml and fix button text
PedroFonsecaDEV Apr 18, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docker/production.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ services:
- AUTH_URL=${AUTH_URL}
- POSTS_URL=${POSTS_URL}
- SEARCH_URL=${SEARCH_URL}
- FEED_DISCOVERY_URL=${FEED_DISCOVERY_URL}
PedroFonsecaDEV marked this conversation as resolved.
Show resolved Hide resolved
container_name: 'telescope'
restart: unless-stopped
environment:
Expand All @@ -47,8 +48,10 @@ services:
- PORT
- POSTS_URL
- API_URL
- AUTH_URL
- WEB_URL
- SEARCH_URL
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@humphd
same here for: 'AUTH_URL' and 'USERS_URL' ?
reference: #2148 (comment)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we need AUTH_URL in here, and if we're going to include USERS_URL above, we need it here too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay.
Tks.

Done.

- FEED_DISCOVERY_URL
- LOG_LEVEL
- FEED_URL
- FEED_URL_INTERVAL_MS
Expand Down
10 changes: 9 additions & 1 deletion src/web/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,15 @@ const dotenv = require('dotenv');
const loadApiUrlFromEnv = (envFile) => dotenv.config({ path: envFile });

// ENV Variables we need to forward to next by prefix with NEXT_PUBLIC_*
const envVarsToForward = ['WEB_URL', 'API_URL', 'IMAGE_URL', 'POSTS_URL', 'AUTH_URL', 'SEARCH_URL'];
const envVarsToForward = [
'WEB_URL',
'API_URL',
'IMAGE_URL',
'POSTS_URL',
'AUTH_URL',
'SEARCH_URL',
'FEED_DISCOVERY_URL',
];
humphd marked this conversation as resolved.
Show resolved Hide resolved

// Copy an existing ENV Var so it's visible to next: API_URL -> NEXT_PUBLIC_API_URL
const forwardToNext = (envVar) => {
Expand Down
5 changes: 4 additions & 1 deletion src/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
"@mdx-js/loader": "^1.6.22",
"@next/mdx": "^10.1.3",
"@types/smoothscroll-polyfill": "^0.3.1",
"@types/yup": "^0.29.11",
"dotenv": "^8.2.0",
"formik": "^2.2.6",
"highlight.js": "10.7.2",
"jwt-decode": "^3.1.2",
"nanoid": "^3.1.22",
Expand All @@ -25,7 +27,8 @@
"react-use": "^17.2.1",
"smoothscroll-polyfill": "^0.4.4",
"swr": "^0.5.5",
"valid-url": "^1.0.9"
"valid-url": "^1.0.9",
"yup": "^0.32.9"
},
"devDependencies": {
"@testing-library/react": "^11.2.6",
Expand Down
53 changes: 36 additions & 17 deletions src/web/src/components/AuthProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createContext, ReactNode } from 'react';
import { createContext, ReactNode, useState, useEffect } from 'react';
import { useLocalStorage } from 'react-use';
import { useRouter } from 'next/router';
import { nanoid } from 'nanoid';
Expand All @@ -9,6 +9,7 @@ import { loginUrl, logoutUrl, webUrl } from '../config';
export interface AuthContextInterface {
login: (returnTo?: string) => void;
logout: () => void;
register: (token: string) => void;
user?: User;
token?: string;
}
Expand All @@ -20,6 +21,9 @@ const AuthContext = createContext<AuthContextInterface>({
logout() {
throw new Error('You need to wrap your component in <AuthProvider>');
},
register() {
throw new Error('You need to wrap your component in <AuthProvider>');
},
});

type Props = {
Expand All @@ -29,6 +33,7 @@ type Props = {
const AuthProvider = ({ children }: Props) => {
const router = useRouter();
const { pathname, asPath } = router;
const [user, setUser] = useState<User | undefined>();
const [authState, setAuthState, removeAuthState] = useLocalStorage<string>(
'auth:state',
undefined,
Expand All @@ -43,12 +48,34 @@ const AuthProvider = ({ children }: Props) => {
// Server-side rendering.
if (typeof window === 'undefined') {
return (
<AuthContext.Provider value={{ login: () => null, logout: () => null }}>
<AuthContext.Provider value={{ login: () => null, logout: () => null, register: () => null }}>
{children}
</AuthContext.Provider>
);
}

// Mange the user state based on the presence and validity of the token
useEffect(() => {
const cleanup = () => {
removeToken();
removeAuthState();
setUser(undefined);
};

if (!token) {
cleanup();
return;
}

try {
setUser(User.fromToken(token));
} catch (err) {
// This token isn't parsable, remove all auth info from storage
console.error('Error parsing token for user', err);
cleanup();
}
}, [token]);

// Browser-side rendering
try {
// Try to extract access_token and state query params from the URL, which may not be there
Expand Down Expand Up @@ -78,20 +105,6 @@ const AuthProvider = ({ children }: Props) => {
console.error('Error parsing access_token from URL', err.message);
}

// If we have a token, see if we can extract user info from it
let user: User | undefined;
if (token) {
try {
user = User.fromToken(token);
} catch (err) {
// This token isn't ok, remove all auth info from storage
removeToken();
removeAuthState();

console.error('Error parsing token for user', err);
}
}

const login = (returnTo?: string) => {
// Create and store some random state that we'll send along with this login request
const loginState = nanoid();
Expand All @@ -111,8 +124,14 @@ const AuthProvider = ({ children }: Props) => {
window.location.href = `${logoutUrl}?redirect_uri=${webUrl}`;
};

const register = (token: string) => {
setToken(token);
};

return (
<AuthContext.Provider value={{ login, logout, user, token }}>{children}</AuthContext.Provider>
<AuthContext.Provider value={{ login, logout, register, user, token }}>
{children}
</AuthContext.Provider>
);
};

Expand Down
73 changes: 49 additions & 24 deletions src/web/src/components/BannerButtons.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import Link from 'next/link';
import { makeStyles } from '@material-ui/core';
import { useRouter } from 'next/router';
import { makeStyles, Tooltip, withStyles, Zoom } from '@material-ui/core';
import Button from '@material-ui/core/Button';
import useAuth from '../hooks/use-auth';
import TelescopeAvatar from './TelescopeAvatar';
import PopUp from './PopUp';

const useStyles = makeStyles((theme) => ({
buttonsContainer: {
Expand All @@ -27,12 +29,35 @@ const useStyles = makeStyles((theme) => ({
},
}));

const ButtonTooltip = withStyles({
tooltip: {
fontSize: '1.5rem',
margin: 0,
},
})(Tooltip);

const LandingButtons = () => {
const classes = useStyles();
const { login, logout, user } = useAuth();

const classes = useStyles();

const router = useRouter();

return (
<div className={classes.buttonsContainer}>
<div
className={classes.buttonsContainer}
style={user?.isRegistered ? { width: '155px' } : { width: '250px' }}
>
{user && !user?.isRegistered && (
<PopUp
messageTitle="Telescope"
message={`Hello ${user?.name}, to sign in you need to create your Telescope account. Click SIGN UP to start.`}
agreeAction={() => router.push('/signup')}
agreeButtonText="SIGN UP"
disagreeAction={() => logout()}
disagreeButtonText="CANCEL"
/>
)}
<Link href="/about" passHref>
<Button
style={{
Expand All @@ -45,20 +70,18 @@ const LandingButtons = () => {
About us
</Button>
</Link>
{user ? (
{user?.isRegistered ? (
<>
<Button
onClick={() => logout()}
style={{
border: 'none',
padding: 0,
fontSize: '1.2rem',
}}
variant="outlined"
>
Sign out
</Button>
<TelescopeAvatar name={user.name} img={user.avatarUrl} size="40px" />
<ButtonTooltip title="Sign out" arrow placement="top" TransitionComponent={Zoom}>
<div>
<TelescopeAvatar
action={() => logout()}
name={user.name}
img={user.avatarUrl}
size="40px"
/>
</div>
</ButtonTooltip>
</>
) : (
<>
Expand All @@ -73,14 +96,16 @@ const LandingButtons = () => {
>
Sign in
</Button>
<Button
style={{
fontSize: '1.3rem',
}}
variant="outlined"
>
Sign up
</Button>
<Link href="/signup" passHref>
<Button
style={{
fontSize: '1.3rem',
}}
variant="outlined"
humphd marked this conversation as resolved.
Show resolved Hide resolved
>
Sign up
</Button>
</Link>
</>
)}
</div>
Expand Down
73 changes: 73 additions & 0 deletions src/web/src/components/PopUp.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { MouseEventHandler, useState } from 'react';

import { useRouter } from 'next/router';

import Button from '@material-ui/core/Button';
import Dialog from '@material-ui/core/Dialog';
import DialogActions from '@material-ui/core/DialogActions';
import DialogContent from '@material-ui/core/DialogContent';
import DialogContentText from '@material-ui/core/DialogContentText';
import DialogTitle from '@material-ui/core/DialogTitle';

type PopUpProps = {
messageTitle: string;
message: string;
buttonText?: string;
agreeAction?: MouseEventHandler;
disagreeAction?: MouseEventHandler;
agreeButtonText: string;
disagreeButtonText?: string;
simple?: boolean;
};

const PopUp = ({
messageTitle,
message,
agreeAction,
disagreeAction,
agreeButtonText,
disagreeButtonText,
simple,
buttonText,
}: PopUpProps) => {
const [open, setOpen] = useState(true);

const handleClose = () => {
setOpen(false);
};

const router = useRouter();

return (
<>
<Dialog
open={simple ? open : true}
onClose={() => router.push('/')}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<DialogTitle id="alert-dialog-title">{messageTitle}</DialogTitle>
<DialogContent>
<DialogContentText id="alert-dialog-description">{message}</DialogContentText>
</DialogContent>
<DialogActions>
{disagreeAction && (
<Button onClick={disagreeAction} color="primary">
{disagreeButtonText}
</Button>
)}
{simple && (
<Button onClick={handleClose} color="primary">
{buttonText}
</Button>
)}
<Button onClick={agreeAction} color="primary" autoFocus>
{agreeButtonText}
</Button>
</DialogActions>
</Dialog>
</>
);
};

export default PopUp;
48 changes: 48 additions & 0 deletions src/web/src/components/SignUp/FormFields/CheckBoxInput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { createStyles, makeStyles } from '@material-ui/core';
import { useField } from 'formik';
import FormControl from '@material-ui/core/FormControl';
import FormGroup from '@material-ui/core/FormGroup';
import FormHelperText from '@material-ui/core/FormHelperText';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import Checkbox from '@material-ui/core/Checkbox';

const useStyles = makeStyles(() =>
createStyles({
formInputLabel: {
fontSize: '1.4em',
color: 'black',
},
formControlLabel: {
fontSize: '1em',
color: '#474747',
},
})
);

type CheckboxProps = {
name: string;
label: string;
checked: boolean;
};

const CheckBoxInput = (props: CheckboxProps) => {
const classes = useStyles();

const { label, name, checked, ...rest } = props;
const [field, meta] = useField(props);

return (
<FormControl {...rest} error={!!meta.error && meta.touched}>
<FormGroup>
<FormControlLabel
control={<Checkbox {...field} checked={checked} />}
label={<span className={classes.formControlLabel}>{label}</span>}
name={name}
/>
</FormGroup>
<FormHelperText>{meta.error && meta.touched ? meta.error : ''}</FormHelperText>
</FormControl>
);
};

export default CheckBoxInput;
Loading