2023-08-04 16:40:07 (UTC-03:00)
Marcel Rodrigues <marcelgmr@gmail.com>
add some ticket operations
diff --git a/data.lua b/data.lua index ed6fac9..d562eca 100644 --- a/data.lua +++ b/data.lua @@ -191,21 +191,31 @@ function Model:get_next_code(proj_id) return last_code + 1 end -function Model:create_ticket(user_id, proj_id, title, desc) +function Model:create_ticket(user_id, proj_id, title, desc, priority) local code = self:get_next_code(proj_id) self.db:execute([[ - INSERT INTO Ticket(proj_id, user_id, state_id, time, code, title, desc) - VALUES (?, ?, 1, unixepoch(), ?, ?, ?); - ]], proj_id, user_id, code, title, desc) + INSERT INTO Ticket(proj_id, user_id, state_id, time, code, title, desc, priority, is_active) + VALUES (?, ?, 1, unixepoch(), ?, ?, ?, ?, 1); + ]], proj_id, user_id, code, title, desc, priority) return code end +function Model:get_ticket(proj_id, code) + local query = "SELECT * FROM Ticket WHERE proj_id = ? AND code = ?;" + return self.db:execute(query, proj_id, code)[1] +end + function Model:get_tickets(proj_id, state_id) -- TODO: limit "done" tickets by age local query = "SELECT * FROM Ticket WHERE proj_id = ? AND state_id = ?;" return self.db:execute(query, proj_id, state_id) end +function Model:update_ticket(tick_id, title, desc, priority) + local query = "UPDATE Ticket SET title = ?, desc = ?, priority = ? WHERE id = ?;" + self.db:execute(query, title, desc, priority, tick_id) +end + function Model:shift_ticket(user_id, ticket, state_id) self.db:execute([[ INSERT INTO Shift(ticket_id, old_stt_id, new_stt_id, user_id, time) @@ -214,6 +224,10 @@ function Model:shift_ticket(user_id, ticket, state_id) self.db:execute("UPDATE Ticket SET state_id = ? WHERE id = ?;", state_id, ticket.id) end +function Model:del_ticket(tick_id) + self.db:execute("DELETE FROM Ticket WHERE id = ?;", tick_id) +end + function Model:add_comment(user_id, ticket_id, text) self.db:execute([[ INSERT INTO Comment(ticket_id, user_id, time, text) diff --git a/skopos.lua b/skopos.lua index ac19462..fb21c7a 100644 --- a/skopos.lua +++ b/skopos.lua @@ -204,6 +204,80 @@ function App:routes() end return "/p", 303 end}, + {"GET", "/p/([-_%w]+)/t/(%d+)", + function (req, name, code) + local user = self:get_user(req) + if user == nil then return "/login", 303 end + local proj = self.model:get_user_project(user.id, name) + if proj == nil then return "not found", 404 end + local tick = self.model:get_ticket(proj.id, tonumber(code)) + if tick == nil then return "not found", 404 end + -- TODO: load comments + local comments = {} + local env = {title=self.title, user=user, proj=proj, tick=tick, comments=comments} + return lud.template.render_file("view/ticket.html", env) + end}, + {"GET", "/p/([-_%w]+)/new/ticket", + function (req, name) + local user = self:get_user(req) + if user == nil then return "/login", 303 end + local proj = self.model:get_user_project(user.id, name) + if proj == nil then return "not found", 404 end + local env = {title=self.title, user=user, proj=proj} + return lud.template.render_file("view/ticket_form.html", env) + end}, + {"POST", "/p/([-_%w]+)/new/ticket", + function (req, name) + local user = self:get_user(req) + if user == nil then return "/login", 303 end + local proj = self.model:get_user_project(user.id, name) + if proj == nil then return "not found", 404 end + local title = req.form.title + local desc = req.form.desc + local priority = tonumber(req.form.priority or 0) + local code = self.model:create_ticket(user.id, proj.id, title, desc, priority) + self:log(LOG_INFO, "user "..user.nick.." created ticket "..name.."#"..code) + return "/p/"..name.."/t/"..code, 303 + end}, + {"GET", "/p/([-_%w]+)/t/(%d+)/edit", + function (req, name, code) + local user = self:get_user(req) + if user == nil then return "/login", 303 end + local proj = self.model:get_user_project(user.id, name) + if proj == nil then return "not found", 404 end + local tick = self.model:get_ticket(proj.id, code) + if tick == nil then return "not found", 404 end + local env = {title=self.title, user=user, proj=proj, tick=tick} + return lud.template.render_file("view/ticket_form.html", env) + end}, + {"POST", "/p/([-_%w]+)/upd/ticket/(%d+)", + function (req, name, code) + local user = self:get_user(req) + if user == nil then return "/login", 303 end + local proj = self.model:get_user_project(user.id, name) + if proj == nil then return "not found", 404 end + local tick = self.model:get_ticket(proj.id, code) + if tick == nil then return "not found", 404 end + local title = req.form.title + local desc = req.form.desc + local priority = tonumber(req.form.priority or 0) + self.model:update_ticket(tick.id, title, desc, priority) + self:log(LOG_INFO, "user "..user.nick.." edited ticket "..name.."#"..code) + return "/p/"..name.."/t/"..code, 303 + end}, + {"POST", "/p/([-_%w]+)/del/ticket/(%d+)", + function (req, name, code) + local user = self:get_user(req) + if user == nil then return "/login", 303 end + local proj = self.model:get_user_project(user.id, name) + if proj == nil then return "not found", 404 end + local tick = self.model:get_ticket(proj.id, code) + if tick ~= nil then + self.model:del_ticket(tick.id) + self:log(LOG_INFO, "user "..user.nick.." deleted ticket "..name.."#"..code) + end + return "/p/"..name, 303 + end}, } end local function new_app(db_path, port, title, log_level) diff --git a/view/ticket.css b/view/ticket.css new file mode 100644 index 0000000..c283503 --- /dev/null +++ b/view/ticket.css @@ -0,0 +1,30 @@ +.ticket-details, .comment { + padding: 20px; + background-color: #f2f2f2; + border-radius: 5px; + box-shadow: 0px 0px 10px rgba(0,0,0,0.1); + margin-bottom: 20px; +} + +.ticket-details h1 { + margin-bottom: 20px; +} + +.header-details { + display: flex; + justify-content: space-between; + font-size: 0.8em; + margin-bottom: 10px; +} + +.comments-section { + padding: 20px; +} + +.comment { + background-color: white; +} + +.comment p:last-child { + margin-bottom: 0; +} diff --git a/view/ticket.html b/view/ticket.html new file mode 100644 index 0000000..934b6b7 --- /dev/null +++ b/view/ticket.html @@ -0,0 +1,39 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> + <title>{{$title}}</title> + <style> + .centered { text-align: center; } + .menu a { margin: 7px; } + % include view/ticket.css + </style> +</head> +<body> + <div class="centered menu"> + <a href="/p/{{$proj.name}}/t/{{$tick.code}}/new/comment">new comment</a> + </div> + <br> + <h1 class="centered">{{$proj.name}} - Ticket #{{$tick.code}}</h1> + <div class="ticket-details"> + <h1>{{$tick.title}}</h1> + <div class="header-details"> + <p class="date">Date: {{os.date("%Y-%m-%d", $tick.time)}}</p> + <p class="author">Author: {{$tick.user_id}}</p> + </div> + <pre>{{$tick.desc}}</pre> + </div> + <div class="comments-section"> + <h2>Comments</h2> + % for comment in $comments do + <div class="comment"> + <div class="header-details"> + <p class="date">Date: {{os.date("%Y-%m-%d", $comment.time)}}</p> + <p class="author">Author: {{$comment.user_id}}</p> + </div> + <pre>{{$comment.text}}</pre> + </div> + % end + </div> +</body> +</html> diff --git a/view/ticket_form.html b/view/ticket_form.html new file mode 100644 index 0000000..0b00989 --- /dev/null +++ b/view/ticket_form.html @@ -0,0 +1,61 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> + <title>{{$title}}</title> + <style> + .centered { text-align: center; } + % include view/form.css + </style> +</head> +<body> + <h1 class="centered">Ticket</h1> + % set action = "/p/" .. $proj.name + % if $tick == nil then + % set action = $action .. "/new/ticket" + % set tick = {title="", desc="", priority=0} + % set submit_value = "Create" + % else + % set action = $action .. "/upd/ticket/" .. $tick.code + % set submit_value = "Save" + % end + <form action="{{$action}}" method="post"> + <table class="field-list"> + <tbody> + <tr> + <td> + <label for="title">Title:</label> + </td> + <td> + <input + type="text" class="flat-field" id="title" name="title" required + size="50" value="{{$tick.title}}" autofocus> + </td> + </tr> + <tr> + <td> + <label for="desc">Description:</label> + </td> + <td> + <textarea + class="flat-field" id="desc" name="desc" + cols="50" rows="5">{{$tick.desc}}</textarea> + </td> + </tr> + <tr> + <td> + <label for="priority">Priority:</label> + </td> + <td> + <input + type="number" class="flat-field" id="priority" name="priority" + required value="{{$tick.priority}}"> + </td> + </tr> + </tbody> + </table> + <br> + <input type="submit" class="flat-button" value="{{$submit_value}}"> + </form> +</body> +</html>