mirror of
https://github.com/status-im/safe-react.git
synced 2025-02-26 08:25:14 +00:00
Merge pull request #296 from gnosis/189-cookie-banner
Feature #189: Cookie banner
This commit is contained in:
commit
2c42eb56af
30
flow-typed/npm/js-cookie_v2.x.x.js
vendored
Normal file
30
flow-typed/npm/js-cookie_v2.x.x.js
vendored
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
// flow-typed signature: a23fa96dc9c75f8931650efff45badee
|
||||||
|
// flow-typed version: c6154227d1/js-cookie_v2.x.x/flow_>=v0.104.x
|
||||||
|
|
||||||
|
declare module 'js-cookie' {
|
||||||
|
declare type CookieOptions = {
|
||||||
|
expires?: number | Date,
|
||||||
|
path?: string,
|
||||||
|
domain?: string,
|
||||||
|
secure?: boolean,
|
||||||
|
...
|
||||||
|
}
|
||||||
|
declare type ConverterFunc = (value: string, name: string) => string;
|
||||||
|
declare type ConverterObj = {
|
||||||
|
read: ConverterFunc,
|
||||||
|
write: ConverterFunc,
|
||||||
|
...
|
||||||
|
};
|
||||||
|
declare class Cookie {
|
||||||
|
defaults: CookieOptions;
|
||||||
|
set(name: string, value: mixed, options?: CookieOptions): void;
|
||||||
|
get(...args: Array<void>): { [key: string]: string, ... };
|
||||||
|
get(name: string, ...args: Array<void>): string | void;
|
||||||
|
remove(name: string, options?: CookieOptions): void;
|
||||||
|
getJSON(name: string): Object;
|
||||||
|
withConverter(converter: ConverterFunc | ConverterObj): this;
|
||||||
|
noConflict(): this;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module.exports: Cookie;
|
||||||
|
}
|
@ -49,9 +49,11 @@
|
|||||||
"history": "4.10.1",
|
"history": "4.10.1",
|
||||||
"immortal-db": "^1.0.2",
|
"immortal-db": "^1.0.2",
|
||||||
"immutable": "^4.0.0-rc.9",
|
"immutable": "^4.0.0-rc.9",
|
||||||
|
"js-cookie": "^2.2.1",
|
||||||
"material-ui-search-bar": "^1.0.0-beta.13",
|
"material-ui-search-bar": "^1.0.0-beta.13",
|
||||||
"notistack": "https://github.com/gnosis/notistack.git#v0.9.4",
|
"notistack": "https://github.com/gnosis/notistack.git#v0.9.4",
|
||||||
"optimize-css-assets-webpack-plugin": "5.0.3",
|
"optimize-css-assets-webpack-plugin": "5.0.3",
|
||||||
|
"polished": "^3.4.2",
|
||||||
"qrcode.react": "1.0.0",
|
"qrcode.react": "1.0.0",
|
||||||
"react": "16.12.0",
|
"react": "16.12.0",
|
||||||
"react-dom": "16.12.0",
|
"react-dom": "16.12.0",
|
||||||
|
169
src/components/CookiesBanner/index.jsx
Normal file
169
src/components/CookiesBanner/index.jsx
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
// @flow
|
||||||
|
import Checkbox from '@material-ui/core/Checkbox'
|
||||||
|
import Close from '@material-ui/icons/Close'
|
||||||
|
import FormControlLabel from '@material-ui/core/FormControlLabel'
|
||||||
|
import IconButton from '@material-ui/core/IconButton'
|
||||||
|
import React, { useEffect, useState } from 'react'
|
||||||
|
import { makeStyles } from '@material-ui/core/styles'
|
||||||
|
import { useDispatch, useSelector } from 'react-redux'
|
||||||
|
import Link from '~/components/layout/Link'
|
||||||
|
import Button from '~/components/layout/Button'
|
||||||
|
import { primary, mainFontFamily } from '~/theme/variables'
|
||||||
|
import type { CookiesProps } from '~/logic/cookies/model/cookie'
|
||||||
|
import { COOKIES_KEY } from '~/logic/cookies/model/cookie'
|
||||||
|
import { loadFromCookie, saveCookie } from '~/logic/cookies/utils'
|
||||||
|
import { cookieBannerOpen } from '~/logic/cookies/store/selectors'
|
||||||
|
import { openCookieBanner } from '~/logic/cookies/store/actions/openCookieBanner'
|
||||||
|
|
||||||
|
const useStyles = makeStyles({
|
||||||
|
container: {
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
bottom: '0',
|
||||||
|
boxShadow: '0 2px 4px 0 rgba(212, 212, 211, 0.59)',
|
||||||
|
boxSizing: 'border-box',
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center',
|
||||||
|
left: '0',
|
||||||
|
minHeight: '200px',
|
||||||
|
padding: '27px 15px',
|
||||||
|
position: 'fixed',
|
||||||
|
width: '100%',
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
maxWidth: '100%',
|
||||||
|
width: '830px',
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
color: primary,
|
||||||
|
fontFamily: mainFontFamily,
|
||||||
|
fontSize: '16px',
|
||||||
|
fontWeight: 'normal',
|
||||||
|
lineHeight: '1.38',
|
||||||
|
margin: '0 0 25px',
|
||||||
|
textAlign: 'center',
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
columnGap: '10px',
|
||||||
|
display: 'grid',
|
||||||
|
gridTemplateColumns: '1fr',
|
||||||
|
rowGap: '10px',
|
||||||
|
'@media (min-width: 960px)': {
|
||||||
|
gridTemplateColumns: '1fr 1fr 1fr',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
formItem: {
|
||||||
|
alignItems: 'center',
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center',
|
||||||
|
},
|
||||||
|
link: {
|
||||||
|
textDecoration: 'underline',
|
||||||
|
'&:hover': {
|
||||||
|
textDecoration: 'none',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
close: {
|
||||||
|
position: 'absolute',
|
||||||
|
right: '12px',
|
||||||
|
top: '12px',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const CookiesBanner = () => {
|
||||||
|
const classes = useStyles()
|
||||||
|
const dispatch = useDispatch()
|
||||||
|
const [localNecessary, setLocalNecessary] = useState(true)
|
||||||
|
const [localAnalytics, setLocalAnalytics] = useState(false)
|
||||||
|
const showBanner = useSelector(cookieBannerOpen)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
async function fetchCookiesFromStorage() {
|
||||||
|
const cookiesState: ?CookiesProps = await loadFromCookie(COOKIES_KEY)
|
||||||
|
if (cookiesState) {
|
||||||
|
const { acceptedNecessary, acceptedAnalytics } = cookiesState
|
||||||
|
setLocalAnalytics(acceptedAnalytics)
|
||||||
|
setLocalNecessary(acceptedNecessary)
|
||||||
|
const openBanner = acceptedNecessary === false || showBanner
|
||||||
|
dispatch(openCookieBanner(openBanner))
|
||||||
|
} else {
|
||||||
|
dispatch(openCookieBanner(true))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fetchCookiesFromStorage()
|
||||||
|
}, [showBanner])
|
||||||
|
|
||||||
|
const acceptCookiesHandler = async () => {
|
||||||
|
const newState = {
|
||||||
|
acceptedNecessary: true,
|
||||||
|
acceptedAnalytics: true,
|
||||||
|
}
|
||||||
|
await saveCookie(COOKIES_KEY, newState, 365)
|
||||||
|
dispatch(openCookieBanner(false))
|
||||||
|
}
|
||||||
|
|
||||||
|
const closeCookiesBannerHandler = async () => {
|
||||||
|
const newState = {
|
||||||
|
acceptedNecessary: true,
|
||||||
|
acceptedAnalytics: localAnalytics,
|
||||||
|
}
|
||||||
|
const expDays = localAnalytics ? 365 : 7
|
||||||
|
await saveCookie(COOKIES_KEY, newState, expDays)
|
||||||
|
dispatch(openCookieBanner(false))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return showBanner ? (
|
||||||
|
<div className={classes.container}>
|
||||||
|
<IconButton onClick={() => closeCookiesBannerHandler()} className={classes.close}><Close /></IconButton>
|
||||||
|
<div className={classes.content}>
|
||||||
|
<p className={classes.text}>
|
||||||
|
We use cookies to give you the best experience and to help improve our website. Please read our
|
||||||
|
{' '}
|
||||||
|
<Link className={classes.link} to="https://safe.gnosis.io/cookie">Cookie Policy</Link>
|
||||||
|
{' '}
|
||||||
|
for more information. By clicking "Accept all", you agree to the storing of cookies on your device
|
||||||
|
to enhance site navigation, analyze site usage and provide customer support.
|
||||||
|
</p>
|
||||||
|
<div className={classes.form}>
|
||||||
|
<div className={classes.formItem}>
|
||||||
|
<FormControlLabel
|
||||||
|
checked={localNecessary}
|
||||||
|
disabled
|
||||||
|
label="Necessary"
|
||||||
|
name="Necessary"
|
||||||
|
onChange={() => setLocalNecessary((prev) => !prev)}
|
||||||
|
value={localNecessary}
|
||||||
|
control={(
|
||||||
|
<Checkbox disabled />
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className={classes.formItem}>
|
||||||
|
<FormControlLabel
|
||||||
|
label="Analytics"
|
||||||
|
name="Analytics"
|
||||||
|
onChange={() => setLocalAnalytics((prev) => !prev)}
|
||||||
|
value={localAnalytics}
|
||||||
|
control={(
|
||||||
|
<Checkbox checked={localAnalytics} />
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className={classes.formItem}>
|
||||||
|
<Button
|
||||||
|
color="primary"
|
||||||
|
component={Link}
|
||||||
|
minWidth={180}
|
||||||
|
variant="outlined"
|
||||||
|
onClick={() => acceptCookiesHandler()}
|
||||||
|
>
|
||||||
|
Accept All
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : null
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CookiesBanner
|
@ -75,9 +75,4 @@ class Notifier extends Component<Props> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withSnackbar(
|
export default withSnackbar(connect(selector, actions)(Notifier))
|
||||||
connect(
|
|
||||||
selector,
|
|
||||||
actions,
|
|
||||||
)(Notifier),
|
|
||||||
)
|
|
||||||
|
@ -9,32 +9,34 @@ body {
|
|||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
src: local("Averta-Regular"), url(../../assets/fonts/Averta-normal.woff2) format('woff2');
|
src: local("Averta-Regular"),
|
||||||
|
url(../../assets/fonts/Averta-normal.woff2) format("woff2");
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Averta';
|
font-family: "Averta";
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
src: local("Averta-Extrabold"), url(../../assets/fonts/Averta-ExtraBold.woff2) format('woff2');
|
src: local("Averta-Extrabold"),
|
||||||
|
url(../../assets/fonts/Averta-ExtraBold.woff2) format("woff2");
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
overflow-x: hidden;
|
|
||||||
color: $fontColor;
|
|
||||||
font-family: 'Averta', monospace;
|
|
||||||
font-size: $mediumFontSize;
|
|
||||||
margin: 0;
|
|
||||||
background-color: $background;
|
|
||||||
text-rendering: geometricPrecision;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
background-color: $background;
|
||||||
|
bottom: 0;
|
||||||
|
color: $fontColor;
|
||||||
|
font-family: "Averta", monospace;
|
||||||
|
font-size: $mediumFontSize;
|
||||||
|
left: 0;
|
||||||
|
margin: 0;
|
||||||
|
overflow-x: hidden;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
text-rendering: geometricPrecision;
|
||||||
|
top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
body > div:first-child {
|
body > div:first-child {
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { makeStyles } from '@material-ui/core/styles'
|
import { makeStyles } from '@material-ui/core/styles'
|
||||||
|
import { useDispatch } from 'react-redux'
|
||||||
import Block from '~/components/layout/Block'
|
import Block from '~/components/layout/Block'
|
||||||
import Link from '~/components/layout/Link'
|
import Link from '~/components/layout/Link'
|
||||||
import { sm, primary } from '~/theme/variables'
|
import { sm, primary } from '~/theme/variables'
|
||||||
|
import { openCookieBanner } from '~/logic/cookies/store/actions/openCookieBanner'
|
||||||
|
import GnoButtonLink from '~/components/layout/ButtonLink'
|
||||||
|
|
||||||
const useStyles = makeStyles({
|
const useStyles = makeStyles({
|
||||||
container: {
|
container: {
|
||||||
@ -12,24 +15,42 @@ const useStyles = makeStyles({
|
|||||||
link: {
|
link: {
|
||||||
color: primary,
|
color: primary,
|
||||||
},
|
},
|
||||||
|
buttonLink: {
|
||||||
|
textDecoration: 'none',
|
||||||
|
color: primary,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const LegalLinks = () => {
|
type Props = {
|
||||||
|
toggleSidebar: Function,
|
||||||
|
}
|
||||||
|
|
||||||
|
const LegalLinks = (props: Props) => {
|
||||||
const classes = useStyles()
|
const classes = useStyles()
|
||||||
|
const dispatch = useDispatch()
|
||||||
|
|
||||||
|
const openCookiesHandler = () => {
|
||||||
|
dispatch(openCookieBanner(true))
|
||||||
|
props.toggleSidebar()
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Block className={classes.container} justify="space-around">
|
<Block className={classes.container} justify="space-around">
|
||||||
<Link className={classes.link} to="https://safe.gnosis.io/terms-of-use-072018.html" target="_blank">
|
<Link className={classes.link} to="https://safe.gnosis.io/terms" target="_blank">
|
||||||
Terms
|
Terms
|
||||||
</Link>
|
</Link>
|
||||||
<Link className={classes.link} to="https://safe.gnosis.io/privacy-policy-052019.html" target="_blank">
|
<Link className={classes.link} to="https://safe.gnosis.io/privacy" target="_blank">
|
||||||
Privacy
|
Privacy
|
||||||
</Link>
|
</Link>
|
||||||
<Link className={classes.link} to="https://safe.gnosis.io/licenses-092019.html" target="_blank">
|
<Link className={classes.link} to="https://safe.gnosis.io/licenses" target="_blank">
|
||||||
Licenses
|
Licenses
|
||||||
</Link>
|
</Link>
|
||||||
<Link className={classes.link} to="https://safe.gnosis.io/imprint.html" target="_blank">
|
<Link className={classes.link} to="https://safe.gnosis.io/imprint" target="_blank">
|
||||||
Imprint
|
Imprint
|
||||||
</Link>
|
</Link>
|
||||||
|
<GnoButtonLink className={classes.buttonLink} onClick={openCookiesHandler}>
|
||||||
|
Cookies
|
||||||
|
</GnoButtonLink>
|
||||||
</Block>
|
</Block>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -131,7 +131,7 @@ const Sidebar = ({
|
|||||||
setDefaultSafe={setDefaultSafeAction}
|
setDefaultSafe={setDefaultSafeAction}
|
||||||
defaultSafe={defaultSafe}
|
defaultSafe={defaultSafe}
|
||||||
/>
|
/>
|
||||||
<LegalLinks />
|
<LegalLinks toggleSidebar={toggleSidebar} />
|
||||||
</Drawer>
|
</Drawer>
|
||||||
</ClickAwayListener>
|
</ClickAwayListener>
|
||||||
{children}
|
{children}
|
||||||
|
@ -15,6 +15,7 @@ import AlertIcon from './assets/alert.svg'
|
|||||||
import CheckIcon from './assets/check.svg'
|
import CheckIcon from './assets/check.svg'
|
||||||
import ErrorIcon from './assets/error.svg'
|
import ErrorIcon from './assets/error.svg'
|
||||||
import InfoIcon from './assets/info.svg'
|
import InfoIcon from './assets/info.svg'
|
||||||
|
import CookiesBanner from '~/components/CookiesBanner'
|
||||||
import styles from './index.scss'
|
import styles from './index.scss'
|
||||||
|
|
||||||
const notificationStyles = {
|
const notificationStyles = {
|
||||||
@ -92,6 +93,7 @@ const PageFrame = ({ children, classes, currentNetwork }: Props) => {
|
|||||||
{children}
|
{children}
|
||||||
</SidebarProvider>
|
</SidebarProvider>
|
||||||
</SnackbarProvider>
|
</SnackbarProvider>
|
||||||
|
<CookiesBanner />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
12
src/index.js
12
src/index.js
@ -1,14 +1,13 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import 'babel-polyfill'
|
import 'babel-polyfill'
|
||||||
|
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import ReactDOM from 'react-dom'
|
import ReactDOM from 'react-dom'
|
||||||
import { BigNumber } from 'bignumber.js'
|
import { BigNumber } from 'bignumber.js'
|
||||||
import Root from '~/components/Root'
|
import Root from '~/components/Root'
|
||||||
import { store } from '~/store'
|
|
||||||
import loadSafesFromStorage from '~/routes/safe/store/actions/loadSafesFromStorage'
|
|
||||||
import loadActiveTokens from '~/logic/tokens/store/actions/loadActiveTokens'
|
import loadActiveTokens from '~/logic/tokens/store/actions/loadActiveTokens'
|
||||||
import loadDefaultSafe from '~/routes/safe/store/actions/loadDefaultSafe'
|
import loadDefaultSafe from '~/routes/safe/store/actions/loadDefaultSafe'
|
||||||
|
import loadSafesFromStorage from '~/routes/safe/store/actions/loadSafesFromStorage'
|
||||||
|
import { store } from '~/store'
|
||||||
|
|
||||||
BigNumber.set({ EXPONENTIAL_AT: [-7, 255] })
|
BigNumber.set({ EXPONENTIAL_AT: [-7, 255] })
|
||||||
|
|
||||||
@ -18,8 +17,13 @@ if (process.env.NODE_ENV !== 'production') {
|
|||||||
whyDidYouRender(React)
|
whyDidYouRender(React)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// $FlowFixMe
|
||||||
store.dispatch(loadActiveTokens())
|
store.dispatch(loadActiveTokens())
|
||||||
store.dispatch(loadSafesFromStorage())
|
store.dispatch(loadSafesFromStorage())
|
||||||
store.dispatch(loadDefaultSafe())
|
store.dispatch(loadDefaultSafe())
|
||||||
|
|
||||||
ReactDOM.render(<Root />, document.getElementById('root'))
|
const root = document.getElementById('root')
|
||||||
|
|
||||||
|
if (root !== null) {
|
||||||
|
ReactDOM.render(<Root />, root)
|
||||||
|
}
|
||||||
|
@ -75,7 +75,10 @@ export const deploySafeContract = async (safeAccounts: string[], numConfirmation
|
|||||||
const gasPrice = await calculateGasPrice()
|
const gasPrice = await calculateGasPrice()
|
||||||
|
|
||||||
return proxyFactoryMaster.createProxy(safeMaster.address, gnosisSafeData, {
|
return proxyFactoryMaster.createProxy(safeMaster.address, gnosisSafeData, {
|
||||||
from: userAccount, gas, gasPrice, value: 0,
|
from: userAccount,
|
||||||
|
gas,
|
||||||
|
gasPrice,
|
||||||
|
value: 0,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
12
src/logic/cookies/model/cookie.js
Normal file
12
src/logic/cookies/model/cookie.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// @flow
|
||||||
|
import type { RecordOf } from 'immutable'
|
||||||
|
|
||||||
|
export const COOKIES_KEY = 'COOKIES'
|
||||||
|
|
||||||
|
export type CookiesProps = {
|
||||||
|
acceptedNecessary: boolean,
|
||||||
|
acceptedAnalytics: boolean,
|
||||||
|
cookieBannerOpen: boolean,
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Cookie = RecordOf<CookiesProps>
|
6
src/logic/cookies/store/actions/openCookieBanner.js
Normal file
6
src/logic/cookies/store/actions/openCookieBanner.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
// @flow
|
||||||
|
import { createAction } from 'redux-actions'
|
||||||
|
|
||||||
|
export const OPEN_COOKIE_BANNER = 'OPEN_COOKIE_BANNER'
|
||||||
|
|
||||||
|
export const openCookieBanner = createAction<string, *, *>(OPEN_COOKIE_BANNER, (cookieBannerOpen: boolean) => ({ cookieBannerOpen }))
|
20
src/logic/cookies/store/reducer/cookies.js
Normal file
20
src/logic/cookies/store/reducer/cookies.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// @flow
|
||||||
|
import { Map } from 'immutable'
|
||||||
|
import { handleActions, type ActionType } from 'redux-actions'
|
||||||
|
import type { Cookie } from '~/logic/cookies/model/cookie'
|
||||||
|
import { OPEN_COOKIE_BANNER } from '~/logic/cookies/store/actions/openCookieBanner'
|
||||||
|
|
||||||
|
export const COOKIES_REDUCER_ID = 'cookies'
|
||||||
|
|
||||||
|
export type State = Map<string, Map<string, Cookie>>
|
||||||
|
|
||||||
|
export default handleActions<State, *>(
|
||||||
|
{
|
||||||
|
[OPEN_COOKIE_BANNER]: (state: State, action: ActionType<Function>): State => {
|
||||||
|
const { cookieBannerOpen } = action.payload
|
||||||
|
|
||||||
|
return state.set('cookieBannerOpen', cookieBannerOpen)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Map(),
|
||||||
|
)
|
5
src/logic/cookies/store/selectors/index.js
Normal file
5
src/logic/cookies/store/selectors/index.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
// @flow
|
||||||
|
import type { Provider } from '~/logic/wallets/store/model/provider'
|
||||||
|
import { COOKIES_REDUCER_ID } from '~/logic/cookies/store/reducer/cookies'
|
||||||
|
|
||||||
|
export const cookieBannerOpen = (state: any): Provider => state[COOKIES_REDUCER_ID].get('cookieBannerOpen')
|
29
src/logic/cookies/utils/index.js
Normal file
29
src/logic/cookies/utils/index.js
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// @flow
|
||||||
|
import Cookies from 'js-cookie'
|
||||||
|
import { getNetwork } from '~/config'
|
||||||
|
|
||||||
|
const PREFIX = `v1_${getNetwork()}`
|
||||||
|
|
||||||
|
export const loadFromCookie = async (key: string): Promise<*> => {
|
||||||
|
try {
|
||||||
|
const stringifiedValue = await Cookies.get(`${PREFIX}__${key}`)
|
||||||
|
if (stringifiedValue === null || stringifiedValue === undefined) {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
return JSON.parse(stringifiedValue)
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`Failed to load ${key} from cookies:`, err)
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const saveCookie = async (key: string, value: *, expirationDays: number): Promise<*> => {
|
||||||
|
try {
|
||||||
|
const stringifiedValue = JSON.stringify(value)
|
||||||
|
const expiration = expirationDays ? { expires: expirationDays } : undefined
|
||||||
|
await Cookies.set(`${PREFIX}__${key}`, stringifiedValue, expiration)
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`Failed to save ${key} in cookies:`, err)
|
||||||
|
}
|
||||||
|
}
|
@ -8,9 +8,7 @@ export const ENQUEUE_SNACKBAR = 'ENQUEUE_SNACKBAR'
|
|||||||
|
|
||||||
const addSnackbar = createAction<string, *>(ENQUEUE_SNACKBAR)
|
const addSnackbar = createAction<string, *>(ENQUEUE_SNACKBAR)
|
||||||
|
|
||||||
const enqueueSnackbar = (notification: NotificationProps) => (
|
const enqueueSnackbar = (notification: NotificationProps) => (dispatch: ReduxDispatch<GlobalState>) => {
|
||||||
dispatch: ReduxDispatch<GlobalState>,
|
|
||||||
) => {
|
|
||||||
const newNotification = {
|
const newNotification = {
|
||||||
...notification,
|
...notification,
|
||||||
key: new Date().getTime(),
|
key: new Date().getTime(),
|
||||||
|
@ -5,11 +5,10 @@ import { type GlobalState } from '~/store'
|
|||||||
import { NOTIFICATIONS_REDUCER_ID } from '~/logic/notifications/store/reducer/notifications'
|
import { NOTIFICATIONS_REDUCER_ID } from '~/logic/notifications/store/reducer/notifications'
|
||||||
import { type Notification } from '~/logic/notifications/store/models/notification'
|
import { type Notification } from '~/logic/notifications/store/models/notification'
|
||||||
|
|
||||||
const notificationsMapSelector = (
|
const notificationsMapSelector = (state: GlobalState): Map<string, Notification> => state[NOTIFICATIONS_REDUCER_ID]
|
||||||
state: GlobalState,
|
|
||||||
): Map<string, Notification> => state[NOTIFICATIONS_REDUCER_ID]
|
|
||||||
|
|
||||||
export const notificationsListSelector: Selector<GlobalState, {}, List<Notification>> = createSelector(
|
export const notificationsListSelector: Selector<
|
||||||
notificationsMapSelector,
|
GlobalState,
|
||||||
(notifications: Map<string, Notification>): List<Notification> => notifications.toList(),
|
{},
|
||||||
)
|
List<Notification>,
|
||||||
|
> = createSelector(notificationsMapSelector, (notifications: Map<string, Notification>): List<Notification> => notifications.toList())
|
||||||
|
@ -68,7 +68,18 @@ export const getExecutionTransaction = async (
|
|||||||
const web3 = getWeb3()
|
const web3 = getWeb3()
|
||||||
const contract = new web3.eth.Contract(GnosisSafeSol.abi, safeInstance.address)
|
const contract = new web3.eth.Contract(GnosisSafeSol.abi, safeInstance.address)
|
||||||
|
|
||||||
return contract.methods.execTransaction(to, valueInWei, data, operation, safeTxGas, baseGas, gasPrice, gasToken, refundReceiver, sigs)
|
return contract.methods.execTransaction(
|
||||||
|
to,
|
||||||
|
valueInWei,
|
||||||
|
data,
|
||||||
|
operation,
|
||||||
|
safeTxGas,
|
||||||
|
baseGas,
|
||||||
|
gasPrice,
|
||||||
|
gasToken,
|
||||||
|
refundReceiver,
|
||||||
|
sigs,
|
||||||
|
)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(`Error while creating transaction: ${err}`)
|
console.error(`Error while creating transaction: ${err}`)
|
||||||
|
|
||||||
|
@ -13,7 +13,8 @@ export const tokenListSelector: Selector<GlobalState, Map<string, Token>, List<T
|
|||||||
(tokens: Map<string, Token>) => tokens.toList(),
|
(tokens: Map<string, Token>) => tokens.toList(),
|
||||||
)
|
)
|
||||||
|
|
||||||
export const orderedTokenListSelector: Selector<GlobalState, RouterProps, List<Token>> = createSelector(
|
export const orderedTokenListSelector: Selector<
|
||||||
tokenListSelector,
|
GlobalState,
|
||||||
(tokens: List<Token>) => tokens.sortBy((token: Token) => token.get('symbol')),
|
RouterProps,
|
||||||
)
|
List<Token>,
|
||||||
|
> = createSelector(tokenListSelector, (tokens: List<Token>) => tokens.sortBy((token: Token) => token.get('symbol')))
|
||||||
|
@ -6,40 +6,25 @@ import { ETHEREUM_NETWORK_IDS, ETHEREUM_NETWORK } from '~/logic/wallets/getWeb3'
|
|||||||
|
|
||||||
const providerSelector = (state: any): Provider => state[PROVIDER_REDUCER_ID]
|
const providerSelector = (state: any): Provider => state[PROVIDER_REDUCER_ID]
|
||||||
|
|
||||||
export const userAccountSelector = createSelector(
|
export const userAccountSelector = createSelector(providerSelector, (provider: Provider) => {
|
||||||
providerSelector,
|
|
||||||
(provider: Provider) => {
|
|
||||||
const account = provider.get('account')
|
const account = provider.get('account')
|
||||||
|
|
||||||
return account || ''
|
return account || ''
|
||||||
},
|
})
|
||||||
)
|
|
||||||
|
|
||||||
export const providerNameSelector = createSelector(
|
export const providerNameSelector = createSelector(providerSelector, (provider: Provider) => {
|
||||||
providerSelector,
|
|
||||||
(provider: Provider) => {
|
|
||||||
const name = provider.get('name')
|
const name = provider.get('name')
|
||||||
|
|
||||||
return name ? name.toLowerCase() : undefined
|
return name ? name.toLowerCase() : undefined
|
||||||
},
|
})
|
||||||
)
|
|
||||||
|
|
||||||
export const networkSelector = createSelector(
|
export const networkSelector = createSelector(providerSelector, (provider: Provider) => {
|
||||||
providerSelector,
|
|
||||||
(provider: Provider) => {
|
|
||||||
const networkId = provider.get('network')
|
const networkId = provider.get('network')
|
||||||
const network = ETHEREUM_NETWORK_IDS[networkId] || ETHEREUM_NETWORK.UNKNOWN
|
const network = ETHEREUM_NETWORK_IDS[networkId] || ETHEREUM_NETWORK.UNKNOWN
|
||||||
|
|
||||||
return network
|
return network
|
||||||
},
|
})
|
||||||
)
|
|
||||||
|
|
||||||
export const loadedSelector = createSelector(
|
export const loadedSelector = createSelector(providerSelector, (provider: Provider) => provider.get('loaded'))
|
||||||
providerSelector,
|
|
||||||
(provider: Provider) => provider.get('loaded'),
|
|
||||||
)
|
|
||||||
|
|
||||||
export const availableSelector = createSelector(
|
export const availableSelector = createSelector(providerSelector, (provider: Provider) => provider.get('available'))
|
||||||
providerSelector,
|
|
||||||
(provider: Provider) => provider.get('available'),
|
|
||||||
)
|
|
||||||
|
@ -72,8 +72,8 @@ const Routes = ({ defaultSafe, location }: RoutesProps) => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect<Object, Object, ?Function, ?Object>(
|
|
||||||
// $FlowFixMe
|
// $FlowFixMe
|
||||||
|
export default connect<Object, Object, ?Function, ?Object>(
|
||||||
(state) => ({ defaultSafe: defaultSafeSelector(state) }),
|
(state) => ({ defaultSafe: defaultSafeSelector(state) }),
|
||||||
null,
|
null,
|
||||||
)(withRouter(Routes))
|
)(withRouter(Routes))
|
||||||
|
@ -55,13 +55,35 @@ const createTransaction = (
|
|||||||
try {
|
try {
|
||||||
if (isExecution) {
|
if (isExecution) {
|
||||||
tx = await getExecutionTransaction(
|
tx = await getExecutionTransaction(
|
||||||
safeInstance, to, valueInWei, txData, CALL, nonce,
|
safeInstance,
|
||||||
0, 0, 0, ZERO_ADDRESS, ZERO_ADDRESS, from, sigs
|
to,
|
||||||
|
valueInWei,
|
||||||
|
txData,
|
||||||
|
CALL,
|
||||||
|
nonce,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
ZERO_ADDRESS,
|
||||||
|
ZERO_ADDRESS,
|
||||||
|
from,
|
||||||
|
sigs,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
tx = await getApprovalTransaction(
|
tx = await getApprovalTransaction(
|
||||||
safeInstance, to, valueInWei, txData, CALL, nonce,
|
safeInstance,
|
||||||
0, 0, 0, ZERO_ADDRESS, ZERO_ADDRESS, from, sigs
|
to,
|
||||||
|
valueInWei,
|
||||||
|
txData,
|
||||||
|
CALL,
|
||||||
|
nonce,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
ZERO_ADDRESS,
|
||||||
|
ZERO_ADDRESS,
|
||||||
|
from,
|
||||||
|
sigs,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,9 +43,7 @@ const getLocalSafe = async (safeAddress: string) => {
|
|||||||
return storedSafes[safeAddress]
|
return storedSafes[safeAddress]
|
||||||
}
|
}
|
||||||
|
|
||||||
export const checkAndUpdateSafeOwners = (safeAddress: string) => async (
|
export const checkAndUpdateSafeOwners = (safeAddress: string) => async (dispatch: ReduxDispatch<GlobalState>) => {
|
||||||
dispatch: ReduxDispatch<GlobalState>,
|
|
||||||
) => {
|
|
||||||
// Check if the owner's safe did change and update them
|
// Check if the owner's safe did change and update them
|
||||||
const [gnosisSafe, localSafe] = await Promise.all([getGnosisSafeInstanceAt(safeAddress), getLocalSafe(safeAddress)])
|
const [gnosisSafe, localSafe] = await Promise.all([getGnosisSafeInstanceAt(safeAddress), getLocalSafe(safeAddress)])
|
||||||
const remoteOwners = await gnosisSafe.getOwners()
|
const remoteOwners = await gnosisSafe.getOwners()
|
||||||
|
@ -15,11 +15,7 @@ import {
|
|||||||
TX_TYPE_EXECUTION,
|
TX_TYPE_EXECUTION,
|
||||||
TX_TYPE_CONFIRMATION,
|
TX_TYPE_CONFIRMATION,
|
||||||
} from '~/logic/safe/transactions'
|
} from '~/logic/safe/transactions'
|
||||||
import {
|
import { type NotificationsQueue, getNotificationsFromTxType, showSnackbar } from '~/logic/notifications'
|
||||||
type NotificationsQueue,
|
|
||||||
getNotificationsFromTxType,
|
|
||||||
showSnackbar,
|
|
||||||
} from '~/logic/notifications'
|
|
||||||
import { getErrorMessage } from '~/test/utils/ethereumErrors'
|
import { getErrorMessage } from '~/test/utils/ethereumErrors'
|
||||||
|
|
||||||
// https://gnosis-safe.readthedocs.io/en/latest/contracts/signatures.html#pre-validated-signatures
|
// https://gnosis-safe.readthedocs.io/en/latest/contracts/signatures.html#pre-validated-signatures
|
||||||
@ -40,7 +36,9 @@ export const generateSignaturesFromTxConfirmations = (
|
|||||||
}
|
}
|
||||||
|
|
||||||
let sigs = '0x'
|
let sigs = '0x'
|
||||||
Object.keys(confirmationsMap).sort().forEach((addr) => {
|
Object.keys(confirmationsMap)
|
||||||
|
.sort()
|
||||||
|
.forEach((addr) => {
|
||||||
const conf = confirmationsMap[addr]
|
const conf = confirmationsMap[addr]
|
||||||
if (conf.signature) {
|
if (conf.signature) {
|
||||||
sigs += conf.signature.slice(2)
|
sigs += conf.signature.slice(2)
|
||||||
|
@ -90,7 +90,10 @@ const safeStorageMware = (store: Store<GlobalState>) => (next: Function) => asyn
|
|||||||
case REMOVE_SAFE_OWNER: {
|
case REMOVE_SAFE_OWNER: {
|
||||||
const { safeAddress, ownerAddress } = action.payload
|
const { safeAddress, ownerAddress } = action.payload
|
||||||
const { owners } = safes.get(safeAddress)
|
const { owners } = safes.get(safeAddress)
|
||||||
setOwners(safeAddress, owners.filter((o) => o.address.toLowerCase() !== ownerAddress.toLowerCase()))
|
setOwners(
|
||||||
|
safeAddress,
|
||||||
|
owners.filter((o) => o.address.toLowerCase() !== ownerAddress.toLowerCase()),
|
||||||
|
)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case REPLACE_SAFE_OWNER: {
|
case REPLACE_SAFE_OWNER: {
|
||||||
@ -110,7 +113,10 @@ const safeStorageMware = (store: Store<GlobalState>) => (next: Function) => asyn
|
|||||||
const { safeAddress, ownerAddress, ownerName } = action.payload
|
const { safeAddress, ownerAddress, ownerName } = action.payload
|
||||||
const { owners } = safes.get(safeAddress)
|
const { owners } = safes.get(safeAddress)
|
||||||
const ownerToUpdateIndex = owners.findIndex((o) => o.address.toLowerCase() === ownerAddress.toLowerCase())
|
const ownerToUpdateIndex = owners.findIndex((o) => o.address.toLowerCase() === ownerAddress.toLowerCase())
|
||||||
setOwners(safeAddress, owners.update(ownerToUpdateIndex, (owner) => owner.set('name', ownerName)))
|
setOwners(
|
||||||
|
safeAddress,
|
||||||
|
owners.update(ownerToUpdateIndex, (owner) => owner.set('name', ownerName)),
|
||||||
|
)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case SET_DEFAULT_SAFE: {
|
case SET_DEFAULT_SAFE: {
|
||||||
|
@ -46,7 +46,10 @@ export default handleActions<SafeReducerState, *>(
|
|||||||
const tokenAddress = action.payload
|
const tokenAddress = action.payload
|
||||||
|
|
||||||
const newState = state.withMutations((map) => {
|
const newState = state.withMutations((map) => {
|
||||||
map.get('safes').keySeq().forEach((safeAddress) => {
|
map
|
||||||
|
.get('safes')
|
||||||
|
.keySeq()
|
||||||
|
.forEach((safeAddress) => {
|
||||||
const safeActiveTokens = map.getIn(['safes', safeAddress, 'activeTokens'])
|
const safeActiveTokens = map.getIn(['safes', safeAddress, 'activeTokens'])
|
||||||
const activeTokens = safeActiveTokens.add(tokenAddress)
|
const activeTokens = safeActiveTokens.add(tokenAddress)
|
||||||
|
|
||||||
|
@ -18,6 +18,8 @@ import notifications, {
|
|||||||
NOTIFICATIONS_REDUCER_ID,
|
NOTIFICATIONS_REDUCER_ID,
|
||||||
type NotificationReducerState as NotificationsState,
|
type NotificationReducerState as NotificationsState,
|
||||||
} from '~/logic/notifications/store/reducer/notifications'
|
} from '~/logic/notifications/store/reducer/notifications'
|
||||||
|
import cookies, { COOKIES_REDUCER_ID } from '~/logic/cookies/store/reducer/cookies'
|
||||||
|
|
||||||
|
|
||||||
export const history = createBrowserHistory()
|
export const history = createBrowserHistory()
|
||||||
|
|
||||||
@ -44,8 +46,10 @@ const reducers: Reducer<GlobalState> = combineReducers({
|
|||||||
[TOKEN_REDUCER_ID]: tokens,
|
[TOKEN_REDUCER_ID]: tokens,
|
||||||
[TRANSACTIONS_REDUCER_ID]: transactions,
|
[TRANSACTIONS_REDUCER_ID]: transactions,
|
||||||
[NOTIFICATIONS_REDUCER_ID]: notifications,
|
[NOTIFICATIONS_REDUCER_ID]: notifications,
|
||||||
|
[COOKIES_REDUCER_ID]: cookies,
|
||||||
})
|
})
|
||||||
|
|
||||||
export const store: Store<GlobalState> = createStore(reducers, finalCreateStore)
|
export const store: Store<GlobalState> = createStore(reducers, finalCreateStore)
|
||||||
|
|
||||||
|
// eslint-disable-next-line max-len
|
||||||
export const aNewStore = (localState?: Object): Store<GlobalState> => createStore(reducers, localState, finalCreateStore)
|
export const aNewStore = (localState?: Object): Store<GlobalState> => createStore(reducers, localState, finalCreateStore)
|
||||||
|
@ -115,7 +115,7 @@ export const whenSafeDeployed = (): Promise<string> => new Promise((resolve, rej
|
|||||||
const interval = setInterval(() => {
|
const interval = setInterval(() => {
|
||||||
if (times >= MAX_TIMES_EXECUTED) {
|
if (times >= MAX_TIMES_EXECUTED) {
|
||||||
clearInterval(interval)
|
clearInterval(interval)
|
||||||
reject(new Error('Didn\'t load the safe'))
|
reject(new Error("Didn't load the safe"))
|
||||||
}
|
}
|
||||||
const url = `${window.location}`
|
const url = `${window.location}`
|
||||||
console.log(url)
|
console.log(url)
|
||||||
|
@ -12,9 +12,7 @@ import { fillAndSubmitSendFundsForm } from './utils/transactions'
|
|||||||
import { TRANSACTIONS_TAB_BTN_TEST_ID } from '~/routes/safe/components/Layout'
|
import { TRANSACTIONS_TAB_BTN_TEST_ID } from '~/routes/safe/components/Layout'
|
||||||
import { TRANSACTION_ROW_TEST_ID } from '~/routes/safe/components/Transactions/TxsTable'
|
import { TRANSACTION_ROW_TEST_ID } from '~/routes/safe/components/Transactions/TxsTable'
|
||||||
import { useTestAccountAt, resetTestAccount } from './utils/accounts'
|
import { useTestAccountAt, resetTestAccount } from './utils/accounts'
|
||||||
import {
|
import { CONFIRM_TX_BTN_TEST_ID } from '~/routes/safe/components/Transactions/TxsTable/ExpandedTx/OwnersColumn/ButtonRow'
|
||||||
CONFIRM_TX_BTN_TEST_ID,
|
|
||||||
} from '~/routes/safe/components/Transactions/TxsTable/ExpandedTx/OwnersColumn/ButtonRow'
|
|
||||||
import { APPROVE_TX_MODAL_SUBMIT_BTN_TEST_ID } from '~/routes/safe/components/Transactions/TxsTable/ExpandedTx/ApproveTxModal'
|
import { APPROVE_TX_MODAL_SUBMIT_BTN_TEST_ID } from '~/routes/safe/components/Transactions/TxsTable/ExpandedTx/ApproveTxModal'
|
||||||
|
|
||||||
afterEach(resetTestAccount)
|
afterEach(resetTestAccount)
|
||||||
|
@ -1,23 +1,26 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import { createMuiTheme } from '@material-ui/core/styles'
|
import { createMuiTheme } from '@material-ui/core/styles'
|
||||||
|
import { rgba } from 'polished'
|
||||||
import {
|
import {
|
||||||
extraSmallFontSize,
|
|
||||||
mediumFontSize,
|
|
||||||
smallFontSize,
|
|
||||||
disabled,
|
|
||||||
primary,
|
|
||||||
secondary,
|
|
||||||
error,
|
|
||||||
sm,
|
|
||||||
md,
|
|
||||||
lg,
|
|
||||||
bolderFont,
|
|
||||||
regularFont,
|
|
||||||
boldFont,
|
boldFont,
|
||||||
|
bolderFont,
|
||||||
buttonLargeFontSize,
|
buttonLargeFontSize,
|
||||||
|
disabled,
|
||||||
|
error,
|
||||||
|
extraSmallFontSize,
|
||||||
largeFontSize,
|
largeFontSize,
|
||||||
xs,
|
lg,
|
||||||
|
mainFontFamily,
|
||||||
|
md,
|
||||||
|
mediumFontSize,
|
||||||
|
primary,
|
||||||
|
regularFont,
|
||||||
|
secondary,
|
||||||
|
secondaryFontFamily,
|
||||||
secondaryText,
|
secondaryText,
|
||||||
|
sm,
|
||||||
|
smallFontSize,
|
||||||
|
xs,
|
||||||
} from './variables'
|
} from './variables'
|
||||||
|
|
||||||
export type WithStyles = {
|
export type WithStyles = {
|
||||||
@ -42,7 +45,7 @@ const palette = {
|
|||||||
// see https://github.com/mui-org/material-ui/blob/v1-beta/src/styles/createMuiTheme.js
|
// see https://github.com/mui-org/material-ui/blob/v1-beta/src/styles/createMuiTheme.js
|
||||||
export default createMuiTheme({
|
export default createMuiTheme({
|
||||||
typography: {
|
typography: {
|
||||||
fontFamily: 'Averta,sans-serif',
|
fontFamily: mainFontFamily,
|
||||||
useNextVariants: true,
|
useNextVariants: true,
|
||||||
},
|
},
|
||||||
overrides: {
|
overrides: {
|
||||||
@ -53,7 +56,7 @@ export default createMuiTheme({
|
|||||||
fontWeight: regularFont,
|
fontWeight: regularFont,
|
||||||
},
|
},
|
||||||
root: {
|
root: {
|
||||||
fontFamily: 'Averta, monospace',
|
fontFamily: secondaryFontFamily,
|
||||||
letterSpacing: '0.9px',
|
letterSpacing: '0.9px',
|
||||||
'&$disabled': {
|
'&$disabled': {
|
||||||
color: disabled,
|
color: disabled,
|
||||||
@ -109,7 +112,7 @@ export default createMuiTheme({
|
|||||||
},
|
},
|
||||||
MuiChip: {
|
MuiChip: {
|
||||||
root: {
|
root: {
|
||||||
fontFamily: 'Averta, monospace',
|
fontFamily: secondaryFontFamily,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
MuiStepIcon: {
|
MuiStepIcon: {
|
||||||
@ -132,30 +135,30 @@ export default createMuiTheme({
|
|||||||
},
|
},
|
||||||
MuiTypography: {
|
MuiTypography: {
|
||||||
body1: {
|
body1: {
|
||||||
fontFamily: 'Averta, monospace',
|
fontFamily: secondaryFontFamily,
|
||||||
letterSpacing: '-0.5px',
|
letterSpacing: '-0.5px',
|
||||||
fontSize: mediumFontSize,
|
fontSize: mediumFontSize,
|
||||||
},
|
},
|
||||||
body2: {
|
body2: {
|
||||||
fontFamily: 'Averta, monospace',
|
fontFamily: secondaryFontFamily,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
MuiFormHelperText: {
|
MuiFormHelperText: {
|
||||||
root: {
|
root: {
|
||||||
fontFamily: 'Averta, monospace',
|
color: secondary,
|
||||||
|
fontFamily: secondaryFontFamily,
|
||||||
fontSize: '12px',
|
fontSize: '12px',
|
||||||
|
marginTop: '0px',
|
||||||
|
order: 0,
|
||||||
padding: `0 0 0 ${md}`,
|
padding: `0 0 0 ${md}`,
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
top: '5px',
|
top: '5px',
|
||||||
color: secondary,
|
|
||||||
order: 0,
|
|
||||||
marginTop: '0px',
|
|
||||||
zIndex: 1, // for firefox
|
zIndex: 1, // for firefox
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
MuiInput: {
|
MuiInput: {
|
||||||
root: {
|
root: {
|
||||||
fontFamily: 'Averta, monospace',
|
fontFamily: secondaryFontFamily,
|
||||||
color: primary,
|
color: primary,
|
||||||
fontSize: mediumFontSize,
|
fontSize: mediumFontSize,
|
||||||
lineHeight: '56px',
|
lineHeight: '56px',
|
||||||
@ -222,7 +225,7 @@ export default createMuiTheme({
|
|||||||
},
|
},
|
||||||
MuiTab: {
|
MuiTab: {
|
||||||
root: {
|
root: {
|
||||||
fontFamily: 'Averta, monospace',
|
fontFamily: secondaryFontFamily,
|
||||||
fontWeight: 'normal',
|
fontWeight: 'normal',
|
||||||
fontSize: extraSmallFontSize,
|
fontSize: extraSmallFontSize,
|
||||||
'&$selected': {
|
'&$selected': {
|
||||||
@ -244,7 +247,7 @@ export default createMuiTheme({
|
|||||||
top: '0px',
|
top: '0px',
|
||||||
},
|
},
|
||||||
caption: {
|
caption: {
|
||||||
fontFamily: 'Averta, monospace',
|
fontFamily: secondaryFontFamily,
|
||||||
fontSize: mediumFontSize,
|
fontSize: mediumFontSize,
|
||||||
order: 2,
|
order: 2,
|
||||||
color: disabled,
|
color: disabled,
|
||||||
@ -270,7 +273,7 @@ export default createMuiTheme({
|
|||||||
},
|
},
|
||||||
MuiTableCell: {
|
MuiTableCell: {
|
||||||
root: {
|
root: {
|
||||||
fontFamily: 'Averta, monospace',
|
fontFamily: secondaryFontFamily,
|
||||||
fontSize: mediumFontSize,
|
fontSize: mediumFontSize,
|
||||||
borderBottomWidth: '2px',
|
borderBottomWidth: '2px',
|
||||||
},
|
},
|
||||||
@ -298,7 +301,7 @@ export default createMuiTheme({
|
|||||||
},
|
},
|
||||||
MuiMenuItem: {
|
MuiMenuItem: {
|
||||||
root: {
|
root: {
|
||||||
fontFamily: 'Averta, monospace',
|
fontFamily: secondaryFontFamily,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
MuiListItemIcon: {
|
MuiListItemIcon: {
|
||||||
@ -308,17 +311,31 @@ export default createMuiTheme({
|
|||||||
},
|
},
|
||||||
MuiListItemText: {
|
MuiListItemText: {
|
||||||
primary: {
|
primary: {
|
||||||
fontFamily: 'Averta, monospace',
|
fontFamily: secondaryFontFamily,
|
||||||
fontSize: mediumFontSize,
|
fontSize: mediumFontSize,
|
||||||
fontWeight: bolderFont,
|
fontWeight: bolderFont,
|
||||||
color: primary,
|
color: primary,
|
||||||
},
|
},
|
||||||
secondary: {
|
secondary: {
|
||||||
fontFamily: 'Averta, monospace',
|
fontFamily: secondaryFontFamily,
|
||||||
fontSize: smallFontSize,
|
fontSize: smallFontSize,
|
||||||
color: disabled,
|
color: disabled,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
MuiCheckbox: {
|
||||||
|
colorSecondary: {
|
||||||
|
'&$disabled': {
|
||||||
|
color: rgba(secondary, 0.5),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
MuiFormControlLabel: {
|
||||||
|
label: {
|
||||||
|
'&$disabled': {
|
||||||
|
color: primary,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
palette,
|
palette,
|
||||||
})
|
})
|
||||||
|
@ -1,65 +1,67 @@
|
|||||||
// @flow
|
// @flow
|
||||||
const border = '#e8e7e6'
|
|
||||||
const background = '#f7f5f5'
|
const background = '#f7f5f5'
|
||||||
const primary = '#001428'
|
const border = '#e8e7e6'
|
||||||
const secondary = '#008C73'
|
|
||||||
const fontColor = '#001428'
|
|
||||||
const fancyColor = '#f02525'
|
|
||||||
const warningColor = '#ffc05f'
|
|
||||||
const errorColor = '#f02525'
|
|
||||||
const secondaryTextOrSvg = '#B2B5B2'
|
|
||||||
const connectedColor = '#008C73'
|
const connectedColor = '#008C73'
|
||||||
const disabled = '#5D6D74'
|
const disabled = '#5D6D74'
|
||||||
const xs = '4px'
|
const errorColor = '#f02525'
|
||||||
const sm = '8px'
|
const fancyColor = '#f02525'
|
||||||
const md = '16px'
|
const fontColor = '#001428'
|
||||||
const lg = '24px'
|
|
||||||
const xl = '32px'
|
|
||||||
const xxl = '40px'
|
|
||||||
const marginButtonImg = '12px'
|
|
||||||
const headerHeight = '53px'
|
const headerHeight = '53px'
|
||||||
|
const lg = '24px'
|
||||||
|
const marginButtonImg = '12px'
|
||||||
|
const md = '16px'
|
||||||
|
const primary = '#001428'
|
||||||
|
const secondary = '#008C73'
|
||||||
|
const secondaryTextOrSvg = '#B2B5B2'
|
||||||
|
const sm = '8px'
|
||||||
|
const warningColor = '#ffc05f'
|
||||||
|
const xl = '32px'
|
||||||
|
const xs = '4px'
|
||||||
|
const xxl = '40px'
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
primary,
|
|
||||||
secondary,
|
|
||||||
disabled,
|
|
||||||
background,
|
background,
|
||||||
fontColor,
|
|
||||||
secondaryText: secondaryTextOrSvg,
|
|
||||||
fancy: fancyColor,
|
|
||||||
warning: warningColor,
|
|
||||||
error: errorColor,
|
|
||||||
connected: connectedColor,
|
|
||||||
headerHeight,
|
|
||||||
xs,
|
|
||||||
sm,
|
|
||||||
md,
|
|
||||||
lg,
|
|
||||||
xl,
|
|
||||||
xxl,
|
|
||||||
border,
|
|
||||||
marginButtonImg,
|
|
||||||
fontSizeHeadingXs: 13,
|
|
||||||
fontSizeHeadingSm: 16,
|
|
||||||
fontSizeHeadingMd: 20,
|
|
||||||
fontSizeHeadingLg: 32,
|
|
||||||
buttonLargeFontSize: '16px',
|
|
||||||
lightFont: 300,
|
|
||||||
regularFont: 400,
|
|
||||||
bolderFont: 500,
|
|
||||||
boldFont: 700,
|
boldFont: 700,
|
||||||
|
bolderFont: 500,
|
||||||
|
border,
|
||||||
|
buttonLargeFontSize: '16px',
|
||||||
|
connected: connectedColor,
|
||||||
|
disabled,
|
||||||
|
error: errorColor,
|
||||||
extraBoldFont: 800,
|
extraBoldFont: 800,
|
||||||
extraSmallFontSize: '11px',
|
|
||||||
smallFontSize: '12px',
|
|
||||||
mediumFontSize: '14px',
|
|
||||||
largeFontSize: '16px',
|
|
||||||
extraLargeFontSize: '20px',
|
extraLargeFontSize: '20px',
|
||||||
xxlFontSize: '32px',
|
extraSmallFontSize: '11px',
|
||||||
screenXs: 480,
|
fancy: fancyColor,
|
||||||
screenXsMax: 767,
|
fontColor,
|
||||||
screenSm: 768,
|
fontSizeHeadingLg: 32,
|
||||||
screenSmMax: 991,
|
fontSizeHeadingMd: 20,
|
||||||
|
fontSizeHeadingSm: 16,
|
||||||
|
fontSizeHeadingXs: 13,
|
||||||
|
headerHeight,
|
||||||
|
largeFontSize: '16px',
|
||||||
|
lg,
|
||||||
|
lightFont: 300,
|
||||||
|
mainFontFamily: 'Averta, sans-serif',
|
||||||
|
marginButtonImg,
|
||||||
|
md,
|
||||||
|
mediumFontSize: '14px',
|
||||||
|
primary,
|
||||||
|
regularFont: 400,
|
||||||
|
screenLg: 1200,
|
||||||
screenMd: 992,
|
screenMd: 992,
|
||||||
screenMdMax: 1199,
|
screenMdMax: 1199,
|
||||||
screenLg: 1200,
|
screenSm: 768,
|
||||||
|
screenSmMax: 991,
|
||||||
|
screenXs: 480,
|
||||||
|
screenXsMax: 767,
|
||||||
|
secondary,
|
||||||
|
secondaryFontFamily: 'Averta, monospace',
|
||||||
|
secondaryText: secondaryTextOrSvg,
|
||||||
|
sm,
|
||||||
|
smallFontSize: '12px',
|
||||||
|
warning: warningColor,
|
||||||
|
xl,
|
||||||
|
xs,
|
||||||
|
xxl,
|
||||||
|
xxlFontSize: '32px',
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user