@gaud_erp/paperclip-github-manager 0.3.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/README.md +69 -0
- package/dist/manifest.js +118 -0
- package/dist/manifest.js.map +7 -0
- package/dist/ui/index.js +627 -0
- package/dist/ui/index.js.map +7 -0
- package/dist/worker.js +9441 -0
- package/dist/worker.js.map +7 -0
- package/package.json +55 -0
package/dist/ui/index.js
ADDED
|
@@ -0,0 +1,627 @@
|
|
|
1
|
+
// src/ui/index.tsx
|
|
2
|
+
import { useMemo, useState } from "react";
|
|
3
|
+
import {
|
|
4
|
+
useHostContext,
|
|
5
|
+
useHostLocation,
|
|
6
|
+
useHostNavigation,
|
|
7
|
+
usePluginAction,
|
|
8
|
+
usePluginData
|
|
9
|
+
} from "@paperclipai/plugin-sdk/ui";
|
|
10
|
+
|
|
11
|
+
// src/constants.ts
|
|
12
|
+
var PATHS = {
|
|
13
|
+
repos: "/github",
|
|
14
|
+
settings: "/github-settings",
|
|
15
|
+
pullRequests: "/github-pull-requests",
|
|
16
|
+
companySecrets: "/company/settings"
|
|
17
|
+
};
|
|
18
|
+
var GITHUB_TOKEN_SECRET_KEY = "github_token";
|
|
19
|
+
|
|
20
|
+
// src/ui/index.tsx
|
|
21
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
22
|
+
var panelStyle = {
|
|
23
|
+
border: "1px solid rgba(255,255,255,0.12)",
|
|
24
|
+
borderRadius: 8,
|
|
25
|
+
padding: "1rem",
|
|
26
|
+
display: "grid",
|
|
27
|
+
gap: "0.75rem"
|
|
28
|
+
};
|
|
29
|
+
var buttonStyle = {
|
|
30
|
+
padding: "0.4rem 0.75rem",
|
|
31
|
+
borderRadius: 6,
|
|
32
|
+
border: "1px solid rgba(255,255,255,0.2)",
|
|
33
|
+
background: "rgba(255,255,255,0.06)",
|
|
34
|
+
cursor: "pointer"
|
|
35
|
+
};
|
|
36
|
+
var sidebarLinkClass = "flex w-full items-center gap-2.5 px-3 py-2 text-[13px] font-medium transition-colors no-underline";
|
|
37
|
+
var sidebarLinkActiveClass = "bg-accent text-foreground";
|
|
38
|
+
var sidebarLinkIdleClass = "text-foreground/80 hover:bg-accent/50 hover:text-foreground";
|
|
39
|
+
var NAV_ITEMS = [
|
|
40
|
+
{ path: PATHS.settings, label: "Configura\xE7\xF5es" },
|
|
41
|
+
{ path: PATHS.repos, label: "Reposit\xF3rios" },
|
|
42
|
+
{ path: PATHS.pullRequests, label: "Pull requests" }
|
|
43
|
+
];
|
|
44
|
+
function useGithubCompany() {
|
|
45
|
+
const { companyId } = useHostContext();
|
|
46
|
+
const companyParams = useMemo(
|
|
47
|
+
() => companyId ? { companyId } : void 0,
|
|
48
|
+
[companyId]
|
|
49
|
+
);
|
|
50
|
+
return { companyId, companyParams };
|
|
51
|
+
}
|
|
52
|
+
function isPathActive(pathname, href) {
|
|
53
|
+
return pathname === href || pathname.startsWith(`${href}/`);
|
|
54
|
+
}
|
|
55
|
+
function GitHubModuleNav() {
|
|
56
|
+
const nav = useHostNavigation();
|
|
57
|
+
const { pathname } = useHostLocation();
|
|
58
|
+
return /* @__PURE__ */ jsx("nav", { style: { display: "flex", flexDirection: "column", gap: "0.125rem" }, children: NAV_ITEMS.map((item) => {
|
|
59
|
+
const href = nav.resolveHref(item.path);
|
|
60
|
+
const active = isPathActive(pathname, href);
|
|
61
|
+
return /* @__PURE__ */ jsx(
|
|
62
|
+
"a",
|
|
63
|
+
{
|
|
64
|
+
...nav.linkProps(item.path),
|
|
65
|
+
className: `${sidebarLinkClass} ${active ? sidebarLinkActiveClass : sidebarLinkIdleClass}`,
|
|
66
|
+
children: /* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: item.label })
|
|
67
|
+
},
|
|
68
|
+
item.path
|
|
69
|
+
);
|
|
70
|
+
}) });
|
|
71
|
+
}
|
|
72
|
+
function GitHubSidebarModule(_props) {
|
|
73
|
+
return /* @__PURE__ */ jsxs("div", { style: { display: "grid", gap: "0.25rem" }, children: [
|
|
74
|
+
/* @__PURE__ */ jsx(
|
|
75
|
+
"div",
|
|
76
|
+
{
|
|
77
|
+
style: {
|
|
78
|
+
padding: "0.25rem 0.75rem",
|
|
79
|
+
fontSize: "0.7rem",
|
|
80
|
+
fontWeight: 600,
|
|
81
|
+
letterSpacing: "0.04em",
|
|
82
|
+
textTransform: "uppercase",
|
|
83
|
+
opacity: 0.55
|
|
84
|
+
},
|
|
85
|
+
children: "GitHub"
|
|
86
|
+
}
|
|
87
|
+
),
|
|
88
|
+
/* @__PURE__ */ jsx(GitHubModuleNav, {})
|
|
89
|
+
] });
|
|
90
|
+
}
|
|
91
|
+
function GitHubRouteSidebar(_props) {
|
|
92
|
+
const nav = useHostNavigation();
|
|
93
|
+
return /* @__PURE__ */ jsxs("nav", { style: { display: "flex", flexDirection: "column", gap: "0.25rem", padding: "0.5rem 0" }, children: [
|
|
94
|
+
/* @__PURE__ */ jsx(
|
|
95
|
+
"a",
|
|
96
|
+
{
|
|
97
|
+
...nav.linkProps("/dashboard"),
|
|
98
|
+
className: `${sidebarLinkClass} ${sidebarLinkIdleClass}`,
|
|
99
|
+
children: /* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: "\u2190 Company dashboard" })
|
|
100
|
+
}
|
|
101
|
+
),
|
|
102
|
+
/* @__PURE__ */ jsx(
|
|
103
|
+
"div",
|
|
104
|
+
{
|
|
105
|
+
style: {
|
|
106
|
+
padding: "0.75rem 0.75rem 0.25rem",
|
|
107
|
+
fontSize: "0.7rem",
|
|
108
|
+
fontWeight: 600,
|
|
109
|
+
letterSpacing: "0.04em",
|
|
110
|
+
textTransform: "uppercase",
|
|
111
|
+
opacity: 0.55
|
|
112
|
+
},
|
|
113
|
+
children: "GitHub"
|
|
114
|
+
}
|
|
115
|
+
),
|
|
116
|
+
/* @__PURE__ */ jsx(GitHubModuleNav, {})
|
|
117
|
+
] });
|
|
118
|
+
}
|
|
119
|
+
function RepoTable({ repos }) {
|
|
120
|
+
if (repos.length === 0) {
|
|
121
|
+
return /* @__PURE__ */ jsx("div", { children: "Nenhum reposit\xF3rio listado. Configure o token em Configura\xE7\xF5es." });
|
|
122
|
+
}
|
|
123
|
+
return /* @__PURE__ */ jsxs("table", { style: { width: "100%", borderCollapse: "collapse", fontSize: "0.9rem" }, children: [
|
|
124
|
+
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { style: { textAlign: "left", opacity: 0.7 }, children: [
|
|
125
|
+
/* @__PURE__ */ jsx("th", { style: { padding: "0.35rem 0" }, children: "Reposit\xF3rio" }),
|
|
126
|
+
/* @__PURE__ */ jsx("th", { children: "Atualizado" }),
|
|
127
|
+
/* @__PURE__ */ jsx("th", { children: "Visibilidade" })
|
|
128
|
+
] }) }),
|
|
129
|
+
/* @__PURE__ */ jsx("tbody", { children: repos.map((repo) => /* @__PURE__ */ jsxs("tr", { children: [
|
|
130
|
+
/* @__PURE__ */ jsx("td", { style: { padding: "0.35rem 0" }, children: /* @__PURE__ */ jsx("a", { href: repo.htmlUrl, target: "_blank", rel: "noreferrer", children: repo.fullName }) }),
|
|
131
|
+
/* @__PURE__ */ jsx("td", { children: new Date(repo.updatedAt).toLocaleString() }),
|
|
132
|
+
/* @__PURE__ */ jsx("td", { children: repo.private ? "private" : "public" })
|
|
133
|
+
] }, repo.id)) })
|
|
134
|
+
] });
|
|
135
|
+
}
|
|
136
|
+
function DashboardWidget(_props) {
|
|
137
|
+
const { companyParams } = useGithubCompany();
|
|
138
|
+
const { data, loading, error } = usePluginData("health", companyParams);
|
|
139
|
+
const ping = usePluginAction("ping");
|
|
140
|
+
const nav = useHostNavigation();
|
|
141
|
+
if (loading) return /* @__PURE__ */ jsx("div", { children: "Carregando status do GitHub..." });
|
|
142
|
+
if (error) return /* @__PURE__ */ jsxs("div", { children: [
|
|
143
|
+
"Erro do plugin: ",
|
|
144
|
+
error.message
|
|
145
|
+
] });
|
|
146
|
+
return /* @__PURE__ */ jsxs("div", { style: { display: "grid", gap: "0.5rem" }, children: [
|
|
147
|
+
/* @__PURE__ */ jsx("strong", { children: "GitHub Manager" }),
|
|
148
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
149
|
+
"Status: ",
|
|
150
|
+
data?.status ?? "unknown"
|
|
151
|
+
] }),
|
|
152
|
+
data?.login ? /* @__PURE__ */ jsxs("div", { children: [
|
|
153
|
+
"Conta: ",
|
|
154
|
+
data.login
|
|
155
|
+
] }) : null,
|
|
156
|
+
data?.message ? /* @__PURE__ */ jsx("div", { children: data.message }) : null,
|
|
157
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
158
|
+
"Verificado: ",
|
|
159
|
+
data?.checkedAt ?? "nunca"
|
|
160
|
+
] }),
|
|
161
|
+
data?.status !== "ok" ? /* @__PURE__ */ jsx("a", { ...nav.linkProps(PATHS.settings), style: { fontSize: "0.85rem" }, children: "Configurar token \u2192" }) : null,
|
|
162
|
+
/* @__PURE__ */ jsx("button", { style: buttonStyle, onClick: () => void ping(), children: "Ping Worker" })
|
|
163
|
+
] });
|
|
164
|
+
}
|
|
165
|
+
function GitHubSettingsPage(_props) {
|
|
166
|
+
const nav = useHostNavigation();
|
|
167
|
+
const { companyId, companyParams } = useGithubCompany();
|
|
168
|
+
const { data: health, loading, error, refresh } = usePluginData("health", companyParams);
|
|
169
|
+
const saveGithubToken = usePluginAction("saveGithubToken");
|
|
170
|
+
const saveGithubSecretRef = usePluginAction("saveGithubSecretRef");
|
|
171
|
+
const clearGithubAuth = usePluginAction("clearGithubAuth");
|
|
172
|
+
const [pat, setPat] = useState("");
|
|
173
|
+
const [secretRef, setSecretRef] = useState("");
|
|
174
|
+
const [busy, setBusy] = useState(null);
|
|
175
|
+
const [formMessage, setFormMessage] = useState(null);
|
|
176
|
+
async function runSave(label, fn) {
|
|
177
|
+
if (!companyId) {
|
|
178
|
+
setFormMessage("Selecione uma company no header do Paperclip.");
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
setBusy(label);
|
|
182
|
+
setFormMessage(null);
|
|
183
|
+
try {
|
|
184
|
+
await fn();
|
|
185
|
+
setPat("");
|
|
186
|
+
setFormMessage(`${label} \u2014 OK. Testando conex\xE3o\u2026`);
|
|
187
|
+
refresh();
|
|
188
|
+
} catch (err) {
|
|
189
|
+
setFormMessage(err instanceof Error ? err.message : String(err));
|
|
190
|
+
} finally {
|
|
191
|
+
setBusy(null);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return /* @__PURE__ */ jsxs("div", { style: { padding: "1.5rem", display: "grid", gap: "1rem", maxWidth: 720 }, children: [
|
|
195
|
+
/* @__PURE__ */ jsxs("header", { children: [
|
|
196
|
+
/* @__PURE__ */ jsx("h1", { style: { margin: 0 }, children: "GitHub \u2014 Configura\xE7\xF5es" }),
|
|
197
|
+
/* @__PURE__ */ jsxs("p", { style: { margin: "0.5rem 0 0", opacity: 0.8 }, children: [
|
|
198
|
+
"Conecte um Personal Access Token (PAT) da GitHub. O token fica no estado do plugin por company (o Paperclip ainda n\xE3o resolve ",
|
|
199
|
+
/* @__PURE__ */ jsx("code", { children: "secrets.read-ref" }),
|
|
200
|
+
" em workers \u2014 PAP-2394)."
|
|
201
|
+
] })
|
|
202
|
+
] }),
|
|
203
|
+
!companyId ? /* @__PURE__ */ jsx("p", { style: { margin: 0, opacity: 0.8 }, children: "Selecione uma company no header do Paperclip." }) : null,
|
|
204
|
+
/* @__PURE__ */ jsxs("section", { style: panelStyle, children: [
|
|
205
|
+
/* @__PURE__ */ jsx("strong", { children: "1. Personal Access Token (recomendado)" }),
|
|
206
|
+
/* @__PURE__ */ jsxs("p", { style: { margin: 0, opacity: 0.85 }, children: [
|
|
207
|
+
"Gere um PAT em GitHub \u2192 Settings \u2192 Developer settings. Escopos: ",
|
|
208
|
+
/* @__PURE__ */ jsx("code", { children: "repo" }),
|
|
209
|
+
",",
|
|
210
|
+
" ",
|
|
211
|
+
/* @__PURE__ */ jsx("code", { children: "read:user" }),
|
|
212
|
+
"; para webhooks tamb\xE9m ",
|
|
213
|
+
/* @__PURE__ */ jsx("code", { children: "admin:repo_hook" }),
|
|
214
|
+
"."
|
|
215
|
+
] }),
|
|
216
|
+
/* @__PURE__ */ jsxs("label", { style: { display: "grid", gap: "0.35rem" }, children: [
|
|
217
|
+
"PAT",
|
|
218
|
+
/* @__PURE__ */ jsx(
|
|
219
|
+
"input",
|
|
220
|
+
{
|
|
221
|
+
type: "password",
|
|
222
|
+
autoComplete: "off",
|
|
223
|
+
value: pat,
|
|
224
|
+
onChange: (e) => setPat(e.target.value),
|
|
225
|
+
placeholder: "ghp_\u2026",
|
|
226
|
+
style: { maxWidth: 480, padding: "0.4rem 0.5rem" }
|
|
227
|
+
}
|
|
228
|
+
)
|
|
229
|
+
] }),
|
|
230
|
+
/* @__PURE__ */ jsx(
|
|
231
|
+
"button",
|
|
232
|
+
{
|
|
233
|
+
style: buttonStyle,
|
|
234
|
+
type: "button",
|
|
235
|
+
disabled: Boolean(busy) || !companyId || !pat.trim(),
|
|
236
|
+
onClick: () => void runSave(
|
|
237
|
+
"Salvar token",
|
|
238
|
+
() => saveGithubToken({ companyId, token: pat })
|
|
239
|
+
),
|
|
240
|
+
children: "Salvar token"
|
|
241
|
+
}
|
|
242
|
+
)
|
|
243
|
+
] }),
|
|
244
|
+
/* @__PURE__ */ jsxs("section", { style: panelStyle, children: [
|
|
245
|
+
/* @__PURE__ */ jsx("strong", { children: "2. Secret ID (futuro)" }),
|
|
246
|
+
/* @__PURE__ */ jsxs("p", { style: { margin: 0, opacity: 0.85 }, children: [
|
|
247
|
+
"Se voc\xEA j\xE1 criou um secret em ",
|
|
248
|
+
/* @__PURE__ */ jsx("strong", { children: "Company \u2192 Settings" }),
|
|
249
|
+
" (chave",
|
|
250
|
+
" ",
|
|
251
|
+
/* @__PURE__ */ jsx("code", { children: GITHUB_TOKEN_SECRET_KEY }),
|
|
252
|
+
"), copie o ",
|
|
253
|
+
/* @__PURE__ */ jsx("strong", { children: "ID (UUID)" }),
|
|
254
|
+
" do secret \u2014 n\xE3o basta a chave. Quando o Paperclip reabilitar secret refs, este campo passar\xE1 a funcionar sem colar o PAT aqui."
|
|
255
|
+
] }),
|
|
256
|
+
/* @__PURE__ */ jsx(
|
|
257
|
+
"a",
|
|
258
|
+
{
|
|
259
|
+
...nav.linkProps(PATHS.companySecrets),
|
|
260
|
+
className: sidebarLinkClass,
|
|
261
|
+
style: { display: "inline-flex", width: "auto", marginTop: "0.25rem" },
|
|
262
|
+
children: "Abrir Company Settings"
|
|
263
|
+
}
|
|
264
|
+
),
|
|
265
|
+
/* @__PURE__ */ jsxs("label", { style: { display: "grid", gap: "0.35rem", marginTop: "0.75rem" }, children: [
|
|
266
|
+
"Secret ID (UUID)",
|
|
267
|
+
/* @__PURE__ */ jsx(
|
|
268
|
+
"input",
|
|
269
|
+
{
|
|
270
|
+
value: secretRef,
|
|
271
|
+
onChange: (e) => setSecretRef(e.target.value),
|
|
272
|
+
placeholder: "00000000-0000-0000-0000-000000000000",
|
|
273
|
+
style: { maxWidth: 480, padding: "0.4rem 0.5rem", fontFamily: "monospace" }
|
|
274
|
+
}
|
|
275
|
+
)
|
|
276
|
+
] }),
|
|
277
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", flexWrap: "wrap", gap: "0.5rem" }, children: [
|
|
278
|
+
/* @__PURE__ */ jsx(
|
|
279
|
+
"button",
|
|
280
|
+
{
|
|
281
|
+
style: buttonStyle,
|
|
282
|
+
type: "button",
|
|
283
|
+
disabled: Boolean(busy) || !companyId || !secretRef.trim(),
|
|
284
|
+
onClick: () => void runSave(
|
|
285
|
+
"Salvar Secret ID",
|
|
286
|
+
() => saveGithubSecretRef({ companyId, secretRef })
|
|
287
|
+
),
|
|
288
|
+
children: "Salvar Secret ID"
|
|
289
|
+
}
|
|
290
|
+
),
|
|
291
|
+
/* @__PURE__ */ jsx(
|
|
292
|
+
"button",
|
|
293
|
+
{
|
|
294
|
+
style: buttonStyle,
|
|
295
|
+
type: "button",
|
|
296
|
+
disabled: Boolean(busy) || !companyId,
|
|
297
|
+
onClick: () => void runSave("Limpar credenciais", () => clearGithubAuth({ companyId })),
|
|
298
|
+
children: "Limpar"
|
|
299
|
+
}
|
|
300
|
+
)
|
|
301
|
+
] })
|
|
302
|
+
] }),
|
|
303
|
+
/* @__PURE__ */ jsxs("section", { style: panelStyle, children: [
|
|
304
|
+
/* @__PURE__ */ jsx("strong", { children: "3. Testar conex\xE3o" }),
|
|
305
|
+
health?.auth ? /* @__PURE__ */ jsxs("div", { style: { fontSize: "0.85rem", opacity: 0.75 }, children: [
|
|
306
|
+
"Credencial: ",
|
|
307
|
+
health.auth.configured ? health.auth.mode : "nenhuma"
|
|
308
|
+
] }) : null,
|
|
309
|
+
loading ? /* @__PURE__ */ jsx("div", { children: "Verificando..." }) : null,
|
|
310
|
+
error ? /* @__PURE__ */ jsxs("div", { children: [
|
|
311
|
+
"Erro: ",
|
|
312
|
+
error.message
|
|
313
|
+
] }) : null,
|
|
314
|
+
health ? /* @__PURE__ */ jsxs("div", { style: { display: "grid", gap: "0.35rem" }, children: [
|
|
315
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
316
|
+
"Status: ",
|
|
317
|
+
/* @__PURE__ */ jsx("strong", { children: health.status }),
|
|
318
|
+
health.login ? ` \u2014 @${health.login}` : ""
|
|
319
|
+
] }),
|
|
320
|
+
health.message ? /* @__PURE__ */ jsx("div", { children: health.message }) : null,
|
|
321
|
+
/* @__PURE__ */ jsxs("div", { style: { fontSize: "0.85rem", opacity: 0.7 }, children: [
|
|
322
|
+
"Verificado: ",
|
|
323
|
+
new Date(health.checkedAt).toLocaleString()
|
|
324
|
+
] })
|
|
325
|
+
] }) : null,
|
|
326
|
+
/* @__PURE__ */ jsx(
|
|
327
|
+
"button",
|
|
328
|
+
{
|
|
329
|
+
style: buttonStyle,
|
|
330
|
+
type: "button",
|
|
331
|
+
disabled: Boolean(busy) || !companyId,
|
|
332
|
+
onClick: () => refresh(),
|
|
333
|
+
children: "Testar conex\xE3o"
|
|
334
|
+
}
|
|
335
|
+
),
|
|
336
|
+
health?.status === "ok" ? /* @__PURE__ */ jsxs("p", { style: { margin: 0, color: "inherit", opacity: 0.85 }, children: [
|
|
337
|
+
"Token OK. Use ",
|
|
338
|
+
/* @__PURE__ */ jsx("a", { ...nav.linkProps(PATHS.repos), children: "Reposit\xF3rios" }),
|
|
339
|
+
" e",
|
|
340
|
+
" ",
|
|
341
|
+
/* @__PURE__ */ jsx("a", { ...nav.linkProps(PATHS.pullRequests), children: "Pull requests" }),
|
|
342
|
+
"."
|
|
343
|
+
] }) : null
|
|
344
|
+
] }),
|
|
345
|
+
formMessage ? /* @__PURE__ */ jsx("div", { children: formMessage }) : null,
|
|
346
|
+
busy ? /* @__PURE__ */ jsxs("div", { children: [
|
|
347
|
+
"Executando: ",
|
|
348
|
+
busy,
|
|
349
|
+
"\u2026"
|
|
350
|
+
] }) : null
|
|
351
|
+
] });
|
|
352
|
+
}
|
|
353
|
+
function GitHubReposPage(_props) {
|
|
354
|
+
const nav = useHostNavigation();
|
|
355
|
+
const { companyId, companyParams } = useGithubCompany();
|
|
356
|
+
const { data: health, loading: healthLoading, error: healthError } = usePluginData("health", companyParams);
|
|
357
|
+
const {
|
|
358
|
+
data: reposData,
|
|
359
|
+
loading: reposLoading,
|
|
360
|
+
error: reposError,
|
|
361
|
+
refresh: refreshRepos
|
|
362
|
+
} = usePluginData("repos", companyParams);
|
|
363
|
+
const {
|
|
364
|
+
data: webhookData,
|
|
365
|
+
loading: webhookLoading,
|
|
366
|
+
refresh: refreshWebhook
|
|
367
|
+
} = usePluginData("webhookConfig", companyParams);
|
|
368
|
+
const setTrackedRepos = usePluginAction("setTrackedRepos");
|
|
369
|
+
const configureWebhook = usePluginAction("configureWebhook");
|
|
370
|
+
const [selectedRepo, setSelectedRepo] = useState("");
|
|
371
|
+
const [busy, setBusy] = useState(null);
|
|
372
|
+
const [actionMessage, setActionMessage] = useState(null);
|
|
373
|
+
const trackedSelection = selectedRepo || reposData?.repos[0]?.fullName || "";
|
|
374
|
+
const needsToken = health?.status === "degraded" || health?.status === "error";
|
|
375
|
+
async function runAction(label, fn) {
|
|
376
|
+
if (!companyId) {
|
|
377
|
+
setActionMessage("Selecione uma company no host antes de continuar.");
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
setBusy(label);
|
|
381
|
+
setActionMessage(null);
|
|
382
|
+
try {
|
|
383
|
+
await fn();
|
|
384
|
+
refreshRepos();
|
|
385
|
+
refreshWebhook();
|
|
386
|
+
setActionMessage(`${label} conclu\xEDdo.`);
|
|
387
|
+
} catch (err) {
|
|
388
|
+
setActionMessage(err instanceof Error ? err.message : String(err));
|
|
389
|
+
} finally {
|
|
390
|
+
setBusy(null);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
return /* @__PURE__ */ jsxs("div", { style: { padding: "1.5rem", display: "grid", gap: "1rem", maxWidth: 960 }, children: [
|
|
394
|
+
/* @__PURE__ */ jsxs("header", { children: [
|
|
395
|
+
/* @__PURE__ */ jsx("h1", { style: { margin: 0 }, children: "GitHub \u2014 Reposit\xF3rios" }),
|
|
396
|
+
/* @__PURE__ */ jsx("p", { style: { margin: "0.5rem 0 0", opacity: 0.8 }, children: "Liste reposit\xF3rios e escolha quais rastrear para sync e webhooks." })
|
|
397
|
+
] }),
|
|
398
|
+
needsToken ? /* @__PURE__ */ jsxs("section", { style: panelStyle, children: [
|
|
399
|
+
/* @__PURE__ */ jsx("strong", { children: "Token n\xE3o configurado" }),
|
|
400
|
+
/* @__PURE__ */ jsxs("p", { style: { margin: 0 }, children: [
|
|
401
|
+
/* @__PURE__ */ jsx("a", { ...nav.linkProps(PATHS.settings), children: "Abrir Configura\xE7\xF5es" }),
|
|
402
|
+
" e salve um PAT da GitHub."
|
|
403
|
+
] })
|
|
404
|
+
] }) : null,
|
|
405
|
+
/* @__PURE__ */ jsxs("section", { style: panelStyle, children: [
|
|
406
|
+
/* @__PURE__ */ jsx("strong", { children: "Conex\xE3o" }),
|
|
407
|
+
healthLoading ? /* @__PURE__ */ jsx("div", { children: "Carregando..." }) : null,
|
|
408
|
+
healthError ? /* @__PURE__ */ jsxs("div", { children: [
|
|
409
|
+
"Erro: ",
|
|
410
|
+
healthError.message
|
|
411
|
+
] }) : null,
|
|
412
|
+
health ? /* @__PURE__ */ jsxs("div", { children: [
|
|
413
|
+
"Status: ",
|
|
414
|
+
health.status,
|
|
415
|
+
health.login ? ` \u2014 ${health.login}` : "",
|
|
416
|
+
health.message ? /* @__PURE__ */ jsx("div", { children: health.message }) : null
|
|
417
|
+
] }) : null
|
|
418
|
+
] }),
|
|
419
|
+
/* @__PURE__ */ jsxs("section", { style: panelStyle, children: [
|
|
420
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between", gap: "0.5rem" }, children: [
|
|
421
|
+
/* @__PURE__ */ jsx("strong", { children: "Reposit\xF3rios" }),
|
|
422
|
+
/* @__PURE__ */ jsx("button", { style: buttonStyle, disabled: Boolean(busy), onClick: () => refreshRepos(), children: "Atualizar lista" })
|
|
423
|
+
] }),
|
|
424
|
+
reposLoading ? /* @__PURE__ */ jsx("div", { children: "Carregando reposit\xF3rios..." }) : null,
|
|
425
|
+
reposError ? /* @__PURE__ */ jsxs("div", { children: [
|
|
426
|
+
"Erro: ",
|
|
427
|
+
reposError.message
|
|
428
|
+
] }) : null,
|
|
429
|
+
reposData?.message ? /* @__PURE__ */ jsx("div", { children: reposData.message }) : null,
|
|
430
|
+
reposData ? /* @__PURE__ */ jsx(RepoTable, { repos: reposData.repos }) : null,
|
|
431
|
+
reposData?.repos.length ? /* @__PURE__ */ jsxs("label", { style: { display: "grid", gap: "0.35rem" }, children: [
|
|
432
|
+
"Repo para webhook",
|
|
433
|
+
/* @__PURE__ */ jsx(
|
|
434
|
+
"select",
|
|
435
|
+
{
|
|
436
|
+
value: trackedSelection,
|
|
437
|
+
onChange: (e) => setSelectedRepo(e.target.value),
|
|
438
|
+
style: { maxWidth: 420 },
|
|
439
|
+
children: reposData.repos.map((repo) => /* @__PURE__ */ jsx("option", { value: repo.fullName, children: repo.fullName }, repo.id))
|
|
440
|
+
}
|
|
441
|
+
)
|
|
442
|
+
] }) : null,
|
|
443
|
+
/* @__PURE__ */ jsx(
|
|
444
|
+
"button",
|
|
445
|
+
{
|
|
446
|
+
style: buttonStyle,
|
|
447
|
+
disabled: Boolean(busy) || !trackedSelection || !companyId || needsToken,
|
|
448
|
+
onClick: () => void runAction(
|
|
449
|
+
"Salvar repos rastreados",
|
|
450
|
+
() => setTrackedRepos({
|
|
451
|
+
companyId,
|
|
452
|
+
repos: reposData?.repos.slice(0, 5).map((r) => r.fullName) ?? []
|
|
453
|
+
})
|
|
454
|
+
),
|
|
455
|
+
children: "Rastrear top 5 repos"
|
|
456
|
+
}
|
|
457
|
+
)
|
|
458
|
+
] }),
|
|
459
|
+
/* @__PURE__ */ jsxs("section", { style: panelStyle, children: [
|
|
460
|
+
/* @__PURE__ */ jsx("strong", { children: "Webhooks" }),
|
|
461
|
+
webhookLoading ? /* @__PURE__ */ jsx("div", { children: "Carregando configura\xE7\xE3o..." }) : null,
|
|
462
|
+
/* @__PURE__ */ jsxs("div", { style: { fontSize: "0.85rem", opacity: 0.85 }, children: [
|
|
463
|
+
"URL inbound: ",
|
|
464
|
+
/* @__PURE__ */ jsx("code", { children: webhookData?.inboundUrl ?? "\u2014" })
|
|
465
|
+
] }),
|
|
466
|
+
webhookData?.configured && webhookData.config ? /* @__PURE__ */ jsxs("div", { children: [
|
|
467
|
+
"Configurado para ",
|
|
468
|
+
/* @__PURE__ */ jsx("strong", { children: webhookData.config.repoFullName }),
|
|
469
|
+
" (hook",
|
|
470
|
+
" ",
|
|
471
|
+
webhookData.config.hookId ?? "?",
|
|
472
|
+
") em",
|
|
473
|
+
" ",
|
|
474
|
+
new Date(webhookData.config.configuredAt).toLocaleString()
|
|
475
|
+
] }) : /* @__PURE__ */ jsx("div", { children: "Nenhum webhook registrado nesta company." }),
|
|
476
|
+
/* @__PURE__ */ jsx(
|
|
477
|
+
"button",
|
|
478
|
+
{
|
|
479
|
+
style: buttonStyle,
|
|
480
|
+
disabled: Boolean(busy) || !companyId || !trackedSelection || needsToken,
|
|
481
|
+
onClick: () => void runAction(
|
|
482
|
+
"Registrar webhook",
|
|
483
|
+
() => configureWebhook({
|
|
484
|
+
companyId,
|
|
485
|
+
repoFullName: trackedSelection,
|
|
486
|
+
events: ["pull_request", "issues"]
|
|
487
|
+
})
|
|
488
|
+
),
|
|
489
|
+
children: "Registrar webhook no GitHub"
|
|
490
|
+
}
|
|
491
|
+
)
|
|
492
|
+
] }),
|
|
493
|
+
actionMessage ? /* @__PURE__ */ jsx("div", { children: actionMessage }) : null,
|
|
494
|
+
busy ? /* @__PURE__ */ jsxs("div", { children: [
|
|
495
|
+
"Executando: ",
|
|
496
|
+
busy,
|
|
497
|
+
"..."
|
|
498
|
+
] }) : null
|
|
499
|
+
] });
|
|
500
|
+
}
|
|
501
|
+
function GitHubPullRequestsPage(_props) {
|
|
502
|
+
const nav = useHostNavigation();
|
|
503
|
+
const { companyId, companyParams } = useGithubCompany();
|
|
504
|
+
const { data: health } = usePluginData("health", companyParams);
|
|
505
|
+
const {
|
|
506
|
+
data: syncOverview,
|
|
507
|
+
loading: syncLoading,
|
|
508
|
+
error: syncError,
|
|
509
|
+
refresh: refreshSync
|
|
510
|
+
} = usePluginData("syncOverview", companyParams);
|
|
511
|
+
const syncAll = usePluginAction("syncAll");
|
|
512
|
+
const syncPullRequests = usePluginAction("syncPullRequests");
|
|
513
|
+
const syncIssues = usePluginAction("syncIssues");
|
|
514
|
+
const [busy, setBusy] = useState(null);
|
|
515
|
+
const [actionMessage, setActionMessage] = useState(null);
|
|
516
|
+
const needsToken = health?.status === "degraded" || health?.status === "error";
|
|
517
|
+
async function runAction(label, fn) {
|
|
518
|
+
if (!companyId) {
|
|
519
|
+
setActionMessage("Selecione uma company no host.");
|
|
520
|
+
return;
|
|
521
|
+
}
|
|
522
|
+
setBusy(label);
|
|
523
|
+
setActionMessage(null);
|
|
524
|
+
try {
|
|
525
|
+
await fn();
|
|
526
|
+
refreshSync();
|
|
527
|
+
setActionMessage(`${label} conclu\xEDdo.`);
|
|
528
|
+
} catch (err) {
|
|
529
|
+
setActionMessage(err instanceof Error ? err.message : String(err));
|
|
530
|
+
} finally {
|
|
531
|
+
setBusy(null);
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
return /* @__PURE__ */ jsxs("div", { style: { padding: "1.5rem", display: "grid", gap: "1rem", maxWidth: 960 }, children: [
|
|
535
|
+
/* @__PURE__ */ jsxs("header", { children: [
|
|
536
|
+
/* @__PURE__ */ jsx("h1", { style: { margin: 0 }, children: "GitHub \u2014 Pull requests" }),
|
|
537
|
+
/* @__PURE__ */ jsx("p", { style: { margin: "0.5rem 0 0", opacity: 0.8 }, children: "Sincronize PRs e issues abertos dos reposit\xF3rios rastreados." })
|
|
538
|
+
] }),
|
|
539
|
+
needsToken ? /* @__PURE__ */ jsx("section", { style: panelStyle, children: /* @__PURE__ */ jsx("a", { ...nav.linkProps(PATHS.settings), children: "Configurar token GitHub" }) }) : null,
|
|
540
|
+
/* @__PURE__ */ jsxs("section", { style: panelStyle, children: [
|
|
541
|
+
/* @__PURE__ */ jsx("strong", { children: "Sync PRs / Issues" }),
|
|
542
|
+
syncLoading ? /* @__PURE__ */ jsx("div", { children: "Carregando overview..." }) : null,
|
|
543
|
+
syncError ? /* @__PURE__ */ jsxs("div", { children: [
|
|
544
|
+
"Erro: ",
|
|
545
|
+
syncError.message
|
|
546
|
+
] }) : null,
|
|
547
|
+
syncOverview ? /* @__PURE__ */ jsxs("div", { style: { display: "grid", gap: "0.35rem" }, children: [
|
|
548
|
+
/* @__PURE__ */ jsx("div", { children: syncOverview.message }),
|
|
549
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
550
|
+
"PRs abertos: ",
|
|
551
|
+
syncOverview.pullRequestCount,
|
|
552
|
+
" \u2014 Issues abertas:",
|
|
553
|
+
" ",
|
|
554
|
+
syncOverview.issueCount
|
|
555
|
+
] }),
|
|
556
|
+
syncOverview.lastSyncedAt ? /* @__PURE__ */ jsxs("div", { children: [
|
|
557
|
+
"\xDAltimo sync: ",
|
|
558
|
+
new Date(syncOverview.lastSyncedAt).toLocaleString()
|
|
559
|
+
] }) : null
|
|
560
|
+
] }) : null,
|
|
561
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", flexWrap: "wrap", gap: "0.5rem" }, children: [
|
|
562
|
+
/* @__PURE__ */ jsx(
|
|
563
|
+
"button",
|
|
564
|
+
{
|
|
565
|
+
style: buttonStyle,
|
|
566
|
+
disabled: Boolean(busy) || !companyId || needsToken,
|
|
567
|
+
onClick: () => void runAction("Sync completo", () => syncAll({ companyId })),
|
|
568
|
+
children: "Sync tudo"
|
|
569
|
+
}
|
|
570
|
+
),
|
|
571
|
+
/* @__PURE__ */ jsx(
|
|
572
|
+
"button",
|
|
573
|
+
{
|
|
574
|
+
style: buttonStyle,
|
|
575
|
+
disabled: Boolean(busy) || !companyId || needsToken,
|
|
576
|
+
onClick: () => void runAction("Sync PRs", () => syncPullRequests({ companyId })),
|
|
577
|
+
children: "Sync PRs"
|
|
578
|
+
}
|
|
579
|
+
),
|
|
580
|
+
/* @__PURE__ */ jsx(
|
|
581
|
+
"button",
|
|
582
|
+
{
|
|
583
|
+
style: buttonStyle,
|
|
584
|
+
disabled: Boolean(busy) || !companyId || needsToken,
|
|
585
|
+
onClick: () => void runAction("Sync issues", () => syncIssues({ companyId })),
|
|
586
|
+
children: "Sync issues"
|
|
587
|
+
}
|
|
588
|
+
)
|
|
589
|
+
] }),
|
|
590
|
+
syncOverview?.recentPullRequests.length ? /* @__PURE__ */ jsxs("div", { children: [
|
|
591
|
+
/* @__PURE__ */ jsx("div", { style: { fontWeight: 600, marginBottom: 4 }, children: "PRs recentes" }),
|
|
592
|
+
/* @__PURE__ */ jsx("ul", { style: { margin: 0, paddingLeft: "1.2rem" }, children: syncOverview.recentPullRequests.map((pr) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs("a", { href: pr.htmlUrl, target: "_blank", rel: "noreferrer", children: [
|
|
593
|
+
pr.repoFullName,
|
|
594
|
+
"#",
|
|
595
|
+
pr.number,
|
|
596
|
+
" \u2014 ",
|
|
597
|
+
pr.title
|
|
598
|
+
] }) }, `${pr.repoFullName}#${pr.number}`)) })
|
|
599
|
+
] }) : null,
|
|
600
|
+
syncOverview?.recentIssues.length ? /* @__PURE__ */ jsxs("div", { children: [
|
|
601
|
+
/* @__PURE__ */ jsx("div", { style: { fontWeight: 600, marginBottom: 4 }, children: "Issues recentes" }),
|
|
602
|
+
/* @__PURE__ */ jsx("ul", { style: { margin: 0, paddingLeft: "1.2rem" }, children: syncOverview.recentIssues.map((issue) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs("a", { href: issue.htmlUrl, target: "_blank", rel: "noreferrer", children: [
|
|
603
|
+
issue.repoFullName,
|
|
604
|
+
"#",
|
|
605
|
+
issue.number,
|
|
606
|
+
" \u2014 ",
|
|
607
|
+
issue.title
|
|
608
|
+
] }) }, `${issue.repoFullName}#${issue.number}`)) })
|
|
609
|
+
] }) : null
|
|
610
|
+
] }),
|
|
611
|
+
actionMessage ? /* @__PURE__ */ jsx("div", { children: actionMessage }) : null,
|
|
612
|
+
busy ? /* @__PURE__ */ jsxs("div", { children: [
|
|
613
|
+
"Executando: ",
|
|
614
|
+
busy,
|
|
615
|
+
"..."
|
|
616
|
+
] }) : null
|
|
617
|
+
] });
|
|
618
|
+
}
|
|
619
|
+
export {
|
|
620
|
+
DashboardWidget,
|
|
621
|
+
GitHubPullRequestsPage,
|
|
622
|
+
GitHubReposPage,
|
|
623
|
+
GitHubRouteSidebar,
|
|
624
|
+
GitHubSettingsPage,
|
|
625
|
+
GitHubSidebarModule
|
|
626
|
+
};
|
|
627
|
+
//# sourceMappingURL=index.js.map
|