Skip to content
This repository has been archived by the owner on Nov 10, 2023. It is now read-only.

Feature #189: Cookie banner #296

Merged
merged 30 commits into from
Dec 4, 2019
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
a4b92ca
Adds cookie permissions to localStorage/redux state
Agupane Nov 19, 2019
ad3d27e
Adds action
Agupane Nov 20, 2019
13d1de8
Adds files to git
Agupane Nov 20, 2019
5839fbe
Merge branch 'development' into 189-cookie-banner
Agupane Nov 20, 2019
3a3761a
(fix) linting issues
gabitoesmiapodo Nov 21, 2019
21e97b1
(update) flow-typed
gabitoesmiapodo Nov 21, 2019
cb8cabb
(update) .eslint and .flowconfig
gabitoesmiapodo Nov 21, 2019
8848ecd
(add) cookie banner
gabitoesmiapodo Nov 22, 2019
3af4622
Merge branch '189-cookie-banner' of https://github.com/gnosis/safe-re…
Agupane Nov 25, 2019
6ea47d6
Finish cookie banner implementation
Agupane Nov 25, 2019
3b063d3
Merge branch 'development' of https://github.com/gnosis/safe-react in…
Agupane Nov 25, 2019
43a1990
(Add) checkbox's disabled style.
gabitoesmiapodo Nov 25, 2019
9c6235f
Removes redux for cookiesStorage
Agupane Nov 26, 2019
3625135
Merge branch '189-cookie-banner' of https://github.com/gnosis/safe-re…
Agupane Nov 26, 2019
26b4207
Fix cookieStore deletion
Agupane Nov 26, 2019
a9dee4c
Fixs cookies acceptance
Agupane Nov 27, 2019
c995cc2
Fixs cookies banner verbiage
Agupane Nov 27, 2019
a9e3204
Pull updated flow-types from dev
mmv08 Dec 2, 2019
fe422cb
(remove) unused library
gabitoesmiapodo Dec 2, 2019
bc994dc
Adds cookies utils
Agupane Dec 2, 2019
1fa3c04
(fix) added correct polished library and import, updated flow-typed
gabitoesmiapodo Dec 2, 2019
a7d7142
Merge branch '189-cookie-banner' of github.com:gnosis/safe-react into…
gabitoesmiapodo Dec 2, 2019
4cf4ea3
(update) removed polish flow type, added js-cookie flow type
gabitoesmiapodo Dec 2, 2019
4a6fc32
Add link to cookie policy, use generic links for legal docs
mmv08 Dec 3, 2019
b909cf2
Merge branch '189-cookie-banner' of github.com:gnosis/safe-react into…
mmv08 Dec 3, 2019
dd3743e
Remove link to cookie policy from sidebar, link cookie policy in the …
mmv08 Dec 3, 2019
d2a7ff9
Let the user re-open the cookie banner
Agupane Dec 3, 2019
639b2b0
remove withMutations from cookies reducer, move utils/cookies to logi…
mmv08 Dec 4, 2019
2e1acb5
Now the sidebar closes when the cookie banner is toggled
Agupane Dec 4, 2019
5cb148b
Merge branch '189-cookie-banner' of https://github.com/gnosis/safe-re…
Agupane Dec 4, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ flow-typed
flow-typed/npm
config
scripts
migrations
migrations
30 changes: 30 additions & 0 deletions flow-typed/npm/js-cookie_v2.x.x.js
Original file line number Diff line number Diff line change
@@ -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;
}
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,11 @@
"history": "4.10.1",
"immortal-db": "^1.0.2",
"immutable": "^4.0.0-rc.9",
"js-cookie": "^2.2.1",
"material-ui-search-bar": "^1.0.0-beta.13",
"notistack": "https://github.com/gnosis/notistack.git#v0.9.4",
"optimize-css-assets-webpack-plugin": "5.0.3",
"polished": "^3.4.2",
"qrcode.react": "1.0.0",
"react": "16.12.0",
"react-dom": "16.12.0",
Expand Down
166 changes: 166 additions & 0 deletions src/components/CookiesBanner/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
// @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 Link from '~/components/layout/Link'
import { WELCOME_ADDRESS } from '~/routes/routes'
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 '~/utils/cookies'

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 [showBanner, setShowBanner] = useState(false)
const [localNecessary, setLocalNecessary] = useState(true)
const [localAnalytics, setLocalAnalytics] = useState(false)

useEffect(() => {
async function fetchCookiesFromStorage() {
const cookiesState: CookiesProps = await loadFromCookie(COOKIES_KEY)
if (cookiesState) {
const { acceptedNecessary, acceptedAnalytics } = cookiesState
setLocalAnalytics(acceptedAnalytics)
setLocalNecessary(acceptedNecessary)
setShowBanner(acceptedNecessary === false)
} else {
setShowBanner(true)
}
}
fetchCookiesFromStorage()
}, [])

const acceptCookiesHandler = async () => {
const newState = {
acceptedNecessary: true,
acceptedAnalytics: true,
}
await saveCookie(COOKIES_KEY, newState, 365)
setShowBanner(false)
}

const closeCookiesBannerHandler = async () => {
const newState = {
acceptedNecessary: true,
acceptedAnalytics: localAnalytics,
}
const expDays = localAnalytics ? 365 : 7
await saveCookie(COOKIES_KEY, newState, expDays)
setShowBanner(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={WELCOME_ADDRESS}>Cookie Policy</Link>
{' '}
for more information. By clicking &quot;Accept all&quot;, 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 />
)}
/>
</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
7 changes: 1 addition & 6 deletions src/components/Notifier/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,4 @@ class Notifier extends Component<Props> {
}
}

export default withSnackbar(
connect(
selector,
actions,
)(Notifier),
)
export default withSnackbar(connect(selector, actions)(Notifier))
26 changes: 14 additions & 12 deletions src/components/Root/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -9,32 +9,34 @@ body {
font-style: normal;
font-weight: 400;
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-family: 'Averta';
font-family: "Averta";
font-style: normal;
font-weight: 800;
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 {
position: absolute;
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
background-color: $background;
bottom: 0;
top: 0;
left: 0;
right: 0;
overflow-x: hidden;
color: $fontColor;
font-family: 'Averta', monospace;
font-family: "Averta", monospace;
font-size: $mediumFontSize;
left: 0;
margin: 0;
background-color: $background;
overflow-x: hidden;
position: absolute;
right: 0;
text-rendering: geometricPrecision;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
top: 0;
}

body > div:first-child {
Expand Down
2 changes: 2 additions & 0 deletions src/components/layout/PageFrame/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import AlertIcon from './assets/alert.svg'
import CheckIcon from './assets/check.svg'
import ErrorIcon from './assets/error.svg'
import InfoIcon from './assets/info.svg'
import CookiesBanner from '~/components/CookiesBanner'
import styles from './index.scss'

const notificationStyles = {
Expand Down Expand Up @@ -92,6 +93,7 @@ const PageFrame = ({ children, classes, currentNetwork }: Props) => {
{children}
</SidebarProvider>
</SnackbarProvider>
<CookiesBanner />
</div>
)
}
Expand Down
12 changes: 8 additions & 4 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
// @flow
import 'babel-polyfill'

import React from 'react'
import ReactDOM from 'react-dom'
import { BigNumber } from 'bignumber.js'
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 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] })

Expand All @@ -18,8 +17,13 @@ if (process.env.NODE_ENV !== 'production') {
whyDidYouRender(React)
}

// $FlowFixMe
store.dispatch(loadActiveTokens())
store.dispatch(loadSafesFromStorage())
store.dispatch(loadDefaultSafe())

ReactDOM.render(<Root />, document.getElementById('root'))
const root = document.getElementById('root')

if (root !== null) {
mmv08 marked this conversation as resolved.
Show resolved Hide resolved
ReactDOM.render(<Root />, root)
}
5 changes: 4 additions & 1 deletion src/logic/contracts/safeContracts.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,10 @@ export const deploySafeContract = async (safeAccounts: string[], numConfirmation
const gasPrice = await calculateGasPrice()

return proxyFactoryMaster.createProxy(safeMaster.address, gnosisSafeData, {
from: userAccount, gas, gasPrice, value: 0,
from: userAccount,
gas,
gasPrice,
value: 0,
})
}

Expand Down
11 changes: 11 additions & 0 deletions src/logic/cookies/model/cookie.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// @flow
import type { RecordOf } from 'immutable'

export const COOKIES_KEY = 'COOKIES'

export type CookiesProps = {
acceptedNecessary: boolean,
acceptedAnalytics: boolean,
}

export type Cookie = RecordOf<CookiesProps>
4 changes: 1 addition & 3 deletions src/logic/notifications/store/actions/enqueueSnackbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ export const ENQUEUE_SNACKBAR = 'ENQUEUE_SNACKBAR'

const addSnackbar = createAction<string, *>(ENQUEUE_SNACKBAR)

const enqueueSnackbar = (notification: NotificationProps) => (
dispatch: ReduxDispatch<GlobalState>,
) => {
const enqueueSnackbar = (notification: NotificationProps) => (dispatch: ReduxDispatch<GlobalState>) => {
const newNotification = {
...notification,
key: new Date().getTime(),
Expand Down
13 changes: 6 additions & 7 deletions src/logic/notifications/store/selectors/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@ import { type GlobalState } from '~/store'
import { NOTIFICATIONS_REDUCER_ID } from '~/logic/notifications/store/reducer/notifications'
import { type Notification } from '~/logic/notifications/store/models/notification'

const notificationsMapSelector = (
state: GlobalState,
): Map<string, Notification> => state[NOTIFICATIONS_REDUCER_ID]
const notificationsMapSelector = (state: GlobalState): Map<string, Notification> => state[NOTIFICATIONS_REDUCER_ID]

export const notificationsListSelector: Selector<GlobalState, {}, List<Notification>> = createSelector(
notificationsMapSelector,
(notifications: Map<string, Notification>): List<Notification> => notifications.toList(),
)
export const notificationsListSelector: Selector<
GlobalState,
{},
List<Notification>,
> = createSelector(notificationsMapSelector, (notifications: Map<string, Notification>): List<Notification> => notifications.toList())
13 changes: 12 additions & 1 deletion src/logic/safe/transactions/send.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,18 @@ export const getExecutionTransaction = async (
const web3 = getWeb3()
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) {
console.error(`Error while creating transaction: ${err}`)

Expand Down
Loading