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
|
(*
* Copyright (C) 2020, 2021 Alban Gruin
*
* ucs is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ucs is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with ucs. If not, see <http://www.gnu.org/licenses/>.
*)
let escape str =
Stringext.replace_all_assoc str ["<", "<"; ">", ">"]
let common content =
{|<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>µCS</title>
<link rel="stylesheet" href="/css/style.css">
</head>
<body>
<header>
<h1><a href="/">µCS</a></h1>
</header>
<article>|} ^ content ^
{| </article>
<footer>
<p>(c) 2021 – Alban Gruin – µCS |} ^ escape (Version.version ()) ^ {| « GEMINI II »</p>
</footer>
</body>
</html>
|}
let main = common {|
<section>
<h3>Récupérer un emploi du temps au format ICS</h3>
<form action="/lnk" method="get">
<label for="id_group">Nom du groupe</label>
<input type="text" name="group" id="id_group" required />
<input type="submit" value="Générer un ICS" />
</form>
<form action="/filter" method="get">
<label for="id_module">ID du module</label>
<input type="text" name="module" id="id_module" required />
<input type="submit" value="Filtrer par groupes" />
</form>
</section>
<section>
<p>
Le format ICS (ou iCalendar) permet d’importer un calendrier
dans un agenda électronique.<br />
<a href="https://fr.wikipedia.org/wiki/ICalendar">En savoir plus</a>
<p>
Il existe plusieurs logiciels ou services permettant
d’utiliser ces fichiers :
<ul>
<li>sur Linux et Windows, l’extension Lightning du logiciel
Thunderbird ;</li>
<li>sur Mac et iOS, iCloud ;</li>
<li>sur Android, l’application libre ICSx<sup>5</sup> peut les
récupérer périodiquement et les afficher sur l’application
Agenda de base.
<a href="https://f-droid.org/fr/packages/at.bitfire.icsdroid/">Elle
est gratuite sur F-Droid</a> ;</li>
<li>sur Web, NextCloud.</li>
</ul>
<p>
<b>N’utilisez pas Google Calendar pour synchroniser un
calendrier ICS</b>. Ce service empêche de définir la
fréquence de synchronisation ou de forcer une mise à jour et
conserve les événements en cache, même si on supprime le
calendrier. À cause de cela, il peut y avoir un délai de un
jour entre le changement d’une information sur micro celcatsanitizer
et sa prise en compte, sans aucun recours possible.
<!-- Le lecteur attentif pourra se demander si il n’y a pas de
conflit d’intérêt entre l’écosystème Android, dans lequel
l’application de base (Agenda) ne peut se synchroniser qu’à Google
Calendar à moins d’installer une application tierce (telles que
DAVDroid ou ICSDroid, malheureusement payantes sur le Play Store mais
gratuites sur F-Droid).
Il pourra aussi se questionner sur la raison du mauvais support des
ICS par ce service - serait-ce une technique pour inciter les
utilisateurs à se servir de Google Calendar en priorité, au détriment
des formats standards et des autres écosystèmes (par exemple, celui
d’Apple), et ainsi attirer plus d’utilisateurs ? -->
</section>
|}
let link lnk =
let lnk = escape lnk in
common @@ {|
<section>
<h3>Lien de l'emploi du temps</h3>
<a href="|} ^ lnk ^ {|">|} ^ lnk ^ {|</a>
</section>
|}
let select module_id groups =
let options =
Seq.map (fun group -> " <option>" ^ escape group ^ "</option>") groups
|> List.of_seq in
let num = string_of_int (List.length options) in
let options = String.concat "\n" options in
common @@ {|
<h3>Filtrer par groupe</h3>
<p>
Sélectionnez les groupes que vous souhaitez voir dans votre emploi
du temps. N'en sélectionnez aucun si vous les voulez tous.
</p>
<form method="post" action="/lnk">
<label for="groups">Liste des groupes</label>
<select id="groups" name="groups" multiple="multiple" size="|} ^ num ^ {|">
|} ^ options ^ {|
</select>
<input type="hidden" name="module" value="|} ^ escape module_id ^ {|" />
<input type="reset" value="Effacer la sélection" />
<input type="submit" value="Générer un ICS" />
</form>
|}
|