blob: 70965248a9e44367e0deb7238992e96e09ae4498 (
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
|
module OptionInfix = Operators.Binding (Option)
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.div
~at:Brr.At.[ class' (Jstr.v "card") ]
[
Brr.El.div
~at:Brr.At.[ class' (Jstr.v "card-header") ]
[
Brr.El.header
~at:Brr.At.[ class' (Jstr.v "card-header") ]
[
Brr.El.p
~at:Brr.At.[ class' (Jstr.v "card-header-title") ]
[ Brr.El.txt' "Response from the server" ];
];
];
Brr.El.div
~at:Brr.At.[ class' (Jstr.v "card-content") ]
[
Brr.El.form
[
Elements.input_field ~label:(Jstr.v "Word received")
~value':(Jstr.v word) ();
Elements.input_field ~label:(Jstr.v "Nb of car")
~value':(Jstr.of_int len) ();
Elements.input_field ~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
[
Elements.input_field ~name:(Jstr.v "text") ~id':(Jstr.v "text")
~label:(Jstr.v "Text") ();
Brr.El.div
~at:Brr.At.[ class' (Jstr.v "field is-horizontal") ]
[
Brr.El.div ~at:Brr.At.[ class' (Jstr.v "field-label") ] [];
Brr.El.div
~at:Brr.At.[ class' (Jstr.v "field-body") ]
[
Brr.El.input
~at:
Brr.At.
[
class' (Jstr.v "button is-primary");
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
[
Brr.El.div
~at:Brr.At.[ class' (Jstr.v "card") ]
[
Brr.El.div
~at:Brr.At.[ class' (Jstr.v "card-header") ]
[
Brr.El.header
~at:Brr.At.[ class' (Jstr.v "card-header") ]
[
Brr.El.p
~at:Brr.At.[ class' (Jstr.v "card-header-title") ]
[ Brr.El.txt' "Request to the server" ];
];
];
Brr.El.div ~at:Brr.At.[ class' (Jstr.v "card-content") ] [ 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
|