login

<     >

2023-08-10 14:53:42 (UTC-03:00)

Marcel Rodrigues <marcelgmr@gmail.com>

archive/restore tickets

diff --git a/data.lua b/data.lua
index ef61c83..8815492 100644
--- a/data.lua
+++ b/data.lua
@@ -226,6 +226,18 @@ function Model:get_tickets(proj_id, state_id)
     return self.db:execute(query, proj_id, state_id)
 end
 
+function Model:get_archived_tickets(proj_id)
+    local query = [[
+        SELECT * FROM Ticket WHERE proj_id = ? AND is_active = FALSE
+        ORDER BY state_id ASC, code DESC;
+    ]]
+    local ticks = self.db:execute(query, proj_id)
+    for i = 1, #ticks do
+        ticks[i].state = self.states[ticks[i].state_id]
+    end
+    return ticks
+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)
@@ -252,6 +264,14 @@ 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:archive_ticket(tick_id)
+    self.db:execute("UPDATE Ticket SET is_active = FALSE WHERE id = ?;", tick_id)
+end
+
+function Model:restore_ticket(tick_id)
+    self.db:execute("UPDATE Ticket SET is_active = TRUE WHERE id = ?;", tick_id)
+end
+
 function Model:del_ticket(tick_id)
     self.db:execute("DELETE FROM Ticket WHERE id = ?;", tick_id)
 end
@@ -350,7 +370,7 @@ function Model:get_board(user_id, proj_id)
     JOIN User ON Ticket.user_id = User.id
     WHERE
         Membership.user_id = ?]]..filter..[[
-        AND Project.is_active
+        AND Project.is_active AND Ticket.is_active
     ORDER BY Ticket.priority DESC, proj_priority DESC;
     ]]
     local tickets

diff --git a/skopos.lua b/skopos.lua
index 0004cc8..c9d74c7 100644
--- a/skopos.lua
+++ b/skopos.lua
@@ -167,6 +167,16 @@ function App:routes()
         }
         return lud.template.render_file("view/board.html", env)
     end},
+    {"GET", "/p/([-_%w]+)/a",
+    function (req, name)
+        local user = self:get_user(req)
+        if user == nil then return "/login?after="..req.path, 303 end
+        local proj = self.model:get_user_project(user.id, name)
+        if proj == nil then return "not found", 404 end
+        local ticks = self.model:get_archived_tickets(proj.id)
+        local env = {title=self.title, user=user, proj=proj, ticks=ticks}
+        return lud.template.render_file("view/archive.html", env)
+    end},
     {"POST", "/p",
     function (req)
         local user = self:get_user(req)
@@ -308,14 +318,40 @@ function App:routes()
         local tick = self.model:get_ticket(proj.id, tcode)
         if tick == nil then return "not found", 404 end
         self.model:shift_ticket(user.id, tick, tonumber(state_id))
-        local path
+        local path = "/"
         if req.query.from == "proj" then
             path = "/p/"..name
-        else
-            path = "/"
         end
         return path, 303
     end},
+    {"POST", "/p/([-_%w]+)/t/(%d+)/archive",
+    function (req, name, tcode)
+        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, tcode)
+        if tick == nil then return "not found", 404 end
+        self.model:archive_ticket(tick.id)
+        self:log(LOG_INFO, "user "..user.nick.." archived ticket "..name.."#"..tcode)
+        local path = "/"
+        if req.query.from == "proj" then
+            path = "/p/"..name
+        end
+        return path, 303
+    end},
+    {"POST", "/p/([-_%w]+)/t/(%d+)/restore",
+    function (req, name, tcode)
+        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, tcode)
+        if tick == nil then return "not found", 404 end
+        self.model:restore_ticket(tick.id)
+        self:log(LOG_INFO, "user "..user.nick.." restored ticket "..name.."#"..tcode)
+        return "/p/"..name.."/a", 303
+    end},
     {"POST", "/p/([-_%w]+)/t/(%d+)/del",
     function (req, name, tcode)
         local user = self:get_user(req)

diff --git a/view/archive.html b/view/archive.html
new file mode 100644
index 0000000..592c061
--- /dev/null
+++ b/view/archive.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>{{$title}} - Archive</title>
+  <style>
+    .centered { text-align: center; }
+    % include view/table.css
+  </style>
+</head>
+<body>
+  <h1 class="centered">
+    <a href="/p/{{$proj.name}}">{{$proj.name}}</a> - Archived Tickets
+  </h1>
+  <table class="center">
+    <tr>
+      <th>code</th>
+      <th>creation</th>
+      <th>title</th>
+      <th>state</th>
+      <th>priority</th>
+      <th>restore</th>
+    </tr>
+    % for tick in $ticks do
+      % set base_path = "/p/"..$proj.name.."/t/"..$tick.code
+      <tr>
+        <td><a href="{{$base_path}}">#{{$tick.code}}</a></td>
+        <td>{{os.date("%F %T", $tick.time)}}</td>
+        <td>{{$tick.title}}</td>
+        <td>{{$tick.state}}</td>
+        <td>{{$tick.priority}}</td>
+        <td>
+          <form action="{{$base_path}}/restore" method="post">
+            <button type="submit">restore</button>
+          </form>
+        </td>
+      </tr>
+    % end
+  </table>
+</body>
+</html>

diff --git a/view/board.css b/view/board.css
index eeee151..9f232e0 100644
--- a/view/board.css
+++ b/view/board.css
@@ -38,8 +38,3 @@ button {
     background-color: #ddd;
     cursor: pointer;
 }
-
-button:disabled {
-    background-color: #aaa;
-    cursor: not-allowed;
-}

diff --git a/view/board.html b/view/board.html
index 846bc5b..ed25135 100644
--- a/view/board.html
+++ b/view/board.html
@@ -20,6 +20,7 @@
     % set proj_name = $proj.name
     % set from = "proj"
     <a href="/p/{{$proj.name}}/t/new">new ticket</a>
+    <a href="/p/{{$proj.name}}/a">archive</a>
   % end
   </div>
   <br>
@@ -43,20 +44,22 @@
           ({{$card.priority}})
         </div>
         <div class="buttons">
-          % set shift_path = "/p/"..$card.proj_name.."/t/"..$card.code.."/shift/"
-          % set left_disabled = ""
+          % set base_path = "/p/"..$card.proj_name.."/t/"..$card.code
+          % set shift_path = $base_path.."/shift/"
+          % set lpath = $shift_path..($state_id-1)
+          % set rpath = $shift_path..($state_id+1)
+          % set archive_path = $base_path.."/archive"
           % if $state_id == 1 then
-            % set left_disabled = " disabled"
+            % set lpath = $archive_path
           % end
-          <form action="{{$shift_path}}{{$state_id-1}}?from={{$from}}" method="post">
-            <button type="submit"{{$left_disabled}}>←</button>
-          </form>
-          % set right_disabled = ""
           % if $state_id == #$states then
-            % set right_disabled = " disabled"
+            % set rpath = $archive_path
           % end
-          <form action="{{$shift_path}}{{$state_id+1}}?from={{$from}}" method="post">
-            <button type="submit"{{$right_disabled}}>→</button>
+          <form action="{{$lpath}}?from={{$from}}" method="post">
+            <button type="submit">←</button>
+          </form>
+          <form action="{{$rpath}}?from={{$from}}" method="post">
+            <button type="submit">→</button>
           </form>
         </div>
       </div>