Skip to content

Commit ed21496

Browse files
committed
fix addition
1 parent 7e03cc3 commit ed21496

File tree

10 files changed

+139
-82
lines changed

10 files changed

+139
-82
lines changed

client/src/Client.re

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ type data('a, 'b) =
44
| Loading
55
| Finished(Result.t('a, 'b));
66

7+
type error = [
8+
| `DecodingError(option(string))
9+
| `NetworkError(Js.Promise.error)
10+
];
11+
712
let request = (~method_=Fetch.Get, ~input=?, url, decoder) => {
813
Js.Promise.(
914
Fetch.fetchWithInit(
@@ -43,6 +48,12 @@ let request = (~method_=Fetch.Get, ~input=?, url, decoder) => {
4348
);
4449
};
4550

51+
let errorToString: error => string =
52+
fun
53+
| `DecodingError(Some(msg)) => Printf.sprintf("Decoding error: %s", msg)
54+
| `DecodingError(None) => Printf.sprintf("Decoding error")
55+
| `NetworkError(_err) => "Network error";
56+
4657
let usePrevious = value => {
4758
let valueRef = React.useRef(value);
4859
React.useEffect(() => {

client/src/index.html

Lines changed: 0 additions & 12 deletions
This file was deleted.

server/lib/handlers.ml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ let default_head =
1010
(title (txt "OCaml Webapp Tutorial"))
1111
[
1212
meta ~a:[ a_charset "UTF-8" ] ();
13+
meta
14+
~a:
15+
[ a_name "viewport"; a_content "width=device-width, initial-scale=1" ]
16+
();
1317
link ~rel:[ `Icon ]
1418
~a:[ a_mime_type "image/x-icon" ]
1519
~href:"/static/favicon.ico" ();
@@ -107,9 +111,11 @@ module Handlers = struct
107111
json (Shared.PageExcerpts_j.string_of_payload excerpts))
108112

109113
let add_excerpt req =
114+
let open Lwt in
110115
let* str = App.string_of_body_exn req in
111116
let excerpt = Shared.Excerpt_j.t_of_string str in
112-
respond' (json (Shared.Excerpt_j.string_of_t excerpt))
117+
Db.Update.add_excerpt excerpt req
118+
>>= respond_or_err (fun () -> json (Shared.Excerpt_j.string_of_t excerpt))
113119
end
114120
end
115121

server/static/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
<html lang="en">
33
<head>
44
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1">
56
<title>OCaml webapp</title>
67
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
78
</head>

shared/Excerpt.re

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,19 @@ let createElement = (~e: Excerpt_t.t, ()) => {
44
let page =
55
switch (e.page) {
66
| None => ""
7-
| Some(p) => Printf.sprintf(", %s", p)
7+
| Some(p) => Printf.sprintf(", page %s", p)
88
};
99

1010
<div className="content">
11-
<p> {React.string(e.excerpt)} </p>
12-
<p>
13-
{React.string(Printf.sprintf("-- %s (%s%s)", e.author, e.source, page))}
14-
</p>
11+
<blockquote
12+
className="relative p-4 text-xl border-l-4 bg-neutral-100 text-neutral-600 border-neutral-500 quote">
13+
<p className="mb-2"> {React.string(e.excerpt)} </p>
14+
<cite>
15+
{React.string(
16+
Printf.sprintf("-- %s (%s%s)", e.author, e.source, page),
17+
)}
18+
</cite>
19+
</blockquote>
1520
</div>;
1621
};
1722

shared/PageAddExcerpt.re

Lines changed: 107 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,23 @@ type action =
55
| AuthorChanged(string)
66
| ExcerptChanged(string)
77
| SourceChanged(string)
8-
| PageChanged(string);
8+
| PageChanged(string)
9+
| FormSubmitted
10+
| AddExcerptRequestSucceeded(Excerpt_t.t)
11+
| AddExcerptRequestFailed(string);
12+
13+
type submissionState =
14+
| NotAsked
15+
| Loading
16+
| Success(Excerpt_t.t)
17+
| Error(string);
918

1019
type state = {
1120
author: string,
1221
excerpt: string,
1322
source: string,
1423
page: string,
24+
submissionState,
1525
};
1626

1727
let row = (left, right) =>
@@ -26,14 +36,26 @@ let reducer = (state, action) =>
2636
| ExcerptChanged(excerpt) => {...state, excerpt}
2737
| SourceChanged(source) => {...state, source}
2838
| PageChanged(page) => {...state, page}
39+
| FormSubmitted => {...state, submissionState: Loading}
40+
| AddExcerptRequestSucceeded(excerpt) => {
41+
...state,
42+
submissionState: Success(excerpt),
43+
}
44+
| AddExcerptRequestFailed(msg) => {...state, submissionState: Error(msg)}
2945
};
3046

3147
[@react.component]
3248
let make = () => {
3349
let (state, dispatch) =
3450
React.useReducer(
3551
reducer,
36-
{author: "", excerpt: "", source: "", page: ""},
52+
{
53+
author: "",
54+
excerpt: "",
55+
source: "",
56+
page: "",
57+
submissionState: NotAsked,
58+
},
3759
);
3860

3961
let txtInput = (name, value, _onChange) =>
@@ -82,54 +104,89 @@ let make = () => {
82104
);
83105

84106
<PageContainer>
85-
<>
86-
<h1 className="font-semibold text-xl tracking-tight mb-8">
87-
{React.string("Add new excerpt")}
88-
</h1>
89-
{<Form
90-
onSubmit={e => {
91-
ReactEvent.Form.preventDefault(e);
92-
Client.request(
93-
~method_=Post,
94-
~input={
95-
Excerpt_bs.write_t({
96-
author: state.author,
97-
excerpt: state.excerpt,
98-
source: state.source,
99-
page: Some(state.page),
100-
});
101-
},
102-
Routes.sprintf(Router.ApiRoutes.add_excerpt()),
103-
a =>
104-
a
105-
)
106-
|> Js.Promise.then_(res =>
107-
Js.log2("received", res)->Js.Promise.resolve
107+
{switch (state.submissionState) {
108+
| Loading =>
109+
<>
110+
<h1 className="font-semibold text-xl tracking-tight mb-8">
111+
{React.string("Add new excerpt")}
112+
</h1>
113+
<p> {React.string("Loading....")} </p>
114+
</>
115+
| Error(msg) =>
116+
<>
117+
<h1 className="font-semibold text-xl tracking-tight mb-8">
118+
{React.string("Add new excerpt")}
119+
</h1>
120+
<p> {React.string("Error: " ++ msg)} </p>
121+
</>
122+
| Success(e) =>
123+
<>
124+
<h1 className="font-semibold text-xl tracking-tight mb-8">
125+
{React.string("Excerpt added successfully")}
126+
</h1>
127+
<p> {React.string("Added the following excerpt: ")} </p>
128+
<Excerpt e />
129+
<Link url="/" txt="Back home" />
130+
</>
131+
| NotAsked =>
132+
<>
133+
<h1 className="font-semibold text-xl tracking-tight mb-8">
134+
{React.string("Add new excerpt")}
135+
</h1>
136+
{<Form
137+
onSubmit={e => {
138+
ReactEvent.Form.preventDefault(e);
139+
dispatch @@ FormSubmitted;
140+
Client.request(
141+
~method_=Post,
142+
~input={
143+
Excerpt_bs.write_t({
144+
author: state.author,
145+
excerpt: state.excerpt,
146+
source: state.source,
147+
page: Some(state.page),
148+
});
149+
},
150+
Routes.sprintf(Router.ApiRoutes.add_excerpt()),
151+
Excerpt_bs.read_t,
108152
)
109-
|> ignore;
110-
Js.log(state);
111-
}}>
112-
{List.mapi(
113-
(_i, x) =>
114-
<Div cls="md:flex md:items-center mb-6" key={string_of_int(_i)}>
115-
x
116-
</Div>,
117-
[
118-
txtInput("author", state.author, author =>
119-
dispatch @@ AuthorChanged(author)
120-
),
121-
excerptInput,
122-
txtInput("source", state.source, author =>
123-
dispatch @@ SourceChanged(author)
124-
),
125-
txtInput("page", state.page, author =>
126-
dispatch @@ PageChanged(author)
127-
),
128-
submit,
129-
],
130-
)
131-
|> React.list}
132-
</Form>}
133-
</>
153+
|> Js.Promise.then_(res =>
154+
(
155+
switch (res) {
156+
| Ok(excerpt) =>
157+
dispatch @@ AddExcerptRequestSucceeded(excerpt)
158+
| Error(err) =>
159+
dispatch @@
160+
AddExcerptRequestFailed(Client.errorToString(err))
161+
}
162+
)
163+
->Js.Promise.resolve
164+
)
165+
|> ignore;
166+
}}>
167+
{List.mapi(
168+
(_i, x) =>
169+
<Div
170+
cls="md:flex md:items-center mb-6" key={string_of_int(_i)}>
171+
x
172+
</Div>,
173+
[
174+
txtInput("author", state.author, author =>
175+
dispatch @@ AuthorChanged(author)
176+
),
177+
excerptInput,
178+
txtInput("source", state.source, author =>
179+
dispatch @@ SourceChanged(author)
180+
),
181+
txtInput("page", state.page, author =>
182+
dispatch @@ PageChanged(author)
183+
),
184+
submit,
185+
],
186+
)
187+
|> React.list}
188+
</Form>}
189+
</>
190+
}}
134191
</PageContainer>;
135192
};

shared/PageContainer.re

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ let createElement = (~children, ()) => {
44
<Dom.Div cls="flex xs:justify-center overflow-hidden">
55
<>
66
<Dom.Div
7-
cls="mt-32 mx-32 min-w-md lg:align-center w-full px-4 md:px-8 max-w-2xl">
7+
cls="mt-8 md:mt-32 mx-8 md:mx-32 min-w-md lg:align-center w-full px-4 md:px-8 max-w-2xl">
88
children
99
</Dom.Div>
1010
</>

shared/PageExcerptAdded.re

Lines changed: 0 additions & 11 deletions
This file was deleted.

shared/PageWelcome.re

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ open Bridge;
44
let make = () => {
55
<PageContainer>
66
<h1 className="font-semibold text-xl tracking-tight mb-8">
7-
{React.string("OCaml native webapp with SSR + ReasonReact hydration")}
7+
{React.string("OCaml native webapp with SSR + React hydration")}
88
</h1>
99
<h2> {React.string("Hello")} </h2>
1010
<Dom.Ul cls="list-disc list-inside mb-8">

webpack.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ module.exports = {
1414
},
1515
plugins: [
1616
new HtmlWebpackPlugin({
17-
template: "client/src/index.html",
17+
template: path.join(outputDir, "index.html"),
1818
inject: false,
1919
}),
2020
],

0 commit comments

Comments
 (0)