login

<     >

2023-08-13 11:50:21 (UTC-03:00)

Marcel Rodrigues <marcelgmr@gmail.com>

manage project members

diff --git a/data.lua b/data.lua
index d919615..18a0ea5 100644
--- a/data.lua
+++ b/data.lua
@@ -188,6 +188,29 @@ function Model:get_user_projects(user_id)
     ]], user_id)
 end
 
+function Model:get_members(proj_id)
+    return self.db:execute([[
+        SELECT nick, name FROM User JOIN Membership ON User.id = Membership.user_id
+        WHERE Membership.proj_id = ? ORDER BY nick;
+    ]], proj_id)
+end
+
+function Model:add_member(proj_id, nick)
+    local user = self:get_user(nick)
+    if user == nil then return false end
+    local query = "INSERT INTO Membership(proj_id, user_id) VALUES (?, ?);"
+    self.db:execute(query, proj_id, user.id)
+    return true
+end
+
+function Model:remove_member(proj_id, nick)
+    local user = self:get_user(nick)
+    if user == nil then return false end
+    local query = "DELETE FROM Membership WHERE proj_id = ? AND user_id = ?;"
+    self.db:execute(query, proj_id, user.id)
+    return true
+end
+
 function Model:update_project(old_name, new_name, desc, goal, color, priority)
     local query = [[
         UPDATE Project SET name = ?, desc = ?, goal = ?, color = ?, priority = ?

diff --git a/skopos.lua b/skopos.lua
index 8ed88bc..07e029a 100644
--- a/skopos.lua
+++ b/skopos.lua
@@ -288,6 +288,40 @@ function App:routes()
         end
         return "/p", 303
     end},
+    -- members
+    {"GET", "/p/([-_%w]+)/m",
+    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 members = self.model:get_members(proj.id)
+        local env = {title=self.title, user=user, proj=proj, members=members}
+        return lud.template.render_file("view/members.html", env)
+    end},
+    {"POST", "/p/([-_%w]+)/m/add",
+    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 nick = req.form.username
+        if self.model:add_member(proj.id, nick) then
+            self:log(LOG_INFO, "user "..user.nick.." added "..nick.." to "..name)
+        end
+        return "/p/"..name.."/m", 303
+    end},
+    {"POST", "/p/([-_%w]+)/m/([-_%w]+)/rem",
+    function (req, name, nick)
+        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
+        if self.model:remove_member(proj.id, nick) then
+            self:log(LOG_INFO, "user "..user.nick.." removed "..nick.." from "..name)
+        end
+        return "/p/"..name.."/m", 303
+    end},
     -- tickets
     {"GET", "/p/([-_%w]+)/t/new",
     function (req, name)

diff --git a/view/members.html b/view/members.html
new file mode 100644
index 0000000..5c4cb55
--- /dev/null
+++ b/view/members.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>{{$title}} - members</title>
+  <style>
+    .centered { text-align: center; }
+    % include view/menu.css
+    % include view/table.css
+  </style>
+</head>
+<body>
+  % include view/menu.html
+  <h1 class="centered">{{$proj.name}} - members</h1>
+  <table class="center">
+    <tr>
+      <th>nick</th>
+      <th>name</th>
+      <th>remove</th>
+    </tr>
+    % for member in $members do
+      <tr>
+        <td><a href="/u/{{$member.nick}}">{{$member.nick}}</a></td>
+        <td>{{$member.name}}</td>
+        <td>
+          <form action="/p/{{$proj.name}}/m/{{$member.nick}}/rem" method="post">
+            <button type="submit">remove</button>
+          </form>
+        </td>
+      </tr>
+    % end
+  </table>
+  <br>
+  <form class="centered" action="/p/{{$proj.name}}/m/add" method="post">
+    <input type="text" name="username" placeholder="Username" required pattern="[-_A-Za-z0-9]+">
+    <input type="submit" value="add"></li>
+  </form>
+</body>
+</html>

diff --git a/view/menu.html b/view/menu.html
index 7027ca6..69a185e 100644
--- a/view/menu.html
+++ b/view/menu.html
@@ -4,6 +4,7 @@
       <a href="/p">projects</a>
     % if $proj ~= nil then
       <a href="/p/{{$proj.name}}">{{$proj.name}}</a>
+      <a href="/p/{{$proj.name}}/m">members</a>
       <a href="/p/{{$proj.name}}/a">archive</a>
       % if $tick ~= nil then
       <a href="/p/{{$proj.name}}/t/{{$tick.code}}/c/new">new comment</a>