Skip to content

Commit ea46d3b

Browse files
committed
Add HTML page :wip
1 parent e2830e2 commit ea46d3b

File tree

3 files changed

+93
-44
lines changed

3 files changed

+93
-44
lines changed

src/main/kotlin/rest/Cors.kt

-19
This file was deleted.

src/main/kotlin/rest/Router.kt

+36-25
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,33 @@ package com.hexagontk.todo.backend.rest
22

33
import com.hexagonkt.converters.convert
44
import com.hexagonkt.core.media.APPLICATION_JSON
5+
import com.hexagonkt.core.media.TEXT_PLAIN
56
import com.hexagonkt.http.model.ContentType
67
import com.hexagonkt.http.handlers.HttpContext
8+
import com.hexagonkt.http.handlers.HttpController
9+
import com.hexagonkt.http.handlers.HttpHandler
710
import com.hexagonkt.http.handlers.path
11+
import com.hexagonkt.http.model.HttpMethod.*
12+
import com.hexagonkt.http.server.callbacks.CorsCallback
13+
import com.hexagonkt.http.server.callbacks.UrlCallback
814
import com.hexagonkt.serialization.jackson.json.Json
915
import com.hexagonkt.serialization.parseMap
1016
import com.hexagonkt.serialization.serialize
1117
import com.hexagontk.todo.backend.domain.model.Task
1218
import com.hexagontk.todo.backend.domain.TaskStore
1319
import java.util.UUID
1420

15-
class Router(private val store: TaskStore) {
16-
private val tasksHandler = path("/tasks") {
21+
class Router(private val store: TaskStore) : HttpController {
22+
23+
private val json = ContentType(APPLICATION_JSON)
24+
private val text = ContentType(TEXT_PLAIN)
25+
26+
private val tasksHandler: HttpHandler = path("/tasks") {
1727
get {
18-
val taskResponse =
19-
store.findAll().map { task -> task.convert(TaskRetrievalResponse::class) }
20-
ok(taskResponse)
28+
val tasks = store.findAll()
29+
val taskResponses = tasks.map { task -> task.convert(TaskRetrievalResponse::class) }
30+
31+
ok(taskResponses.serialize(Json), contentType = json)
2132
}
2233

2334
get("/{id}") {
@@ -26,8 +37,8 @@ class Router(private val store: TaskStore) {
2637
}
2738

2839
post {
29-
val taskCreationRequest =
30-
request.bodyString().parseMap(Json).convert(TaskCreationRequest::class)
40+
val bodyString = request.bodyString()
41+
val taskCreationRequest = bodyString.parseMap(Json).convert(TaskCreationRequest::class)
3142
val task = Task(
3243
id = UUID.randomUUID().toString(),
3344
title = taskCreationRequest.title,
@@ -39,16 +50,16 @@ class Router(private val store: TaskStore) {
3950

4051
patch("/{id}") {
4152
val id = pathParameters.getValue("id")
42-
val taskUpdateRequest =
43-
request.bodyString().parseMap(Json).convert(TaskUpdateRequest::class)
53+
val bodyString = request.bodyString()
54+
val taskUpdateRequest = bodyString.parseMap(Json).convert(TaskUpdateRequest::class)
4455
store.findOne(id) ?: notFound("Task with id $id not found")
4556
val updates = mapOf(
4657
Task::title.name to taskUpdateRequest.title,
4758
Task::order.name to taskUpdateRequest.order,
4859
Task::completed.name to taskUpdateRequest.completed
4960
)
5061
if (store.updateOne(id, updates)) getTask(id, store)
51-
else badRequest("Unable to update task with id $id")
62+
else badRequest("Unable to update task with id $id", contentType = text)
5263
}
5364

5465
delete {
@@ -60,27 +71,27 @@ class Router(private val store: TaskStore) {
6071
val id = pathParameters.getValue("id")
6172
store.findOne(id) ?: notFound("Task with id $id not found")
6273
if (store.deleteOne(id)) ok()
63-
else badRequest("Unable to delete task with id $id")
74+
else badRequest("Unable to delete task with id $id", contentType = text)
6475
}
6576
}
6677

67-
val handler = path {
68-
cors()
69-
after("*") {
70-
send(
71-
body = response.body.serialize(Json),
72-
contentType = ContentType(APPLICATION_JSON)
78+
override val handler: HttpHandler = path {
79+
filter(
80+
"*",
81+
CorsCallback(
82+
allowedMethods = setOf(GET, POST, PATCH, DELETE, OPTIONS),
83+
allowedHeaders = setOf("Content-Type")
7384
)
74-
}
85+
)
86+
87+
get(callback = UrlCallback("classpath:static/index.html"))
88+
7589
use(tasksHandler)
7690
}
77-
}
7891

79-
internal fun HttpContext.getTask(id: String, store: TaskStore): HttpContext {
80-
val task = store.findOne(id)?.convert(TaskRetrievalResponse::class)
81-
return if (task != null) {
82-
ok(task)
83-
} else {
84-
notFound("Task with id $id not found")
92+
private fun HttpContext.getTask(id: String, store: TaskStore): HttpContext {
93+
val task = store.findOne(id)?.convert(TaskRetrievalResponse::class)
94+
return if (task != null) ok(task.serialize(Json), contentType = json)
95+
else notFound("Task with id $id not found", contentType = text)
8596
}
8697
}

src/main/resources/static/index.html

+57
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,60 @@
1010
</head>
1111

1212
<h1>TODO</h1>
13+
14+
<h2>Open</h2>
15+
<table>
16+
<thead>
17+
<tr>
18+
<th>Id</th>
19+
<th>Title</th>
20+
<th>Order</th>
21+
</tr>
22+
</thead>
23+
<tbody id="tasks">
24+
<tr>
25+
<td>a</td>
26+
<td>b</td>
27+
<td>0</td>
28+
</tr>
29+
</tbody>
30+
</table>
31+
32+
<h2>New</h2>
33+
<form>
34+
<label for="title">Title</label>
35+
<input id="title" type="text">
36+
<label for="order">Order</label>
37+
<input id="order" type="number">
38+
</form>
39+
<button onclick="add()">Add</button>
40+
41+
<script>
42+
const http = new XMLHttpRequest();
43+
44+
function httpSend(method, url, body, callback) {
45+
http.open(method, url);
46+
http.setRequestHeader('Content-type', 'application/json');
47+
http.send(JSON.stringify(body));
48+
http.onreadystatechange = callback;
49+
}
50+
51+
function httpGet(url, body, callback) {
52+
httpSend('GET', url, body, callback);
53+
}
54+
55+
function httpPost(url, body, callback) {
56+
httpSend('POST', url, body, callback);
57+
}
58+
59+
function add() {
60+
let body = { title: 'a', order: 0 };
61+
httpPost('/tasks', body, () => console.log(http.responseText));
62+
}
63+
64+
function main() {
65+
httpGet('/tasks', null, () => console.log(http.responseText));
66+
}
67+
68+
main();
69+
</script>

0 commit comments

Comments
 (0)