Skip to content

Commit

Permalink
Add HTML page :wip
Browse files Browse the repository at this point in the history
  • Loading branch information
jaguililla committed Jun 24, 2024
1 parent ea46d3b commit 791f295
Show file tree
Hide file tree
Showing 7 changed files with 134 additions and 67 deletions.
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ apply(from = "$gradleScripts/application.gradle")
dependencies {
implementation("com.hexagonkt:http_server_jetty:$hexagonVersion")
implementation("com.hexagonkt:serialization_jackson_json:$hexagonVersion")
implementation("com.hexagonkt:rest:$hexagonVersion")
implementation("com.hexagonkt.extra:store_mongodb:$hexagonExtraVersion")
implementation("com.hexagonkt.extra:converters:$hexagonExtraVersion")
implementation("ch.qos.logback:logback-classic:$logbackVersion")
Expand Down
19 changes: 3 additions & 16 deletions src/main/kotlin/Application.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import com.hexagonkt.core.*
import com.hexagonkt.http.server.HttpServer
import com.hexagonkt.http.server.HttpServerSettings
import com.hexagonkt.http.server.jetty.JettyServletAdapter
import com.hexagonkt.serialization.SerializationManager
import com.hexagonkt.serialization.jackson.json.Json
import com.hexagontk.todo.backend.domain.model.Task
import com.hexagontk.todo.backend.adapters.MongoDbTaskStore
import com.hexagontk.todo.backend.rest.Router
import com.hexagontk.todo.backend.rest.TaskCreationRequest
import com.hexagontk.todo.backend.rest.TaskRetrievalResponse
import com.hexagontk.todo.backend.rest.TaskUpdateRequest

internal class Application {
Expand All @@ -23,6 +23,7 @@ internal class Application {
)

fun start() {
SerializationManager.formats = setOf(Json)
registerConverters()
server.start()
}
Expand All @@ -45,20 +46,6 @@ internal class Application {
completed = map.getPath(Task::completed)
)
}
ConvertersManager.register(Task::class to TaskRetrievalResponse::class) { task ->
TaskRetrievalResponse(
url = task.url,
title = task.title,
order = task.order,
completed = task.completed
)
}
ConvertersManager.register(Map::class to TaskCreationRequest::class) { map ->
TaskCreationRequest(
title = map.requirePath(TaskCreationRequest::title),
order = map.getPath(TaskCreationRequest::order),
)
}
ConvertersManager.register(Map::class to TaskUpdateRequest::class) { map ->
TaskUpdateRequest(
title = map.getPath(TaskUpdateRequest::title),
Expand Down
3 changes: 2 additions & 1 deletion src/main/kotlin/domain/model/Task.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ data class Task(
val order: Int? = null,
val completed: Boolean? = false
) {
val url = "${System.getenv("SERVICE_URL")}/tasks/$id"
// val url = "${System.getenv("SERVICE_URL")}/tasks/$id"
val url = "/tasks/$id"
}
21 changes: 13 additions & 8 deletions src/main/kotlin/rest/Router.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ import com.hexagonkt.http.handlers.path
import com.hexagonkt.http.model.HttpMethod.*
import com.hexagonkt.http.server.callbacks.CorsCallback
import com.hexagonkt.http.server.callbacks.UrlCallback
import com.hexagonkt.rest.SerializeResponseCallback
import com.hexagonkt.rest.bodyObject
import com.hexagonkt.serialization.jackson.json.Json
import com.hexagonkt.serialization.parseMap
import com.hexagonkt.serialization.serialize
import com.hexagontk.todo.backend.domain.model.Task
import com.hexagontk.todo.backend.domain.TaskStore
import java.util.UUID
Expand All @@ -24,11 +25,13 @@ class Router(private val store: TaskStore) : HttpController {
private val text = ContentType(TEXT_PLAIN)

private val tasksHandler: HttpHandler = path("/tasks") {
after("*", callback = SerializeResponseCallback())

get {
val tasks = store.findAll()
val taskResponses = tasks.map { task -> task.convert(TaskRetrievalResponse::class) }
val taskResponses = tasks.map(::TaskRetrievalResponse)

ok(taskResponses.serialize(Json), contentType = json)
ok(taskResponses, contentType = json)
}

get("/{id}") {
Expand All @@ -37,8 +40,7 @@ class Router(private val store: TaskStore) : HttpController {
}

post {
val bodyString = request.bodyString()
val taskCreationRequest = bodyString.parseMap(Json).convert(TaskCreationRequest::class)
val taskCreationRequest = request.bodyObject(::TaskCreationRequest)
val task = Task(
id = UUID.randomUUID().toString(),
title = taskCreationRequest.title,
Expand Down Expand Up @@ -84,14 +86,17 @@ class Router(private val store: TaskStore) : HttpController {
)
)

get(callback = UrlCallback("classpath:static/index.html"))
// get(callback = UrlCallback("classpath:static/index.html"))
// get("/main.js", callback = UrlCallback("classpath:static/main.js"))
get(callback = UrlCallback("file:./src/main/resources/static/index.html"))
get("/main.js", callback = UrlCallback("file:./src/main/resources/static/main.js"))

use(tasksHandler)
}

private fun HttpContext.getTask(id: String, store: TaskStore): HttpContext {
val task = store.findOne(id)?.convert(TaskRetrievalResponse::class)
return if (task != null) ok(task.serialize(Json), contentType = json)
val task = store.findOne(id)?.let(::TaskRetrievalResponse)
return if (task != null) ok(task, contentType = json)
else notFound("Task with id $id not found", contentType = text)
}
}
44 changes: 42 additions & 2 deletions src/main/kotlin/rest/TaskMessages.kt
Original file line number Diff line number Diff line change
@@ -1,16 +1,56 @@
package com.hexagontk.todo.backend.rest

import com.hexagonkt.core.*
import com.hexagonkt.serialization.Data
import com.hexagontk.todo.backend.domain.model.Task

data class TaskRetrievalResponse(
val url: String,
val title: String,
val order: Int?,
val completed: Boolean?
)
) : Data<TaskRetrievalResponse> {

constructor(task: Task) : this(
url = task.url,
title = task.title,
order = task.order,
completed = task.completed
)

override val data: Map<String, *> = fieldsMapOfNotNull(
TaskRetrievalResponse::url to url,
TaskRetrievalResponse::title to title,
TaskRetrievalResponse::order to order,
TaskRetrievalResponse::completed to completed,
)

override fun copy(data: Map<String, *>): TaskRetrievalResponse =
copy(
url = data.getString(TaskRetrievalResponse::url) ?: url,
title = data.getString(TaskRetrievalResponse::title) ?: title,
order = data.getInt(TaskRetrievalResponse::order) ?: order,
completed = data.getBoolean(TaskRetrievalResponse::completed) ?: completed
)
}

data class TaskCreationRequest(
val title: String,
val order: Int?
)
) : Data<TaskCreationRequest> {

constructor(data: Map<String, *>) : this(
title = data.requireString(TaskCreationRequest::title),
order = data.getInt(TaskCreationRequest::order),
)

override val data: Map<String, *>
get() = TODO("Not yet implemented")

override fun copy(data: Map<String, *>): TaskCreationRequest {
TODO("Not yet implemented")
}
}

data class TaskUpdateRequest(
val title: String?,
Expand Down
64 changes: 24 additions & 40 deletions src/main/resources/static/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,14 @@
<link rel="stylesheet" href="https://cdn.simplecss.org/simple.min.css">
</head>

<h1>TODO</h1>
<header>
<nav>
<a href="/" class="current">Home</a>
<a href="/">ToDo Web</a>
</nav>
<h1>TODO</h1>
<p>Example task application</p>
</header>

<h2>Open</h2>
<table>
Expand All @@ -20,50 +27,27 @@ <h2>Open</h2>
<th>Order</th>
</tr>
</thead>
<tbody id="tasks">
<tr>
<td>a</td>
<td>b</td>
<td>0</td>
</tr>
</tbody>
<tbody id="tasks"></tbody>
</table>

<h2>New</h2>
<form>
<label for="title">Title</label>
<input id="title" type="text">
<label for="order">Order</label>
<input id="order" type="number">
<fieldset>
<legend>Task data</legend>
<label for="title">Title</label>
<input id="title" type="text">
<label for="order">Order</label>
<input id="order" type="number">
</fieldset>
</form>
<button onclick="add()">Add</button>

<script>
const http = new XMLHttpRequest();

function httpSend(method, url, body, callback) {
http.open(method, url);
http.setRequestHeader('Content-type', 'application/json');
http.send(JSON.stringify(body));
http.onreadystatechange = callback;
}

function httpGet(url, body, callback) {
httpSend('GET', url, body, callback);
}

function httpPost(url, body, callback) {
httpSend('POST', url, body, callback);
}

function add() {
let body = { title: 'a', order: 0 };
httpPost('/tasks', body, () => console.log(http.responseText));
}

function main() {
httpGet('/tasks', null, () => console.log(http.responseText));
}
<template id="todoRow">
<tr>
<td>a</td>
<td>b</td>
<td>0</td>
</tr>
</template>

main();
</script>
<script src="/main.js"></script>
49 changes: 49 additions & 0 deletions src/main/resources/static/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@

const http = new XMLHttpRequest();

function httpSend(method, url, body, callback) {
http.open(method, url);
http.setRequestHeader('Content-type', 'application/json');
http.send(JSON.stringify(body));
http.onload = callback;
}

function httpGet(url, body, callback) {
httpSend('GET', url, body, callback);
}

function httpPost(url, body, callback) {
httpSend('POST', url, body, callback);
}

function add() {
let body = { title: 'a', order: 0 };
httpPost('/tasks', body, () => {

console.log(http.responseText)
});
}

function main() {
const tbody = document.querySelector("tbody#tasks");
const template = document.querySelector("#todoRow");

httpGet('/tasks', null, () => {
let response = JSON.parse(http.responseText);
for (const tr of tbody.children) {
tr.remove();
}

for (const task of response) {
const clone = template.content.cloneNode(true);
let td = clone.querySelectorAll("td");
td[0].textContent = task.title;
td[1].textContent = task.order;
tbody.appendChild(clone);
}

console.log(http.responseText)
});
}

document.body.onload = main;

0 comments on commit 791f295

Please sign in to comment.