Merge pull request #823 from tdurieux/codex/fix-anonymize-access-height

fix: keep GitHub access controls beside the source URL
This commit is contained in:
Thomas Durieux
2026-09-10 09:06:25 -07:00
committed by GitHub
7 changed files with 103 additions and 54 deletions
+2 -2
View File
@@ -1,8 +1,8 @@
{
"core.min.js": "core.c5bd53363a.min.js",
"vendor.min.js": "vendor.0155114e4b.min.js",
"vendor.min.js": "vendor.cc9fc42458.min.js",
"mermaid.min.js": "mermaid.f848a72d16.min.js",
"all.min.css": "all.6a5e0ae79b.min.css",
"all.min.css": "all.87fb103470.min.css",
"markdown.min.js": "markdown.ad7b1d71c3.min.js",
"pdf.min.js": "pdf.eaa7573247.min.js",
"notebook.min.js": "notebook.8844e2735f.min.js",
+1 -1
View File
File diff suppressed because one or more lines are too long
+23 -14
View File
@@ -2353,12 +2353,19 @@ code {
/* ===== Anonymize Page Layout ===== */
.anonymize-page {
display: flex;
flex-direction: column;
min-height: 0;
}
/* Landing state: centered URL input */
.anonymize-landing {
flex: 1 1 0;
min-height: min-content;
display: flex;
align-items: center;
justify-content: center;
height: 100%;
padding: 20px;
}
@@ -2375,7 +2382,8 @@ code {
.anonymize-workspace {
display: flex;
flex-direction: column;
height: 100%;
flex: 1 1 0;
min-height: 0;
background: var(--canvas-bg-color);
}
.anonymize-topbar {
@@ -2576,7 +2584,7 @@ code {
/* Mobile: stack form above preview, tighten paddings */
@media (max-width: 767px) {
.anonymize-workspace { height: auto; min-height: 100%; }
.anonymize-workspace { flex: 0 0 auto; min-height: 0; }
.anonymize-topbar { padding: 14px 16px; }
.anonymize-topbar-title { font-size: 1.6rem; margin-top: 2px; }
.anonymize-split {
@@ -7120,20 +7128,21 @@ body {
.auth-legacy { border-top: 1px solid var(--border-color); padding-top: 24px; }
.auth-legacy h2 { font-size: 16px; margin: 0; }
.auth-legacy p { font-size: 13px; }
.repo-access { max-width: 1036px; margin: 24px auto 0; border-bottom: 1px solid var(--border-color); flex-shrink: 0; }
.repo-access-main { display: flex; align-items: center; justify-content: space-between; gap: 20px; padding: 12px 0; flex-wrap: wrap; }
.repo-access-heading { display: flex; align-items: center; gap: 12px; }
.repo-access-heading > i { font-size: 22px; color: var(--ink-muted); }
.repo-access-heading h2 { font-family: inherit; font-size: 13px; font-weight: 600; margin: 0 0 4px; }
.repo-access-heading p { font-size: 12px; color: var(--ink-muted); margin: 0; }
.repo-access-controls { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.source-url-label-row { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 8px 16px; margin-bottom: 8px; }
.source-url-label-row > .paper-field-label { margin: 0; }
.repo-access { margin: 0; }
.repo-access-details { margin: 12px 0 24px; }
.source-url-label-row .repo-access-switch { padding: 2px; }
.source-url-label-row .repo-access-switch button { padding: 5px 8px; font-size: 11px; }
.repo-access-main { display: flex; align-items: center; gap: 10px; padding: 0 0 8px; flex-wrap: wrap; }
.repo-access-controls { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.repo-access-switch { display: inline-flex; gap: 3px; padding: 3px; border: 1px solid var(--border-color); border-radius: 7px; flex-wrap: wrap; }
.repo-access-switch button { border: 0; border-radius: 4px; background: transparent; color: var(--ink-muted); padding: 7px 10px; font: inherit; font-size: 12px; cursor: pointer; }
.repo-access-switch button[aria-pressed="true"] { background: var(--accent-soft); color: var(--accent); opacity: 1; cursor: default; font-weight: 600; }
.repo-access-switch button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.repo-access .btn { font-size: 12px; padding: 8px 12px; }
.repo-access-note { display: flex; gap: 6px 16px; flex-wrap: wrap; padding: 0 0 14px; color: var(--ink-muted); font-size: 11px; line-height: 1.6; }
@media (max-width: 1100px) { .repo-access { margin-left: 24px; margin-right: 24px; } }
.repo-access-details .btn { font-size: 12px; padding: 8px 12px; }
.repo-access-note { display: flex; gap: 6px 16px; flex-wrap: wrap; padding: 0; color: var(--ink-muted); font-size: 11px; line-height: 1.6; }
@media (max-width: 767px) {
.auth-page { max-width: 480px; }
.auth-back, .auth-intro .paper-eyebrow, .auth-title-desktop { display: none; }
@@ -7152,6 +7161,6 @@ body {
.auth-legacy { padding-top: 20px; }
.auth-legacy h2 { font-size: 15px; }
.auth-legacy .connection-link { min-height: 44px; }
.repo-access { margin: 16px 18px 0; }
.repo-access-controls { width: 100%; gap: 12px; }
}
+39 -17
View File
@@ -1,19 +1,4 @@
<div class="anonymize-page h-100">
<aside class="repo-access" aria-label="GitHub access" v-if="githubConnections?.appEnabled &amp;&amp; githubConnections.appConnected &amp;&amp; githubConnections.oauthConnected">
<div class="repo-access-main">
<div class="repo-access-heading"><i class="fab fa-github" aria-hidden="true"></i><div><h2>{{ detectedType === 'gist' ? 'Gist access' : 'Repository access' }}</h2><p>{{ detectedType === 'gist' ? 'Gists use your OAuth connection.' : 'Choose how we read your source code.' }}</p></div></div>
<div class="repo-access-controls">
<div class="repo-access-switch" role="group" aria-label="Repository connection" v-if="!isUpdate &amp;&amp; detectedType !== 'gist'">
<button type="button" :aria-pressed="githubConnection === 'github-app'" :disabled="githubConnection === 'github-app'" @click="chooseGitHubConnection('github-app')"><i class="fas fa-shield-alt" aria-hidden="true"></i> Read-only GitHub App</button>
<button type="button" :aria-pressed="githubConnection === 'oauth'" :disabled="githubConnection === 'oauth'" @click="chooseGitHubConnection('oauth')">Legacy OAuth</button>
</div>
<span class="connection-badge" v-if="isUpdate || detectedType === 'gist'">{{ detectedType !== 'gist' &amp;&amp; githubConnection === 'github-app' ? 'Read-only GitHub App' : 'Legacy OAuth' }}</span>
<button type="button" class="btn btn-outline-ink" v-if="detectedType !== 'gist' &amp;&amp; githubConnection !== 'oauth'" @click="grantGitHubAccess()">Manage access <i class="fas fa-external-link-alt" aria-hidden="true"></i></button>
<a class="connection-link" href="/connections" v-if="isUpdate || detectedType === 'gist' || githubConnection === 'oauth'">{{ isUpdate ? 'Change connection' : 'Manage connections' }} &rarr;</a>
</div>
</div>
<div class="repo-access-note"><span v-if="detectedType !== 'gist' &amp;&amp; githubConnection !== 'oauth'">Select repositories on GitHub, then return here.</span><span><i class="fas fa-info-circle" aria-hidden="true"></i> Selected content will be published, including content from private repositories.</span></div>
</aside>
<!-- ===== STATE 1: No URL — centered input ===== -->
<div class="anonymize-landing" v-show="!(sourceUrl)">
<div class="anonymize-landing-inner">
@@ -24,12 +9,30 @@
it, strip every trace of identity, and hand you back a stable link.
</p>
<div class="form-group mt-4 mb-2">
<label class="paper-field-label" for="sourceUrl-landing">Source URL</label>
<div class="source-url-label-row">
<label class="paper-field-label" for="sourceUrl-landing">Source URL</label>
<aside class="repo-access" aria-label="GitHub access" v-if="!sourceUrl &amp;&amp; githubConnections?.appEnabled &amp;&amp; githubConnections.appConnected &amp;&amp; githubConnections.oauthConnected">
<div class="repo-access-switch" role="group" aria-label="Repository connection" v-if="!isUpdate &amp;&amp; detectedType !== 'gist'">
<button type="button" :aria-pressed="githubConnection === 'github-app'" :disabled="githubConnection === 'github-app'" @click="chooseGitHubConnection('github-app')"><i class="fas fa-shield-alt" aria-hidden="true"></i> <span class="sr-only">Read-only </span>GitHub App</button>
<button type="button" :aria-pressed="githubConnection === 'oauth'" :disabled="githubConnection === 'oauth'" @click="chooseGitHubConnection('oauth')">Legacy OAuth</button>
</div>
<span class="connection-badge" v-if="isUpdate || detectedType === 'gist'">{{ detectedType !== 'gist' &amp;&amp; githubConnection === 'github-app' ? 'Read-only GitHub App' : 'Legacy OAuth' }}</span>
</aside>
</div>
<input id="sourceUrl-landing" type="text" class="form-control form-control-lg" placeholder="https://github.com/owner/repository" v-field="{ state: viewState, set: value =&gt; { sourceUrl = value }, value: sourceUrl, form: null, options: { debounce: {default: 1000, blur: 0, click: 0}, updateOn: &#x27;default blur click&#x27; }, change: () =&gt; { urlSelected() } }">
</div>
<small class="form-text" style="color: var(--ink-muted);">
Repository, pull request (…/pull/42) and gist (gist.github.com/…) URLs are all accepted.
</small>
<aside class="repo-access-details" aria-label="GitHub access" v-if="!sourceUrl &amp;&amp; githubConnections?.appEnabled &amp;&amp; githubConnections.appConnected &amp;&amp; githubConnections.oauthConnected">
<div class="repo-access-main">
<div class="repo-access-controls">
<button type="button" class="btn btn-outline-ink" v-if="detectedType !== 'gist' &amp;&amp; githubConnection !== 'oauth'" @click="grantGitHubAccess()">Manage access <i class="fas fa-external-link-alt" aria-hidden="true"></i></button>
<a class="connection-link" href="/connections" v-if="isUpdate || detectedType === 'gist' || githubConnection === 'oauth'">{{ isUpdate ? 'Change connection' : 'Manage connections' }} &rarr;</a>
</div>
</div>
<div class="repo-access-note"><span v-if="detectedType !== 'gist' &amp;&amp; githubConnection !== 'oauth'">Select repositories on GitHub, then return here.</span><span><i class="fas fa-info-circle" aria-hidden="true"></i> Selected content will be published, including content from private repositories.</span></div>
</aside>
</div>
</div>
@@ -62,7 +65,16 @@
<div class="paper-section-eyebrow">Source</div>
<div class="form-group">
<label class="paper-field-label" for="sourceUrl">GitHub URL</label>
<div class="source-url-label-row">
<label class="paper-field-label" for="sourceUrl">GitHub URL</label>
<aside class="repo-access" aria-label="GitHub access" v-if="sourceUrl &amp;&amp; githubConnections?.appEnabled &amp;&amp; githubConnections.appConnected &amp;&amp; githubConnections.oauthConnected">
<div class="repo-access-switch" role="group" aria-label="Repository connection" v-if="!isUpdate &amp;&amp; detectedType !== 'gist'">
<button type="button" :aria-pressed="githubConnection === 'github-app'" :disabled="githubConnection === 'github-app'" @click="chooseGitHubConnection('github-app')"><i class="fas fa-shield-alt" aria-hidden="true"></i> <span class="sr-only">Read-only </span>GitHub App</button>
<button type="button" :aria-pressed="githubConnection === 'oauth'" :disabled="githubConnection === 'oauth'" @click="chooseGitHubConnection('oauth')">Legacy OAuth</button>
</div>
<span class="connection-badge" v-if="isUpdate || detectedType === 'gist'">{{ detectedType !== 'gist' &amp;&amp; githubConnection === 'github-app' ? 'Read-only GitHub App' : 'Legacy OAuth' }}</span>
</aside>
</div>
<input type="text" class="form-control" name="sourceUrl" id="sourceUrl" :disabled="isUpdate &amp;&amp; detectedType !== &#x27;repo&#x27;" placeholder="Paste a GitHub repo or pull request URL" v-field="{ state: viewState, set: value =&gt; { sourceUrl = value }, value: sourceUrl, form: &quot;anonymize&quot;, options: { debounce: {default: 1000, blur: 0, click: 0}, updateOn: &#x27;default blur click&#x27; }, change: () =&gt; { urlSelected() } }" :class="{&#x27;is-invalid&#x27;: anonymize?.sourceUrl?.invalid}">
<div class="invalid-feedback" v-show="anonymize?.sourceUrl?.errors?.github">
Please provide a valid GitHub URL.
@@ -78,6 +90,16 @@
</div>
</div>
<aside class="repo-access-details" aria-label="GitHub access" v-if="sourceUrl &amp;&amp; githubConnections?.appEnabled &amp;&amp; githubConnections.appConnected &amp;&amp; githubConnections.oauthConnected">
<div class="repo-access-main">
<div class="repo-access-controls">
<button type="button" class="btn btn-outline-ink" v-if="detectedType !== 'gist' &amp;&amp; githubConnection !== 'oauth'" @click="grantGitHubAccess()">Manage access <i class="fas fa-external-link-alt" aria-hidden="true"></i></button>
<a class="connection-link" href="/connections" v-if="isUpdate || detectedType === 'gist' || githubConnection === 'oauth'">{{ isUpdate ? 'Change connection' : 'Manage connections' }} &rarr;</a>
</div>
</div>
<div class="repo-access-note"><span v-if="detectedType !== 'gist' &amp;&amp; githubConnection !== 'oauth'">Select repositories on GitHub, then return here.</span><span><i class="fas fa-info-circle" aria-hidden="true"></i> Selected content will be published, including content from private repositories.</span></div>
</aside>
<div class="form-grid-2" v-if="detectedType === &#x27;repo&#x27;">
<div class="form-group">
<label class="paper-field-label" for="branch">Branch</label>
+8 -1
View File
@@ -1118,7 +1118,14 @@ export const anonymizeController = function (state, http, html, params, location
}
});
http.get("/github/connections").then(res => { state.githubConnections = res.data; }).catch(() => {});
http.get("/github/connections").then(res => {
state.githubConnections = res.data;
// Preserve saved resources and an explicit or restored draft choice.
if (!params.repoId && !params.pullRequestId && !params.gistId && state.githubConnection === undefined
&& res.data.appEnabled && res.data.appConnected) {
state.githubConnection = "github-app";
}
}).catch(() => {});
// URL change handler - auto-detect type
state.urlSelected = async (preserveDraft = false) => {
+19 -19
View File
File diff suppressed because one or more lines are too long
+11
View File
@@ -129,6 +129,17 @@ describe("Vue 3 UI", function () {
});
}
it("selects the connected GitHub App by default beside the source URL", async () => {
ui = await browser("/anonymize", { "/github/connections": { appEnabled: true, appConnected: true, oauthConnected: true } });
const panel = ui.window.document.querySelector(".anonymize-landing-inner .repo-access");
expect(panel).not.to.equal(null);
expect(panel.querySelector('button[aria-pressed="true"]').textContent).to.include("Read-only GitHub App");
[...panel.querySelectorAll("button")].find(b => b.textContent.includes("Legacy OAuth")).click();
await delay(30);
expect(panel.querySelector('button[aria-pressed="true"]').textContent).to.include("Legacy OAuth");
expect(ui.errors).to.deep.equal([]);
});
it("preserves redactions, identifiers and pinned commits when switching connections", async () => {
ui = await browser("/anonymize", {
"/github/connections": { appEnabled: true, appConnected: true, oauthConnected: true },