[OCaml] High Intensity Training Online
feat Add deployment footer
Show Marius Peter copyright with the current UTC year and the deployment version on every page. Use a development fallback outside deployed environments.
bin/main.ml
@@ -10,6 +10,8 @@
10
10
unset, a random secret is generated for this run only, so
11
11
sessions do not survive a restart. Set it in production.
12
12
- HITO_PORT TCP port. Default: 8080
13
Added:
- HITO_VERSION Deployment commit identifier shown in the page footer. Defaults
14
Added:
to "development" outside a deployment.
13
15
- HITO_SEED_PASSWORD Password for the seeded [blendux] account. Required.
14
16
The server refuses to start when unset. Temporary, until
15
17
public registration returns.
lib/presenter/page_shell.ml
@@ -6,6 +6,25 @@
6
6
omit both. *)
7
7
let theme_session_key = "hito.theme"
8
8
9
Added:
let deployment_version () =
10
Added:
match Sys.getenv_opt "HITO_VERSION" with
11
Added:
| Some version when version <> "" -> version
12
Added:
| _ -> "development"
13
Added:
14
Added:
let copyright_year () =
15
Added:
let now = Unix.gmtime (Unix.gettimeofday ()) in
16
Added:
now.Unix.tm_year + 1900
17
Added:
18
Added:
let footer () =
19
Added:
tag "footer"
20
Added:
[ class_ "site-footer" ]
21
Added:
[
22
Added:
txt "© %d Marius Peter · version " (copyright_year ());
23
Added:
tag "code"
24
Added:
[ class_ "deployment-version" ]
25
Added:
[ txt "%s" (deployment_version ()) ];
26
Added:
]
27
Added:
9
28
let html_page ?viewer ?request ?(active = "") ?(logging = false)
10
29
?(show_nav = false) title content =
11
30
let spa_client = true in
@@ -218,6 +237,7 @@
218
237
[ Dream_html.attr "data-hito-app-content" ]
219
238
else [])
220
239
content;
240
Added:
footer ();
221
241
];
222
242
]
223
243
@ bottom_nav);
lib/web/assets/hito.css
@@ -93,6 +93,20 @@
93
93
.masthead {
94
94
display: flex;
95
95
align-items: center;
96
Added:
97
Added:
.site-footer {
98
Added:
margin: 2rem 0 0;
99
Added:
padding: 1rem 0 0;
100
Added:
border-top: 1px solid var(--rule);
101
Added:
color: var(--muted-ink);
102
Added:
font-size: var(--font-size-small);
103
Added:
text-align: center;
104
Added:
}
105
Added:
106
Added:
.deployment-version {
107
Added:
color: inherit;
108
Added:
font: inherit;
109
Added:
}
96
110
gap: 1rem;
97
111
min-height: 4.75rem;
98
112
}
test/test_web.ml
@@ -265,6 +265,31 @@
265
265
fun () ->
266
266
let c = client () in
267
267
Alcotest.(check int) "GET /login" 200 (status (get c "/login")) );
268
Added:
( "every page carries the copyright and deployment version banner",
269
Added:
`Quick,
270
Added:
fun () ->
271
Added:
let c = client () in
272
Added:
let rendered = body (get c "/login") in
273
Added:
let version =
274
Added:
match Sys.getenv_opt "HITO_VERSION" with
275
Added:
| Some value when value <> "" -> value
276
Added:
| _ -> "development"
277
Added:
in
278
Added:
let now = Unix.gmtime (Unix.gettimeofday ()) in
279
Added:
let copyright =
280
Added:
Printf.sprintf "© %d Marius Peter" (now.Unix.tm_year + 1900)
281
Added:
in
282
Added:
Alcotest.(check bool)
283
Added:
"copyright notice" true
284
Added:
(Option.is_some (index_from ~needle:copyright rendered 0));
285
Added:
Alcotest.(check bool)
286
Added:
"deployment version markup" true
287
Added:
(Option.is_some
288
Added:
(index_from ~needle:"deployment-version" rendered 0));
289
Added:
Alcotest.(check bool)
290
Added:
"deployment version value" true
291
Added:
(Option.is_some
292
Added:
(index_from ~needle:(">" ^ version ^ "</code>") rendered 0)) );
268
293
( "registration creates the account, signs in, and reaches the overview",
269
294
`Quick,
270
295
fun () ->