Release
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"presets": [
|
||||
"@babel/preset-env"
|
||||
],
|
||||
"plugins": [
|
||||
["@babel/plugin-transform-runtime", {
|
||||
"regenerator": true
|
||||
}]
|
||||
]
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = false
|
||||
insert_final_newline = true
|
||||
|
||||
[*.html]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[*.{js,json,yml}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
|
@ -0,0 +1,32 @@
|
|||
module.exports = {
|
||||
root: true,
|
||||
env: {
|
||||
node: true,
|
||||
browser: true,
|
||||
},
|
||||
extends: ["standard"],
|
||||
rules: {
|
||||
"no-console": process.env.NODE_ENV === "production" ? "error" : "off",
|
||||
"no-debugger": process.env.NODE_ENV === "production" ? "error" : "off",
|
||||
"comma-dangle": [2, "always-multiline"],
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ["**/__tests__/*.js", "**/tests/unit/**/*.spec.js"],
|
||||
env: {
|
||||
jest: true
|
||||
}
|
||||
}
|
||||
],
|
||||
parserOptions: {
|
||||
parser: "babel-eslint"
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ["**/__tests__/*.js", "**/tests/unit/**/*.spec.js"],
|
||||
env: {
|
||||
jest: true
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
|
@ -0,0 +1,187 @@
|
|||
|
||||
# Created by https://www.gitignore.io/api/node,code,linux,macos,windows
|
||||
# Edit at https://www.gitignore.io/?templates=node,code,linux,macos,windows
|
||||
|
||||
### Code ###
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
|
||||
### Linux ###
|
||||
*~
|
||||
|
||||
# temporary files which can be created if a process still has a handle open of a deleted file
|
||||
.fuse_hidden*
|
||||
|
||||
# KDE directory preferences
|
||||
.directory
|
||||
|
||||
# Linux trash folder which might appear on any partition or disk
|
||||
.Trash-*
|
||||
|
||||
# .nfs files are created when an open file is removed but is still being accessed
|
||||
.nfs*
|
||||
|
||||
### macOS ###
|
||||
# General
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Icon must end with two \r
|
||||
Icon
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
.com.apple.timemachine.donotpresent
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
|
||||
### Node ###
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# TypeScript v1 declaration files
|
||||
typings/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
.env.test
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
|
||||
# next.js build output
|
||||
.next
|
||||
|
||||
# nuxt.js build output
|
||||
.nuxt
|
||||
|
||||
# rollup.js default build output
|
||||
dist/
|
||||
|
||||
# Uncomment the public line if your project uses Gatsby
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# https://create-react-app.dev/docs/using-the-public-folder/#docsNav
|
||||
# public
|
||||
|
||||
# Storybook build outputs
|
||||
.out
|
||||
.storybook-out
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# Temporary folders
|
||||
tmp/
|
||||
temp/
|
||||
|
||||
### Windows ###
|
||||
# Windows thumbnail cache files
|
||||
Thumbs.db
|
||||
Thumbs.db:encryptable
|
||||
ehthumbs.db
|
||||
ehthumbs_vista.db
|
||||
|
||||
# Dump file
|
||||
*.stackdump
|
||||
|
||||
# Folder config file
|
||||
[Dd]esktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Windows Installer files
|
||||
*.cab
|
||||
*.msi
|
||||
*.msix
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
|
||||
# End of https://www.gitignore.io/api/node,code,linux,macos,windows
|
|
@ -0,0 +1,19 @@
|
|||
Copyright (c) Ministère de l'intérieur
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
After Width: | Height: | Size: 16 KiB |
|
@ -0,0 +1,31 @@
|
|||
# Générateur de certificat de déplacement
|
||||
|
||||
## Développer
|
||||
|
||||
### Installer le projet
|
||||
|
||||
```console
|
||||
$ git clone https://github.com/lab-mi/deplacement-codiv-19.git
|
||||
$ cd deplacement-codiv-19
|
||||
$ npm i
|
||||
$ npm start
|
||||
```
|
||||
|
||||
### Générer le code de production
|
||||
|
||||
```console
|
||||
$ npm run build
|
||||
```
|
||||
|
||||
Le code à déployer sera dans le dossier `dist`
|
||||
|
||||
## Crédits
|
||||
|
||||
Ce projet a été réalisé à partir d'un fork du dépôt [covid-19-certificate](https://github.com/nesk/covid-19-certificate) de [Johann Pardanaud](https://github.com/nesk).
|
||||
|
||||
Les projets open source suivants ont été utilisés pour le développement de ce service :
|
||||
|
||||
- [PDF-LIB](https://pdf-lib.js.org/)
|
||||
- [qrcode](https://github.com/soldair/node-qrcode)
|
||||
- [Bootstrap](https://getbootstrap.com/)
|
||||
- [Font Awesome](https://fontawesome.com/license)
|
|
@ -0,0 +1,257 @@
|
|||
import 'bootstrap/dist/css/bootstrap.min.css'
|
||||
|
||||
import { PDFDocument, StandardFonts } from 'pdf-lib'
|
||||
import QRCode from 'qrcode'
|
||||
|
||||
import pdfBase from './certificate.pdf'
|
||||
import './main.css'
|
||||
|
||||
const $ = (...args) => document.querySelector(...args)
|
||||
const $$ = (...args) => [...document.querySelectorAll(...args)]
|
||||
var year, month, day
|
||||
|
||||
const generateQR = async text => {
|
||||
try {
|
||||
var opts = {
|
||||
errorCorrectionLevel: 'M',
|
||||
type: 'image/png',
|
||||
quality: 0.92,
|
||||
margin: 1,
|
||||
}
|
||||
return await QRCode.toDataURL(text, opts)
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
}
|
||||
}
|
||||
|
||||
function pad (str) {
|
||||
return String(str).padStart(2, '0')
|
||||
}
|
||||
|
||||
function setDateNow (date) {
|
||||
year = date.getFullYear()
|
||||
month = pad(date.getMonth() + 1) // Les mois commencent à 0
|
||||
day = pad(date.getDate())
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', setReleaseDateTime)
|
||||
|
||||
function setReleaseDateTime () {
|
||||
const loadedDate = new Date()
|
||||
setDateNow(loadedDate)
|
||||
const releaseDateInput = document.querySelector('#field-datesortie')
|
||||
releaseDateInput.value = `${year}-${month}-${day}`
|
||||
|
||||
const hour = pad(loadedDate.getHours())
|
||||
const minute = pad(loadedDate.getMinutes())
|
||||
|
||||
const releaseTimeInput = document.querySelector('#field-heuresortie')
|
||||
releaseTimeInput.value = `${hour}:${minute}`
|
||||
}
|
||||
|
||||
function saveProfile () {
|
||||
for (const field of $$('#form-profile input')) {
|
||||
if (field.id === 'field-datesortie') {
|
||||
var dateSortie = field.value.split('-')
|
||||
localStorage.setItem(field.id.substring('field-'.length), `${dateSortie[2]}/${dateSortie[1]}/${dateSortie[0]}`)
|
||||
} else {
|
||||
localStorage.setItem(field.id.substring('field-'.length), field.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getProfile () {
|
||||
const fields = {}
|
||||
for (let i = 0; i < localStorage.length; i++) {
|
||||
const name = localStorage.key(i)
|
||||
fields[name] = localStorage.getItem(name)
|
||||
}
|
||||
return fields
|
||||
}
|
||||
|
||||
function idealFontSize (font, text, maxWidth, minSize, defaultSize) {
|
||||
let currentSize = defaultSize
|
||||
let textWidth = font.widthOfTextAtSize(text, defaultSize)
|
||||
|
||||
while (textWidth > maxWidth && currentSize > minSize) {
|
||||
textWidth = font.widthOfTextAtSize(text, --currentSize)
|
||||
}
|
||||
|
||||
return (textWidth > maxWidth) ? null : currentSize
|
||||
}
|
||||
|
||||
async function generatePdf (profile, reasons) {
|
||||
const generatedDate = new Date()
|
||||
setDateNow(generatedDate)
|
||||
const creationDate = `${day}/${month}/${year}`
|
||||
|
||||
const hour = pad(generatedDate.getHours())
|
||||
const minute = pad(generatedDate.getMinutes())
|
||||
const creationHour = `${hour}h${minute}`
|
||||
|
||||
const { lastname, firstname, birthday, lieunaissance, address, zipcode, town, datesortie, heuresortie } = profile
|
||||
const releaseHours = String(heuresortie).substring(0, 2)
|
||||
const releaseMinutes = String(heuresortie).substring(3, 5)
|
||||
|
||||
const data = [
|
||||
`Cree le: ${creationDate} a ${creationHour}`,
|
||||
`Nom: ${lastname}`,
|
||||
`Prenom: ${firstname}`,
|
||||
`Naissance: ${birthday} a ${lieunaissance}`,
|
||||
`Adresse: ${address} ${zipcode} ${town}`,
|
||||
`Sortie: ${datesortie} a ${releaseHours}h${releaseMinutes}`,
|
||||
`Motifs: ${reasons}`,
|
||||
].join('; ')
|
||||
|
||||
const existingPdfBytes = await fetch(pdfBase).then(res => res.arrayBuffer())
|
||||
|
||||
const pdfDoc = await PDFDocument.load(existingPdfBytes)
|
||||
const page1 = pdfDoc.getPages()[0]
|
||||
|
||||
const font = await pdfDoc.embedFont(StandardFonts.Helvetica)
|
||||
const drawText = (text, x, y, size = 11) => {
|
||||
page1.drawText(text, { x, y, size, font })
|
||||
}
|
||||
|
||||
drawText(`${firstname} ${lastname}`, 123, 686)
|
||||
drawText(birthday, 123, 661)
|
||||
drawText(lieunaissance, 92, 638)
|
||||
drawText(`${address} ${zipcode} ${town}`, 134, 613)
|
||||
|
||||
if (reasons.includes('travail')) {
|
||||
drawText('x', 76, 527, 19)
|
||||
}
|
||||
if (reasons.includes('courses')) {
|
||||
drawText('x', 76, 478, 19)
|
||||
}
|
||||
if (reasons.includes('sante')) {
|
||||
drawText('x', 76, 436, 19)
|
||||
}
|
||||
if (reasons.includes('famille')) {
|
||||
drawText('x', 76, 400, 19)
|
||||
}
|
||||
if (reasons.includes('sport')) {
|
||||
drawText('x', 76, 345, 19)
|
||||
}
|
||||
if (reasons.includes('judiciaire')) {
|
||||
drawText('x', 76, 298, 19)
|
||||
}
|
||||
if (reasons.includes('missions')) {
|
||||
drawText('x', 76, 260, 19)
|
||||
}
|
||||
let locationSize = idealFontSize(font, profile.town, 83, 7, 11)
|
||||
|
||||
if (!locationSize) {
|
||||
alert('Le nom de la ville risque de ne pas être affiché correctement en raison de sa longueur. ' +
|
||||
'Essayez d\'utiliser des abréviations ("Saint" en "St." par exemple) quand cela est possible.')
|
||||
locationSize = 7
|
||||
}
|
||||
|
||||
drawText(profile.town, 111, 226, locationSize)
|
||||
|
||||
if (reasons !== '') {
|
||||
// Date sortie
|
||||
drawText(`${profile.datesortie}`, 92, 200)
|
||||
drawText(releaseHours, 200, 201)
|
||||
drawText(releaseMinutes, 220, 201)
|
||||
}
|
||||
|
||||
// Date création
|
||||
drawText('Date de création:', 464, 150, 7)
|
||||
drawText(`${creationDate} à ${creationHour}`, 455, 144, 7)
|
||||
|
||||
const generatedQR = await generateQR(data)
|
||||
|
||||
const qrImage = await pdfDoc.embedPng(generatedQR)
|
||||
|
||||
page1.drawImage(qrImage, {
|
||||
x: page1.getWidth() - 170,
|
||||
y: 155,
|
||||
width: 100,
|
||||
height: 100,
|
||||
})
|
||||
|
||||
pdfDoc.addPage()
|
||||
const page2 = pdfDoc.getPages()[1]
|
||||
page2.drawImage(qrImage, {
|
||||
x: 50,
|
||||
y: page2.getHeight() - 350,
|
||||
width: 300,
|
||||
height: 300,
|
||||
})
|
||||
|
||||
const pdfBytes = await pdfDoc.save()
|
||||
|
||||
return new Blob([pdfBytes], { type: 'application/pdf' })
|
||||
}
|
||||
|
||||
function downloadBlob (blob, fileName) {
|
||||
const link = document.createElement('a')
|
||||
var url = URL.createObjectURL(blob)
|
||||
link.href = url
|
||||
link.download = fileName
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
}
|
||||
|
||||
function getAndSaveReasons () {
|
||||
const values = $$('input[name="field-reason"]:checked')
|
||||
.map(x => x.value)
|
||||
.join('-')
|
||||
localStorage.setItem('reasons', values)
|
||||
return values
|
||||
}
|
||||
|
||||
// see: https://stackoverflow.com/a/32348687/1513045
|
||||
function isFacebookBrowser () {
|
||||
const ua = navigator.userAgent || navigator.vendor || window.opera
|
||||
return ua.includes('FBAN') || ua.includes('FBAV')
|
||||
}
|
||||
|
||||
if (isFacebookBrowser()) {
|
||||
$('#alert-facebook').classList.remove('d-none')
|
||||
}
|
||||
|
||||
function addSlash () {
|
||||
this.value = this.value.replace(/^(\d{2})$/g, '$1/')
|
||||
this.value = this.value.replace(/^(\d{2})\/(\d{2})$/g, '$1/$2/')
|
||||
}
|
||||
|
||||
$('#field-birthday').addEventListener('keyup', addSlash)
|
||||
|
||||
const snackbar = $('#snackbar')
|
||||
|
||||
$('#form-profile').addEventListener('submit', async event => {
|
||||
event.preventDefault()
|
||||
|
||||
saveProfile()
|
||||
const reasons = getAndSaveReasons()
|
||||
const pdfBlob = await generatePdf(getProfile(), reasons)
|
||||
downloadBlob(pdfBlob, 'attestation.pdf')
|
||||
|
||||
snackbar.classList.remove('d-none')
|
||||
setTimeout(() => snackbar.classList.add('show'), 100)
|
||||
|
||||
setTimeout(function () {
|
||||
snackbar.classList.remove('show')
|
||||
setTimeout(() => snackbar.classList.add('d-none'), 500)
|
||||
}, 6000)
|
||||
})
|
||||
|
||||
$$('input').forEach(input => {
|
||||
const exempleElt = input.parentNode.parentNode.querySelector('.exemple')
|
||||
if (input.placeholder && exempleElt) {
|
||||
input.addEventListener('input', (event) => {
|
||||
if (input.value) {
|
||||
exempleElt.innerHTML = 'ex. : ' + input.placeholder
|
||||
} else {
|
||||
exempleElt.innerHTML = ''
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
function addVersion () {
|
||||
document.getElementById('version').innerHTML = `${new Date().getFullYear()} - ${process.env.VERSION}`
|
||||
}
|
||||
addVersion()
|
|
@ -0,0 +1,188 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
|
||||
<meta name="msapplication-TileColor" content="#603cba" />
|
||||
<meta name="msapplication-config" content="./favicons/browserconfig.xml" />
|
||||
<meta name="theme-color" content="#ffffff" />
|
||||
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="./favicons/apple-touch-icon.png" />
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="./favicons/favicon-32x32.png" />
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="./favicons/favicon-16x16.png" />
|
||||
<link rel="manifest" href="./favicons/site.webmanifest" />
|
||||
<link rel="mask-icon" href="./favicons/safari-pinned-tab.svg" color="#21bf73" />
|
||||
|
||||
<title>COVID-19 – Générateur d'attestation de déplacement</title>
|
||||
</head>
|
||||
|
||||
<body class="confidentialite">
|
||||
<div class="container">
|
||||
<header class="wrapper">
|
||||
<img class="logo" src="/MIN_Interieur_RVB.svg" alt="logo_ministère_interieur" />
|
||||
<div class="header-content">
|
||||
<h1 class="flex flex-wrap">
|
||||
<div class="covid-title">
|
||||
COVID-19
|
||||
</div>
|
||||
<div class="covid-subtitle">
|
||||
Générateur d'attestation de déplacement
|
||||
</div>
|
||||
</h1>
|
||||
</div>
|
||||
</header>
|
||||
<div class="wrapper">
|
||||
<h2 class="titre-2">Politique de confidentialité</h2>
|
||||
<h3 class="titre-3">Collecte des données personnelles</h3>
|
||||
<p>
|
||||
Les informations saisies dans ce générateur d’attestation de
|
||||
déplacement ne font l’objet d’aucune collecte par le ministère
|
||||
de l’Intérieur. Ces données personnelles<sup>1</sup> sont
|
||||
exclusivement stockées dans le terminal (ordinateur, tablette,
|
||||
smartphone) utilisé pour générer l’attestation.
|
||||
</p>
|
||||
<em>1 - Prénom, Nom, Date de naissance, Lieu de naissance, Adresse,
|
||||
Code postal, Ville.</em>
|
||||
<h3 class="titre-3">Traceurs et cookies</h3>
|
||||
<p>
|
||||
Lors de la consultation du générateur, des cookies sont déposés
|
||||
sur le terminal utilisé. Ces cookies sont utilisés pour
|
||||
sécuriser le service proposé.
|
||||
</p>
|
||||
|
||||
<h4 class="titre-4">Définition d’un cookie</h4>
|
||||
<p>
|
||||
Un "cookie" est une suite d'informations, généralement de petite
|
||||
taille et identifié par un nom, qui peut être transmis à votre
|
||||
navigateur par un site web sur lequel vous vous connectez. Votre
|
||||
navigateur web le conserve pendant une certaine durée, et le
|
||||
renvoie au serveur web chaque fois que vous vous y
|
||||
re-connecterez. Les cookies ont de multiples usages : ils
|
||||
peuvent servir à mémoriser votre identifiant client auprès d'un
|
||||
site marchand, le contenu courant de votre panier d'achat, un
|
||||
identifiant permettant de tracer votre navigation pour des
|
||||
finalités statistiques ou publicitaires, etc.
|
||||
</p>
|
||||
<h4 class="titre-4">Cookies utilisés</h4>
|
||||
<p>
|
||||
Différents cookies techniques sont utilisés sur ce générateur
|
||||
d’attestation de déplacement :
|
||||
</p>
|
||||
<table class="cookies">
|
||||
<thead>
|
||||
<tr class="header-row">
|
||||
<th>Nom du Cookie</th>
|
||||
<th>Finalité</th>
|
||||
<th>Durée de conservation</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td data-label="Nom du Cookie" class="name-col">incap_ses_*</td>
|
||||
<td data-label="Finalité" >
|
||||
Protection DDoS Incapsula et Pare-feu pour application
|
||||
web : cookie servant à relier les requêtes HTTP à une
|
||||
session. La réouverture du navigateur et l’accès au même
|
||||
site sont considérés comme des visites différentes. Pour
|
||||
maintenir les sessions existantes (cookie de session).
|
||||
</td>
|
||||
<td data-label="Durée de conservation" >Supprimé après la fermeture du navigateur.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td data-label="Nom du Cookie" class="name-col">nlbi_*</td>
|
||||
<td data-label="Finalité" >
|
||||
Protection DDoS Incapsula et Pare-feu pour application
|
||||
web : cookie équilibreur de charge qui garantit que les
|
||||
requêtes d’un client sont envoyées au même serveur
|
||||
d’origine.
|
||||
</td>
|
||||
<td data-label="Durée de conservation" >Supprimé après la fermeture du navigateur.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td data-label="Nom du Cookie" class="name-col">visid_incap_*</td>
|
||||
<td data-label="Finalité" >
|
||||
Protection DDoS Incapsula et Pare-feu pour application
|
||||
web : cookie servant à relier certaines sessions à un
|
||||
visiteur spécifique (visiteur représentant un ordinateur
|
||||
spécifique). Afin d’identifier les clients ayant déjà
|
||||
consulté Incapsula. Le seul cookie qui perdure pour une
|
||||
durée de 12 mois.
|
||||
</td>
|
||||
<td data-label="Durée de conservation" >12 mois.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td data-label="Nom du Cookie" class="name-col">__utm*</td>
|
||||
<td data-label="Finalité" >
|
||||
Cookie de classification Incapsula : pour voir comment
|
||||
le client réagit à et gère un cookie mal formé afin
|
||||
d’identifier la nature de ce client.
|
||||
</td>
|
||||
<td data-label="Durée de conservation" >900 secondes maximum.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<p>
|
||||
Vous pouvez refuser ces cookies en configurant les paramètres de
|
||||
votre navigateur.
|
||||
</p>
|
||||
<h4 class="titre-4">
|
||||
Moyens d'opposition au dépôt des cookies via votre navigateur
|
||||
</h4>
|
||||
<p>
|
||||
<strong>Si vous utilisez Firefox : </strong>Cliquez sur le
|
||||
bouton de menu et sélectionnez « Options ». Ensuite,
|
||||
sélectionnez le panneau « Vie privée et sécurité ». Rendez-vous
|
||||
à la section « Protection renforcée contre le pistage ».
|
||||
Choisissez la protection personnalisé [bouton radio
|
||||
« Personnalisé »]. Décochez la case « cookies ». Cliquez sur le
|
||||
bouton « Actualisez tous les onglets » si vous souhaitez
|
||||
appliquer ces changements à la navigation en cours au sein de
|
||||
votre navigateur.
|
||||
</p>
|
||||
<p>
|
||||
<strong>Si vous utilisez Chrome : </strong>En haut à droite,
|
||||
cliquez sur « Plus > Paramètres ». En bas, cliquez sur «
|
||||
Paramètres avancés ». Dans la section "Confidentialité et
|
||||
sécurité", cliquez sur « Paramètres des sites». Cliquez sur «
|
||||
Cookies et données des sites». Désactivez l’option « Autoriser
|
||||
les sites à enregistrer/lire les données des cookies ».
|
||||
</p>
|
||||
<p>
|
||||
<strong>Si vous utilisez Internet Explorer : </strong>Sélectionnez le bouton « Outils », puis « Options
|
||||
Internet ».
|
||||
Sélectionnez l’onglet « Confidentialité » puis sous « Paramètres
|
||||
», sélectionnez « Avancé ». Cochez la case "Ignorer la gestion
|
||||
automatique des cookies", puis sélectionner "Refuser" dans la
|
||||
colonne "Cookies tierces parties".
|
||||
</p>
|
||||
<p>
|
||||
Pour plus d’informations sur le sujet, n’hésitez pas à visiter
|
||||
le
|
||||
<a href="https://www.cnil.fr/fr/cookies-et-autres-traceurs">site de la CNIL</a>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="btn-wrapper">
|
||||
<a href="./index.html" class="btn-generateur">
|
||||
Retour au générateur
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<footer class="main-footer">
|
||||
<div class="footer-links">
|
||||
<a class="footer-link">Confidentialité</a>
|
||||
<a href="https://www.interieur.gouv.fr/Infos-du-site/Mentions-legales" target="_blank" title="Mentions légales - nouvelle page"
|
||||
class="footer-link">Mentions légales</a>
|
||||
<a href="https://www.gouvernement.fr/info-coronavirus" target="_blank" title="Information du gouvernement sur le Covid-19 - nouvelle page" class="footer-link">Informations du
|
||||
gouvernement sur le Covid-19</a>
|
||||
<p class="footer-link">
|
||||
Plus d’infos au<a class="num-08" href="tel:0800130000">
|
||||
0 800 130 000</a>
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
<script src="./confidentialite.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,2 @@
|
|||
import 'bootstrap/dist/css/bootstrap.min.css'
|
||||
import './main.css'
|
After Width: | Height: | Size: 9.7 KiB |
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 10 KiB |
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<browserconfig>
|
||||
<msapplication>
|
||||
<tile>
|
||||
<square150x150logo src="mstile-150x150.png"/>
|
||||
<TileColor>#603cba</TileColor>
|
||||
</tile>
|
||||
</msapplication>
|
||||
</browserconfig>
|
After Width: | Height: | Size: 613 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 2.8 KiB |
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||
width="1024.000000pt" height="1024.000000pt" viewBox="0 0 1024.000000 1024.000000"
|
||||
preserveAspectRatio="xMidYMid meet">
|
||||
<metadata>
|
||||
Created by potrace 1.11, written by Peter Selinger 2001-2013
|
||||
</metadata>
|
||||
<g transform="translate(0.000000,1024.000000) scale(0.100000,-0.100000)"
|
||||
fill="#000000" stroke="none">
|
||||
<path d="M4858 10236 c-1 -2 -50 -6 -108 -10 -58 -3 -116 -8 -130 -11 -14 -2
|
||||
-52 -7 -85 -10 -105 -9 -381 -52 -395 -60 -3 -2 -26 -6 -50 -10 -25 -4 -126
|
||||
-27 -225 -52 -661 -165 -1268 -457 -1830 -879 -82 -62 -161 -123 -175 -136
|
||||
-14 -13 -55 -48 -90 -78 -243 -205 -529 -511 -739 -790 -39 -52 -75 -100 -80
|
||||
-106 -22 -27 -153 -228 -218 -334 -178 -293 -340 -637 -453 -965 -69 -202
|
||||
-140 -458 -174 -635 -2 -14 -9 -47 -15 -75 -13 -62 -20 -106 -55 -360 -37
|
||||
-258 -43 -912 -11 -1106 2 -13 6 -51 10 -84 3 -33 8 -76 10 -95 11 -75 27
|
||||
-176 32 -205 3 -16 7 -39 8 -50 7 -43 16 -89 20 -94 2 -4 6 -24 9 -46 6 -38
|
||||
50 -211 95 -375 93 -339 299 -812 504 -1155 105 -175 101 -169 107 -175 3 -3
|
||||
27 -39 54 -80 50 -77 254 -351 301 -405 14 -16 49 -57 78 -90 149 -172 466
|
||||
-486 549 -543 13 -9 32 -25 43 -35 92 -87 397 -307 599 -432 309 -190 707
|
||||
-377 1035 -485 206 -68 328 -103 400 -117 14 -2 28 -6 31 -8 5 -3 121 -28 231
|
||||
-50 56 -11 257 -45 299 -50 289 -35 363 -39 675 -39 245 -1 407 5 510 19 17 2
|
||||
59 7 95 10 36 4 74 9 85 11 11 1 40 6 65 9 81 11 257 44 377 71 65 14 124 27
|
||||
133 29 8 2 56 15 105 30 50 15 106 31 125 36 56 14 255 83 380 132 260 103
|
||||
475 207 735 357 160 92 510 340 675 478 218 182 544 511 671 677 13 17 26 32
|
||||
29 35 14 11 143 183 212 280 66 94 228 346 228 355 0 2 20 37 44 77 45 77 188
|
||||
360 220 438 11 25 27 63 37 85 125 284 284 828 325 1115 3 19 7 46 9 60 12 62
|
||||
23 148 31 225 3 33 7 71 10 85 25 158 25 830 -1 1020 -8 63 -16 129 -21 174
|
||||
-3 27 -6 52 -8 55 -2 3 -7 31 -11 61 -3 30 -8 62 -10 70 -2 8 -7 29 -9 45 -3
|
||||
17 -10 55 -16 85 -6 30 -14 66 -16 80 -44 226 -187 679 -284 895 -10 22 -32
|
||||
74 -50 115 -51 118 -200 404 -280 535 -221 366 -482 698 -781 995 -113 113
|
||||
-258 245 -332 303 -15 12 -39 32 -52 44 -36 32 -280 213 -350 260 -387 258
|
||||
-753 444 -1160 588 -242 86 -581 177 -780 209 -36 6 -82 14 -110 20 -11 2 -45
|
||||
7 -75 11 -30 4 -62 9 -71 10 -29 6 -116 15 -294 32 -50 4 -642 12 -647 9z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.3 KiB |
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"name": "",
|
||||
"short_name": "",
|
||||
"icons": [
|
||||
{
|
||||
"src": "android-chrome-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "android-chrome-512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
}
|
||||
],
|
||||
"theme_color": "#ffffff",
|
||||
"background_color": "#ffffff",
|
||||
"display": "standalone"
|
||||
}
|
|
@ -0,0 +1,273 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta name="msapplication-TileColor" content="#603cba">
|
||||
<meta name="msapplication-config" content="./favicons/browserconfig.xml">
|
||||
<meta name="theme-color" content="#ffffff">
|
||||
<meta name="title" content="Générateur d'attestation de déplacement dérogatoire - COVID-19">
|
||||
<meta name="description" content="Ce service officiel génère une version numérique de l’attestation déplacement covid-19 à présenter aux forces de sécurité lors d’un contrôle.">
|
||||
<meta name="keywords" content="covid19, covid-19, attestation, déplacement, officielle, gouvernement">
|
||||
<meta name="robots" content="index, follow">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<meta name="language" content="French">
|
||||
<meta property="og:title" content="Générateur d'attestation de déplacement dérogatoire - COVID-19" />
|
||||
<meta property="og:locale" content="fr_FR" />
|
||||
<meta property="og:description" content="Ce service officiel génère une version numérique de l’attestation déplacement covid-19 à présenter aux forces de sécurité lors d’un contrôle." />
|
||||
<link rel="canonical" href="https://media.interieur.gouv.fr/deplacement-covid-19/" />
|
||||
<meta property="og:url" content="https://media.interieur.gouv.fr/deplacement-covid-19/" />
|
||||
<meta property="og:site_name" content="Générateur d'attestation de déplacement dérogatoire - COVID-19" />
|
||||
<script type='application/ld+json'>{"@context":"http://www.schema.org","@type":"GovernmentOrganization","name":"Générateur d'attestation de déplacement dérogatoire - COVID-19","description":"Ce service officiel génère une version numérique de l’attestation déplacement covid-19 à présenter aux forces de sécurité lors d’un contrôle.","address":{"@type":"PostalAddress","addressCountry":"France"}}</script>
|
||||
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="./favicons/apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="./favicons/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="./favicons/favicon-16x16.png">
|
||||
<link rel="manifest" href="./favicons/site.webmanifest">
|
||||
<link rel="mask-icon" href="./favicons/safari-pinned-tab.svg" color="#21bf73">
|
||||
|
||||
<title>COVID-19 – Générateur d'attestation de déplacement dérogatoire</title>
|
||||
</head>
|
||||
<body>
|
||||
<header class="wrapper">
|
||||
<img class="logo" src="/MIN_Interieur_RVB.svg" alt="">
|
||||
<div>
|
||||
<h1 class="flex flex-wrap">
|
||||
<span class="covid-title">
|
||||
COVID-19
|
||||
</span>
|
||||
<span class="covid-subtitle">
|
||||
Générateur d'attestation de déplacement dérogatoire
|
||||
</span>
|
||||
</h1>
|
||||
<p class="text-alert">
|
||||
Les données saisies sont stockées exclusivement sur votre téléphone ou votre ordinateur. Aucune information n'est collectée par le Ministère de l'Intérieur.
|
||||
L'attestation pdf générée contient un QR Code. Ce code-barres graphique permet de lire les informations portées dans votre attestation au moment de leur saisie.
|
||||
Il peut être déchiffré à l'aide de tout type de lecteur de QR code générique.
|
||||
</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="wrapper">
|
||||
|
||||
<form id="form-profile">
|
||||
<h2 class="titre-2">Remplissez en ligne votre attestation numérique :</h2>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="field-firstname" id="field-firstname-label">Prénom</label>
|
||||
<div class="input-group align-items-center">
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="field-firstname"
|
||||
name="firstname"
|
||||
autocomplete="given-name"
|
||||
placeholder="Jean"
|
||||
aria-labelledby="field-firstname-label"
|
||||
required
|
||||
autofocus
|
||||
>
|
||||
<span class="validity"></span>
|
||||
</div>
|
||||
<p class="exemple"></p>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="field-lastname" id="field-lastname-label">Nom</label>
|
||||
<div class="input-group align-items-center">
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="field-lastname"
|
||||
name="lastname"
|
||||
autocomplete="family-name"
|
||||
placeholder="Dupont"
|
||||
aria-labelledby="field-lastname-label"
|
||||
required
|
||||
autofocus
|
||||
>
|
||||
<span class="validity"></span>
|
||||
</div>
|
||||
<p class="exemple"></p>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="field-birthday" id="field-birthday-label">Date de naissance (au format jj/mm/aaaa)</label>
|
||||
<div class="input-group align-items-center">
|
||||
<input
|
||||
type="text"
|
||||
inputmode="numeric"
|
||||
class="form-control"
|
||||
id="field-birthday"
|
||||
name="birthday"
|
||||
autocomplete="bday"
|
||||
placeholder="01/01/1970"
|
||||
maxlength="10"
|
||||
aria-labelledby="field-birthday-label"
|
||||
required
|
||||
>
|
||||
<span class="validity"></span>
|
||||
</div>
|
||||
<p class="exemple"></p>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="field-lieunaissance" id="field-lieunaissance-label">Lieu de naissance</label>
|
||||
<div class="input-group align-items-center">
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="field-lieunaissance"
|
||||
name="lieunaissance"
|
||||
aria-labelledby="field-lieunaissance-label"
|
||||
placeholder="Lyon"
|
||||
required
|
||||
>
|
||||
<span class="validity"></span>
|
||||
</div>
|
||||
<p class="exemple"></p>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="field-address" id="field-address-label">Adresse</label>
|
||||
<div class="input-group align-items-center">
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="field-address"
|
||||
name="address"
|
||||
autocomplete="address-line1"
|
||||
aria-labelledby="field-address-label"
|
||||
placeholder="999 avenue de france"
|
||||
required
|
||||
>
|
||||
<span class="validity"></span>
|
||||
</div>
|
||||
<p class="exemple"></p>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="field-town" id="field-town-label">Ville</label>
|
||||
<div class="input-group align-items-center">
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="field-town"
|
||||
name="town"
|
||||
autocomplete="address-level1"
|
||||
aria-labelledby="field-town-label"
|
||||
placeholder="Paris"
|
||||
required
|
||||
>
|
||||
<span class="validity"></span>
|
||||
</div>
|
||||
<p class="exemple"></p>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="field-zipcode" id="field-zipcode-label" >Code Postal</label>
|
||||
<div class="input-group align-items-center">
|
||||
<input
|
||||
type="number"
|
||||
min="00000"
|
||||
max="99999"
|
||||
class="form-control"
|
||||
id="field-zipcode"
|
||||
name="zipcode"
|
||||
autocomplete="zipcode"
|
||||
minlength="4"
|
||||
maxlength="5"
|
||||
aria-labelledby="field-zipcode-label"
|
||||
placeholder="75001"
|
||||
required
|
||||
>
|
||||
<span class="validity"></span>
|
||||
</div>
|
||||
<p class="exemple"></p>
|
||||
</div>
|
||||
|
||||
<h3>Choisissez un motif de sortie</h3>
|
||||
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" name="field-reason" id="checkbox-travail" value="travail">
|
||||
<label class="form-check-label" for="checkbox-travail">Déplacements entre le domicile et le lieu d’exercice de l’activité professionnelle, lorsqu'ils sont indispensables à l'exercice d’activités ne pouvant être organisées sous forme de télétravail ou déplacements professionnels ne pouvant être différés.</label>
|
||||
</div>
|
||||
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" name="field-reason" id="checkbox-courses" value="courses">
|
||||
<label class="form-check-label" for="checkbox-courses">Déplacements pour effectuer des achats de fournitures nécessaires à l’activité professionnelle et des achats de première nécessité dans des établissements dont les activités demeurent autorisées <a href="https://www.service-public.fr/particuliers/actualites/A13921" target="_blank">(liste sur gouvernement.fr)</a>.</label>
|
||||
</div>
|
||||
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" name="field-reason" id="checkbox-sante" value="sante">
|
||||
<label class="form-check-label" for="checkbox-sante">Consultations et soins ne pouvant être assurés à distance et ne pouvant être différés ; consultations et soins des patients atteints d'une affection de longue durée.</label>
|
||||
</div>
|
||||
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" name="field-reason" id="checkbox-famille" value="famille">
|
||||
<label class="form-check-label" for="checkbox-famille">Déplacements pour motif familial impérieux, pour l’assistance aux personnes vulnérables ou la garde d’enfants.</label>
|
||||
</div>
|
||||
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" name="field-reason" id="checkbox-sport" value="sport">
|
||||
<label class="form-check-label" for="checkbox-sport">Déplacements brefs, dans la limite d'une heure quotidienne et dans un rayon maximal d'un kilomètre autour du domicile, liés soit à l'activité physique individuelle des personnes, à l'exclusion de toute pratique sportive collective et de toute proximité avec d'autres personnes, soit à la promenade avec les seules personnes regroupées dans un même domicile, soit aux besoins des animaux de compagnie.</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" name="field-reason" id="checkbox-judiciaire" value="judiciaire">
|
||||
<label class="form-check-label" for="checkbox-judiciaire">Convocation judiciaire ou administrative.</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" name="field-reason" id="checkbox-missions" value="missions">
|
||||
<label class="form-check-label" for="checkbox-missions">Participation à des missions d’intérêt général sur demande de l’autorité administrative.</label>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="field-datesortie">Date de sortie</label>
|
||||
<div class="input-group align-items-center">
|
||||
<input type="date" class="form-control" id="field-datesortie" name="datesortie" placeholder="JJ/MM/YYYY" required>
|
||||
<span class="validity"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="field-heure">Heure de sortie</label>
|
||||
<div class="input-group align-items-center">
|
||||
<input type="time" class="form-control" id="field-heuresortie" name="heure" required>
|
||||
<span class="validity"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<p class="text-center mt-5">
|
||||
<button type="submit" class="btn btn-primary btn-attestation"> <span class="btn-text">Générer mon attestation</span></button>
|
||||
</p>
|
||||
<div class="bg-primary d-none" id="snackbar">
|
||||
L'attestation est téléchargée sur votre appareil.
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="">
|
||||
<p class="label-mi">
|
||||
Ministère de l'Intérieur - DNUM - SDIT
|
||||
</p>
|
||||
<img class="center" src="/logo_dnum.svg" alt="logo dnum">
|
||||
</div>
|
||||
|
||||
<footer class="main-footer">
|
||||
<div class="footer-links">
|
||||
<a href="./confidentialite.html" title="Confidentialité - nouvelle page" target="_blank" class="footer-link">Confidentialité</a>
|
||||
<a href="https://www.interieur.gouv.fr/Infos-du-site/Mentions-legales" title="Mentions légales - nouvelle page" target="_blank" class="footer-link">Mentions légales</a>
|
||||
<a href="https://www.gouvernement.fr/info-coronavirus" title="Information du gouvernement sur le Covid-19 - nouvelle page" target="_blank" class="footer-link">Informations du gouvernement sur le Covid-19</a>
|
||||
<div class="footer-link" >Plus d’infos au<a class="num-08" href="tel:0800130000"> 0 800 130 000</a></div>
|
||||
<p class="footer-link" id="version"></p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<div class="alert alert-danger d-none" role="alert" id="alert-facebook">
|
||||
ATTENTION !! Vous utilisez actuellement le navigateur Facebook, ce générateur ne fonctionne pas correctement au
|
||||
sein de ce navigateur ! Merci d'ouvrir Chrome sur Android ou bien Safari sur iOS.
|
||||
</div>
|
||||
|
||||
<script src="./certificate.js"></script>
|
||||
</body>
|
||||
</html>
|
After Width: | Height: | Size: 49 KiB |
|
@ -0,0 +1,367 @@
|
|||
@font-face {
|
||||
font-family: 'marianne-bold';
|
||||
src: url('./fonts/marianne-bold-webfont.woff2') format('woff2'),
|
||||
url('./fonts/marianne-bold-webfont.woff') format('woff');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'marianne-regular';
|
||||
src: url('./fonts/marianne-regular-webfont.woff2') format('woff2'),
|
||||
url('./fonts/marianne-regular-webfont.woff') format('woff');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
form, #alert-print {
|
||||
margin: 30px auto;
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
|
||||
}
|
||||
|
||||
/* Small devices (landscape phones, 576px and up) */
|
||||
@media (min-width: 576px) {
|
||||
h1 {
|
||||
font-size: 2.5em;
|
||||
}
|
||||
}
|
||||
|
||||
/* Medium devices (tablets, 768px and up) */
|
||||
@media (min-width: 768px) {
|
||||
h1 {
|
||||
font-size: 3em;
|
||||
}
|
||||
}
|
||||
|
||||
svg {
|
||||
height: 1em;
|
||||
}
|
||||
|
||||
h1.flex.flex-wrap {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: large;
|
||||
}
|
||||
|
||||
footer {
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
canvas {
|
||||
border: 1px solid #ced4da;
|
||||
border-radius: .25rem;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
max-width: 800px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
#form-profile .form-check {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
#form-profile .form-check-label {
|
||||
font-weight: 400;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
#form-generate .form-check {
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
#alert-facebook {
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
left: 20px;
|
||||
right: 20px;
|
||||
}
|
||||
|
||||
#alert-print {
|
||||
margin: 1rem auto 0;
|
||||
}
|
||||
|
||||
#date-selector-group {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#date-selector-group-sortie {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#date-selector {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 50%;
|
||||
height: 100%;
|
||||
transform: translateX(-50%); /* center the input to avoid reset buttons */
|
||||
opacity: 0;
|
||||
z-index: 1;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#date-selector-sortie {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 50%;
|
||||
height: 100%;
|
||||
transform: translateX(-50%); /* center the input to avoid reset buttons */
|
||||
opacity: 0;
|
||||
z-index: 1;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
input:invalid+span:after {
|
||||
content: '✖';
|
||||
padding-left: 0.3em;
|
||||
}
|
||||
|
||||
input:valid+span:after {
|
||||
content: '✓';
|
||||
padding-left: 0.3em;
|
||||
}
|
||||
|
||||
::placeholder {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.exemple {
|
||||
margin-top: 0.2em;
|
||||
font-style: italic;
|
||||
color: #999999;
|
||||
height: 1em;
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
|
||||
.covid-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0.3em;
|
||||
font-family: 'marianne-regular', Arial, Helvetica, sans-serif;
|
||||
font-size: 0.50em;
|
||||
color: #ffffff;
|
||||
background-color: #000191;
|
||||
}
|
||||
|
||||
@media (min-width: 992px) {
|
||||
.covid-title {
|
||||
flex-grow: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.covid-subtitle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 0.40em;
|
||||
padding: 0.3em;
|
||||
background-color: #e1000f;
|
||||
text-transform:uppercase ;
|
||||
color: #ffffff;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.text-alert{
|
||||
text-align: left;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.btn-attestation {
|
||||
padding: 0.8em;
|
||||
font-size: 1.2em;
|
||||
font-weight: bold;
|
||||
color: #ffffff;
|
||||
background-color: #000191;
|
||||
border-radius: 0.5em;
|
||||
}
|
||||
|
||||
.github {
|
||||
font-size: 0.7em;
|
||||
text-align: center;
|
||||
color: #000000;
|
||||
|
||||
}
|
||||
|
||||
.github-link {
|
||||
color: #000191;
|
||||
}
|
||||
|
||||
.label-mi {
|
||||
text-align: center;
|
||||
font-size: 1em;
|
||||
color: #000000
|
||||
}
|
||||
|
||||
.main-footer {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding-top: 3em;
|
||||
padding-bottom: 3em;
|
||||
background-color:#000000;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.footer-links {
|
||||
margin: 0 auto;
|
||||
max-width: 500px;
|
||||
}
|
||||
|
||||
.footer-link {
|
||||
display: block;
|
||||
margin: 0.75em;
|
||||
font-size: 0.9em;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.footer-link:hover {
|
||||
text-decoration: none;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.footer-link:focus {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.num-08 {
|
||||
font-weight: bold;
|
||||
color: #00a94f;
|
||||
}
|
||||
|
||||
.confidentialite {
|
||||
.cookies {
|
||||
border-collapse: collapse;
|
||||
|
||||
td,
|
||||
th {
|
||||
border: 1px solid #000191;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.header-row {
|
||||
font-weight: bold;
|
||||
color: #ffffff;
|
||||
background-color: #000191;
|
||||
text-transform: uppercase;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.name-col {
|
||||
font-weight: bold;
|
||||
padding: 8px 16px;
|
||||
color: #000191;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.btn-wrapper {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
.btn-generateur {
|
||||
padding: 0.8em;
|
||||
font-size: 1.2em;
|
||||
font-weight: bold;
|
||||
color: #ffffff;
|
||||
background-color: #000191;
|
||||
border-radius: 0.5em;
|
||||
text-decoration: none;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
}
|
||||
em {
|
||||
font-size: .8rem;
|
||||
}
|
||||
}
|
||||
|
||||
.titre-2 {
|
||||
text-align: left;
|
||||
font-size: 1.5rem;
|
||||
font-weight: bold;
|
||||
color: #000191;
|
||||
}
|
||||
.titre-3 {
|
||||
text-align: left;
|
||||
font-size: 1.25rem;
|
||||
font-weight: bold;
|
||||
color: #000000;
|
||||
}
|
||||
.titre-4 {
|
||||
text-align: left;
|
||||
font-size: 1rem;
|
||||
font-weight: bold;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
@media (max-width: 800px){
|
||||
table thead {
|
||||
display: none;
|
||||
}
|
||||
|
||||
table tr{
|
||||
display: block;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
table td {
|
||||
display: flex;
|
||||
text-align: left;
|
||||
min-height: 3rem;
|
||||
}
|
||||
|
||||
table td:before {
|
||||
content: attr(data-label);
|
||||
font-weight: bold;
|
||||
color: #000191;
|
||||
width: 100px;
|
||||
margin-right: 8px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
|
||||
#snackbar {
|
||||
min-width: 250px;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
border-radius: 3px;
|
||||
padding: 16px;
|
||||
position: fixed;
|
||||
z-index: 1;
|
||||
left: 50%;
|
||||
bottom: 30px;
|
||||
font-size: 17px;
|
||||
transform: translateX(-50%);
|
||||