Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions packages/webapp/src/files/TemplateConnectionsSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -135,6 +141,11 @@ export function TemplateConnectionsSection({
Without an org key, members sign in to {entry.title} themselves.
</p>
)}
{memberOnly && (
<p className="tplf-connection-note">
Members sign in to {entry.title} themselves.
</p>
)}
{wantsOrgConfig && !admin && !configured && (
memberPath ? (
<p className="tplf-connection-note">
Expand Down
2 changes: 1 addition & 1 deletion packages/webapp/src/files/TemplateRepoPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export function TemplateRepoPicker({
return (
<p className="tplf-repos-hint">
{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.'}
</p>
);
Expand Down
10 changes: 7 additions & 3 deletions packages/webapp/test/template-screen.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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(
<CreateTemplateScreen
Expand All @@ -1675,10 +1675,14 @@ describe('template screen org-credential config', () => {
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();
});

Expand Down Expand Up @@ -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');
Expand Down
Loading