login

<     >

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>