@unbrained/pm-web 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/README.md +107 -0
- package/dist/auth.js +20 -0
- package/dist/auth.js.map +1 -0
- package/dist/crypto.js +42 -0
- package/dist/crypto.js.map +1 -0
- package/dist/db.js +111 -0
- package/dist/db.js.map +1 -0
- package/dist/index.js +88 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware/auth.js +16 -0
- package/dist/middleware/auth.js.map +1 -0
- package/dist/routes/admin.js +207 -0
- package/dist/routes/admin.js.map +1 -0
- package/dist/routes/auth.js +163 -0
- package/dist/routes/auth.js.map +1 -0
- package/dist/routes/github.js +354 -0
- package/dist/routes/github.js.map +1 -0
- package/dist/routes/groups.js +180 -0
- package/dist/routes/groups.js.map +1 -0
- package/dist/routes/pm.js +2446 -0
- package/dist/routes/pm.js.map +1 -0
- package/dist/routes/projects.js +151 -0
- package/dist/routes/projects.js.map +1 -0
- package/dist/routes/sharing.js +155 -0
- package/dist/routes/sharing.js.map +1 -0
- package/dist/server.js +64 -0
- package/dist/server.js.map +1 -0
- package/dist/services/pm-runner.js +190 -0
- package/dist/services/pm-runner.js.map +1 -0
- package/dist/services/sse.js +111 -0
- package/dist/services/sse.js.map +1 -0
- package/manifest.json +15 -0
- package/package.json +111 -0
- package/public/icons/icon-192.png +0 -0
- package/public/icons/icon-512.png +0 -0
- package/public/index.html +265 -0
- package/public/manifest.json +66 -0
- package/public/src/api.js +28 -0
- package/public/src/api.js.map +1 -0
- package/public/src/api.ts +29 -0
- package/public/src/app.js +926 -0
- package/public/src/app.js.map +1 -0
- package/public/src/app.ts +929 -0
- package/public/src/components/modals.js +62 -0
- package/public/src/components/modals.js.map +1 -0
- package/public/src/components/modals.ts +73 -0
- package/public/src/components/toast.js +10 -0
- package/public/src/components/toast.js.map +1 -0
- package/public/src/components/toast.ts +13 -0
- package/public/src/constants.js +30 -0
- package/public/src/constants.js.map +1 -0
- package/public/src/constants.ts +41 -0
- package/public/src/state.js +15 -0
- package/public/src/state.js.map +1 -0
- package/public/src/state.ts +19 -0
- package/public/src/types.js +5 -0
- package/public/src/types.js.map +1 -0
- package/public/src/types.ts +253 -0
- package/public/src/utils.js +57 -0
- package/public/src/utils.js.map +1 -0
- package/public/src/utils.ts +56 -0
- package/public/src/views/activity.js +47 -0
- package/public/src/views/activity.js.map +1 -0
- package/public/src/views/activity.ts +41 -0
- package/public/src/views/admin.js +435 -0
- package/public/src/views/admin.js.map +1 -0
- package/public/src/views/admin.ts +504 -0
- package/public/src/views/auth.js +81 -0
- package/public/src/views/auth.js.map +1 -0
- package/public/src/views/auth.ts +74 -0
- package/public/src/views/calendar.js +133 -0
- package/public/src/views/calendar.js.map +1 -0
- package/public/src/views/calendar.ts +129 -0
- package/public/src/views/comments-audit.js +109 -0
- package/public/src/views/comments-audit.js.map +1 -0
- package/public/src/views/comments-audit.ts +108 -0
- package/public/src/views/config.js +322 -0
- package/public/src/views/config.js.map +1 -0
- package/public/src/views/config.ts +344 -0
- package/public/src/views/context.js +98 -0
- package/public/src/views/context.js.map +1 -0
- package/public/src/views/context.ts +100 -0
- package/public/src/views/create.js +293 -0
- package/public/src/views/create.js.map +1 -0
- package/public/src/views/create.ts +246 -0
- package/public/src/views/dedupe.js +51 -0
- package/public/src/views/dedupe.js.map +1 -0
- package/public/src/views/dedupe.ts +43 -0
- package/public/src/views/export.js +300 -0
- package/public/src/views/export.js.map +1 -0
- package/public/src/views/export.ts +274 -0
- package/public/src/views/github.js +360 -0
- package/public/src/views/github.js.map +1 -0
- package/public/src/views/github.ts +308 -0
- package/public/src/views/graph-canvas.js +1986 -0
- package/public/src/views/graph-canvas.js.map +1 -0
- package/public/src/views/graph-canvas.ts +2218 -0
- package/public/src/views/graph.js +1824 -0
- package/public/src/views/graph.js.map +1 -0
- package/public/src/views/graph.ts +1891 -0
- package/public/src/views/groups.js +186 -0
- package/public/src/views/groups.js.map +1 -0
- package/public/src/views/groups.ts +172 -0
- package/public/src/views/guide.js +151 -0
- package/public/src/views/guide.js.map +1 -0
- package/public/src/views/guide.ts +162 -0
- package/public/src/views/health.js +105 -0
- package/public/src/views/health.js.map +1 -0
- package/public/src/views/health.ts +102 -0
- package/public/src/views/items.js +1306 -0
- package/public/src/views/items.js.map +1 -0
- package/public/src/views/items.ts +1196 -0
- package/public/src/views/normalize.js +67 -0
- package/public/src/views/normalize.js.map +1 -0
- package/public/src/views/normalize.ts +58 -0
- package/public/src/views/plan.js +454 -0
- package/public/src/views/plan.js.map +1 -0
- package/public/src/views/plan.ts +496 -0
- package/public/src/views/projects.js +204 -0
- package/public/src/views/projects.js.map +1 -0
- package/public/src/views/projects.ts +196 -0
- package/public/src/views/router.js +227 -0
- package/public/src/views/router.js.map +1 -0
- package/public/src/views/router.ts +188 -0
- package/public/src/views/search.js +103 -0
- package/public/src/views/search.js.map +1 -0
- package/public/src/views/search.ts +94 -0
- package/public/src/views/settings.js +272 -0
- package/public/src/views/settings.js.map +1 -0
- package/public/src/views/settings.ts +190 -0
- package/public/src/views/shared.js +49 -0
- package/public/src/views/shared.js.map +1 -0
- package/public/src/views/shared.ts +49 -0
- package/public/src/views/sharing.js +152 -0
- package/public/src/views/sharing.js.map +1 -0
- package/public/src/views/sharing.ts +139 -0
- package/public/src/views/stats.js +92 -0
- package/public/src/views/stats.js.map +1 -0
- package/public/src/views/stats.ts +88 -0
- package/public/src/views/templates.js +117 -0
- package/public/src/views/templates.js.map +1 -0
- package/public/src/views/templates.ts +113 -0
- package/public/src/views/validate.js +54 -0
- package/public/src/views/validate.js.map +1 -0
- package/public/src/views/validate.ts +48 -0
- package/public/styles.css +2231 -0
- package/public/sw.js +318 -0
- package/public/tsconfig.json +20 -0
- package/sql/schema.sql +105 -0
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { Router } from "express";
|
|
2
|
+
import { pool } from "../db.js";
|
|
3
|
+
import { requireAuth } from "../middleware/auth.js";
|
|
4
|
+
const router = Router();
|
|
5
|
+
router.use(requireAuth);
|
|
6
|
+
// GET /api/groups - list groups I own or am a member of
|
|
7
|
+
router.get("/", async (req, res) => {
|
|
8
|
+
try {
|
|
9
|
+
const result = await pool.query(`SELECT g.id, g.owner_id, g.name, g.description, g.created_at, g.updated_at,
|
|
10
|
+
gm.role,
|
|
11
|
+
(SELECT COUNT(*) FROM pm_group_members WHERE group_id = g.id) AS member_count
|
|
12
|
+
FROM pm_groups g
|
|
13
|
+
JOIN pm_group_members gm ON gm.group_id = g.id AND gm.user_id = $1
|
|
14
|
+
ORDER BY g.created_at DESC`, [req.user.userId]);
|
|
15
|
+
res.json({ groups: result.rows });
|
|
16
|
+
}
|
|
17
|
+
catch (err) {
|
|
18
|
+
console.error("List groups error:", err);
|
|
19
|
+
res.status(500).json({ error: "Failed to fetch groups" });
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
// POST /api/groups - create a group
|
|
23
|
+
router.post("/", async (req, res) => {
|
|
24
|
+
const { name, description } = req.body;
|
|
25
|
+
if (!name?.trim()) {
|
|
26
|
+
res.status(400).json({ error: "Group name is required" });
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const client = await pool.connect();
|
|
30
|
+
try {
|
|
31
|
+
await client.query("BEGIN");
|
|
32
|
+
const groupResult = await client.query(`INSERT INTO pm_groups (owner_id, name, description)
|
|
33
|
+
VALUES ($1, $2, $3)
|
|
34
|
+
RETURNING id, owner_id, name, description, created_at, updated_at`, [req.user.userId, name.trim(), description?.trim() || ""]);
|
|
35
|
+
const group = groupResult.rows[0];
|
|
36
|
+
// Add owner as a member with role 'owner'
|
|
37
|
+
await client.query(`INSERT INTO pm_group_members (group_id, user_id, role) VALUES ($1, $2, 'owner')`, [group.id, req.user.userId]);
|
|
38
|
+
await client.query("COMMIT");
|
|
39
|
+
res.status(201).json({ group: { ...groupResult.rows[0], role: "owner", member_count: "1" } });
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
await client.query("ROLLBACK");
|
|
43
|
+
console.error("Create group error:", err);
|
|
44
|
+
res.status(500).json({ error: "Failed to create group" });
|
|
45
|
+
}
|
|
46
|
+
finally {
|
|
47
|
+
client.release();
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
// GET /api/groups/:id - get group details with members
|
|
51
|
+
router.get("/:id", async (req, res) => {
|
|
52
|
+
try {
|
|
53
|
+
// Check membership
|
|
54
|
+
const memberCheck = await pool.query(`SELECT gm.role FROM pm_group_members gm
|
|
55
|
+
WHERE gm.group_id = $1 AND gm.user_id = $2`, [req.params["id"], req.user.userId]);
|
|
56
|
+
if (memberCheck.rows.length === 0) {
|
|
57
|
+
res.status(404).json({ error: "Group not found" });
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
const groupResult = await pool.query(`SELECT id, owner_id, name, description, created_at, updated_at
|
|
61
|
+
FROM pm_groups WHERE id = $1`, [req.params["id"]]);
|
|
62
|
+
const group = groupResult.rows[0];
|
|
63
|
+
const membersResult = await pool.query(`SELECT gm.id, gm.user_id, gm.role, gm.invited_at,
|
|
64
|
+
u.email, u.display_name
|
|
65
|
+
FROM pm_group_members gm
|
|
66
|
+
JOIN pm_users u ON u.id = gm.user_id
|
|
67
|
+
WHERE gm.group_id = $1
|
|
68
|
+
ORDER BY gm.invited_at ASC`, [req.params["id"]]);
|
|
69
|
+
res.json({ group: { ...group, members: membersResult.rows } });
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
console.error("Get group error:", err);
|
|
73
|
+
res.status(500).json({ error: "Failed to fetch group" });
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
// PATCH /api/groups/:id - update group (owner only)
|
|
77
|
+
router.patch("/:id", async (req, res) => {
|
|
78
|
+
const { name, description } = req.body;
|
|
79
|
+
try {
|
|
80
|
+
const result = await pool.query(`UPDATE pm_groups
|
|
81
|
+
SET name = COALESCE($1, name),
|
|
82
|
+
description = COALESCE($2, description),
|
|
83
|
+
updated_at = NOW()
|
|
84
|
+
WHERE id = $3 AND owner_id = $4
|
|
85
|
+
RETURNING id, owner_id, name, description, created_at, updated_at`, [name?.trim() || null, description !== undefined ? description : null, req.params["id"], req.user.userId]);
|
|
86
|
+
if (result.rows.length === 0) {
|
|
87
|
+
res.status(404).json({ error: "Group not found or you are not the owner" });
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
res.json({ group: result.rows[0] });
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
console.error("Update group error:", err);
|
|
94
|
+
res.status(500).json({ error: "Failed to update group" });
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
// DELETE /api/groups/:id - delete group (owner only)
|
|
98
|
+
router.delete("/:id", async (req, res) => {
|
|
99
|
+
try {
|
|
100
|
+
const result = await pool.query(`DELETE FROM pm_groups WHERE id = $1 AND owner_id = $2 RETURNING id`, [req.params["id"], req.user.userId]);
|
|
101
|
+
if (result.rows.length === 0) {
|
|
102
|
+
res.status(404).json({ error: "Group not found or you are not the owner" });
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
res.json({ ok: true });
|
|
106
|
+
}
|
|
107
|
+
catch (err) {
|
|
108
|
+
console.error("Delete group error:", err);
|
|
109
|
+
res.status(500).json({ error: "Failed to delete group" });
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
// POST /api/groups/:id/members - invite user by email
|
|
113
|
+
router.post("/:id/members", async (req, res) => {
|
|
114
|
+
const { email, role } = req.body;
|
|
115
|
+
if (!email?.trim()) {
|
|
116
|
+
res.status(400).json({ error: "Email is required" });
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
const memberRole = role === "owner" ? "owner" : "member";
|
|
120
|
+
try {
|
|
121
|
+
// Verify requester is owner
|
|
122
|
+
const ownerCheck = await pool.query(`SELECT id FROM pm_groups WHERE id = $1 AND owner_id = $2`, [req.params["id"], req.user.userId]);
|
|
123
|
+
if (ownerCheck.rows.length === 0) {
|
|
124
|
+
res.status(403).json({ error: "Only the group owner can invite members" });
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
// Find the user by email
|
|
128
|
+
const userResult = await pool.query(`SELECT id, email, display_name FROM pm_users WHERE email = $1`, [email.trim().toLowerCase()]);
|
|
129
|
+
if (userResult.rows.length === 0) {
|
|
130
|
+
res.status(404).json({ error: "User not found" });
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
const invitedUser = userResult.rows[0];
|
|
134
|
+
const memberResult = await pool.query(`INSERT INTO pm_group_members (group_id, user_id, role)
|
|
135
|
+
VALUES ($1, $2, $3)
|
|
136
|
+
ON CONFLICT (group_id, user_id) DO UPDATE SET role = EXCLUDED.role
|
|
137
|
+
RETURNING id, user_id, role, invited_at`, [req.params["id"], invitedUser.id, memberRole]);
|
|
138
|
+
res.status(201).json({
|
|
139
|
+
member: {
|
|
140
|
+
...memberResult.rows[0],
|
|
141
|
+
email: invitedUser.email,
|
|
142
|
+
display_name: invitedUser.display_name,
|
|
143
|
+
},
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
catch (err) {
|
|
147
|
+
console.error("Invite member error:", err);
|
|
148
|
+
res.status(500).json({ error: "Failed to invite member" });
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
// DELETE /api/groups/:id/members/:userId - remove member
|
|
152
|
+
router.delete("/:id/members/:userId", async (req, res) => {
|
|
153
|
+
try {
|
|
154
|
+
// Verify requester is owner, OR member is removing themselves
|
|
155
|
+
const isSelf = req.params["userId"] === req.user.userId;
|
|
156
|
+
const ownerCheck = await pool.query(`SELECT id FROM pm_groups WHERE id = $1 AND owner_id = $2`, [req.params["id"], req.user.userId]);
|
|
157
|
+
const isOwner = ownerCheck.rows.length > 0;
|
|
158
|
+
if (!isOwner && !isSelf) {
|
|
159
|
+
res.status(403).json({ error: "Not authorized to remove this member" });
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
// Prevent owner from removing themselves (they must delete the group instead)
|
|
163
|
+
if (isSelf && isOwner) {
|
|
164
|
+
res.status(400).json({ error: "Group owner cannot leave the group. Delete the group instead." });
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
const result = await pool.query(`DELETE FROM pm_group_members WHERE group_id = $1 AND user_id = $2 RETURNING id`, [req.params["id"], req.params["userId"]]);
|
|
168
|
+
if (result.rows.length === 0) {
|
|
169
|
+
res.status(404).json({ error: "Member not found" });
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
res.json({ ok: true });
|
|
173
|
+
}
|
|
174
|
+
catch (err) {
|
|
175
|
+
console.error("Remove member error:", err);
|
|
176
|
+
res.status(500).json({ error: "Failed to remove member" });
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
export { router as groupsRouter };
|
|
180
|
+
//# sourceMappingURL=groups.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"groups.js","sourceRoot":"","sources":["../../src/routes/groups.ts"],"names":[],"mappings":"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"}
|