diff --git a/.babelrc b/.babelrc index db2ad2d51..f6d898bb6 100644 --- a/.babelrc +++ b/.babelrc @@ -1,12 +1,10 @@ { - "presets": [ - "es2015", - "react" - ], + "presets": ["es2015", "react"], "plugins": [ "transform-decorators-legacy", "transform-runtime", "transform-class-properties", - "transform-object-rest-spread" + "transform-object-rest-spread", + "babel-plugin-styled-components" ] -} \ No newline at end of file +} diff --git a/.eslintrc.yml b/.eslintrc.yml index efb3468b2..97b6f9ec0 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -4,7 +4,7 @@ env: jest: true node: true cypress/globals: true -extends: "airbnb" +extends: 'airbnb' parser: babel-eslint parserOptions: ecmaFeatures: @@ -20,61 +20,61 @@ plugins: rules: max-len: - warn - - code: 80 + - code: 90 ignoreStrings: true ignoreTemplateLiterals: true ignoreRegExpLiterals: true - indent: ["warn", 2] - linebreak-style: ["error", "unix"] - quotes: ["warn", "single", { avoidEscape: true }] - semi: ["error", "never"] - import/first: ["warn"] - no-trailing-spaces: ["warn"] + indent: ['warn', 2] + linebreak-style: ['error', 'unix'] + quotes: ['warn', 'single', { avoidEscape: true }] + semi: ['error', 'never'] + import/first: ['warn'] + no-trailing-spaces: ['warn'] no-continue: off no-plusplus: off radix: off - eol-last: ["warn"] - no-nested-ternary: ["warn"] - prefer-const: ["warn"] - import/no-named-as-default: ["warn"] - no-restricted-globals: ["error", "event", "fdescribe"] - no-mixed-operators: ["warn"] + eol-last: ['warn'] + no-nested-ternary: ['warn'] + prefer-const: ['warn'] + import/no-named-as-default: ['warn'] + no-restricted-globals: ['error', 'event', 'fdescribe'] + no-mixed-operators: ['warn'] # See https://github.com/cypress-io/eslint-plugin-cypress#chai-and-no-unused-expressions no-unused-expressions: 0 chai-friendly/no-unused-expressions: 2 # React react/destructuring-assignment: off - react/no-multi-comp: ["warn"] - react/jsx-no-bind: ["warn"] - react/jsx-indent-props: ["warn"] - react/jsx-first-prop-new-line: ["warn"] - react/jsx-closing-bracket-location: ["warn"] - react/jsx-curly-spacing: ["warn"] - react/jsx-tag-spacing: ["warn", { beforeSelfClosing: "allow" }] - react/jsx-wrap-multilines: ["warn"] - react/no-unused-state: ["warn"] - react/jsx-max-props-per-line: ["warn", { when: "multiline" }] - react/jsx-closing-tag-location: ["warn"] - react/no-unescaped-entities: ["warn"] - react/no-unused-prop-types: ["warn"] - react/self-closing-comp: ["warn"] - react/jsx-indent: ["warn"] - react/no-array-index-key: ["warn"] - react/prefer-stateless-function: ["warn"] + react/no-multi-comp: ['warn'] + react/jsx-no-bind: ['warn'] + react/jsx-indent-props: ['warn'] + react/jsx-first-prop-new-line: ['warn'] + react/jsx-closing-bracket-location: ['warn'] + react/jsx-curly-spacing: ['warn'] + react/jsx-tag-spacing: ['warn', { beforeSelfClosing: 'allow' }] + react/jsx-wrap-multilines: ['warn'] + react/no-unused-state: ['warn'] + react/jsx-max-props-per-line: ['warn', { when: 'multiline' }] + react/jsx-closing-tag-location: ['warn'] + react/no-unescaped-entities: ['warn'] + react/no-unused-prop-types: ['warn'] + react/self-closing-comp: ['warn'] + react/jsx-indent: ['warn'] + react/no-array-index-key: ['warn'] + react/prefer-stateless-function: ['warn'] # JSX jsx-a11y/anchor-is-valid: - warn - - components: ["Link"] - specialLink: ["To"] - jsx-a11y/alt-text: ["warn"] - jsx-a11y/label-has-for: ["warn"] + - components: ['Link'] + specialLink: ['To'] + jsx-a11y/alt-text: ['warn'] + jsx-a11y/label-has-for: ['warn'] jsx-a11y/label-has-associated-control: - warn - controlComponents: - - "Field" - jsx-a11y/click-events-have-key-events: ["warn"] - jsx-a11y/no-static-element-interactions: ["warn"] - jsx-a11y/media-has-caption: ["warn"] + - 'Field' + jsx-a11y/click-events-have-key-events: ['warn'] + jsx-a11y/no-static-element-interactions: ['warn'] + jsx-a11y/media-has-caption: ['warn'] jsx-a11y/anchor-has-content: off # Following rule haves been disabled for compatibility with diff --git a/README.md b/README.md index 6bde80aee..1c12d1e1d 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,18 @@ app └── router.jsx => Application router and main entry point ``` +#### Styling + +Styling is based on [Bulma](https://bulma.io/documentation/) and was initially +customized with SASS. However we now include [styled-components](https://github.com/emotion-js/emotion), [styled-system](https://github.com/jxnblk/styled-system) and [@rebass/grid](https://github.com/rebassjs/grid) +. This has become the prefered way to build new components. + +#### Icons + +We bundle a custom font icon built with icomoon. You can find scripts and config +for this in `dev/` but the preferred (and easiest) way to add new icons today +is to use `https://styled-icons.js.org/`. + ## Main Libraries / Frameworks - ES6 with Babel diff --git a/app/API/graphql_queries.js b/app/API/graphql_queries.js new file mode 100644 index 000000000..876b576e2 --- /dev/null +++ b/app/API/graphql_queries.js @@ -0,0 +1,23 @@ +import gql from 'graphql-tag' + +export const VideosQuery = gql` + query VideosIndex($offset: Int! = 1, $limit: Int! = 16, $filters: VideoFilter = {}) { + videos(limit: $limit, offset: $offset, filters: $filters) { + pageNumber + totalPages + entries { + hash_id: hashId + provider_id: providerId + provider + title + insertedAt + isPartner + speakers { + full_name: fullName + id + slug + } + } + } + } +` diff --git a/app/API/matomo.js b/app/API/matomo.js new file mode 100644 index 000000000..c2ecaf05e --- /dev/null +++ b/app/API/matomo.js @@ -0,0 +1,41 @@ +import { IS_DEV } from '../config' + +/** + * Low-level function to push an event to matomo **only** if instanciated. If + * Matomo is not instanciated (which is, if `window._paq` is undefined) the event + * is simply ignored. + * + * @param {string} context The context where this happens (eg. Home, UserProfile...) + * @param {string} action The type of action (Click, Close...) + * @param {string} (optional) name + * @param {number} (optional) numeric value + */ +export const pushEvent = (context, action, name, value) => { + // Generate the event + let event = null + if (name && value) { + event = ['trackEvent', context, action, name, value] + } else if (name) { + event = ['trackEvent', context, action, name] + } else { + event = ['trackEvent', context, action] + } + + // Push the event + if ((window._paq === undefined || !window._paq) && IS_DEV) { + console.debug('[Matomo] Push event', event) + } else { + window._paq.push(event) + } +} + +/** + * Register a click on Matomo. + * + * @param {string} context The context where this happens (eg. Home, UserProfile...) + * @param {string} type of the element (eg. Link, Button) + * @param {string} name The name of the link / button (eg. signin, register...) + */ +export const registerClick = (context, type, name) => { + pushEvent(context, 'Click', `${type}-${name}`) +} diff --git a/app/static/assets/img/contributors/basile.jpg b/app/assets/ambassadors/basile.jpg similarity index 100% rename from app/static/assets/img/contributors/basile.jpg rename to app/assets/ambassadors/basile.jpg diff --git a/app/static/assets/img/contributors/dorian.jpg b/app/assets/ambassadors/dorian.jpg similarity index 100% rename from app/static/assets/img/contributors/dorian.jpg rename to app/assets/ambassadors/dorian.jpg diff --git a/app/static/assets/img/contributors/frederic.jpg b/app/assets/ambassadors/frederic.jpg similarity index 100% rename from app/static/assets/img/contributors/frederic.jpg rename to app/assets/ambassadors/frederic.jpg diff --git a/app/static/assets/img/contributors/timothee.jpg b/app/assets/ambassadors/timothee.jpg similarity index 100% rename from app/static/assets/img/contributors/timothee.jpg rename to app/assets/ambassadors/timothee.jpg diff --git a/app/static/assets/img/contributors/democratie-ouverte.jpg b/app/assets/partners/democratie-ouverte.jpg similarity index 100% rename from app/static/assets/img/contributors/democratie-ouverte.jpg rename to app/assets/partners/democratie-ouverte.jpg diff --git a/app/static/assets/img/contributors/heureka.jpg b/app/assets/partners/heureka.jpg similarity index 100% rename from app/static/assets/img/contributors/heureka.jpg rename to app/assets/partners/heureka.jpg diff --git a/app/static/assets/img/contributors/imago.jpg b/app/assets/partners/imago.jpg similarity index 100% rename from app/static/assets/img/contributors/imago.jpg rename to app/assets/partners/imago.jpg diff --git a/app/static/assets/img/contributors/maiamater.jpg b/app/assets/partners/maiamater.jpg similarity index 100% rename from app/static/assets/img/contributors/maiamater.jpg rename to app/assets/partners/maiamater.jpg diff --git a/app/static/assets/img/contributors/systemed.jpg b/app/assets/partners/systemed.jpg similarity index 100% rename from app/static/assets/img/contributors/systemed.jpg rename to app/assets/partners/systemed.jpg diff --git a/app/static/assets/img/contributors/tedxnoumea.jpg b/app/assets/partners/tedxnoumea.jpg similarity index 100% rename from app/static/assets/img/contributors/tedxnoumea.jpg rename to app/assets/partners/tedxnoumea.jpg diff --git a/app/static/assets/img/contributors/thinkerview.jpg b/app/assets/partners/thinkerview.jpg similarity index 100% rename from app/static/assets/img/contributors/thinkerview.jpg rename to app/assets/partners/thinkerview.jpg diff --git a/app/static/assets/img/contributors/troncheenbiais.jpg b/app/assets/partners/troncheenbiais.jpg similarity index 100% rename from app/static/assets/img/contributors/troncheenbiais.jpg rename to app/assets/partners/troncheenbiais.jpg diff --git a/app/static/assets/img/contributors/yeswehack.jpg b/app/assets/partners/yeswehack.jpg similarity index 100% rename from app/static/assets/img/contributors/yeswehack.jpg rename to app/assets/partners/yeswehack.jpg diff --git a/app/components/Home/AllAmbassadors.jsx b/app/components/Home/AllAmbassadors.jsx new file mode 100644 index 000000000..c181e3655 --- /dev/null +++ b/app/components/Home/AllAmbassadors.jsx @@ -0,0 +1,37 @@ +import React from 'react' +import { Link } from 'react-router' +import styled from 'styled-components' +import { Flex } from '@rebass/grid' + +import imgBasile from '../../assets/ambassadors/basile.jpg' +import imgDorian from '../../assets/ambassadors/dorian.jpg' +import imgFrederic from '../../assets/ambassadors/frederic.jpg' +import imgThimothee from '../../assets/ambassadors/timothee.jpg' + +const AMBASSADORS = [ + { name: 'Frédéric Bouffetier', username: 'DocFred', img: imgFrederic }, + { name: 'Timothée Rolland', username: 'Troplent', img: imgThimothee }, + { name: 'Dorian Cazottes', username: 'DodoLaSoudure', img: imgDorian }, + { name: 'Basile Asti', username: 'Basile', img: imgBasile } +] + +const AmbassadorPicture = styled.img` + border-radius: 1em; + margin: 0 1em; + height: 70px; +` + +/** + * Render all CaptainFact ambassadors + */ +const AllAmbassadors = () => ( + + {AMBASSADORS.map(({ name, username, img }) => ( + + + + ))} + +) + +export default AllAmbassadors diff --git a/app/components/Home/AllContributors.jsx b/app/components/Home/AllContributors.jsx deleted file mode 100644 index 3a1c55552..000000000 --- a/app/components/Home/AllContributors.jsx +++ /dev/null @@ -1,79 +0,0 @@ -import React from 'react' -import { withNamespaces } from 'react-i18next' -import ExternalLinkNewTab from '../Utils/ExternalLinkNewTab' - -const ROLE_AMBASSADOR = 'ambassador' -const ROLE_AMBASSADOR_PADAWAN = 'ambassadorPadawan' -const ROLE_DEVELOPER = 'developer' -const ROLE_DONATOR = 'donator' -const ROLE_PARTNER = 'partner' - -// prettier-ignore -const CONTRIBUTORS = [ - { role: ROLE_AMBASSADOR, name: 'Frédéric Bouffetier', picture: 'frederic' }, - { role: ROLE_AMBASSADOR, name: 'Timothée Roland', picture: 'timothee' }, - { role: ROLE_AMBASSADOR, name: 'Dorian Cazottes', picture: 'dorian' }, - { role: ROLE_PARTNER, name: 'ThinkerView', picture: 'thinkerview', url: 'https://thinkerview.com' }, - { role: ROLE_PARTNER, name: 'Heu?reka', picture: 'heureka', url: 'https://www.youtube.com/channel/UC7sXGI8p8PvKosLWagkK9wQ' }, - { role: ROLE_PARTNER, name: 'La Tronche en Biais', picture: 'troncheenbiais', url: 'https://www.youtube.com/user/TroncheEnBiais' }, - { role: ROLE_PARTNER, name: 'Système D', picture: 'systemed', url: 'https://www.systeme-d.co/' }, - { role: ROLE_PARTNER, name: 'Démocratie Ouverte', picture: 'democratie-ouverte', url: 'https://democratieouverte.org' }, - { role: ROLE_PARTNER, name: 'IMAGO', picture: 'imago', url: 'http://imagotv.fr' }, - { role: ROLE_PARTNER, name: 'TedX Nouméa', picture: 'tedxnoumea', url: 'https://tedxnoumea.com' }, - { role: ROLE_PARTNER, name: 'YesWeHack', picture: 'yeswehack', url: 'https://yeswehack.com' }, - { role: ROLE_PARTNER, name: 'Maia Mater', picture: 'maiamater', url: 'https://www.maiamater.camp' }, - { role: ROLE_DEVELOPER, name: 'Noé Gambini', picture: 'noe' }, - { role: ROLE_DONATOR, name: 'Julien Edmond', picture: 'julien' }, - { role: ROLE_DONATOR, name: 'Basile Asti', picture: 'basile' }, - { role: ROLE_DONATOR, name: 'William Amsler', picture: 'william' }, - { role: ROLE_DONATOR, name: 'William Ledoux', picture: 'williamledoux' }, - { role: ROLE_DONATOR, name: 'Adrien Albertini', picture: 'adrien' }, - { role: ROLE_DONATOR, name: 'Coline Piouffle', i18nContext: 'female', picture: 'coline' }, - { role: ROLE_DONATOR, name: 'Spiderweak', picture: 'spiderweak' }, - { role: ROLE_DONATOR, name: 'Hélène Bouffetier', i18nContext: 'female' }, - { role: ROLE_DONATOR, name: 'Jérôme Bétrancourt' }, - { role: ROLE_DONATOR, name: 'Thibaut Ladouce' }, - { role: ROLE_DONATOR, name: 'Alexandre Mira' }, - { role: ROLE_DONATOR, name: 'Loic Journet' }, - { role: ROLE_DONATOR, name: 'Francois Zedde' }, - { role: ROLE_DONATOR, name: 'William Rode' }, - { role: ROLE_DONATOR, name: 'Alain Mouchez' }, - { role: ROLE_DONATOR, name: 'Samuel Pabion' }, - { role: ROLE_DONATOR, name: 'Driss Boubekeur' }, - { role: ROLE_DONATOR, name: 'Nicolas Jeannesson' }, - { role: ROLE_DONATOR, name: 'Jean-Louis Pioch' }, -] - -const AllContributors = ({ t }) => ( -
- {CONTRIBUTORS.map(contributor => ( -
-
-
{contributorPicture(contributor)}
-
-
-

{contributorName(contributor)}

-

- {t(`roles.${contributor.role}`, { - context: contributor.i18nContext - })} -

-
-
- ))} -
-) - -function contributorName({ url, name }) { - return url ? {name} : name -} - -function contributorPicture({ picture }) { - return picture ? ( - - ) : ( - - ) -} - -export default withNamespaces('home')(AllContributors) diff --git a/app/components/Home/AllPartners.jsx b/app/components/Home/AllPartners.jsx new file mode 100644 index 000000000..923fee2fa --- /dev/null +++ b/app/components/Home/AllPartners.jsx @@ -0,0 +1,44 @@ +import React from 'react' +import { Flex, Box } from '@rebass/grid' + +import ExternalLinkNewTab from '../Utils/ExternalLinkNewTab' + +import imgImago from '../../assets/partners/imago.jpg' +import imgDemocratieOuverte from '../../assets/partners/democratie-ouverte.jpg' +import imgHeureka from '../../assets/partners/heureka.jpg' +import imgSystemeD from '../../assets/partners/systemed.jpg' +import imgTedxNoumea from '../../assets/partners/tedxnoumea.jpg' +import imgThinkerView from '../../assets/partners/thinkerview.jpg' +import imgTroncheEnBiais from '../../assets/partners/troncheenbiais.jpg' +import imgYesWeHack from '../../assets/partners/yeswehack.jpg' + +// prettier-ignore +const PARTNERS = [ + { name: 'ThinkerView', img: imgThinkerView, url: 'https://thinkerview.com' }, + { name: 'Heu?reka', img: imgHeureka, url: 'https://www.youtube.com/channel/UC7sXGI8p8PvKosLWagkK9wQ' }, + { name: 'La Tronche en Biais', img: imgTroncheEnBiais, url: 'https://www.youtube.com/user/TroncheEnBiais' }, + { name: 'Système D', img: imgSystemeD, url: 'https://www.systeme-d.co/' }, + { name: 'Démocratie Ouverte', img: imgDemocratieOuverte, url: 'https://democratieouverte.org' }, + { name: 'IMAGO', img: imgImago, url: 'https://imagotv.fr' }, + { name: 'TedX Nouméa', img: imgTedxNoumea, url: 'https://tedxnoumea.com' }, + { name: 'YesWeHack', img: imgYesWeHack, url: 'https://yeswehack.com' }, +] + +/** + * Render all CaptainFact partners + */ +const AllPartners = () => ( + + {PARTNERS.map(({ name, url, img }) => ( + + +
+ {name} +
+
+
+ ))} +
+) + +export default AllPartners diff --git a/app/components/Home/CFSocialProfiles.jsx b/app/components/Home/CFSocialProfiles.jsx new file mode 100644 index 000000000..e0a5aeabe --- /dev/null +++ b/app/components/Home/CFSocialProfiles.jsx @@ -0,0 +1,70 @@ +import React from 'react' +import PropTypes from 'prop-types' +import { Flex } from '@rebass/grid' +import styled from 'styled-components' + +import { Discord } from 'styled-icons/fa-brands/Discord' +import { Facebook } from 'styled-icons/fa-brands/Facebook' +import { Twitter } from 'styled-icons/fa-brands/Twitter' +import { Github } from 'styled-icons/fa-brands/Github' + +import ExternalLinkNewTab from '../Utils/ExternalLinkNewTab' + +const IconLinkContainer = styled(ExternalLinkNewTab)` + color: white; + margin: 0 0.5em; +` + +/** + * Render a social icon with the proper link and add a popup with the title + * of the social network. + */ +const SocialIconLink = ({ Icon, name, url, size }) => { + return ( + + + + ) +} + +/** + * Render social profiles icons for other CaptainFact profiles on + * Facebook, Twitter... + */ +const CFSocialProfiles = ({ size = '2em' }) => { + return ( + + + + + + + ) +} + +CFSocialProfiles.propTypes = { + /** Icons size. Default to 2em */ + size: PropTypes.string +} + +export default CFSocialProfiles diff --git a/app/components/Home/Home.jsx b/app/components/Home/Home.jsx index d670b267a..09d2811eb 100644 --- a/app/components/Home/Home.jsx +++ b/app/components/Home/Home.jsx @@ -2,80 +2,131 @@ import React from 'react' import { connect } from 'react-redux' import { Link } from 'react-router' import { withNamespaces, Trans } from 'react-i18next' +import { Flex, Box } from '@rebass/grid' +import * as Matomo from '../../API/matomo' import { Icon } from '../Utils' import InvitationRequestForm from '../Users/InvitationRequestForm' import { isAuthenticated } from '../../state/users/current_user/selectors' -import Logo from '../App/Logo' -import ExternalLinkNewTab from '../Utils/ExternalLinkNewTab' import { INVITATION_SYSTEM } from '../../config' -import AllContributors from './AllContributors' -import Statistics from './Statistics' -import landingIllustration from '../../assets/landing-illustration.jpg' +import AllPartners from './AllPartners' +import OpenCollectiveContributors from './OpenCollectiveContributors' +import AllAmbassadors from './AllAmbassadors' +import ExternalLinkNewTab from '../Utils/ExternalLinkNewTab' +import CFSocialProfiles from './CFSocialProfiles' +import LastVideos from './LastVideos' +import Message from '../Utils/Message' @connect(state => ({ authenticated: isAuthenticated(state) })) @withNamespaces('home') export default class Home extends React.PureComponent { + renderPresentation() { + return ( +

+ {this.props.t('presentation1')} +
+
+ CaptainFact {this.props.t('presentation2')} +

+ ) + } + + renderButtons() { + return ( +
+ Matomo.registerClick('Home', 'Button', 'SignUp')} + className="button animated-hover is-medium is-gradient-primary-light" + to="/signup" + > + {this.props.t('registerAndFactCheck')} + + Matomo.registerClick('Home', 'Button', 'ExtensionPage')} + className="button animated-hover is-medium is-gradient-primary-light" + to="/extension" + > + {this.props.t('installExtension')} + +
+ 100%{' '} + + open-source + + , respecte votre vie privée +
+
+ ) + } + render() { const { t } = this.props return ( -
+
-
- -

- Let's check the Internet -

+
+
+

Let's check the Internet

+ {this.renderPresentation()} +
+
+
+

{t('start')}

+ {this.renderButtons()} +
-
-
-

- {t('presentation1')} -
-
- CaptainFact {t('presentation2')} -

+
+
+
+

{t('partners')}

+
+ +
+
+
+ + +

{t('backers')}

+ + +
+ +

{t('ambassadors')}

+ + {t('aboutAmbassadors')}{' '} + {t('learnMore')} + + +
+

-
- - -    {t('main:menu.help')} - - - -    {t('seeVideos')} - - - -    {t('main:menu.donation')} - -
-
- +
+
-
-

{t('videoDebate:community')}

- -
-
-

{t('contributors')}

- - - - {t('seeAllContributors')} - +
+
+
+
+

Les dernières vidéos ajoutées

+ Matomo.registerClick('Home', 'Button', 'SeeAllVideos')} + className="button animated-hover is-medium is-gradient-primary-light" + to="/videos" + > + {this.props.t('seeVideos')} + +
+
+
+
+ +
{INVITATION_SYSTEM && (
@@ -94,10 +145,13 @@ export default class Home extends React.PureComponent { Created with using - Elixir,  - Phoenix + Elixir + ,  + + Phoenix +  {this.props.t('main:misc.and')}  - React + React
diff --git a/app/components/Home/LastVideos.jsx b/app/components/Home/LastVideos.jsx new file mode 100644 index 000000000..8fb2a3d82 --- /dev/null +++ b/app/components/Home/LastVideos.jsx @@ -0,0 +1,35 @@ +import React from 'react' +import { Query } from 'react-apollo' +import { Flex } from '@rebass/grid' +import styled from 'styled-components' + +import { VideosQuery } from '../../API/graphql_queries' +import { VideoCard } from '../Videos/VideoCard' + +const VideosContainer = styled(Flex)` + flex-wrap: wrap; + justify-content: center; + // Override the default Bulma .column. + .column { + flex-basis: 250px; + min-width: 250px; + } +` + +const LastVideos = () => { + return ( + + + {({ data }) => { + return data && data.videos && data.videos.entries.length > 0 + ? data.videos.entries.map(video => ( + + )) + : null + }} + + + ) +} + +export default LastVideos diff --git a/app/components/Home/OpenCollectiveContributors.jsx b/app/components/Home/OpenCollectiveContributors.jsx new file mode 100644 index 000000000..57ef1dd1f --- /dev/null +++ b/app/components/Home/OpenCollectiveContributors.jsx @@ -0,0 +1,37 @@ +import React from 'react' +import PropTypes from 'prop-types' +import { optionsToQueryString } from '../../lib/url_utils' + +/** + * Embed https://opencollective.com contributors. + */ +const OpenCollectiveContributors = ({ + tier, + avatarHeight = 72, + button = true, + width = 325 +}) => { + const queryParams = optionsToQueryString({ + avatarHeight, + button, + width + }) + + return ( + + ) +} + +OpenCollectiveContributors.propTypes = { + tier: PropTypes.oneOf(['soutien-régulier', 'donateur']).isRequired, + avatarHeight: PropTypes.number, + width: PropTypes.number, + button: PropTypes.bool +} + +export default OpenCollectiveContributors diff --git a/app/components/Videos/PaginatedVideosContainer.jsx b/app/components/Videos/PaginatedVideosContainer.jsx index 0c597a661..afd8e18d4 100644 --- a/app/components/Videos/PaginatedVideosContainer.jsx +++ b/app/components/Videos/PaginatedVideosContainer.jsx @@ -1,35 +1,13 @@ import React from 'react' import { Query } from 'react-apollo' import { Link } from 'react-router' -import gql from 'graphql-tag' import { withNamespaces } from 'react-i18next' import { LoadingFrame } from '../Utils/LoadingFrame' import { ErrorView } from '../Utils/ErrorView' import { VideosGrid } from './VideosGrid' import PaginationMenu from '../Utils/PaginationMenu' import { ALL_VIDEOS, ONLY_PARTNERS } from '../../constants' - -const QUERY = gql` - query VideosIndex($offset: Int!, $limit: Int!, $filters: VideoFilter) { - videos(limit: $limit, offset: $offset, filters: $filters) { - pageNumber - totalPages - entries { - hash_id: hashId - provider_id: providerId - provider - title - insertedAt - isPartner - speakers { - full_name: fullName - id - slug - } - } - } - } -` +import { VideosQuery } from '../../API/graphql_queries' const INITIAL_VIDEOS = { pageNumber: 1, totalPages: 1, entries: [] } @@ -42,12 +20,19 @@ const buildFiltersFromProps = ({ language, source, speakerID }) => { return filters } -const PaginatedVideosContainer = ({ t, currentPage = 1, baseURL, ...props }) => { +const PaginatedVideosContainer = ({ + t, + baseURL, + showPagination = true, + currentPage = 1, + limit = 16, + ...props +}) => { const filters = buildFiltersFromProps(props) return ( {({ loading, error, data }) => { @@ -56,7 +41,7 @@ const PaginatedVideosContainer = ({ t, currentPage = 1, baseURL, ...props }) => if (!loading && videos.entries.length === 0) return

{t('errors:client.noVideoAvailable')}

- const paginationMenu = ( + const paginationMenu = !showPagination ? null : ( using ', emailPlaceholder: 'Email address', inviteSuccess: 'Invitation request confirmed!', - error_invalid_email: 'Invalid email address', - registeredUsers: 'registered users', - verifiedStatements: 'verified quotes', - contributors: 'Contributors', - seeAllContributors: 'See all contributors on OpenCollective', - roles: { - ambassador: 'Ambassador', - ambassadorPadawan: 'Padawan Ambassador', - developer: 'Developer', - donator: 'Donator', - partner: 'Partner' - } + registerAndFactCheck: 'Signup and fact-check', + installExtension: 'Install Extension', + partners: 'Our partners', + ambassadors: 'Ambassadors', + start: "Let's go!", + backers: 'Backers', + learnMore: 'Learn more', + aboutAmbassadors: + "Ambassadors are special members in charge of looking after the community. They also aim to report users' expectations to the technical team and participate in the governance of the project." } diff --git a/app/i18n/fr/home.js b/app/i18n/fr/home.js index 9f16c47f9..d58980fe3 100644 --- a/app/i18n/fr/home.js +++ b/app/i18n/fr/home.js @@ -3,24 +3,19 @@ export default { "Internet est rempli de données riches et diverses. L'information voyage vite et nous n'avons pas le temps de vérifier si tout ce que nous entendons et voyons est correct.", presentation2: 'nous permet de débattre et de nous entraider pour vérifier ces données en les sourçant, en votant et en discutant autour de faits.', - seeVideos: 'Voir les vidéos', - creatingAnAccount: 'créant un compte', + seeVideos: 'Voir toutes les vidéos', invitation: 'Demander une invitation', inviteFriend: 'Inviter un ami', footer: "Créé avec <1/> à l'aide d'", emailPlaceholder: 'Adresse e-mail', inviteSuccess: "Demande d'invitation enregistrée !", - error_invalid_email: 'Adresse e-mail invalide', - registeredUsers: 'utilisateurs inscrits', - verifiedStatements: 'citations vérifiées', - contributors: 'Contributeurs', - seeAllContributors: 'Voir tous les contributeurs sur OpenCollective', - roles: { - ambassador: 'Ambassadeur', - ambassadorPadawan: 'Ambassadeur Padawan', - developer: 'Développeur', - donator: 'Donateur', - donator_female: 'Donatrice', - partner: 'Partenaire' - } + registerAndFactCheck: "S'inscrire et vérifier", + installExtension: "Installer l'extension", + partners: 'Les partenaires', + ambassadors: 'Ambassadeurs', + start: 'Commencer', + backers: 'Soutiens', + learnMore: 'En savoir plus', + aboutAmbassadors: + 'Les ambassadeurs sont chargés de veiller sur la communauté. Ils ont aussi pour objectif de faire remonter les attentes des utilisateurs et de participer à la gouvernance du projet.' } diff --git a/app/index.jsx b/app/index.jsx index d7fdb4366..74b52731e 100644 --- a/app/index.jsx +++ b/app/index.jsx @@ -6,6 +6,7 @@ import React from 'react' import ReactDOM from 'react-dom' import { Provider } from 'react-redux' import { ApolloProvider } from 'react-apollo' +import { ThemeProvider } from 'styled-components' // Load store import store from './state' @@ -17,6 +18,7 @@ import GraphQLClient from './API/graphql_api' import CFRouter from './router' // Import styles import './styles/application.sass' +import theme from './styles/theme' // Activate polyfills smoothSrollPolyfill() @@ -25,7 +27,9 @@ smoothSrollPolyfill() ReactDOM.render( - + + + , document.getElementById('app') diff --git a/app/static/assets/img/contributors/adrien.jpg b/app/static/assets/img/contributors/adrien.jpg deleted file mode 100644 index 39f62d3d7..000000000 Binary files a/app/static/assets/img/contributors/adrien.jpg and /dev/null differ diff --git a/app/static/assets/img/contributors/coline.jpg b/app/static/assets/img/contributors/coline.jpg deleted file mode 100644 index bbd9f0639..000000000 Binary files a/app/static/assets/img/contributors/coline.jpg and /dev/null differ diff --git a/app/static/assets/img/contributors/julien.jpg b/app/static/assets/img/contributors/julien.jpg deleted file mode 100644 index 0a686f965..000000000 Binary files a/app/static/assets/img/contributors/julien.jpg and /dev/null differ diff --git a/app/static/assets/img/contributors/no-picture.svg b/app/static/assets/img/contributors/no-picture.svg deleted file mode 100644 index 110493eb6..000000000 --- a/app/static/assets/img/contributors/no-picture.svg +++ /dev/null @@ -1,58 +0,0 @@ - - diff --git a/app/static/assets/img/contributors/noe.jpg b/app/static/assets/img/contributors/noe.jpg deleted file mode 100644 index c78127d2a..000000000 Binary files a/app/static/assets/img/contributors/noe.jpg and /dev/null differ diff --git a/app/static/assets/img/contributors/spiderweak.jpg b/app/static/assets/img/contributors/spiderweak.jpg deleted file mode 100644 index 05627806c..000000000 Binary files a/app/static/assets/img/contributors/spiderweak.jpg and /dev/null differ diff --git a/app/static/assets/img/contributors/william.jpg b/app/static/assets/img/contributors/william.jpg deleted file mode 100644 index 5d8e0ff37..000000000 Binary files a/app/static/assets/img/contributors/william.jpg and /dev/null differ diff --git a/app/static/assets/img/contributors/williamledoux.jpg b/app/static/assets/img/contributors/williamledoux.jpg deleted file mode 100644 index 7fd4a642b..000000000 Binary files a/app/static/assets/img/contributors/williamledoux.jpg and /dev/null differ diff --git a/app/styles/_components/Pages/home_page.sass b/app/styles/_components/Pages/home_page.sass index ff464ce20..be8bad798 100644 --- a/app/styles/_components/Pages/home_page.sass +++ b/app/styles/_components/Pages/home_page.sass @@ -1,85 +1,116 @@ .home-page + $maxHomeSectionWidth: 1160px min-height: 100vh display: flex flex-direction: column - background: linear-gradient(45deg, #78b4b4, #5c8686 70%, #3c5a73) fixed - background-color: #5c8686 + background-attachment: fixed + + +mobile + .title + text-align: center + .columns.is-multiline + justify-content: center .hero min-height: 25vh + .title, p, strong + color: $white + .buttons-container + .button, .button-label + @include ProgressiveAnimationDelay(0.1s, 0.3s, 3) + animation-name: fadeInUp + animation-duration: 0.8s + animation-fill-mode: backwards + .button + width: 100% + margin-bottom: 1em + flex-basis: 240px + padding: 1.2em 1em + font-size: 1.4em + border: 1px solid darken($white, 10) + &:last-of-type + margin-bottom: 0.25em + .button-label + text-align: center + color: $white-bis + a + color: $info + &:hover + text-decoration: underline +mobile min-height: 20vh .hero-body - padding: 5rem + padding: 6em 4em + margin: 0 auto + max-width: $maxHomeSectionWidth +mobile padding: 3rem 1rem font-size: 12px - .site-logo - @include animate(bounceInDown, 0.7s) - .logo-captain - color: $logo-inside-color - .logo-fact - color: lighten($logo-inside-color, 10) - .subtitle - @include animate(fadeIn, 1s) - animation-delay: 0.7s - .title - text-shadow: 1px 1px 1px rgba(74, 74, 74, 0.34) - color: #3c4852 - font-size: 3em - margin: 0 - img - width: 80px - .subtitle - font-style: italic - color: #f3f3f3 - margin-top: 10px + +tablet + padding: 3em 2em + +desktop + padding: 6em 4em + .logo-container + text-align: center + margin-bottom: 3em + + .last-videos-cards + margin: 0 auto + max-width: $maxHomeSectionWidth + + .presentation + font-size: $size-5 .section margin: 0 h2 margin-bottom: 1em - .presentation - @include animate(fadeIn, 1s) - padding: 4rem 4rem 2rem - min-height: 45vh - flex-grow: 1 - display: flex - flex-direction: column - justify-content: center - background: $white + .separator + height: 12em + width: 100% + margin-top: -6em; + background-color: $white + clip-path: ellipse(55% 40% at 50% 100%) +mobile - padding: 3rem - min-height: 65vh - &> div - max-width: 1000px + clip-path: ellipse(60% 25% at 50% 100%) + + .section:not(.hero) + .title + color: $primary + +mobile + .title.is-3 + margin-bottom: 1em + + .partners + background: $white + padding: 0 + + .content + max-width: $maxHomeSectionWidth margin: 0 auto + padding: 4em 3em + +mobile + padding: 2em 1em + .image + @include animate(fadeIn, 1s) + margin-left: 0 + margin-right: 1.3em + .opencollective-contributors + max-width: 100% + display: block + +mobile + margin: 0 auto .actions display: flex flex-wrap: wrap justify-content: center - .button - flex-basis: 240px - animation-name: fadeInUp - animation-duration: 1s - animation-fill-mode: backwards - @include ProgressiveAnimationDelay(0.1s, 0.3s, 3) - margin: 0.3em 0.25em - padding: 1.3em 1em - font-size: 1.6em - box-shadow: -1px 2px 8px #457480 - transition: box-shadow 0.2s, transform 0.2s - transform: translateY(0) scale(1) - border: 1px solid $grey - &:hover - box-shadow: -1px 7px 14px #476f79 - transform: translateY(-0.15em) scale(1.025) - .illustration + .last-videos background: $white min-height: 15vh + padding: 1em .community background: #5abda8 @@ -125,6 +156,7 @@ padding: 1.5rem 1.5rem justify-content: flex-end border-top: 1px solid lighten($border, 5) + color: $dark .icon-heart color: $red diff --git a/app/styles/_components/User/user_page.sass b/app/styles/_components/User/user_page.sass index 388c45112..39c6f8942 100644 --- a/app/styles/_components/User/user_page.sass +++ b/app/styles/_components/User/user_page.sass @@ -56,7 +56,7 @@ width: 100% .linked-account-title - background-color: lighten($info, 20) + background-color: #4267b2 color: $info-invert height: 2.25em padding: 0.35em 1em diff --git a/app/styles/_components/Videos/index.sass b/app/styles/_components/Videos/index.sass index 3efd6a240..7fa130ac4 100644 --- a/app/styles/_components/Videos/index.sass +++ b/app/styles/_components/Videos/index.sass @@ -21,12 +21,15 @@ $videos-list-max-width: 1300px .field, .control margin: 0 +.videos-page, .speaker-page + .videos-list + border-top: 1px solid #e8e8e8 + border-bottom: 1px solid #e8e8e8 + .videos-list margin: 0 auto justify-content: center max-width: $videos-list-max-width - border-top: 1px solid #e8e8e8 - border-bottom: 1px solid #e8e8e8 padding: 1em 0 .column diff --git a/app/styles/_global/buttons.sass b/app/styles/_global/buttons.sass new file mode 100644 index 000000000..acc6f85c3 --- /dev/null +++ b/app/styles/_global/buttons.sass @@ -0,0 +1,7 @@ +.button.animated-hover + transition: box-shadow 0.2s, transform 0.2s + transform: translateY(0) scale(1) + box-shadow: -1px 2px 8px #457480 + &:hover + box-shadow: -1px 7px 14px #476f79 + transform: translateY(-0.15em) scale(1.025) diff --git a/app/styles/_global/global.sass b/app/styles/_global/global.sass index 8d5ff80e5..02cb37570 100644 --- a/app/styles/_global/global.sass +++ b/app/styles/_global/global.sass @@ -23,4 +23,28 @@ a[disabled] width: 40px h1 - font-family: $family-serif \ No newline at end of file + font-family: $family-serif + +.is-gradient-primary + background: linear-gradient(45deg, #78b4b4, #5c8686 70%, #3c5a73) + background-color: #5c8686 + color: $white-bis + +.is-gradient-primary-light + background: linear-gradient(15deg, lighten($primary, 5), darken($primary, 5) 70%) + background-color: $primary + color: $white-bis + border: none + &:hover, &:active, &:focus + color: $white-bis + border-color: $grey-light + +.is-gradient-info + background: linear-gradient(45deg, $info, darken($info, 30) 65%) + background-color: $info + color: $white-bis + +.button.is-gradient-info + border-color: darken($white, 15) + &:hover + color: darken($white, 10) diff --git a/app/styles/_global/variables.sass b/app/styles/_global/variables.sass index a9483a871..4049080fe 100644 --- a/app/styles/_global/variables.sass +++ b/app/styles/_global/variables.sass @@ -7,7 +7,7 @@ $green: #39b714 $red: #e0454e -$blue: #1c49d2 +$blue: #75caff $primary: #6ba3a7 $primary-dark: #1B6DB6 @@ -68,7 +68,7 @@ $sidebar_width: 270px $sidebar_collapsed_width: 60px $sidebar_collapse_transition_duration: 0.10s $sidebar_full_collapse_under: $tablet - 1 -$sidebar_full_collapse_banner_height: 75px +$sidebar_full_collapse_banner_height: 70px @import "bulma/sass/utilities/derived-variables" diff --git a/app/styles/application.sass b/app/styles/application.sass index 0505cf2ea..e957c4835 100644 --- a/app/styles/application.sass +++ b/app/styles/application.sass @@ -55,6 +55,7 @@ // Custom styles @import "_global/global" +@import "_global/buttons" @import "_global/icons" @import "_global/icons_list" @import "_global/card" diff --git a/app/styles/theme.js b/app/styles/theme.js new file mode 100644 index 000000000..820693a5f --- /dev/null +++ b/app/styles/theme.js @@ -0,0 +1,12 @@ +const theme = { + breakpoints: ['768px', '1024px', '1216px', '1408px'], + colors: { + green: '#39b714', + red: '#e0454e', + blue: '#75caff', + primary: '#6ba3a7', + info: '#75caff' + } +} + +export default theme diff --git a/package-lock.json b/package-lock.json index 867e251bf..6ca252b06 100644 --- a/package-lock.json +++ b/package-lock.json @@ -34,6 +34,31 @@ } } }, + "@babel/helper-annotate-as-pure": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz", + "integrity": "sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q==", + "requires": { + "@babel/types": "^7.0.0" + }, + "dependencies": { + "@babel/types": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.1.6.tgz", + "integrity": "sha512-DMiUzlY9DSjVsOylJssxLHSgj6tWM9PRFJOGW/RaOglVOK9nzTxoOMfTfRQXGUCUQ/HmlG2efwC+XqUEJ5ay4w==", + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.10", + "to-fast-properties": "^2.0.0" + } + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" + } + } + }, "@babel/helper-function-name": { "version": "7.0.0-beta.44", "resolved": "http://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.44.tgz", @@ -212,6 +237,24 @@ } } }, + "@emotion/is-prop-valid": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.6.8.tgz", + "integrity": "sha512-IMSL7ekYhmFlILXcouA6ket3vV7u9BqStlXzbKOF9HBtpUPMMlHU+bBxrLOa2NvleVwNIxeq/zL8LafLbeUXcA==", + "requires": { + "@emotion/memoize": "^0.6.6" + } + }, + "@emotion/memoize": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.6.6.tgz", + "integrity": "sha512-h4t4jFjtm1YV7UirAFuSuFGyLa+NNxjdkq6DpFLANNQY5rHueFZHVY+8Cu1HYVP6DrheB0kv4m5xPjo7eKT7yQ==" + }, + "@emotion/unitless": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.3.tgz", + "integrity": "sha512-4zAPlpDEh2VwXswwr/t8xGNDGg8RQiPxtxZ3qQEXyQsBV39ptTdESCjuBvGze1nLMVrxmTIKmnO/nAV8Tqjjzg==" + }, "@iamstarkov/listr-update-renderer": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/@iamstarkov/listr-update-renderer/-/listr-update-renderer-0.4.1.tgz", @@ -287,6 +330,14 @@ } } }, + "@rebass/grid": { + "version": "6.0.0-5", + "resolved": "https://registry.npmjs.org/@rebass/grid/-/grid-6.0.0-5.tgz", + "integrity": "sha512-HxAMY4/E57qoHdqI2D6xCZEw9p4ZUQP6PfoGok/je/PzbkiV+NAEtIwCO/ZHwwKW04zQe5shMc3rLaN2nxRufQ==", + "requires": { + "styled-system": "^3.1.11" + } + }, "@samverschueren/stream-to-observable": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz", @@ -1598,6 +1649,16 @@ "integrity": "sha1-5h+uBaHKiAGq3uV6bWa4zvr0QWc=", "dev": true }, + "babel-plugin-styled-components": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-1.9.2.tgz", + "integrity": "sha512-McnheW8RkBkur/mQw7rEwQO/oUUruQ/nIIj5LIRpsVL8pzG1oo1Y53xyvAYeOfamIrl4/ta7g1G/kuTR1ekO3A==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.0.0", + "babel-plugin-syntax-jsx": "^6.18.0", + "lodash": "^4.17.10" + } + }, "babel-plugin-syntax-async-functions": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", @@ -1631,8 +1692,7 @@ "babel-plugin-syntax-jsx": { "version": "6.18.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", - "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=", - "dev": true + "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=" }, "babel-plugin-syntax-object-rest-spread": { "version": "6.13.0", @@ -3785,6 +3845,11 @@ "randomfill": "^1.0.3" } }, + "css-color-keywords": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", + "integrity": "sha1-/qJhbcZ2spYmhrOvjb2+GAskTgU=" + }, "css-color-names": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", @@ -3911,6 +3976,37 @@ } } }, + "css-to-react-native": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-2.2.2.tgz", + "integrity": "sha512-w99Fzop1FO8XKm0VpbQp3y5mnTnaS+rtCvS+ylSEOK76YXO5zoHQx/QMB1N54Cp+Ya9jB9922EHrh14ld4xmmw==", + "requires": { + "css-color-keywords": "^1.0.0", + "fbjs": "^0.8.5", + "postcss-value-parser": "^3.3.0" + }, + "dependencies": { + "core-js": { + "version": "1.2.7", + "resolved": "http://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", + "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=" + }, + "fbjs": { + "version": "0.8.17", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.17.tgz", + "integrity": "sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=", + "requires": { + "core-js": "^1.0.0", + "isomorphic-fetch": "^2.1.1", + "loose-envify": "^1.0.0", + "object-assign": "^4.1.0", + "promise": "^7.1.1", + "setimmediate": "^1.0.5", + "ua-parser-js": "^0.7.18" + } + } + } + }, "css-tree": { "version": "1.0.0-alpha.28", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.28.tgz", @@ -5482,8 +5578,7 @@ "esutils": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", - "dev": true + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" }, "etag": { "version": "1.8.1", @@ -7064,8 +7159,7 @@ "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, "has-symbols": { "version": "1.0.0", @@ -10675,6 +10769,11 @@ "mimic-fn": "^1.0.0" } }, + "memoize-one": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-4.0.3.tgz", + "integrity": "sha512-QmpUu4KqDmX0plH4u+tf0riMc1KHE1+lw95cMrLlXQAFOx/xnBtwhZ52XJxd9X2O6kwKBqX32kmhbhlobD0cuw==" + }, "memory-fs": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", @@ -17548,8 +17647,7 @@ "postcss-value-parser": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz", - "integrity": "sha1-h/OPnxj3dKSrTIojL1xc6IcqnRU=", - "dev": true + "integrity": "sha1-h/OPnxj3dKSrTIojL1xc6IcqnRU=" }, "prelude-ls": { "version": "1.1.2", @@ -20659,6 +20757,52 @@ } } }, + "styled-components": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-4.1.2.tgz", + "integrity": "sha512-NdvWatJ2WLqZxAvto+oH0k7GAC/TlAUJTrHoXJddjbCrU6U23EmVbb9LXJBF+d6q6hH+g9nQYOWYPUeX/Vlc2w==", + "requires": { + "@emotion/is-prop-valid": "^0.6.8", + "@emotion/unitless": "^0.7.0", + "babel-plugin-styled-components": ">= 1", + "css-to-react-native": "^2.2.2", + "memoize-one": "^4.0.0", + "prop-types": "^15.5.4", + "react-is": "^16.6.0", + "stylis": "^3.5.0", + "stylis-rule-sheet": "^0.0.10", + "supports-color": "^5.5.0" + }, + "dependencies": { + "react-is": { + "version": "16.6.3", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.6.3.tgz", + "integrity": "sha512-u7FDWtthB4rWibG/+mFbVd5FvdI20yde86qKGx4lVUTWmPlSWQ4QxbBIrrs+HnXGbxOUlUzTAP/VDmvCwaP2yA==" + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "styled-icons": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/styled-icons/-/styled-icons-5.2.2.tgz", + "integrity": "sha512-9xus9e/rzuccgBB4LLNtKcl3ZYF2lmy3uj9Uz7KUahrfVIWZ8KDyFgH+O3VzsWyfKwVzSONNht//2ZberDnwRA==" + }, + "styled-system": { + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/styled-system/-/styled-system-3.1.11.tgz", + "integrity": "sha512-d0p32F7Y55uRWNDb1P0JcIiGVi13ZxiSCvn8zNS68exAKW9Q5jp+IGTXUIavQOD/J8r3tydtE3vRk8Ii2i39HA==", + "requires": { + "@babel/runtime": "^7.1.2", + "prop-types": "^15.6.2" + } + }, "stylehacks": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.1.tgz", @@ -20729,6 +20873,16 @@ } } }, + "stylis": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-3.5.4.tgz", + "integrity": "sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q==" + }, + "stylis-rule-sheet": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stylis-rule-sheet/-/stylis-rule-sheet-0.0.10.tgz", + "integrity": "sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw==" + }, "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", diff --git a/package.json b/package.json index 1f77dc9d9..433173563 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,7 @@ ] }, "dependencies": { + "@rebass/grid": "^6.0.0-5", "animate.scss": "0.0.6", "apollo-boost": "^0.1.12", "babel-polyfill": "^6.26.0", @@ -95,6 +96,9 @@ "redux-thunk": "^2.2.0", "reselect": "^4.0.0", "smoothscroll-polyfill": "^0.4.0", + "styled-components": "^4.1.2", + "styled-icons": "^5.2.2", + "styled-system": "^3.1.11", "tinycon": "^0.6.8", "uuid": "^3.3.2", "validator": "10.8.0", @@ -106,6 +110,7 @@ "babel-eslint": "^8.2.6", "babel-jest": "^23.4.2", "babel-loader": "^7.1.5", + "babel-plugin-styled-components": "^1.9.2", "babel-plugin-transform-class-properties": "^6.24.1", "babel-plugin-transform-decorators-legacy": "^1.3.5", "babel-plugin-transform-object-rest-spread": "^6.26.0",