-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathgenerateHTML.js
355 lines (323 loc) · 17.9 KB
/
generateHTML.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
const data = require('./data.json')
const marked = require("marked")
const renderMarkdown = (text) => {
return marked.parse(text)
}
const cleanId = (id) => {
return id.replace(".", "_")
}
const anchorText = (txt) => {
return encodeURIComponent(txt)
}
const moduleLink = (moduleId) => {
return `<a href="https://www.modulbaukasten.ch/module/${moduleId}/0/fr-FR" target="_blank">${moduleId}</a>`
}
// Change the layout of the checkboxes
let mode_vertical = false
const args = process.argv.slice(2)
if (args[0] === '--vertical') {
mode_vertical = true
}
console.log(`<!DOCTYPE html>
<html lang="en">`)
// Head
console.log(`
<head>
<title>Dossier de formation de</title>
<script
src="https://code.jquery.com/jquery-3.6.0.slim.min.js"
integrity="sha256-u7e5khyithlIdTpu22PHhENmPcRdFiHRjhAuHcs05RI="
crossorigin="anonymous">
</script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.3.1/dist/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<link rel="stylesheet" href="styles.css">
<!-- Favicon -->
<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="#5bbad5">
<link rel="shortcut icon" href="favicons/favicon.ico">
<meta name="apple-mobile-web-app-title" content="dossier-formation">
<meta name="application-name" content="dossier-formation">
<meta name="msapplication-TileColor" content="#da532c">
<meta name="msapplication-config" content="favicons/browserconfig.xml">
<meta name="theme-color" content="#ffffff">
</head>`)
// Body
console.log(`
<body>
<h1><img src="favicons/favicon-32x32.png" /> Dossier de formation de <span id="dossier-name" contenteditable="true">Prénom Nom (changez-moi)</span></h1>`)
if (mode_vertical) {
console.log(`
<div class="no-print" style="float: right"><a href="index.html">horizontal</a></div>`)
} else {
console.log(`
<div class="no-print" style="float: right"><a href="index-vertical.html">vertical</a></div>`)
}
console.log(`
<button id="export-button" class="btn btn-primary no-print">Export to JSON</button>
<label class ="custom-file-upload btn btn-primary no-print">Import JSON<input class="d-none" type="file" id="import-file"/></label>`)
console.log(`
<div class="no-print">
<h2 id="a-propos">À propos</h2>
<p>
Vous consultez actuellement un projet fonctionnel de dossier de formation électronique à l’attention des
apprenti·e·s informaticien·ne en orientation développement d’applications. Des explications plus détaillées
ainsi que les sources du projet sont disponibles sur la page du projet sur
<a href="https://github.com/ponsfrilus/dossier-formation" target="_blank">GitHub</a>.
</p>
<p>
Ce dossier de formation a pour but de se conformer à
l’<a href="https://www.fedlex.admin.ch/eli/oc/2020/941/fr">article 12 de l’Ordonnance du SEFRI sur la
formation professionnelle initiale d’informaticienne / informaticien avec certificat fédéral de capacité
(CFC)</a>.
<blockquote>
Pendant la formation à la pratique professionnelle, la personne en formation tient un dossier de formation
dans lequel elle inscrit au fur et à mesure les travaux importants concernant les compétences opérationnelles à
acquérir. Au moins une fois par semestre, le formateur contrôle et signe le dossier de formation et en discute
avec la personne en formation.
</blockquote>
</p>
<p>
Les textes des différentes compétences opérationnelles de ce document sont repris du document officiel
disponible sur le site <a href="https://www.ict-berufsbildung.ch/formation-initiale/apprentissages-ict/informaticienne-cfc" target="blank">http://ict-formationprofessionnelle.ch</a>, plus particuliérement le document
<a href="https://www.ict-berufsbildung.ch/resources/Bildungsplan_Informatik-EFZ_BiVo-2021_FR1.pdf">Bildungsplan_Informatik-EFZ_BiVo-2021_FR1.pdf</a>.
</p>
<p>
L’Institut fédéral des hautes études en formation professionnelle (IFFP) a élaboré des standards pour
un dossier de formation de qualité dans la formation professionnelle initiale. Ce document est téléchargeable sur
le site <a href="https://formationprof.ch/dyn/bin/18579-19380-1-20120917_ehb-standards_ld-f.pdf">formationprof.ch</a>,
et nous incitons apprenant·e·s et formateurs·trices à le consulter.
</p>
<h3 id="utilisation">Utilisation</h3>
<p>
L'utilisation se veut très simple :
<ol>
<li>Commencez par modifier le titre de cette page en cliquant sur "Prénom Nom (changez-moi)".</li>
<li>Cochez les cases selon l'avancement de votre apprentissage ; le site sauvegarde automatiquement
vos modifications dans le stockage de votre navigateur.</li>
<li>Utilisez les boutons "Export to JSON" et "Import JSON" pour partager votre dossier de formation avec
des tiers (par exemple votre formateur·trice).</li>
<li>À toutes fins utiles, vous pouvez utiliser la fonction "imprimer" de votre navigateur pour sauver
une version PDF du document.</li>
</ol>
</p>
<p>
Toutes questions ou commentaires peuvent être adressés via des issues sur la page du projet
<a href="https://github.com/ponsfrilus/dossier-formation" target="_blank">GitHub</a>.
</p>
<hr size="1" />
</div>
`)
for (domaineDeCompetance of data) {
for (competence of domaineDeCompetance.competences) {
let verticalColspan = mode_vertical ? 4 : 2
console.log(`
<h4 id="${anchorText(competence.title)}">${competence.title} : ${competence.subject}</h4>
<div>${renderMarkdown(competence.description)}</div>
<table class="main-table external-border">
<tr>
<th class="main-th border-bottom" colspan="${verticalColspan}">Objectifs évaluateurs entreprise</th>
<th class="main-th border-bottom">Modules école professionnelle</th>
<th class="main-th border-bottom">Modules cours interentreprises</th>
</tr>`)
if (mode_vertical) {
console.log(`
<tr>
<td class="border-bottom border-right"> </td>
<td class="vericaltext border-bottom border-right no-padding">expliqué</td>
<td class="vericaltext border-bottom border-right no-padding">exercé</td>
<td class="vericaltext border-bottom border-right no-padding">autonome</td>
<td class="border-bottom border-right"> </td>
<td class="border-bottom"> </td>
</tr>`)
}
let alreadyDisplayModuleEcolePro = false
let alreadyDisplayModuleCoursInter = false
for (objectif of competence["Objectifs évaluateurs entreprise"]) {
if (mode_vertical) {
console.log(`
<tr>
<td class="module border-bottom">
<p>${objectif.id}: ${objectif.descr} (${objectif.bloom})</p>
<small class="show-hide-comment" data-objectifId="${cleanId(objectif.id)}">Montrer commentaire / Cacher commentaire</small>
<div id="${cleanId(objectif.id)}-comment" contenteditable="true" class="editable-comment-div">Vous pouvez écrire vos commentaires personnels ici.</div>
</td>
<td class="border-bottom"><input id="${cleanId(objectif.id)}_explique" type="checkbox" /></td>
<td class="border-bottom"><input id="${cleanId(objectif.id)}_exerce" type="checkbox" /></td>
<td class="border-bottom border-right"><input id="${cleanId(objectif.id)}_autonome" type="checkbox" /></td>`)
} else {
console.log(`
<tr>
<td class="module border-bottom">
<p>${objectif.id}: ${objectif.descr}</p>
<small class="show-hide-comment" data-objectifId="${cleanId(objectif.id)}">Montrer commentaire / Cacher commentaire</small>
<div id="${cleanId(objectif.id)}-comment" contenteditable="true" class="editable-comment-div">Vous pouvez écrire vos commentaires personnels ici.</div>
</td>
<td class="border-bottom border-right">
<table>
<tr>
<td class="border-bottom">Bloom</td>
<td class="border-bottom">${objectif.bloom}</td>
</tr>
<tr>
<td class="objectifs-check">
<label for="${cleanId(objectif.id)}_explique">Expliqué</label>
</td>
<td><input id="${cleanId(objectif.id)}_explique" type="checkbox" /></td>
</tr>
<tr>
<td class="objectifs-check">
<label for="${cleanId(objectif.id)}_exerce">Exercé</label>
</td>
<td><input id="${cleanId(objectif.id)}_exerce" type="checkbox" /></td>
</tr>
<tr>
<td class="objectifs-check">
<label for="${cleanId(objectif.id)}_autonome">Autonome</label>
</td>
<td><input id="${cleanId(objectif.id)}_autonome" type="checkbox" /></td>
</tr>
</table>
</td>`)
}
if(competence["Modules école professionnelle"] && !alreadyDisplayModuleEcolePro) {
alreadyDisplayModuleEcolePro = true
console.log(` <td class="modulesEcolePro border-right" rowspan="${competence["Objectifs évaluateurs entreprise"].length}">`)
for(moduleEcolePro of competence["Modules école professionnelle"]) {
console.log(` <p>${moduleLink(moduleEcolePro.id)}: ${moduleEcolePro.descr}</p>`)
}
console.log(` </td>`)
} else if(!competence["Modules école professionnelle"] && !alreadyDisplayModuleEcolePro){
alreadyDisplayModuleEcolePro = true
console.log(` <td class="modulesEcolePro border-right" rowspan="${competence["Objectifs évaluateurs entreprise"].length}"></td>`)
}
if(competence["Modules cours interentreprises"] && !alreadyDisplayModuleCoursInter) {
alreadyDisplayModuleCoursInter = true
console.log(` <td class="modulesCoursInter" rowspan="${competence["Objectifs évaluateurs entreprise"].length}">`)
for(moduleCoursInter of competence["Modules cours interentreprises"]) {
console.log(` <p>${moduleLink(moduleCoursInter.id)}: ${moduleCoursInter.descr}</p>`)
}
console.log(` </td>`)
} else if(!competence["Modules cours interentreprises"] && !alreadyDisplayModuleCoursInter) {
alreadyDisplayModuleCoursInter = true
console.log(` <td class="modulesCoursInter" rowspan="${competence["Objectifs évaluateurs entreprise"].length}"></td>`)
}
console.log(` </tr>`)
}
console.log(` </table>`)
}
}
const version = require('./package.json').version
console.log(`
<footer class="pt-5 text-center border-top">
<p>
Coded with ❤ by <a href="https://github.com/Azecko" target="_blank">Azecko</a> —
sources <a href="https://github.com/ponsfrilus/dossier-formation" target="_blank">dossier_formation</a> —
<span class="version"></span>
</p>
</footer>
<script>
const dossierFormationVarName = 'dossier-formation-properties'
const setLocalStorage = () => {
var localStorageItems = {}
var dossierName = $('#dossier-name').text()
document.title = 'Dossier de formation de ' + dossierName
localStorageItems['name'] = dossierName
localStorageItems[dossierFormationVarName] = true
localStorageItems['dossier-formation-version'] = '${version}'
$('input[type=checkbox]').each(function () {
localStorageItems[$(this).attr('id')] = this.checked
})
$('.editable-comment-div').each(function() {
localStorageItems[$(this).attr('id')] = $(this).text()
})
localStorage.setItem(dossierFormationVarName, JSON.stringify(localStorageItems, null, 2))
}
var dossierFormationLocalStorage = localStorage.getItem(dossierFormationVarName)
if(!dossierFormationLocalStorage) {
setLocalStorage()
} else {
$('input[type=checkbox]').each(function () {
$(this).prop('checked', JSON.parse(dossierFormationLocalStorage)[$(this).attr('id')])
})
$('.editable-comment-div').each(function() {
$(this).text(JSON.parse(dossierFormationLocalStorage)[$(this).attr('id')])
})
$('#dossier-name').text(JSON.parse(dossierFormationLocalStorage)['name'])
document.title = 'Dossier de formation de ' + JSON.parse(dossierFormationLocalStorage)['name']
}
$('input:checkbox').change(
function(){
setLocalStorage()
})
$('.editable-comment-div').on('DOMSubtreeModified', function(){
setLocalStorage()
})
document.getElementById("dossier-name").addEventListener("input", inputEvt => {
setLocalStorage()
}, false)
// https://stackoverflow.com/a/18197341
function download(filename, text) {
var element = document.createElement('a')
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text))
element.setAttribute('download', filename)
element.style.display = 'none'
document.body.appendChild(element)
element.click()
document.body.removeChild(element)
}
$('#export-button').click(function() {
var dossierFormationLocalStorage = localStorage.getItem(dossierFormationVarName)
var date = new Date()
var name = JSON.parse(dossierFormationLocalStorage)['name'].replaceAll(/\s\s+/g, '_').replaceAll(' ', '_')
download("dossier_formation_" + name + "_" + date.toISOString().split('T')[0] + ".json", localStorage.getItem(dossierFormationVarName))
})
document.getElementById('import-file').addEventListener('change', handleFileSelect, false)
$('.show-hide-comment').click(function() {
let objectifComment = "#" + $(this).attr('data-objectifId') + "-comment"
$(objectifComment).toggle()
$(this).text($(objectifComment).css("display") == "block" ? 'Cacher commentaire' : 'Montrer commentaire')
})
// https://stackoverflow.com/a/56737666
function handleFileSelect(event) {
const reader = new FileReader()
reader.onload = handleFileLoad
reader.readAsText(event.target.files[0])
}
// https://stackoverflow.com/a/3710226
function isJsonString(str) {
try {
JSON.parse(str)
} catch (e) {
return false
}
return true
}
function handleFileLoad(event) {
let confirm = window.confirm("Voulez-vous vraiment importer les données de ce fichier ?")
if(confirm) {
var resultObject = JSON.parse(event.target.result)
if(!resultObject[dossierFormationVarName] || !resultObject['dossier-formation-version']) {
alert("Merci d'importer un fichier JSON valide généré par le bouton Export to JSON.")
} else {
localStorage.setItem(dossierFormationVarName, event.target.result)
window.location.reload()
}
}
}
$('.version').html('v${version}')
/* add some anchors to titles */
$("h2, h3, h4").hover(
function () {
let id = $( this ).attr('id')
$( this ).append( "<span class='anchor'><a href='#"+id+"'>§</a></span>" )
}, function () {
$( this ).find( ".anchor" ).last().remove()
}
)
</script>
</body>
</html>
`)