From 15ae933a18c2fbd6c092e3cd95445678247621c6 Mon Sep 17 00:00:00 2001 From: Fernando Date: Thu, 1 Apr 2021 17:47:15 -0300 Subject: [PATCH] (Feature) - v3 Decoded Tx - Generic Modal (#2054) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Agustín Longoni Co-authored-by: Daniel Sanchez --- src/components/App/index.tsx | 8 +- src/components/Modal/index.stories.tsx | 174 +++++++++++ src/components/Modal/index.tsx | 290 +++++++++++++++--- .../CreateEditEntryModal/index.tsx | 2 +- .../AddressBook/CreateEditEntryModal/style.ts | 3 - .../AddressBook/DeleteEntryModal/index.tsx | 2 +- .../AddressBook/DeleteEntryModal/style.ts | 3 - .../components/Balances/SendModal/index.tsx | 11 +- src/routes/safe/components/Balances/index.tsx | 4 +- src/routes/safe/components/Balances/style.ts | 6 - src/routes/safe/components/Layout/style.ts | 1 + .../Settings/Advanced/RemoveModuleModal.tsx | 2 +- .../components/Settings/Advanced/style.ts | 5 - .../ManageOwners/AddOwnerModal/index.tsx | 13 +- .../ManageOwners/EditOwnerModal/index.tsx | 2 +- .../ManageOwners/EditOwnerModal/style.ts | 3 - .../ManageOwners/RemoveOwnerModal/index.tsx | 13 +- .../ManageOwners/ReplaceOwnerModal/index.tsx | 13 +- .../Settings/RemoveSafeModal/index.tsx | 2 +- .../Settings/RemoveSafeModal/style.ts | 5 - .../Settings/SpendingLimit/Modal/index.tsx | 102 ------ .../SpendingLimit/NewLimitModal/Create.tsx | 43 +-- .../SpendingLimit/NewLimitModal/Review.tsx | 46 +-- .../SpendingLimit/NewLimitModal/index.tsx | 2 +- .../SpendingLimit/RemoveLimitModal.tsx | 49 ++- .../Settings/SpendingLimit/style.ts | 4 - 26 files changed, 495 insertions(+), 313 deletions(-) create mode 100644 src/components/Modal/index.stories.tsx delete mode 100644 src/routes/safe/components/Settings/SpendingLimit/Modal/index.tsx diff --git a/src/components/App/index.tsx b/src/components/App/index.tsx index ae64a97d..158725fe 100644 --- a/src/components/App/index.tsx +++ b/src/components/App/index.tsx @@ -50,12 +50,6 @@ const notificationStyles = { info: { background: '#fff', }, - receiveModal: { - height: 'auto', - maxWidth: 'calc(100% - 30px)', - minHeight: '544px', - overflow: 'hidden', - }, } const Frame = styled.div` @@ -149,7 +143,7 @@ const App: React.FC = ({ children }) => { description="Receive Tokens Form" handleClose={onReceiveHide} open={safeActionsState.showReceive} - paperClassName={classes.receiveModal} + paperClassName="receive-modal" title="Receive Tokens" > diff --git a/src/components/Modal/index.stories.tsx b/src/components/Modal/index.stories.tsx new file mode 100644 index 00000000..df2fb808 --- /dev/null +++ b/src/components/Modal/index.stories.tsx @@ -0,0 +1,174 @@ +import { Text } from '@gnosis.pm/safe-react-components' +import React, { ReactElement, useState } from 'react' + +import TextField from 'src/components/forms/TextField' +import GnoField from 'src/components/forms/Field' +import GnoForm from 'src/components/forms/GnoForm' +import { required } from 'src/components/forms/validator' + +import { Modal } from '.' + +export default { + title: 'Modal', + component: Modal, + parameters: { + children: 'The body of the modal or the whole modal being composed by `Modal.Header` and `Modal.Footer` components', + title: 'The title, useful for screen readers', + description: 'A description, useful for screen readers', + handleClose: + 'A callback which will be called when an action to close the modal is triggered (Esc, clicking outside, etc)', + open: 'If `true`, the modal will be displayed. Hidden otherwise.', + }, + compositionElements: [ + { + title: 'Modal.Header', + component: , + parameters: { + title: 'The title that will be displayed in the modal', + titleNote: 'An annotation for the title, like "1 of 2"', + onClose: 'Callback to be called when attempt to close the modal', + }, + compositionElements: [ + { + title: 'Modal.Header.Title', + component: {}, + description: 'safe-react-component exposed with a few styles added to personalize the modal header', + }, + ], + }, + { + title: 'Modal.Header', + component: {}, + parameters: { + children: 'whatever is required to be rendered in the footer. Usually buttons.', + noPadding: 'a flag that will set padding to 0 (zero) in case it is needed', + }, + }, + { + title: 'Modal.Footer', + component: {}, + parameters: { + children: 'whatever is required to be rendered in the footer. Usually buttons.', + }, + compositionElements: [ + { + title: 'Modal.Footer.Buttons', + component: , + description: 'standard two buttons wrapped implementation. One "Cancel" and one "Submit" button.', + }, + ], + }, + ], +} + +const SimpleFormModal = ({ title, description, handleClose, handleSubmit, isOpen, children }) => ( + + {/* header */} + + {title} + + + + {() => ( + <> + {/* body */} + {children} + + {/* footer */} + + + + + )} + + +) + +const Username = () => ( + +) + +export const FormModal = (): ReactElement => { + const [isOpen, setIsOpen] = useState(false) + + const handleClose = () => { + setIsOpen(false) + console.log('modal closed') + } + + const handleSubmit = (values) => { + alert(JSON.stringify(values, null, 2)) + console.log('form submitted', values) + handleClose() + } + + return ( +
+ + {/* Modal with Form */} + + {/* Form Fields */} + + +
+ ) +} + +export const RemoveSomething = (): ReactElement => { + const [isOpen, setIsOpen] = useState(false) + const title = 'Remove Something' + + const handleClose = () => { + setIsOpen(false) + console.log('modal closed') + } + + const handleSubmit = () => { + alert('Something was removed') + handleClose() + } + + return ( +
+ + {/* Modal */} + + {/* Header */} + + {title} + + + {/* Body */} + + You are about to remove something + + + {/* Footer */} + + + + +
+ ) +} diff --git a/src/components/Modal/index.tsx b/src/components/Modal/index.tsx index d9a2ea46..5a6dcc33 100644 --- a/src/components/Modal/index.tsx +++ b/src/components/Modal/index.tsx @@ -1,69 +1,267 @@ -import Modal from '@material-ui/core/Modal' -import { makeStyles, createStyles } from '@material-ui/core/styles' +import { Button, Icon, theme, Title as TitleSRC } from '@gnosis.pm/safe-react-components' +import { ButtonProps as ButtonPropsMUI, Modal as ModalMUI } from '@material-ui/core' import cn from 'classnames' -import React, { ReactElement, ReactNode } from 'react' +import React, { ReactElement, ReactNode, ReactNodeArray } from 'react' +import styled from 'styled-components' -import { sm } from 'src/theme/variables' +type Theme = typeof theme -const useStyles = makeStyles( - createStyles({ - root: { - alignItems: 'center', - flexDirection: 'column', - display: 'flex', - overflowY: 'scroll', - }, - paper: { - position: 'relative', - top: '68px', - width: '500px', - borderRadius: sm, - backgroundColor: '#ffffff', - boxShadow: '0 0 5px 0 rgba(74, 85, 121, 0.5)', - '&:focus': { - outline: 'none', - }, - display: 'flex', - flexDirection: 'column', - }, - }), -) +const ModalStyled = styled(ModalMUI)` + & { + align-items: center; + flex-direction: column; + display: flex; + overflow-y: scroll; + } + + .overlay { + background-color: rgba(232, 231, 230, 0.75) !important; + } + + .paper { + position: relative; + top: 68px; + width: 500px; + border-radius: 8px; + background-color: #ffffff; + box-shadow: 1px 2px 10px 0 rgba(40, 54, 61, 0.18); + display: flex; + flex-direction: column; + + &:focus { + outline: none; + } + + // TODO: replace class-based styles by params + &.receive-modal { + height: auto; + max-width: calc(100% - 130px); + min-height: 544px; + overflow: hidden; + } + + &.bigger-modal-window { + width: 775px; + height: auto; + } + + &.smaller-modal-window { + height: auto; + } + + &.modal { + height: auto; + max-width: calc(100% - 130px); + } + } +` interface GnoModalProps { children: ReactNode description: string // type copied from Material-UI Modal's `close` prop - handleClose?: { - bivarianceHack(event: Record, reason: 'backdropClick' | 'escapeKeyDown'): void - }['bivarianceHack'] - modalClassName?: string + handleClose?: (event: Record, reason: 'backdropClick' | 'escapeKeyDown') => void open: boolean paperClassName?: string title: string } -const GnoModal = ({ - children, - description, - handleClose, - modalClassName, - open, - paperClassName, - title, -}: GnoModalProps): ReactElement => { - const classes = useStyles() - +const GnoModal = ({ children, description, handleClose, open, paperClassName, title }: GnoModalProps): ReactElement => { return ( - -
{children}
-
+
{children}
+ ) } export default GnoModal + +/*****************/ +/* Generic Modal */ +/*****************/ + +/*** Header ***/ +const HeaderSection = styled.div` + display: flex; + padding: 24px 18px 24px 24px; + border-bottom: 2px solid ${({ theme }) => theme.colors.separator}; + + h5 { + color: ${({ theme }) => theme.colors.text}; + } + + .close-button { + align-self: flex-end; + background: none; + border: none; + padding: 5px; + width: 26px; + height: 26px; + + span { + margin-right: 0; + } + + :hover { + background: ${({ theme }) => theme.colors.separator}; + border-radius: 16px; + cursor: pointer; + } + } +` + +const TitleStyled = styled(TitleSRC)` + display: flex; + align-items: center; + flex-basis: 100%; + + .image, + img { + width: 20px; + margin-right: 10px; + } + + .note, + span { + margin-left: 12px; + } +` + +interface TitleProps { + children: string | ReactNode + size?: keyof Theme['title']['size'] + withoutMargin?: boolean + strong?: boolean +} + +const Title = ({ children, ...props }: TitleProps): ReactElement => ( + + {children} + +) + +interface HeaderProps { + children?: ReactNode + onClose?: (event: any) => void +} + +const Header = ({ children, onClose }: HeaderProps): ReactElement => { + return ( + + {children} + + {onClose && ( + + )} + + ) +} + +Header.Title = Title + +/*** Body ***/ +const BodySection = styled.div<{ withoutPadding: BodyProps['withoutPadding'] }>` + padding: ${({ withoutPadding }) => (withoutPadding ? 0 : '24px')}; +` + +interface BodyProps { + children: ReactNode | ReactNodeArray + withoutPadding?: boolean +} + +const Body = ({ children, withoutPadding = false }: BodyProps): ReactElement => ( + + {children} + +) + +/*** Footer ***/ +const FooterSection = styled.div` + display: flex; + justify-content: center; + border-top: 2px solid ${({ theme }) => theme.colors.separator}; + padding: 24px; +` + +const ButtonStyled = styled(Button)` + &.MuiButtonBase-root { + margin: 0 10px; + } +` + +type CustomButtonMUIProps = Omit & { + to?: string + component?: ReactNode +} + +interface ButtonProps extends CustomButtonMUIProps { + text?: string + size?: keyof Theme['buttons']['size'] + color?: 'primary' | 'secondary' | 'error' + variant?: 'bordered' | 'contained' | 'outlined' +} + +interface ButtonsProps { + cancelButtonProps?: ButtonProps + confirmButtonProps?: ButtonProps +} + +const Buttons = ({ cancelButtonProps = {}, confirmButtonProps = {} }: ButtonsProps): ReactElement => { + const { text: cancelText = 'Cancel' } = cancelButtonProps + const { text: confirmText = 'Submit' } = confirmButtonProps + + return ( + <> + + {cancelText} + + + {confirmText} + + + ) +} + +interface FooterProps { + children: ReactNode | ReactNodeArray +} + +const Footer = ({ children }: FooterProps): ReactElement => ( + {children} +) + +Footer.Buttons = Buttons + +interface ModalProps { + children: ReactNode + description: string + handleClose: () => void + open: boolean + title: string +} + +export const Modal = ({ children, ...props }: ModalProps): ReactElement => { + return ( + + {children} + + ) +} + +Modal.Header = Header +Modal.Body = Body +Modal.Footer = Footer diff --git a/src/routes/safe/components/AddressBook/CreateEditEntryModal/index.tsx b/src/routes/safe/components/AddressBook/CreateEditEntryModal/index.tsx index bb7aa3e8..cc37955f 100644 --- a/src/routes/safe/components/AddressBook/CreateEditEntryModal/index.tsx +++ b/src/routes/safe/components/AddressBook/CreateEditEntryModal/index.tsx @@ -67,7 +67,7 @@ export const CreateEditEntryModal = ({ description={isNew ? 'Create new addressBook entry' : 'Edit addressBook entry'} handleClose={onClose} open={isOpen} - paperClassName={classes.smallerModalWindow} + paperClassName="smaller-modal-window" title={isNew ? 'Create new entry' : 'Edit entry'} > diff --git a/src/routes/safe/components/AddressBook/CreateEditEntryModal/style.ts b/src/routes/safe/components/AddressBook/CreateEditEntryModal/style.ts index 839697a1..8aca604c 100644 --- a/src/routes/safe/components/AddressBook/CreateEditEntryModal/style.ts +++ b/src/routes/safe/components/AddressBook/CreateEditEntryModal/style.ts @@ -23,8 +23,5 @@ export const useStyles = makeStyles( height: '84px', justifyContent: 'center', }, - smallerModalWindow: { - height: 'auto', - }, }), ) diff --git a/src/routes/safe/components/AddressBook/DeleteEntryModal/index.tsx b/src/routes/safe/components/AddressBook/DeleteEntryModal/index.tsx index 9a1432a7..91390839 100644 --- a/src/routes/safe/components/AddressBook/DeleteEntryModal/index.tsx +++ b/src/routes/safe/components/AddressBook/DeleteEntryModal/index.tsx @@ -25,7 +25,7 @@ const DeleteEntryModalComponent = ({ classes, deleteEntryModalHandler, entryToDe description="Delete entry" handleClose={onClose} open={isOpen} - paperClassName={classes.smallerModalWindow} + paperClassName="smaller-modal-window" title="Delete entry" > diff --git a/src/routes/safe/components/AddressBook/DeleteEntryModal/style.ts b/src/routes/safe/components/AddressBook/DeleteEntryModal/style.ts index 3ea5fab9..4952235f 100644 --- a/src/routes/safe/components/AddressBook/DeleteEntryModal/style.ts +++ b/src/routes/safe/components/AddressBook/DeleteEntryModal/style.ts @@ -27,7 +27,4 @@ export const styles = () => ({ buttonCancel: { color: '#008c73', }, - smallerModalWindow: { - height: 'auto', - }, }) diff --git a/src/routes/safe/components/Balances/SendModal/index.tsx b/src/routes/safe/components/Balances/SendModal/index.tsx index 7623d9fa..c90f1690 100644 --- a/src/routes/safe/components/Balances/SendModal/index.tsx +++ b/src/routes/safe/components/Balances/SendModal/index.tsx @@ -1,6 +1,5 @@ import CircularProgress from '@material-ui/core/CircularProgress' import { makeStyles } from '@material-ui/core/styles' -import cn from 'classnames' import React, { Suspense, useEffect, useState } from 'react' import Modal from 'src/components/Modal' @@ -32,12 +31,6 @@ const SendCustomTx = React.lazy(() => import('./screens/ContractInteraction/Send const ReviewCustomTx = React.lazy(() => import('./screens/ContractInteraction/ReviewCustomTx')) const useStyles = makeStyles({ - scalableModalWindow: { - height: 'auto', - }, - scalableStaticModalWindow: { - height: 'auto', - }, loaderStyle: { height: '500px', width: '100%', @@ -86,8 +79,6 @@ const SendModal = ({ setTx({}) }, [activeScreenType, isOpen]) - const scalableModalSize = activeScreen === 'chooseTxType' - const handleTxCreation = (txInfo: SendCollectibleTxInfo) => { setActiveScreen('sendFundsReviewTx') setTx(txInfo) @@ -117,7 +108,7 @@ const SendModal = ({ description="Send Tokens Form" handleClose={onClose} open={isOpen} - paperClassName={cn(scalableModalSize ? classes.scalableStaticModalWindow : classes.scalableModalWindow)} + paperClassName="smaller-modal-window" title="Send Tokens" > { })) } - const { assetDivider, assetTab, assetTabActive, assetTabs, controls, receiveModal, tokenControls } = classes + const { assetDivider, assetTab, assetTabActive, assetTabs, controls, tokenControls } = classes const { erc721Enabled, sendFunds, showReceive } = state return ( @@ -174,7 +174,7 @@ const Balances = (): React.ReactElement => { description="Receive Tokens Form" handleClose={() => onHide('Receive')} open={showReceive} - paperClassName={receiveModal} + paperClassName="receive-modal" title="Receive Tokens" > onHide('Receive')} /> diff --git a/src/routes/safe/components/Balances/style.ts b/src/routes/safe/components/Balances/style.ts index bcdaf782..2f408901 100644 --- a/src/routes/safe/components/Balances/style.ts +++ b/src/routes/safe/components/Balances/style.ts @@ -58,12 +58,6 @@ export const styles = createStyles({ marginLeft: '0', }, }, - receiveModal: { - height: 'auto', - maxWidth: 'calc(100% - 30px)', - minHeight: '544px', - overflow: 'hidden', - }, send: { width: '75px', minWidth: '75px', diff --git a/src/routes/safe/components/Layout/style.ts b/src/routes/safe/components/Layout/style.ts index ed951783..71f6b493 100644 --- a/src/routes/safe/components/Layout/style.ts +++ b/src/routes/safe/components/Layout/style.ts @@ -1,3 +1,4 @@ +// TODO: remove this file. It's no longer used import { screenSm, sm } from 'src/theme/variables' import { createStyles } from '@material-ui/core' diff --git a/src/routes/safe/components/Settings/Advanced/RemoveModuleModal.tsx b/src/routes/safe/components/Settings/Advanced/RemoveModuleModal.tsx index 042f47d3..ca38680a 100644 --- a/src/routes/safe/components/Settings/Advanced/RemoveModuleModal.tsx +++ b/src/routes/safe/components/Settings/Advanced/RemoveModuleModal.tsx @@ -122,7 +122,7 @@ export const RemoveModuleModal = ({ onClose, selectedModulePair }: RemoveModuleM diff --git a/src/routes/safe/components/Settings/Advanced/style.ts b/src/routes/safe/components/Settings/Advanced/style.ts index 69925f4f..7cfc93d1 100644 --- a/src/routes/safe/components/Settings/Advanced/style.ts +++ b/src/routes/safe/components/Settings/Advanced/style.ts @@ -101,11 +101,6 @@ export const styles = createStyles({ cursor: 'pointer', }, }, - modal: { - height: 'auto', - maxWidth: 'calc(100% - 30px)', - overflow: 'hidden', - }, gasCostsContainer: { backgroundColor: background, padding: `0 ${lg}`, diff --git a/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/index.tsx b/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/index.tsx index 864e1918..e376e73b 100644 --- a/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/index.tsx +++ b/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/index.tsx @@ -1,4 +1,3 @@ -import { createStyles, makeStyles } from '@material-ui/core/styles' import React, { useEffect, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' @@ -18,15 +17,6 @@ import { OwnerForm } from './screens/OwnerForm' import { ReviewAddOwner } from './screens/Review' import { ThresholdForm } from './screens/ThresholdForm' -const styles = createStyles({ - biggerModalWindow: { - width: '775px', - height: 'auto', - }, -}) - -const useStyles = makeStyles(styles) - export type OwnerValues = { ownerAddress: string ownerName: string @@ -66,7 +56,6 @@ type Props = { } export const AddOwnerModal = ({ isOpen, onClose }: Props): React.ReactElement => { - const classes = useStyles() const [activeScreen, setActiveScreen] = useState('selectOwner') const [values, setValues] = useState({ ownerName: '', ownerAddress: '', threshold: '' }) const dispatch = useDispatch() @@ -123,7 +112,7 @@ export const AddOwnerModal = ({ isOpen, onClose }: Props): React.ReactElement => description="Add owner to Safe" handleClose={onClose} open={isOpen} - paperClassName={classes.biggerModalWindow} + paperClassName="bigger-modal-window" title="Add owner to Safe" > <> diff --git a/src/routes/safe/components/Settings/ManageOwners/EditOwnerModal/index.tsx b/src/routes/safe/components/Settings/ManageOwners/EditOwnerModal/index.tsx index 914da3c2..d213c512 100644 --- a/src/routes/safe/components/Settings/ManageOwners/EditOwnerModal/index.tsx +++ b/src/routes/safe/components/Settings/ManageOwners/EditOwnerModal/index.tsx @@ -60,7 +60,7 @@ export const EditOwnerModal = ({ isOpen, onClose, ownerAddress, selectedOwnerNam description="Edit owner from Safe" handleClose={onClose} open={isOpen} - paperClassName={classes.smallerModalWindow} + paperClassName="smaller-modal-window" title="Edit owner from Safe" > diff --git a/src/routes/safe/components/Settings/ManageOwners/EditOwnerModal/style.ts b/src/routes/safe/components/Settings/ManageOwners/EditOwnerModal/style.ts index 968f88d2..73340afa 100644 --- a/src/routes/safe/components/Settings/ManageOwners/EditOwnerModal/style.ts +++ b/src/routes/safe/components/Settings/ManageOwners/EditOwnerModal/style.ts @@ -32,7 +32,4 @@ export const styles = createStyles({ cursor: 'pointer', }, }, - smallerModalWindow: { - height: 'auto', - }, }) diff --git a/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/index.tsx b/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/index.tsx index 0875cac1..add0309d 100644 --- a/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/index.tsx +++ b/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/index.tsx @@ -1,4 +1,3 @@ -import { createStyles, makeStyles } from '@material-ui/core/styles' import React, { useEffect, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' @@ -15,15 +14,6 @@ import { safeParamAddressFromStateSelector, safeThresholdSelector } from 'src/lo import { Dispatch } from 'src/logic/safe/store/actions/types.d' import { TxParameters } from 'src/routes/safe/container/hooks/useTransactionParameters' -const styles = createStyles({ - biggerModalWindow: { - width: '775px', - height: 'auto', - }, -}) - -const useStyles = makeStyles(styles) - type OwnerValues = { ownerAddress: string ownerName: string @@ -78,7 +68,6 @@ export const RemoveOwnerModal = ({ ownerAddress, ownerName, }: RemoveOwnerProps): React.ReactElement => { - const classes = useStyles() const [activeScreen, setActiveScreen] = useState('checkOwner') const [values, setValues] = useState({ ownerAddress, ownerName, threshold: '' }) const dispatch = useDispatch() @@ -120,7 +109,7 @@ export const RemoveOwnerModal = ({ description="Remove owner from Safe" handleClose={onClose} open={isOpen} - paperClassName={classes.biggerModalWindow} + paperClassName="bigger-modal-window" title="Remove owner from Safe" > <> diff --git a/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.tsx b/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.tsx index 74cd9f81..0ef75508 100644 --- a/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.tsx +++ b/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.tsx @@ -1,4 +1,3 @@ -import { createStyles, makeStyles } from '@material-ui/core/styles' import React, { useEffect, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' @@ -18,15 +17,6 @@ import { OwnerForm } from 'src/routes/safe/components/Settings/ManageOwners/Repl import { ReviewReplaceOwnerModal } from 'src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/screens/Review' import { TxParameters } from 'src/routes/safe/container/hooks/useTransactionParameters' -const styles = createStyles({ - biggerModalWindow: { - width: '775px', - height: 'auto', - }, -}) - -const useStyles = makeStyles(styles) - type OwnerValues = { newOwnerAddress: string newOwnerName: string @@ -84,7 +74,6 @@ export const ReplaceOwnerModal = ({ ownerAddress, ownerName, }: ReplaceOwnerProps): React.ReactElement => { - const classes = useStyles() const [activeScreen, setActiveScreen] = useState('checkOwner') const [values, setValues] = useState({ newOwnerAddress: '', @@ -137,7 +126,7 @@ export const ReplaceOwnerModal = ({ description="Replace owner from Safe" handleClose={onClose} open={isOpen} - paperClassName={classes.biggerModalWindow} + paperClassName="bigger-modal-window" title="Replace owner from Safe" > <> diff --git a/src/routes/safe/components/Settings/RemoveSafeModal/index.tsx b/src/routes/safe/components/Settings/RemoveSafeModal/index.tsx index 4d2f8b72..a846751d 100644 --- a/src/routes/safe/components/Settings/RemoveSafeModal/index.tsx +++ b/src/routes/safe/components/Settings/RemoveSafeModal/index.tsx @@ -68,7 +68,7 @@ export const RemoveSafeModal = ({ isOpen, onClose }: RemoveSafeModalProps): Reac description="Remove the selected Safe" handleClose={onClose} open={isOpen} - paperClassName={classes.modal} + paperClassName="modal" title="Remove Safe" > diff --git a/src/routes/safe/components/Settings/RemoveSafeModal/style.ts b/src/routes/safe/components/Settings/RemoveSafeModal/style.ts index 2d41fb79..b034d782 100644 --- a/src/routes/safe/components/Settings/RemoveSafeModal/style.ts +++ b/src/routes/safe/components/Settings/RemoveSafeModal/style.ts @@ -52,9 +52,4 @@ export const styles = createStyles({ cursor: 'pointer', }, }, - modal: { - height: 'auto', - maxWidth: 'calc(100% - 30px)', - overflow: 'hidden', - }, }) diff --git a/src/routes/safe/components/Settings/SpendingLimit/Modal/index.tsx b/src/routes/safe/components/Settings/SpendingLimit/Modal/index.tsx deleted file mode 100644 index b546f02f..00000000 --- a/src/routes/safe/components/Settings/SpendingLimit/Modal/index.tsx +++ /dev/null @@ -1,102 +0,0 @@ -import { Icon, Text, Title } from '@gnosis.pm/safe-react-components' -import React, { ReactElement, ReactNode, ReactNodeArray } from 'react' -import styled from 'styled-components' - -import GnoModal from 'src/components/Modal' -import { useStyles } from 'src/routes/safe/components/Settings/SpendingLimit/style' - -const TitleSection = styled.div` - display: flex; - justify-content: space-between; - padding: 16px 24px; - border-bottom: 2px solid ${({ theme }) => theme.colors.separator}; -` - -const StyledButton = styled.button` - background: none; - border: none; - padding: 5px; - width: 26px; - height: 26px; - - span { - margin-right: 0; - } - - :hover { - background: ${({ theme }) => theme.colors.separator}; - border-radius: 16px; - cursor: pointer; - } -` - -const FooterSection = styled.div` - border-top: 2px solid ${({ theme }) => theme.colors.separator}; - padding: 16px 24px; -` - -const FooterWrapper = styled.div` - display: flex; - justify-content: space-around; -` - -export interface TopBarProps { - title: string - titleNote?: string - onClose: () => void -} - -const TopBar = ({ title, titleNote, onClose }: TopBarProps): ReactElement => ( - - - {title} - {titleNote && ( - <> - {' '} - <Text size="lg" color="secondaryLight" as="span"> - {titleNote} - </Text> - </> - )} - - - - - - -) - -interface FooterProps { - children: ReactNodeArray -} - -const Footer = ({ children }: FooterProps): ReactElement => ( - - {children} - -) - -export interface ModalProps { - children: ReactNode - description: string - handleClose: () => void - open: boolean - title: string -} - -// TODO: this is a potential proposal for `safe-react-components` Modal -// By being able to combine components for better flexibility, this way Buttons can be part of the form body -const Modal = ({ children, ...props }: ModalProps): ReactElement => { - const classes = useStyles() - - return ( - - {children} - - ) -} - -Modal.TopBar = TopBar -Modal.Footer = Footer - -export default Modal diff --git a/src/routes/safe/components/Settings/SpendingLimit/NewLimitModal/Create.tsx b/src/routes/safe/components/Settings/SpendingLimit/NewLimitModal/Create.tsx index 2c048203..ab417c26 100644 --- a/src/routes/safe/components/Settings/SpendingLimit/NewLimitModal/Create.tsx +++ b/src/routes/safe/components/Settings/SpendingLimit/NewLimitModal/Create.tsx @@ -1,12 +1,11 @@ -import { Button } from '@gnosis.pm/safe-react-components' +import { Text } from '@gnosis.pm/safe-react-components' import { FormState, Mutator } from 'final-form' import React, { ReactElement } from 'react' import styled from 'styled-components' import GnoForm from 'src/components/forms/GnoForm' -import GnoButton from 'src/components/layout/Button' +import { Modal } from 'src/components/Modal' import { Amount, Beneficiary, ResetTime, Token } from 'src/routes/safe/components/Settings/SpendingLimit/FormFields' -import Modal from 'src/routes/safe/components/Settings/SpendingLimit/Modal' const FormContainer = styled.div` padding: 24px 8px 24px 24px; @@ -24,14 +23,6 @@ const FormContainer = styled.div` 'resetTimeOption resetTimeOption'; ` -const YetAnotherButton = styled(GnoButton)` - &.Mui-disabled { - background-color: ${({ theme }) => theme.colors.primary}; - color: ${({ theme }) => theme.colors.white}; - opacity: 0.5; - } -` - const formMutators: Record> = { setBeneficiary: (args, state, utils) => { utils.changeValue(state, 'beneficiary', () => args[0]) @@ -55,7 +46,16 @@ const canReview = ({ const Create = ({ initialValues, onCancel, onReview }: NewSpendingLimitProps): ReactElement => { return ( <> - + + + <> + New Spending Limit + + 1 of 2 + + + + {(...args) => { @@ -69,21 +69,10 @@ const Create = ({ initialValues, onCancel, onReview }: NewSpendingLimitProps): R - - - {/* TODO: replace this with safe-react-components button. */} - {/* This is used as "submit" SRC Button does not triggers submission up until the 2nd click */} - - Review - + ) diff --git a/src/routes/safe/components/Settings/SpendingLimit/NewLimitModal/Review.tsx b/src/routes/safe/components/Settings/SpendingLimit/NewLimitModal/Review.tsx index 9d803ded..ff4feb57 100644 --- a/src/routes/safe/components/Settings/SpendingLimit/NewLimitModal/Review.tsx +++ b/src/routes/safe/components/Settings/SpendingLimit/NewLimitModal/Review.tsx @@ -1,10 +1,10 @@ -import { Button, Text } from '@gnosis.pm/safe-react-components' +import { Text } from '@gnosis.pm/safe-react-components' import React, { ReactElement, useEffect, useMemo, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' -import Block from 'src/components/layout/Block' import Col from 'src/components/layout/Col' import Row from 'src/components/layout/Row' +import { Modal } from 'src/components/Modal' import { createTransaction, CreateTransactionArgs } from 'src/logic/safe/store/actions/createTransaction' import { SafeRecordProps, SpendingLimit } from 'src/logic/safe/store/models/safe' import { @@ -22,7 +22,6 @@ import { fromTokenUnit, toTokenUnit } from 'src/logic/tokens/utils/humanReadable import { sameAddress } from 'src/logic/wallets/ethAddresses' import { RESET_TIME_OPTIONS } from 'src/routes/safe/components/Settings/SpendingLimit/FormFields/ResetTime' import { AddressInfo, ResetTimeInfo, TokenInfo } from 'src/routes/safe/components/Settings/SpendingLimit/InfoDisplay' -import Modal from 'src/routes/safe/components/Settings/SpendingLimit/Modal' import { useStyles } from 'src/routes/safe/components/Settings/SpendingLimit/style' import { safeParamAddressFromStateSelector, safeSpendingLimitsSelector } from 'src/logic/safe/store/selectors' import { TxParameters } from 'src/routes/safe/container/hooks/useTransactionParameters' @@ -242,9 +241,16 @@ export const ReviewSpendingLimits = ({ onBack, onClose, txToken, values }: Revie > {(txParameters, toggleEditMode) => ( <> - + + + New Spending Limit + + 2 of 2 + + + - + @@ -286,7 +292,7 @@ export const ReviewSpendingLimits = ({ onBack, onClose, txToken, values }: Revie isTransactionExecution={isExecution} isOffChainSignature={isOffChainSignature} /> - +
- - - + onBack({ values: {}, txToken: makeToken(), step: CREATE }), + text: 'Back', + }} + confirmButtonProps={{ + onClick: () => handleSubmit(txParameters), + disabled: + existentSpendingLimit === undefined || txEstimationExecutionStatus === EstimationStatus.LOADING, + }} + /> )} diff --git a/src/routes/safe/components/Settings/SpendingLimit/NewLimitModal/index.tsx b/src/routes/safe/components/Settings/SpendingLimit/NewLimitModal/index.tsx index 7cb5b9a5..84666696 100644 --- a/src/routes/safe/components/Settings/SpendingLimit/NewLimitModal/index.tsx +++ b/src/routes/safe/components/Settings/SpendingLimit/NewLimitModal/index.tsx @@ -2,10 +2,10 @@ import { List } from 'immutable' import React, { ReactElement, Reducer, useCallback, useReducer } from 'react' import { useSelector } from 'react-redux' +import { Modal } from 'src/components/Modal' import { makeToken, Token } from 'src/logic/tokens/store/model/token' import { sameAddress } from 'src/logic/wallets/ethAddresses' import { extendedSafeTokensSelector } from 'src/routes/safe/container/selector' -import Modal from 'src/routes/safe/components/Settings/SpendingLimit/Modal' import Create from './Create' import { ReviewSpendingLimits } from './Review' diff --git a/src/routes/safe/components/Settings/SpendingLimit/RemoveLimitModal.tsx b/src/routes/safe/components/Settings/SpendingLimit/RemoveLimitModal.tsx index 6ad0ec6e..7e9002c6 100644 --- a/src/routes/safe/components/Settings/SpendingLimit/RemoveLimitModal.tsx +++ b/src/routes/safe/components/Settings/SpendingLimit/RemoveLimitModal.tsx @@ -1,29 +1,27 @@ -import { Button } from '@gnosis.pm/safe-react-components' +import cn from 'classnames' import React, { ReactElement, useEffect, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' -import Block from 'src/components/layout/Block' import Col from 'src/components/layout/Col' +import Row from 'src/components/layout/Row' +import { Modal } from 'src/components/Modal' +import { TransactionFees } from 'src/components/TransactionsFees' +import { EstimationStatus, useEstimateTransactionGas } from 'src/logic/hooks/useEstimateTransactionGas' import useTokenInfo from 'src/logic/safe/hooks/useTokenInfo' import { createTransaction } from 'src/logic/safe/store/actions/createTransaction' import { safeParamAddressFromStateSelector } from 'src/logic/safe/store/selectors' import { TX_NOTIFICATION_TYPES } from 'src/logic/safe/transactions' import { getDeleteAllowanceTxData } from 'src/logic/safe/utils/spendingLimits' import { fromTokenUnit } from 'src/logic/tokens/utils/humanReadableValue' +import { EditableTxParameters } from 'src/routes/safe/components/Transactions/helpers/EditableTxParameters' +import { TxParametersDetail } from 'src/routes/safe/components/Transactions/helpers/TxParametersDetail' +import { TxParameters } from 'src/routes/safe/container/hooks/useTransactionParameters' import { SPENDING_LIMIT_MODULE_ADDRESS } from 'src/utils/constants' import { RESET_TIME_OPTIONS } from './FormFields/ResetTime' import { AddressInfo, ResetTimeInfo, TokenInfo } from './InfoDisplay' import { SpendingLimitTable } from './LimitsTable/dataFetcher' -import Modal from './Modal' import { useStyles } from './style' -import { EstimationStatus, useEstimateTransactionGas } from 'src/logic/hooks/useEstimateTransactionGas' -import { EditableTxParameters } from 'src/routes/safe/components/Transactions/helpers/EditableTxParameters' -import { TxParameters } from 'src/routes/safe/container/hooks/useTransactionParameters' -import { TxParametersDetail } from 'src/routes/safe/components/Transactions/helpers/TxParametersDetail' -import Row from 'src/components/layout/Row' -import { TransactionFees } from 'src/components/TransactionsFees' -import cn from 'classnames' interface RemoveSpendingLimitModalProps { onClose: () => void @@ -126,9 +124,13 @@ export const RemoveLimitModal = ({ onClose, spendingLimit, open }: RemoveSpendin {(txParameters, toggleEditMode) => { return ( <> - + + + Remove Spending Limit + + - + @@ -152,7 +154,7 @@ export const RemoveLimitModal = ({ onClose, spendingLimit, open }: RemoveSpendin isTransactionExecution={isExecution} isOffChainSignature={isOffChainSignature} /> - + - - + removeSelectedSpendingLimit(txParameters), + disabled: txEstimationExecutionStatus === EstimationStatus.LOADING, + text: 'Remove', + }} + /> ) diff --git a/src/routes/safe/components/Settings/SpendingLimit/style.ts b/src/routes/safe/components/Settings/SpendingLimit/style.ts index 0b8a9568..8df8e247 100644 --- a/src/routes/safe/components/Settings/SpendingLimit/style.ts +++ b/src/routes/safe/components/Settings/SpendingLimit/style.ts @@ -120,10 +120,6 @@ export const useStyles = makeStyles( cursor: 'pointer', }, }, - modal: { - height: 'auto', - maxWidth: 'calc(100% - 30px)', - }, amountInput: { width: '100% !important', },