|
// retoor <retoor@molodetz.nl>
|
|
|
|
import "web" for Application, Response, View
|
|
import "wdantic" for Schema, Field
|
|
import "dataset" for Dataset
|
|
import "uuid" for Uuid
|
|
import "json" for Json
|
|
|
|
var db = Dataset.memory()
|
|
var messages = db["messages"]
|
|
|
|
var messageSchema = Schema.new({
|
|
"username": Field.string({"minLength": 1, "maxLength": 50}),
|
|
"content": Field.string({"minLength": 1, "maxLength": 500})
|
|
})
|
|
|
|
class MessagesView is View {
|
|
get(request) {
|
|
var allMessages = messages.all()
|
|
return Response.json(allMessages)
|
|
}
|
|
|
|
post(request) {
|
|
var data = request.json
|
|
var result = messageSchema.validate(data)
|
|
if (!result.isValid) {
|
|
var r = Response.json({"error": "Validation failed", "details": result.errors.map { |e| e.toString }.toList})
|
|
r.status = 400
|
|
return r
|
|
}
|
|
var msg = messages.insert({
|
|
"username": data["username"],
|
|
"content": data["content"]
|
|
})
|
|
return Response.json(msg)
|
|
}
|
|
}
|
|
|
|
class MessageView is View {
|
|
get(request) {
|
|
var id = request.params["id"]
|
|
var msg = messages.findOne({"uid": id})
|
|
if (msg == null) {
|
|
var r = Response.json({"error": "Message not found"})
|
|
r.status = 404
|
|
return r
|
|
}
|
|
return Response.json(msg)
|
|
}
|
|
|
|
delete(request) {
|
|
var id = request.params["id"]
|
|
var deleted = messages.delete(id)
|
|
if (!deleted) {
|
|
var r = Response.json({"error": "Message not found"})
|
|
r.status = 404
|
|
return r
|
|
}
|
|
return Response.json({"status": "deleted"})
|
|
}
|
|
}
|
|
|
|
var indexHtml = "<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>Chat Demo</title>
|
|
<style>
|
|
body { font-family: sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }
|
|
#messages { border: 1px solid #ccc; padding: 10px; height: 300px; overflow-y: auto; margin-bottom: 10px; }
|
|
.message { margin: 5px 0; padding: 5px; background: #f5f5f5; }
|
|
.message .username { font-weight: bold; }
|
|
form { display: flex; gap: 10px; }
|
|
input, button { padding: 8px; }
|
|
input[name=content] { flex: 1; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<h1>Chat Demo</h1>
|
|
<div id=\"messages\"></div>
|
|
<form id=\"form\">
|
|
<input name=\"username\" placeholder=\"Username\" required>
|
|
<input name=\"content\" placeholder=\"Message\" required>
|
|
<button type=\"submit\">Send</button>
|
|
</form>
|
|
<script>
|
|
async function loadMessages() {
|
|
const res = await fetch('/api/messages');
|
|
const msgs = await res.json();
|
|
const div = document.getElementById('messages');
|
|
div.innerHTML = msgs.map(m =>
|
|
'<div class=\"message\"><span class=\"username\">' + m.username + ':</span> ' + m.content + '</div>'
|
|
).join('');
|
|
div.scrollTop = div.scrollHeight;
|
|
}
|
|
document.getElementById('form').onsubmit = async (e) => {
|
|
e.preventDefault();
|
|
const form = e.target;
|
|
await fetch('/api/messages', {
|
|
method: 'POST',
|
|
headers: {'Content-Type': 'application/json'},
|
|
body: JSON.stringify({
|
|
username: form.username.value,
|
|
content: form.content.value
|
|
})
|
|
});
|
|
form.content.value = '';
|
|
loadMessages();
|
|
};
|
|
loadMessages();
|
|
setInterval(loadMessages, 3000);
|
|
</script>
|
|
</body>
|
|
</html>"
|
|
|
|
var app = Application.new()
|
|
|
|
app.get("/", Fn.new { |req| Response.html(indexHtml) })
|
|
app.addView("/api/messages", MessagesView)
|
|
app.addView("/api/messages/:id", MessageView)
|
|
|
|
System.print("Chat demo running on http://localhost:8080")
|
|
app.run("0.0.0.0", 8080)
|