@parallelworks/tandem-web 0.142.0 → 0.144.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 (58) hide show
  1. package/_virtual/_virtual_i18n/en/common.js +156 -6
  2. package/_virtual/_virtual_i18n/es/common.js +156 -6
  3. package/_virtual/_virtual_i18n/ja/common.js +156 -6
  4. package/_virtual/_virtual_i18n/ko/common.js +156 -6
  5. package/_virtual/_virtual_i18n/zh/common.js +156 -6
  6. package/api/queries.js +85 -74
  7. package/components/AccessGrants.js +6 -6
  8. package/components/ActivityTimeline.js +2 -0
  9. package/components/CodeHostSettings.js +25 -25
  10. package/components/CustomFields.js +349 -0
  11. package/components/DocProperties.js +8 -2
  12. package/components/GitHub.js +22 -22
  13. package/components/IssueBoard.js +48 -43
  14. package/components/IssueEvent.js +2 -0
  15. package/components/IssueFilters.js +210 -122
  16. package/components/IssueImport.js +1 -1
  17. package/components/IssueRow.js +96 -79
  18. package/components/IssueTemplates.js +216 -156
  19. package/components/IssueTypes.js +318 -0
  20. package/components/NewIssueDialog.js +254 -216
  21. package/components/SettingsNav.js +45 -35
  22. package/components/TeamForm.js +49 -35
  23. package/components/TeamRepositories.js +51 -51
  24. package/components/TeamWorkflow.js +8 -8
  25. package/components/Updates.js +8 -8
  26. package/components/icons.js +8 -8
  27. package/lib/boardMove.js +69 -47
  28. package/lib/customFields.js +113 -0
  29. package/lib/issueDisplay.js +27 -12
  30. package/lib/issueList.js +166 -62
  31. package/lib/issueTypes.js +50 -0
  32. package/lib/teamTree.js +24 -0
  33. package/lib/views.js +13 -11
  34. package/package.json +1 -1
  35. package/pages/issues.js +331 -291
  36. package/routeTree.gen.js +186 -174
  37. package/routes/_workspace/agents/index2.js +9 -9
  38. package/routes/_workspace/issues/_identifier2.js +433 -370
  39. package/routes/_workspace/projects/_projectId3.js +213 -201
  40. package/routes/_workspace/settings/audit-log3.js +2 -0
  41. package/routes/_workspace/settings/fields.js +6 -0
  42. package/routes/_workspace/settings/fields2.js +30 -0
  43. package/routes/_workspace/settings/fields3.js +5 -0
  44. package/routes/_workspace/settings/groups2.js +74 -74
  45. package/routes/_workspace/settings/import.js +6 -0
  46. package/routes/_workspace/settings/import2.js +330 -0
  47. package/routes/_workspace/settings/import3.js +4 -0
  48. package/routes/_workspace/settings/labels2.js +33 -33
  49. package/routes/_workspace/settings/members2.js +35 -35
  50. package/routes/_workspace/settings/roles2.js +24 -24
  51. package/routes/_workspace/settings/runners2.js +18 -18
  52. package/routes/_workspace/settings/sessions2.js +9 -9
  53. package/routes/_workspace/settings/slack2.js +8 -8
  54. package/routes/_workspace/settings/sso2.js +50 -50
  55. package/routes/_workspace/settings/tokens2.js +15 -15
  56. package/routes/_workspace/settings/webhooks2.js +42 -42
  57. package/routes/_workspace/teams/_key/settings2.js +138 -76
  58. package/routes/_workspace2.js +320 -318
@@ -1,9 +1,9 @@
1
1
  import { api as e, unwrap as t } from "../api/client.js";
2
2
  import { codeHostAccountsQuery as n, codeHostQuery as r, meQuery as i } from "../api/queries.js";
3
- import { CodeHostIcon as a } from "./icons.js";
4
- import { usePeople as o } from "../lib/people.js";
5
- import { useFormError as s } from "./settings.js";
6
- import { useConfirm as c } from "../lib/confirm.js";
3
+ import { useConfirm as a } from "../lib/confirm.js";
4
+ import { CodeHostIcon as o } from "./icons.js";
5
+ import { usePeople as s } from "../lib/people.js";
6
+ import { useFormError as c } from "./settings.js";
7
7
  import { externalUrl as l } from "../lib/externalUrl.js";
8
8
  import { ConnectionCard as u, ConnectionPanel as d } from "./ConnectionCard.js";
9
9
  import { Avatar as f, Button as p, Card as m, ErrorText as h, Section as g, Select as _, SettingsCard as v, StatusLabel as y } from "@parallelworks/ui";
@@ -13,7 +13,7 @@ import { Fragment as S, jsx as C, jsxs as w } from "react/jsx-runtime";
13
13
  import { useMutation as T, useQueryClient as E, useSuspenseQuery as D } from "@tanstack/react-query";
14
14
  // src/components/CodeHostSettings.tsx
15
15
  function O({ workspace: n }) {
16
- let a = x("code"), { data: o } = D(i), { data: l } = D(r(n)), u = E(), d = s(), { confirm: f, dialog: m } = c(), v = T({
16
+ let o = x("code"), { data: s } = D(i), { data: l } = D(r(n)), u = E(), d = c(), { confirm: f, dialog: m } = a(), v = T({
17
17
  mutationFn: async (r) => t(await e.DELETE("/api/v1/workspaces/{workspace}/code-host/connections/{account}", { params: { path: {
18
18
  workspace: n,
19
19
  account: r
@@ -27,11 +27,11 @@ function O({ workspace: n }) {
27
27
  ] });
28
28
  }
29
29
  }), y = (e) => f({
30
- title: a("disconnectConfirm", { account: e }),
31
- description: a("disconnectDetail"),
32
- confirmLabel: a("disconnect"),
30
+ title: o("disconnectConfirm", { account: e }),
31
+ description: o("disconnectDetail"),
32
+ confirmLabel: o("disconnect"),
33
33
  onConfirm: () => v.mutateAsync(e)
34
- }), [S, O] = b(""), k = l.connections.filter((e) => e.connectedBy === o?.user.username), A = k[0];
34
+ }), [S, O] = b(""), k = l.connections.filter((e) => e.connectedBy === s?.user.username), A = k[0];
35
35
  if (!A) return null;
36
36
  let j = k.some((e) => e.account === S) ? S : A.account;
37
37
  return /* @__PURE__ */ w(g, {
@@ -39,8 +39,8 @@ function O({ workspace: n }) {
39
39
  tone: "error",
40
40
  collapsible: !1,
41
41
  headingLevel: 2,
42
- title: a("dangerZone"),
43
- description: a("disconnectDetail"),
42
+ title: o("dangerZone"),
43
+ description: o("disconnectDetail"),
44
44
  className: "mt-10",
45
45
  children: [
46
46
  /* @__PURE__ */ w("div", {
@@ -48,7 +48,7 @@ function O({ workspace: n }) {
48
48
  children: [/* @__PURE__ */ C("div", {
49
49
  className: "w-56 max-w-full",
50
50
  children: /* @__PURE__ */ C(_, {
51
- "aria-label": a("disconnectWhich"),
51
+ "aria-label": o("disconnectWhich"),
52
52
  value: j,
53
53
  onValueChange: (e) => e && O(e),
54
54
  items: k.map((e) => ({
@@ -60,7 +60,7 @@ function O({ workspace: n }) {
60
60
  variant: "danger",
61
61
  onClick: () => y(j),
62
62
  loading: v.isPending,
63
- children: a("disconnectAccount", { account: j })
63
+ children: o("disconnectAccount", { account: j })
64
64
  })]
65
65
  }),
66
66
  /* @__PURE__ */ C(h, {
@@ -72,8 +72,8 @@ function O({ workspace: n }) {
72
72
  ]
73
73
  });
74
74
  }
75
- function k({ workspace: n, isAdmin: i, result: c }) {
76
- let m = x("code"), { data: h } = D(r(n)), { person: g } = o(n), _ = s(), b = T({
75
+ function k({ workspace: n, isAdmin: i, result: a }) {
76
+ let m = x("code"), { data: h } = D(r(n)), { person: g } = s(n), _ = c(), b = T({
77
77
  mutationFn: async () => t(await e.POST("/api/v1/workspaces/{workspace}/code-host/connect", { params: { path: { workspace: n } } })),
78
78
  onMutate: _.clear,
79
79
  onSuccess: ({ url: e }) => {
@@ -86,13 +86,13 @@ function k({ workspace: n, isAdmin: i, result: c }) {
86
86
  className: "px-3 py-2 text-sm text-muted-foreground",
87
87
  children: m("notConfigured")
88
88
  }) }) : /* @__PURE__ */ w(S, { children: [
89
- c && c !== "choose" && /* @__PURE__ */ C("p", {
89
+ a && a !== "choose" && /* @__PURE__ */ C("p", {
90
90
  role: "status",
91
- className: `mb-3 rounded-md bg-muted px-3 py-2 text-sm ${c === "failed" ? "text-danger" : ""}`,
92
- children: m(`result.${c}`)
91
+ className: `mb-3 rounded-md bg-muted px-3 py-2 text-sm ${a === "failed" ? "text-danger" : ""}`,
92
+ children: m(`result.${a}`)
93
93
  }),
94
94
  /* @__PURE__ */ C(u, {
95
- icon: /* @__PURE__ */ C(a, { className: "size-7" }),
95
+ icon: /* @__PURE__ */ C(o, { className: "size-7" }),
96
96
  name: m("provider"),
97
97
  status: h.connections.length > 0 ? m("linkedCount", { count: h.connections.length }) : m("description"),
98
98
  error: _.error,
@@ -129,12 +129,12 @@ function k({ workspace: n, isAdmin: i, result: c }) {
129
129
  }),
130
130
  i && /* @__PURE__ */ C(A, {
131
131
  workspace: n,
132
- chosen: c === "choose"
132
+ chosen: a === "choose"
133
133
  })
134
134
  ] });
135
135
  }
136
136
  function A({ workspace: i, chosen: a }) {
137
- let o = x("code"), { data: c } = D(n(i)), u = E(), d = s(), f = T({
137
+ let o = x("code"), { data: s } = D(n(i)), u = E(), d = c(), f = T({
138
138
  mutationFn: async (n) => t(await e.POST("/api/v1/workspaces/{workspace}/code-host/connections", {
139
139
  params: { path: { workspace: i } },
140
140
  body: { id: n }
@@ -156,7 +156,7 @@ function A({ workspace: i, chosen: a }) {
156
156
  onMutate: d.clear,
157
157
  onError: d.set
158
158
  });
159
- return !a && c.length === 0 ? null : /* @__PURE__ */ w(m, {
159
+ return !a && s.length === 0 ? null : /* @__PURE__ */ w(m, {
160
160
  size: "fill",
161
161
  padding: "sm",
162
162
  className: "mt-4",
@@ -167,11 +167,11 @@ function A({ workspace: i, chosen: a }) {
167
167
  }),
168
168
  /* @__PURE__ */ C("p", {
169
169
  className: "mt-0.5 text-sm text-muted-foreground",
170
- children: c.length > 0 ? o("chooseDescription") : o("noAccounts")
170
+ children: s.length > 0 ? o("chooseDescription") : o("noAccounts")
171
171
  }),
172
- c.length > 0 && /* @__PURE__ */ C("ul", {
172
+ s.length > 0 && /* @__PURE__ */ C("ul", {
173
173
  className: "mt-3 divide-y divide-border rounded-md border border-border",
174
- children: c.map((e) => /* @__PURE__ */ w("li", {
174
+ children: s.map((e) => /* @__PURE__ */ w("li", {
175
175
  className: "px-3 py-2 text-sm",
176
176
  children: [/* @__PURE__ */ w("div", {
177
177
  className: "flex items-center gap-3",
@@ -0,0 +1,349 @@
1
+ import { issueQuery as e } from "../api/queries.js";
2
+ import { useConfirm as t } from "../lib/confirm.js";
3
+ import { customFieldsQuery as n, fieldKinds as r, fieldsFor as i, hasValue as a, setIssueFields as o, setProjectFields as s, useCustomFieldActions as c } from "../lib/customFields.js";
4
+ import { issueTypesQuery as l, typeShows as u } from "../lib/issueTypes.js";
5
+ import { AddIcon as d } from "./icons.js";
6
+ import { invalidateIssueViews as f } from "../api/mutations.js";
7
+ import { PropertyField as p, usePropertyText as m } from "./DocProperties.js";
8
+ import { Button as h, Checkbox as g, ErrorText as _, IconButton as v, Input as y, Select as b, SettingsCard as x, Textarea as S, menuDivider as C, useOpenMenu as w } from "@parallelworks/ui";
9
+ import { useId as T, useState as E } from "react";
10
+ import { useErrorMessage as D } from "@parallelworks/problem/react";
11
+ import { useTranslations as O } from "use-intl";
12
+ import { Fragment as k, jsx as A, jsxs as j } from "react/jsx-runtime";
13
+ import { useMutation as M, useQuery as N, useQueryClient as P } from "@tanstack/react-query";
14
+ // src/components/CustomFields.tsx
15
+ function F(e) {
16
+ let t = m(e);
17
+ return (e, n) => t(e, n);
18
+ }
19
+ function I({ workspace: t, issue: r, label: a }) {
20
+ let s = D(), c = P(), { data: d } = N(n(t)), { data: m } = N(l(t)), h = m?.find((e) => e.id === r.type?.id), g = i(d, "issue", r.teamId).filter((e) => u(h, e.id)), v = e(t, r.identifier).queryKey, y = M({
21
+ mutationFn: (e) => o(t, r.identifier, e),
22
+ onMutate: async (e) => {
23
+ await c.cancelQueries({ queryKey: v });
24
+ let t = c.getQueryData(v);
25
+ return t && c.setQueryData(v, {
26
+ ...t,
27
+ fields: {
28
+ ...t.fields,
29
+ ...e
30
+ }
31
+ }), { previous: t };
32
+ },
33
+ onError: (e, t, n) => {
34
+ n?.previous && c.setQueryData(v, n.previous);
35
+ },
36
+ onSuccess: (e) => c.setQueryData(v, e),
37
+ onSettled: () => f(c, t, r.identifier)
38
+ });
39
+ return g.length === 0 ? null : /* @__PURE__ */ j(k, { children: [g.map((e) => a(e.name, /* @__PURE__ */ A("div", {
40
+ className: "px-2",
41
+ children: /* @__PURE__ */ A(p, {
42
+ workspace: t,
43
+ property: e,
44
+ value: r.fields[e.id],
45
+ editable: !0,
46
+ onChange: (t) => y.mutate({ [e.id]: t })
47
+ })
48
+ }), e.id)), y.error && /* @__PURE__ */ A(_, {
49
+ className: "px-2",
50
+ children: s(y.error)
51
+ })] });
52
+ }
53
+ function L({ workspace: e, project: t, editable: r, onChange: a }) {
54
+ let o = O("customFields"), c = D(), { data: l } = N(n(e)), u = i(l, "project"), d = M({
55
+ mutationFn: (n) => s(e, t.id, n),
56
+ onSuccess: a
57
+ });
58
+ return u.length === 0 ? null : /* @__PURE__ */ j("section", {
59
+ "aria-label": o("title"),
60
+ className: "max-w-xl space-y-0.5 text-sm",
61
+ children: [u.map((n) => /* @__PURE__ */ j("div", {
62
+ className: "flex min-h-8 items-center gap-2",
63
+ children: [/* @__PURE__ */ A("span", {
64
+ className: "w-36 shrink-0 truncate text-muted-foreground",
65
+ children: n.name
66
+ }), /* @__PURE__ */ A("div", {
67
+ className: "min-w-0 flex-1",
68
+ children: /* @__PURE__ */ A(p, {
69
+ workspace: e,
70
+ property: n,
71
+ value: t.fields[n.id],
72
+ editable: r,
73
+ onChange: (e) => d.mutate({ [n.id]: e })
74
+ })
75
+ })]
76
+ }, n.id)), d.error && /* @__PURE__ */ A(_, { children: c(d.error) })]
77
+ });
78
+ }
79
+ function R({ workspace: e, teamId: t, typeId: r, values: o, onChange: s }) {
80
+ let c = O("customFields"), { data: d } = N(n(e)), { data: f } = N(l(e)), m = f?.find((e) => e.id === r), h = i(d, "issue", t).filter((e) => u(m, e.id)).map((e) => m?.requiredFieldIds.includes(e.id) ? {
81
+ ...e,
82
+ required: !0
83
+ } : e).filter((e) => e.required || a(o[e.id]));
84
+ return h.length === 0 ? null : /* @__PURE__ */ j("fieldset", {
85
+ className: "space-y-0.5 text-sm",
86
+ children: [/* @__PURE__ */ A("legend", {
87
+ className: "sr-only",
88
+ children: c("title")
89
+ }), h.map((t) => /* @__PURE__ */ j("div", {
90
+ className: "flex min-h-8 items-center gap-2",
91
+ children: [/* @__PURE__ */ j("span", {
92
+ className: "w-36 shrink-0 truncate text-muted-foreground",
93
+ children: [t.name, t.required && /* @__PURE__ */ j(k, { children: [/* @__PURE__ */ j("span", {
94
+ "aria-hidden": !0,
95
+ className: "text-destructive",
96
+ children: [" ", "*"]
97
+ }), /* @__PURE__ */ A("span", {
98
+ className: "sr-only",
99
+ children: c("required")
100
+ })] })]
101
+ }), /* @__PURE__ */ A("div", {
102
+ className: "min-w-0 flex-1",
103
+ children: /* @__PURE__ */ A(p, {
104
+ workspace: e,
105
+ property: t,
106
+ value: o[t.id],
107
+ editable: !0,
108
+ onChange: (e) => s({
109
+ ...o,
110
+ [t.id]: e
111
+ })
112
+ })
113
+ })]
114
+ }, t.id))]
115
+ });
116
+ }
117
+ function z({ workspace: e, target: t, team: r }) {
118
+ let i = O("customFields"), { data: a } = N(n(e)), o = (a ?? []).filter((e) => e.target === t && (r ? e.teamId === r.id : !e.teamId)).sort((e, t) => e.position - t.position), [s, c] = E(!1);
119
+ return /* @__PURE__ */ j(x, {
120
+ title: i(t === "issue" ? "issueFields" : "projectFields"),
121
+ description: i(r ? "teamFieldsHelp" : t === "issue" ? "issueFieldsHelp" : "projectFieldsHelp"),
122
+ action: /* @__PURE__ */ A(h, {
123
+ size: "sm",
124
+ icon: /* @__PURE__ */ A(d, {}),
125
+ onClick: () => c(!0),
126
+ children: i("add")
127
+ }),
128
+ children: [s && /* @__PURE__ */ A(V, {
129
+ workspace: e,
130
+ target: t,
131
+ team: r?.key,
132
+ onDone: () => c(!1)
133
+ }), o.length === 0 && !s ? /* @__PURE__ */ A("p", {
134
+ className: "px-3 py-3 text-sm text-muted-foreground",
135
+ children: i("none")
136
+ }) : /* @__PURE__ */ A("ul", {
137
+ className: "divide-y divide-border",
138
+ children: o.map((t, n) => /* @__PURE__ */ A(B, {
139
+ workspace: e,
140
+ field: t,
141
+ before: o[n - 1],
142
+ after: o[n + 1]
143
+ }, t.id))
144
+ })]
145
+ });
146
+ }
147
+ function B({ workspace: e, field: n, before: r, after: i }) {
148
+ let a = O("customFields"), o = c(e), s = w(), { confirm: l, dialog: u } = t(), [d, f] = E(!1), p = (e, t) => e && o.update.mutate({
149
+ id: n.id,
150
+ position: t ? (e.position + t.position) / 2 : e.position + (e === i ? 1 : -1)
151
+ }), m = () => l({
152
+ title: a("deleteTitle", { name: n.name }),
153
+ description: a("deleteDescription", { count: n.values }),
154
+ confirmLabel: a("delete"),
155
+ destructive: !0,
156
+ onConfirm: () => o.remove.mutateAsync(n.id)
157
+ }), h = () => [
158
+ {
159
+ label: a("edit"),
160
+ onClick: () => f(!0)
161
+ },
162
+ ...r ? [{
163
+ label: a("moveUp"),
164
+ onClick: () => p(r, void 0)
165
+ }] : [],
166
+ ...i ? [{
167
+ label: a("moveDown"),
168
+ onClick: () => p(i, void 0)
169
+ }] : [],
170
+ {
171
+ label: n.archivedAt ? a("restore") : a("archive"),
172
+ onClick: () => o.update.mutate({
173
+ id: n.id,
174
+ archived: !n.archivedAt
175
+ })
176
+ },
177
+ C,
178
+ {
179
+ label: a("delete"),
180
+ destructive: !0,
181
+ onClick: m
182
+ }
183
+ ];
184
+ return d ? /* @__PURE__ */ A("li", {
185
+ className: "p-2",
186
+ children: /* @__PURE__ */ A(V, {
187
+ workspace: e,
188
+ target: n.target,
189
+ field: n,
190
+ onDone: () => f(!1)
191
+ })
192
+ }) : /* @__PURE__ */ j("li", {
193
+ className: "flex min-h-10 items-center gap-3 px-3 py-1.5",
194
+ onContextMenu: (e) => s(e, h()),
195
+ children: [
196
+ /* @__PURE__ */ j("div", {
197
+ className: "min-w-0 flex-1",
198
+ children: [/* @__PURE__ */ j("p", {
199
+ className: `truncate text-sm ${n.archivedAt ? "text-muted-foreground" : ""}`,
200
+ children: [n.name, n.required && /* @__PURE__ */ A("span", {
201
+ className: "ml-2 text-xs text-muted-foreground",
202
+ children: a("required")
203
+ })]
204
+ }), n.description && /* @__PURE__ */ A("p", {
205
+ className: "truncate text-xs text-muted-foreground",
206
+ children: n.description
207
+ })]
208
+ }),
209
+ n.archivedAt && /* @__PURE__ */ A("span", {
210
+ className: "shrink-0 text-xs text-muted-foreground",
211
+ children: a("archived")
212
+ }),
213
+ /* @__PURE__ */ A("span", {
214
+ className: "shrink-0 text-xs text-muted-foreground",
215
+ children: a(`kinds.${n.kind}`)
216
+ }),
217
+ /* @__PURE__ */ A("span", {
218
+ className: "w-20 shrink-0 text-right text-xs tabular-nums text-muted-foreground",
219
+ children: a("values", { count: n.values })
220
+ }),
221
+ /* @__PURE__ */ A(v, {
222
+ variant: "ghost",
223
+ size: "sm",
224
+ label: a("actions", { name: n.name }),
225
+ icon: /* @__PURE__ */ A("span", {
226
+ "aria-hidden": !0,
227
+ children: "⋯"
228
+ }),
229
+ onClick: (e) => s(e, h())
230
+ }),
231
+ u
232
+ ]
233
+ });
234
+ }
235
+ function V({ workspace: e, target: t, team: n, field: i, onDone: a }) {
236
+ let o = O("customFields"), s = D(), l = c(e), [u, d] = E(i?.name ?? ""), [f, p] = E(i?.description ?? ""), [m, v] = E(i?.kind ?? "text"), [x, C] = E(i?.required ?? !1), w = T(), [k, M] = E((i?.options ?? []).map((e) => e.name).join("\n")), N = m === "select" || m === "multi_select", P = () => k.split("\n").map((e) => e.trim()).filter(Boolean).map((e) => {
237
+ let t = i?.options.find((t) => t.name === e)?.id;
238
+ return {
239
+ name: e,
240
+ ...t && { id: t }
241
+ };
242
+ }), F = i ? l.update : l.create;
243
+ return /* @__PURE__ */ j("form", {
244
+ onSubmit: (e) => {
245
+ e.preventDefault(), i ? l.update.mutate({
246
+ id: i.id,
247
+ name: u,
248
+ description: f,
249
+ ...t === "issue" && { required: x },
250
+ ...N && { options: P() }
251
+ }, { onSuccess: a }) : l.create.mutate({
252
+ target: t,
253
+ ...n && { team: n },
254
+ name: u,
255
+ description: f,
256
+ kind: m,
257
+ ...t === "issue" && { required: x },
258
+ ...N && { options: P() }
259
+ }, { onSuccess: a });
260
+ },
261
+ className: "space-y-3 rounded-md border border-border p-3 text-sm",
262
+ children: [
263
+ /* @__PURE__ */ j("div", {
264
+ className: "grid gap-3 sm:grid-cols-2",
265
+ children: [/* @__PURE__ */ j("label", {
266
+ className: "block text-xs font-medium text-muted-foreground",
267
+ children: [o("name"), /* @__PURE__ */ A(y, {
268
+ value: u,
269
+ onChange: (e) => d(e.target.value),
270
+ required: !0,
271
+ maxLength: 60,
272
+ className: "mt-1",
273
+ autoFocus: !0
274
+ })]
275
+ }), /* @__PURE__ */ j("div", {
276
+ className: "text-xs font-medium text-muted-foreground",
277
+ children: [o("kind"), /* @__PURE__ */ A("div", {
278
+ className: "mt-1",
279
+ children: /* @__PURE__ */ A(b, {
280
+ value: m,
281
+ items: r.map((e) => ({
282
+ value: e,
283
+ label: o(`kinds.${e}`)
284
+ })),
285
+ onValueChange: v,
286
+ "aria-label": o("kind"),
287
+ width: "fill",
288
+ disabled: !!i
289
+ })
290
+ })]
291
+ })]
292
+ }),
293
+ /* @__PURE__ */ j("label", {
294
+ className: "block text-xs font-medium text-muted-foreground",
295
+ children: [o("description"), /* @__PURE__ */ A(y, {
296
+ value: f,
297
+ onChange: (e) => p(e.target.value),
298
+ maxLength: 500,
299
+ className: "mt-1"
300
+ })]
301
+ }),
302
+ N && /* @__PURE__ */ j("label", {
303
+ className: "block text-xs font-medium text-muted-foreground",
304
+ children: [
305
+ o("options"),
306
+ /* @__PURE__ */ A(S, {
307
+ value: k,
308
+ onChange: (e) => M(e.target.value),
309
+ rows: 4,
310
+ className: "mt-1"
311
+ }),
312
+ /* @__PURE__ */ A("span", {
313
+ className: "mt-1 block font-normal",
314
+ children: o("optionsHint")
315
+ })
316
+ ]
317
+ }),
318
+ t === "issue" && /* @__PURE__ */ j("div", {
319
+ className: "flex items-center gap-2 text-sm",
320
+ children: [/* @__PURE__ */ A(g, {
321
+ id: w,
322
+ checked: x,
323
+ onCheckedChange: (e) => C(e === !0)
324
+ }), /* @__PURE__ */ A("label", {
325
+ htmlFor: w,
326
+ children: o("requiredLabel")
327
+ })]
328
+ }),
329
+ F.error && /* @__PURE__ */ A(_, { children: s(F.error) }),
330
+ /* @__PURE__ */ j("div", {
331
+ className: "flex justify-end gap-2",
332
+ children: [/* @__PURE__ */ A(h, {
333
+ size: "sm",
334
+ variant: "ghost",
335
+ onClick: a,
336
+ children: o("cancel")
337
+ }), /* @__PURE__ */ A(h, {
338
+ type: "submit",
339
+ size: "sm",
340
+ variant: "primary",
341
+ loading: F.isPending,
342
+ disabled: !u.trim(),
343
+ children: o(i ? "save" : "add")
344
+ })]
345
+ })
346
+ ]
347
+ });
348
+ }
349
+ export { z as FieldSettings, I as IssueFields, R as NewIssueFields, L as ProjectFields, F as useFieldText };
@@ -116,6 +116,12 @@ function O({ workspace: e, property: n, value: r, editable: i, onChange: a }) {
116
116
  },
117
117
  className: "text-primary hover:underline",
118
118
  children: t
119
+ }) : n.kind === "url" && t ? /* @__PURE__ */ S("a", {
120
+ href: t,
121
+ target: "_blank",
122
+ rel: "noopener noreferrer",
123
+ className: "truncate text-primary hover:underline",
124
+ children: t
119
125
  }) : /* @__PURE__ */ S("span", {
120
126
  className: t ? "" : "text-muted-foreground",
121
127
  children: t || u
@@ -189,12 +195,12 @@ function k({ property: e, value: t, onChange: n }) {
189
195
  a !== i && (a.trim() ? n(e.kind === "number" ? Number(a) : a) : n(null));
190
196
  };
191
197
  return /* @__PURE__ */ S(d, {
192
- type: e.kind === "number" ? "number" : "text",
198
+ type: e.kind === "number" ? "number" : e.kind === "url" ? "url" : "text",
193
199
  value: a,
194
200
  onChange: (e) => o(e.target.value),
195
201
  onBlur: s,
196
202
  onKeyDown: (e) => e.key === "Enter" && s(),
197
- placeholder: r(e.kind === "issue" ? "issueExample" : "empty"),
203
+ placeholder: r(e.kind === "issue" ? "issueExample" : e.kind === "url" ? "urlExample" : "empty"),
198
204
  "aria-label": e.name,
199
205
  className: "h-7 border-transparent px-1.5 shadow-none hover:border-border"
200
206
  });
@@ -1,9 +1,9 @@
1
1
  import { basePath as e } from "../lib/base.js";
2
2
  import { api as t, unwrap as n } from "../api/client.js";
3
3
  import { githubAccountQuery as r, githubSettingsQuery as i, teamsQuery as a } from "../api/queries.js";
4
- import { CheckIcon as o, CodeHostIcon as s } from "./icons.js";
5
- import { cardList as c, useFormError as l } from "./settings.js";
6
- import { useConfirm as u } from "../lib/confirm.js";
4
+ import { useConfirm as o } from "../lib/confirm.js";
5
+ import { CheckIcon as s, CodeHostIcon as c } from "./icons.js";
6
+ import { cardList as l, useFormError as u } from "./settings.js";
7
7
  import { ConnectionCard as d } from "./ConnectionCard.js";
8
8
  import { TeamName as f } from "./TeamName.js";
9
9
  import { Button as p, ErrorText as m, ProgressBar as h, Select as g, SettingsCard as _, StatusLabel as v, Tooltip as y, buttonClasses as b } from "@parallelworks/ui";
@@ -44,15 +44,15 @@ async function I(e) {
44
44
  }
45
45
  var L = () => window.location.pathname.slice(e.length) || "/";
46
46
  function R() {
47
- let { data: e } = M(r), i = T("github"), a = j(), o = l(), c = P(), f = k({
47
+ let { data: e } = M(r), i = T("github"), a = j(), s = u(), l = P(), f = k({
48
48
  mutationFn: () => I(async () => n(await t.POST("/api/v1/me/github", { body: { returnTo: L() } }))),
49
- onMutate: o.clear,
50
- onError: o.set
49
+ onMutate: s.clear,
50
+ onError: s.set
51
51
  }), m = k({
52
52
  mutationFn: async () => n(await t.DELETE("/api/v1/me/github")),
53
- onMutate: o.clear,
53
+ onMutate: s.clear,
54
54
  onSettled: () => a.invalidateQueries({ queryKey: r.queryKey })
55
- }), { confirm: h, dialog: g } = u();
55
+ }), { confirm: h, dialog: g } = o();
56
56
  if (!e.enabled) return null;
57
57
  let _ = e.keepsTokens ? i("accountDescriptionBothWays") : i("accountDescription"), y = e.login ? /* @__PURE__ */ D(z, {
58
58
  login: e.login,
@@ -62,7 +62,7 @@ function R() {
62
62
  children: i("notLinkedLabel")
63
63
  });
64
64
  if (e.linkedByHost) return /* @__PURE__ */ D(d, {
65
- icon: /* @__PURE__ */ D(s, { className: "size-7" }),
65
+ icon: /* @__PURE__ */ D(c, { className: "size-7" }),
66
66
  name: i("accountTitle"),
67
67
  status: /* @__PURE__ */ O(E, { children: [/* @__PURE__ */ D("span", {
68
68
  className: "block",
@@ -79,10 +79,10 @@ function R() {
79
79
  });
80
80
  let S = !!e.login && e.keepsTokens && !e.actsAsYou;
81
81
  return /* @__PURE__ */ O(E, { children: [/* @__PURE__ */ D(d, {
82
- icon: /* @__PURE__ */ D(s, { className: "size-7" }),
82
+ icon: /* @__PURE__ */ D(c, { className: "size-7" }),
83
83
  name: i("accountTitle"),
84
84
  status: y,
85
- error: o.error,
85
+ error: s.error,
86
86
  action: e.login ? /* @__PURE__ */ D(p, {
87
87
  variant: "outline",
88
88
  type: "button",
@@ -101,7 +101,7 @@ function R() {
101
101
  onClick: () => f.mutate(),
102
102
  children: i("link")
103
103
  })] }),
104
- children: (c || S) && /* @__PURE__ */ O(E, { children: [/* @__PURE__ */ D(F, { outcome: c }), S && /* @__PURE__ */ O("div", {
104
+ children: (l || S) && /* @__PURE__ */ O(E, { children: [/* @__PURE__ */ D(F, { outcome: l }), S && /* @__PURE__ */ O("div", {
105
105
  className: "flex items-center gap-3 rounded-lg border border-border px-4 py-3 text-sm",
106
106
  children: [/* @__PURE__ */ D("p", {
107
107
  className: "min-w-0 flex-1",
@@ -134,7 +134,7 @@ function B({ workspace: e }) {
134
134
  title: r("settingsTitle"),
135
135
  description: r("settingsDescription"),
136
136
  children: /* @__PURE__ */ O("ul", {
137
- className: c,
137
+ className: l,
138
138
  children: [t.repositories.map((t) => {
139
139
  let i = n.find((e) => e.key === t.team)?.name ?? t.team;
140
140
  return /* @__PURE__ */ D("li", {
@@ -167,8 +167,8 @@ function B({ workspace: e }) {
167
167
  }) : null;
168
168
  }
169
169
  var V = "", H = 2e3;
170
- function U({ workspace: e, repository: r, teamName: s, children: c }) {
171
- let d = T("github"), h = j(), _ = l(), { confirm: v, dialog: y } = u(), { data: b } = A(i(e)), { data: C = [] } = A(a(e)), w = (e) => C.find((t) => t.key === e) ?? {
170
+ function U({ workspace: e, repository: r, teamName: c, children: l }) {
171
+ let d = T("github"), h = j(), _ = u(), { confirm: v, dialog: y } = o(), { data: b } = A(i(e)), { data: C = [] } = A(a(e)), w = (e) => C.find((t) => t.key === e) ?? {
172
172
  icon: "",
173
173
  name: e
174
174
  }, M = (e) => w(e).name, N = (e) => () => /* @__PURE__ */ D(f, { team: w(e) }), P = (b?.repositories ?? []).filter((e) => e.id === r.id && e.team !== r.team), F = P.find((e) => e.syncMode), [I, L] = S(!1);
@@ -224,12 +224,12 @@ function U({ workspace: e, repository: r, teamName: s, children: c }) {
224
224
  repository: r.fullName
225
225
  }),
226
226
  description: /* @__PURE__ */ O(E, { children: [/* @__PURE__ */ D("p", { children: d.rich("takeOverIntro", {
227
- teamName: s,
227
+ teamName: c,
228
228
  team: N(r.team)
229
229
  }) }), /* @__PURE__ */ O("ul", {
230
230
  className: "mt-2 list-disc space-y-1 pl-5",
231
231
  children: [/* @__PURE__ */ D("li", { children: d.rich("takeOverNew", {
232
- teamName: s,
232
+ teamName: c,
233
233
  team: N(r.team)
234
234
  }) }), F.imported > 0 && /* @__PURE__ */ D("li", { children: d.rich("takeOverKeeps", {
235
235
  fromName: t,
@@ -237,7 +237,7 @@ function U({ workspace: e, repository: r, teamName: s, children: c }) {
237
237
  count: F.imported
238
238
  }) })]
239
239
  })] }),
240
- confirmLabel: d("takeOver", { team: s }),
240
+ confirmLabel: d("takeOver", { team: c }),
241
241
  destructive: !1,
242
242
  onConfirm: () => B.mutateAsync({
243
243
  syncMode: e,
@@ -255,12 +255,12 @@ function U({ workspace: e, repository: r, teamName: s, children: c }) {
255
255
  /* @__PURE__ */ O("div", {
256
256
  className: "flex flex-wrap items-center gap-2",
257
257
  children: [
258
- c,
258
+ l,
259
259
  I && /* @__PURE__ */ O("span", {
260
260
  role: "status",
261
261
  className: "flex items-center gap-1 text-xs text-muted-foreground",
262
262
  children: [
263
- /* @__PURE__ */ D(o, { className: "size-3.5" }),
263
+ /* @__PURE__ */ D(s, { className: "size-3.5" }),
264
264
  " ",
265
265
  d("saved")
266
266
  ]
@@ -268,7 +268,7 @@ function U({ workspace: e, repository: r, teamName: s, children: c }) {
268
268
  /* @__PURE__ */ D(g, {
269
269
  "aria-label": d("modeFor", {
270
270
  repository: r.fullName,
271
- team: s
271
+ team: c
272
272
  }),
273
273
  value: K,
274
274
  disabled: B.isPending,
@@ -411,7 +411,7 @@ function q({ links: e }) {
411
411
  target: "_blank",
412
412
  rel: "noreferrer",
413
413
  className: "inline-flex h-6 min-w-0 items-center gap-1.5 rounded-md border border-border px-1.5 text-xs text-muted-foreground hover:bg-muted hover:text-foreground",
414
- children: [/* @__PURE__ */ D(s, { className: "size-3.5" }), /* @__PURE__ */ D("span", {
414
+ children: [/* @__PURE__ */ D(c, { className: "size-3.5" }), /* @__PURE__ */ D("span", {
415
415
  className: "truncate",
416
416
  children: J(e.url)
417
417
  })]