aboutsummaryrefslogtreecommitdiff
path: root/js/content.ml
blob: f41bc46432d64b373b61124fc0483feff5537ca1 (plain)
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
module OptionInfix = Operators.Binding (Option)

let add_field :
    label:Jstr.t ->
    id':Jstr.t ->
    value':Jstr.t ->
    Brr.El.t list ->
    Brr.El.t list =
 fun ~label ~id' ~value' elt ->
  Brr.El.label ~at:Brr.At.[ for' id' ] [ Brr.El.txt label ]
  :: Brr.El.input ~at:Brr.At.[ type' (Jstr.v "text"); id id'; value value' ] ()
  :: elt

module State = struct
  type t = { word : string; len : int; counter : int }

  let repr_html : t -> Brr.El.t list =
   fun { word; len; counter } ->
    [
      Brr.El.form
      @@ add_field ~id':(Jstr.v "text_state") ~label:(Jstr.v "Word received")
           ~value':(Jstr.v word)
      @@ add_field ~id':(Jstr.v "nbcar_state") ~label:(Jstr.v "Nb of car")
           ~value':(Jstr.of_int len)
      @@ add_field ~id':(Jstr.v "counter_state") ~label:(Jstr.v "Request sent")
           ~value':(Jstr.of_int counter) [];
    ]
end

(** Service transforming the response from the request into the state *)
module WordCount = struct
  type t = Services_impl.Nb_car.response

  let process response state =
    Brr.Console.log
      [
        Jstr.v response.Services_impl.Nb_car.value;
        Int64.to_int response.Services_impl.Nb_car.nbcar;
      ];
    State.
      {
        counter = state.counter + 1;
        word = response.Services_impl.Nb_car.value;
        len = Int64.to_int response.Services_impl.Nb_car.nbcar;
      }
end

module App = Application.Make (State)

let main () =
  let open OptionInfix in
  let- content_div =
    Brr.Document.find_el_by_id Brr.G.document (Jstr.v "content")
  in

  let form =
    Brr.El.form
      [
        Brr.El.label
          ~at:Brr.At.[ for' (Jstr.v "text") ]
          [ Brr.El.txt (Jstr.v "Text") ];
        Brr.El.input
          ~at:
            Brr.At.
              [
                type' (Jstr.v "text"); id (Jstr.v "text"); name (Jstr.v "text");
              ]
          ();
        Brr.El.input
          ~at:Brr.At.[ type' (Jstr.v "submit"); value (Jstr.v "Count") ]
          ();
      ]
  in

  (* Listen the submit event on the form. This is an example of event of event :

     First we listen for the click event, and then for the request response
     event. *)
  let post_event : Brr.El.t -> App.event Note.event =
   fun form ->
    Note.E.join
    @@ Note_brr.Evr.on_el Brr_io.Form.Ev.submit
         (fun ev ->
           (* Do not send the query, we use it with javascript *)
           Brr.Ev.prevent_default ev;

           (* Extract the data from the form *)
           let data = Brr_io.Form.(Data.of_form (of_el form)) in
           let text_value = Brr_io.Form.Data.find data (Jstr.v "text") in
           let value =
             match text_value with
             | Some (`String s) -> Jstr.to_string s
             | _ -> ""
           in

           (* Send the request *)
           Js_handler.send (module Services_impl.Nb_car) () { value }
           |> Note_brr.Futr.to_event
           |> Note.E.map (function
                | Error _ -> App.dispatch (module App.ID) ()
                | Ok response -> App.dispatch (module WordCount) response))
         form
  in
  let bottom = Brr.El.div [] in
  Brr.El.append_children content_div [ form; Brr.El.hr (); bottom ];

  let state =
    App.run
      { word = ""; len = 0; counter = 0 }
      (Note.E.select [ post_event form ])
  in

  Note_brr.Elr.def_children bottom (Note.S.map State.repr_html state);

  let log state = ignore state in
  Note.Logr.hold (Note.S.log state log)

let () =
  Brr.Console.(debug [ Jstr.v "Js started" ]);
  let open Jv in
  let post = obj [| ("start", repr main) |] in
  set global "client" post