Affiche une bannière dans la section dev lors d'un recrutement
parent
bec524a411
commit
fd02b0095f
|
@ -12,7 +12,10 @@
|
|||
"engines": {
|
||||
"node": ">=12.16.1"
|
||||
},
|
||||
"browserslist": ["> 1% in FR", "not ie < 11"],
|
||||
"browserslist": [
|
||||
"> 1% in FR",
|
||||
"not ie < 11"
|
||||
],
|
||||
"scripts": {
|
||||
"prepare": "node scripts/prepare.js",
|
||||
"build": "yarn run build:prod && yarn run build:legacy",
|
||||
|
@ -40,6 +43,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.3.4",
|
||||
"@icons/material": "^0.4.1",
|
||||
"@internationalized/number": "^3.0.3",
|
||||
"@mui/material": "^5.0.4",
|
||||
"@mui/styled-engine": "npm:@mui/styled-engine-sc@latest",
|
||||
|
@ -188,6 +192,7 @@
|
|||
"webpack-hot-middleware": "^2.24.2",
|
||||
"workbox-webpack-plugin": "^6.0.2",
|
||||
"worker-loader": "^2.0.0",
|
||||
"xml2js": "^0.4.23",
|
||||
"yaml-loader": "^0.5.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
// We publish our job offers on https://beta.gouv.fr/recrutement/. To augment
|
||||
// their reach, we also publish a banner on our website automatically by using
|
||||
// the beta.gouv.fr API.
|
||||
|
||||
require('isomorphic-fetch')
|
||||
const xml2js = require('xml2js')
|
||||
const util = require('util')
|
||||
const { createDataDir, writeInDataDir } = require('./utils.js')
|
||||
|
||||
const parseXML = util.promisify(xml2js.parseString)
|
||||
|
||||
main()
|
||||
|
||||
async function main() {
|
||||
createDataDir()
|
||||
const jobOffers = await fetchJobOffers()
|
||||
writeInDataDir('job-offers.json', jobOffers)
|
||||
}
|
||||
|
||||
async function fetchJobOffers() {
|
||||
const response = await fetch('https://beta.gouv.fr/jobs.xml')
|
||||
const content = await response.text()
|
||||
// The XML API isn't the most ergonomic, we ought to have a JSON API.
|
||||
// cf. https://github.com/betagouv/beta.gouv.fr/issues/6343
|
||||
const jobOffers = (await parseXML(content)).feed.entry
|
||||
.map((entry) => ({
|
||||
title: entry.title[0]['_'].trim(),
|
||||
link: entry.link[0].$.href,
|
||||
content: entry.content[0]['_'].trim(),
|
||||
}))
|
||||
.filter(({ title }) => title.includes('Offre de Mon-entreprise'))
|
||||
.map(({ title, ...rest }) => ({
|
||||
...rest,
|
||||
title: title.replace(' - Offre de Mon-entreprise', ''),
|
||||
}))
|
||||
|
||||
return jobOffers
|
||||
}
|
|
@ -1,2 +1,3 @@
|
|||
require('./fetch-releases.js')
|
||||
require('./fetch-stats.js')
|
||||
require('./fetch-job-offers.js')
|
||||
|
|
|
@ -2,12 +2,11 @@ import { useLocalStorage, writeStorage } from '@rehooks/local-storage'
|
|||
import { Appear } from 'Components/ui/animate'
|
||||
import Emoji from 'Components/utils/Emoji'
|
||||
import { SitePathsContext } from 'Components/utils/SitePathsContext'
|
||||
import { Button } from 'DesignSystem/buttons'
|
||||
import { GenericButtonOrLinkProps, Link } from 'DesignSystem/typography/link'
|
||||
import lastRelease from 'Data/last-release.json'
|
||||
import { Banner, HideButton, InnerBanner } from 'DesignSystem/banner'
|
||||
import { Link } from 'DesignSystem/typography/link'
|
||||
import { useContext, useEffect } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
import lastRelease from '../../data/last-release.json'
|
||||
|
||||
const localStorageKey = 'last-viewed-release'
|
||||
|
||||
|
@ -17,44 +16,6 @@ export const hideNewsBanner = () => {
|
|||
export const determinant = (word: string) =>
|
||||
/^[aeiouy]/i.exec(word) ? 'd’' : 'de '
|
||||
|
||||
const Container = styled.div`
|
||||
display: flex;
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-family: ${({ theme }) => theme.fonts.main};
|
||||
`
|
||||
|
||||
const InnerContainer = styled.div`
|
||||
display: flex;
|
||||
margin: auto;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0.5rem 1rem;
|
||||
background-color: ${({ theme }) => theme.colors.bases.primary[100]};
|
||||
border: 2px solid;
|
||||
border-color: ${({ theme }) => theme.colors.bases.primary[500]};
|
||||
border-radius: 0.375rem;
|
||||
`
|
||||
|
||||
const HideButton = styled(Button)<GenericButtonOrLinkProps>`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 1.5rem;
|
||||
width: 1.5rem;
|
||||
padding: 0;
|
||||
background: ${({ theme }) => theme.colors.extended.grey[100]};
|
||||
color: ${({ theme }) => theme.colors.bases.primary[600]};
|
||||
font-weight: bold;
|
||||
margin-left: 1rem;
|
||||
|
||||
&:hover {
|
||||
background: ${({ theme }) => theme.colors.bases.primary[300]};
|
||||
}
|
||||
`
|
||||
|
||||
export default function NewsBanner() {
|
||||
const [lastViewedRelease] = useLocalStorage(localStorageKey)
|
||||
const sitePaths = useContext(SitePathsContext)
|
||||
|
@ -77,8 +38,8 @@ export default function NewsBanner() {
|
|||
}
|
||||
return (
|
||||
<Appear>
|
||||
<Container className="print-hidden">
|
||||
<InnerContainer>
|
||||
<Banner className="print-hidden">
|
||||
<InnerBanner>
|
||||
<span>
|
||||
<Emoji emoji="✨" /> Découvrez les nouveautés{' '}
|
||||
{determinant(lastRelease.name)}
|
||||
|
@ -89,8 +50,8 @@ export default function NewsBanner() {
|
|||
<HideButton onPress={hideNewsBanner} aria-label={t('Fermer')}>
|
||||
×
|
||||
</HideButton>
|
||||
</InnerContainer>
|
||||
</Container>
|
||||
</InnerBanner>
|
||||
</Banner>
|
||||
</Appear>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
import { Button } from 'DesignSystem/buttons'
|
||||
import { GenericButtonOrLinkProps } from 'DesignSystem/typography/link'
|
||||
import styled from 'styled-components'
|
||||
|
||||
export const Banner = styled.div`
|
||||
display: flex;
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-family: ${({ theme }) => theme.fonts.main};
|
||||
`
|
||||
|
||||
export const InnerBanner = styled.div`
|
||||
display: flex;
|
||||
margin: auto;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0.5rem 1rem;
|
||||
background-color: ${({ theme }) => theme.colors.bases.primary[100]};
|
||||
border: 2px solid;
|
||||
border-color: ${({ theme }) => theme.colors.bases.primary[500]};
|
||||
border-radius: 0.375rem;
|
||||
`
|
||||
|
||||
export const HideButton = styled(Button)<GenericButtonOrLinkProps>`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 1.5rem;
|
||||
width: 1.5rem;
|
||||
padding: 0;
|
||||
background: ${({ theme }) => theme.colors.extended.grey[100]};
|
||||
color: ${({ theme }) => theme.colors.bases.primary[600]};
|
||||
font-weight: bold;
|
||||
margin-left: 1rem;
|
||||
|
||||
&:hover {
|
||||
background: ${({ theme }) => theme.colors.bases.primary[300]};
|
||||
}
|
||||
`
|
|
@ -4,7 +4,7 @@ import { Li, Ul } from 'DesignSystem/typography/list'
|
|||
import { Body } from 'DesignSystem/typography/paragraphs'
|
||||
import { useState } from 'react'
|
||||
import styled from 'styled-components'
|
||||
import stats from '../../data/stats.json'
|
||||
import stats from 'Data/stats.json'
|
||||
|
||||
export default function DemandeUtilisateurs() {
|
||||
return (
|
||||
|
|
|
@ -13,7 +13,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react'
|
|||
import { Trans } from 'react-i18next'
|
||||
import { useHistory, useLocation } from 'react-router-dom'
|
||||
import { toAtString } from '../../ATInternetTracking'
|
||||
import statsJson from '../../data/stats.json'
|
||||
import statsJson from 'Data/stats.json'
|
||||
import { debounce } from '../../utils'
|
||||
import { SimulateurCard } from '../Simulateurs/Home'
|
||||
import useSimulatorsData, { SimulatorData } from '../Simulateurs/metadata'
|
||||
|
|
|
@ -9,10 +9,19 @@ import { TrackChapter } from '../../ATInternetTracking'
|
|||
import Iframe from './Iframe'
|
||||
import Library from './Library'
|
||||
import Options from './Options'
|
||||
import jobOffers from 'Data/job-offers.json'
|
||||
import { Banner, InnerBanner } from 'DesignSystem/banner'
|
||||
|
||||
type JobOffer = {
|
||||
title: string
|
||||
link: string
|
||||
content: string
|
||||
}
|
||||
|
||||
export default function Integration() {
|
||||
const sitePaths = useContext(SitePathsContext)
|
||||
const { pathname } = useLocation()
|
||||
const openJobOffer = (jobOffers as Array<JobOffer>)[0]
|
||||
return (
|
||||
<>
|
||||
<TrackChapter chapter1="integration" />
|
||||
|
@ -26,27 +35,19 @@ export default function Integration() {
|
|||
← <Trans>Outils pour les développeurs</Trans> <Emoji emoji="👨💻" />
|
||||
</Link>
|
||||
)}
|
||||
{/* TODO: Nous pourrions automatiser la publication de cette bannière
|
||||
de recrutement lorsqu'une annonce est postée sur beta.gouv.fr
|
||||
https://github.com/betagouv/beta.gouv.fr/issues/6343 */}
|
||||
{/* <div
|
||||
className="ui__ card plain"
|
||||
css={`
|
||||
margin: 1rem 0;
|
||||
transform: translateY(1rem);
|
||||
|
||||
text-align: center;
|
||||
padding: 0.4rem;
|
||||
`}
|
||||
>
|
||||
📯{' '}
|
||||
<strong>
|
||||
<a href="https://beta.gouv.fr/recrutement/2021/05/25/mon-entreprise-fr.recrute.js.html">
|
||||
Mon-entreprise recrute !
|
||||
</a>
|
||||
</strong>{' '}
|
||||
<small>Freelance Typescript / React pour 6 mois minimum</small>
|
||||
</div> */}
|
||||
{openJobOffer && (
|
||||
<Banner>
|
||||
<InnerBanner>
|
||||
<span>
|
||||
<Emoji emoji="📯" />{' '}
|
||||
<strong>
|
||||
<a href={openJobOffer.link}>Mon-entreprise recrute !</a>
|
||||
</strong>{' '}
|
||||
<small>{openJobOffer.title}</small>
|
||||
</span>
|
||||
</InnerBanner>
|
||||
</Banner>
|
||||
)}
|
||||
<Switch>
|
||||
<Route exact path={sitePaths.integration.index} component={Options} />
|
||||
<Route path={sitePaths.integration.iframe} component={Iframe} />
|
||||
|
|
|
@ -18,7 +18,8 @@
|
|||
"Reducers/*": ["reducers/*"],
|
||||
"Selectors/*": ["selectors/*"],
|
||||
"Types/*": ["types/*"],
|
||||
"DesignSystem/*": ["design-system/*"]
|
||||
"DesignSystem/*": ["design-system/*"],
|
||||
"Data/*": ["data/*"]
|
||||
},
|
||||
"typeRoots": ["./types/", "./node_modules/@types"],
|
||||
"noEmit": true,
|
||||
|
|
|
@ -113,6 +113,7 @@ module.exports.default = {
|
|||
Types: path.resolve('source/types/'),
|
||||
Images: path.resolve('source/static/images/'),
|
||||
DesignSystem: path.resolve('source/design-system'),
|
||||
Data: path.resolve('source/data'),
|
||||
},
|
||||
extensions: ['.js', '.ts', '.tsx'],
|
||||
},
|
||||
|
|
20
yarn.lock
20
yarn.lock
|
@ -1243,6 +1243,11 @@
|
|||
resolved "https://registry.npmjs.org/@icons/material/-/material-0.2.4.tgz"
|
||||
integrity sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw==
|
||||
|
||||
"@icons/material@^0.4.1":
|
||||
version "0.4.1"
|
||||
resolved "https://registry.yarnpkg.com/@icons/material/-/material-0.4.1.tgz#20ba0dff8d59a2b8749c7ad765faad52ae45b868"
|
||||
integrity sha512-r4CuKUZv9GeAYvWc6WEVF0Xiw/IS4S50zna/M0/ISJOKe3RbpbHN3yBjX7ZnaPGqH/rm5SnDBv8FNOHLpM7OpQ==
|
||||
|
||||
"@internationalized/date@3.0.0-alpha.1":
|
||||
version "3.0.0-alpha.1"
|
||||
resolved "https://registry.npmjs.org/@internationalized/date/-/date-3.0.0-alpha.1.tgz"
|
||||
|
@ -12557,7 +12562,7 @@ safe-regex@^1.1.0:
|
|||
resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz"
|
||||
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
|
||||
|
||||
sax@~1.2.1:
|
||||
sax@>=0.6.0, sax@~1.2.1:
|
||||
version "1.2.4"
|
||||
resolved "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz"
|
||||
integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
|
||||
|
@ -14909,6 +14914,19 @@ xml-name-validator@^3.0.0:
|
|||
resolved "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz"
|
||||
integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==
|
||||
|
||||
xml2js@^0.4.23:
|
||||
version "0.4.23"
|
||||
resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.23.tgz#a0c69516752421eb2ac758ee4d4ccf58843eac66"
|
||||
integrity sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==
|
||||
dependencies:
|
||||
sax ">=0.6.0"
|
||||
xmlbuilder "~11.0.0"
|
||||
|
||||
xmlbuilder@~11.0.0:
|
||||
version "11.0.1"
|
||||
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3"
|
||||
integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==
|
||||
|
||||
xmlchars@^2.1.1, xmlchars@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz"
|
||||
|
|
Loading…
Reference in New Issue