diff --git a/packages/webapp/src/files/TemplateConnectionsSection.tsx b/packages/webapp/src/files/TemplateConnectionsSection.tsx index bbac7132..e0863fee 100644 --- a/packages/webapp/src/files/TemplateConnectionsSection.tsx +++ b/packages/webapp/src/files/TemplateConnectionsSection.tsx @@ -80,6 +80,12 @@ export function TemplateConnectionsSection({ const chosen = templateConnections.get(entry.id) ?? null; const configured = orgCredentialFor(orgConnections, entry.id); const wantsOrgConfig = chosen !== null && entry.adminForm !== null; + // A provider with no admin form has no org-key path at all, so every + // branch below — which all hang off wantsOrgConfig — used to skip it. + // Selecting Google Workspace, Linear or YouTrack therefore produced a + // bare checkbox that explained nothing. They are member-authorized, so + // say that, in the sentence the org-key providers already use. + const memberOnly = chosen !== null && entry.adminForm === null; // A provider members can authorize themselves — OAuth or a token // paste — is usable without any org credential, so its admin form is // an offer, never a gate. @@ -135,6 +141,11 @@ export function TemplateConnectionsSection({ Without an org key, members sign in to {entry.title} themselves.

)} + {memberOnly && ( +

+ Members sign in to {entry.title} themselves. +

+ )} {wantsOrgConfig && !admin && !configured && ( memberPath ? (

diff --git a/packages/webapp/src/files/TemplateRepoPicker.tsx b/packages/webapp/src/files/TemplateRepoPicker.tsx index 4410e957..c6b08ca8 100644 --- a/packages/webapp/src/files/TemplateRepoPicker.tsx +++ b/packages/webapp/src/files/TemplateRepoPicker.tsx @@ -61,7 +61,7 @@ export function TemplateRepoPicker({ return (

{admin - ? 'Set up GitHub above first. Repos show up here when it saves.' + ? 'Connect GitHub above first. Repos show up here when it saves.' : 'Ask an admin to set up GitHub above. Repos show up here after that.'}

); diff --git a/packages/webapp/test/template-screen.test.tsx b/packages/webapp/test/template-screen.test.tsx index 707ab5e9..5939a5d3 100644 --- a/packages/webapp/test/template-screen.test.tsx +++ b/packages/webapp/test/template-screen.test.tsx @@ -1661,7 +1661,7 @@ describe('template screen org-credential config', () => { await view.unmount(); }); - it('keeps per-member providers as plain checkboxes with no admin form', async () => { + it('explains a per-member provider when it is picked, with no admin form', async () => { connectionsStub(); const view = await render( { await settle(); await tick(view, 'YouTrack'); // YouTrack is per-member PAT: the template names it, the member pastes - // inside the workspace. No org form, no ask-your-admin note. + // inside the workspace. No org form, no ask-your-admin note. It still owes + // the picker one line saying so — a provider with no admin form used to + // render a bare checkbox that explained nothing. expect(view.container.querySelector('.tplf-connections input[name="root"]')).toBeNull(); expect(view.container.querySelector('.tplf-connections')?.textContent) .not.toContain('Ask an organization admin'); + expect(view.container.querySelector('.tplf-connections')?.textContent) + .toContain('Members sign in to YouTrack themselves.'); await view.unmount(); }); @@ -1719,7 +1723,7 @@ describe('template screen org-credential config', () => { />, ); await settle(); - expect(view.container.textContent).toContain('Set up GitHub above first'); + expect(view.container.textContent).toContain('Connect GitHub above first'); expect(view.container.querySelector('input[aria-label="Filter repositories"]')).toBeNull(); await tick(view, 'GitHub');