From 537702322fd9c6520628acd5e2de679f936aaacd Mon Sep 17 00:00:00 2001 From: Benjamin Piouffle Date: Sat, 1 Dec 2018 01:19:34 +0100 Subject: [PATCH 1/4] [WIP] New homepage --- .eslintrc.yml | 78 +++++----- .../ambassadors}/basile.jpg | Bin .../ambassadors}/dorian.jpg | Bin .../ambassadors}/frederic.jpg | Bin .../ambassadors}/timothee.jpg | Bin .../partners}/democratie-ouverte.jpg | Bin .../partners}/heureka.jpg | Bin .../partners}/imago.jpg | Bin .../partners}/maiamater.jpg | Bin .../partners}/systemed.jpg | Bin .../partners}/tedxnoumea.jpg | Bin .../partners}/thinkerview.jpg | Bin .../partners}/troncheenbiais.jpg | Bin .../partners}/yeswehack.jpg | Bin app/components/Home/AllAmbassadors.jsx | 27 ++++ app/components/Home/AllContributors.jsx | 79 ---------- app/components/Home/AllPartners.jsx | 37 +++++ app/components/Home/Home.jsx | 126 +++++++++------- .../Home/OpenCollectiveContributors.jsx | 34 +++++ app/i18n/en/home.js | 12 +- app/i18n/fr/home.js | 13 +- app/static/assets/img/contributors/adrien.jpg | Bin 5789 -> 0 bytes app/static/assets/img/contributors/coline.jpg | Bin 3276 -> 0 bytes app/static/assets/img/contributors/julien.jpg | Bin 7278 -> 0 bytes .../assets/img/contributors/no-picture.svg | 58 -------- app/static/assets/img/contributors/noe.jpg | Bin 22545 -> 0 bytes .../assets/img/contributors/spiderweak.jpg | Bin 5761 -> 0 bytes .../assets/img/contributors/william.jpg | Bin 4750 -> 0 bytes .../assets/img/contributors/williamledoux.jpg | Bin 6190 -> 0 bytes app/styles/_components/Pages/home_page.sass | 139 +++++++++++------- app/styles/_components/User/user_page.sass | 2 +- app/styles/_global/global.sass | 22 ++- app/styles/_global/variables.sass | 4 +- 33 files changed, 332 insertions(+), 299 deletions(-) rename app/{static/assets/img/contributors => assets/ambassadors}/basile.jpg (100%) rename app/{static/assets/img/contributors => assets/ambassadors}/dorian.jpg (100%) rename app/{static/assets/img/contributors => assets/ambassadors}/frederic.jpg (100%) rename app/{static/assets/img/contributors => assets/ambassadors}/timothee.jpg (100%) rename app/{static/assets/img/contributors => assets/partners}/democratie-ouverte.jpg (100%) rename app/{static/assets/img/contributors => assets/partners}/heureka.jpg (100%) rename app/{static/assets/img/contributors => assets/partners}/imago.jpg (100%) rename app/{static/assets/img/contributors => assets/partners}/maiamater.jpg (100%) rename app/{static/assets/img/contributors => assets/partners}/systemed.jpg (100%) rename app/{static/assets/img/contributors => assets/partners}/tedxnoumea.jpg (100%) rename app/{static/assets/img/contributors => assets/partners}/thinkerview.jpg (100%) rename app/{static/assets/img/contributors => assets/partners}/troncheenbiais.jpg (100%) rename app/{static/assets/img/contributors => assets/partners}/yeswehack.jpg (100%) create mode 100644 app/components/Home/AllAmbassadors.jsx delete mode 100644 app/components/Home/AllContributors.jsx create mode 100644 app/components/Home/AllPartners.jsx create mode 100644 app/components/Home/OpenCollectiveContributors.jsx delete mode 100644 app/static/assets/img/contributors/adrien.jpg delete mode 100644 app/static/assets/img/contributors/coline.jpg delete mode 100644 app/static/assets/img/contributors/julien.jpg delete mode 100644 app/static/assets/img/contributors/no-picture.svg delete mode 100644 app/static/assets/img/contributors/noe.jpg delete mode 100644 app/static/assets/img/contributors/spiderweak.jpg delete mode 100644 app/static/assets/img/contributors/william.jpg delete mode 100644 app/static/assets/img/contributors/williamledoux.jpg 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/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..07f6d1b8d --- /dev/null +++ b/app/components/Home/AllAmbassadors.jsx @@ -0,0 +1,27 @@ +import React from 'react' + +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', img: imgFrederic }, + { name: 'Timothée Rolland', img: imgThimothee }, + { name: 'Dorian Cazottes', img: imgDorian }, + { name: 'Basile Asti', img: imgBasile } +] + +const AllAmbassadors = () => ( +
+ {AMBASSADORS.map(ambassador => ( +
+
+ {ambassador.name} +
+
+ ))} +
+) + +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..d3bbb581f --- /dev/null +++ b/app/components/Home/AllPartners.jsx @@ -0,0 +1,37 @@ +import React from 'react' +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' }, +] + +const AllPartners = () => ( +
+ {PARTNERS.map(partner => ( + +
+ {partner.name} +
+
+ ))} +
+) + +export default AllPartners diff --git a/app/components/Home/Home.jsx b/app/components/Home/Home.jsx index d670b267a..bba8a6546 100644 --- a/app/components/Home/Home.jsx +++ b/app/components/Home/Home.jsx @@ -6,77 +6,96 @@ import { withNamespaces, Trans } from 'react-i18next' 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' @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 ( +
+ + {this.props.t('seeVideos')} + + + {this.props.t('registerAndFactCheck')} + + + {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('contributors')}

+ +
+

{t('ambassadors')}

+ +
+

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

Add social networks here

+

Quelques vidéos au hasard

+
+
+
-
-

{t('videoDebate:community')}

- -
-
-

{t('contributors')}

- - - - {t('seeAllContributors')} - -
{INVITATION_SYSTEM && (

@@ -94,10 +113,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/OpenCollectiveContributors.jsx b/app/components/Home/OpenCollectiveContributors.jsx new file mode 100644 index 000000000..9c171ae78 --- /dev/null +++ b/app/components/Home/OpenCollectiveContributors.jsx @@ -0,0 +1,34 @@ +import React from 'react' +import PropTypes from 'prop-types' +import { optionsToQueryString } from '../../lib/url_utils' + +const OpenCollectiveContributors = ({ + tier, + avatarHeight = 72, + showBtn = true, + width = 325 +}) => { + const queryParams = optionsToQueryString({ + avatarHeight, + showBtn, + width + }) + + return ( + + ) +} + +OpenCollectiveContributors.propTypes = { + tier: PropTypes.oneOf(['soutien-régulier', 'donateur']).isRequired, + avatarHeight: PropTypes.number, + width: PropTypes.number, + showBtn: PropTypes.bool +} + +export default OpenCollectiveContributors diff --git a/app/i18n/en/home.js b/app/i18n/en/home.js index ce0ce2588..61e6b0b24 100644 --- a/app/i18n/en/home.js +++ b/app/i18n/en/home.js @@ -15,11 +15,9 @@ export default { 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!" } diff --git a/app/i18n/fr/home.js b/app/i18n/fr/home.js index 9f16c47f9..ba0a796e8 100644 --- a/app/i18n/fr/home.js +++ b/app/i18n/fr/home.js @@ -15,12 +15,9 @@ export default { 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' } diff --git a/app/static/assets/img/contributors/adrien.jpg b/app/static/assets/img/contributors/adrien.jpg deleted file mode 100644 index 39f62d3d7615ab57a09f1fb4157f6b47fe7984db..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5789 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 diff --git a/app/static/assets/img/contributors/coline.jpg b/app/static/assets/img/contributors/coline.jpg deleted file mode 100644 index bbd9f063941bf74e35bd8ca6f708d407de160195..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3276 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 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 c78127d2a9ad5912786b6420c3d7c92721077383..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22545 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 AGynhq diff --git a/app/static/assets/img/contributors/william.jpg b/app/static/assets/img/contributors/william.jpg deleted file mode 100644 index 5d8e0ff37d3c7efb0209bef6c1b21c5e7c0edfe2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4750 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 F{{t8QP6_}3 diff --git a/app/static/assets/img/contributors/williamledoux.jpg b/app/static/assets/img/contributors/williamledoux.jpg deleted file mode 100644 index 7fd4a642b8bf1c899366a7da4f15f559c843801c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6190 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 diff --git a/app/styles/_components/Pages/home_page.sass b/app/styles/_components/Pages/home_page.sass index ff464ce20..44e4c05b9 100644 --- a/app/styles/_components/Pages/home_page.sass +++ b/app/styles/_components/Pages/home_page.sass @@ -1,81 +1,115 @@ .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 + box-shadow: -1px 2px 8px #457480 + transition: box-shadow 0.2s, transform 0.2s + transform: translateY(0) scale(1) + border-color: darken($white, 10) + &:hover + box-shadow: -1px 7px 14px #476f79 + transform: translateY(-0.15em) scale(1.025) + &: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 + + .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: 2em + + .partners + background: $white + padding: 0 + + .content + max-width: $maxHomeSectionWidth margin: 0 auto + padding: 4em 3em + .column + flex-basis: 125px + .image + @include animate(fadeIn, 1s) + margin-left: 0 + margin-right: 1.3em + .opencollective-contributors + .opencollective-svg + width: 10px + + .ambassadors + img + border-radius: 1em .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 background: $white @@ -125,6 +159,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/_global/global.sass b/app/styles/_global/global.sass index 8d5ff80e5..2f2bd6520 100644 --- a/app/styles/_global/global.sass +++ b/app/styles/_global/global.sass @@ -23,4 +23,24 @@ 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 + +.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" From 8e2c6c843770a070eb638987ef5023ff4777288c Mon Sep 17 00:00:00 2001 From: Benjamin Piouffle Date: Sat, 1 Dec 2018 12:59:46 +0100 Subject: [PATCH 2/4] Add social profiles icons with styled-components / styled-icons --- .babelrc | 10 +- README.md | 12 ++ app/components/Home/AllAmbassadors.jsx | 3 + app/components/Home/AllPartners.jsx | 3 + app/components/Home/CFSocialProfiles.jsx | 70 ++++++++ app/components/Home/Home.jsx | 5 +- .../Home/OpenCollectiveContributors.jsx | 3 + package-lock.json | 170 +++++++++++++++++- package.json | 5 + 9 files changed, 265 insertions(+), 16 deletions(-) create mode 100644 app/components/Home/CFSocialProfiles.jsx 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/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/components/Home/AllAmbassadors.jsx b/app/components/Home/AllAmbassadors.jsx index 07f6d1b8d..e458aa9cf 100644 --- a/app/components/Home/AllAmbassadors.jsx +++ b/app/components/Home/AllAmbassadors.jsx @@ -12,6 +12,9 @@ const AMBASSADORS = [ { name: 'Basile Asti', img: imgBasile } ] +/** + * Render all CaptainFact ambassadors + */ const AllAmbassadors = () => (
{AMBASSADORS.map(ambassador => ( diff --git a/app/components/Home/AllPartners.jsx b/app/components/Home/AllPartners.jsx index d3bbb581f..ad2ca3228 100644 --- a/app/components/Home/AllPartners.jsx +++ b/app/components/Home/AllPartners.jsx @@ -22,6 +22,9 @@ const PARTNERS = [ { name: 'YesWeHack', img: imgYesWeHack, url: 'https://yeswehack.com' }, ] +/** + * Render all CaptainFact partners + */ const AllPartners = () => (
{PARTNERS.map(partner => ( diff --git a/app/components/Home/CFSocialProfiles.jsx b/app/components/Home/CFSocialProfiles.jsx new file mode 100644 index 000000000..8352d3e9e --- /dev/null +++ b/app/components/Home/CFSocialProfiles.jsx @@ -0,0 +1,70 @@ +import React from 'react' +import PropTypes from 'prop-types' +import { Flex, Box } 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 bba8a6546..d0a8194fb 100644 --- a/app/components/Home/Home.jsx +++ b/app/components/Home/Home.jsx @@ -12,6 +12,7 @@ import AllPartners from './AllPartners' import OpenCollectiveContributors from './OpenCollectiveContributors' import AllAmbassadors from './AllAmbassadors' import ExternalLinkNewTab from '../Utils/ExternalLinkNewTab' +import CFSocialProfiles from './CFSocialProfiles' @connect(state => ({ authenticated: isAuthenticated(state) })) @withNamespaces('home') @@ -86,8 +87,8 @@ export default class Home extends React.PureComponent {
-
-

Add social networks here

+
+

Quelques vidéos au hasard

diff --git a/app/components/Home/OpenCollectiveContributors.jsx b/app/components/Home/OpenCollectiveContributors.jsx index 9c171ae78..e336561f1 100644 --- a/app/components/Home/OpenCollectiveContributors.jsx +++ b/app/components/Home/OpenCollectiveContributors.jsx @@ -2,6 +2,9 @@ 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, 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", From cd6da1da438a893cd84268081969acaa7dc7c82e Mon Sep 17 00:00:00 2001 From: Benjamin Piouffle Date: Sat, 1 Dec 2018 18:32:19 +0100 Subject: [PATCH 3/4] Add last videos and imprive existing styles --- app/API/graphql_queries.js | 23 ++++++++++ app/components/Home/AllAmbassadors.jsx | 31 ++++++++----- app/components/Home/AllPartners.jsx | 20 +++++---- app/components/Home/CFSocialProfiles.jsx | 2 +- app/components/Home/Home.jsx | 45 ++++++++++++++----- app/components/Home/LastVideos.jsx | 35 +++++++++++++++ .../Home/OpenCollectiveContributors.jsx | 6 +-- .../Videos/PaginatedVideosContainer.jsx | 39 +++++----------- app/constants.js | 4 +- app/i18n/en/home.js | 11 ++--- app/i18n/fr/home.js | 11 ++--- app/index.jsx | 6 ++- app/styles/_components/Pages/home_page.sass | 29 ++++++------ app/styles/_components/Videos/index.sass | 7 ++- app/styles/_global/buttons.sass | 7 +++ app/styles/_global/global.sass | 6 ++- app/styles/application.sass | 1 + app/styles/theme.js | 12 +++++ 18 files changed, 195 insertions(+), 100 deletions(-) create mode 100644 app/API/graphql_queries.js create mode 100644 app/components/Home/LastVideos.jsx create mode 100644 app/styles/_global/buttons.sass create mode 100644 app/styles/theme.js 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/components/Home/AllAmbassadors.jsx b/app/components/Home/AllAmbassadors.jsx index e458aa9cf..c181e3655 100644 --- a/app/components/Home/AllAmbassadors.jsx +++ b/app/components/Home/AllAmbassadors.jsx @@ -1,4 +1,7 @@ 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' @@ -6,25 +9,29 @@ import imgFrederic from '../../assets/ambassadors/frederic.jpg' import imgThimothee from '../../assets/ambassadors/timothee.jpg' const AMBASSADORS = [ - { name: 'Frédéric Bouffetier', img: imgFrederic }, - { name: 'Timothée Rolland', img: imgThimothee }, - { name: 'Dorian Cazottes', img: imgDorian }, - { name: 'Basile Asti', img: imgBasile } + { 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(ambassador => ( -
-
- {ambassador.name} -
-
+ + {AMBASSADORS.map(({ name, username, img }) => ( + + + ))} -
+ ) export default AllAmbassadors diff --git a/app/components/Home/AllPartners.jsx b/app/components/Home/AllPartners.jsx index ad2ca3228..923fee2fa 100644 --- a/app/components/Home/AllPartners.jsx +++ b/app/components/Home/AllPartners.jsx @@ -1,4 +1,6 @@ import React from 'react' +import { Flex, Box } from '@rebass/grid' + import ExternalLinkNewTab from '../Utils/ExternalLinkNewTab' import imgImago from '../../assets/partners/imago.jpg' @@ -26,15 +28,17 @@ const PARTNERS = [ * Render all CaptainFact partners */ const AllPartners = () => ( -
- {PARTNERS.map(partner => ( - -
- {partner.name} -
-
+ + {PARTNERS.map(({ name, url, img }) => ( + + +
+ {name} +
+
+
))} -
+ ) export default AllPartners diff --git a/app/components/Home/CFSocialProfiles.jsx b/app/components/Home/CFSocialProfiles.jsx index 8352d3e9e..e0a5aeabe 100644 --- a/app/components/Home/CFSocialProfiles.jsx +++ b/app/components/Home/CFSocialProfiles.jsx @@ -1,6 +1,6 @@ import React from 'react' import PropTypes from 'prop-types' -import { Flex, Box } from '@rebass/grid' +import { Flex } from '@rebass/grid' import styled from 'styled-components' import { Discord } from 'styled-icons/fa-brands/Discord' diff --git a/app/components/Home/Home.jsx b/app/components/Home/Home.jsx index d0a8194fb..af6648ddf 100644 --- a/app/components/Home/Home.jsx +++ b/app/components/Home/Home.jsx @@ -7,12 +7,13 @@ import { Icon } from '../Utils' import InvitationRequestForm from '../Users/InvitationRequestForm' import { isAuthenticated } from '../../state/users/current_user/selectors' import { INVITATION_SYSTEM } from '../../config' -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') @@ -31,13 +32,16 @@ export default class Home extends React.PureComponent { renderButtons() { return (
- - {this.props.t('seeVideos')} - - + {this.props.t('registerAndFactCheck')} - + {this.props.t('installExtension')}
@@ -77,10 +81,18 @@ export default class Home extends React.PureComponent {

{t('partners')}


-

{t('contributors')}

- +

{t('backers')}

+ +

{t('ambassadors')}

+ + 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 a travers des droits de véto et une + consultation obligatoire de l'équipe technique sur cetaines décisions.{' '} + En savoir plus. +

@@ -90,12 +102,23 @@ export default class Home extends React.PureComponent {
-
-

Quelques vidéos au hasard

+


+
+

Les dernières vidéos ajoutées

+ + {this.props.t('seeVideos')} + +

- +
+
+ +
{INVITATION_SYSTEM && (
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 index e336561f1..57ef1dd1f 100644 --- a/app/components/Home/OpenCollectiveContributors.jsx +++ b/app/components/Home/OpenCollectiveContributors.jsx @@ -8,12 +8,12 @@ import { optionsToQueryString } from '../../lib/url_utils' const OpenCollectiveContributors = ({ tier, avatarHeight = 72, - showBtn = true, + button = true, width = 325 }) => { const queryParams = optionsToQueryString({ avatarHeight, - showBtn, + button, width }) @@ -31,7 +31,7 @@ OpenCollectiveContributors.propTypes = { tier: PropTypes.oneOf(['soutien-régulier', 'donateur']).isRequired, avatarHeight: PropTypes.number, width: PropTypes.number, - showBtn: PropTypes.bool + 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', registerAndFactCheck: 'Signup and fact-check', installExtension: 'Install Extension', partners: 'Our partners', ambassadors: 'Ambassadors', - start: "Let's go!" + start: "Let's go!", + backers: 'Backers' } diff --git a/app/i18n/fr/home.js b/app/i18n/fr/home.js index ba0a796e8..bc49165e3 100644 --- a/app/i18n/fr/home.js +++ b/app/i18n/fr/home.js @@ -3,21 +3,16 @@ 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', registerAndFactCheck: "S'inscrire et vérifier", installExtension: "Installer l'extension", partners: 'Les partenaires', ambassadors: 'Ambassadeurs', - start: 'Commencer' + start: 'Commencer', + backers: 'Soutiens' } 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/styles/_components/Pages/home_page.sass b/app/styles/_components/Pages/home_page.sass index 44e4c05b9..a2ec65d79 100644 --- a/app/styles/_components/Pages/home_page.sass +++ b/app/styles/_components/Pages/home_page.sass @@ -27,13 +27,7 @@ flex-basis: 240px padding: 1.2em 1em font-size: 1.4em - box-shadow: -1px 2px 8px #457480 - transition: box-shadow 0.2s, transform 0.2s - transform: translateY(0) scale(1) - border-color: darken($white, 10) - &:hover - box-shadow: -1px 7px 14px #476f79 - transform: translateY(-0.15em) scale(1.025) + border: 1px solid darken($white, 10) &:last-of-type margin-bottom: 0.25em .button-label @@ -60,6 +54,10 @@ text-align: center margin-bottom: 3em + .last-videos-cards + margin: 0 auto + max-width: $maxHomeSectionWidth + .presentation font-size: $size-5 @@ -92,28 +90,27 @@ max-width: $maxHomeSectionWidth margin: 0 auto padding: 4em 3em - .column - flex-basis: 125px + +mobile + padding: 2em 1em .image @include animate(fadeIn, 1s) margin-left: 0 margin-right: 1.3em .opencollective-contributors - .opencollective-svg - width: 10px - - .ambassadors - img - border-radius: 1em + max-width: 100% + display: block + +mobile + margin: 0 auto .actions display: flex flex-wrap: wrap justify-content: center - .illustration + .last-videos background: $white min-height: 15vh + padding: 1em .community background: #5abda8 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 2f2bd6520..02cb37570 100644 --- a/app/styles/_global/global.sass +++ b/app/styles/_global/global.sass @@ -33,7 +33,11 @@ h1 .is-gradient-primary-light background: linear-gradient(15deg, lighten($primary, 5), darken($primary, 5) 70%) background-color: $primary - color: $white + 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%) 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 From 5f756d89c767d3471e4b46f9c770373c0acea607 Mon Sep 17 00:00:00 2001 From: Benjamin Piouffle Date: Sat, 1 Dec 2018 23:06:38 +0100 Subject: [PATCH 4/4] Add matomo events on homepage buttons and last-minute design improv. --- app/API/matomo.js | 41 +++++++++++++++++++++ app/components/Home/Home.jsx | 34 ++++++++++------- app/config.js | 4 ++ app/i18n/en/home.js | 5 ++- app/i18n/fr/home.js | 5 ++- app/styles/_components/Pages/home_page.sass | 2 +- 6 files changed, 75 insertions(+), 16 deletions(-) create mode 100644 app/API/matomo.js 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/components/Home/Home.jsx b/app/components/Home/Home.jsx index af6648ddf..09d2811eb 100644 --- a/app/components/Home/Home.jsx +++ b/app/components/Home/Home.jsx @@ -2,6 +2,8 @@ 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' @@ -33,12 +35,14 @@ export default class Home extends React.PureComponent { 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" > @@ -79,23 +83,26 @@ export default class Home extends React.PureComponent {

{t('partners')}

-
-

{t('backers')}

- - +
-

{t('ambassadors')}

- - 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 a travers des droits de véto et une - consultation obligatoire de l'équipe technique sur cetaines décisions.{' '} - En savoir plus. - -

+ + +

{t('backers')}

+ + +
+ +

{t('ambassadors')}

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

@@ -108,6 +115,7 @@ export default class Home extends React.PureComponent {

Les dernières vidéos ajoutées

Matomo.registerClick('Home', 'Button', 'SeeAllVideos')} className="button animated-hover is-medium is-gradient-primary-light" to="/videos" > diff --git a/app/config.js b/app/config.js index 608a6e893..0c2810088 100644 --- a/app/config.js +++ b/app/config.js @@ -10,6 +10,7 @@ function boolFromConfig(value) { return false } +// Raw env export export const JS_ENV = process.env.JS_ENV export const HTTP_API_URL = process.env.HTTP_API_URL export const WS_API_URL = process.env.WS_API_URL @@ -17,3 +18,6 @@ export const GRAPHQL_API_URL = process.env.GRAPHQL_API_URL export const FRONTEND_URL = process.env.FRONTEND_URL export const FB_APP_ID = process.env.FB_APP_ID export const INVITATION_SYSTEM = boolFromConfig(process.env.INVITATION_SYSTEM) + +// Some helpers based on env +export const IS_DEV = JS_ENV === 'dev' diff --git a/app/i18n/en/home.js b/app/i18n/en/home.js index c66e87d51..89bdc4eee 100644 --- a/app/i18n/en/home.js +++ b/app/i18n/en/home.js @@ -14,5 +14,8 @@ export default { partners: 'Our partners', ambassadors: 'Ambassadors', start: "Let's go!", - backers: 'Backers' + 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 bc49165e3..d58980fe3 100644 --- a/app/i18n/fr/home.js +++ b/app/i18n/fr/home.js @@ -14,5 +14,8 @@ export default { partners: 'Les partenaires', ambassadors: 'Ambassadeurs', start: 'Commencer', - backers: 'Soutiens' + 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/styles/_components/Pages/home_page.sass b/app/styles/_components/Pages/home_page.sass index a2ec65d79..be8bad798 100644 --- a/app/styles/_components/Pages/home_page.sass +++ b/app/styles/_components/Pages/home_page.sass @@ -80,7 +80,7 @@ color: $primary +mobile .title.is-3 - margin-bottom: 2em + margin-bottom: 1em .partners background: $white