paperclip-github-plugin 0.7.3 → 0.7.4
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 +12 -5
- package/dist/manifest.js +5 -1
- package/dist/ui/index.js +266 -14
- package/dist/ui/index.js.map +2 -2
- package/dist/worker.js +425 -30
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -35,7 +35,7 @@ The plugin adds a full in-host workflow instead of a one-off import script:
|
|
|
35
35
|
- saved sync diagnostics that let operators inspect the latest per-issue failures, raw errors, and suggested next steps
|
|
36
36
|
- a project sidebar item that opens a live project-scoped Pull Requests page for the mapped repository and can show the open PR count through a lightweight badge read
|
|
37
37
|
- manual sync actions from global, project, and issue surfaces
|
|
38
|
-
- a GitHub detail tab on synced Paperclip issues that
|
|
38
|
+
- a GitHub detail tab on synced Paperclip issues that includes GitHub-marked action buttons plus the GitHub issue creator with avatar, and lets operators manually link an unlinked Paperclip issue to a GitHub issue or pull request
|
|
39
39
|
- GitHub link annotations on sync-generated status transition comments when the host supports comment annotations
|
|
40
40
|
|
|
41
41
|
## How it works
|
|
@@ -68,7 +68,7 @@ The plugin does more than mirror issue text. It looks at linked pull requests, m
|
|
|
68
68
|
|
|
69
69
|
GitHub Sync exposes a dedicated KPI dashboard widget alongside the operational sync widget. During full company syncs, the worker snapshots the current open GitHub backlog and records when already-imported GitHub issues move from open to closed. The KPI widget turns that worker-owned state into backlog, issue-closure, and Paperclip PR-creation cards with recent history and comparisons against older periods.
|
|
70
70
|
|
|
71
|
-
Because GitHub alone cannot tell which pull requests came from a Paperclip company, the plugin uses explicit Paperclip attribution for delivery activity. `create_pull_request` automatically records a Paperclip-created PR event, and agents that use `gh` or another non-plugin GitHub client can post pull-request-created events to the plugin API route so the KPI history stays specific to Paperclip work.
|
|
71
|
+
Because GitHub alone cannot tell which pull requests came from a Paperclip company, the plugin uses explicit Paperclip attribution for delivery activity. `create_pull_request` automatically records a Paperclip-created PR event, and agents that use `gh` or another non-plugin GitHub client can post pull-request-created events to the plugin API route so the KPI history stays specific to Paperclip work. When either path includes the Paperclip issue id, GitHub Sync also records the pull request link so later sync runs can move that issue based on PR CI, merge state, and review activity.
|
|
72
72
|
|
|
73
73
|
That API route path matters on authenticated Paperclip deployments today because a current host bug blocks agents from calling plugin tools unless the instance runs in `local_trusted` mode. Those agents can still use `gh` with the propagated `GITHUB_TOKEN`, then call the agent-authenticated plugin API route from the shell after they create a PR. The Paperclip host authenticates `Authorization: Bearer <PAPERCLIP_API_KEY>`, scopes the request to the calling agent's company, and rejects anonymous or non-agent calls before dispatching to the worker.
|
|
74
74
|
|
|
@@ -78,10 +78,16 @@ Each mapped project can expose a **Pull Requests** entry in the sidebar that ope
|
|
|
78
78
|
|
|
79
79
|
Paperclip issue linkage on the queue prefers the GitHub issue that the pull request closes, so imported GitHub issues and delivery work stay connected in the same project view. If a pull request has no closing-issue-backed link yet, the queue falls back to the Paperclip issue created directly from that pull request and updates the table immediately when that create action returns.
|
|
80
80
|
|
|
81
|
-
Those pull-request-created Paperclip issues also stay in the scheduled/manual sync loop even when the pull request does not close a GitHub issue. GitHub Sync checks their CI, merge state, and review threads so new failures or unresolved feedback move the Paperclip issue back into active work.
|
|
81
|
+
Those pull-request-created Paperclip issues also stay in the scheduled/manual sync loop even when the pull request does not close a GitHub issue. GitHub Sync checks their CI, merge state, and review threads so new failures or unresolved feedback move the Paperclip issue back into active work. The same durable PR link is written when an agent creates a PR through the plugin tool with `paperclipIssueId`, when an authenticated agent records a `gh`-created PR through the agent API route with `paperclipIssueId`, or when an operator manually links an unlinked issue from the issue page.
|
|
82
82
|
|
|
83
83
|
The issue detail panel and sync-created comment annotations also preserve cross-repository linked pull requests, showing those PRs with their real repository path so operators land in the right place on GitHub.
|
|
84
84
|
|
|
85
|
+
### Manual GitHub links
|
|
86
|
+
|
|
87
|
+
If a Paperclip issue was created locally or by an agent workflow before GitHub Sync saw the matching GitHub item, the issue detail surface shows a **Link GitHub item** action. The modal accepts either a GitHub issue number or full issue URL, or a pull request number or full pull request URL. Number-only entries use the issue's mapped Paperclip project repository; full URLs can point at any repository mapped to that project.
|
|
88
|
+
|
|
89
|
+
Manual GitHub issue links are added to the same import registry and issue-link entity used by normal sync, so future syncs update the Paperclip issue from the GitHub issue. Manual pull request links are added to the PR-link entity used by the project Pull Requests page, so future syncs monitor PR status even when there is no closing GitHub issue.
|
|
90
|
+
|
|
85
91
|
### Agent workflows built in
|
|
86
92
|
|
|
87
93
|
Paperclip agents can search GitHub for duplicates, read and update issues, post comments, create pull requests, inspect changed files and CI, reply to review threads, resolve or unresolve threads, request reviewers, search org-level GitHub Projects, and associate pull requests with those projects without leaving the Paperclip plugin surface.
|
|
@@ -219,6 +225,7 @@ Supported payload fields:
|
|
|
219
225
|
- `repository` optional: `owner/repo` or `https://github.com/owner/repo`
|
|
220
226
|
- `pullRequestNumber` optional
|
|
221
227
|
- `pullRequestUrl` optional
|
|
228
|
+
- `paperclipIssueId` optional: the Paperclip issue id that should be linked to the pull request for future PR-status sync
|
|
222
229
|
- `occurredAt` optional ISO timestamp
|
|
223
230
|
- `eventKey` optional custom dedupe key
|
|
224
231
|
- `count` optional positive integer
|
|
@@ -232,7 +239,7 @@ The Paperclip host validates that bearer token and passes the authenticated agen
|
|
|
232
239
|
Example:
|
|
233
240
|
|
|
234
241
|
```bash
|
|
235
|
-
payload='{"metric":"pull_request_created","repository":"paperclipai/example-repo","pullRequestNumber":21}'
|
|
242
|
+
payload='{"metric":"pull_request_created","repository":"paperclipai/example-repo","pullRequestNumber":21,"paperclipIssueId":"iss_123"}'
|
|
236
243
|
|
|
237
244
|
curl -X POST "${PAPERCLIP_API_URL%/}/api/plugins/paperclip-github-plugin/api/company-metrics/events" \
|
|
238
245
|
-H "content-type: application/json" \
|
|
@@ -240,7 +247,7 @@ curl -X POST "${PAPERCLIP_API_URL%/}/api/plugins/paperclip-github-plugin/api/com
|
|
|
240
247
|
-d "${payload}"
|
|
241
248
|
```
|
|
242
249
|
|
|
243
|
-
The worker deduplicates repeated PR events by preferring the pull request URL, then `repository + pullRequestNumber`, before falling back to the explicit `eventKey`.
|
|
250
|
+
The worker deduplicates repeated PR events by preferring the pull request URL, then `repository + pullRequestNumber`, before falling back to the explicit `eventKey`. When `paperclipIssueId` is present, the worker verifies the live pull request and persists the same PR-link metadata used by scheduled/manual status syncs.
|
|
244
251
|
|
|
245
252
|
Current host caveat: on authenticated Paperclip deployments, the Paperclip host currently guards `GET /api/plugins/tools` and `POST /api/plugins/tools/execute` with board authentication before dispatching to any plugin worker. If an agent run does not have board access for the target company, GitHub Sync tool discovery and execution fail with `403 {"error":"Board access required"}` before this plugin's worker code runs.
|
|
246
253
|
|
package/dist/manifest.js
CHANGED
|
@@ -246,6 +246,10 @@ var GITHUB_AGENT_TOOLS = [
|
|
|
246
246
|
required: ["head", "base", "title"],
|
|
247
247
|
properties: {
|
|
248
248
|
repository: repositoryProperty,
|
|
249
|
+
paperclipIssueId: {
|
|
250
|
+
type: "string",
|
|
251
|
+
description: "Optional Paperclip issue id to link with the created pull request so GitHub Sync can monitor PR status for that issue."
|
|
252
|
+
},
|
|
249
253
|
head: {
|
|
250
254
|
type: "string",
|
|
251
255
|
description: "Head branch name or owner:branch."
|
|
@@ -516,7 +520,7 @@ var COMPANY_METRIC_API_ROUTE_URL_PATH = `/api/plugins/${GITHUB_SYNC_PLUGIN_ID}/a
|
|
|
516
520
|
var require2 = createRequire(import.meta.url);
|
|
517
521
|
var packageJson = require2("../package.json");
|
|
518
522
|
var SCHEDULE_TICK_CRON = "* * * * *";
|
|
519
|
-
var MANIFEST_VERSION = "0.7.
|
|
523
|
+
var MANIFEST_VERSION = "0.7.4"?.trim() || typeof packageJson.version === "string" && packageJson.version.trim() || process.env.npm_package_version?.trim() || "0.0.0-dev";
|
|
520
524
|
var manifest = {
|
|
521
525
|
id: GITHUB_SYNC_PLUGIN_ID,
|
|
522
526
|
apiVersion: 1,
|
package/dist/ui/index.js
CHANGED
|
@@ -26778,6 +26778,113 @@ var EXTENSION_SURFACE_STYLES = `
|
|
|
26778
26778
|
margin: 0;
|
|
26779
26779
|
}
|
|
26780
26780
|
|
|
26781
|
+
.ghsync__field {
|
|
26782
|
+
display: grid;
|
|
26783
|
+
gap: 8px;
|
|
26784
|
+
}
|
|
26785
|
+
|
|
26786
|
+
.ghsync__field label {
|
|
26787
|
+
color: var(--ghsync-title);
|
|
26788
|
+
font-size: 12px;
|
|
26789
|
+
font-weight: 600;
|
|
26790
|
+
}
|
|
26791
|
+
|
|
26792
|
+
.ghsync__input {
|
|
26793
|
+
width: 100%;
|
|
26794
|
+
min-height: 40px;
|
|
26795
|
+
border-radius: 8px;
|
|
26796
|
+
border: 1px solid var(--ghsync-input-border);
|
|
26797
|
+
background: var(--ghsync-input-bg);
|
|
26798
|
+
color: var(--ghsync-input-text);
|
|
26799
|
+
padding: 0 12px;
|
|
26800
|
+
outline: none;
|
|
26801
|
+
}
|
|
26802
|
+
|
|
26803
|
+
.ghsync__input::placeholder {
|
|
26804
|
+
color: var(--ghsync-muted);
|
|
26805
|
+
}
|
|
26806
|
+
|
|
26807
|
+
.ghsync__input:focus {
|
|
26808
|
+
border-color: var(--ghsync-border);
|
|
26809
|
+
}
|
|
26810
|
+
|
|
26811
|
+
.ghsync-link-modal-backdrop {
|
|
26812
|
+
position: fixed;
|
|
26813
|
+
inset: 0;
|
|
26814
|
+
z-index: 50;
|
|
26815
|
+
display: flex;
|
|
26816
|
+
align-items: center;
|
|
26817
|
+
justify-content: center;
|
|
26818
|
+
padding: 24px;
|
|
26819
|
+
background: rgba(10, 10, 12, 0.48);
|
|
26820
|
+
backdrop-filter: blur(10px);
|
|
26821
|
+
}
|
|
26822
|
+
|
|
26823
|
+
.ghsync-link-modal {
|
|
26824
|
+
width: min(520px, 100%);
|
|
26825
|
+
display: grid;
|
|
26826
|
+
gap: 16px;
|
|
26827
|
+
padding: 18px;
|
|
26828
|
+
border-radius: 8px;
|
|
26829
|
+
border: 1px solid var(--ghsync-border);
|
|
26830
|
+
background: var(--ghsync-surface);
|
|
26831
|
+
color: var(--ghsync-text);
|
|
26832
|
+
box-shadow: 0 28px 80px rgba(2, 6, 23, 0.34);
|
|
26833
|
+
}
|
|
26834
|
+
|
|
26835
|
+
.ghsync-prs-modal__header {
|
|
26836
|
+
display: grid;
|
|
26837
|
+
gap: 6px;
|
|
26838
|
+
}
|
|
26839
|
+
|
|
26840
|
+
.ghsync-prs-modal__header h3 {
|
|
26841
|
+
margin: 0;
|
|
26842
|
+
color: var(--ghsync-title);
|
|
26843
|
+
font-size: 18px;
|
|
26844
|
+
}
|
|
26845
|
+
|
|
26846
|
+
.ghsync-prs-modal__header p {
|
|
26847
|
+
margin: 0;
|
|
26848
|
+
color: var(--ghsync-muted);
|
|
26849
|
+
font-size: 12px;
|
|
26850
|
+
line-height: 1.5;
|
|
26851
|
+
}
|
|
26852
|
+
|
|
26853
|
+
.ghsync-prs-modal__actions {
|
|
26854
|
+
display: flex;
|
|
26855
|
+
justify-content: flex-end;
|
|
26856
|
+
gap: 8px;
|
|
26857
|
+
flex-wrap: wrap;
|
|
26858
|
+
}
|
|
26859
|
+
|
|
26860
|
+
.ghsync-link-kind {
|
|
26861
|
+
display: grid;
|
|
26862
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
26863
|
+
gap: 6px;
|
|
26864
|
+
padding: 4px;
|
|
26865
|
+
border-radius: 8px;
|
|
26866
|
+
border: 1px solid var(--ghsync-border-soft);
|
|
26867
|
+
background: var(--ghsync-surfaceAlt);
|
|
26868
|
+
}
|
|
26869
|
+
|
|
26870
|
+
.ghsync-link-kind__button {
|
|
26871
|
+
min-height: 34px;
|
|
26872
|
+
border: 0;
|
|
26873
|
+
border-radius: 6px;
|
|
26874
|
+
background: transparent;
|
|
26875
|
+
color: var(--ghsync-muted);
|
|
26876
|
+
font: inherit;
|
|
26877
|
+
font-size: 13px;
|
|
26878
|
+
font-weight: 600;
|
|
26879
|
+
cursor: pointer;
|
|
26880
|
+
}
|
|
26881
|
+
|
|
26882
|
+
.ghsync-link-kind__button--active {
|
|
26883
|
+
background: var(--ghsync-surface);
|
|
26884
|
+
color: var(--ghsync-title);
|
|
26885
|
+
box-shadow: inset 0 0 0 1px var(--ghsync-border);
|
|
26886
|
+
}
|
|
26887
|
+
|
|
26781
26888
|
${SHARED_LOADING_STYLES}
|
|
26782
26889
|
`;
|
|
26783
26890
|
function createEmptyMapping(index2) {
|
|
@@ -34523,7 +34630,8 @@ function GitHubSyncIssueDetailTabContent(props) {
|
|
|
34523
34630
|
loadingIssueId: props.loadingIssueId,
|
|
34524
34631
|
detailsLoading: details.loading,
|
|
34525
34632
|
detailsError: Boolean(details.error),
|
|
34526
|
-
issueDetails
|
|
34633
|
+
issueDetails,
|
|
34634
|
+
canLinkManually: Boolean(props.companyId && props.issueId)
|
|
34527
34635
|
});
|
|
34528
34636
|
const issueSyncButton = useGitHubSyncButtonController({
|
|
34529
34637
|
companyId: props.companyId,
|
|
@@ -34532,6 +34640,12 @@ function GitHubSyncIssueDetailTabContent(props) {
|
|
|
34532
34640
|
resolvedIssueId: props.issueId,
|
|
34533
34641
|
forceVisible: true
|
|
34534
34642
|
});
|
|
34643
|
+
const linkGitHubItem = usePluginAction("issue.linkGitHubItem");
|
|
34644
|
+
const toast = usePluginToast();
|
|
34645
|
+
const [manualLinkOpen, setManualLinkOpen] = useState2(false);
|
|
34646
|
+
const [manualLinkKind, setManualLinkKind] = useState2("issue");
|
|
34647
|
+
const [manualLinkReference, setManualLinkReference] = useState2("");
|
|
34648
|
+
const [manualLinkPending, setManualLinkPending] = useState2(false);
|
|
34535
34649
|
useEffect2(() => {
|
|
34536
34650
|
if (!props.companyId || !props.issueId) {
|
|
34537
34651
|
return;
|
|
@@ -34546,18 +34660,77 @@ function GitHubSyncIssueDetailTabContent(props) {
|
|
|
34546
34660
|
return null;
|
|
34547
34661
|
}
|
|
34548
34662
|
const linkedPullRequests = issueDetails ? getLinkedPullRequestsForIssueDetails(issueDetails) : [];
|
|
34663
|
+
const issueDetailsKind = issueDetails?.kind ?? "issue";
|
|
34664
|
+
const githubUrl = issueDetailsKind === "pull_request" ? issueDetails?.githubPullRequestUrl : issueDetails?.githubIssueUrl;
|
|
34665
|
+
const githubStateLabel = issueDetailsKind === "pull_request" ? issueDetails?.githubPullRequestState === "closed" ? "Closed" : "Open" : formatGitHubIssueState(issueDetails?.githubIssueState, issueDetails?.githubIssueStateReason);
|
|
34666
|
+
function closeManualLinkModal() {
|
|
34667
|
+
if (manualLinkPending) {
|
|
34668
|
+
return;
|
|
34669
|
+
}
|
|
34670
|
+
setManualLinkOpen(false);
|
|
34671
|
+
setManualLinkReference("");
|
|
34672
|
+
setManualLinkKind("issue");
|
|
34673
|
+
}
|
|
34674
|
+
async function handleManualLinkSubmit() {
|
|
34675
|
+
if (!props.companyId || !props.issueId || !manualLinkReference.trim()) {
|
|
34676
|
+
return;
|
|
34677
|
+
}
|
|
34678
|
+
setManualLinkPending(true);
|
|
34679
|
+
try {
|
|
34680
|
+
const result = await linkGitHubItem({
|
|
34681
|
+
companyId: props.companyId,
|
|
34682
|
+
issueId: props.issueId,
|
|
34683
|
+
kind: manualLinkKind,
|
|
34684
|
+
reference: manualLinkReference.trim()
|
|
34685
|
+
});
|
|
34686
|
+
setManualLinkOpen(false);
|
|
34687
|
+
setManualLinkReference("");
|
|
34688
|
+
await details.refresh();
|
|
34689
|
+
notifyGitHubSyncPullRequestsChanged();
|
|
34690
|
+
toast({
|
|
34691
|
+
title: "GitHub link saved",
|
|
34692
|
+
body: result.kind === "pull_request" ? `Linked pull request #${result.githubPullRequestNumber ?? manualLinkReference.trim()}.` : `Linked issue #${result.githubIssueNumber ?? manualLinkReference.trim()}.`,
|
|
34693
|
+
tone: "success"
|
|
34694
|
+
});
|
|
34695
|
+
} catch (error) {
|
|
34696
|
+
toast({
|
|
34697
|
+
title: "Unable to link GitHub item",
|
|
34698
|
+
body: getActionErrorMessage(error, "GitHub Sync could not save this link."),
|
|
34699
|
+
tone: "error"
|
|
34700
|
+
});
|
|
34701
|
+
} finally {
|
|
34702
|
+
setManualLinkPending(false);
|
|
34703
|
+
}
|
|
34704
|
+
}
|
|
34549
34705
|
return /* @__PURE__ */ jsxs2("section", { className: "ghsync-issue-detail", style: props.themeVars, children: [
|
|
34550
34706
|
/* @__PURE__ */ jsx2("style", { children: EXTENSION_SURFACE_STYLES }),
|
|
34551
34707
|
detailTabState === "loading" ? /* @__PURE__ */ jsx2("p", { className: "ghsync-extension-empty", children: "Loading GitHub sync details\u2026" }) : null,
|
|
34552
34708
|
detailTabState === "error" && details.error ? /* @__PURE__ */ jsx2("p", { className: "ghsync-extension-empty", children: details.error.message }) : null,
|
|
34709
|
+
detailTabState === "unlinked" ? /* @__PURE__ */ jsx2("div", { className: "ghsync-issue-detail__intro", children: /* @__PURE__ */ jsxs2("div", { className: "ghsync-extension-heading", children: [
|
|
34710
|
+
/* @__PURE__ */ jsxs2("div", { className: "ghsync-issue-detail__headline", children: [
|
|
34711
|
+
/* @__PURE__ */ jsx2("h4", { children: "GitHub link" }),
|
|
34712
|
+
/* @__PURE__ */ jsx2("p", { children: "No GitHub issue or pull request is linked to this Paperclip issue yet." })
|
|
34713
|
+
] }),
|
|
34714
|
+
/* @__PURE__ */ jsx2("div", { className: "ghsync-issue-detail__actions", children: /* @__PURE__ */ jsx2(
|
|
34715
|
+
"button",
|
|
34716
|
+
{
|
|
34717
|
+
type: "button",
|
|
34718
|
+
className: getPluginActionClassName({
|
|
34719
|
+
variant: "secondary",
|
|
34720
|
+
size: "sm",
|
|
34721
|
+
extraClassName: "ghsync-extension-link"
|
|
34722
|
+
}),
|
|
34723
|
+
onClick: () => setManualLinkOpen(true),
|
|
34724
|
+
children: /* @__PURE__ */ jsx2(GitHubButtonLabel, { label: "Link GitHub item" })
|
|
34725
|
+
}
|
|
34726
|
+
) })
|
|
34727
|
+
] }) }) : null,
|
|
34553
34728
|
detailTabState === "ready" && issueDetails ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
34554
34729
|
/* @__PURE__ */ jsxs2("div", { className: "ghsync-extension-heading", children: [
|
|
34555
34730
|
/* @__PURE__ */ jsxs2("div", { className: "ghsync-issue-detail__headline", children: [
|
|
34556
|
-
/* @__PURE__ */
|
|
34557
|
-
"Issue #",
|
|
34558
|
-
issueDetails.githubIssueNumber
|
|
34559
|
-
] }),
|
|
34731
|
+
/* @__PURE__ */ jsx2("h4", { children: issueDetailsKind === "pull_request" ? `Pull request #${issueDetails.githubPullRequestNumber ?? ""}` : `Issue #${issueDetails.githubIssueNumber ?? ""}` }),
|
|
34560
34732
|
/* @__PURE__ */ jsx2("p", { children: formatGitHubRepositoryLabel(issueDetails.repositoryUrl) }),
|
|
34733
|
+
issueDetailsKind === "pull_request" && issueDetails.title ? /* @__PURE__ */ jsx2("p", { children: issueDetails.title }) : null,
|
|
34561
34734
|
issueDetails.creator ? /* @__PURE__ */ jsxs2("div", { className: "ghsync-issue-detail__creator-row", children: [
|
|
34562
34735
|
/* @__PURE__ */ jsx2("span", { className: "ghsync-issue-detail__creator-label", children: "Creator" }),
|
|
34563
34736
|
/* @__PURE__ */ jsxs2(
|
|
@@ -34599,10 +34772,10 @@ function GitHubSyncIssueDetailTabContent(props) {
|
|
|
34599
34772
|
)
|
|
34600
34773
|
}
|
|
34601
34774
|
) : null,
|
|
34602
|
-
/* @__PURE__ */ jsx2(
|
|
34775
|
+
githubUrl ? /* @__PURE__ */ jsx2(
|
|
34603
34776
|
"a",
|
|
34604
34777
|
{
|
|
34605
|
-
href:
|
|
34778
|
+
href: githubUrl,
|
|
34606
34779
|
target: "_blank",
|
|
34607
34780
|
rel: "noreferrer",
|
|
34608
34781
|
className: getPluginActionClassName({
|
|
@@ -34612,17 +34785,17 @@ function GitHubSyncIssueDetailTabContent(props) {
|
|
|
34612
34785
|
}),
|
|
34613
34786
|
children: /* @__PURE__ */ jsx2(GitHubButtonLabel, { label: "Open on GitHub" })
|
|
34614
34787
|
}
|
|
34615
|
-
)
|
|
34788
|
+
) : null
|
|
34616
34789
|
] })
|
|
34617
34790
|
] }),
|
|
34618
34791
|
/* @__PURE__ */ jsxs2("div", { className: "ghsync-extension-grid", children: [
|
|
34619
34792
|
/* @__PURE__ */ jsxs2("div", { className: "ghsync-extension-metric", children: [
|
|
34620
34793
|
/* @__PURE__ */ jsx2("span", { children: "State" }),
|
|
34621
|
-
/* @__PURE__ */ jsx2("strong", { children:
|
|
34794
|
+
/* @__PURE__ */ jsx2("strong", { children: githubStateLabel })
|
|
34622
34795
|
] }),
|
|
34623
34796
|
/* @__PURE__ */ jsxs2("div", { className: "ghsync-extension-metric", children: [
|
|
34624
|
-
/* @__PURE__ */ jsx2("span", { children: "
|
|
34625
|
-
/* @__PURE__ */ jsx2("strong", { children:
|
|
34797
|
+
/* @__PURE__ */ jsx2("span", { children: "Type" }),
|
|
34798
|
+
/* @__PURE__ */ jsx2("strong", { children: issueDetailsKind === "pull_request" ? "Pull request" : "Issue" })
|
|
34626
34799
|
] }),
|
|
34627
34800
|
/* @__PURE__ */ jsxs2("div", { className: "ghsync-extension-metric", children: [
|
|
34628
34801
|
/* @__PURE__ */ jsx2("span", { children: "Linked PRs" }),
|
|
@@ -34656,7 +34829,7 @@ function GitHubSyncIssueDetailTabContent(props) {
|
|
|
34656
34829
|
`${pullRequest.repositoryUrl}:${pullRequest.number}`
|
|
34657
34830
|
)) })
|
|
34658
34831
|
] }) : null,
|
|
34659
|
-
issueDetails.labels && issueDetails.labels.length > 0 ? /* @__PURE__ */ jsxs2("div", { className: "ghsync-issue-detail__section", children: [
|
|
34832
|
+
issueDetails.kind !== "pull_request" && issueDetails.labels && issueDetails.labels.length > 0 ? /* @__PURE__ */ jsxs2("div", { className: "ghsync-issue-detail__section", children: [
|
|
34660
34833
|
/* @__PURE__ */ jsx2("div", { className: "ghsync-issue-detail__section-heading", children: "Labels" }),
|
|
34661
34834
|
/* @__PURE__ */ jsx2("div", { className: "ghsync-extension-labels", children: issueDetails.labels.map((label) => /* @__PURE__ */ jsx2(
|
|
34662
34835
|
"span",
|
|
@@ -34668,8 +34841,84 @@ function GitHubSyncIssueDetailTabContent(props) {
|
|
|
34668
34841
|
`${label.name}:${label.color ?? "none"}`
|
|
34669
34842
|
)) })
|
|
34670
34843
|
] }) : null,
|
|
34671
|
-
issueDetails.source !== "entity" ? /* @__PURE__ */ jsx2("div", { className: "ghsync-extension-note", children: "GitHub Sync recovered this link from older sync metadata. Run sync once to refresh the creator, GitHub state, labels, and linked PRs in this panel." }) : null
|
|
34672
|
-
] }) : null
|
|
34844
|
+
issueDetails.kind !== "pull_request" && issueDetails.source !== "entity" ? /* @__PURE__ */ jsx2("div", { className: "ghsync-extension-note", children: "GitHub Sync recovered this link from older sync metadata. Run sync once to refresh the creator, GitHub state, labels, and linked PRs in this panel." }) : null
|
|
34845
|
+
] }) : null,
|
|
34846
|
+
manualLinkOpen ? /* @__PURE__ */ jsx2("div", { className: "ghsync-link-modal-backdrop", onClick: closeManualLinkModal, children: /* @__PURE__ */ jsxs2(
|
|
34847
|
+
"div",
|
|
34848
|
+
{
|
|
34849
|
+
className: "ghsync-link-modal",
|
|
34850
|
+
role: "dialog",
|
|
34851
|
+
"aria-modal": "true",
|
|
34852
|
+
"aria-labelledby": "ghsync-link-modal-title",
|
|
34853
|
+
onClick: (event) => event.stopPropagation(),
|
|
34854
|
+
children: [
|
|
34855
|
+
/* @__PURE__ */ jsxs2("div", { className: "ghsync-prs-modal__header", children: [
|
|
34856
|
+
/* @__PURE__ */ jsx2("h3", { id: "ghsync-link-modal-title", children: "Link GitHub item" }),
|
|
34857
|
+
/* @__PURE__ */ jsx2("p", { children: "Enter a GitHub issue or pull request number from the mapped repository, or paste the full GitHub URL." })
|
|
34858
|
+
] }),
|
|
34859
|
+
/* @__PURE__ */ jsxs2("div", { className: "ghsync-link-kind", role: "group", "aria-label": "GitHub item type", children: [
|
|
34860
|
+
/* @__PURE__ */ jsx2(
|
|
34861
|
+
"button",
|
|
34862
|
+
{
|
|
34863
|
+
type: "button",
|
|
34864
|
+
className: manualLinkKind === "issue" ? "ghsync-link-kind__button ghsync-link-kind__button--active" : "ghsync-link-kind__button",
|
|
34865
|
+
onClick: () => setManualLinkKind("issue"),
|
|
34866
|
+
disabled: manualLinkPending,
|
|
34867
|
+
children: "Issue"
|
|
34868
|
+
}
|
|
34869
|
+
),
|
|
34870
|
+
/* @__PURE__ */ jsx2(
|
|
34871
|
+
"button",
|
|
34872
|
+
{
|
|
34873
|
+
type: "button",
|
|
34874
|
+
className: manualLinkKind === "pull_request" ? "ghsync-link-kind__button ghsync-link-kind__button--active" : "ghsync-link-kind__button",
|
|
34875
|
+
onClick: () => setManualLinkKind("pull_request"),
|
|
34876
|
+
disabled: manualLinkPending,
|
|
34877
|
+
children: "Pull request"
|
|
34878
|
+
}
|
|
34879
|
+
)
|
|
34880
|
+
] }),
|
|
34881
|
+
/* @__PURE__ */ jsxs2("div", { className: "ghsync__field", children: [
|
|
34882
|
+
/* @__PURE__ */ jsx2("label", { htmlFor: "ghsync-link-reference", children: manualLinkKind === "pull_request" ? "Pull request number or URL" : "Issue number or URL" }),
|
|
34883
|
+
/* @__PURE__ */ jsx2(
|
|
34884
|
+
"input",
|
|
34885
|
+
{
|
|
34886
|
+
id: "ghsync-link-reference",
|
|
34887
|
+
className: "ghsync__input",
|
|
34888
|
+
value: manualLinkReference,
|
|
34889
|
+
onChange: (event) => setManualLinkReference(event.currentTarget.value),
|
|
34890
|
+
placeholder: manualLinkKind === "pull_request" ? "89 or https://github.com/owner/repo/pull/89" : "88 or https://github.com/owner/repo/issues/88",
|
|
34891
|
+
disabled: manualLinkPending
|
|
34892
|
+
}
|
|
34893
|
+
)
|
|
34894
|
+
] }),
|
|
34895
|
+
/* @__PURE__ */ jsxs2("div", { className: "ghsync-prs-modal__actions", children: [
|
|
34896
|
+
/* @__PURE__ */ jsx2(
|
|
34897
|
+
"button",
|
|
34898
|
+
{
|
|
34899
|
+
type: "button",
|
|
34900
|
+
className: getPluginActionClassName({ variant: "secondary", size: "sm" }),
|
|
34901
|
+
onClick: closeManualLinkModal,
|
|
34902
|
+
disabled: manualLinkPending,
|
|
34903
|
+
children: "Cancel"
|
|
34904
|
+
}
|
|
34905
|
+
),
|
|
34906
|
+
/* @__PURE__ */ jsx2(
|
|
34907
|
+
"button",
|
|
34908
|
+
{
|
|
34909
|
+
type: "button",
|
|
34910
|
+
className: getPluginActionClassName({ variant: "primary", size: "sm" }),
|
|
34911
|
+
onClick: () => {
|
|
34912
|
+
void handleManualLinkSubmit();
|
|
34913
|
+
},
|
|
34914
|
+
disabled: !manualLinkReference.trim() || manualLinkPending,
|
|
34915
|
+
children: /* @__PURE__ */ jsx2(LoadingButtonContent, { busy: manualLinkPending, label: "Link", busyLabel: "Linking" })
|
|
34916
|
+
}
|
|
34917
|
+
)
|
|
34918
|
+
] })
|
|
34919
|
+
]
|
|
34920
|
+
}
|
|
34921
|
+
) }) : null
|
|
34673
34922
|
] });
|
|
34674
34923
|
}
|
|
34675
34924
|
function resolveGitHubIssueDetailTabState(params) {
|
|
@@ -34682,6 +34931,9 @@ function resolveGitHubIssueDetailTabState(params) {
|
|
|
34682
34931
|
if (params.detailsError) {
|
|
34683
34932
|
return "error";
|
|
34684
34933
|
}
|
|
34934
|
+
if (params.canLinkManually) {
|
|
34935
|
+
return "unlinked";
|
|
34936
|
+
}
|
|
34685
34937
|
return "hidden";
|
|
34686
34938
|
}
|
|
34687
34939
|
function GitHubSyncIssueTaskDetailView() {
|