aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugene Sokolov <eug-vs@keemail.me>2020-10-08 20:40:45 +0300
committerGitHub <noreply@github.com>2020-10-08 20:40:45 +0300
commitbdb4d194307c9755c2083c1a11bb876abebcb6de (patch)
tree9aff25b0bd0b47127b66e4db4818468ec70719bf
parent45b4094c02301ff854b8b8017437ad9989efa117 (diff)
parent2c093ce738cb1281db04a8a3f2b6a35b3aa9b354 (diff)
downloadwhich-ui-bdb4d194307c9755c2083c1a11bb876abebcb6de.tar.gz
Merge pull request #102 from which-ecosystem/feat/modal
Modal improvements
-rw-r--r--package-lock.json8
-rw-r--r--package.json1
-rw-r--r--src/components/AttachLink/AttachLink.tsx2
-rw-r--r--src/components/Message/Message.tsx9
-rw-r--r--src/components/ModalScreen/ModalScreen.tsx20
-rw-r--r--src/containers/Page/Page.tsx8
-rw-r--r--src/containers/Page/Router.tsx2
-rw-r--r--src/containers/PollCreation/ImageInput.tsx46
-rw-r--r--src/containers/PollCreation/PollCreation.tsx52
-rw-r--r--src/hooks/APIClient.ts4
10 files changed, 86 insertions, 66 deletions
diff --git a/package-lock.json b/package-lock.json
index 03961ee..e25fb85 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -6396,14 +6396,6 @@
"resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz",
"integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ=="
},
- "history": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/history/-/history-5.0.0.tgz",
- "integrity": "sha512-3NyRMKIiFSJmIPdq7FxkNMJkQ7ZEtVblOQ38VtKaA0zZMW1Eo6Q6W8oDKEflr1kNNTItSnk4JMCO1deeSgbLLg==",
- "requires": {
- "@babel/runtime": "^7.7.6"
- }
- },
"hmac-drbg": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
diff --git a/package.json b/package.json
index f45d4e7..2bb2500 100644
--- a/package.json
+++ b/package.json
@@ -10,7 +10,6 @@
"bluebird": "^3.7.2",
"compressorjs": "^1.0.6",
"formik": "^2.1.5",
- "history": "^5.0.0",
"lodash": "^4.17.15",
"notistack": "^0.9.17",
"react": "^16.13.1",
diff --git a/src/components/AttachLink/AttachLink.tsx b/src/components/AttachLink/AttachLink.tsx
index 742ba65..7c32635 100644
--- a/src/components/AttachLink/AttachLink.tsx
+++ b/src/components/AttachLink/AttachLink.tsx
@@ -21,7 +21,7 @@ const AttachLink: React.FC<PropTypes> = ({ callback, children }) => {
color="primary"
startIcon={<LinkIcon />}
>
- Attach a link
+ Link
</Button>
);
diff --git a/src/components/Message/Message.tsx b/src/components/Message/Message.tsx
index f568552..e5191ed 100644
--- a/src/components/Message/Message.tsx
+++ b/src/components/Message/Message.tsx
@@ -6,6 +6,7 @@ import { makeStyles } from '@material-ui/core/styles';
interface PropTypes {
tagline?: string;
message?: string;
+ noMargin?: boolean;
}
const useStyles = makeStyles(theme => ({
@@ -13,7 +14,9 @@ const useStyles = makeStyles(theme => ({
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
- alignItems: 'center',
+ alignItems: 'center'
+ },
+ margin: {
marginTop: theme.spacing(6)
},
content: {
@@ -21,11 +24,11 @@ const useStyles = makeStyles(theme => ({
}
}));
-const Message: React.FC<PropTypes> = React.memo(({ tagline, message, children }) => {
+const Message: React.FC<PropTypes> = React.memo(({ tagline, message, noMargin, children }) => {
const classes = useStyles();
return (
- <div className={classes.root}>
+ <div className={`${classes.root} ${!noMargin && classes.margin}`}>
<div className={classes.content}>
{children}
</div>
diff --git a/src/components/ModalScreen/ModalScreen.tsx b/src/components/ModalScreen/ModalScreen.tsx
index 81e5c5a..c6f0565 100644
--- a/src/components/ModalScreen/ModalScreen.tsx
+++ b/src/components/ModalScreen/ModalScreen.tsx
@@ -12,11 +12,14 @@ import {
useTheme
} from '@material-ui/core';
import { makeStyles } from '@material-ui/core/styles';
-import CloseIcon from '@material-ui/icons/Close';
import { TransitionProps } from '@material-ui/core/transitions';
+import CloseIcon from '@material-ui/icons/Close';
interface PropTypes {
title: string;
+ actionIcon?: JSX.Element;
+ handleAction?: () => void;
+ isActionDisabled?: boolean;
}
const useStyles = makeStyles(theme => ({
@@ -24,7 +27,7 @@ const useStyles = makeStyles(theme => ({
backgroundColor: theme.palette.background.default
},
content: {
- padding: theme.spacing(3, 0, 0, 0)
+ padding: theme.spacing(6, 0)
},
toolbar: {
display: 'flex',
@@ -37,7 +40,7 @@ const Transition = React.forwardRef((
ref: React.Ref<unknown>
) => <Slide direction="left" ref={ref} {...props} />);
-const ModalScreen: React.FC<PropTypes> = ({ title, children }) => {
+const ModalScreen: React.FC<PropTypes> = ({ title, actionIcon, handleAction, isActionDisabled, children }) => {
const [isOpen, setIsOpen] = useState<boolean>(true);
const classes = useStyles();
const theme = useTheme();
@@ -47,13 +50,20 @@ const ModalScreen: React.FC<PropTypes> = ({ title, children }) => {
const handleClose = useCallback(() => setIsOpen(false), [setIsOpen]);
const onExited = useCallback(() => history.goBack(), [history]);
+ const handleClickAction = useCallback(async () => {
+ if (handleAction) await handleAction();
+ return handleClose();
+ }, [handleAction, handleClose]);
+
return (
<Dialog
open={isOpen}
+ onClose={handleClose}
onExited={onExited}
TransitionComponent={Transition}
PaperProps={{ className: classes.root }}
fullScreen={isMobile}
+ maxWidth="md"
fullWidth
>
<AppBar position="static">
@@ -64,8 +74,8 @@ const ModalScreen: React.FC<PropTypes> = ({ title, children }) => {
<Typography variant="h6">
{ title }
</Typography>
- <IconButton style={{ opacity: 0, pointerEvents: 'none' }}>
- <CloseIcon />
+ <IconButton onClick={handleClickAction} disabled={isActionDisabled}>
+ { actionIcon }
</IconButton>
</Toolbar>
</AppBar>
diff --git a/src/containers/Page/Page.tsx b/src/containers/Page/Page.tsx
index b7e1938..e60f7da 100644
--- a/src/containers/Page/Page.tsx
+++ b/src/containers/Page/Page.tsx
@@ -10,10 +10,6 @@ import DynoWaiter from './DynoWaiter';
import Loading from '../../components/Loading/Loading';
import EmptyState from '../../components/EmptyState/EmptyState';
-interface HistoryChange {
- state?: LocationState | null;
-}
-
const useStyles = makeStyles(theme => ({
root: {
[theme.breakpoints.down('sm')]: {
@@ -32,10 +28,10 @@ const ErrorFallback: React.FC = () => (
const Page: React.FC = () => {
const classes = useStyles();
const theme = useTheme();
- const history = useHistory();
+ const history = useHistory<LocationState>();
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
- useEffect(() => history.listen((update: HistoryChange) => {
+ useEffect(() => history.listen(update => {
if (!update.state?.background) window.scrollTo(0, 0);
}), [history]);
diff --git a/src/containers/Page/Router.tsx b/src/containers/Page/Router.tsx
index 7c3a418..7c74e9a 100644
--- a/src/containers/Page/Router.tsx
+++ b/src/containers/Page/Router.tsx
@@ -12,7 +12,7 @@ const Home = React.lazy(() => import('../Home/Home'));
const Notifications = React.lazy(() => import('../Notifications/Notifications'));
export interface LocationState {
- background?: Location;
+ background: Location;
}
const Router: React.FC = React.memo(() => {
diff --git a/src/containers/PollCreation/ImageInput.tsx b/src/containers/PollCreation/ImageInput.tsx
index e807865..181294e 100644
--- a/src/containers/PollCreation/ImageInput.tsx
+++ b/src/containers/PollCreation/ImageInput.tsx
@@ -17,13 +17,33 @@ interface PropTypes {
progress?: number;
}
-const useStyles = makeStyles({
+const useStyles = makeStyles(theme => ({
root: {
+ width: '50%',
+ display: 'flex'
+ },
+ mediaRoot: {
+ display: 'flex'
+ },
+ uploadRoot: {
+ flex: 1,
+ display: 'flex',
+ [theme.breakpoints.up('md')]: {
+ padding: theme.spacing(4)
+ },
+ [theme.breakpoints.down('sm')]: {
+ padding: theme.spacing(8, 1)
+ }
+ },
+ outline: {
+ padding: theme.spacing(2),
+ flex: 1,
+ border: '2px dashed gray',
+ borderRadius: theme.spacing(1),
display: 'flex',
justifyContent: 'center',
flexDirection: 'column',
- alignItems: 'center',
- width: '50%'
+ alignItems: 'center'
},
clearIcon: {
opacity: '.5',
@@ -48,7 +68,7 @@ const useStyles = makeStyles({
icon: {
color: 'white'
}
-});
+}));
const ImageInput: React.FC<PropTypes> = ({ callback, progress }) => {
@@ -69,15 +89,17 @@ const ImageInput: React.FC<PropTypes> = ({ callback, progress }) => {
};
const Upload = (
- <div className={classes.root}>
- <FileUpload callback={childrenCallback} />
- <Typography variant="h6"> or </Typography>
- <AttachLink callback={childrenCallback} />
+ <div className={classes.uploadRoot}>
+ <div className={classes.outline}>
+ <FileUpload callback={childrenCallback} />
+ <Typography variant="h6"> or </Typography>
+ <AttachLink callback={childrenCallback} />
+ </div>
</div>
);
const Media = (
- <CardActionArea onClick={handleClear} className={classes.root} disabled={Boolean(progress)}>
+ <CardActionArea onClick={handleClear} className={classes.mediaRoot} disabled={Boolean(progress)}>
<BackgroundImage src={url} />
<div className={`${classes.overlay} ${progress === 100 && classes.invisible}`}>
{
@@ -91,7 +113,11 @@ const ImageInput: React.FC<PropTypes> = ({ callback, progress }) => {
</CardActionArea>
);
- return url ? Media : Upload;
+ return (
+ <div className={classes.root}>
+ {url ? Media : Upload}
+ </div>
+ );
};
export default ImageInput;
diff --git a/src/containers/PollCreation/PollCreation.tsx b/src/containers/PollCreation/PollCreation.tsx
index b7ee00a..68f41d2 100644
--- a/src/containers/PollCreation/PollCreation.tsx
+++ b/src/containers/PollCreation/PollCreation.tsx
@@ -1,21 +1,17 @@
import React from 'react';
import Bluebird from 'bluebird';
-import { useHistory } from 'react-router-dom';
import { makeStyles } from '@material-ui/core/styles';
-import {
- Button,
- Card,
- Container,
- LinearProgress
-} from '@material-ui/core';
+import { Card, Container, LinearProgress } from '@material-ui/core';
+import SendIcon from '@material-ui/icons/Send';
import { useSnackbar } from 'notistack';
import useS3Preupload from './useS3Preupload';
import ImageInput from './ImageInput';
import ModalScreen from '../../components/ModalScreen/ModalScreen';
+import Message from '../../components/Message/Message';
import UserStrip from '../../components/UserStrip/UserStrip';
import { post } from '../../requests';
-import { useFeed } from '../../hooks/APIClient';
+import { useFeed, useProfile } from '../../hooks/APIClient';
import { useAuth } from '../../hooks/useAuth';
@@ -29,10 +25,10 @@ const useStyles = makeStyles(theme => ({
const PollCreation: React.FC = () => {
const classes = useStyles();
- const history = useHistory();
const { user } = useAuth();
const { enqueueSnackbar } = useSnackbar();
const { mutate: updateFeed } = useFeed();
+ const { mutate: updateProfile } = useProfile(user?.username || '');
const {
file: left,
setFile: setLeft,
@@ -46,7 +42,7 @@ const PollCreation: React.FC = () => {
progress: rightProgress
} = useS3Preupload();
- const handleClick = async () => {
+ const handleSubmit = async () => {
try {
const [leftUrl, rightUrl] = await Bluebird.all([resolveLeft(), resolveRight()]);
@@ -55,20 +51,23 @@ const PollCreation: React.FC = () => {
right: { url: rightUrl }
};
- history.push('/feed');
-
post('/polls/', { contents }).then(() => {
updateFeed();
+ updateProfile();
enqueueSnackbar('Your poll has been successfully created!', { variant: 'success' });
});
} catch (error) {
enqueueSnackbar('Failed to create a poll. Please, try again.', { variant: 'error' });
- history.push('/feed');
}
};
return (
- <ModalScreen title="Create a poll">
+ <ModalScreen
+ title="Create a poll"
+ actionIcon={<SendIcon />}
+ handleAction={handleSubmit}
+ isActionDisabled={!(left && right) || leftProgress > 0 || rightProgress > 0}
+ >
<Container maxWidth="sm" disableGutters>
<Card elevation={3}>
{user && <UserStrip user={user} info="" />}
@@ -76,22 +75,17 @@ const PollCreation: React.FC = () => {
<ImageInput callback={setLeft} progress={leftProgress} />
<ImageInput callback={setRight} progress={rightProgress} />
</div>
- {
- leftProgress || rightProgress
- ? <LinearProgress color="primary" />
- : (
- <Button
- color="primary"
- disabled={!(left && right)}
- variant="contained"
- onClick={handleClick}
- fullWidth
- >
- Submit
- </Button>
- )
- }
</Card>
+ {(leftProgress > 0 || rightProgress > 0) && (
+ <>
+ <LinearProgress color="primary" />
+ <Message
+ tagline="You can close this window now"
+ message="We will upload your images in the background."
+ noMargin
+ />
+ </>
+ )}
</Container>
</ModalScreen>
);
diff --git a/src/hooks/APIClient.ts b/src/hooks/APIClient.ts
index cf5d247..68413b0 100644
--- a/src/hooks/APIClient.ts
+++ b/src/hooks/APIClient.ts
@@ -13,8 +13,8 @@ export const useUser = (username: string | null): Response<User> => {
);
};
-export const useProfile = (id: string): Response<Poll[]> => {
- return useSWR(id && `/profiles/${id}`, fetcher);
+export const useProfile = (username: string): Response<Poll[]> => {
+ return useSWR(username && `/profiles/${username}`, fetcher);
};
export const useFeed = (): Response<Poll[]> => {