diff --git a/.gitignore b/.gitignore
index e6db162e5..cc191ab98 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,7 @@
.tags*
.tmp
+.env
+source/data
node_modules/
dist/
.DS_Store
diff --git a/package.json b/package.json
index 64c77128c..3f86a3b28 100644
--- a/package.json
+++ b/package.json
@@ -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",
diff --git a/source/components/Banner.css b/source/components/Banner.css
index acff8a89b..b536caca8 100644
--- a/source/components/Banner.css
+++ b/source/components/Banner.css
@@ -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;
+}
diff --git a/source/components/ui/Typography.css b/source/components/ui/Typography.css
index e66956de9..c00392b7d 100644
--- a/source/components/ui/Typography.css
+++ b/source/components/ui/Typography.css
@@ -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);
}
diff --git a/source/components/utils/markdown.tsx b/source/components/utils/markdown.tsx
index 92a4ef118..e073d8328 100644
--- a/source/components/utils/markdown.tsx
+++ b/source/components/utils/markdown.tsx
@@ -30,7 +30,7 @@ export const Markdown = ({
)
diff --git a/source/scripts/fetch-releases.js b/source/scripts/fetch-releases.js
new file mode 100644
index 000000000..2df5781a5
--- /dev/null
+++ b/source/scripts/fetch-releases.js
@@ -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.
+ See the script
fetch-releases.js 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()
diff --git a/source/scripts/postinstall.js b/source/scripts/postinstall.js
index fff6d1566..09e33f836 100644
--- a/source/scripts/postinstall.js
+++ b/source/scripts/postinstall.js
@@ -1 +1,2 @@
require('./dottednames.js')
+require('./fetch-releases.js')
diff --git a/source/sites/mon-entreprise.fr/App.css b/source/sites/mon-entreprise.fr/App.css
index 7b5b75b2f..e973c688d 100644
--- a/source/sites/mon-entreprise.fr/App.css
+++ b/source/sites/mon-entreprise.fr/App.css
@@ -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;
}
diff --git a/source/sites/mon-entreprise.fr/App.tsx b/source/sites/mon-entreprise.fr/App.tsx
index 9d5fa7d64..b87f73082 100644
--- a/source/sites/mon-entreprise.fr/App.tsx
+++ b/source/sites/mon-entreprise.fr/App.tsx
@@ -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
- }}>
+ }}
+ >
)
@@ -113,6 +121,7 @@ const App = () => {
component={Documentation}
/>
+
{
{' • '}
- {' • '}
-
- Nouveautés
-
+ {i18n.language === 'fr' && (
+ <>
+ {' • '}
+ Nouveautés
+ >
+ )}
{' • '}
Stats
- {' • '}{' '}
+ {' • '}
Intégrer nos simulateurs
diff --git a/source/sites/mon-entreprise.fr/layout/Header.tsx b/source/sites/mon-entreprise.fr/layout/Header.tsx
index fa0c2eb4f..fac62a808 100644
--- a/source/sites/mon-entreprise.fr/layout/Header.tsx
+++ b/source/sites/mon-entreprise.fr/layout/Header.tsx
@@ -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 (
-
+
+ >
)
}
diff --git a/source/sites/mon-entreprise.fr/layout/NewsBanner.tsx b/source/sites/mon-entreprise.fr/layout/NewsBanner.tsx
new file mode 100644
index 000000000..2c60012dd
--- /dev/null
+++ b/source/sites/mon-entreprise.fr/layout/NewsBanner.tsx
@@ -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 ? (
+
+
+ {emoji('✨')} Découvrez les nouveautés de{' '}
+ {lastRelease}
+
+
+ ×
+
+
+ ) : null
+}
diff --git a/source/sites/mon-entreprise.fr/pages/Nouveautés/Nouveautés.tsx b/source/sites/mon-entreprise.fr/pages/Nouveautés/Nouveautés.tsx
new file mode 100644
index 000000000..4f286930c
--- /dev/null
+++ b/source/sites/mon-entreprise.fr/pages/Nouveautés/Nouveautés.tsx
@@ -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
+ }
+
+ return (
+ <>
+ Les nouveautés {emoji('✨')}
+
+ 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()}`}{' '}
+ :
+
+ {
+ history.push(getPath(Number(evt.target.value)))
+ }}
+ >
+ {data.map(({ name }, index) => (
+
+ {name}
+
+ ))}
+
+
+
+ {data.map(({ name }, index) => (
+
+
+ {name}
+
+
+ ))}
+
+
+
+
+ {selectedRelease + 1 < data.length ? (
+
+ ← {data[selectedRelease + 1].name}
+
+ ) : (
+ // For spacing
+ )}
+ {selectedRelease > 0 && (
+
+ {data[selectedRelease - 1].name} →
+
+ )}
+
+
+
+ >
+ )
+}
+
+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;
+ }
+`
diff --git a/source/sites/mon-entreprise.fr/sitePaths.ts b/source/sites/mon-entreprise.fr/sitePaths.ts
index 559f341d0..e7920b1d5 100644
--- a/source/sites/mon-entreprise.fr/sitePaths.ts
+++ b/source/sites/mon-entreprise.fr/sitePaths.ts
@@ -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')
diff --git a/source/types/app-env.d.ts b/source/types/app-env.d.ts
index 9208b9579..b3ec2e780 100644
--- a/source/types/app-env.d.ts
+++ b/source/types/app-env.d.ts
@@ -4,5 +4,6 @@ declare module NodeJS {
FR_SITE: string
NODE_ENV: 'development' | 'production'
MASTER: boolean
+ GITHUB_API_SECRET: string
}
}
diff --git a/source/webpack.common.js b/source/webpack.common.js
index f410cdeda..5ec4c75da 100644
--- a/source/webpack.common.js
+++ b/source/webpack.common.js
@@ -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'
diff --git a/yarn.lock b/yarn.lock
index f2500b205..36ea8fc9e 100644
--- a/yarn.lock
+++ b/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==