106 lines
2.8 KiB
Gleam
106 lines
2.8 KiB
Gleam
import argv
|
|
import gleam/dynamic/decode
|
|
import gleam/erlang/process
|
|
import gleam/http.{Get, Post}
|
|
import gleam/int
|
|
import gleam/json
|
|
import lustre/attribute
|
|
import lustre/element
|
|
import lustre/element/html
|
|
import mist
|
|
import shared
|
|
import shared/geofeed
|
|
import simplifile
|
|
import wisp.{type Request, type Response}
|
|
import wisp/wisp_mist
|
|
|
|
pub fn main() {
|
|
wisp.configure_logger()
|
|
let secret_key_base = wisp.random_string(64)
|
|
let assert Ok(priv_directory) = wisp.priv_directory("server")
|
|
let static_directory = priv_directory <> "/static"
|
|
let assert [port_str, geofeed_path, ..] = argv.load().arguments
|
|
let assert Ok(port) = int.parse(port_str)
|
|
let assert Ok(_) =
|
|
handle_request(static_directory, geofeed_path, _)
|
|
|> wisp_mist.handler(secret_key_base)
|
|
|> mist.new
|
|
|> mist.port(port)
|
|
|> mist.start
|
|
process.sleep_forever()
|
|
}
|
|
|
|
fn app_middleware(
|
|
req: Request,
|
|
static_directory: String,
|
|
next: fn(Request) -> Response,
|
|
) -> Response {
|
|
let req = wisp.method_override(req)
|
|
use <- wisp.log_request(req)
|
|
use <- wisp.rescue_crashes
|
|
use req <- wisp.handle_head(req)
|
|
use <- wisp.serve_static(req, under: "/static", from: static_directory)
|
|
next(req)
|
|
}
|
|
|
|
fn handle_request(
|
|
static_directory: String,
|
|
geofeed_path: String,
|
|
req: Request,
|
|
) -> Response {
|
|
use req <- app_middleware(req, static_directory)
|
|
case req.method, wisp.path_segments(req) {
|
|
Post, ["api", "geofeed"] -> handle_save_geofeed(req, geofeed_path)
|
|
Get, _ -> serve_index(geofeed_path)
|
|
_, _ -> wisp.not_found()
|
|
}
|
|
}
|
|
|
|
fn serve_index(geofeed_path: String) -> Response {
|
|
html.html(
|
|
[
|
|
attribute.styles([
|
|
#("color-scheme", "dark light"),
|
|
shared.font_family_style,
|
|
]),
|
|
],
|
|
[
|
|
html.head([], [
|
|
html.title([], "Pinpoint - Geofeed Editor"),
|
|
html.script(
|
|
[attribute.type_("module"), attribute.src("/static/client.mjs")],
|
|
"",
|
|
),
|
|
]),
|
|
html.script(
|
|
[
|
|
attribute.type_("application/json"),
|
|
attribute.id(shared.model_element_id),
|
|
],
|
|
json.to_string(
|
|
geofeed.encode(case simplifile.read(geofeed_path) {
|
|
Ok(csv) -> geofeed.from_csv(csv)
|
|
Error(_) -> []
|
|
}),
|
|
),
|
|
),
|
|
html.body([attribute.styles([#("margin", "0"), #("padding", "0")])], [
|
|
html.div([attribute.id(shared.app_element_id)], []),
|
|
]),
|
|
],
|
|
)
|
|
|> element.to_document_string_tree
|
|
|> wisp.html_response(200)
|
|
}
|
|
|
|
fn handle_save_geofeed(req: Request, geofeed_path: String) -> Response {
|
|
use json <- wisp.require_json(req)
|
|
case decode.run(json, geofeed.decoder()) {
|
|
Ok(geofeed) ->
|
|
case simplifile.write(geofeed_path, geofeed.to_csv(geofeed)) {
|
|
Ok(_) -> wisp.ok()
|
|
Error(_) -> wisp.internal_server_error()
|
|
}
|
|
Error(_) -> wisp.bad_request()
|
|
}
|
|
}
|