-
Notifications
You must be signed in to change notification settings - Fork 30
/
htmxboard.lua
95 lines (87 loc) · 3.18 KB
/
htmxboard.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
-- Minimalistic trello-like example using Fullmoon web framework
-- Based on https://github.com/rajasegar/htmx-trello
-- Copyright 2022 Paul Kulchenko
local fm = require "fullmoon"
local function finder(type)
return function (tbl, id, checkonly)
for i, v in ipairs(tbl) do
if v.id == id then return v, i end
end
if checkonly then return nil end
assert(false, "can't find "..type.." for id "..id)
end
end
local function newid()
return fm.encodeBase64(fm.getRandomBytes(6)):gsub("%W",""):lower()
end
local lists = {find = finder("list")}
fm.setTemplate({"/tmpl/", fmt = "fmt", fmg = "fmg"})
fm.setRoute("/favicon.ico", fm.serveAsset)
fm.setRoute("/*", "/assets/*")
fm.setRoute(fm.GET"/", fm.serveContent("index", {lists = lists}))
fm.setRoute(fm.GET{"/list/add", routeName="list-add"},
fm.serveContent("list-add"))
fm.setRoute(fm.GET{"/list/cancel", routeName="list-cancel"},
fm.serveContent("list-new"))
fm.setRoute(fm.POST{"/board/?", routeName="board"},
function(r)
table.insert(lists, {
name = r.params.name,
id = 'l'..newid(),
cards = {find = finder("card")},
})
return fm.serveContent("board", {lists = lists})
end)
-- this is a hook/before route that loads the card value
-- and stores them in the request object
fm.setRoute("/card/:listid(/:id)(/*)", function(r)
r.list = lists:find(r.params.listid, true)
r.card = r.params.id and r.list.cards:find(r.params.id) or nil
-- need to check other routes, so return `false` to signal falling through
return false
end)
fm.setRoute(fm.PUT{"/card/:listid(/:id)", routeName="card-save"},
function(r)
local card = r.card
if not card then
card = { id = 'c'..newid(), listid = r.params.listid }
table.insert(r.list.cards, card)
end
card.label = r.params.label
return fm.serveContent("card", {card = card})
end)
fm.setRoute(fm.GET{"/card/:listid/:id/edit", routeName="card-edit"},
function(r)
return fm.serveContent("card-edit", {card = r.card})
end)
fm.setRoute(fm.GET{"/card/:listid/:id", routeName="card-get"},
function(r)
return fm.serveContent("card", {card = r.card})
end)
fm.setRoute(fm.DELETE{"/card/:listid/:id", routeName="card-delete"},
function(r)
local _, idx = r.list.cards:find(r.params.id)
table.remove(r.list.cards, idx)
return ""
end)
fm.setRoute(fm.POST{"/card/move", routeName="card-move"},
function(r)
local fromlist = lists:find(r.params.from:gsub("list%-",""))
local tolist = lists:find(r.params.to:gsub("list%-",""))
local cardid = r.params.movedCard:gsub("card%-","")
-- check if ids are the different
if fromlist.id ~= tolist.id
-- check if the card is still there
and fromlist.cards:find(cardid, true) then
local card, idx = fromlist.cards:find(cardid)
table.remove(fromlist.cards, idx)
card.listid = tolist.id
table.insert(tolist.cards, card)
end
return fm.serveContent("board", {lists = lists})
end)
-- debugging route; only available locally
fm.setRoute(fm.GET{"/state/?", clientAddr = {fm.isLoopbackIp, otherwise = 403}},
fm.serveContent("state-show", {lists = lists}))
-- run as one process; same as launching redbean with -u option
fm.run({uniprocess = true})