prreviewbuddy 0.48.0 → 0.49.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/dist/server.js CHANGED
@@ -1,4 +1,4 @@
1
- import { $t as mutateWorkspace, A as createPrState, An as describeAuthorship, At as allJobs, B as toneOf, Bt as purposeOf, C as readEvents, Cn as doneVerb, Ct as forgeFor, D as announceJob, Dn as questionsOutstanding, Dt as checkReview, E as telemetryUploadConsent, En as issuesOutstanding, Et as checkCodeFreshness, F as markAllRead, Ft as saveJob, G as extractJsonText, Gn as agentFor, Gt as groupByLineage, H as withUsageRecorded, Hn as AGENT_IDS, I as markRead, In as resolveModel, J as readMarker, Jn as AgentUnavailableError, Jt as latestKissRun, K as ReviewBeingDeletedError, Kt as indexKeptIds, L as pruneNotifications, Ln as clearAgentPreference, Lt as isLiveJob, M as eventName, Mt as fail, N as headline, Nn as isCommitReview, Nt as isTerminal, O as branchOf, On as reviewerDispositions, Ot as followedBranch, P as listNotifications, Pn as git, Pt as loadJob, Q as compactQueue, R as readNotification, Rn as readAgentPreference, Rt as phasesFor, Sn as readQueue, T as recordTelemetryUploadConsent, Tn as isQuestionOutstanding, Tt as fillFileUrlTemplate, U as EXPLAIN_SIMPLY_PROMPT, Ut as isClaimed, V as unreadCount$1, Vn as STORE_ROOT, W as asString, Wt as followedRefName, Xt as lineagePosition, Y as removeWorktree, Z as relativeTime$1, Zt as loadWorkspace, _ as agentEnvOf, _n as dequeueOnComplete, _t as parseWorkspacePort, a as wasBlocked, bn as queueRemove, bt as writePortPreference, c as RefreshUnavailableError, cn as workspaceStamps, d as refreshPrContext, dn as isLifecycle, dt as BUILD_VERSION, et as readIndexToken, f as isUnchanged, fn as lifecycleAction, gn as sectionOf, gt as MIN_WORKSPACE_PORT, h as liveUpdateFor, hn as parseLifecycle, ht as MAX_WORKSPACE_PORT, i as liveJobsFor, it as readServerRecord, j as createPrUpdate, jt as endedAt, k as subjectOf, kn as processDiscussion, kt as reviewedShaOf, l as mergeUpdateInto, ln as LIFECYCLES, m as UpdateAlreadyRunningError, mn as offersLifecycle, mt as DEFAULT_WORKSPACE_PORT, n as deleteReview, nn as recentWorkspaces, nt as clearServerRecord, o as discardJob, on as touchWorkspace, ot as serverEntryExists, p as askCheckout, pn as lifecycleChip, pt as feedbackUrl, q as MANAGED_ROOT, qn as AgentCancelledError, qt as indexReviewGroups, r as lineageIds, rn as reviewedCommit, s as FETCH_TIMEOUT_MS, sn as workspaceRevision, st as spawnServer, t as deleteLineage, tn as previousKissResult, u as updateReview, un as activityLabel, ut as writeServerRecord, vn as queueAdd, vt as resolveWorkspacePort, w as record, wn as isIssueOutstanding, wt as remoteHost, x as runJob, xn as queueStamp, xt as claimRequestUrl, y as startKissJob, yn as queueAddMany, yt as statedWorkspacePort, z as removeNotification, zn as writeAgentPreference, zt as progressSteps } from "./delete_review-D52wkt66.js";
1
+ import { $ as compactQueue, A as createPrState, An as processDiscussion, At as reviewedShaOf, B as toneOf, Bn as writeAgentPreference, Bt as progressSteps, C as readEvents, Cn as readQueue, D as announceJob, Dn as issuesOutstanding, Dt as checkCodeFreshness, E as telemetryUploadConsent, En as isQuestionOutstanding, Et as fillFileUrlTemplate, F as markAllRead, Fn as git, Ft as loadJob, G as extractJsonText, Gt as followedRefName, H as withUsageRecorded, Hn as STORE_ROOT, I as markRead, It as saveJob, J as readMarker, Jn as AgentCancelledError, Jt as indexReviewGroups, K as ReviewBeingDeletedError, Kn as agentFor, Kt as groupByLineage, L as pruneNotifications, Ln as resolveModel, M as eventName, Mt as endedAt, N as headline, Nt as fail, O as branchOf, On as questionsOutstanding, Ot as checkReview, P as listNotifications, Pn as isCommitReview, Pt as isTerminal, Q as activateQueued, Qt as loadWorkspace, R as readNotification, Rn as clearAgentPreference, Rt as isLiveJob, Sn as queueStamp, St as claimRequestUrl, T as recordTelemetryUploadConsent, Tn as isIssueOutstanding, Tt as remoteHost, U as EXPLAIN_SIMPLY_PROMPT, Un as AGENT_IDS, V as unreadCount$1, Vt as purposeOf, W as asString, Wt as isClaimed, Y as removeWorktree, Yn as AgentUnavailableError, Yt as latestKissRun, Z as relativeTime$1, Zt as lineagePosition, _ as agentEnvOf, _n as parseLifecycle, _t as MIN_WORKSPACE_PORT, a as wasBlocked, at as readServerRecord, bn as queueAddMany, bt as statedWorkspacePort, c as RefreshUnavailableError, cn as workspaceRevision, ct as spawnServer, d as refreshPrContext, dn as activityLabel, dt as writeServerRecord, en as mutateWorkspace, f as isUnchanged, fn as isLifecycle, ft as BUILD_VERSION, gn as offersLifecycle, gt as MAX_WORKSPACE_PORT, h as liveUpdateFor, hn as lifecyclePill, ht as DEFAULT_WORKSPACE_PORT, i as liveJobsFor, in as reviewedCommit, j as createPrUpdate, jn as describeAuthorship, jt as allJobs, k as subjectOf, kn as reviewerDispositions, kt as followedBranch, l as mergeUpdateInto, ln as workspaceStamps, m as UpdateAlreadyRunningError, mn as lifecycleChip, mt as feedbackUrl, n as deleteReview, nn as previousKissResult, o as discardJob, p as askCheckout, pn as lifecycleAction, q as MANAGED_ROOT, qt as indexKeptIds, r as lineageIds, rn as recentWorkspaces, rt as clearServerRecord, s as FETCH_TIMEOUT_MS, sn as touchWorkspace, st as serverEntryExists, t as deleteLineage, tt as readIndexToken, u as updateReview, un as LIFECYCLES, vn as sectionOf, vt as parseWorkspacePort, w as record, wn as doneVerb, wt as forgeFor, x as runJob, xn as queueRemove, xt as writePortPreference, y as startKissJob, yn as queueAdd, yt as resolveWorkspacePort, z as removeNotification, zn as readAgentPreference, zt as phasesFor } from "./delete_review-BBjXPfMV.js";
2
2
  import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
3
3
  import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, statSync, unlinkSync, writeFileSync } from "node:fs";
4
4
  import { createHash, timingSafeEqual } from "node:crypto";
@@ -253,6 +253,14 @@ function saveItemLabel(saved) {
253
253
  return saved ? "Remove from saved" : "Save review";
254
254
  }
255
255
  /**
256
+ * The queue item, on a card and on the review's own page. "review queue" rather than "queue",
257
+ * because a menu is where somebody meets the idea for the first time. Here because the browser
258
+ * relabels it after a change, on both pages.
259
+ */
260
+ function queueItemLabel(queued) {
261
+ return queued ? "Remove from review queue" : "Add to review queue";
262
+ }
263
+ /**
256
264
  * What `Continue reviewing` opens, and whether it exists at all.
257
265
  *
258
266
  * One rule rather than an expression in the template, because "is there anything to continue" and
@@ -4698,9 +4706,30 @@ function renderReviewBody(view, sections) {
4698
4706
  ${updating(view) ? renderUpdatingDoc(view) : renderReviewDoc(view, sections)}
4699
4707
  </main>
4700
4708
  ${result ? renderAsk(view, sections, updating(view)) : ""}
4709
+ ${result ? renderAskTab() : ""}
4701
4710
  </div>`;
4702
4711
  }
4703
4712
  /**
4713
+ * Buddy AI's own way in: a tab on the window's right edge, where its pane opens.
4714
+ *
4715
+ * Out of the header, which says where the review stands; the assistant is a tool beside the review,
4716
+ * and the edge it lives on is the edge this sits on. Hidden by the stylesheet whenever the pane is
4717
+ * showing, where the chevron in the pane's own header closes it again. The pane's left border is
4718
+ * not free for it: the resize handle runs its full height.
4719
+ *
4720
+ * Horizontal, and only as wide as its words: the product reads left to right everywhere else, and
4721
+ * a vertical label was a pattern it would have used exactly once.
4722
+ *
4723
+ * Only with a standard review, like the pane. A control that opens nothing is worse than none.
4724
+ */
4725
+ function renderAskTab() {
4726
+ return `<button type="button" class="prb-ask-tab" data-ask-toggle aria-controls="prb-ask" aria-expanded="false">${ASK_TAB_ICON}<span class="prb-ask-tab-label">Buddy AI</span></button>`;
4727
+ }
4728
+ /** Four-pointed, stroked like the rail's icons, so it reads as one of the product's own marks. */
4729
+ var ASK_TAB_ICON = "<svg class=\"prb-ask-tab-icon\" viewBox=\"0 0 24 24\" width=\"14\" height=\"14\" focusable=\"false\" aria-hidden=\"true\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.75\" stroke-linejoin=\"round\"><path d=\"M12 3l1.8 5.6a2 2 0 0 0 1.3 1.3L21 12l-5.9 2.1a2 2 0 0 0-1.3 1.3L12 21l-1.8-5.6a2 2 0 0 0-1.3-1.3L3 12l5.9-2.1a2 2 0 0 0 1.3-1.3z\"/></svg>";
4730
+ /** Two chevrons pointing where the pane goes. */
4731
+ var ASK_HIDE_ICON = "<svg viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" focusable=\"false\" aria-hidden=\"true\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"m6 17 5-5-5-5M13 17l5-5-5-5\"/></svg>";
4732
+ /**
4704
4733
  * The document while an update runs: its progress and nothing else.
4705
4734
  *
4706
4735
  * Deliberately not a `.prb-view`. Views are what the rail and the hash switch between, and a page
@@ -5007,42 +5036,69 @@ function renderReviewBar(view, freshness) {
5007
5036
  <span><span class="prb-add">+${additions}</span> <span class="prb-del">&minus;${deletions}</span></span>
5008
5037
  ${freshness || view.remote ? (() => {
5009
5038
  const { label, state } = freshnessLabel(freshness ?? null, view.remote ?? null);
5010
- return `<span class="prb-fresh-status" data-fresh-status data-state="${state}">${escapeHtml$1(label)}</span>${view.token ? "<button type=\"button\" class=\"prb-fresh-check\" data-fresh-check>Check for updates</button>" : ""}`;
5039
+ return `<span class="prb-fresh-status" data-fresh-status data-state="${state}">${escapeHtml$1(label)}</span>`;
5011
5040
  })() : ""}
5012
- ${view.token ? `<button type="button" class="prb-complete" data-complete aria-pressed="${view.complete === true}">${view.complete ? "Reviewed" : "Mark reviewed"}</button>` : ""}
5013
- ${view.id ? renderIdMenu(view.id, Boolean(view.token), view.saved === true) : ""}
5014
- ${view.session.result ? "<button type=\"button\" class=\"prb-ask-toggle\" data-ask-toggle aria-expanded=\"false\">Buddy AI</button>" : ""}
5041
+ ${view.token ? renderStatePills(view) : ""}
5042
+ ${view.id ? renderIdMenu(view, freshness) : ""}
5015
5043
  </div>
5016
5044
  </div>`;
5017
5045
  }
5018
5046
  /**
5019
- * This review's ID, where somebody looking at this review would think to find it.
5047
+ * Where this review stands, as pills that say and never do.
5020
5048
  *
5021
- * In the header because the header answers "what am I looking at", and an ID is the most literal
5022
- * possible answer to that: it is the name `prreviewbuddy review --review <review> --delete` takes.
5023
- * It was on the index only, so the one page devoted to a single review was the only place that
5024
- * could not tell you which review it was, and the help text's advice amounted to reading it out of
5025
- * the address bar.
5049
+ * Two, because they answer two questions. Reviewed or In progress is what the reviewer has done;
5050
+ * Waiting or Done is what happens next with the branch. A review can be Reviewed and Waiting, so a
5051
+ * single pill would have to drop one of them. Active draws nothing, as an open pull request does
5052
+ * not: it is where every review starts, and a pill that never varies teaches nothing.
5026
5053
  *
5027
- * The same `...` and the same menu markup as the index, deliberately. One gesture, in both places
5028
- * it can be wanted, behaving identically. That includes deleting, with the same confirmation in the
5029
- * same panel and the same sentence. The list is where you land afterwards, since the page you were
5030
- * reading no longer exists. It deletes this review only, as a history row on the list does.
5054
+ * Never "New" here, because being on this page is what ends it.
5055
+ */
5056
+ function renderStatePills(view) {
5057
+ const status = view.complete ? "complete" : "in-progress";
5058
+ const pill = lifecyclePill(view.lifecycle, view.activity);
5059
+ return `<span class="prb-card-status" data-status="${status}" data-page-status>${statusLabel(status)}</span>
5060
+ <span class="prb-card-status prb-page-lifecycle" data-page-lifecycle${pill?.changed ? " data-changed" : ""}${pill ? "" : " hidden"}>${escapeHtml$1(pill?.text ?? "")}</span>`;
5061
+ }
5062
+ /**
5063
+ * Everything that can be done to this review, from the page you are reading it on.
5064
+ *
5065
+ * The header only says where the review stands; this is where that is changed. It holds what the
5066
+ * Reviews list's card menu holds, in the same words from the same registries, so nobody has to go
5067
+ * back to the list to park or queue the review they are in. Check for updates leads because it is
5068
+ * the one thing here the list does not offer, and it is here rather than in the header because the
5069
+ * page already checks by itself, every minute while visible and on coming back to the tab.
5070
+ *
5071
+ * Waiting, Done and the queue belong to the branch, so they are offered on its newest review only,
5072
+ * as on the list, where the older reviews' rows carry none. The lineage notice already points at
5073
+ * the newest one.
5031
5074
  *
5032
- * No delete where there is no server, which is the offline preview: the item would be a lie there.
5033
- * Save follows the same rule, since saving is a write to the store the preview does not have. It
5034
- * is the index's star, reachable from the page you are reading, so its words are the star's
5035
- * `aria-pressed` pair spelled out: what pressing it will do, never the state it is in.
5075
+ * Delete keeps the index's confirmation, in the same panel with the same sentence. The list is
5076
+ * where you land afterwards, since the page you were reading no longer exists.
5077
+ *
5078
+ * Nothing that writes where there is no server, which is the offline preview: each item would be a
5079
+ * lie there. Copy review ID stays, because it is the name `prreviewbuddy review --review <review>
5080
+ * --delete` takes, and the page devoted to one review should be able to say which one it is.
5036
5081
  */
5037
- function renderIdMenu(id, canWrite, saved) {
5038
- const safe = escapeHtml$1(id);
5039
- return `<div class="prb-menu" data-menu>
5082
+ function renderIdMenu(view, freshness) {
5083
+ const safe = escapeHtml$1(view.id ?? "");
5084
+ const canWrite = Boolean(view.token);
5085
+ const latest = !view.lineage || view.lineage.position >= view.lineage.total;
5086
+ const mark = view.complete ? "in-progress" : "complete";
5087
+ const branchItems = canWrite && latest;
5088
+ const items = [
5089
+ canWrite && (freshness || view.remote) ? "<button type=\"button\" class=\"prb-menu-item\" data-fresh-check>Check for updates</button>" : "",
5090
+ canWrite ? `<button type="button" class="prb-menu-item" data-mark-status="${mark}">${markItemLabel(mark)}</button>` : "",
5091
+ ...branchItems ? LIFECYCLES.map(({ id }) => `<button type="button" class="prb-menu-item" data-lifecycle-set="${id}"${offersLifecycle(id, view.lifecycle, view.activity) ? "" : " hidden"}>${escapeHtml$1(lifecycleAction(id))}</button>`) : [],
5092
+ branchItems ? `<button type="button" class="prb-menu-item" data-queue-action="${view.queued ? "remove" : "add"}">${queueItemLabel(view.queued === true)}</button>` : "",
5093
+ canWrite ? `<button type="button" class="prb-menu-item" data-save-toggle aria-pressed="${view.saved === true}">${saveItemLabel(view.saved === true)}</button>` : "",
5094
+ `<button type="button" class="prb-menu-item" data-copy-id="${safe}">Copy review ID</button>`,
5095
+ canWrite ? `<button type="button" class="prb-menu-item prb-menu-item-danger" data-delete="${safe}">Delete review</button>` : ""
5096
+ ].filter(Boolean);
5097
+ return `<div class="prb-menu" data-menu data-review-menu${[view.lifecycle ? ` data-lifecycle-state="${view.lifecycle.state}" data-lifecycle-at="${view.lifecycle.at}"` : "", view.activity ? ` data-activity-at="${view.activity.at}" data-activity-kind="${view.activity.kind}"` : ""].join("")}>
5040
5098
  <button type="button" class="prb-menu-trigger" data-menu-trigger aria-expanded="false" aria-haspopup="true" aria-label="Actions for this review">&#8943;</button>
5041
5099
  <div class="prb-menu-panel" data-menu-panel hidden>
5042
5100
  <div data-menu-items>
5043
- ${canWrite ? `<button type="button" class="prb-menu-item" data-save-toggle aria-pressed="${saved}">${saveItemLabel(saved)}</button>` : ""}
5044
- <button type="button" class="prb-menu-item" data-copy-id="${safe}">Copy review ID</button>
5045
- ${canWrite ? `<button type="button" class="prb-menu-item prb-menu-item-danger" data-delete="${safe}">Delete review</button>` : ""}
5101
+ ${items.join("\n ")}
5046
5102
  </div>
5047
5103
  ${canWrite ? `<div class="prb-menu-confirm" data-menu-confirm hidden>
5048
5104
  <p class="prb-menu-question">Delete this review?</p>
@@ -5059,7 +5115,7 @@ function renderIdMenu(id, canWrite, saved) {
5059
5115
  * Everything below the review: where else to go, and what to do to the server.
5060
5116
  *
5061
5117
  * These are in the rail rather than the header because they are not about this review. The header
5062
- * answers "what am I looking at" — branch, size, whether I am done with it, and Buddy AI — and
5118
+ * answers "what am I looking at" — branch, size, where the review stands — and
5063
5119
  * anything global sitting up there competed with that. Leaving the review is navigation, and it
5064
5120
  * belongs with the other navigation.
5065
5121
  *
@@ -5569,7 +5625,7 @@ function renderAsk(view, sections, paused = false) {
5569
5625
  const pending = view.pendingAsk ?? null;
5570
5626
  const pendingTurn = pending ? `<div class="prb-msg prb-msg-user">${escapeHtml$1(pending.question ?? "")}</div>
5571
5627
  <div class="prb-thinking" data-ask-pending><i></i><i></i><i></i><span>Reading the change…</span></div>` : "";
5572
- return `<aside class="prb-ask" aria-label="Ask Buddy AI">
5628
+ return `<aside class="prb-ask" id="prb-ask" aria-label="Ask Buddy AI">
5573
5629
  <div
5574
5630
  class="prb-ask-resize"
5575
5631
  data-ask-resize
@@ -5582,6 +5638,7 @@ function renderAsk(view, sections, paused = false) {
5582
5638
  <h2>Ask Buddy AI</h2>
5583
5639
  <span class="prb-ask-scope" data-ask-scope>whole change</span>
5584
5640
  ${renderFocusToggle("buddy", "Buddy AI")}
5641
+ <button type="button" class="prb-ask-hide" data-ask-toggle aria-controls="prb-ask" aria-label="Hide Buddy AI">${ASK_HIDE_ICON}</button>
5585
5642
  </div>
5586
5643
  ${paused ? "" : renderPromptBank(view.prompts ?? [], view.promptsCollapsed === true)}
5587
5644
  <div class="prb-ask-log" data-ask-log>
@@ -7034,7 +7091,7 @@ function renderCardMenu(group, followed, queued, status, activity) {
7034
7091
  function renderMenu(item) {
7035
7092
  const id = escapeHtml$1(item.id);
7036
7093
  const markItem = item.mark === void 0 ? "" : `<button type="button" class="prb-menu-item" data-mark-status="${item.mark}" data-mark-id="${id}">${markItemLabel(item.mark)}</button>`;
7037
- const queueItem = item.queue === void 0 ? "" : `<button type="button" class="prb-menu-item" data-queue-action="${item.queue}" data-queue-id="${id}">${item.queue === "remove" ? "Remove from review queue" : "Add to review queue"}</button>`;
7094
+ const queueItem = item.queue === void 0 ? "" : `<button type="button" class="prb-menu-item" data-queue-action="${item.queue}" data-queue-id="${id}">${queueItemLabel(item.queue === "remove")}</button>`;
7038
7095
  const lifecycleItems = item.lifecycle === void 0 ? "" : LIFECYCLES.map(({ id: target }) => `<button type="button" class="prb-menu-item" data-lifecycle-set="${target}" data-lifecycle-id="${id}"${offersLifecycle(target, item.lifecycle.stored, item.lifecycle.activity) ? "" : " hidden"}>${escapeHtml$1(lifecycleAction(target))}</button>`).join("\n ");
7039
7096
  return `<div class="prb-menu" data-menu>
7040
7097
  <button type="button" class="prb-menu-trigger" data-menu-trigger aria-expanded="false" aria-haspopup="true" aria-label="${escapeHtml$1(item.label)}">&#8943;</button>
@@ -9239,6 +9296,8 @@ async function handle(req, res, options) {
9239
9296
  if (action === "/stop") return handleStop(req, res, workspace);
9240
9297
  if (action === "/kiss") return handleKiss(req, res, workspace);
9241
9298
  if (action === "/state") return handleState(req, res, workspace);
9299
+ if (action === "/lifecycle") return handleOwnLifecycle(req, res, workspace, options.establishBaseline ?? establishBaseline);
9300
+ if (action === "/queue") return handleOwnQueue(req, res, workspace);
9242
9301
  if (action === "/delete") return handleDeleteOwn(req, res, workspace);
9243
9302
  if (action === "/event") return handleEvent(req, res, workspace);
9244
9303
  if (action === "/prefs") return handlePrefs(req, res);
@@ -9545,7 +9604,6 @@ async function handleStatus(req, res, indexToken) {
9545
9604
  current.completedAt = complete ? now : void 0;
9546
9605
  if (!complete) current.lastViewedAt = current.lastViewedAt ?? now;
9547
9606
  })) continue;
9548
- dequeueOnComplete(id, complete);
9549
9607
  changed += 1;
9550
9608
  }
9551
9609
  send(res, 200, {
@@ -9579,28 +9637,110 @@ async function handleLifecycle(req, res, indexToken, baseline) {
9579
9637
  return send(res, 400, { error: `There is no lifecycle state called \`${String(state)}\`. Choose one of ${choices}.` });
9580
9638
  }
9581
9639
  const ids = Array.isArray(body?.ids) ? body.ids.filter((id) => typeof id === "string") : [];
9582
- const now = Date.now();
9640
+ const { changed, at } = applyLifecycle(ids, state);
9641
+ send(res, 200, {
9642
+ ok: true,
9643
+ changed,
9644
+ at,
9645
+ queue: readQueue()
9646
+ });
9647
+ baselineParked(ids, state, baseline);
9648
+ }
9649
+ /**
9650
+ * The write behind every lifecycle mark, from the list or from the review's own page. Waiting and
9651
+ * Done dequeue; see `handleLifecycle`.
9652
+ */
9653
+ function applyLifecycle(ids, state) {
9654
+ const at = Date.now();
9583
9655
  let changed = 0;
9584
9656
  for (const id of ids) {
9585
9657
  if (!mutateWorkspace(id, (current) => {
9586
9658
  current.lifecycle = state === "active" ? void 0 : {
9587
9659
  state,
9588
- at: now
9660
+ at
9589
9661
  };
9590
9662
  })) continue;
9591
9663
  if (state !== "active") queueRemove(id);
9592
9664
  changed += 1;
9593
9665
  }
9666
+ return {
9667
+ changed,
9668
+ at
9669
+ };
9670
+ }
9671
+ /** After the answer is sent, so a first look at the forge never holds up the page that asked. */
9672
+ function baselineParked(ids, state, baseline) {
9673
+ if (state !== "waiting") return;
9674
+ const unseen = unobserved(ids);
9675
+ if (unseen.size > 0) baseline(unseen);
9676
+ }
9677
+ /**
9678
+ * Lifecycle and queue, asked by the review's own page on its own token.
9679
+ *
9680
+ * Both belong to the branch, and the list only ever reads them from the newest review of it, so a
9681
+ * mark written on an older one would be a write nobody sees. The page offers neither there; this
9682
+ * says why to anything that asks anyway.
9683
+ */
9684
+ function refuseUnlessLatest(res, workspace) {
9685
+ const { position, total } = lineagePosition(workspace);
9686
+ if (position >= total) return false;
9687
+ send(res, 409, { error: "A newer review of this branch exists. Waiting, Done and the review queue are set on the newest one." });
9688
+ return true;
9689
+ }
9690
+ /**
9691
+ * What the Reviews list would say about this branch: the newest analysis's creation, a push the
9692
+ * watcher saw, or a change of pull request state. Reads every record, so it is asked only where
9693
+ * it can change what is drawn.
9694
+ */
9695
+ function branchActivity(workspace, all = recentWorkspaces(Number.MAX_SAFE_INTEGER)) {
9696
+ const group = groupByLineage(all).find((candidate) => candidate.history.some((review) => review.id === workspace.id));
9697
+ return group ? reviewActivity([group]).get(group.latest.id) : void 0;
9698
+ }
9699
+ /**
9700
+ * Where the review stands, for the page's own checks to repaint from. Another tab can mark or park
9701
+ * it, and the watcher can see the branch move while the page is open.
9702
+ *
9703
+ * Activity only for a parked review: it decides nothing for an Active one, and it costs a read of
9704
+ * every record (measured 27 ms warm, 525 ms cold, on 66 reviews), once a minute per open tab.
9705
+ */
9706
+ function pageStanding(workspace) {
9707
+ const lifecycle = parseLifecycle(workspace.lifecycle) ?? null;
9708
+ return {
9709
+ complete: workspace.completedAt !== void 0,
9710
+ lifecycle,
9711
+ queued: readQueue().includes(workspace.id),
9712
+ activity: lifecycle ? branchActivity(workspace) ?? null : null
9713
+ };
9714
+ }
9715
+ /** Where this review stands after a lifecycle or queue change, which is everything the page repaints. */
9716
+ function ownStanding(id) {
9717
+ return {
9718
+ lifecycle: parseLifecycle(loadWorkspace(id)?.lifecycle) ?? null,
9719
+ queued: readQueue().includes(id)
9720
+ };
9721
+ }
9722
+ async function handleOwnLifecycle(req, res, workspace, baseline) {
9723
+ const state = (await readJson(req))?.state;
9724
+ if (!isLifecycle(state)) {
9725
+ const choices = LIFECYCLES.map((lifecycle) => lifecycle.id).join(", ");
9726
+ return send(res, 400, { error: `There is no lifecycle state called \`${String(state)}\`. Choose one of ${choices}.` });
9727
+ }
9728
+ if (refuseUnlessLatest(res, workspace)) return;
9729
+ applyLifecycle([workspace.id], state);
9594
9730
  send(res, 200, {
9595
9731
  ok: true,
9596
- changed,
9597
- at: now,
9598
- queue: readQueue()
9732
+ ...ownStanding(workspace.id)
9599
9733
  });
9600
- if (state === "waiting") {
9601
- const unseen = unobserved(ids);
9602
- if (unseen.size > 0) baseline(unseen);
9603
- }
9734
+ baselineParked([workspace.id], state, baseline);
9735
+ }
9736
+ async function handleOwnQueue(req, res, workspace) {
9737
+ const action = (await readJson(req))?.action;
9738
+ if (action !== "add" && action !== "remove") return send(res, 400, { error: "Unknown queue action." });
9739
+ if (refuseUnlessLatest(res, workspace)) return;
9740
+ const stored = applyQueue(workspace.id, action);
9741
+ if (stored === null) return send(res, 500, { error: "The queue could not be saved." });
9742
+ if (action === "add" && !stored.includes(workspace.id)) return send(res, 409, { error: `The review queue is full. It holds 50 reviews at most.` });
9743
+ send(res, 200, ownStanding(workspace.id));
9604
9744
  }
9605
9745
  /**
9606
9746
  * Which of these reviews the watcher has never seen the head of.
@@ -9713,28 +9853,17 @@ async function handleQueue(req, res, indexToken) {
9713
9853
  return addMany(res, body.ids.filter((one) => typeof one === "string"));
9714
9854
  }
9715
9855
  if (!id || !loadWorkspace(id)) return send(res, 404, { error: "No such review" });
9856
+ const stored = applyQueue(id, action);
9857
+ if (stored === null) return send(res, 500, { error: "The queue could not be saved." });
9858
+ send(res, 200, { queue: stored });
9859
+ }
9860
+ /** One review in or out of the queue, from a card or from its own page. The queue as stored, or null. */
9861
+ function applyQueue(id, action) {
9716
9862
  if (action === "add") compactQueue(readQueue());
9717
9863
  const stored = action === "add" ? queueAdd(id) : queueRemove(id);
9718
- if (stored === null) return send(res, 500, { error: "The queue could not be saved." });
9864
+ if (stored === null) return null;
9719
9865
  if (action === "add") activateQueued([id], stored);
9720
- send(res, 200, { queue: compactQueue(stored) });
9721
- }
9722
- /**
9723
- * Queueing a review puts it back in Active.
9724
- *
9725
- * The queue is work the reviewer wants surfaced next, and Waiting and Done both say the opposite; a
9726
- * queued review folded away in Done would be a contradiction the page then has to draw. Parking
9727
- * takes a review out of the queue, and this is the same rule read the other way. Only what actually
9728
- * went in: a review refused because the queue was full keeps the lifecycle it had.
9729
- */
9730
- function activateQueued(ids, queue) {
9731
- const queued = new Set(queue);
9732
- for (const one of ids) {
9733
- if (!queued.has(one) || loadWorkspace(one)?.lifecycle === void 0) continue;
9734
- mutateWorkspace(one, (current) => {
9735
- current.lifecycle = void 0;
9736
- });
9737
- }
9866
+ return compactQueue(stored);
9738
9867
  }
9739
9868
  /**
9740
9869
  * Adding a selection, and saying which of it did not go in.
@@ -9976,6 +10105,7 @@ async function sendWorkspacePage(res, workspace) {
9976
10105
  if (notice) mutateWorkspace(workspace.id, (current) => {
9977
10106
  if (current.lastUpdate?.at === notice.at) current.lastUpdate.acknowledged = true;
9978
10107
  });
10108
+ const everyReview = recentWorkspaces(Number.MAX_SAFE_INTEGER);
9979
10109
  const html = renderWorkspace({
9980
10110
  session: workspace.session,
9981
10111
  changeSet: workspace.changeSet,
@@ -10014,7 +10144,10 @@ async function sendWorkspacePage(res, workspace) {
10014
10144
  changeMap: workspace.changeMap,
10015
10145
  reviewedSha: reviewedCommit(workspace),
10016
10146
  revision: workspaceRevision(workspace),
10017
- lineage: lineagePosition(workspace),
10147
+ lineage: lineagePosition(workspace, everyReview),
10148
+ lifecycle: parseLifecycle(workspace.lifecycle),
10149
+ activity: branchActivity(workspace, everyReview),
10150
+ queued: readQueue().includes(workspace.id),
10018
10151
  job: workspace.jobId ? loadJob(workspace.jobId) : void 0,
10019
10152
  updateJob: liveUpdateFor(workspace.id),
10020
10153
  kissRun,
@@ -10134,7 +10267,8 @@ async function handleFreshness(res, workspace, quiet) {
10134
10267
  prState,
10135
10268
  kiss,
10136
10269
  kissDismissedSha: workspace.dismissedKissFreshnessSha ?? null,
10137
- revision
10270
+ revision,
10271
+ standing: pageStanding(workspace)
10138
10272
  });
10139
10273
  if (!quiet) record({
10140
10274
  event: "freshness_checked",
@@ -10151,7 +10285,8 @@ async function handleFreshness(res, workspace, quiet) {
10151
10285
  dismissedSha: workspace.dismissedFreshnessSha ?? null,
10152
10286
  kiss,
10153
10287
  kissDismissedSha: workspace.dismissedKissFreshnessSha ?? null,
10154
- revision
10288
+ revision,
10289
+ standing: pageStanding(workspace)
10155
10290
  });
10156
10291
  }
10157
10292
  /**
@@ -10609,7 +10744,8 @@ async function handleState(req, res, workspace) {
10609
10744
  send(res, 200, {
10610
10745
  ok: true,
10611
10746
  completedAt: saved.completedAt ?? null,
10612
- pinned: saved.pinned === true
10747
+ pinned: saved.pinned === true,
10748
+ queued: readQueue().includes(saved.id)
10613
10749
  });
10614
10750
  }
10615
10751
  /** What `/state` can change. A body naming none of these writes nothing. */
@@ -10627,10 +10763,7 @@ function applyState(workspace, body) {
10627
10763
  if (Array.isArray(body?.dismissedIssues)) reviewer.dismissedIssues = body.dismissedIssues.filter((entry) => typeof entry?.id === "string" && typeof entry?.sessionId === "string");
10628
10764
  if (typeof body?.dismissFreshnessSha === "string" || body?.dismissFreshnessSha === null) workspace.dismissedFreshnessSha = body.dismissFreshnessSha ?? void 0;
10629
10765
  if (typeof body?.dismissKissFreshnessSha === "string" || body?.dismissKissFreshnessSha === null) workspace.dismissedKissFreshnessSha = body.dismissKissFreshnessSha ?? void 0;
10630
- if (typeof body?.complete === "boolean") {
10631
- workspace.completedAt = body.complete ? Date.now() : void 0;
10632
- dequeueOnComplete(workspace.id, body.complete);
10633
- }
10766
+ if (typeof body?.complete === "boolean") workspace.completedAt = body.complete ? Date.now() : void 0;
10634
10767
  if (typeof body?.pinned === "boolean") workspace.pinned = body.pinned;
10635
10768
  }
10636
10769
  /** 1 MB is far more than any question or id list, and far less than a memory problem. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prreviewbuddy",
3
- "version": "0.48.0",
3
+ "version": "0.49.0",
4
4
  "description": "Review a branch or pull request in an isolated checkout, from your terminal, with the coding agent you already have installed.",
5
5
  "license": "UNLICENSED",
6
6
  "homepage": "https://prreviewbuddy.com",
@@ -1,4 +1,4 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["chunk-DdkvfxwB.js","chunk-DsF7k-Jl.js","chunk-BWjKdrB5.js","chunk-hePW80VL.js","chunk-CN9Gw02i.js","workspace.js","chunk-BeL0x-wt.js","chunk-DaUgQrSg.js","chunk-DJ4Pz6CG.js","chunk-B2kMZj3m.js","chunk-DN473Oml.js","chunk-DwZ_OKDV.js","chunk-CFLfawWY.js","chunk-Wc3Sd0cy.js","chunk-Dy-Kn_BL.js","chunk-CUxm3YXF.js","chunk-tz4nb_gp.js","chunk-BsaS8BTP.js","chunk-fybaL0A-.js","chunk-BifhSqXX.js","chunk-DS17s2tU.js","chunk-BvO9qrHb.js","chunk-nU5620mN.js","chunk-Bh1X0--a.js","chunk-Br7K6EJO.js","chunk-CGd-uY3x.js","chunk-CmOPaNov.js","chunk-C3zyi6X6.js","chunk-DOebnhRz.js","chunk-yqeNYXbH.js","chunk-CG_wK_-W.js","chunk-i2ycf8WY.js","chunk-Dx2-dNbd.js","chunk-DDhk861e.js","chunk-Wi1hfKnY.js","chunk-BYPUwVJd.js","chunk-B0sWk9pb.js","chunk-xyBkudn9.js","chunk-CU_yc7c0.js","chunk-DHwB1DNv.js","chunk-C6X32c5Y.js","chunk-DxSMoRAg.js","chunk-COmCkMOw.js","chunk-D1rSZHoG.js","chunk-BFoDCU3G.js","chunk-C-OQMol4.js","chunk-BwpXVz85.js","chunk-BKQNYMf0.js","chunk-CQhDWCuO.js","chunk-CLNPO3K2.js","chunk-gyMXflOg.js","chunk-B6QMLbPb.js","chunk-CNECTSY3.js","chunk-BveIbUwm.js","chunk-Bz6J7zHc.js","chunk-DmCmlw77.js","chunk-BNE4vRAl.js","chunk-Dgyv2z85.js","chunk-BgAz67x8.js","chunk-DYSi9-67.js","chunk-PhC9V0kv.js","chunk-CNG5uajc.js","chunk-CWJTY3LS.js","chunk-BLYKMRgX.js","chunk-B-z83rju.js","chunk-DYi0PdOM.js","chunk-I02WWcy5.js","chunk-CVHEykQZ.js","chunk-Tk2BGjOK.js","chunk-745C7DWL.js","chunk-BhOdd-9U.js","chunk-2cPIwDyu.js","chunk-CVKo9lqM.js","chunk-IT8Wx1rP.js","chunk-BOGxj-MG.js","chunk-DecH1K7C.js","chunk-BFC1myXj.js","chunk-CqXMuRFL.js","chunk-Cuz7gAE5.js","chunk-DFxPlKZ4.js","chunk-Dlx_va8c.js"])))=>i.map(i=>d[i]);
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["chunk-DdkvfxwB.js","chunk-DsF7k-Jl.js","chunk-BWjKdrB5.js","chunk-hePW80VL.js","chunk-CN9Gw02i.js","workspace.js","chunk-BeL0x-wt.js","chunk-vvGSmhmc.js","chunk-DJ4Pz6CG.js","chunk-B2kMZj3m.js","chunk-DN473Oml.js","chunk-DwZ_OKDV.js","chunk-CFLfawWY.js","chunk-Wc3Sd0cy.js","chunk-Dy-Kn_BL.js","chunk-CUxm3YXF.js","chunk-tz4nb_gp.js","chunk-BsaS8BTP.js","chunk-fybaL0A-.js","chunk-BifhSqXX.js","chunk-DS17s2tU.js","chunk-BvO9qrHb.js","chunk-nU5620mN.js","chunk-Bh1X0--a.js","chunk-Br7K6EJO.js","chunk-CGd-uY3x.js","chunk-CmOPaNov.js","chunk-C3zyi6X6.js","chunk-DOebnhRz.js","chunk-yqeNYXbH.js","chunk-CG_wK_-W.js","chunk-i2ycf8WY.js","chunk-Dx2-dNbd.js","chunk-DDhk861e.js","chunk-Wi1hfKnY.js","chunk-BYPUwVJd.js","chunk-B0sWk9pb.js","chunk-xyBkudn9.js","chunk-CU_yc7c0.js","chunk-DHwB1DNv.js","chunk-C6X32c5Y.js","chunk-DxSMoRAg.js","chunk-COmCkMOw.js","chunk-D1rSZHoG.js","chunk-BFoDCU3G.js","chunk-C-OQMol4.js","chunk-BwpXVz85.js","chunk-BKQNYMf0.js","chunk-CQhDWCuO.js","chunk-CLNPO3K2.js","chunk-gyMXflOg.js","chunk-B6QMLbPb.js","chunk-CNECTSY3.js","chunk-BveIbUwm.js","chunk-Bz6J7zHc.js","chunk-DmCmlw77.js","chunk-BNE4vRAl.js","chunk-Dgyv2z85.js","chunk-BgAz67x8.js","chunk-DYSi9-67.js","chunk-PhC9V0kv.js","chunk-CNG5uajc.js","chunk-CWJTY3LS.js","chunk-BLYKMRgX.js","chunk-B-z83rju.js","chunk-DYi0PdOM.js","chunk-I02WWcy5.js","chunk-CVHEykQZ.js","chunk-Tk2BGjOK.js","chunk-745C7DWL.js","chunk-BhOdd-9U.js","chunk-2cPIwDyu.js","chunk-CVKo9lqM.js","chunk-IT8Wx1rP.js","chunk-BOGxj-MG.js","chunk-DecH1K7C.js","chunk-BFC1myXj.js","chunk-CqXMuRFL.js","chunk-Cuz7gAE5.js","chunk-DFxPlKZ4.js","chunk-Dlx_va8c.js"])))=>i.map(i=>d[i]);
2
2
  import{t as e}from"./workspace.js";import{n as t}from"./chunk-DsF7k-Jl.js";import{h as n,m as r,p as i}from"./chunk-BWjKdrB5.js";import{$ as a,C as o,E as s,I as c,L as l,N as u,P as d,Q as f,S as p,T as m,V as h,W as g,X as _,Z as v,_ as y,b,c as x,g as S,l as C,m as w,n as T,p as E,q as D,r as O,s as k,t as A,u as j,x as M}from"./chunk-CN9Gw02i.js";import{S as N,a as ee,d as P,f as F,g as I,h as L,i as R,o as te,v as ne,x as re,y as ie}from"./chunk-DJ4Pz6CG.js";import{r as ae}from"./chunk-DN473Oml.js";import{i as oe}from"./chunk-DwZ_OKDV.js";import"./chunk-CFLfawWY.js";import{a as se}from"./chunk-Wc3Sd0cy.js";import{i as ce,n as le,r as ue,t as de}from"./chunk-CUxm3YXF.js";import{a as fe,c as pe,i as z,l as B,n as me,r as he,s as ge,t as _e}from"./chunk-tz4nb_gp.js";import{t as ve}from"./chunk-DS17s2tU.js";import{n as ye,t as be}from"./chunk-nU5620mN.js";var xe=t(e=>{let{securityLevel:t}=M(),n=i(`body`);if(t===`sandbox`){let t=i(`#i${e}`).node()?.contentDocument??document;n=i(t.body)}return n.select(`#${e}`)},`selectSvgElement`);function Se(e){let t=e?.constructor;return e===(typeof t==`function`?t.prototype:Object.prototype)}function Ce(e){if(e==null)return!0;if(re(e))return typeof e.splice!=`function`&&typeof e!=`string`&&!N(e)&&!ne(e)&&!ie(e)?!1:e.length===0;if(typeof e==`object`||typeof e==`function`){if(e instanceof Map||e instanceof Set)return e.size===0;let t=Object.keys(e);return Se(e)?t.filter(e=>e!==`constructor`).length===0:t.length===0}return!0}var we={common:k,getConfig:b,insertCluster:ye,insertEdge:z,insertEdgeLabel:fe,insertMarkers:ge,insertNode:ue,interpolateToCurve:P,labelHelper:se,log:r,positionEdgeLabel:pe},Te={},Ee=t(e=>{for(let t of e)Te[t.name]=t},`registerLayoutLoaders`);t(()=>{Ee([{name:`dagre`,loader:t(async()=>await e(()=>import(`./chunk-DdkvfxwB.js`),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22])),`loader`)},{name:`swimlane`,loader:t(async()=>await e(()=>import(`./chunk-Bh1X0--a.js`),__vite__mapDeps([23,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,22])),`loader`)},{name:`cose-bilkent`,loader:t(async()=>await e(()=>import(`./chunk-Br7K6EJO.js`),__vite__mapDeps([24,3,1,2,25])),`loader`)}])},`registerDefaultLayoutLoaders`)();var De=t(async(e,t)=>{if(!(e.layoutAlgorithm in Te))throw Error(`Unknown layout algorithm: ${e.layoutAlgorithm}`);if(e.diagramId)for(let t of e.nodes){let n=t.domId||t.id;t.domId=`${e.diagramId}-${n}`}let n=Te[e.layoutAlgorithm],r=await n.loader(),{theme:i,themeVariables:a}=e.config,{useGradient:o,gradientStart:s,gradientStop:c}=a,l=t.attr(`id`);if(t.append(`defs`).append(`filter`).attr(`id`,`${l}-drop-shadow`).attr(`height`,`130%`).attr(`width`,`130%`).append(`feDropShadow`).attr(`dx`,`4`).attr(`dy`,`4`).attr(`stdDeviation`,0).attr(`flood-opacity`,`0.06`).attr(`flood-color`,`${i?.includes(`dark`)?`#FFFFFF`:`#000000`}`),t.append(`defs`).append(`filter`).attr(`id`,`${l}-drop-shadow-small`).attr(`height`,`150%`).attr(`width`,`150%`).append(`feDropShadow`).attr(`dx`,`2`).attr(`dy`,`2`).attr(`stdDeviation`,0).attr(`flood-opacity`,`0.06`).attr(`flood-color`,`${i?.includes(`dark`)?`#FFFFFF`:`#000000`}`),o){let e=t.append(`linearGradient`).attr(`id`,t.attr(`id`)+`-gradient`).attr(`gradientUnits`,`objectBoundingBox`).attr(`x1`,`0%`).attr(`y1`,`0%`).attr(`x2`,`100%`).attr(`y2`,`0%`);e.append(`svg:stop`).attr(`offset`,`0%`).attr(`stop-color`,s).attr(`stop-opacity`,1),e.append(`svg:stop`).attr(`offset`,`100%`).attr(`stop-color`,c).attr(`stop-opacity`,1)}return r.render(e,t,we,{algorithm:n.algorithm})},`render`),Oe=t((e=``,{fallback:t=`dagre`}={})=>{if(e in Te)return e;if(t in Te)return r.warn(`Layout algorithm ${e} is not registered. Using ${t} as fallback.`),t;throw Error(`Both layout algorithms ${e} and ${t} are not registered.`)},`getRegisteredLayoutAlgorithm`);function ke(e,{edgePathsClass:t=`edges edgePaths`}={}){let n=e.insert(`g`).attr(`class`,`root`);return{clusters:n.insert(`g`).attr(`class`,`clusters`),edgePaths:n.insert(`g`).attr(`class`,t),edgeLabels:n.insert(`g`).attr(`class`,`edgeLabels`),nodes:n.insert(`g`).attr(`class`,`nodes`),rootGroups:n}}t(ke,`createLayoutElementGroups`);async function Ae(e,t){if(t.label){let{shapeSvg:n,bbox:r}=await se(e,t);t.labelBBox={width:r.width,height:r.height},n.remove()}else t.labelBBox={width:0,height:0}}t(Ae,`measureGroupLabel`);async function je(e,t,n){let r=await ue(e,t,n),i=r.node()?.getBBox()??{width:0,height:0};return t.width=i.width,t.height=i.height,r}t(je,`insertMeasuredNode`);async function Me(t,n){let r=new ve({multigraph:!0,compound:!0}),i=[...n.edges],a=M(),o=ke(t),{edgeLabels:s,nodes:c}=o,l=new Map,u=t.node()!=null;await Promise.all(n.nodes.map(async e=>{if(e.isGroup)u&&await Ae(c,e),r.setNode(e.id,{...e});else{if(u){let t=await je(c,e,{config:a,dir:e.dir});l.set(e.id,t)}r.setNode(e.id,{...e})}}));for(let e of i)u&&he(e)&&await fe(s,e),r.setEdge(e.start,e.end,{...e},e.id),n.edges.some(t=>t.id===e.id)||n.edges.push(e);if(globalThis.mermaidCaptureSizes){let{captureNodeSizes:r}=await e(async()=>{let{captureNodeSizes:e}=await import(`./chunk-CmOPaNov.js`);return{captureNodeSizes:e}},__vite__mapDeps([26,1]));r(t,n)}return{graph:r,groups:o,nodeElements:l}}t(Me,`createGraphWithElements`);var V=new Map,H=new Map,Ne=new Map,Pe=t(()=>{H.clear(),Ne.clear(),V.clear()},`clear`),Fe=t((e,t)=>{let n=H.get(t)||[];return r.trace(`In isDescendant`,t,` `,e,` = `,n.includes(e)),n.includes(e)},`isDescendant`),Ie=t((e,t)=>{let n=H.get(t)||[];return r.info(`Descendants of `,t,` is `,n),r.info(`Edge is `,e),e.v===t||e.w===t?!1:n?n.includes(e.v)||Fe(e.v,t)||Fe(e.w,t)||n.includes(e.w):(r.debug(`Tilt, `,t,`,not in descendants`),!1)},`edgeInCluster`),Le=t((e,t,n,i)=>{r.debug(`Copying children of `,e,`root`,i,`data`,t.node(e),i);let a=t.children(e)||[];e!==i&&a.push(e),r.debug(`Copying (nodes) clusterId`,e,`nodes`,a),a.forEach(a=>{if(t.children(a).length>0)Le(a,t,n,i);else{let o=t.node(a);r.info(`cp `,a,` to `,i,` with parent `,e),n.setNode(a,o),i!==t.parent(a)&&(r.debug(`Setting parent`,a,t.parent(a)),n.setParent(a,t.parent(a))),e!==i&&a!==e?(r.debug(`Setting parent`,a,e),n.setParent(a,e)):(r.info(`In copy `,e,`root`,i,`data`,t.node(e),i),r.debug(`Not Setting parent for node=`,a,`cluster!==rootId`,e!==i,`node!==clusterId`,a!==e));let s=t.edges(a);r.debug(`Copying Edges`,s),s.forEach(a=>{r.info(`Edge`,a);let o=t.edge(a.v,a.w,a.name);r.info(`Edge data`,o,i);try{Ie(a,i)?(r.info(`Copying as `,a.v,a.w,o,a.name),n.setEdge(a.v,a.w,o,a.name),r.info(`newGraph edges `,n.edges(),n.edge(n.edges()[0]))):r.info(`Skipping copy of edge `,a.v,`-->`,a.w,` rootId: `,i,` clusterId:`,e)}catch(e){r.error(e)}})}r.debug(`Removing node`,a),t.removeNode(a)})},`copy`),Re=t((e,t)=>{let n=t.children(e),r=[...n];for(let i of n)Ne.set(i,e),r=[...r,...Re(i,t)];return r},`extractDescendants`),ze=t((e,t,n)=>{let r=e.edges().filter(e=>e.v===t||e.w===t),i=e.edges().filter(e=>e.v===n||e.w===n),a=r.map(e=>({v:e.v===t?n:e.v,w:e.w===t?t:e.w})),o=i.map(e=>({v:e.v,w:e.w}));return a.filter(e=>o.some(t=>e.v===t.v&&e.w===t.w))},`findCommonEdges`),Be=t((e,t,n)=>{let i=t.children(e);if(r.trace(`Searching children of id `,e,i),i.length<1)return e;let a;for(let e of i){let r=Be(e,t,n),i=ze(t,n,r);if(r){if(i.length>0)a=r;else return r}}return a},`findNonClusterChild`),Ve=t(e=>!V.has(e)||!V.get(e).externalConnections?e:V.has(e)?V.get(e).id:e,`getAnchorId`),He=t((e,t)=>{if(!e||t>10){r.debug(`Opting out, no graph `);return}r.debug(`Opting in, graph `),e.nodes().forEach(function(t){e.children(t).length>0&&(r.debug(`Cluster identified`,t,` Replacement id in edges: `,Be(t,e,t)),H.set(t,Re(t,e)),V.set(t,{id:Be(t,e,t),clusterData:e.node(t)}))}),e.nodes().forEach(function(t){let n=e.children(t),i=e.edges();n.length>0?(r.debug(`Cluster identified`,t,H),i.forEach(e=>{Fe(e.v,t)^Fe(e.w,t)&&(r.debug(`Edge: `,e,` leaves cluster `,t),r.debug(`Descendants of XXX `,t,`: `,H.get(t)),V.get(t).externalConnections=!0)})):r.debug(`Not a cluster `,t,H)});for(let t of V.keys()){let n=V.get(t).id,r=e.parent(n);r!==t&&V.has(r)&&!V.get(r).externalConnections&&(V.get(t).id=r);let i=e.edges().some(e=>e.v===t);if(n&&V.get(t)?.externalConnections&&i&&Ke(e,n,t)){let r=qe(e,t,e.parent(n));r&&(V.get(t).id=r)}}e.edges().forEach(function(t){let n=e.edge(t);r.debug(`Edge `+t.v+` -> `+t.w+`: `+JSON.stringify(t)),r.debug(`Edge `+t.v+` -> `+t.w+`: `+JSON.stringify(e.edge(t)));let i=t.v,a=t.w;if(r.debug(`Fix XXX`,V,`ids:`,t.v,t.w,`Translating: `,V.get(t.v),` --- `,V.get(t.w)),V.get(t.v)||V.get(t.w)){if(r.debug(`Fixing and trying - removing XXX`,t.v,t.w,t.name),i=Ve(t.v),a=Ve(t.w),e.removeEdge(t.v,t.w,t.name),i!==t.v){let r=e.parent(i);V.get(r).externalConnections=!0,n.fromCluster=t.v}if(a!==t.w){let r=e.parent(a);V.get(r).externalConnections=!0,n.toCluster=t.w}r.debug(`Fix Replacing with XXX`,i,a,t.name),e.setEdge(i,a,n,t.name)}}),Ue(e,0),r.trace(V)},`adjustClustersAndEdges`),Ue=t((e,t)=>{if(t>10){r.error(`Bailing out`);return}let n=e.nodes(),i=!1;for(let t of n){let n=e.children(t);i||=n.length>0}if(!i){r.debug(`Done, no node has children`,e.nodes());return}r.debug(`Nodes = `,n,t);for(let i of n)if(r.debug(`Extracting node`,i,V,V.has(i)&&!V.get(i).externalConnections,!e.parent(i),e.node(i),e.children(`D`),` Depth `,t),!V.has(i))r.debug(`Not a cluster`,i,t);else if(!V.get(i).externalConnections&&e.children(i)&&e.children(i).length>0){r.debug(`Cluster without external connections, without a parent and with children`,i,t);let n=e.graph().rankdir===`TB`?`LR`:`TB`;V.get(i)?.clusterData?.dir&&(n=V.get(i).clusterData.dir,r.debug(`Fixing dir`,V.get(i).clusterData.dir,n));let a=new ve({multigraph:!0,compound:!0}).setGraph({rankdir:n,nodesep:50,ranksep:50,marginx:8,marginy:8}).setDefaultEdgeLabel(function(){return{}});Le(i,e,a,i),e.setNode(i,{clusterNode:!0,id:i,clusterData:V.get(i).clusterData,label:V.get(i).label,graph:a})}else r.debug(`Cluster ** `,i,` **not meeting the criteria !externalConnections:`,!V.get(i).externalConnections,` no parent: `,!e.parent(i),` children `,e.children(i)&&e.children(i).length>0,e.children(`D`),t),r.debug(V);n=e.nodes(),r.debug(`New list of nodes`,n);for(let i of n){let n=e.node(i);r.debug(` Now next level`,i,n),n?.clusterNode&&Ue(n.graph,t+1)}},`extractor`),We=t((e,t)=>{if(t.length===0)return[];let n=Object.assign([],t);return t.forEach(t=>{let r=We(e,e.children(t));n=[...n,...r]}),n},`sorter`),Ge=t(e=>We(e,e.children()),`sortNodesByHierarchy`),Ke=t((e,t,n)=>{let r=e.parent(t);for(;r&&r!==n;){let t=V.get(r);if(t&&!t.externalConnections)return!0;r=e.parent(r)}return!1},`isNodeInExtractableCluster`),qe=t((e,t,n)=>{let r=e.children(t)??[];for(let i of r){if(i===n||Fe(i,n))continue;let r=Be(i,e,t);if(r&&!Ke(e,r,t))return r}return null},`findSafeAnchorNode`);function Je({prepareLayout:e,measureLayout:n,runLayoutCore:r,paintLayout:i,afterPaint:a,paintOptions:o}){let s=n??Xe;return t(async function(t,n,c,l){let u=n.select(`g`);(c?.insertMarkers??ge)(u,t.markers,t.type,t.diagramId),Ye();let d={element:u,helpers:c,options:l};d.preparedLayout=await e?.(t,d);let f=await s(t,d),p=await r(t,d),m={...d,measure:f};i?await i(t,m,p):await Ze(t,m,o),await a?.(t,m,p)},`render`)}t(Je,`createCommonLayoutRenderer`);function Ye(){de(),_e(),be(),Pe()}t(Ye,`clearLayoutRenderState`);async function Xe(e,{element:t}){return await Me(t,e)}t(Xe,`defaultMeasureLayout`);async function Ze(e,t,n={}){let{measure:r}=t,{groups:i}=r;for(let r of n.getNodes?.(e,t)??e.nodes)n.skipNode?.(r,t)||await Qe(i,r,t,n);let a=et(e.nodes);for(let r of e.edges)tt(r,n)||await nt(i,r,a,e,n,t)}t(Ze,`paintLayoutData`);async function Qe(e,t,n,r){t.clusterNode?ce(t):$e(t,n,r)?await ye(e.clusters,t):ce(t)}t(Qe,`paintLayoutNode`);function $e(e,t,n){return e.isGroup===!0&&(n.isCluster?.(e,t)??!0)}t($e,`shouldPaintAsCluster`);function et(e){let t=new Map;for(let n of e)n?.id&&t.set(n.id,n);return t}t(et,`buildNodeLookup`);function tt(e,t){return e.isLayoutOnly||!!t.skipEdge?.(e)}t(tt,`shouldSkipPaintEdge`);async function nt(e,t,n,r,i,a){let o=z(e.edgePaths,{...t},i.clusterDb??new Map,r.type,rt(t.start,t,n,a,i),rt(t.end,t,n,a,i),r.diagramId,it(t,i));he(t)&&(me.has(t.id)||await fe(e.edgeLabels,t),at(t,o))}t(nt,`paintLayoutEdge`);function rt(e,t,n,r,i){return i.getEdgeNode?.(e,t,r)??(e?n.get(e)??{}:{})}t(rt,`getRenderedNode`);function it(e,t){return typeof t.skipIntersect==`function`?t.skipIntersect(e):t.skipIntersect??!1}t(it,`shouldSkipIntersect`);function at(e,t){let n=t?.updatedPath??t?.originalPath,i=b(),{subGraphTitleTotalMargin:a}=le({flowchart:i.flowchart??{}});if(e.label){let i=me.get(e.id),o=e.x,s=e.y;if(n){let i=I.calcLabelPosition(n);r.debug(`Moving label `+e.label+` from (`,o,`,`,s,`) to (`,i.x,`,`,i.y,`) abc88`),t?.updatedPath&&(o=i.x,s=i.y)}i.attr(`transform`,`translate(${o}, ${s+a/2})`)}if(e?.startLabelLeft){let t=B.get(e.id).startLeft,r=e?.x,i=e?.y;if(n){let t=I.calcTerminalLabelPosition(e.arrowTypeStart?10:0,`start_left`,n);r=t.x,i=t.y}t.attr(`transform`,`translate(${r}, ${i})`)}if(e.startLabelRight){let t=B.get(e.id).startRight,r=e.x,i=e.y;if(n){let t=I.calcTerminalLabelPosition(e.arrowTypeStart?10:0,`start_right`,n);r=t.x,i=t.y}t.attr(`transform`,`translate(${r}, ${i})`)}if(e.endLabelLeft){let t=B.get(e.id).endLeft,r=e.x,i=e.y;if(n){let t=I.calcTerminalLabelPosition(e.arrowTypeEnd?10:0,`end_left`,n);r=t.x,i=t.y}t.attr(`transform`,`translate(${r}, ${i})`)}if(e.endLabelRight){let t=B.get(e.id).endRight,r=e.x,i=e.y;if(n){let t=I.calcTerminalLabelPosition(e.arrowTypeEnd?10:0,`end_right`,n);r=t.x,i=t.y}t.attr(`transform`,`translate(${r}, ${i})`)}}t(at,`positionRenderedEdgeLabel`);function ot(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,`default`)?e.default:e}t(ot,`getDefaultExportFromCjs`);var U={},st={},W={},ct;function G(){if(ct)return W;ct=1;function e(e){return e==null}t(e,`isNothing`);function n(e){return typeof e==`object`&&!!e}t(n,`isObject`);function r(t){return Array.isArray(t)?t:e(t)?[]:[t]}t(r,`toArray`);function i(e,t){if(t){let n=Object.keys(t);for(let r=0,i=n.length;r<i;r+=1){let i=n[r];e[i]=t[i]}}return e}t(i,`extend`);function a(e,t){let n=``;for(let r=0;r<t;r+=1)n+=e;return n}t(a,`repeat`);function o(e){return e===0&&1/e==-1/0}return t(o,`isNegativeZero`),W.isNothing=e,W.isObject=n,W.toArray=r,W.repeat=a,W.isNegativeZero=o,W.extend=i,W}t(G,`requireCommon`);var lt,ut;function dt(){if(ut)return lt;ut=1;function e(e,t){let n=``,r=e.reason||`(unknown reason)`;return e.mark?(e.mark.name&&(n+=`in "`+e.mark.name+`" `),n+=`(`+(e.mark.line+1)+`:`+(e.mark.column+1)+`)`,!t&&e.mark.snippet&&(n+=`
3
3
 
4
4
  `+e.mark.snippet),r+` `+n):r}t(e,`formatError`);function n(t,n){Error.call(this),this.name=`YAMLException`,this.reason=t,this.mark=n,this.message=e(this,!1),Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):this.stack=Error().stack||``}return t(n,`YAMLException2`),n.prototype=Object.create(Error.prototype),n.prototype.constructor=n,n.prototype.toString=t(function(t){return this.name+`: `+e(this,t)},`toString`),lt=n,lt}t(dt,`requireException`);var ft,pt;function mt(){if(pt)return ft;pt=1;let e=G();function n(e,t,n,r,i){let a=``,o=``,s=Math.floor(i/2)-1;return r-t>s&&(a=` ... `,t=r-s+a.length),n-r>s&&(o=` ...`,n=r+s-o.length),{str:a+e.slice(t,n).replace(/\t/g,`→`)+o,pos:r-t+a.length}}t(n,`getLine`);function r(t,n){return e.repeat(` `,n-t.length)+t}t(r,`padStart`);function i(t,i){if(i=Object.create(i||null),!t.buffer)return null;i.maxLength||(i.maxLength=79),typeof i.indent!=`number`&&(i.indent=1),typeof i.linesBefore!=`number`&&(i.linesBefore=3),typeof i.linesAfter!=`number`&&(i.linesAfter=2);let a=/\r?\n|\r|\0/g,o=[0],s=[],c,l=-1;for(;c=a.exec(t.buffer);)s.push(c.index),o.push(c.index+c[0].length),t.position<=c.index&&l<0&&(l=o.length-2);l<0&&(l=o.length-1);let u=``,d=Math.min(t.line+i.linesAfter,s.length).toString().length,f=i.maxLength-(i.indent+d+3);for(let a=1;a<=i.linesBefore&&!(l-a<0);a++){let c=n(t.buffer,o[l-a],s[l-a],t.position-(o[l]-o[l-a]),f);u=e.repeat(` `,i.indent)+r((t.line-a+1).toString(),d)+` | `+c.str+`
@@ -1 +1 @@
1
- var e=`prb-scroll-keep`;function t(t,r){let i=()=>`${t.location.pathname}${t.location.hash}`;t.addEventListener(`pagehide`,()=>{let n={key:i(),pane:r?.scrollTop??0,window:t.scrollY};try{t.sessionStorage.setItem(e,JSON.stringify(n))}catch{}});let a=null;try{let n=t.sessionStorage.getItem(e);t.sessionStorage.removeItem(e),a=n?JSON.parse(n):null}catch{return}if(!a||a.key!==i()||!n(t))return;try{t.history.scrollRestoration=`manual`}catch{}r&&(r.scrollTop=a.pane),a.window&&t.scrollTo(0,a.window);let o=r?.scrollTop??0,s=a.pane;t.addEventListener(`load`,()=>{r&&r.scrollTop===o&&o!==s&&(r.scrollTop=s)},{once:!0})}function n(e){return e.performance?.getEntriesByType?.(`navigation`)[0]?.type===`reload`}async function r(e,t){try{await navigator.clipboard.writeText(t);let n=e.textContent;e.textContent=`Copied`,window.setTimeout(()=>{e.textContent=n},1200)}catch{let n=document.createElement(`input`);n.type=`text`,n.readOnly=!0,n.value=t,n.className=`prb-menu-id`,n.setAttribute(`data-id-field`,``),e.after(n),n.select()}}function i(e){return e<3e4?1e3:e<12e4?3e3:e<6e5?8e3:15e3}var a=[`all`,`queue`,`saved`,`in-progress`,`complete`],o=[`any`,`open`,`merged`,`closed`];function s(e,t){let n=`${e} review${e===1?``:`s`}`;return e===t?n:`${n} · ${t} branch${t===1?``:`es`}`}function c(e,t,n){let r={active:{shown:[],total:0},waiting:{shown:[],total:0},done:{shown:[],total:0}};for(let i of e){let e=t(i),a=r[e];a.total<n[e]&&a.shown.push(i),a.total+=1}return r}function l(){return{active:15,waiting:15,done:15}}function u(e){let t=new URLSearchParams(e.replace(/^#/,``)),n=t.get(`f`)??``,r=t.get(`pr`)??``;return{query:t.get(`q`)??``,filter:a.includes(n)?n:`all`,author:t.get(`by`)??``,pr:o.includes(r)?r:`any`}}function d(e){let t=new URLSearchParams;e.query!==``&&t.set(`q`,e.query),e.filter!==`all`&&t.set(`f`,e.filter),e.author!==``&&t.set(`by`,e.author),e.pr!==`any`&&t.set(`pr`,e.pr);let n=t.toString();return n===``?``:`#${n}`}function f(e,t){return t===`all`||t===`queue`?!0:t===`saved`?e.pinned===!0:e.status===t}function p(e,t){return t===`any`||e.prState===t}function m(e,t){return t===``||e===t}function h(e){return e===`complete`?`Mark reviewed`:`Mark in progress`}function g(e){return e?`Remove from saved`:`Save review`}function _(e,t){let n=t.query.trim().toLowerCase();return v(e.filter(e=>(!n||e.searchText.includes(n))&&f(e,t.filter)&&m(e.author,t.author)&&p(e,t.pr)),t.filter)}function v(e,t){return t===`queue`?e.filter(e=>e.queue!==void 0).sort((e,t)=>(e.queue??0)-(t.queue??0)):e}function y(e){return e===0?`Queue`:`Queue (${e})`}function b(e){return e===`complete`?`Reviewed`:e===`in-progress`?`In progress`:`New`}function x(e,t){if(e===0)return`Nothing selected`;let n=`${e} selected`;return t>0?`${n} · ${t} not shown`:n}function S(e){return e===0?`Select all`:`Select all ${e}`}function C(e){return e===0?`Delete`:`Delete ${e} review${e===1?``:`s`}`}function w(e){return`${C(e)}?`}function T(e,t,n){return e===``||t===``||t===e?`wait`:n?`hold`:`reload`}export{r as _,d as a,u as c,g as d,c as f,i as g,b as h,_ as i,y as l,x as m,C as n,l as o,S as p,w as r,h as s,s as t,T as u,t as v};
1
+ var e=`prb-scroll-keep`;function t(t,r){let i=()=>`${t.location.pathname}${t.location.hash}`;t.addEventListener(`pagehide`,()=>{let n={key:i(),pane:r?.scrollTop??0,window:t.scrollY};try{t.sessionStorage.setItem(e,JSON.stringify(n))}catch{}});let a=null;try{let n=t.sessionStorage.getItem(e);t.sessionStorage.removeItem(e),a=n?JSON.parse(n):null}catch{return}if(!a||a.key!==i()||!n(t))return;try{t.history.scrollRestoration=`manual`}catch{}r&&(r.scrollTop=a.pane),a.window&&t.scrollTo(0,a.window);let o=r?.scrollTop??0,s=a.pane;t.addEventListener(`load`,()=>{r&&r.scrollTop===o&&o!==s&&(r.scrollTop=s)},{once:!0})}function n(e){return e.performance?.getEntriesByType?.(`navigation`)[0]?.type===`reload`}async function r(e,t){try{await navigator.clipboard.writeText(t);let n=e.textContent;e.textContent=`Copied`,window.setTimeout(()=>{e.textContent=n},1200)}catch{let n=document.createElement(`input`);n.type=`text`,n.readOnly=!0,n.value=t,n.className=`prb-menu-id`,n.setAttribute(`data-id-field`,``),e.after(n),n.select()}}function i(e){return e<3e4?1e3:e<12e4?3e3:e<6e5?8e3:15e3}var a=[`all`,`queue`,`saved`,`in-progress`,`complete`],o=[`any`,`open`,`merged`,`closed`];function s(e,t){let n=`${e} review${e===1?``:`s`}`;return e===t?n:`${n} · ${t} branch${t===1?``:`es`}`}function c(e,t,n){let r={active:{shown:[],total:0},waiting:{shown:[],total:0},done:{shown:[],total:0}};for(let i of e){let e=t(i),a=r[e];a.total<n[e]&&a.shown.push(i),a.total+=1}return r}function l(){return{active:15,waiting:15,done:15}}function u(e){let t=new URLSearchParams(e.replace(/^#/,``)),n=t.get(`f`)??``,r=t.get(`pr`)??``;return{query:t.get(`q`)??``,filter:a.includes(n)?n:`all`,author:t.get(`by`)??``,pr:o.includes(r)?r:`any`}}function d(e){let t=new URLSearchParams;e.query!==``&&t.set(`q`,e.query),e.filter!==`all`&&t.set(`f`,e.filter),e.author!==``&&t.set(`by`,e.author),e.pr!==`any`&&t.set(`pr`,e.pr);let n=t.toString();return n===``?``:`#${n}`}function f(e,t){return t===`all`||t===`queue`?!0:t===`saved`?e.pinned===!0:e.status===t}function p(e,t){return t===`any`||e.prState===t}function m(e,t){return t===``||e===t}function h(e){return e===`complete`?`Mark reviewed`:`Mark in progress`}function g(e){return e?`Remove from saved`:`Save review`}function _(e){return e?`Remove from review queue`:`Add to review queue`}function v(e,t){let n=t.query.trim().toLowerCase();return y(e.filter(e=>(!n||e.searchText.includes(n))&&f(e,t.filter)&&m(e.author,t.author)&&p(e,t.pr)),t.filter)}function y(e,t){return t===`queue`?e.filter(e=>e.queue!==void 0).sort((e,t)=>(e.queue??0)-(t.queue??0)):e}function b(e){return e===0?`Queue`:`Queue (${e})`}function x(e){return e===`complete`?`Reviewed`:e===`in-progress`?`In progress`:`New`}function S(e,t){if(e===0)return`Nothing selected`;let n=`${e} selected`;return t>0?`${n} · ${t} not shown`:n}function C(e){return e===0?`Select all`:`Select all ${e}`}function w(e){return e===0?`Delete`:`Delete ${e} review${e===1?``:`s`}`}function T(e){return`${w(e)}?`}function E(e,t,n){return e===``||t===``||t===e?`wait`:n?`hold`:`reload`}var D=[{id:`active`,name:`Active`,action:`Move to active`},{id:`waiting`,name:`Waiting`,action:`Mark waiting`},{id:`done`,name:`Done`,action:`Mark done`}];function O(e){if(typeof e!=`object`||!e)return;let{state:t,at:n}=e;if(!(t!==`waiting`&&t!==`done`||typeof n!=`number`||!Number.isFinite(n)))return{state:t,at:n}}function k(e,t){if(!e)return;let n=j(e,t);return n===void 0?{text:D.find(t=>t.id===e.state).name,changed:!1}:{text:n,changed:!0}}function A(e,t){return!e||e.state===`waiting`&&M(e,t)?`active`:e.state}function j(e,t){if(!(!e||!M(e,t)))return e.state===`waiting`?`Changed while waiting`:`Changed since done`}function M(e,t){return t!==void 0&&t.kind!==`created`&&t.at>e.at}function N(e,t,n){return j(t,n)!==void 0||e!==(t?.state??`active`)}export{r as C,i as S,g as _,A as a,S as b,T as c,l as d,h as f,E as g,b as h,O as i,v as l,_ as m,k as n,s as o,u as p,N as r,w as s,j as t,d as u,c as v,t as w,x,C as y};
package/static/reviews.js CHANGED
@@ -1 +1 @@
1
- import{a as e,c as t,i as n,n as r,t as i}from"./chunk-BeL0x-wt.js";import{_ as a,a as o,c as s,f as c,g as ee,h as te,i as ne,l as re,m as ie,n as ae,o as l,p as oe,r as se,s as ce,t as le,u as ue,v as de}from"./chunk-DaUgQrSg.js";function fe(e,t){t.forEach((t,n)=>{e.children[n]!==t&&e.insertBefore(t,e.children[n]??null)})}var u=`Fetch updates`,pe=`Fetch selected`;function d(e){return`${e} ${e===1?`repository`:`repositories`}`}function me(e){return`Fetching ${d(e)}…`}function he(e){return e.fetched===0?`Could not fetch ${d(e.repositories)}`:e.fetched===e.repositories?`Fetched ${d(e.repositories)}`:`Fetched ${e.fetched} of ${d(e.repositories)}`}function ge(e,t){let n=new Set,r=new Set;for(let i of e)for(let e of i.lineage){let i=t[e];i!==void 0&&(n.add(e),r.add(i))}return{ids:[...n],repositories:r.size}}function _e(e){if(typeof e!=`object`||!e)return;let{state:t,at:n}=e;if(!(t!==`waiting`&&t!==`done`||typeof n!=`number`||!Number.isFinite(n)))return{state:t,at:n}}function ve(e,t){return!e||e.state===`waiting`&&f(e,t)?`active`:e.state}function ye(e,t){if(!(!e||!f(e,t)))return e.state===`waiting`?`Changed while waiting`:`Changed since done`}function f(e,t){return t!==void 0&&t.kind!==`created`&&t.at>e.at}function be(e,t,n){return ye(t,n)!==void 0||e!==(t?.state??`active`)}i(`/restart`);var p=[...document.querySelectorAll(`[data-card]`)].sort((e,t)=>Number(e.dataset.rank)-Number(t.dataset.rank)),m=[`active`,`waiting`,`done`],xe=Object.fromEntries(m.map(e=>[e,document.querySelector(`[data-cards="${e}"]`)])),h=document.querySelector(`.prb-index`);function Se(e){return{id:e.dataset.id??``,queue:e.dataset.queue===void 0?void 0:Number(e.dataset.queue),status:e.dataset.status??`new`,pinned:e.dataset.pinned===`true`,prState:e.dataset.prState}}var g=document.querySelector(`[data-search]`),_=document.querySelector(`[data-status-filter]`),v=document.querySelector(`[data-author-filter]`),y=document.querySelector(`[data-pr-filter]`),b=document.querySelector(`[data-no-matches]`),Ce=document.querySelector(`[data-count]`),x=l();function we(e){return{stored:_e({state:e.dataset.lifecycle,at:Number(e.dataset.lifecycleAt)}),activity:{at:Number(e.dataset.activityAt??0),kind:e.dataset.activityKind??`created`}}}function Te(e){let{stored:t,activity:n}=we(e);return ve(t,n)}var S=document.querySelector(`[data-bulk]`),C=document.querySelector(`[data-bulk-count]`),w=document.querySelector(`[data-bulk-delete]`),T=document.querySelector(`[data-bulk-question]`),E=document.querySelector(`[data-bulk-confirm]`),D=document.querySelector(`[data-bulk-actions]`),O=document.querySelector(`[data-bulk-error]`),k=document.querySelector(`[data-bulk-select-all]`),A=s(window.location.hash),j=new Set,M=!1,N=document.querySelector(`[data-fetch-updates]`),P=document.querySelector(`[data-bulk-fetch]`),F={},I=[],L=!1;function R(){let e=A.query.trim().toLowerCase();A.author!==``&&![...v?.options??[]].some(e=>e.value===A.author)&&(A.author=``);let t=ne(p.map(e=>({...Se(e),searchText:e.dataset.searchText??``,author:e.dataset.author,card:e})),{...A,query:e}).map(e=>e.card);I=t;let n=c(t,Te,x),r=new Set(m.flatMap(e=>n[e].shown));for(let e of p)e.hidden=!r.has(e);for(let e of m){let t=xe[e];t&&fe(t,n[e].shown);let r=document.querySelector(`[data-load-more="${e}"]`);if(r&&(r.hidden=n[e].total<=n[e].shown.length),e===`active`)continue;let i=document.querySelector(`[data-section="${e}"]`);i&&(i.hidden=n[e].total===0);let a=i?.querySelector(`[data-section-count]`);a&&(a.textContent=String(n[e].total))}if(g&&g.value!==A.query&&(g.value=A.query),v&&(v.value=A.author,A.author===``?delete v.dataset.active:v.dataset.active=``),y||(A.pr=`any`),y&&(y.value=A.pr,A.pr===`any`?delete y.dataset.active:y.dataset.active=``),_&&(_.value=A.filter,A.filter===`all`?delete _.dataset.active:_.dataset.active=``),Ce){let e=t.filter(e=>Te(e)===`active`),n=e.reduce((e,t)=>e+Number(t.dataset.reviews??1),0);Ce.textContent=le(n,e.length)}b&&(b.hidden=t.length>0||p.length===0),ke(t),Ve()}function z(e,t){A={...A,...e},x=l(),R();let n=`${window.location.pathname}${window.location.search}${o(A)}`;t===`push`?window.history.pushState(null,``,n):window.history.replaceState(null,``,n)}g?.addEventListener(`input`,()=>z({query:g.value},`replace`)),g?.addEventListener(`keydown`,e=>{e.key===`Escape`&&g.value!==``&&(e.preventDefault(),z({query:``},`replace`))}),_?.addEventListener(`change`,()=>{z({filter:_.value},`push`)}),v?.addEventListener(`change`,()=>{z({author:v.value},`push`)}),y?.addEventListener(`change`,()=>{z({pr:y.value},`push`)}),document.addEventListener(`click`,e=>{let t=e.target.closest(`[data-load-more]`)?.dataset.loadMore;!t||!m.includes(t)||(x={...x,[t]:x[t]+15},R())});for(let e of[`popstate`,`hashchange`])window.addEventListener(e,()=>{A=s(window.location.hash),x=l(),R()});document.addEventListener(`click`,e=>{let t=e.target.closest(`[data-pin]`);if(!t?.dataset.pin)return;e.preventDefault(),e.stopPropagation();let n=t.getAttribute(`aria-pressed`)!==`true`;t.setAttribute(`aria-pressed`,String(n)),t.innerHTML=n?`&#9733;`:`&#9734;`,t.setAttribute(`aria-label`,`${n?`Unsave`:`Save`} this review`);let r=t.closest(`[data-card]`);r&&(r.dataset.pinned=String(n)),fetch(`/pin`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({id:t.dataset.pin,pinned:n})}).catch(()=>{})});async function Ee(e,t){let n;try{let r=await fetch(`/queue`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({id:e,action:t})});if(!r.ok)return;n=(await r.json()).queue}catch{return}B(n),R()}function B(e){let t=new Map(e.map((e,t)=>[e,t]));for(let e of p){let n=t.get(e.dataset.id??``);n===void 0?delete e.dataset.queue:e.dataset.queue=String(n),n!==void 0&&e.dataset.lifecycle!==`active`&&(e.dataset.lifecycle=`active`,delete e.dataset.lifecycleAt,Ie(e))}for(let e of document.querySelectorAll(`[data-queue-action][data-queue-id]`)){let n=t.has(e.dataset.queueId??``);e.dataset.queueAction=n?`remove`:`add`,e.textContent=n?`Remove from review queue`:`Add to review queue`}let n=document.querySelector(`[data-queue-option]`);n&&(n.textContent=re(e.length))}document.addEventListener(`click`,e=>{let t=e.target.closest(`[data-history-toggle]`);if(!t)return;e.preventDefault(),e.stopPropagation();let n=t.parentElement?.querySelector(`[data-history-list]`);if(!n)return;let r=n.hidden;n.hidden=!r,t.setAttribute(`aria-expanded`,String(r))}),R();function V(e){for(let t of document.querySelectorAll(`[data-menu]`)){if(t===e)continue;let n=t.querySelector(`[data-menu-panel]`),r=t.querySelector(`[data-menu-trigger]`);n&&(n.hidden=!0),r?.setAttribute(`aria-expanded`,`false`),H(t)}}function H(e){let t=e.querySelector(`[data-menu-items]`),n=e.querySelector(`[data-menu-confirm]`);t&&(t.hidden=!1),n&&(n.hidden=!0),e.querySelector(`[data-menu-error]`)?.remove(),e.querySelector(`[data-id-field]`)?.remove()}document.addEventListener(`keydown`,e=>{e.key===`Escape`&&V()}),document.addEventListener(`click`,e=>{let t=e.target,n=t.closest(`[data-menu]`);if(!n)return void V();let r=t.closest(`[data-menu-trigger]`);if(r){e.preventDefault(),e.stopPropagation();let t=n.querySelector(`[data-menu-panel]`);if(!t)return;let i=t.hidden;V(n),H(n),t.hidden=!i,r.setAttribute(`aria-expanded`,String(i));return}let i=t.closest(`[data-copy-id]`);if(i?.dataset.copyId){e.preventDefault(),e.stopPropagation(),a(i,i.dataset.copyId);return}let o=t.closest(`[data-mark-status]`);if(o?.dataset.markId){e.preventDefault(),e.stopPropagation(),V(),Pe(o.dataset.markId,o.dataset.markStatus===`complete`);return}let s=t.closest(`[data-lifecycle-set]`);if(s?.dataset.lifecycleId){e.preventDefault(),e.stopPropagation(),V(),Fe([s.dataset.lifecycleId],s.dataset.lifecycleSet);return}let c=t.closest(`[data-queue-action]`);if(c?.dataset.queueId){e.preventDefault(),e.stopPropagation(),V(),Ee(c.dataset.queueId,c.dataset.queueAction===`remove`?`remove`:`add`);return}if(t.closest(`[data-delete]`)){e.preventDefault(),e.stopPropagation();let t=n.querySelector(`[data-menu-items]`),r=n.querySelector(`[data-menu-confirm]`);t&&(t.hidden=!0),r&&(r.hidden=!1);return}if(t.closest(`[data-cancel-delete]`)){e.preventDefault(),e.stopPropagation(),H(n);return}if(t.closest(`[data-confirm-delete]`)){e.preventDefault(),e.stopPropagation(),De(n);return}e.preventDefault(),e.stopPropagation()});async function De(e){let t=e.querySelector(`[data-delete]`),n=t?.dataset.delete;if(!n)return;let r=e.querySelector(`[data-menu-confirm]`),i=e.querySelector(`[data-confirm-delete]`);i&&(i.disabled=!0,i.textContent=`Deleting`);try{let r=await fetch(`/delete`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({id:n,scope:t?.dataset.scope??`review`})});if(r.ok)return void window.location.reload();Oe(e,(await r.json().catch(()=>null))?.error??`That could not be deleted.`)}catch{Oe(e,`The workspace server did not answer. It may have stopped.`)}i&&(i.disabled=!1,i.textContent=`Delete`),r&&(r.hidden=!0);let a=e.querySelector(`[data-menu-items]`);a&&(a.hidden=!1)}function Oe(e,t){e.querySelector(`[data-menu-error]`)?.remove();let n=document.createElement(`p`);n.className=`prb-menu-error`,n.setAttribute(`data-menu-error`,``),n.textContent=t,e.querySelector(`[data-menu-panel]`)?.append(n)}function U(e){M=e,e||j.clear(),h&&(e?h.dataset.selecting=``:delete h.dataset.selecting),document.querySelector(`[data-select-mode]`)?.setAttribute(`aria-pressed`,String(e));for(let t of document.querySelectorAll(`.prb-card-link`))e?t.setAttribute(`aria-disabled`,`true`):t.removeAttribute(`aria-disabled`);W(),R()}function W(){E&&(E.hidden=!0),D&&(D.hidden=!1),O&&(O.hidden=!0,O.textContent=``)}function ke(e){for(let e of p){let t=j.has(e.dataset.id??``),n=e.querySelector(`[data-select]`);n&&(n.checked=t),t?e.dataset.selected=``:delete e.dataset.selected}if(!S||(S.hidden=!M,!M))return;let t=new Set(e.filter(Ae).map(e=>e.dataset.id)),n=[...j].filter(e=>!t.has(e)).length;C&&(C.textContent=ie(j.size,n)),k&&(k.textContent=oe(e.length),k.disabled=e.every(e=>j.has(e.dataset.id??``))),w&&(w.textContent=ae(je()));for(let e of S.querySelectorAll(`[data-bulk-mark], [data-bulk-lifecycle], [data-bulk-queue], [data-bulk-delete]`))e.disabled=j.size===0;P&&!L&&(P.disabled=X(K()).repositories===0)}function Ae(e){return!e.hidden&&e.closest(`details`)?.open!==!1}for(let e of document.querySelectorAll(`details[data-section]`))e.addEventListener(`toggle`,()=>ke(I));document.querySelector(`[data-select-mode]`)?.addEventListener(`click`,()=>{U(!M)}),k?.addEventListener(`click`,()=>{for(let e of I)e.dataset.id&&j.add(e.dataset.id);W(),R()});function G(e){j.has(e)?j.delete(e):j.add(e),W(),R()}document.addEventListener(`change`,e=>{let t=e.target.closest(`[data-select]`);t?.dataset.select&&G(t.dataset.select)}),document.addEventListener(`click`,e=>{if(!M)return;let t=e.target,n=t.closest(`[data-card]`);n?.dataset.id&&(t.closest(`[data-select], [data-pin], [data-menu], [data-history-toggle]`)||(e.preventDefault(),G(n.dataset.id)))}),document.addEventListener(`keydown`,e=>{if(!M||e.key!==`Enter`)return;let t=e.target.closest(`.prb-card-link`)?.closest(`[data-card]`);t?.dataset.id&&(e.preventDefault(),G(t.dataset.id))});function K(){return p.filter(e=>j.has(e.dataset.id??``))}function je(){return K().reduce((e,t)=>e+Number(t.dataset.reviews??1),0)}function q(e){O&&(O.textContent=e,O.hidden=!1)}function J(e){for(let t of S?.querySelectorAll(`button`)??[])t.disabled=e}async function Me(e){let t=[...j];if(t.length!==0){J(!0);try{if(!(await fetch(`/status`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({ids:t,complete:e})})).ok)return J(!1),q(`That could not be saved. The workspace server refused it.`)}catch{return J(!1),q(`The workspace server did not answer. It may have stopped.`)}Ne(K(),e),J(!1),U(!1)}}function Ne(e,t){let n=t?`complete`:`in-progress`,r=t?`in-progress`:`complete`;for(let t of e){t.dataset.status=n;let e=t.querySelector(`.prb-card-status`);e&&(e.dataset.status=n,e.textContent=te(n));let i=t.querySelector(`[data-mark-status]`);i&&(i.dataset.markStatus=r,i.textContent=ce(r))}}async function Pe(e,t){try{if(!(await fetch(`/status`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({ids:[e],complete:t})})).ok)return}catch{return}Ne(p.filter(t=>t.dataset.id===e),t),R()}async function Fe(e,t){let n;try{let r=await fetch(`/lifecycle`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({ids:e,state:t})});n=r.ok?await r.json().catch(()=>null):null}catch{n=null}if(!n)return!1;let r=new Set(e);for(let e of p)r.has(e.dataset.id??``)&&(e.dataset.lifecycle=t,t===`active`?delete e.dataset.lifecycleAt:e.dataset.lifecycleAt=String(n.at),Ie(e));return B(n.queue),R(),!0}function Ie(e){let{stored:t,activity:n}=we(e),r=e.querySelector(`[data-lifecycle-chip]`);if(r){let e=ye(t,n);r.textContent=e??``,r.hidden=e===void 0}for(let r of e.querySelectorAll(`[data-lifecycle-set]`))r.hidden=!be(r.dataset.lifecycleSet,t,n)}async function Le(e){let t=[...j];if(t.length===0)return;J(!0);let n=await Fe(t,e);if(J(!1),!n)return q(`That could not be saved. The workspace server refused it or did not answer.`);U(!1)}async function Re(){let e=[...j];if(e.length===0)return;J(!0);let t=null;try{let n=await fetch(`/delete`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({ids:e})});if(t=n.ok?await n.json().catch(()=>null):null,!t)return J(!1),W(),q(`Nothing was deleted. The workspace server refused it.`)}catch{return J(!1),W(),q(`The workspace server did not answer. It may have stopped.`)}let n=t.blocked??[],r=new Set(n.map(e=>e.id));for(let e of K())r.has(e.dataset.id??``)||e.remove();p=p.filter(e=>e.isConnected),j.clear();for(let e of r)j.add(e);if(J(!1),W(),n.length===0)return U(!1);R(),q([...new Set(n.map(e=>e.error))].join(` `))}async function ze(){let e=K().map(e=>e.dataset.id??``).filter(Boolean);if(e.length===0)return;J(!0);let t=null;try{let n=await fetch(`/queue`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({ids:e,action:`add`})});t=n.ok?await n.json().catch(()=>null):null}catch{return J(!1),W(),q(`The workspace server did not answer. It may have stopped.`)}if(!t?.queue)return J(!1),W(),q(`Nothing was added. The workspace server refused it.`);B(t.queue);let n=t.refused??[];j.clear();for(let e of n)j.add(e.id);if(J(!1),W(),n.length===0)return U(!1);R(),q([...new Set(n.map(e=>e.error))].join(` `))}S?.addEventListener(`click`,e=>{let t=e.target;if(t.closest(`[data-bulk-queue]`))return void ze();let n=t.closest(`[data-bulk-mark]`);if(n)return void Me(n.dataset.bulkMark===`complete`);let r=t.closest(`[data-bulk-lifecycle]`);if(r)return void Le(r.dataset.bulkLifecycle);if(t.closest(`[data-bulk-delete]`)){T&&(T.textContent=se(je())),D&&(D.hidden=!0),E&&(E.hidden=!1);return}if(t.closest(`[data-bulk-confirm-delete]`))return void Re();if(t.closest(`[data-bulk-cancel-delete]`))return W();if(t.closest(`[data-bulk-cancel]`))return U(!1)}),t(window,()=>window.location.reload()),de(window,document.querySelector(`.prb-shell > main`));var Y=`prb-fetch-summary`,Be=4e3;function X(e){return ge(e.map(e=>({lineage:(e.dataset.lineage??e.dataset.id??``).split(` `).filter(Boolean)})),F)}function Ve(){N&&!L&&(N.disabled=X(I).repositories===0)}function He(e,t,n){e.textContent=t,window.setTimeout(()=>{L||(e.textContent=n)},Be)}async function Ue(){try{let e=await fetch(`/fetch-updates`);if(!e.ok)return;F=(await e.json()).targets??{}}catch{return}R()}async function We(e,t,n){let r=X(n);if(L||r.repositories===0)return;L=!0;for(let e of[N,P])e&&(e.disabled=!0);e.textContent=me(r.repositories);let i=null;try{let e=await fetch(`/fetch-updates`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({ids:r.ids})});e.ok&&(i=await e.json())}catch{}L=!1,R();let a=he(i||{repositories:r.repositories,fetched:0,failed:[],moved:0});if((i?.moved??0)>0||Q){try{window.sessionStorage.setItem(Y,a)}catch{}if(!$())return void window.location.reload();Q=!0}He(e,a,t)}try{let e=window.sessionStorage.getItem(Y);e&&(window.sessionStorage.removeItem(Y),N&&He(N,e,u))}catch{}N?.addEventListener(`click`,()=>void We(N,u,I)),P?.addEventListener(`click`,()=>void We(P,pe,K())),Ue();var Ge=document.body.dataset.indexRevision??``,Z=document.body.dataset.live===`true`?Date.now():0,Q=!1;function $(){return j.size>0||document.activeElement===g||L}function Ke(){Q&&!$()&&window.location.reload()}async function qe(){try{let t=await fetch(`/revision`);if(t.ok){e(document,!0);let n=await t.json();r(document,n),n.live&&Z===0&&(Z=Date.now()),n.live||(Z=0);let i=ue(Ge,n.revision??``,$());if(i===`reload`)return void window.location.reload();i===`hold`&&(Q=!0)}}catch{e(document,!1)}window.setTimeout(()=>void qe(),ee(Z===0?2**53-1:Date.now()-Z))}qe(),g?.addEventListener(`blur`,Ke),document.addEventListener(`click`,()=>window.setTimeout(Ke,0)),n();
1
+ import{a as e,c as t,i as n,n as r,t as i}from"./chunk-BeL0x-wt.js";import{C as a,S as o,a as s,b as c,c as ee,d as l,f as te,g as ne,h as re,i as ie,l as ae,m as oe,o as se,p as u,r as ce,s as le,t as ue,u as de,v as fe,w as pe,x as me,y as he}from"./chunk-vvGSmhmc.js";function ge(e,t){t.forEach((t,n)=>{e.children[n]!==t&&e.insertBefore(t,e.children[n]??null)})}var _e=`Fetch updates`,ve=`Fetch selected`;function d(e){return`${e} ${e===1?`repository`:`repositories`}`}function ye(e){return`Fetching ${d(e)}…`}function be(e){return e.fetched===0?`Could not fetch ${d(e.repositories)}`:e.fetched===e.repositories?`Fetched ${d(e.repositories)}`:`Fetched ${e.fetched} of ${d(e.repositories)}`}function xe(e,t){let n=new Set,r=new Set;for(let i of e)for(let e of i.lineage){let i=t[e];i!==void 0&&(n.add(e),r.add(i))}return{ids:[...n],repositories:r.size}}i(`/restart`);var f=[...document.querySelectorAll(`[data-card]`)].sort((e,t)=>Number(e.dataset.rank)-Number(t.dataset.rank)),p=[`active`,`waiting`,`done`],Se=Object.fromEntries(p.map(e=>[e,document.querySelector(`[data-cards="${e}"]`)])),m=document.querySelector(`.prb-index`);function Ce(e){return{id:e.dataset.id??``,queue:e.dataset.queue===void 0?void 0:Number(e.dataset.queue),status:e.dataset.status??`new`,pinned:e.dataset.pinned===`true`,prState:e.dataset.prState}}var h=document.querySelector(`[data-search]`),g=document.querySelector(`[data-status-filter]`),_=document.querySelector(`[data-author-filter]`),v=document.querySelector(`[data-pr-filter]`),we=document.querySelector(`[data-no-matches]`),Te=document.querySelector(`[data-count]`),y=l();function b(e){return{stored:ie({state:e.dataset.lifecycle,at:Number(e.dataset.lifecycleAt)}),activity:{at:Number(e.dataset.activityAt??0),kind:e.dataset.activityKind??`created`}}}function x(e){let{stored:t,activity:n}=b(e);return s(t,n)}var S=document.querySelector(`[data-bulk]`),C=document.querySelector(`[data-bulk-count]`),Ee=document.querySelector(`[data-bulk-delete]`),De=document.querySelector(`[data-bulk-question]`),w=document.querySelector(`[data-bulk-confirm]`),T=document.querySelector(`[data-bulk-actions]`),E=document.querySelector(`[data-bulk-error]`),D=document.querySelector(`[data-bulk-select-all]`),O=u(window.location.hash),k=new Set,A=!1,j=document.querySelector(`[data-fetch-updates]`),M=document.querySelector(`[data-bulk-fetch]`),N={},P=[],F=!1;function I(){let e=O.query.trim().toLowerCase();O.author!==``&&![..._?.options??[]].some(e=>e.value===O.author)&&(O.author=``);let t=ae(f.map(e=>({...Ce(e),searchText:e.dataset.searchText??``,author:e.dataset.author,card:e})),{...O,query:e}).map(e=>e.card);P=t;let n=fe(t,x,y),r=new Set(p.flatMap(e=>n[e].shown));for(let e of f)e.hidden=!r.has(e);for(let e of p){let t=Se[e];t&&ge(t,n[e].shown);let r=document.querySelector(`[data-load-more="${e}"]`);if(r&&(r.hidden=n[e].total<=n[e].shown.length),e===`active`)continue;let i=document.querySelector(`[data-section="${e}"]`);i&&(i.hidden=n[e].total===0);let a=i?.querySelector(`[data-section-count]`);a&&(a.textContent=String(n[e].total))}if(h&&h.value!==O.query&&(h.value=O.query),_&&(_.value=O.author,O.author===``?delete _.dataset.active:_.dataset.active=``),v||(O.pr=`any`),v&&(v.value=O.pr,O.pr===`any`?delete v.dataset.active:v.dataset.active=``),g&&(g.value=O.filter,O.filter===`all`?delete g.dataset.active:g.dataset.active=``),Te){let e=t.filter(e=>x(e)===`active`),n=e.reduce((e,t)=>e+Number(t.dataset.reviews??1),0);Te.textContent=se(n,e.length)}we&&(we.hidden=t.length>0||f.length===0),W(t),Ve()}function L(e,t){O={...O,...e},y=l(),I();let n=`${window.location.pathname}${window.location.search}${de(O)}`;t===`push`?window.history.pushState(null,``,n):window.history.replaceState(null,``,n)}h?.addEventListener(`input`,()=>L({query:h.value},`replace`)),h?.addEventListener(`keydown`,e=>{e.key===`Escape`&&h.value!==``&&(e.preventDefault(),L({query:``},`replace`))}),g?.addEventListener(`change`,()=>{L({filter:g.value},`push`)}),_?.addEventListener(`change`,()=>{L({author:_.value},`push`)}),v?.addEventListener(`change`,()=>{L({pr:v.value},`push`)}),document.addEventListener(`click`,e=>{let t=e.target.closest(`[data-load-more]`)?.dataset.loadMore;!t||!p.includes(t)||(y={...y,[t]:y[t]+15},I())});for(let e of[`popstate`,`hashchange`])window.addEventListener(e,()=>{O=u(window.location.hash),y=l(),I()});document.addEventListener(`click`,e=>{let t=e.target.closest(`[data-pin]`);if(!t?.dataset.pin)return;e.preventDefault(),e.stopPropagation();let n=t.getAttribute(`aria-pressed`)!==`true`;t.setAttribute(`aria-pressed`,String(n)),t.innerHTML=n?`&#9733;`:`&#9734;`,t.setAttribute(`aria-label`,`${n?`Unsave`:`Save`} this review`);let r=t.closest(`[data-card]`);r&&(r.dataset.pinned=String(n)),fetch(`/pin`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({id:t.dataset.pin,pinned:n})}).catch(()=>{})});async function Oe(e,t){let n;try{let r=await fetch(`/queue`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({id:e,action:t})});if(!r.ok)return;n=(await r.json()).queue}catch{return}R(n),I()}function R(e){let t=new Map(e.map((e,t)=>[e,t]));for(let e of f){let n=t.get(e.dataset.id??``);n===void 0?delete e.dataset.queue:e.dataset.queue=String(n),n!==void 0&&e.dataset.lifecycle!==`active`&&(e.dataset.lifecycle=`active`,delete e.dataset.lifecycleAt,Ie(e))}for(let e of document.querySelectorAll(`[data-queue-action][data-queue-id]`)){let n=t.has(e.dataset.queueId??``);e.dataset.queueAction=n?`remove`:`add`,e.textContent=oe(n)}let n=document.querySelector(`[data-queue-option]`);n&&(n.textContent=re(e.length))}document.addEventListener(`click`,e=>{let t=e.target.closest(`[data-history-toggle]`);if(!t)return;e.preventDefault(),e.stopPropagation();let n=t.parentElement?.querySelector(`[data-history-list]`);if(!n)return;let r=n.hidden;n.hidden=!r,t.setAttribute(`aria-expanded`,String(r))}),I();function z(e){for(let t of document.querySelectorAll(`[data-menu]`)){if(t===e)continue;let n=t.querySelector(`[data-menu-panel]`),r=t.querySelector(`[data-menu-trigger]`);n&&(n.hidden=!0),r?.setAttribute(`aria-expanded`,`false`),B(t)}}function B(e){let t=e.querySelector(`[data-menu-items]`),n=e.querySelector(`[data-menu-confirm]`);t&&(t.hidden=!1),n&&(n.hidden=!0),e.querySelector(`[data-menu-error]`)?.remove(),e.querySelector(`[data-id-field]`)?.remove()}document.addEventListener(`keydown`,e=>{e.key===`Escape`&&z()}),document.addEventListener(`click`,e=>{let t=e.target,n=t.closest(`[data-menu]`);if(!n)return void z();let r=t.closest(`[data-menu-trigger]`);if(r){e.preventDefault(),e.stopPropagation();let t=n.querySelector(`[data-menu-panel]`);if(!t)return;let i=t.hidden;z(n),B(n),t.hidden=!i,r.setAttribute(`aria-expanded`,String(i));return}let i=t.closest(`[data-copy-id]`);if(i?.dataset.copyId){e.preventDefault(),e.stopPropagation(),a(i,i.dataset.copyId);return}let o=t.closest(`[data-mark-status]`);if(o?.dataset.markId){e.preventDefault(),e.stopPropagation(),z(),Pe(o.dataset.markId,o.dataset.markStatus===`complete`);return}let s=t.closest(`[data-lifecycle-set]`);if(s?.dataset.lifecycleId){e.preventDefault(),e.stopPropagation(),z(),Fe([s.dataset.lifecycleId],s.dataset.lifecycleSet);return}let c=t.closest(`[data-queue-action]`);if(c?.dataset.queueId){e.preventDefault(),e.stopPropagation(),z(),Oe(c.dataset.queueId,c.dataset.queueAction===`remove`?`remove`:`add`);return}if(t.closest(`[data-delete]`)){e.preventDefault(),e.stopPropagation();let t=n.querySelector(`[data-menu-items]`),r=n.querySelector(`[data-menu-confirm]`);t&&(t.hidden=!0),r&&(r.hidden=!1);return}if(t.closest(`[data-cancel-delete]`)){e.preventDefault(),e.stopPropagation(),B(n);return}if(t.closest(`[data-confirm-delete]`)){e.preventDefault(),e.stopPropagation(),ke(n);return}e.preventDefault(),e.stopPropagation()});async function ke(e){let t=e.querySelector(`[data-delete]`),n=t?.dataset.delete;if(!n)return;let r=e.querySelector(`[data-menu-confirm]`),i=e.querySelector(`[data-confirm-delete]`);i&&(i.disabled=!0,i.textContent=`Deleting`);try{let r=await fetch(`/delete`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({id:n,scope:t?.dataset.scope??`review`})});if(r.ok)return void window.location.reload();V(e,(await r.json().catch(()=>null))?.error??`That could not be deleted.`)}catch{V(e,`The workspace server did not answer. It may have stopped.`)}i&&(i.disabled=!1,i.textContent=`Delete`),r&&(r.hidden=!0);let a=e.querySelector(`[data-menu-items]`);a&&(a.hidden=!1)}function V(e,t){e.querySelector(`[data-menu-error]`)?.remove();let n=document.createElement(`p`);n.className=`prb-menu-error`,n.setAttribute(`data-menu-error`,``),n.textContent=t,e.querySelector(`[data-menu-panel]`)?.append(n)}function H(e){A=e,e||k.clear(),m&&(e?m.dataset.selecting=``:delete m.dataset.selecting),document.querySelector(`[data-select-mode]`)?.setAttribute(`aria-pressed`,String(e));for(let t of document.querySelectorAll(`.prb-card-link`))e?t.setAttribute(`aria-disabled`,`true`):t.removeAttribute(`aria-disabled`);U(),I()}function U(){w&&(w.hidden=!0),T&&(T.hidden=!1),E&&(E.hidden=!0,E.textContent=``)}function W(e){for(let e of f){let t=k.has(e.dataset.id??``),n=e.querySelector(`[data-select]`);n&&(n.checked=t),t?e.dataset.selected=``:delete e.dataset.selected}if(!S||(S.hidden=!A,!A))return;let t=new Set(e.filter(Ae).map(e=>e.dataset.id)),n=[...k].filter(e=>!t.has(e)).length;C&&(C.textContent=c(k.size,n)),D&&(D.textContent=he(e.length),D.disabled=e.every(e=>k.has(e.dataset.id??``))),Ee&&(Ee.textContent=le(je()));for(let e of S.querySelectorAll(`[data-bulk-mark], [data-bulk-lifecycle], [data-bulk-queue], [data-bulk-delete]`))e.disabled=k.size===0;M&&!F&&(M.disabled=X(K()).repositories===0)}function Ae(e){return!e.hidden&&e.closest(`details`)?.open!==!1}for(let e of document.querySelectorAll(`details[data-section]`))e.addEventListener(`toggle`,()=>W(P));document.querySelector(`[data-select-mode]`)?.addEventListener(`click`,()=>{H(!A)}),D?.addEventListener(`click`,()=>{for(let e of P)e.dataset.id&&k.add(e.dataset.id);U(),I()});function G(e){k.has(e)?k.delete(e):k.add(e),U(),I()}document.addEventListener(`change`,e=>{let t=e.target.closest(`[data-select]`);t?.dataset.select&&G(t.dataset.select)}),document.addEventListener(`click`,e=>{if(!A)return;let t=e.target,n=t.closest(`[data-card]`);n?.dataset.id&&(t.closest(`[data-select], [data-pin], [data-menu], [data-history-toggle]`)||(e.preventDefault(),G(n.dataset.id)))}),document.addEventListener(`keydown`,e=>{if(!A||e.key!==`Enter`)return;let t=e.target.closest(`.prb-card-link`)?.closest(`[data-card]`);t?.dataset.id&&(e.preventDefault(),G(t.dataset.id))});function K(){return f.filter(e=>k.has(e.dataset.id??``))}function je(){return K().reduce((e,t)=>e+Number(t.dataset.reviews??1),0)}function q(e){E&&(E.textContent=e,E.hidden=!1)}function J(e){for(let t of S?.querySelectorAll(`button`)??[])t.disabled=e}async function Me(e){let t=[...k];if(t.length!==0){J(!0);try{if(!(await fetch(`/status`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({ids:t,complete:e})})).ok)return J(!1),q(`That could not be saved. The workspace server refused it.`)}catch{return J(!1),q(`The workspace server did not answer. It may have stopped.`)}Ne(K(),e),J(!1),H(!1)}}function Ne(e,t){let n=t?`complete`:`in-progress`,r=t?`in-progress`:`complete`;for(let t of e){t.dataset.status=n;let e=t.querySelector(`.prb-card-status`);e&&(e.dataset.status=n,e.textContent=me(n));let i=t.querySelector(`[data-mark-status]`);i&&(i.dataset.markStatus=r,i.textContent=te(r))}}async function Pe(e,t){try{if(!(await fetch(`/status`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({ids:[e],complete:t})})).ok)return}catch{return}Ne(f.filter(t=>t.dataset.id===e),t),I()}async function Fe(e,t){let n;try{let r=await fetch(`/lifecycle`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({ids:e,state:t})});n=r.ok?await r.json().catch(()=>null):null}catch{n=null}if(!n)return!1;let r=new Set(e);for(let e of f)r.has(e.dataset.id??``)&&(e.dataset.lifecycle=t,t===`active`?delete e.dataset.lifecycleAt:e.dataset.lifecycleAt=String(n.at),Ie(e));return R(n.queue),I(),!0}function Ie(e){let{stored:t,activity:n}=b(e),r=e.querySelector(`[data-lifecycle-chip]`);if(r){let e=ue(t,n);r.textContent=e??``,r.hidden=e===void 0}for(let r of e.querySelectorAll(`[data-lifecycle-set]`))r.hidden=!ce(r.dataset.lifecycleSet,t,n)}async function Le(e){let t=[...k];if(t.length===0)return;J(!0);let n=await Fe(t,e);if(J(!1),!n)return q(`That could not be saved. The workspace server refused it or did not answer.`);H(!1)}async function Re(){let e=[...k];if(e.length===0)return;J(!0);let t=null;try{let n=await fetch(`/delete`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({ids:e})});if(t=n.ok?await n.json().catch(()=>null):null,!t)return J(!1),U(),q(`Nothing was deleted. The workspace server refused it.`)}catch{return J(!1),U(),q(`The workspace server did not answer. It may have stopped.`)}let n=t.blocked??[],r=new Set(n.map(e=>e.id));for(let e of K())r.has(e.dataset.id??``)||e.remove();f=f.filter(e=>e.isConnected),k.clear();for(let e of r)k.add(e);if(J(!1),U(),n.length===0)return H(!1);I(),q([...new Set(n.map(e=>e.error))].join(` `))}async function ze(){let e=K().map(e=>e.dataset.id??``).filter(Boolean);if(e.length===0)return;J(!0);let t=null;try{let n=await fetch(`/queue`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({ids:e,action:`add`})});t=n.ok?await n.json().catch(()=>null):null}catch{return J(!1),U(),q(`The workspace server did not answer. It may have stopped.`)}if(!t?.queue)return J(!1),U(),q(`Nothing was added. The workspace server refused it.`);R(t.queue);let n=t.refused??[];k.clear();for(let e of n)k.add(e.id);if(J(!1),U(),n.length===0)return H(!1);I(),q([...new Set(n.map(e=>e.error))].join(` `))}S?.addEventListener(`click`,e=>{let t=e.target;if(t.closest(`[data-bulk-queue]`))return void ze();let n=t.closest(`[data-bulk-mark]`);if(n)return void Me(n.dataset.bulkMark===`complete`);let r=t.closest(`[data-bulk-lifecycle]`);if(r)return void Le(r.dataset.bulkLifecycle);if(t.closest(`[data-bulk-delete]`)){De&&(De.textContent=ee(je())),T&&(T.hidden=!0),w&&(w.hidden=!1);return}if(t.closest(`[data-bulk-confirm-delete]`))return void Re();if(t.closest(`[data-bulk-cancel-delete]`))return U();if(t.closest(`[data-bulk-cancel]`))return H(!1)}),t(window,()=>window.location.reload()),pe(window,document.querySelector(`.prb-shell > main`));var Y=`prb-fetch-summary`,Be=4e3;function X(e){return xe(e.map(e=>({lineage:(e.dataset.lineage??e.dataset.id??``).split(` `).filter(Boolean)})),N)}function Ve(){j&&!F&&(j.disabled=X(P).repositories===0)}function He(e,t,n){e.textContent=t,window.setTimeout(()=>{F||(e.textContent=n)},Be)}async function Ue(){try{let e=await fetch(`/fetch-updates`);if(!e.ok)return;N=(await e.json()).targets??{}}catch{return}I()}async function We(e,t,n){let r=X(n);if(F||r.repositories===0)return;F=!0;for(let e of[j,M])e&&(e.disabled=!0);e.textContent=ye(r.repositories);let i=null;try{let e=await fetch(`/fetch-updates`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({ids:r.ids})});e.ok&&(i=await e.json())}catch{}F=!1,I();let a=be(i||{repositories:r.repositories,fetched:0,failed:[],moved:0});if((i?.moved??0)>0||Q){try{window.sessionStorage.setItem(Y,a)}catch{}if(!$())return void window.location.reload();Q=!0}He(e,a,t)}try{let e=window.sessionStorage.getItem(Y);e&&(window.sessionStorage.removeItem(Y),j&&He(j,e,_e))}catch{}j?.addEventListener(`click`,()=>void We(j,_e,P)),M?.addEventListener(`click`,()=>void We(M,ve,K())),Ue();var Ge=document.body.dataset.indexRevision??``,Z=document.body.dataset.live===`true`?Date.now():0,Q=!1;function $(){return k.size>0||document.activeElement===h||F}function Ke(){Q&&!$()&&window.location.reload()}async function qe(){try{let t=await fetch(`/revision`);if(t.ok){e(document,!0);let n=await t.json();r(document,n),n.live&&Z===0&&(Z=Date.now()),n.live||(Z=0);let i=ne(Ge,n.revision??``,$());if(i===`reload`)return void window.location.reload();i===`hold`&&(Q=!0)}}catch{e(document,!1)}window.setTimeout(()=>void qe(),o(Z===0?2**53-1:Date.now()-Z))}qe(),h?.addEventListener(`blur`,Ke),document.addEventListener(`click`,()=>window.setTimeout(Ke,0)),n();