Création d'une section /nouveautés
Cette nouvelle section s'accompagne d'un bandeau qui s'affiche quand une nouvelle version est publiée sur GitHub. Les données sont téléchargées depuis l'API GitHub en GraphQL au moment du build du site puis persistées dans un fichier Json statique.pull/842/head
parent
90e42a8b47
commit
54d45dbdb6
|
@ -1,5 +1,7 @@
|
|||
.tags*
|
||||
.tmp
|
||||
.env
|
||||
source/data
|
||||
node_modules/
|
||||
dist/
|
||||
.DS_Store
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
"dependencies": {
|
||||
"@babel/polyfill": "^7.4.0",
|
||||
"@babel/runtime": "^7.3.4",
|
||||
"@rehooks/local-storage": "^2.1.1",
|
||||
"classnames": "^2.2.5",
|
||||
"color-convert": "^1.9.2",
|
||||
"core-js": "^3.2.1",
|
||||
|
@ -59,6 +60,7 @@
|
|||
"regenerator-runtime": "^0.13.3",
|
||||
"reselect": "^4.0.0",
|
||||
"screenfull": "^3.3.2",
|
||||
"swr": "^0.1.16",
|
||||
"whatwg-fetch": "^3.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
|
@ -135,6 +137,7 @@
|
|||
"csv-loader": "^2.1.1",
|
||||
"daggy": "^1.3.0",
|
||||
"dedent-js": "^1.0.1",
|
||||
"dotenv": "=8.1.0",
|
||||
"enzyme": "^3.3.0",
|
||||
"enzyme-adapter-react-16": "^1.1.1",
|
||||
"eslint": "^6.5.1",
|
||||
|
@ -148,6 +151,7 @@
|
|||
"http-server": "^0.11.1",
|
||||
"intl": "^1.2.5",
|
||||
"intl-locales-supported": "^1.0.0",
|
||||
"isomorphic-fetch": "^2.2.1",
|
||||
"isomorphic-style-loader": "^5.1.0",
|
||||
"jest": "^24.9.0",
|
||||
"jest-transform-nearley": "^1.0.0",
|
||||
|
|
|
@ -12,3 +12,29 @@
|
|||
font-size: 1.4rem;
|
||||
margin-bottom: 0.6rem !important;
|
||||
}
|
||||
|
||||
.ui__.banner.news {
|
||||
justify-content: space-between;
|
||||
background: var(--lightestColor);
|
||||
font-size: 0.9em;
|
||||
width: auto;
|
||||
max-width: 450px;
|
||||
margin: auto;
|
||||
padding: 4px 15px 0px;
|
||||
border-radius: 15px;
|
||||
}
|
||||
|
||||
.ui__.banner.news img {
|
||||
vertical-align: middle !important;
|
||||
top: 4px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.ui__.close-button {
|
||||
cursor: pointer;
|
||||
font-size: 1.3em;
|
||||
}
|
||||
|
||||
.ui__.close-button:hover {
|
||||
color: black;
|
||||
}
|
||||
|
|
|
@ -107,6 +107,7 @@ a {
|
|||
font-size: inherit;
|
||||
padding: none;
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 4px;
|
||||
color: rgb(41, 117, 209);
|
||||
color: var(--color);
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ export const Markdown = ({
|
|||
<ReactMarkdown
|
||||
source={source}
|
||||
className={`markdown ${className}`}
|
||||
renderers={{ ...renderers, link: LinkRenderer, text: TextRenderer }}
|
||||
renderers={{ link: LinkRenderer, text: TextRenderer, ...renderers }}
|
||||
{...otherProps}
|
||||
/>
|
||||
)
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
// This script uses the GitHub API which requires an access token.
|
||||
// https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line
|
||||
// Once you have your access token you can put it in a `.env` file at the root
|
||||
// of the project to enable it during development. For instance:
|
||||
//
|
||||
// GITHUB_API_SECRET=f4336c82cb1e494752d06e610614eab12b65f1d1
|
||||
//
|
||||
require('dotenv').config()
|
||||
require('isomorphic-fetch')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
// We use the GitHub API V4 in GraphQL to download the releases. A GraphQL
|
||||
// explorer can be found here : https://developer.github.com/v4/explorer/
|
||||
const githubAuthToken = process.env.GITHUB_API_SECRET
|
||||
const cursorOfV1Release = 'Y3Vyc29yOnYyOpHOARHb8g=='
|
||||
const query = `query {
|
||||
repository(owner:"betagouv", name:"mon-entreprise") {
|
||||
releases(after:"${cursorOfV1Release}", last:100) {
|
||||
nodes {
|
||||
name
|
||||
description
|
||||
}
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
||||
// In case we cannot fetch the release (the API is down or the Authorization
|
||||
// token isn't valid) we fallback to some fake data -- it would be better to
|
||||
// have a static ressource accessible without authentification.
|
||||
const fakeData = [
|
||||
{
|
||||
name: 'Fake release',
|
||||
descriptionHTML: `You are seing this fake release because you
|
||||
didn't configure your GitHub access token and we weren't
|
||||
able to fetch the real releases from GitHub.<br /><br />
|
||||
See the script <pre>fetch-releases.js</pre> for more informations.`
|
||||
},
|
||||
{
|
||||
name: 'Release 2',
|
||||
descriptionHTML: 'blah blah blah'
|
||||
},
|
||||
{
|
||||
name: 'Release 3',
|
||||
descriptionHTML: 'blah blah blah'
|
||||
}
|
||||
]
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
const dataDir = path.resolve(__dirname, '../data/')
|
||||
|
||||
async function main() {
|
||||
createDataDir()
|
||||
writeReleasesInDataDir(await fetchReleases())
|
||||
}
|
||||
|
||||
function createDataDir() {
|
||||
if (!fs.existsSync(dataDir)) {
|
||||
fs.mkdirSync(dataDir)
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchReleases() {
|
||||
if (!githubAuthToken) {
|
||||
return fakeData
|
||||
}
|
||||
try {
|
||||
const response = await fetch('https://api.github.com/graphql', {
|
||||
method: 'post',
|
||||
headers: new Headers({ Authorization: `bearer ${githubAuthToken}` }),
|
||||
body: JSON.stringify({ query })
|
||||
})
|
||||
const {
|
||||
data: {
|
||||
repository: {
|
||||
releases: { nodes: releases }
|
||||
}
|
||||
}
|
||||
} = await response.json()
|
||||
return releases.filter(Boolean).reverse()
|
||||
} catch (e) {
|
||||
return fakeData
|
||||
}
|
||||
}
|
||||
|
||||
function writeReleasesInDataDir(releases) {
|
||||
// The last release name is fetched on all pages (to display the banner)
|
||||
// whereas the full release data is used only in the dedicated page, that why
|
||||
// we deduplicate the releases data in two separated files that can be
|
||||
// bundled/fetched separately.
|
||||
fs.writeFileSync(
|
||||
path.join(dataDir, 'releases.json'),
|
||||
JSON.stringify(releases)
|
||||
)
|
||||
fs.writeFileSync(
|
||||
path.join(dataDir, 'last-release.json'),
|
||||
JSON.stringify({ lastRelease: releases[0].name })
|
||||
)
|
||||
}
|
||||
|
||||
main()
|
|
@ -1 +1,2 @@
|
|||
require('./dottednames.js')
|
||||
require('./fetch-releases.js')
|
||||
|
|
|
@ -13,7 +13,6 @@ body,
|
|||
min-height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
@media (min-width: 500px) {
|
||||
|
@ -22,7 +21,6 @@ body,
|
|||
flex: 1;
|
||||
}
|
||||
.app-container {
|
||||
overflow: auto;
|
||||
min-height: 100vh;
|
||||
height: auto;
|
||||
}
|
||||
|
|
|
@ -1,37 +1,44 @@
|
|||
import Route404 from 'Components/Route404';
|
||||
import { SitePathsContext } from 'Components/utils/withSitePaths';
|
||||
import { rules as baseRulesEn, rulesFr as baseRulesFr } from 'Engine/rules';
|
||||
import 'iframe-resizer';
|
||||
import createRavenMiddleware from 'raven-for-redux';
|
||||
import Raven from 'raven-js';
|
||||
import React, { useContext, useEffect } from 'react';
|
||||
import { Helmet } from 'react-helmet';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Route, Switch } from 'react-router-dom';
|
||||
import 'Ui/index.css';
|
||||
import Provider from '../../Provider';
|
||||
import { persistEverything, retrievePersistedState } from '../../storage/persistEverything';
|
||||
import { persistSimulation, retrievePersistedSimulation } from '../../storage/persistSimulation';
|
||||
import Tracker, { devTracker } from '../../Tracker';
|
||||
import { getSessionStorage, inIframe } from '../../utils';
|
||||
import './App.css';
|
||||
import Footer from './layout/Footer/Footer';
|
||||
import Header from './layout/Header';
|
||||
import trackSimulatorActions from './middlewares/trackSimulatorActions';
|
||||
import Créer from './pages/Créer';
|
||||
import Couleur from './pages/Dev/Couleur';
|
||||
import IntegrationTest from './pages/Dev/IntegrationTest';
|
||||
import Personas from './pages/Dev/Personas';
|
||||
import Sitemap from './pages/Dev/Sitemap';
|
||||
import Documentation from './pages/Documentation';
|
||||
import Gérer from './pages/Gérer';
|
||||
import Iframes from './pages/Iframes';
|
||||
import Integration from './pages/integration/index';
|
||||
import Landing from './pages/Landing/Landing';
|
||||
import Simulateurs from './pages/Simulateurs';
|
||||
import ÉconomieCollaborative from './pages/ÉconomieCollaborative';
|
||||
import redirects from './redirects';
|
||||
import { constructLocalizedSitePath } from './sitePaths';
|
||||
import Route404 from 'Components/Route404'
|
||||
import { SitePathsContext } from 'Components/utils/withSitePaths'
|
||||
import { rules as baseRulesEn, rulesFr as baseRulesFr } from 'Engine/rules'
|
||||
import 'iframe-resizer'
|
||||
import createRavenMiddleware from 'raven-for-redux'
|
||||
import Raven from 'raven-js'
|
||||
import React, { useContext, useEffect } from 'react'
|
||||
import { Helmet } from 'react-helmet'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Route, Switch } from 'react-router-dom'
|
||||
import 'Ui/index.css'
|
||||
import Provider from '../../Provider'
|
||||
import {
|
||||
persistEverything,
|
||||
retrievePersistedState
|
||||
} from '../../storage/persistEverything'
|
||||
import {
|
||||
persistSimulation,
|
||||
retrievePersistedSimulation
|
||||
} from '../../storage/persistSimulation'
|
||||
import Tracker, { devTracker } from '../../Tracker'
|
||||
import { getSessionStorage, inIframe } from '../../utils'
|
||||
import './App.css'
|
||||
import Footer from './layout/Footer/Footer'
|
||||
import Header from './layout/Header'
|
||||
import trackSimulatorActions from './middlewares/trackSimulatorActions'
|
||||
import Créer from './pages/Créer'
|
||||
import Couleur from './pages/Dev/Couleur'
|
||||
import IntegrationTest from './pages/Dev/IntegrationTest'
|
||||
import Personas from './pages/Dev/Personas'
|
||||
import Sitemap from './pages/Dev/Sitemap'
|
||||
import Documentation from './pages/Documentation'
|
||||
import Gérer from './pages/Gérer'
|
||||
import Iframes from './pages/Iframes'
|
||||
import Integration from './pages/integration/index'
|
||||
import Landing from './pages/Landing/Landing'
|
||||
import Nouveautés from './pages/Nouveautés/Nouveautés'
|
||||
import Simulateurs from './pages/Simulateurs'
|
||||
import ÉconomieCollaborative from './pages/ÉconomieCollaborative'
|
||||
import redirects from './redirects'
|
||||
import { constructLocalizedSitePath } from './sitePaths'
|
||||
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
Raven.config(
|
||||
|
@ -70,7 +77,8 @@ function InFranceRoute({ basename, language }) {
|
|||
...retrievePersistedState(),
|
||||
previousSimulation: retrievePersistedSimulation(),
|
||||
rules
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
<RouterSwitch />
|
||||
</Provider>
|
||||
)
|
||||
|
@ -113,6 +121,7 @@ const App = () => {
|
|||
component={Documentation}
|
||||
/>
|
||||
<Route path={sitePaths.integration.index} component={Integration} />
|
||||
<Route path={sitePaths.nouveautés} component={Nouveautés} />
|
||||
<Route exact path="/dev/sitemap" component={Sitemap} />
|
||||
<Route
|
||||
exact
|
||||
|
|
|
@ -84,13 +84,15 @@ const Footer = () => {
|
|||
<LegalNotice />
|
||||
{' • '}
|
||||
<Privacy />
|
||||
{' • '}
|
||||
<a href="https://github.com/betagouv/mon-entreprise/releases">
|
||||
Nouveautés
|
||||
</a>
|
||||
{i18n.language === 'fr' && (
|
||||
<>
|
||||
{' • '}
|
||||
<Link to={sitePaths.nouveautés}>Nouveautés</Link>
|
||||
</>
|
||||
)}
|
||||
{' • '}
|
||||
<a href="https://mon-entreprise.fr/stats">Stats</a>
|
||||
{' • '}{' '}
|
||||
{' • '}
|
||||
<Link to={sitePaths.integration.index}>
|
||||
Intégrer nos simulateurs
|
||||
</Link>
|
||||
|
|
|
@ -6,47 +6,58 @@ import urssafSvg from 'Images/urssaf.svg'
|
|||
import React, { useContext } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Link } from 'react-router-dom'
|
||||
import NewsBanner from './NewsBanner'
|
||||
|
||||
export default function Header() {
|
||||
const sitePaths = useContext(SitePathsContext)
|
||||
const { language } = useTranslation().i18n
|
||||
return (
|
||||
<div
|
||||
className="ui__ container"
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center'
|
||||
}}>
|
||||
<Link style={{ height: '4rem' }} to={sitePaths.index}>
|
||||
<img
|
||||
alt="logo mon-entreprise.fr"
|
||||
style={{
|
||||
padding: '0.5rem 0',
|
||||
height: '100%'
|
||||
}}
|
||||
src={language === 'fr' ? logoSvg : logoEnSvg}
|
||||
/>
|
||||
</Link>
|
||||
<div style={{ flex: 1 }} />
|
||||
<a
|
||||
href="https://beta.gouv.fr"
|
||||
target="_blank"
|
||||
<>
|
||||
<div
|
||||
className="ui__ container"
|
||||
style={{
|
||||
height: '4rem',
|
||||
padding: '1rem'
|
||||
}}>
|
||||
<img alt="logo marianne" style={{ height: '100%' }} src={marianneSvg} />
|
||||
</a>
|
||||
<a
|
||||
href="https://www.urssaf.fr"
|
||||
target="_blank"
|
||||
style={{
|
||||
height: '4rem',
|
||||
padding: '1rem'
|
||||
display: 'flex',
|
||||
alignItems: 'center'
|
||||
}}
|
||||
className="landing-header__institutional-logo">
|
||||
<img alt="logo urssaf" style={{ height: '100%' }} src={urssafSvg} />
|
||||
</a>
|
||||
</div>
|
||||
>
|
||||
<Link style={{ height: '4rem' }} to={sitePaths.index}>
|
||||
<img
|
||||
alt="logo mon-entreprise.fr"
|
||||
style={{
|
||||
padding: '0.5rem 0',
|
||||
height: '100%'
|
||||
}}
|
||||
src={language === 'fr' ? logoSvg : logoEnSvg}
|
||||
/>
|
||||
</Link>
|
||||
<div style={{ flex: 1 }} />
|
||||
<a
|
||||
href="https://beta.gouv.fr"
|
||||
target="_blank"
|
||||
style={{
|
||||
height: '4rem',
|
||||
padding: '1rem'
|
||||
}}
|
||||
>
|
||||
<img
|
||||
alt="logo marianne"
|
||||
style={{ height: '100%' }}
|
||||
src={marianneSvg}
|
||||
/>
|
||||
</a>
|
||||
<a
|
||||
href="https://www.urssaf.fr"
|
||||
target="_blank"
|
||||
style={{
|
||||
height: '4rem',
|
||||
padding: '1rem'
|
||||
}}
|
||||
className="landing-header__institutional-logo"
|
||||
>
|
||||
<img alt="logo urssaf" style={{ height: '100%' }} src={urssafSvg} />
|
||||
</a>
|
||||
</div>
|
||||
<NewsBanner />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
import { useLocalStorage, writeStorage } from '@rehooks/local-storage'
|
||||
import { SitePathsContext } from 'Components/utils/withSitePaths'
|
||||
import React, { useContext } from 'react'
|
||||
import emoji from 'react-easy-emoji'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { lastRelease } from '../../../data/last-release.json'
|
||||
import { inIframe } from '../../../utils'
|
||||
|
||||
const localStorageKey = 'last-viewed-release'
|
||||
|
||||
export const hideNewsBanner = () => writeStorage(localStorageKey, lastRelease)
|
||||
|
||||
export default function NewsBanner() {
|
||||
const [lastViewedRelease] = useLocalStorage(localStorageKey)
|
||||
const sitePaths = useContext(SitePathsContext)
|
||||
const { i18n } = useTranslation()
|
||||
|
||||
const showBanner =
|
||||
lastViewedRelease !== lastRelease && i18n.language === 'fr' && !inIframe()
|
||||
|
||||
// We only want to show the banner to returning visitors, so we initiate the
|
||||
// local storage value with the last release.
|
||||
if (showBanner && lastViewedRelease === undefined) {
|
||||
hideNewsBanner()
|
||||
}
|
||||
|
||||
return showBanner ? (
|
||||
<div className="ui__ banner news">
|
||||
<span>
|
||||
{emoji('✨')} Découvrez les nouveautés de{' '}
|
||||
<Link to={sitePaths.nouveautés}>{lastRelease}</Link>
|
||||
</span>
|
||||
<span onClick={hideNewsBanner} className="ui__ close-button">
|
||||
×
|
||||
</span>
|
||||
</div>
|
||||
) : null
|
||||
}
|
|
@ -0,0 +1,186 @@
|
|||
import { Markdown } from 'Components/utils/markdown'
|
||||
import { SitePathsContext } from 'Components/utils/withSitePaths'
|
||||
import React, { useContext, useEffect } from 'react'
|
||||
import emoji from 'react-easy-emoji'
|
||||
import { Redirect, useHistory, useRouteMatch } from 'react-router'
|
||||
import { Link, NavLink } from 'react-router-dom'
|
||||
import styled from 'styled-components'
|
||||
import useSWR from 'swr'
|
||||
import { hideNewsBanner } from '../../layout/NewsBanner'
|
||||
|
||||
const fetcher = (url: RequestInfo) => fetch(url).then(r => r.json())
|
||||
const slugify = (name: string) => name.toLowerCase().replace(' ', '-')
|
||||
|
||||
export default function Nouveautés() {
|
||||
// The release.json file may be big, we don't want to include it in the main
|
||||
// bundle, that's why we only fetch it on this page. Alternatively we could
|
||||
// use import("data/release.json") and configure code splitting with Webpack.
|
||||
const { data } = useSWR('/data/releases.json', fetcher)
|
||||
const history = useHistory()
|
||||
const sitePaths = useContext(SitePathsContext)
|
||||
const slug = useRouteMatch<{ slug: string }>(`${sitePaths.nouveautés}/:slug`)
|
||||
?.params?.slug
|
||||
const selectedRelease = data?.findIndex(({ name }) => slugify(name) === slug)
|
||||
|
||||
useEffect(hideNewsBanner, [])
|
||||
useEffect(() => {
|
||||
window.scrollTo({ top: 0 })
|
||||
}, [selectedRelease])
|
||||
|
||||
const getPath = (index: number) =>
|
||||
`${sitePaths.nouveautés}/${slugify(data[index].name)}`
|
||||
|
||||
if (!data) {
|
||||
return null
|
||||
} else if (!slug || selectedRelease === -1) {
|
||||
return <Redirect to={getPath(0)} />
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<h1>Les nouveautés {emoji('✨')}</h1>
|
||||
<p>
|
||||
Nous améliorons le site en continu à partir de vos retours. Découvrez
|
||||
les{' '}
|
||||
{selectedRelease === 0
|
||||
? 'dernières nouveautés'
|
||||
: `nouveautés de ${data[selectedRelease].name.toLowerCase()}`}{' '}
|
||||
:
|
||||
</p>
|
||||
<SmallScreenSelect
|
||||
onChange={evt => {
|
||||
history.push(getPath(Number(evt.target.value)))
|
||||
}}
|
||||
>
|
||||
{data.map(({ name }, index) => (
|
||||
<option
|
||||
key={index}
|
||||
value={index}
|
||||
selected={index === selectedRelease}
|
||||
>
|
||||
{name}
|
||||
</option>
|
||||
))}
|
||||
</SmallScreenSelect>
|
||||
<NewsSection>
|
||||
<Sidebar>
|
||||
{data.map(({ name }, index) => (
|
||||
<li key={name}>
|
||||
<NavLink activeClassName="active" to={getPath(index)}>
|
||||
{name}
|
||||
</NavLink>
|
||||
</li>
|
||||
))}
|
||||
</Sidebar>
|
||||
<MainBlock>
|
||||
<Markdown
|
||||
source={data[selectedRelease].description}
|
||||
escapeHtml={false}
|
||||
renderers={{ text: TextRenderer }}
|
||||
/>
|
||||
<NavigationButtons>
|
||||
{selectedRelease + 1 < data.length ? (
|
||||
<Link to={getPath(selectedRelease + 1)}>
|
||||
← {data[selectedRelease + 1].name}
|
||||
</Link>
|
||||
) : (
|
||||
<span /> // For spacing
|
||||
)}
|
||||
{selectedRelease > 0 && (
|
||||
<Link to={getPath(selectedRelease - 1)}>
|
||||
{data[selectedRelease - 1].name} →
|
||||
</Link>
|
||||
)}
|
||||
</NavigationButtons>
|
||||
</MainBlock>
|
||||
</NewsSection>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const removeGithubIssuesReferences = (text: string) =>
|
||||
text.replace(/#[0-9]{1,5}/g, '')
|
||||
|
||||
const TextRenderer = ({ children }) => (
|
||||
<>{emoji(removeGithubIssuesReferences(children))}</>
|
||||
)
|
||||
|
||||
const NewsSection = styled.section`
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
|
||||
@media (min-width: 1250px) {
|
||||
margin-left: -175px;
|
||||
}
|
||||
`
|
||||
|
||||
const Sidebar = styled.ul`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: sticky;
|
||||
top: 20px;
|
||||
margin-right: 25px;
|
||||
padding-left: 0;
|
||||
font-size: 0.9em;
|
||||
border-right: 1px solid var(--lighterColor);
|
||||
|
||||
@media (max-width: 700px) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
li {
|
||||
list-style-type: none;
|
||||
list-style-position: inside;
|
||||
width: 150px;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
|
||||
a {
|
||||
display: block;
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
padding: 4px 10px;
|
||||
margin: 0;
|
||||
|
||||
&:hover,
|
||||
&.active {
|
||||
background: var(--lightestColor);
|
||||
}
|
||||
|
||||
&.active {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const SmallScreenSelect = styled.select`
|
||||
display: none;
|
||||
|
||||
@media (max-width: 700px) {
|
||||
display: initial;
|
||||
}
|
||||
`
|
||||
|
||||
const MainBlock = styled.div`
|
||||
flex: 1;
|
||||
|
||||
> h1:first-child,
|
||||
h2:first-child,
|
||||
h3:first-child {
|
||||
margin-top: 0px;
|
||||
}
|
||||
`
|
||||
|
||||
const NavigationButtons = styled.div`
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-top: 40px;
|
||||
|
||||
a {
|
||||
cursor: pointer;
|
||||
background: var(--lightestColor);
|
||||
padding: 20px 30px;
|
||||
}
|
||||
`
|
|
@ -111,6 +111,7 @@ export const constructLocalizedSitePath = (language: string) => {
|
|||
'/votre-situation'
|
||||
)
|
||||
},
|
||||
nouveautés: t('path.nouveautés', '/nouveautés'),
|
||||
documentation: {
|
||||
exemples: t('path.documentation.exemples', '/exemples'),
|
||||
index: t('path.documentation.index', '/documentation')
|
||||
|
|
|
@ -4,5 +4,6 @@ declare module NodeJS {
|
|||
FR_SITE: string
|
||||
NODE_ENV: 'development' | 'production'
|
||||
MASTER: boolean
|
||||
GITHUB_API_SECRET: string
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,6 +55,10 @@ module.exports.default = {
|
|||
from: './source/images',
|
||||
to: 'images'
|
||||
},
|
||||
{
|
||||
from: './source/data',
|
||||
to: 'data'
|
||||
},
|
||||
{
|
||||
from: './source/sites/mon-entreprise.fr/favicon',
|
||||
to: 'favicon'
|
||||
|
|
48
yarn.lock
48
yarn.lock
|
@ -1056,6 +1056,11 @@
|
|||
promise-limit "^2.5.0"
|
||||
puppeteer "^1.7.0"
|
||||
|
||||
"@rehooks/local-storage@^2.1.1":
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@rehooks/local-storage/-/local-storage-2.1.1.tgz#e9d9a36a17308667f2aee9b01cbec9a29d53d341"
|
||||
integrity sha512-w+7kwnFn3tdRreDG+Pi610eqozTyuJnmYIqwa0GojNpoLMjnYDSCF02eyWQOkVPUj1UHf+Zeqnjg+jzqg3OcuQ==
|
||||
|
||||
"@sinonjs/commons@^1", "@sinonjs/commons@^1.3.0", "@sinonjs/commons@^1.7.0":
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.7.0.tgz#f90ffc52a2e519f018b13b6c4da03cbff36ebed6"
|
||||
|
@ -3757,6 +3762,11 @@ domutils@^2.0.0:
|
|||
domelementtype "^2.0.1"
|
||||
domhandler "^3.0.0"
|
||||
|
||||
dotenv@=8.1.0:
|
||||
version "8.1.0"
|
||||
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.1.0.tgz#d811e178652bfb8a1e593c6dd704ec7e90d85ea2"
|
||||
integrity sha512-GUE3gqcDCaMltj2++g6bRQ5rBJWtkWTmqmD0fo1RnnMuUqHNCt2oTPeDnS9n6fKYvlhn7AeBkb38lymBtWBQdA==
|
||||
|
||||
duplexify@^3.4.2, duplexify@^3.6.0:
|
||||
version "3.7.1"
|
||||
resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309"
|
||||
|
@ -3841,6 +3851,13 @@ encodeurl@~1.0.2:
|
|||
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
|
||||
integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=
|
||||
|
||||
encoding@^0.1.11:
|
||||
version "0.1.12"
|
||||
resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb"
|
||||
integrity sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=
|
||||
dependencies:
|
||||
iconv-lite "~0.4.13"
|
||||
|
||||
end-of-stream@^1.0.0, end-of-stream@^1.1.0:
|
||||
version "1.4.4"
|
||||
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
|
||||
|
@ -4401,7 +4418,7 @@ extsprintf@^1.2.0:
|
|||
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
|
||||
integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=
|
||||
|
||||
fast-deep-equal@^2.0.1:
|
||||
fast-deep-equal@2.0.1, fast-deep-equal@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49"
|
||||
integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=
|
||||
|
@ -5294,7 +5311,7 @@ i18next@^18.0.1:
|
|||
dependencies:
|
||||
"@babel/runtime" "^7.3.1"
|
||||
|
||||
iconv-lite@0.4.24, iconv-lite@^0.4.24:
|
||||
iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@~0.4.13:
|
||||
version "0.4.24"
|
||||
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
|
||||
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
|
||||
|
@ -5728,7 +5745,7 @@ is-regexp@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069"
|
||||
integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk=
|
||||
|
||||
is-stream@^1.1.0:
|
||||
is-stream@^1.0.1, is-stream@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
|
||||
integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
|
||||
|
@ -5821,6 +5838,14 @@ isobject@^3.0.0, isobject@^3.0.1:
|
|||
resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
|
||||
integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8=
|
||||
|
||||
isomorphic-fetch@^2.2.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9"
|
||||
integrity sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=
|
||||
dependencies:
|
||||
node-fetch "^1.0.1"
|
||||
whatwg-fetch ">=0.10.0"
|
||||
|
||||
isomorphic-style-loader@^5.1.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/isomorphic-style-loader/-/isomorphic-style-loader-5.1.0.tgz#4845f90bb9828f3dfecc82d0574c9ed01bbaba2d"
|
||||
|
@ -7257,6 +7282,14 @@ no-case@^2.2.0:
|
|||
dependencies:
|
||||
lower-case "^1.1.1"
|
||||
|
||||
node-fetch@^1.0.1:
|
||||
version "1.7.3"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef"
|
||||
integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==
|
||||
dependencies:
|
||||
encoding "^0.1.11"
|
||||
is-stream "^1.0.1"
|
||||
|
||||
node-int64@^0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"
|
||||
|
@ -10077,6 +10110,13 @@ svgo@^0.7.0:
|
|||
sax "~1.2.1"
|
||||
whet.extend "~0.9.9"
|
||||
|
||||
swr@^0.1.16:
|
||||
version "0.1.16"
|
||||
resolved "https://registry.yarnpkg.com/swr/-/swr-0.1.16.tgz#e1667f2260ac091fb4c2cc6255ca1b8ff83b0acd"
|
||||
integrity sha512-E+i0pJOCCPRxnwQMFKf3RYr4os+B4swNuwnHo+pBCNxwfuJiN0ZalwP9u4OqjoeMl9eZFgcQYUPHD8KVyTqM1g==
|
||||
dependencies:
|
||||
fast-deep-equal "2.0.1"
|
||||
|
||||
symbol-observable@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.1.tgz#8340fc4702c3122df5d22288f88283f513d3fdd4"
|
||||
|
@ -10853,7 +10893,7 @@ whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3, whatwg-encoding@^1.0.5:
|
|||
dependencies:
|
||||
iconv-lite "0.4.24"
|
||||
|
||||
whatwg-fetch@^3.0.0:
|
||||
whatwg-fetch@>=0.10.0, whatwg-fetch@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#fc804e458cc460009b1a2b966bc8817d2578aefb"
|
||||
integrity sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==
|
||||
|
|
Loading…
Reference in New Issue