PageSourceSearch

https://formation-sooty.vercel.app/dk-notebook.js

js formation-sooty.vercel.app collected 2026-10-03 06:57:56 UTC 17,710 bytes, 321 lines download raw bytes

1/* DressKool — « Mon carnet d'actions ».
2   ------------------------------------------------------------------
3   C'est la piece qui fait passer l'app de « cours » a « outil » : les 68 lecons
4   ne laissent plus seulement des cases cochees dans un localStorage, elles
5   produisent un PLAN D'AFFAIRES PERSONNEL que l'eleve peut relire, imprimer et
6   emporter (export .md ou .txt).
7
8   Source de verite : S.ex, ecrit par dk-lesson.js
9   ({ lid: { items:[bool], note, num, doneAt } }). Ce module ne fait que lire.
10
11   Points d'accroche, sans jamais toucher aux 6 index.html :
12     - route #/carnet          (DK.registerRoute, pose par dk-nav.js)
13     - encart tableau de bord  (DK.cards.push)
14     - entree sidebar + nav basse mobile (posees par dk-nav.js)
15   ------------------------------------------------------------------ */
16(function () {
17  var DK = window.DK;
18  if (!DK || !DK.S) return;
19  var t = DK.t, S = DK.S;
20
21  var L = {
22    fr: {
23      title: 'Mon carnet d’actions',
24      sub: 'Tout ce que tu as réellement fait pendant la formation, module par module. C’est ton plan de travail : relis-le, complète-le, emporte-le.',
25      empty_t: 'Ton carnet est encore vide',
26      empty_b: 'Chaque leçon se termine par un exercice concret. Coche ce que tu fais et note tes chiffres : tout se retrouve ici.',
27      empty_go: 'Commencer un exercice',
28      st_actions: 'actions faites', st_notes: 'notes écrites', st_lessons: 'leçons travaillées',
29      exp_md: '⬇ Exporter (.md)', exp_txt: '⬇ Exporter (.txt)',
30      note_label: 'Ta note', num_label: 'Ton chiffre',
31      card_t: 'Mon carnet d’actions', card_open: 'Ouvrir le carnet',
32      card_p: '{a} action(s) faite(s) et {n} note(s) sur {l} leçon(s).',
33      card_p0: 'Coche les exercices des leçons : ils construisent ton plan de travail ici.',
34      f_head: 'Mon carnet d’actions · DressKool',
35      f_by: 'Élève', f_on: 'Exporté le', f_done: 'Actions faites', f_notes: 'Notes'
36    },
37    en: {
38      title: 'My action notebook',
39      sub: 'Everything you actually did during the course, module by module. This is your working plan: read it again, complete it, take it with you.',
40      empty_t: 'Your notebook is still empty',
41      empty_b: 'Every lesson ends with a concrete exercise. Tick what you do and write your numbers: it all lands here.',
42      empty_go: 'Start an exercise',
43      st_actions: 'actions done', st_notes: 'notes written', st_lessons: 'lessons worked on',
44      exp_md: '⬇ Export (.md)', exp_txt: '⬇ Export (.txt)',
45      note_label: 'Your note', num_label: 'Your number',
46      card_t: 'My action notebook', card_open: 'Open the notebook',
47      card_p: '{a} action(s) done and {n} note(s) across {l} lesson(s).',
48      card_p0: 'Tick the lesson exercises: they build your working plan right here.',
49      f_head: 'My action notebook · DressKool',
50      f_by: 'Student', f_on: 'Exported on', f_done: 'Actions done', f_notes: 'Notes'
51    },
52    es: {
53      title: 'Mi cuaderno de acciones',
54      sub: 'Todo lo que has hecho de verdad durante la formación, módulo a módulo. Es tu plan de trabajo: reléelo, complétalo, llévatelo.',
55      empty_t: 'Tu cuaderno todavía está vacío',
56      empty_b: 'Cada lección termina con un ejercicio concreto. Marca lo que haces y anota tus cifras: todo aparece aquí.',
57      empty_go: 'Empezar un ejercicio',
58      st_actions: 'acciones hechas', st_notes: 'notas escritas', st_lessons: 'lecciones trabajadas',
59      exp_md: '⬇ Exportar (.md)', exp_txt: '⬇ Exportar (.txt)',
60      note_label: 'Tu nota', num_label: 'Tu cifra',
61      card_t: 'Mi cuaderno de acciones', card_open: 'Abrir el cuaderno',
62      card_p: '{a} acción(es) hecha(s) y {n} nota(s) en {l} lección(es).',
63      card_p0: 'Marca los ejercicios de las lecciones: construyen aquí tu plan de trabajo.',
64      f_head: 'Mi cuaderno de acciones · DressKool',
65      f_by: 'Alumna', f_on: 'Exportado el', f_done: 'Acciones hechas', f_notes: 'Notas'
66    },
67    it: {
68      title: 'Il mio quaderno di azioni',
69      sub: 'Tutto quello che hai davvero fatto durante il corso, modulo per modulo. È il tuo piano di lavoro: rileggilo, completalo, portalo con te.',
70      empty_t: 'Il tuo quaderno è ancora vuoto',
71      empty_b: 'Ogni lezione finisce con un esercizio concreto. Spunta quello che fai e annota i tuoi numeri: finisce tutto qui.',
72      empty_go: 'Inizia un esercizio',
73      st_actions: 'azioni fatte', st_notes: 'note scritte', st_lessons: 'lezioni lavorate',
74      exp_md: '⬇ Esporta (.md)', exp_txt: '⬇ Esporta (.txt)',
75      note_label: 'La tua nota', num_label: 'Il tuo numero',
76      card_t: 'Il mio quaderno di azioni', card_open: 'Apri il quaderno',
77      card_p: '{a} azione/i fatte e {n} nota/e su {l} lezione/i.',
78      card_p0: 'Spunta gli esercizi delle lezioni: costruiscono qui il tuo piano di lavoro.',
79      f_head: 'Il mio quaderno di azioni · DressKool',
80      f_by: 'Studentessa', f_on: 'Esportato il', f_done: 'Azioni fatte', f_notes: 'Note'
81    },
82    de: {
83      title: 'Mein Aktions-Notizbuch',
84      sub: 'Alles, was du in der Schulung wirklich getan hast, Modul für Modul. Das ist de
84in Arbeitsplan: lies ihn nach, ergänze ihn, nimm ihn mit.',
85      empty_t: 'Dein Notizbuch ist noch leer',
86      empty_b: 'Jede Lektion endet mit einer konkreten Übung. Hak ab, was du tust, und notiere deine Zahlen: alles landet hier.',
87      empty_go: 'Eine Übung starten',
88      st_actions: 'erledigte Aktionen', st_notes: 'geschriebene Notizen', st_lessons: 'bearbeitete Lektionen',
89      exp_md: '⬇ Export (.md)', exp_txt: '⬇ Export (.txt)',
90      note_label: 'Deine Notiz', num_label: 'Deine Zahl',
91      card_t: 'Mein Aktions-Notizbuch', card_open: 'Notizbuch öffnen',
92      card_p: '{a} Aktion(en) erledigt und {n} Notiz(en) in {l} Lektion(en).',
93      card_p0: 'Hak die Übungen der Lektionen ab: sie bauen hier deinen Arbeitsplan auf.',
94      f_head: 'Mein Aktions-Notizbuch · DressKool',
95      f_by: 'Teilnehmerin', f_on: 'Exportiert am', f_done: 'Erledigte Aktionen', f_notes: 'Notizen'
96    },
97    pt: {
98      title: 'O meu caderno de ações',
99      sub: 'Tudo o que fizeste mesmo durante a formação, módulo a módulo. É o teu plano de trabalho: relê-o, completa-o, leva-o contigo.',
100      empty_t: 'O teu caderno ainda está vazio',
101      empty_b: 'Cada lição acaba com um exercício concreto. Marca o que fazes e escreve os teus números: fica tudo aqui.',
102      empty_go: 'Começar um exercício',
103      st_actions: 'ações feitas', st_notes: 'notas escritas', st_lessons: 'lições trabalhadas',
104      exp_md: '⬇ Exportar (.md)', exp_txt: '⬇ Exportar (.txt)',
105      note_label: 'A tua nota', num_label: 'O teu número',
106      card_t: 'O meu caderno de ações', card_open: 'Abrir o caderno',
107      card_p: '{a} ação(ões) feita(s) e {n} nota(s) em {l} lição(ões).',
108      card_p0: 'Marca os exercícios das lições: são eles que constroem aqui o teu plano de trabalho.',
109      f_head: 'O meu caderno de ações · DressKool',
110      f_by: 'Aluna', f_on: 'Exportado a', f_done: 'Ações feitas', f_notes: 'Notas'
111    }
112  };
113  function x(k, vars) {
114    var d = L[DK.lang] || L.fr, s = (typeof d[k] === 'string') ? d[k] : (L.fr[k] || k);
115    if (vars) Object.keys(vars).forEach(function (v) { s = s.split('{' + v + '}').join(vars[v]); });
116    return s;
117  }
118  function esc(s) {
119    return String(s == null ? '' : s)
120      .replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
121      .replace(/"/g, '&quot;').replace(/'/g, '&#39;');
122  }
123  function plain(html) {
124    if (typeof DK.detag === 'function') return DK.detag(html);
125    var d = document.createElement('div');
126    d.innerHTML = String(html || '');
127    return (d.textContent || '').replace(/\s+/g, ' ').trim();
128  }
129
130  /* ══════════════════════════════════════════════════════════════
131     COLLECTE — on ne lit que S.ex, jamais on n'y ecrit
132     ══════════════════════════════════════════════════════════════ */
133  function collect() {
134    var DATA = window.DATA || [], ex = S.ex || {};
135    var out = [], nAct = 0, nNote = 0, nLes = 0;
136
137    DATA.forEach(function (b) {
138      var lessons = [];
139      b.lessons.forEach(function (l) {
140        var e = ex[l.id];
141        if (!e) return;
142        var labels = [];
143        if (typeof DK.parseExercise === 'function' && Array.isArray(e.items)) {
144          var p = DK.parseExercise(l.exercise);
145          e.items.forEach(function (on, i) {
146            if (on && p.items[i]) labels.push(plain(p.items[i]));
147          });
148        }
149        var note = (e.note || '').trim();
150        var num = (e.num || '').trim();
151        if (!labels.length && !note && !num) return;
152        nAct += labels.length;
153        if (note) nNote++;
154        nLes++;
155        lessons.push({ id: l.id, title: l.title, actions: labels, note: note, num: num, doneAt: e.doneAt || '' });
156      });
157      if (lessons.length) out.push({ mod: b, lessons: lessons });
158    });
159    return { groups: out, actions: nAct, notes: nNote, lessons: nLes };
160  }
161
162  /* ══════════════════════════════════════════════════════════════
163     EXPORT
164     ══════════════════════════════════════════════════════════════ */
165  function buildText(fmt) {
166    var d = collect(), lines = [];
167    var today = new Date().toLocaleDateString(DK.lang);
168    var md = fmt === 'md';
169
170    lines.push(md ? '# ' + x('f_head') : x('f_head').toUpperCase());
171    lines.push('');
172    if (S.user) lines.push(x('f_by') + ' : ' + S.user);
173    lines.push(x('f_on') + ' : ' + today);
174    lines.push(x('f_done') + ' : ' + d.actions + '   ·   ' + x('f_notes') + ' : ' + d.notes);
175    lines.push('');
176
177    d.groups.forEach(function (g) {
178      lines.push(md ? '## ' + g.mod.emoji + ' ' + g.mod.id + '. ' + g.mod.title
179                    : '== ' + g.mod.id + '. ' + plain(g.mod.title) + ' ==');
180      lines.push('');
181      g.lessons.forEach(function (l) {
182        lines.push(md ? '### ' + plain(l.title) : '-- ' + plain(l.title));
183        l.actions.forEach(function (a) { lines.push(md ? '- [x] ' + a : '  [x] ' + a); });
184        if (l.num) lines.push((md ? '- **' + x('num_label') + '** : ' : '  ' + x('num_label') + ' : ') + l.num);
185        if (l.note) {
186          lines.push('');
187          lines.push(md ? '> ' + l.note.split('\n').join('\n> ') : '  ' + l.note.split('\n').join('\n  '));
188        }
189        lines.push('');
190      });
191    });
192    if (!d.groups.length) { lines.push(x('empty_b')); lines.push(''); }
193    lines.push(md ? '---' : '');
194    lines.push('DressKool · https://formation-sooty.vercel.app');
195    return lines.join('\n');
196  }
197
198  function download(fmt) {
199    var text = buildText(fmt);
200    var name = 'carnet-dresskool-' + new Date().toISOString().slice(0, 10) + '.' + (fmt === 'md' ? 'md' : 'txt');
201    try {
202      var blob = new Blob([text], { type: 'text/' + (fmt === 'md' ? 'markdown' : 'plain') + ';charset=utf-8' });
203      var url = URL.createObjectURL(blob);
204      var a = document.createElement('a');
205      a.href = url;
205 a.download = name;
206      document.body.appendChild(a);
207      a.click();
208      setTimeout(function () { document.body.removeChild(a); URL.revokeObjectURL(url); }, 400);
209      if (typeof DK.ftrack === 'function') DK.ftrack('notebook_exported', { format: fmt, actions: collect().actions });
210    } catch (e) {
211      /* Repli : un onglet avec le texte brut vaut mieux qu'un bouton mort. */
212      try { var w = window.open('', '_blank'); if (w) { w.document.write('<pre></pre>'); w.document.querySelector('pre').textContent = text; } }
213      catch (e2) {}
214    }
215  }
216
217  /* ══════════════════════════════════════════════════════════════
218     VUE #/carnet
219     ══════════════════════════════════════════════════════════════ */
220  function view() {
221    if (typeof DK.enterApp === 'function') DK.enterApp();
222    S.view = 'carnet'; S.cur = null;
223    if (typeof DK.sv === 'function') DK.sv();
224    if (typeof window.renderSB === 'function') window.renderSB();
225
226    var main = document.getElementById('main');
227    if (!main) return;
228    var d = collect();
229
230    var head = '<div class="dk-nb-hd"><div><h1>📓 ' + esc(x('title')) + '</h1><p>' + esc(x('sub')) + '</p></div>' +
231      (d.groups.length
232        ? '<div class="dk-nb-acts"><button type="button" class="pri" id="dk-nb-md">' + esc(x('exp_md')) +
233          '</button><button type="button" id="dk-nb-txt">' + esc(x('exp_txt')) + '</button></div>'
234        : '') + '</div>';
235
236    if (!d.groups.length) {
237      main.innerHTML = head +
238        (typeof DK.emptyHTML === 'function'
239          ? DK.emptyHTML('📝', x('empty_t'), x('empty_b'), x('empty_go'), 'dk-nb-go')
240          : '<div class="dk-empty"><h3>' + esc(x('empty_t')) + '</h3><p>' + esc(x('empty_b')) + '</p></div>');
241      var go = document.getElementById('dk-nb-go');
242      if (go) go.addEventListener('click', function () { window.continueCourse(); });
243      if (typeof DK.scrollTop === 'function') DK.scrollTop();
244      return;
245    }
246
247    var stats = '<div class="dk-nb-stats">' +
248      '<div class="dk-nb-stat"><div class="n">' + d.actions + '</div><div class="k">' + esc(x('st_actions')) + '</div></div>' +
249      '<div class="dk-nb-stat"><div class="n">' + d.notes + '</div><div class="k">' + esc(x('st_notes')) + '</div></div>' +
250      '<div class="dk-nb-stat"><div class="n">' + d.lessons + '</div><div class="k">' + esc(x('st_lessons')) + '</div></div>' +
251      '</div>';
252
253    var body = d.groups.map(function (g) {
254      return '<div class="dk-nb-mod"><h3><span aria-hidden="true">' + g.mod.emoji + '</span>' +
255        t('block') + ' ' + g.mod.id + ' · ' + g.mod.short + '</h3>' +
256        g.lessons.map(function (l) {
257          return '<div class="dk-nb-les"><h4 data-lid="' + esc(l.id) + '" role="button" tabindex="0">' +
258            l.title + '</h4>' +
259            (l.actions.length ? '<ul>' + l.actions.map(function (a) { return '<li>' + esc(a) + '</li>'; }).join('') + '</ul>' : '') +
260            (l.num ? '<div class="dk-nb-num">' + esc(x('num_label')) + ' : ' + esc(l.num) + '</div>' : '') +
261            (l.note ? '<div class="dk-nb-note">' + esc(l.note) + '</div>' : '') +
262            '</div>';
263        }).join('') + '</div>';
264    }).join('');
265
266    main.innerHTML = head + stats + body + '<div style="height:60px"></div>';
267
268    var bmd = document.getElementById('dk-nb-md'), btxt = document.getElementById('dk-nb-txt');
269    if (bmd) bmd.addEventListener('click', function () { download('md'); });
270    if (btxt) btxt.addEventListener('click', function () { download('txt'); });
271    main.querySelectorAll('.dk-nb-les h4[data-lid]').forEach(function (h) {
272      function go() {
273        if (typeof DK.navigate === 'function') DK.navigate('#/lecon/' + h.dataset.lid);
274      }
275      h.addEventListener('click', go);
276      h.addEventListener('keydown', function (e) {
277        if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); go(); }
278      });
279    });
280    if (typeof DK.scrollTop === 'function') DK.scrollTop();
281  }
282
283  /* ══════════════════════════════════════════════════════════════
284     ENCART TABLEAU DE BORD (registre DK.cards, sans toucher au markup)
285     ══════════════════════════════════════════════════════════════ */
286  function cardHTML() {
287    var d = collect();
288    return '<div class="dk-nbcard"><div class="em" aria-hidden="true">📓</div><div class="i">' +
289      '<h3>' + esc(x('card_t')) + '</h3><p>' +
290      esc(d.actions || d.notes ? x('card_p', { a: d.actions, n: d.notes, l: d.lessons }) : x('card_p0')) +
291      '</p></div><button type="button" id="dk-nbcard-btn">' + esc(x('card_open')) + '</button></div>';
292  }
293
294  DK.cards = DK.cards || [];
295  DK.cards.push(cardHTML);
296
297  /* Le bouton est recree a chaque rendu du tableau de bord : on delegue depuis
298     le document plutot que de rebrancher un listener a chaque fois. */
299  document.addEventListener('click', function (e) {
300    var b = e.target && e.target.closest ? e.target.closest('#dk-nbcard-btn') : null;
301    if (b && typeof DK.navigate === 'function') DK.navigate('#/carnet');
302  });
303
304  function renderNotebookCard() {
305    if (typeof DK.renderCards === 'function') {
306      var dash = document.getElementById('dashboard');
307      if (dash && dash.classList.contains('visible')) DK.renderCards();
308    }
309  }
310
311  Object.assign(DK, {
312    notebookCollect: collect, notebookText: buildText, notebookExport: download,
313    renderNotebook: view, renderNotebookCard: renderNotebookCard, notebookCardHTML: cardHTML
314  });
315
316  /* dk-notebook.js se charge APRES dk-dashboard.js (donc apres DK.init()) :
317     registerRoute() relance le routeur si c'est justement #/carnet qui est
318     demande, et renderCards() rattrape le tableau de bord deja affiche. */
319  if (typeof DK.registerRoute === 'function') DK.registerRoute('carnet', view);
320  renderNotebookCard();
321})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.