[OCaml] High Intensity Training Online
refactor share workout save handler tail
Keep current and saved workout validation redirects and save feedback in one controller helper while preserving their distinct guards.
Changed files
lib/web/handlers_current_workout.ml
@@ -43,13 +43,11 @@
43
43
44
44
let show t trainee request = render_workout t trainee request
45
45
46
Removed:
(* The response after a successful record or correction: a POST-redirect-GET
47
Removed:
that flashes [message] and reloads the workout. Record and correction
48
Removed:
submits navigate natively with a full page. The full page guarantees that
49
Removed:
the reloaded view reflects exactly what the app saved, with no client swap
50
Removed:
that could race. *)
51
Removed:
let saved _t _trainee request message =
52
Removed:
redirect_with_flash_to request Routes.workout message
46
Added:
(* Every record and correction submit ends with a POST-redirect-GET back to
47
Added:
the workout: the reload navigates natively with a full page, so the view
48
Added:
reflects exactly what the app saved, with no client swap that could race.
49
Added:
[decode_and_save] flashes and redirects here on every outcome. *)
50
Added:
let workout_dest = Dream_html.path_attr Dream_html.HTML.href Routes.workout
53
51
54
52
let log t trainee request slot =
55
53
Service.in_progress t.service trainee.Trainee.id >>= function
@@ -57,19 +55,9 @@
57
55
| Some workout -> (
58
56
match outstanding workout slot with
59
57
| None -> not_found Present.slot_not_awaiting
60
Removed:
| Some prescription -> (
61
Removed:
decode_form (Decode.stimulus prescription) request >>= function
62
Removed:
| Error (`Invalid errors) ->
63
Removed:
redirect_with_flash_to request Routes.workout
64
Removed:
(Decode.errors_to_text errors)
65
Removed:
| Error `Bad_request ->
66
Removed:
redirect_with_flash_to request Routes.workout
67
Removed:
Present.form_invalid
68
Removed:
| Ok stimulus -> (
69
Removed:
save_current t trainee.Trainee.id stimulus >>= function
70
Removed:
| Ok () -> saved t trainee request "Record saved."
71
Removed:
| Error detail ->
72
Removed:
redirect_with_flash_to request Routes.workout detail)))
58
Added:
| Some prescription ->
59
Added:
decode_and_save request ~dest:workout_dest ~prescription
60
Added:
~save:(save_current t trainee.Trainee.id))
73
61
74
62
(* Correct a recorded slot of the workout in progress. The slot may be
75
63
filled, so its prescription comes from the workout, not [outstanding].
@@ -80,19 +68,9 @@
80
68
| Some workout -> (
81
69
match prescription_at workout slot with
82
70
| None -> not_found Present.slot_not_awaiting
83
Removed:
| Some prescription -> (
84
Removed:
decode_form (Decode.stimulus prescription) request >>= function
85
Removed:
| Error (`Invalid errors) ->
86
Removed:
redirect_with_flash_to request Routes.workout
87
Removed:
(Decode.errors_to_text errors)
88
Removed:
| Error `Bad_request ->
89
Removed:
redirect_with_flash_to request Routes.workout
90
Removed:
Present.form_invalid
91
Removed:
| Ok stimulus -> (
92
Removed:
replace_current t trainee.Trainee.id ~slot stimulus >>= function
93
Removed:
| Ok () -> saved t trainee request "Record saved."
94
Removed:
| Error detail ->
95
Removed:
redirect_with_flash_to request Routes.workout detail)))
71
Added:
| Some prescription ->
72
Added:
decode_and_save request ~dest:workout_dest ~prescription
73
Added:
~save:(replace_current t trainee.Trainee.id ~slot))
96
74
97
75
let finish t trainee request =
98
76
guard_csrf request >>= function
lib/web/handlers_kit.ml
@@ -471,4 +471,21 @@
471
471
Service.replace_in_record t.service trainee id ~slot stimulus >|= function
472
472
| Ok _ -> Ok ()
473
473
| Error e -> Error (Present.edit_error e)
474
Added:
475
Added:
(* Decode a stimulus against [prescription], then persist it with [save].
476
Added:
Every outcome flashes and redirects to [dest]: the two decode failures name
477
Added:
the fault, a save failure carries the service's own wording, and a success
478
Added:
confirms the save. [dest] is a dream-html [href], so a caller passes a
479
Added:
route path or a captured record path. The current-workout and logbook slot
480
Added:
handlers share this tail and differ only in [dest] and [save]. *)
481
Added:
let decode_and_save request ~dest ~prescription ~save =
482
Added:
decode_form (Decode.stimulus prescription) request >>= function
483
Added:
| Error (`Invalid errors) ->
484
Added:
redirect_with_flash request dest (Decode.errors_to_text errors)
485
Added:
| Error `Bad_request ->
486
Added:
redirect_with_flash request dest Present.form_invalid
487
Added:
| Ok stimulus -> (
488
Added:
save stimulus >>= function
489
Added:
| Ok () -> redirect_with_flash request dest "Record saved."
490
Added:
| Error detail -> redirect_with_flash request dest detail)
474
491
end
lib/web/handlers_logbook.ml
@@ -342,28 +342,11 @@
342
342
| Some (record_id, workout) -> (
343
343
match outstanding workout slot with
344
344
| None -> not_found Present.slot_not_awaiting
345
Removed:
| Some prescription -> (
346
Removed:
decode_form (Decode.stimulus prescription) request >>= function
347
Removed:
| Error (`Invalid errors) ->
348
Removed:
redirect_with_flash request
349
Removed:
(Dream_html.path_attr Dream_html.HTML.href Routes.record id)
350
Removed:
(Decode.errors_to_text errors)
351
Removed:
| Error `Bad_request ->
352
Removed:
redirect_with_flash request
353
Removed:
(Dream_html.path_attr Dream_html.HTML.href Routes.record id)
354
Removed:
Present.form_invalid
355
Removed:
| Ok stimulus -> (
356
Removed:
save_record t trainee.Trainee.id record_id stimulus >>= function
357
Removed:
| Ok () ->
358
Removed:
redirect_with_flash request
359
Removed:
(Dream_html.path_attr Dream_html.HTML.href Routes.record
360
Removed:
id)
361
Removed:
"Record saved."
362
Removed:
| Error detail ->
363
Removed:
redirect_with_flash request
364
Removed:
(Dream_html.path_attr Dream_html.HTML.href Routes.record
365
Removed:
id)
366
Removed:
detail)))
345
Added:
| Some prescription ->
346
Added:
decode_and_save request
347
Added:
~dest:(Dream_html.path_attr Dream_html.HTML.href Routes.record id)
348
Added:
~prescription
349
Added:
~save:(save_record t trainee.Trainee.id record_id))
367
350
368
351
(* Correct a recorded slot of a saved workout. [replace_record] targets the
369
352
slot, replacing its record rather than appending volume. *)
@@ -373,29 +356,11 @@
373
356
| Some (record_id, workout) -> (
374
357
match prescription_at workout slot with
375
358
| None -> not_found Present.slot_not_awaiting
376
Removed:
| Some prescription -> (
377
Removed:
decode_form (Decode.stimulus prescription) request >>= function
378
Removed:
| Error (`Invalid errors) ->
379
Removed:
redirect_with_flash request
380
Removed:
(Dream_html.path_attr Dream_html.HTML.href Routes.record id)
381
Removed:
(Decode.errors_to_text errors)
382
Removed:
| Error `Bad_request ->
383
Removed:
redirect_with_flash request
384
Removed:
(Dream_html.path_attr Dream_html.HTML.href Routes.record id)
385
Removed:
Present.form_invalid
386
Removed:
| Ok stimulus -> (
387
Removed:
replace_record t trainee.Trainee.id record_id ~slot stimulus
388
Removed:
>>= function
389
Removed:
| Ok () ->
390
Removed:
redirect_with_flash request
391
Removed:
(Dream_html.path_attr Dream_html.HTML.href Routes.record
392
Removed:
id)
393
Removed:
"Record saved."
394
Removed:
| Error detail ->
395
Removed:
redirect_with_flash request
396
Removed:
(Dream_html.path_attr Dream_html.HTML.href Routes.record
397
Removed:
id)
398
Removed:
detail)))
359
Added:
| Some prescription ->
360
Added:
decode_and_save request
361
Added:
~dest:(Dream_html.path_attr Dream_html.HTML.href Routes.record id)
362
Added:
~prescription
363
Added:
~save:(replace_record t trainee.Trainee.id record_id ~slot))
399
364
400
365
let delete t trainee request id =
401
366
guard_csrf request >>= function