diff options
author | Eugene Sokolov <eug-vs@keemail.me> | 2020-10-08 20:40:45 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-10-08 20:40:45 +0300 |
commit | bdb4d194307c9755c2083c1a11bb876abebcb6de (patch) | |
tree | 9aff25b0bd0b47127b66e4db4818468ec70719bf | |
parent | 45b4094c02301ff854b8b8017437ad9989efa117 (diff) | |
parent | 2c093ce738cb1281db04a8a3f2b6a35b3aa9b354 (diff) | |
download | which-ui-bdb4d194307c9755c2083c1a11bb876abebcb6de.tar.gz |
Merge pull request #102 from which-ecosystem/feat/modal
Modal improvements
-rw-r--r-- | package-lock.json | 8 | ||||
-rw-r--r-- | package.json | 1 | ||||
-rw-r--r-- | src/components/AttachLink/AttachLink.tsx | 2 | ||||
-rw-r--r-- | src/components/Message/Message.tsx | 9 | ||||
-rw-r--r-- | src/components/ModalScreen/ModalScreen.tsx | 20 | ||||
-rw-r--r-- | src/containers/Page/Page.tsx | 8 | ||||
-rw-r--r-- | src/containers/Page/Router.tsx | 2 | ||||
-rw-r--r-- | src/containers/PollCreation/ImageInput.tsx | 46 | ||||
-rw-r--r-- | src/containers/PollCreation/PollCreation.tsx | 52 | ||||
-rw-r--r-- | src/hooks/APIClient.ts | 4 |
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[]> => { |