Skip to content

Commit

Permalink
Merge 0e21f03 into aa95882
Browse files Browse the repository at this point in the history
  • Loading branch information
natterstefan committed Jul 10, 2018
2 parents aa95882 + 0e21f03 commit 25e6b0a
Show file tree
Hide file tree
Showing 39 changed files with 3,257 additions and 35 deletions.
3 changes: 3 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@ webpack/base.config.js
webpack/dev.config.js
webpack/prod.config.js
webpack/prod.analyse.config.js

## 3rd Party
static/js/*.min.js
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@ config.js

## Coverall
.coveralls.yml

## Content
src/content/privacy.md
1 change: 1 addition & 0 deletions config/config.example.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
module.exports = {
app_title: 'Multiboard for Trello®',
api_key: 'your_api_key',
google_analytics_property: 'UA-12345678-9',
company_member: 'exampleusername',
preferred_members: /exampleusername|anotheruser/,
lists: [/#upcoming/],
Expand Down
8 changes: 7 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"format:scss": "stylelint --fix ./src",
"lint": "eslint ./src",
"lint:scss": "stylelint ./src",
"postinstall": "./node_modules/.bin/cpy \"./config/config.example.js\" \"./config\" --no-overwrite --rename=\"config.js\"",
"postinstall": "cpy \"./config/config.example.js\" \"./config\" --no-overwrite --rename=\"config.js\" && cpy \"./src/content/privacy.example.md\" \"./src/content\" --no-overwrite --rename=\"privacy.md\"",
"precommit": "npm run build && npm run analyse:size && lint-staged",
"prepush": "npm test",
"start": "webpack-dev-server --hot --config webpack/dev.config.js",
Expand Down Expand Up @@ -80,9 +80,11 @@
"connected-react-router": "4.3.0",
"history": "4.7.2",
"lodash": "4.17.10",
"marked": "0.4.0",
"prop-types": "15.6.1",
"query-string": "6.1.0",
"react": "16.4.0",
"react-cookie-banner": "4.0.0",
"react-dom": "16.4.0",
"react-redux": "5.0.7",
"react-router-dom": "4.2.2",
Expand All @@ -101,6 +103,7 @@
"babel-preset-env": "1.7.0",
"babel-preset-react": "6.24.1",
"babel-preset-stage-2": "6.24.1",
"copy-webpack-plugin": "4.5.2",
"coveralls": "3.0.1",
"cpy-cli": "2.0.0",
"cross-env": "5.1.6",
Expand All @@ -110,11 +113,14 @@
"enzyme-to-json": "3.3.4",
"error-overlay-webpack-plugin": "0.1.5",
"extract-text-webpack-plugin": "4.0.0-beta.0",
"file-loader": "1.1.11",
"html-loader": "0.5.5",
"html-webpack-plugin": "3.2.0",
"husky": "0.14.3",
"jest": "23.0.1",
"jest-styled-components": "5.0.1",
"lint-staged": "7.1.2",
"markdown-loader": "3.0.0",
"node-sass": "4.9.0",
"redux-mock-store": "1.5.1",
"sass-loader": "7.0.1",
Expand Down
5 changes: 5 additions & 0 deletions setup-jest.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ fontawesome.library.add(brands, faAlignLeft, faCheckSquare, faCommentDots, faPap
jest.mock('./config/config', () => ({
app_title: 'Trello Multiboard',
api_key: 'your_api_key',
google_analytics_property: 'UA-12345678-9',
company_member: 'exampleusername',
preferred_members: /exampleusername|anotheruser/,
lists: [/#upcoming/],
Expand Down Expand Up @@ -61,3 +62,7 @@ window.TrelloCards = {
}),
load: jest.fn(),
}

// as long as we do not have implemented a Markdown-Loader for Jest, we mock
// every markdown file here
jest.mock('./src/content/privacy.md', () => ({}))
4 changes: 4 additions & 0 deletions src/__tests__/__snapshots__/index.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ exports[`Component/TrelloMultiBoard should render without throwing an error 1`]
component={[Function]}
path="/github"
/>
<Route
component={[Function]}
path="/privacy"
/>
<Route
component={[Function]}
path="/"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Component/AppMenuContent should render without throwing an error 1`] = `
<div>
<React.Fragment>
<WithStyles(List)
component="nav"
>
<WithStyles(ListItem)
button={true}
component={[Function]}
key="Dashboard"
replace={true}
to="/"
>
Expand All @@ -21,6 +22,7 @@ exports[`Component/AppMenuContent should render without throwing an error 1`] =
<WithStyles(ListItem)
button={true}
component={[Function]}
key="Config"
replace={true}
to="/config"
>
Expand All @@ -34,6 +36,21 @@ exports[`Component/AppMenuContent should render without throwing an error 1`] =
<WithStyles(ListItem)
button={true}
component={[Function]}
key="Privacy"
replace={true}
to="/privacy"
>
<WithStyles(ListItemIcon)>
<pure(Fingerprint) />
</WithStyles(ListItemIcon)>
<WithStyles(ListItemText)
primary="Privacy"
/>
</WithStyles(ListItem)>
<WithStyles(ListItem)
button={true}
component={[Function]}
key="GitHub"
replace={true}
to="/github"
>
Expand Down Expand Up @@ -66,5 +83,5 @@ exports[`Component/AppMenuContent should render without throwing an error 1`] =
/>
</WithStyles(ListItem)>
</WithStyles(List)>
</div>
</React.Fragment>
`;
8 changes: 7 additions & 1 deletion src/components/app-menu-container/__tests__/menu.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ describe('Component/AppMenuContent', () => {
<AppMenuContent />
</Router>,
)
expect(wrapper.find(ListItem).length).toBe(3)
expect(wrapper.find(ListItem).length).toBe(4)
expect(
wrapper
.find(ListItem)
Expand All @@ -34,6 +34,12 @@ describe('Component/AppMenuContent', () => {
.find(ListItem)
.at(2)
.prop('to'),
).toBe('/privacy')
expect(
wrapper
.find(ListItem)
.at(3)
.prop('to'),
).toBe('/github')
})
})
71 changes: 50 additions & 21 deletions src/components/app-menu-container/menu.js
Original file line number Diff line number Diff line change
@@ -1,37 +1,66 @@
import React from 'react'
import { map } from 'lodash'
import { Link } from 'react-router-dom'

import FontAwesomeIcon from '@fortawesome/react-fontawesome'
import List from '@material-ui/core/List'
import ListItem from '@material-ui/core/ListItem'
import ListItemIcon from '@material-ui/core/ListItemIcon'
import ListItemText from '@material-ui/core/ListItemText'
import DashboardIcon from '@material-ui/icons/Dashboard'
import SettingsIcon from '@material-ui/icons/Settings'
import FingerprintIcon from '@material-ui/icons/Fingerprint'

import Config from '../../../config/config'

let menuConfig = [
{
target: '/',
icon: () => <DashboardIcon />,
title: 'Dashboard',
},
{
target: '/config',
icon: () => <SettingsIcon />,
title: 'Config',
},
{
target: '/github',
icon: () => <FontAwesomeIcon icon={['fab', 'github']} size="lg" />,
title: 'GitHub',
},
]

// inspired by https://stackoverflow.com/a/38181008/1238150
const appendAtIndex = (array, obj, index = 0) => [
...array.slice(0, index),
obj,
...array.slice(index),
]

// - add Privacy only if config.google_analytics_property = true
if (Config.google_analytics_property) {
const menuItem = {
target: '/privacy',
icon: () => <FingerprintIcon />,
title: 'Privacy',
}
menuConfig = appendAtIndex(menuConfig, menuItem, 2)
}

// NOTE: add replace to ListItem because of: https://github.com/ReactTraining/react-router/issues/4467
// NOTE: add 'replace' property to ListItem because of:
// https://github.com/ReactTraining/react-router/issues/4467
const AppMenuContent = () => (
<div>
<React.Fragment>
<List component="nav">
<ListItem component={Link} button replace to="/">
<ListItemIcon>
<DashboardIcon />
</ListItemIcon>
<ListItemText primary="Dashboard" />
</ListItem>
<ListItem component={Link} button replace to="/config">
<ListItemIcon>
<SettingsIcon />
</ListItemIcon>
<ListItemText primary="Config" />
</ListItem>
<ListItem component={Link} button replace to="/github">
<ListItemIcon>
<FontAwesomeIcon icon={['fab', 'github']} size="lg" />
</ListItemIcon>
<ListItemText primary="GitHub" />
</ListItem>
{map(menuConfig, menu => (
<ListItem key={menu.title} component={Link} button replace to={menu.target}>
<ListItemIcon>{menu.icon()}</ListItemIcon>
<ListItemText primary={menu.title} />
</ListItem>
))}
</List>
</div>
</React.Fragment>
)

AppMenuContent.displayName = 'AppMenuContent'
Expand Down
1 change: 1 addition & 0 deletions src/components/board/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const ThinContainer = styled.div`
min-width: 200px;
justify-content: center;
display: flex;
flex-direction: column;
`

class Board extends React.Component {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Component/CookieNotice should render without throwing an error 1`] = `
<div
className="cookie-notice"
>
<CookieBanner
buttonMessage="OK"
className="cookie-notice--banner"
cookie="user-has-accepted-cookies"
cookieExpiration={
Object {
"years": 1,
}
}
cookiePath="/"
cookies={
Cookies {
"HAS_DOCUMENT_COOKIE": true,
"changeListeners": Array [],
"cookies": Object {},
"hooks": undefined,
}
}
disableStyle={true}
dismissOnScroll={false}
dismissOnScrollThreshold={0}
link={
<Link
replace={false}
to="/privacy"
>
here.
</Link>
}
message="We use cookies to give you the best online experience. See what we do and how you can disagree "
onAccept={[Function]}
styles={Object {}}
/>
</div>
`;
9 changes: 9 additions & 0 deletions src/components/cookie-notice/__tests__/index.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React from 'react'
import { shallow } from 'enzyme'
import CookieNotice from '../'

describe('Component/CookieNotice', () => {
test('should render without throwing an error', () => {
expect(shallow(<CookieNotice />)).toMatchSnapshot()
})
})
26 changes: 26 additions & 0 deletions src/components/cookie-notice/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/* eslint-disable jsx-a11y/anchor-is-valid */
import React from 'react'
import { Link } from 'react-router-dom'
import CookieBanner from 'react-cookie-banner'

const message =
'We use cookies to give you the best online experience. See what we do and how you can disagree '

// TODO
// - add notice only if config.google_analytics_property = true
const CookieNotice = () => (
<div className="cookie-notice">
<CookieBanner
className="cookie-notice--banner"
cookiePath="/"
cookie="user-has-accepted-cookies"
dismissOnScroll={false}
disableStyle
buttonMessage="OK"
link={<Link to="/privacy">here.</Link>}
message={message}
/>
</div>
)

export default CookieNotice
37 changes: 37 additions & 0 deletions src/components/cookie-notice/styles.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
.cookie-notice {
background-color: $primary-color;
padding-left: 5px;
padding-top: 5px;

&--banner {
align-items: center;
background-color: #484848;
color: #fff;
display: flex;
height: auto;
justify-content: space-evenly;
padding: 10px 15px;

a {
color: #fff;
}
}

.cookie-message {
padding-right: 15px;
}

.button-close {
background-color: #fff;
cursor: pointer;
flex: 0 0 auto; // important for mobile
font-weight: bold;
margin-right: 15px; // important for mobile
outline: 0;
padding: 0.75em;
text-align: center;
text-decoration: none;
text-transform: uppercase;
width: 100px;
}
}
3 changes: 3 additions & 0 deletions src/content/privacy.example.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## Data privacy statement

Your statement goes here.
Loading

0 comments on commit 25e6b0a

Please sign in to comment.