@parallelworks/tandem-web 0.138.0 → 0.139.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.
Files changed (71) hide show
  1. package/components/AgentWork.js +35 -35
  2. package/components/AppRoot.js +4 -4
  3. package/components/AreaWork.js +1 -1
  4. package/components/BlockHandle.js +3 -3
  5. package/components/CommandPalette.js +27 -27
  6. package/components/DateChip.js +27 -27
  7. package/components/DocLinkPicker.js +17 -17
  8. package/components/Graph.js +6 -6
  9. package/components/HoverCards.js +30 -29
  10. package/components/IssueListBlock.js +83 -83
  11. package/components/LinkCard.js +20 -20
  12. package/components/MentionPicker.js +12 -12
  13. package/components/NewIssueDialog.js +116 -116
  14. package/components/NewProjectDialog.js +5 -4
  15. package/components/Planning.js +31 -43
  16. package/components/RouterLink.js +4 -4
  17. package/components/ShareDialog.js +12 -12
  18. package/components/SharedUI.js +19 -19
  19. package/components/SlashMenu.js +11 -11
  20. package/components/SubPages.js +10 -10
  21. package/components/UnlinkedMentions.js +10 -10
  22. package/components/WorkCounts.js +8 -8
  23. package/components/settings.js +26 -26
  24. package/hostedApp.js +36 -36
  25. package/hosting.d.ts +24 -11
  26. package/index.js +58 -27
  27. package/lib/base.js +1 -14
  28. package/lib/docs.js +6 -6
  29. package/lib/issueMenu.js +33 -33
  30. package/lib/knowledge.js +90 -101
  31. package/lib/knowledgeKinds.js +14 -0
  32. package/lib/projectList.js +1 -1
  33. package/lib/projectStates.js +15 -0
  34. package/lib/router.js +20 -34
  35. package/package.json +6 -6
  36. package/pages/areas.js +147 -147
  37. package/pages/decisions.js +40 -40
  38. package/pages/issues.js +4 -4
  39. package/pages/projects.js +232 -231
  40. package/pages/triage.js +86 -86
  41. package/pages.js +21 -0
  42. package/routes/__root.js +6 -6
  43. package/routes/_workspace/docs/_doc2.js +12 -12
  44. package/routes/_workspace/docs2.js +8 -8
  45. package/routes/_workspace/graph2.js +9 -9
  46. package/routes/_workspace/issues/_identifier2.js +327 -327
  47. package/routes/_workspace/issues/index.js +6 -6
  48. package/routes/_workspace/knowledge/_term2.js +125 -124
  49. package/routes/_workspace/knowledge/index.js +8 -8
  50. package/routes/_workspace/knowledge/index2.js +22 -21
  51. package/routes/_workspace/measures2.js +4 -4
  52. package/routes/_workspace/people/_username.js +4 -4
  53. package/routes/_workspace/projects/_projectId3.js +264 -263
  54. package/routes/_workspace/projects/index.js +7 -7
  55. package/routes/_workspace/settings/account2.js +3 -3
  56. package/routes/_workspace/settings/audit-log2.js +4 -4
  57. package/routes/_workspace/settings/audit-log3.js +51 -51
  58. package/routes/_workspace/settings/labels2.js +14 -14
  59. package/routes/_workspace/settings/members2.js +9 -9
  60. package/routes/_workspace/settings/runners2.js +11 -11
  61. package/routes/_workspace/settings/teams2.js +15 -15
  62. package/routes/_workspace/settings/tokens2.js +5 -5
  63. package/routes/_workspace/settings/webhooks2.js +7 -7
  64. package/routes/_workspace/settings2.js +3 -3
  65. package/routes/_workspace/teams/_key/cycles/_number2.js +8 -8
  66. package/routes/_workspace/teams/_key/cycles/index2.js +20 -20
  67. package/routes/_workspace/teams/_key/issues.js +4 -4
  68. package/routes/_workspace/teams/_key/projects.js +4 -4
  69. package/routes/_workspace/teams/_key/settings2.js +8 -8
  70. package/routes/_workspace2.js +319 -319
  71. package/routes/docs/route2.js +15 -15
@@ -1,7 +1,7 @@
1
1
  import { api as e, unwrap as t } from "../../../api/client.js";
2
2
  import { teamsQuery as n, webhooksQuery as r } from "../../../api/queries.js";
3
- import { useTime as i } from "../../../lib/time.js";
4
- import { Route as a } from "./webhooks.js";
3
+ import { Route as i } from "./webhooks.js";
4
+ import { useTime as a } from "../../../lib/time.js";
5
5
  import { useCan as o } from "../../../lib/roles.js";
6
6
  import { AdminOnly as s, SettingsPage as c, cardFooter as l, cardList as u, useFormError as d } from "../../../components/settings.js";
7
7
  import { useConfirm as f } from "../../../lib/confirm.js";
@@ -20,20 +20,20 @@ var A = {
20
20
  plans: ["project."]
21
21
  };
22
22
  function j() {
23
- let { workspace: e } = a.useParams(), t = o(e, "manage_workspace"), n = S("webhooks"), r = S("settingsNav");
23
+ let { workspace: e } = i.useParams(), t = o(e, "manage_workspace"), n = S("webhooks"), r = S("settingsNav");
24
24
  return /* @__PURE__ */ T(c, {
25
25
  title: r("webhooks"),
26
26
  description: n("description"),
27
27
  children: [/* @__PURE__ */ w(s, { workspace: e }), t && /* @__PURE__ */ w(M, { workspace: e })]
28
28
  });
29
29
  }
30
- function M({ workspace: a }) {
31
- let { data: o } = k(r(a)), s = S("webhooks"), c = S("common"), j = i(), M = O(), N = d(), [P, F] = x(""), [I, L] = x([]), [R, z] = x("json"), [B, V] = x(""), { data: H = [] } = D(n(a)), [U, W] = x(null), [G, K] = x({}), q = () => M.invalidateQueries({ queryKey: r(a).queryKey }), J = (e) => ({ path: {
32
- workspace: a,
30
+ function M({ workspace: i }) {
31
+ let { data: o } = k(r(i)), s = S("webhooks"), c = S("common"), j = a(), M = O(), N = d(), [P, F] = x(""), [I, L] = x([]), [R, z] = x("json"), [B, V] = x(""), { data: H = [] } = D(n(i)), [U, W] = x(null), [G, K] = x({}), q = () => M.invalidateQueries({ queryKey: r(i).queryKey }), J = (e) => ({ path: {
32
+ workspace: i,
33
33
  webhookId: e
34
34
  } }), Y = E({
35
35
  mutationFn: async () => t(await e.POST("/api/v1/workspaces/{workspace}/webhooks", {
36
- params: { path: { workspace: a } },
36
+ params: { path: { workspace: i } },
37
37
  body: {
38
38
  url: P,
39
39
  events: I.flatMap((e) => A[e]),
@@ -1,7 +1,7 @@
1
- import { jsx as e } from "react/jsx-runtime";
2
- import { Outlet as t } from "@tanstack/react-router";
1
+ import { Outlet as e } from "@tanstack/react-router";
2
+ import { jsx as t } from "react/jsx-runtime";
3
3
  // src/routes/$workspace/settings.tsx?tsr-split=component
4
4
  function n() {
5
- return /* @__PURE__ */ e(t, {});
5
+ return /* @__PURE__ */ t(e, {});
6
6
  }
7
7
  export { n as component };
@@ -3,10 +3,10 @@ import { useNavigate as n } from "../../../../../lib/router.js";
3
3
  import { cyclesQuery as r, issuesQuery as i, teamsQuery as a } from "../../../../../api/queries.js";
4
4
  import { CloseIcon as ee, CycleIcon as o } from "../../../../../components/icons.js";
5
5
  import { teamPath as s } from "../../../../../lib/teamPaths.js";
6
- import { addDays as te, today as ne, useTime as re } from "../../../../../lib/time.js";
7
- import { ProgressBar as c } from "../../../../../components/Planning.js";
8
- import { Route as l } from "./_number.js";
9
- import { invalidateIssueViews as u } from "../../../../../api/mutations.js";
6
+ import { Route as te } from "./_number.js";
7
+ import { invalidateIssueViews as ne } from "../../../../../api/mutations.js";
8
+ import { addDays as re, today as c, useTime as l } from "../../../../../lib/time.js";
9
+ import { ProgressBar as u } from "../../../../../components/Planning.js";
10
10
  import { usePageTitle as d } from "../../../../../lib/pageTitle.js";
11
11
  import { useCan as f } from "../../../../../lib/roles.js";
12
12
  import { FavoriteStar as p } from "../../../../../components/FavoriteStar.js";
@@ -27,7 +27,7 @@ var k = [
27
27
  "projects"
28
28
  ];
29
29
  function A() {
30
- let { workspace: A, key: j, number: M } = l.useParams(), N = S("planning"), P = x(), F = re(), I = n(), { data: L } = O(a(A)), { data: R } = O(r(A, j)), z = R.find((e) => String(e.number) === M), B = L.find((e) => e.key === j);
30
+ let { workspace: A, key: j, number: M } = te.useParams(), N = S("planning"), P = x(), F = l(), I = n(), { data: L } = O(a(A)), { data: R } = O(r(A, j)), z = R.find((e) => String(e.number) === M), B = L.find((e) => e.key === j);
31
31
  d(z && (z.name ? N("cycleNamed", {
32
32
  number: z.number,
33
33
  name: z.name
@@ -42,13 +42,13 @@ function A() {
42
42
  number: Number(M)
43
43
  } } })),
44
44
  onSuccess: (e) => W(e.moved),
45
- onSettled: () => u(H, A)
45
+ onSettled: () => ne(H, A)
46
46
  });
47
47
  if (!z) return /* @__PURE__ */ C("p", {
48
48
  className: "px-8 py-10 text-sm text-muted-foreground",
49
49
  children: N("noSuchCycle")
50
50
  });
51
- let X = ce?.issues ?? [], Z = q ? X.filter((e) => g(e, q.tab).includes(q.key)) : X, Q = X.filter((e) => e.status.category !== "completed" && e.status.category !== "canceled").length, le = z.state === "past" || z.state === "current" && te(ne(), 2) >= z.endsOn, $ = z.name ? N("cycleNamed", {
51
+ let X = ce?.issues ?? [], Z = q ? X.filter((e) => g(e, q.tab).includes(q.key)) : X, Q = X.filter((e) => e.status.category !== "completed" && e.status.category !== "canceled").length, le = z.state === "past" || z.state === "current" && re(c(), 2) >= z.endsOn, $ = z.name ? N("cycleNamed", {
52
52
  number: z.number,
53
53
  name: z.name
54
54
  }) : N("cycle", { number: z.number });
@@ -139,7 +139,7 @@ function A() {
139
139
  /* @__PURE__ */ C("section", {
140
140
  className: "mt-6",
141
141
  "aria-label": N("progressTitle"),
142
- children: /* @__PURE__ */ C(c, { progress: z.progress })
142
+ children: /* @__PURE__ */ C(u, { progress: z.progress })
143
143
  }),
144
144
  /* @__PURE__ */ C("section", {
145
145
  className: "mt-6 rounded-xl border border-border bg-card p-4",
@@ -3,8 +3,8 @@ import { Link as n } from "../../../../../lib/router.js";
3
3
  import { cyclesQuery as r, teamsQuery as i } from "../../../../../api/queries.js";
4
4
  import { AddIcon as a, CycleIcon as o } from "../../../../../components/icons.js";
5
5
  import { teamPath as s } from "../../../../../lib/teamPaths.js";
6
- import { useTime as c } from "../../../../../lib/time.js";
7
- import { Route as l } from "./index.js";
6
+ import { Route as c } from "./index.js";
7
+ import { useTime as l } from "../../../../../lib/time.js";
8
8
  import { usePageTitle as u } from "../../../../../lib/pageTitle.js";
9
9
  import { useCan as d } from "../../../../../lib/roles.js";
10
10
  import { BurnUp as f } from "../../../../../components/Reports.js";
@@ -23,17 +23,17 @@ function A(e) {
23
23
  return n > 0 ? n : null;
24
24
  }
25
25
  function j() {
26
- let { workspace: c, key: f } = l.useParams(), _ = x("planning"), b = y(), { data: k } = D(i(c)), { data: j } = D(r(c, f)), N = k.find((e) => e.key === f);
26
+ let { workspace: l, key: f } = c.useParams(), _ = x("planning"), b = y(), { data: k } = D(i(l)), { data: j } = D(r(l, f)), N = k.find((e) => e.key === f);
27
27
  u(_("cycles"), N?.name);
28
- let P = d(c, "manage_cycles", { team: f }), F = E(), [I, L] = v(!1), R = T({
28
+ let P = d(l, "manage_cycles", { team: f }), F = E(), [I, L] = v(!1), R = T({
29
29
  mutationFn: async () => t(await e.POST("/api/v1/workspaces/{workspace}/teams/{key}/cycles", {
30
30
  params: { path: {
31
- workspace: c,
31
+ workspace: l,
32
32
  key: f
33
33
  } },
34
34
  body: {}
35
35
  })),
36
- onSettled: () => F.invalidateQueries({ queryKey: r(c, f).queryKey })
36
+ onSettled: () => F.invalidateQueries({ queryKey: r(l, f).queryKey })
37
37
  }), z = [...j].sort((e, t) => e.number - t.number), B = z.filter((e) => e.state === "past"), V = I ? 0 : Math.max(0, B.length - O), H = z.filter((e) => e.state !== "past" || B.indexOf(e) >= V), U = A(j);
38
38
  return /* @__PURE__ */ w("div", {
39
39
  className: "flex h-full min-h-0 flex-col",
@@ -41,7 +41,7 @@ function j() {
41
41
  heading: !1,
42
42
  breadcrumbs: [{
43
43
  label: N?.name ?? f,
44
- href: s(c, f, "issues")
44
+ href: s(l, f, "issues")
45
45
  }, { label: _("cycles") }]
46
46
  }), /* @__PURE__ */ C("div", {
47
47
  className: "min-h-0 flex-1 overflow-y-auto",
@@ -78,7 +78,7 @@ function j() {
78
78
  action: /* @__PURE__ */ C(n, {
79
79
  to: "/$workspace/teams/$key/settings",
80
80
  params: {
81
- workspace: c,
81
+ workspace: l,
82
82
  key: f
83
83
  },
84
84
  className: "text-sm text-primary hover:underline",
@@ -97,7 +97,7 @@ function j() {
97
97
  }), /* @__PURE__ */ C("ol", {
98
98
  className: "relative mt-6",
99
99
  children: H.map((e, t) => /* @__PURE__ */ C(M, {
100
- workspace: c,
100
+ workspace: l,
101
101
  teamKey: f,
102
102
  cycle: e,
103
103
  capacity: U,
@@ -111,18 +111,18 @@ function j() {
111
111
  });
112
112
  }
113
113
  function M({ workspace: e, teamKey: t, cycle: r, capacity: i, first: a, last: s }) {
114
- let l = x("planning"), u = c(), d = b(), p = r.state === "current", m = (e) => d.number(e, {
114
+ let c = x("planning"), u = l(), d = b(), p = r.state === "current", m = (e) => d.number(e, {
115
115
  style: "percent",
116
116
  maximumFractionDigits: 0
117
117
  }), h = r.state === "past" ? k(r) : r.progress.total, g = i !== null && r.state !== "past" && h > i, v = r.state === "past" ? [
118
- ...h > 0 ? [l("success", { percent: m(r.progress.completed / h) })] : [],
119
- l("completedCount", { count: r.progress.completed }),
120
- l("scopeCount", { count: h }),
121
- ...r.carriedOut > 0 ? [l("carriedOut", { count: r.carriedOut })] : []
118
+ ...h > 0 ? [c("success", { percent: m(r.progress.completed / h) })] : [],
119
+ c("completedCount", { count: r.progress.completed }),
120
+ c("scopeCount", { count: h }),
121
+ ...r.carriedOut > 0 ? [c("carriedOut", { count: r.carriedOut })] : []
122
122
  ] : [
123
- ...i ? [l("ofCapacity", { percent: m(h / i) })] : [],
124
- l("scopeCount", { count: h }),
125
- ...r.carriedIn > 0 ? [l("carriedIn", { count: r.carriedIn })] : []
123
+ ...i ? [c("ofCapacity", { percent: m(h / i) })] : [],
124
+ c("scopeCount", { count: h }),
125
+ ...r.carriedIn > 0 ? [c("carriedIn", { count: r.carriedIn })] : []
126
126
  ];
127
127
  return /* @__PURE__ */ w("li", {
128
128
  className: "grid grid-cols-[3.5rem_1fr] gap-x-3 md:grid-cols-[4.5rem_1fr] md:gap-x-4",
@@ -159,10 +159,10 @@ function M({ workspace: e, teamKey: t, cycle: r, capacity: i, first: a, last: s
159
159
  className: "min-w-0",
160
160
  children: [/* @__PURE__ */ C("span", {
161
161
  className: "block truncate text-sm font-medium",
162
- children: r.name ? l("cycleNamed", {
162
+ children: r.name ? c("cycleNamed", {
163
163
  number: r.number,
164
164
  name: r.name
165
- }) : l("cycle", { number: r.number })
165
+ }) : c("cycle", { number: r.number })
166
166
  }), /* @__PURE__ */ C("span", {
167
167
  className: "block text-xs text-muted-foreground",
168
168
  children: u.dayRange(r.startsOn, r.endsOn)
@@ -172,7 +172,7 @@ function M({ workspace: e, teamKey: t, cycle: r, capacity: i, first: a, last: s
172
172
  /* @__PURE__ */ C(_, {
173
173
  variant: p ? "info" : "muted",
174
174
  size: "sm",
175
- children: l(`states.${r.state}`)
175
+ children: c(`states.${r.state}`)
176
176
  }),
177
177
  /* @__PURE__ */ C("span", {
178
178
  className: "flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-muted-foreground tabular-nums",
@@ -1,5 +1,5 @@
1
- import { redirect as e } from "../../../../lib/router.js";
2
- import { rememberSearch as t } from "../../../../lib/listSearch.js";
1
+ import { rememberSearch as e } from "../../../../lib/listSearch.js";
2
+ import { redirect as t } from "../../../../lib/router.js";
3
3
  import { issueSearch as n } from "../../../../lib/issueList.js";
4
4
  import { rememberTeam as r } from "../../../../lib/teamPaths.js";
5
5
  import { createFileRoute as i, lazyFn as a, lazyRouteComponent as o } from "@tanstack/react-router";
@@ -10,8 +10,8 @@ var s = i("/$workspace/teams/$key/issues")({
10
10
  },
11
11
  beforeLoad: ({ params: n, search: i, location: a, preload: o }) => {
12
12
  o || r(n.workspace, n.key);
13
- let s = t(a.pathname, i, o);
14
- if (s) throw e({
13
+ let s = e(a.pathname, i, o);
14
+ if (s) throw t({
15
15
  to: "/$workspace/teams/$key/issues",
16
16
  params: n,
17
17
  search: s,
@@ -1,5 +1,5 @@
1
- import { redirect as e } from "../../../../lib/router.js";
2
- import { rememberSearch as t } from "../../../../lib/listSearch.js";
1
+ import { rememberSearch as e } from "../../../../lib/listSearch.js";
2
+ import { redirect as t } from "../../../../lib/router.js";
3
3
  import { projectSearch as n } from "../../../../lib/projectList.js";
4
4
  import { createFileRoute as r, lazyFn as i, lazyRouteComponent as a } from "@tanstack/react-router";
5
5
  var o = r("/$workspace/teams/$key/projects")({
@@ -8,8 +8,8 @@ var o = r("/$workspace/teams/$key/projects")({
8
8
  return r;
9
9
  },
10
10
  beforeLoad: ({ params: n, search: r, location: i, preload: a }) => {
11
- let o = t(i.pathname, r, a);
12
- if (o) throw e({
11
+ let o = e(i.pathname, r, a);
12
+ if (o) throw t({
13
13
  to: "/$workspace/teams/$key/projects",
14
14
  params: n,
15
15
  search: o,
@@ -3,8 +3,8 @@ import { api as t, unwrap as n } from "../../../../api/client.js";
3
3
  import { useNavigate as r } from "../../../../lib/router.js";
4
4
  import { agentsQuery as i, meQuery as a, teamAccessQuery as o, teamMembersQuery as s, teamsQuery as c } from "../../../../api/queries.js";
5
5
  import { AddIcon as l, ShieldIcon as u, UsersIcon as d } from "../../../../components/icons.js";
6
- import { copyItem as f } from "../../../../lib/menus.js";
7
- import { Route as p } from "./settings.js";
6
+ import { Route as f } from "./settings.js";
7
+ import { copyItem as p } from "../../../../lib/menus.js";
8
8
  import { usePeople as m } from "../../../../lib/people.js";
9
9
  import { usePageTitle as h } from "../../../../lib/pageTitle.js";
10
10
  import { usePermissions as g } from "../../../../lib/roles.js";
@@ -26,7 +26,7 @@ import { Fragment as K, jsx as q, jsxs as J } from "react/jsx-runtime";
26
26
  import { useMutation as Y, useQuery as X, useQueryClient as Z, useSuspenseQuery as Q } from "@tanstack/react-query";
27
27
  // src/routes/$workspace/teams/$key/settings.tsx?tsr-split=component
28
28
  function ee() {
29
- let { workspace: e, key: r } = p.useParams(), { data: i } = Q(c(e)), a = g(e, { team: r }), o = a.has("manage_teams"), s = G("settingsNav"), l = Z(), u = Y({
29
+ let { workspace: e, key: r } = f.useParams(), { data: i } = Q(c(e)), a = g(e, { team: r }), o = a.has("manage_teams"), s = G("settingsNav"), l = Z(), u = Y({
30
30
  mutationFn: async (i) => n(await t.PATCH("/api/v1/workspaces/{workspace}/teams/{key}", {
31
31
  params: { path: {
32
32
  workspace: e,
@@ -666,7 +666,7 @@ function oe({ workspace: e, team: r, isAdmin: i }) {
666
666
  });
667
667
  }
668
668
  function se({ workspace: e, teamKey: i, isAdmin: o }) {
669
- let { data: c } = Q(s(e, i)), { data: u } = Q(a), { members: d, person: p } = m(e), h = Z(), g = H(), _ = r(), [y, b] = U(null), x = G("team"), S = W(), C = G("common"), w = Y({
669
+ let { data: c } = Q(s(e, i)), { data: u } = Q(a), { members: d, person: f } = m(e), h = Z(), g = H(), _ = r(), [y, b] = U(null), x = G("team"), S = W(), C = G("common"), w = Y({
670
670
  mutationFn: async (r) => {
671
671
  for (let { username: a, add: o } of r) {
672
672
  let r = { params: { path: {
@@ -750,7 +750,7 @@ function se({ workspace: e, teamKey: i, isAdmin: o }) {
750
750
  search: { assignee: t }
751
751
  })
752
752
  },
753
- f(C("copyEmail"), p(t).email ?? ""),
753
+ p(C("copyEmail"), f(t).email ?? ""),
754
754
  ...o || t === E ? [V, {
755
755
  label: x(t === E ? "leaveTeam" : "removeFromTeam"),
756
756
  destructive: !0,
@@ -766,14 +766,14 @@ function se({ workspace: e, teamKey: i, isAdmin: o }) {
766
766
  workspace: e,
767
767
  handle: t,
768
768
  children: /* @__PURE__ */ q(D, {
769
- name: p(t).name,
770
- src: p(t).avatarUrl,
769
+ name: f(t).name,
770
+ src: f(t).avatarUrl,
771
771
  size: "md"
772
772
  })
773
773
  }),
774
774
  /* @__PURE__ */ J("span", {
775
775
  className: "flex-1",
776
- children: [p(t).name, t === E && /* @__PURE__ */ J("span", {
776
+ children: [f(t).name, t === E && /* @__PURE__ */ J("span", {
777
777
  className: "text-muted-foreground",
778
778
  children: [" ", x("you")]
779
779
  })]