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.

Commit
6752cf932a976f4d3a1bd00176ae940a3174542f
Author
Marius Peter <dev@marius-peter.com>
Author date
Committer
Marius Peter <dev@marius-peter.com>
Committer date
Changed files
lib/web/handlers_current_workout.ml
index 96b3321d..5e9b985e 100644..100644
@@ -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
index b141e011..f8282483 100644..100644
@@ -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
index 36db8afa..0164d3cf 100644..100644
@@ -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