hale-commenting-system 3.7.1 → 3.8.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/README.md +3 -3
- package/package.json +1 -1
- package/scripts/integrate.js +174 -33
- package/src/app/commenting-system/components/CommentPanel.tsx +7 -4
- package/src/app/commenting-system/components/FloatingWidget.tsx +52 -7
- package/src/app/commenting-system/contexts/CommentContext.tsx +33 -30
- package/src/app/commenting-system/contexts/GitHubAuthContext.tsx +8 -85
- package/src/app/commenting-system/contexts/ProviderAuthContext.tsx +151 -0
- package/src/app/commenting-system/index.ts +2 -1
- package/src/app/commenting-system/services/githubAdapter.ts +56 -40
- package/src/app/commenting-system/services/gitlabAdapter.ts +400 -0
- package/src/app/commenting-system/services/providerFactory.ts +148 -0
- package/src/app/commenting-system/types/index.ts +2 -1
- package/src/app/commenting-system/types/provider.ts +117 -0
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
A commenting system for PatternFly React applications that allows designers and developers to add comments directly on design pages, sync with GitHub Issues, and link Jira tickets.
|
|
4
4
|
|
|
5
|
-

|
|
6
6
|
|
|
7
7
|
## 🚨 Important: Proper Uninstall Required
|
|
8
8
|
|
|
@@ -92,7 +92,7 @@ npm uninstall hale-commenting-system
|
|
|
92
92
|
2. **Click** to attach a comment pin - the system detects React components automatically
|
|
93
93
|
3. **View** component details in the panel including name, type, tree path, and props
|
|
94
94
|
|
|
95
|
-

|
|
96
96
|
|
|
97
97
|
### Managing Comments
|
|
98
98
|
|
|
@@ -127,7 +127,7 @@ The system uses a **hybrid approach**:
|
|
|
127
127
|
- View ticket details in the commenting panel
|
|
128
128
|
- Track design work alongside development
|
|
129
129
|
|
|
130
|
-

|
|
131
131
|
|
|
132
132
|
## Configuration
|
|
133
133
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hale-commenting-system",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.8.0",
|
|
4
4
|
"description": "A commenting system for PatternFly React applications that allows designers and developers to add comments directly on design pages, sync with GitHub Issues, and link Jira tickets.",
|
|
5
5
|
"homepage": "https://www.npmjs.com/package/hale-commenting-system",
|
|
6
6
|
"license": "MIT",
|
package/scripts/integrate.js
CHANGED
|
@@ -369,12 +369,34 @@ function generateFiles(config) {
|
|
|
369
369
|
|
|
370
370
|
`;
|
|
371
371
|
|
|
372
|
-
|
|
372
|
+
// Provider configuration (GitHub or GitLab)
|
|
373
|
+
if (config.provider && config.provider.type === 'gitlab') {
|
|
374
|
+
envContent += `# Provider Type
|
|
375
|
+
VITE_PROVIDER_TYPE=gitlab
|
|
376
|
+
|
|
377
|
+
# GitLab OAuth (client-side; safe to expose)
|
|
378
|
+
VITE_GITLAB_CLIENT_ID=${config.provider.clientId}
|
|
379
|
+
VITE_GITLAB_BASE_URL=${config.provider.baseUrl}
|
|
380
|
+
|
|
381
|
+
# Target project for Issues/Comments
|
|
382
|
+
VITE_GITLAB_PROJECT_PATH=${config.provider.projectPath}
|
|
383
|
+
|
|
384
|
+
`;
|
|
385
|
+
} else if (config.provider && config.provider.type === 'github') {
|
|
386
|
+
envContent += `# Provider Type
|
|
387
|
+
VITE_PROVIDER_TYPE=github
|
|
388
|
+
|
|
389
|
+
# GitHub OAuth (client-side; safe to expose)
|
|
390
|
+
VITE_GITHUB_CLIENT_ID=${config.provider.clientId}
|
|
391
|
+
|
|
392
|
+
# Target repo for Issues/Comments
|
|
393
|
+
VITE_GITHUB_OWNER=${config.provider.owner || config.owner}
|
|
394
|
+
VITE_GITHUB_REPO=${config.provider.repo || config.repo}
|
|
395
|
+
|
|
396
|
+
`;
|
|
397
|
+
} else if (config.github && config.github.clientId) {
|
|
398
|
+
// Backward compatibility: old GitHub-only config
|
|
373
399
|
envContent += `# GitHub OAuth (client-side; safe to expose)
|
|
374
|
-
# Get your Client ID from: https://github.com/settings/developers
|
|
375
|
-
# 1. Click "New OAuth App"
|
|
376
|
-
# 2. Fill in the form (Homepage: http://localhost:9000, Callback: http://localhost:9000/api/github-oauth-callback)
|
|
377
|
-
# 3. Copy the Client ID
|
|
378
400
|
VITE_GITHUB_CLIENT_ID=${config.github.clientId}
|
|
379
401
|
|
|
380
402
|
# Target repo for Issues/Comments
|
|
@@ -385,14 +407,11 @@ VITE_GITHUB_REPO=${config.github.repo || config.repo}
|
|
|
385
407
|
} else {
|
|
386
408
|
envContent += `# GitHub OAuth (client-side; safe to expose)
|
|
387
409
|
# Get your Client ID from: https://github.com/settings/developers
|
|
388
|
-
# 1. Click "New OAuth App"
|
|
389
|
-
# 2. Fill in the form (Homepage: http://localhost:9000, Callback: http://localhost:9000/api/github-oauth-callback)
|
|
390
|
-
# 3. Copy the Client ID
|
|
391
410
|
VITE_GITHUB_CLIENT_ID=
|
|
392
411
|
|
|
393
412
|
# Target repo for Issues/Comments
|
|
394
|
-
VITE_GITHUB_OWNER=${config.owner}
|
|
395
|
-
VITE_GITHUB_REPO=${config.repo}
|
|
413
|
+
VITE_GITHUB_OWNER=${config.owner || ''}
|
|
414
|
+
VITE_GITHUB_REPO=${config.repo || ''}
|
|
396
415
|
|
|
397
416
|
`;
|
|
398
417
|
}
|
|
@@ -457,7 +476,19 @@ VITE_JIRA_BASE_URL=
|
|
|
457
476
|
|
|
458
477
|
`;
|
|
459
478
|
|
|
460
|
-
|
|
479
|
+
// Provider secrets (GitHub or GitLab)
|
|
480
|
+
if (config.provider && config.provider.type === 'gitlab' && config.provider.clientSecret) {
|
|
481
|
+
envServerContent += `# GitLab OAuth Application Secret (server-only)
|
|
482
|
+
GITLAB_CLIENT_SECRET=${config.provider.clientSecret}
|
|
483
|
+
|
|
484
|
+
`;
|
|
485
|
+
} else if (config.provider && config.provider.type === 'github' && config.provider.clientSecret) {
|
|
486
|
+
envServerContent += `# GitHub OAuth Client Secret (server-only)
|
|
487
|
+
GITHUB_CLIENT_SECRET=${config.provider.clientSecret}
|
|
488
|
+
|
|
489
|
+
`;
|
|
490
|
+
} else if (config.github && config.github.clientSecret) {
|
|
491
|
+
// Backward compatibility: old GitHub-only config
|
|
461
492
|
envServerContent += `# GitHub OAuth Client Secret (server-only)
|
|
462
493
|
# Get this from your GitHub OAuth App settings: https://github.com/settings/developers
|
|
463
494
|
# Click on your OAuth App, then "Generate a new client secret"
|
|
@@ -1355,24 +1386,35 @@ async function main() {
|
|
|
1355
1386
|
}
|
|
1356
1387
|
}
|
|
1357
1388
|
|
|
1358
|
-
// Step 2:
|
|
1359
|
-
console.log('\n📦 Step 2:
|
|
1360
|
-
console.log('
|
|
1361
|
-
console.log('
|
|
1362
|
-
|
|
1363
|
-
|
|
1389
|
+
// Step 2: Issue Tracking Integration
|
|
1390
|
+
console.log('\n📦 Step 2: Issue Tracking Integration\n');
|
|
1391
|
+
console.log('Comments can sync with GitHub or GitLab Issues.');
|
|
1392
|
+
console.log('This allows comments to persist and be managed like regular issues.\n');
|
|
1393
|
+
console.log('Options:');
|
|
1394
|
+
console.log(' • GitHub - Sync with GitHub Issues');
|
|
1395
|
+
console.log(' • GitLab - Sync with GitLab Issues (supports self-hosted)');
|
|
1396
|
+
console.log(' • Skip - Set up later (you can still use local comments)\n');
|
|
1397
|
+
|
|
1398
|
+
const platformChoice = await prompt([
|
|
1364
1399
|
{
|
|
1365
|
-
type: '
|
|
1366
|
-
name: '
|
|
1367
|
-
message: '
|
|
1368
|
-
|
|
1400
|
+
type: 'list',
|
|
1401
|
+
name: 'platform',
|
|
1402
|
+
message: 'Select your issue tracking platform:',
|
|
1403
|
+
choices: [
|
|
1404
|
+
{ name: 'GitHub', value: 'github' },
|
|
1405
|
+
{ name: 'GitLab', value: 'gitlab' },
|
|
1406
|
+
{ name: 'Skip (set up later)', value: 'skip' }
|
|
1407
|
+
],
|
|
1408
|
+
default: 'github'
|
|
1369
1409
|
}
|
|
1370
1410
|
]);
|
|
1371
1411
|
|
|
1372
|
-
|
|
1373
|
-
let githubValid = false;
|
|
1412
|
+
const selectedPlatform = platformChoice.platform; // 'github', 'gitlab', or 'skip'
|
|
1374
1413
|
|
|
1375
|
-
|
|
1414
|
+
let providerConfig = null;
|
|
1415
|
+
let providerValid = false;
|
|
1416
|
+
|
|
1417
|
+
if (selectedPlatform === 'github') {
|
|
1376
1418
|
console.log('\nTo sync comments with GitHub Issues, we need to authenticate with GitHub.');
|
|
1377
1419
|
console.log('This requires creating a GitHub OAuth App.\n');
|
|
1378
1420
|
console.log('Instructions:');
|
|
@@ -1610,14 +1652,112 @@ async function main() {
|
|
|
1610
1652
|
}
|
|
1611
1653
|
console.log('✅ GitHub credentials validated!\n');
|
|
1612
1654
|
|
|
1613
|
-
|
|
1655
|
+
providerConfig = {
|
|
1656
|
+
type: 'github',
|
|
1614
1657
|
clientId: githubAnswers.clientId,
|
|
1615
1658
|
clientSecret: githubAnswers.clientSecret,
|
|
1616
1659
|
owner: targetOwner,
|
|
1617
1660
|
repo: targetRepo
|
|
1618
1661
|
};
|
|
1619
|
-
|
|
1620
|
-
|
|
1662
|
+
providerValid = githubValid;
|
|
1663
|
+
} else if (selectedPlatform === 'gitlab') {
|
|
1664
|
+
// GitLab setup flow
|
|
1665
|
+
console.log('\nTo sync comments with GitLab Issues, we need to authenticate with GitLab.');
|
|
1666
|
+
console.log('This requires creating a GitLab OAuth Application.\n');
|
|
1667
|
+
|
|
1668
|
+
// Prompt for GitLab instance URL
|
|
1669
|
+
console.log('💡 This supports both gitlab.com and self-hosted GitLab instances.');
|
|
1670
|
+
console.log(' Examples:');
|
|
1671
|
+
console.log(' • https://gitlab.com (public GitLab)');
|
|
1672
|
+
console.log(' • https://gitlab.cee.redhat.com (Red Hat internal)\n');
|
|
1673
|
+
|
|
1674
|
+
const gitlabInstanceAnswer = await prompt([
|
|
1675
|
+
{
|
|
1676
|
+
type: 'input',
|
|
1677
|
+
name: 'baseUrl',
|
|
1678
|
+
message: 'GitLab instance URL:',
|
|
1679
|
+
default: 'https://gitlab.com',
|
|
1680
|
+
validate: (input) => {
|
|
1681
|
+
if (!input.trim()) return 'Base URL is required';
|
|
1682
|
+
try {
|
|
1683
|
+
new URL(input);
|
|
1684
|
+
return true;
|
|
1685
|
+
} catch {
|
|
1686
|
+
return 'Invalid URL format (must start with https://)';
|
|
1687
|
+
}
|
|
1688
|
+
}
|
|
1689
|
+
}
|
|
1690
|
+
]);
|
|
1691
|
+
|
|
1692
|
+
const baseUrl = gitlabInstanceAnswer.baseUrl.replace(/\/+$/, '');
|
|
1693
|
+
const isSelfHosted = !baseUrl.includes('gitlab.com');
|
|
1694
|
+
|
|
1695
|
+
console.log('\nInstructions:');
|
|
1696
|
+
console.log(`1. Visit: ${baseUrl}/-/user_settings/applications`);
|
|
1697
|
+
console.log('2. Click "Add new application"');
|
|
1698
|
+
console.log('3. Fill in the form:');
|
|
1699
|
+
console.log(' - Name: Your app name (e.g., "My Design Comments")');
|
|
1700
|
+
console.log(' - Redirect URI: http://localhost:9000/api/gitlab-oauth-callback');
|
|
1701
|
+
console.log(' - Confidential: ✓ (checked)');
|
|
1702
|
+
console.log(' - Scopes: ✓ api (full API access)');
|
|
1703
|
+
console.log('4. Click "Save application"');
|
|
1704
|
+
console.log('5. Copy the Application ID and Secret\n');
|
|
1705
|
+
|
|
1706
|
+
const gitlabAnswers = await prompt([
|
|
1707
|
+
{
|
|
1708
|
+
type: 'input',
|
|
1709
|
+
name: 'clientId',
|
|
1710
|
+
message: 'GitLab Application ID:',
|
|
1711
|
+
validate: (input) => {
|
|
1712
|
+
if (!input.trim()) return 'Application ID is required';
|
|
1713
|
+
return true;
|
|
1714
|
+
}
|
|
1715
|
+
},
|
|
1716
|
+
{
|
|
1717
|
+
type: 'password',
|
|
1718
|
+
name: 'clientSecret',
|
|
1719
|
+
message: 'GitLab Application Secret:',
|
|
1720
|
+
mask: '*',
|
|
1721
|
+
validate: (input) => {
|
|
1722
|
+
if (!input.trim()) return 'Application Secret is required';
|
|
1723
|
+
return true;
|
|
1724
|
+
}
|
|
1725
|
+
}
|
|
1726
|
+
]);
|
|
1727
|
+
|
|
1728
|
+
// Prompt for project path
|
|
1729
|
+
console.log('\nWhere do you want to store comments as GitLab Issues?');
|
|
1730
|
+
console.log('This should be a project you have maintainer/owner access to.');
|
|
1731
|
+
console.log('Format: group/project or namespace/group/project\n');
|
|
1732
|
+
|
|
1733
|
+
const projectPathAnswer = await prompt([
|
|
1734
|
+
{
|
|
1735
|
+
type: 'input',
|
|
1736
|
+
name: 'projectPath',
|
|
1737
|
+
message: 'GitLab project path (e.g., mygroup/myproject):',
|
|
1738
|
+
validate: (input) => {
|
|
1739
|
+
if (!input.trim()) return 'Project path is required';
|
|
1740
|
+
if (!input.includes('/')) return 'Project path must include at least one slash (e.g., group/project)';
|
|
1741
|
+
return true;
|
|
1742
|
+
}
|
|
1743
|
+
}
|
|
1744
|
+
]);
|
|
1745
|
+
|
|
1746
|
+
// Note: GitLab credential validation would require more complex setup
|
|
1747
|
+
console.log('\n⚠️ Note: GitLab credentials will not be validated automatically.');
|
|
1748
|
+
console.log('Please ensure you have maintainer/owner access to the project and the OAuth app is configured correctly.\n');
|
|
1749
|
+
|
|
1750
|
+
providerConfig = {
|
|
1751
|
+
type: 'gitlab',
|
|
1752
|
+
clientId: gitlabAnswers.clientId,
|
|
1753
|
+
clientSecret: gitlabAnswers.clientSecret,
|
|
1754
|
+
baseUrl: baseUrl,
|
|
1755
|
+
projectPath: projectPathAnswer.projectPath
|
|
1756
|
+
};
|
|
1757
|
+
providerValid = true; // Assume valid since we can't validate GitLab easily
|
|
1758
|
+
} else if (selectedPlatform === 'skip') {
|
|
1759
|
+
console.log('\n⏭️ Skipping issue tracking setup. Comments will work locally only.');
|
|
1760
|
+
console.log('You can add GitHub or GitLab integration later by editing .env and .env.server files.\n');
|
|
1621
1761
|
}
|
|
1622
1762
|
|
|
1623
1763
|
// Step 3: Jira Setup (Optional)
|
|
@@ -1702,10 +1842,11 @@ async function main() {
|
|
|
1702
1842
|
// Step 4: Generate files
|
|
1703
1843
|
console.log('📝 Step 4: Generating configuration files...\n');
|
|
1704
1844
|
generateFiles({
|
|
1705
|
-
|
|
1845
|
+
provider: providerConfig,
|
|
1846
|
+
github: providerConfig && providerConfig.type === 'github' ? providerConfig : null, // For backward compat
|
|
1706
1847
|
jira: jiraConfig,
|
|
1707
|
-
owner:
|
|
1708
|
-
repo:
|
|
1848
|
+
owner: providerConfig && providerConfig.type === 'github' ? providerConfig.owner : owner,
|
|
1849
|
+
repo: providerConfig && providerConfig.type === 'github' ? providerConfig.repo : repo
|
|
1709
1850
|
});
|
|
1710
1851
|
|
|
1711
1852
|
// Step 5: Integrate into project
|
|
@@ -1785,10 +1926,10 @@ async function main() {
|
|
|
1785
1926
|
console.log(' 4. Restart your dev server\n');
|
|
1786
1927
|
}
|
|
1787
1928
|
|
|
1788
|
-
if (!
|
|
1929
|
+
if (!providerConfig || !jiraConfig) {
|
|
1789
1930
|
console.log('📝 To add integrations later:');
|
|
1790
|
-
if (!
|
|
1791
|
-
console.log(' • GitHub: Edit .env and .env.server files (see comments in files for instructions)');
|
|
1931
|
+
if (!providerConfig) {
|
|
1932
|
+
console.log(' • GitHub/GitLab: Edit .env and .env.server files (see comments in files for instructions)');
|
|
1792
1933
|
}
|
|
1793
1934
|
if (!jiraConfig) {
|
|
1794
1935
|
console.log(' • Jira: Edit .env and .env.server files (see comments in files for instructions)');
|
|
@@ -17,8 +17,9 @@ import {
|
|
|
17
17
|
TextArea,
|
|
18
18
|
Title,
|
|
19
19
|
} from '@patternfly/react-core';
|
|
20
|
-
import { ExternalLinkAltIcon, GithubIcon, InfoCircleIcon, TrashIcon } from '@patternfly/react-icons';
|
|
20
|
+
import { ExternalLinkAltIcon, GithubIcon, GitlabIcon, InfoCircleIcon, TrashIcon } from '@patternfly/react-icons';
|
|
21
21
|
import { useComments } from '../contexts/CommentContext';
|
|
22
|
+
import { useProviderAuth } from '../contexts/ProviderAuthContext';
|
|
22
23
|
import { DetailsTab } from './DetailsTab';
|
|
23
24
|
import { JiraTab } from './JiraTab';
|
|
24
25
|
import { FloatingWidget } from './FloatingWidget';
|
|
@@ -41,6 +42,8 @@ export const CommentPanel: React.FunctionComponent<CommentPanelProps> = ({ child
|
|
|
41
42
|
removePin,
|
|
42
43
|
retrySync,
|
|
43
44
|
} = useComments();
|
|
45
|
+
const { providerType } = useProviderAuth();
|
|
46
|
+
const ProviderIcon = providerType === 'gitlab' ? GitlabIcon : GithubIcon;
|
|
44
47
|
const location = useLocation();
|
|
45
48
|
const detectedVersion = getVersionFromPathOrQuery(location.pathname, location.search);
|
|
46
49
|
const [newCommentText, setNewCommentText] = React.useState('');
|
|
@@ -170,7 +173,7 @@ export const CommentPanel: React.FunctionComponent<CommentPanelProps> = ({ child
|
|
|
170
173
|
switch (status) {
|
|
171
174
|
case 'synced':
|
|
172
175
|
return (
|
|
173
|
-
<Label color="green" icon={<
|
|
176
|
+
<Label color="green" icon={<ProviderIcon />}>
|
|
174
177
|
Synced
|
|
175
178
|
</Label>
|
|
176
179
|
);
|
|
@@ -293,13 +296,13 @@ export const CommentPanel: React.FunctionComponent<CommentPanelProps> = ({ child
|
|
|
293
296
|
rel="noopener noreferrer"
|
|
294
297
|
style={{ display: 'inline-flex', alignItems: 'center', gap: '0.25rem' }}
|
|
295
298
|
>
|
|
296
|
-
<
|
|
299
|
+
<ProviderIcon />
|
|
297
300
|
Issue #{selectedThread.issueNumber}
|
|
298
301
|
<ExternalLinkAltIcon style={{ fontSize: '0.75rem' }} />
|
|
299
302
|
</a>
|
|
300
303
|
) : (
|
|
301
304
|
<span style={{ display: 'inline-flex', alignItems: 'center', gap: '0.25rem', color: 'var(--pf-t--global--text--color--subtle)' }}>
|
|
302
|
-
<
|
|
305
|
+
<ProviderIcon />
|
|
303
306
|
Issue pending…
|
|
304
307
|
</span>
|
|
305
308
|
)}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { createPortal } from 'react-dom';
|
|
3
|
-
import { Button, Switch, Title } from '@patternfly/react-core';
|
|
4
|
-
import { GripVerticalIcon, WindowMinimizeIcon, GithubIcon, ArrowsAltVIcon } from '@patternfly/react-icons';
|
|
3
|
+
import { Button, Dropdown, DropdownItem, DropdownList, MenuToggle, Switch, Title } from '@patternfly/react-core';
|
|
4
|
+
import { GripVerticalIcon, WindowMinimizeIcon, GithubIcon, GitlabIcon, ArrowsAltVIcon } from '@patternfly/react-icons';
|
|
5
5
|
import { useComments } from '../contexts/CommentContext';
|
|
6
|
-
import {
|
|
6
|
+
import { useProviderAuth } from '../contexts/ProviderAuthContext';
|
|
7
7
|
|
|
8
8
|
interface FloatingWidgetProps {
|
|
9
9
|
children: React.ReactNode;
|
|
@@ -23,7 +23,10 @@ export const FloatingWidget: React.FunctionComponent<FloatingWidgetProps> = ({ c
|
|
|
23
23
|
const resizeHandleRef = React.useRef<HTMLDivElement>(null);
|
|
24
24
|
|
|
25
25
|
const { commentsEnabled, setCommentsEnabled, showPinsEnabled, setShowPinsEnabled } = useComments();
|
|
26
|
-
const { isAuthenticated, user, login, logout } =
|
|
26
|
+
const { isAuthenticated, user, login, logout, providerType, providerDisplayName, availableProviders } = useProviderAuth();
|
|
27
|
+
const ProviderIcon = providerType === 'gitlab' ? GitlabIcon : GithubIcon;
|
|
28
|
+
const [isSignInOpen, setIsSignInOpen] = React.useState(false);
|
|
29
|
+
const showProviderMenu = availableProviders.length > 1;
|
|
27
30
|
|
|
28
31
|
const handleMouseDown = (e: React.MouseEvent) => {
|
|
29
32
|
if (!widgetRef.current) return;
|
|
@@ -211,16 +214,58 @@ export const FloatingWidget: React.FunctionComponent<FloatingWidgetProps> = ({ c
|
|
|
211
214
|
{isAuthenticated ? (
|
|
212
215
|
<>
|
|
213
216
|
<span style={{ display: 'inline-flex', alignItems: 'center', gap: '0.25rem', fontSize: 'var(--pf-t--global--font--size--sm)' }}>
|
|
214
|
-
<
|
|
217
|
+
<ProviderIcon />
|
|
215
218
|
{user?.login ? `@${user.login}` : 'Signed in'}
|
|
216
219
|
</span>
|
|
217
220
|
<Button variant="link" isInline onClick={logout} style={{ fontSize: 'var(--pf-t--global--font--size--sm)' }}>
|
|
218
221
|
Sign out
|
|
219
222
|
</Button>
|
|
220
223
|
</>
|
|
224
|
+
) : showProviderMenu ? (
|
|
225
|
+
<Dropdown
|
|
226
|
+
isOpen={isSignInOpen}
|
|
227
|
+
onSelect={() => setIsSignInOpen(false)}
|
|
228
|
+
toggle={(toggleRef) => (
|
|
229
|
+
<MenuToggle
|
|
230
|
+
ref={toggleRef}
|
|
231
|
+
variant="plain"
|
|
232
|
+
isExpanded={isSignInOpen}
|
|
233
|
+
onClick={() => setIsSignInOpen((prev) => !prev)}
|
|
234
|
+
style={{ fontSize: 'var(--pf-t--global--font--size--sm)' }}
|
|
235
|
+
aria-label="Sign in menu"
|
|
236
|
+
>
|
|
237
|
+
Sign in
|
|
238
|
+
</MenuToggle>
|
|
239
|
+
)}
|
|
240
|
+
>
|
|
241
|
+
<DropdownList>
|
|
242
|
+
{availableProviders.includes('github') && (
|
|
243
|
+
<DropdownItem
|
|
244
|
+
onClick={() => {
|
|
245
|
+
setIsSignInOpen(false);
|
|
246
|
+
login('github');
|
|
247
|
+
}}
|
|
248
|
+
icon={<GithubIcon />}
|
|
249
|
+
>
|
|
250
|
+
Sign in with GitHub
|
|
251
|
+
</DropdownItem>
|
|
252
|
+
)}
|
|
253
|
+
{availableProviders.includes('gitlab') && (
|
|
254
|
+
<DropdownItem
|
|
255
|
+
onClick={() => {
|
|
256
|
+
setIsSignInOpen(false);
|
|
257
|
+
login('gitlab');
|
|
258
|
+
}}
|
|
259
|
+
icon={<GitlabIcon />}
|
|
260
|
+
>
|
|
261
|
+
Sign in with GitLab
|
|
262
|
+
</DropdownItem>
|
|
263
|
+
)}
|
|
264
|
+
</DropdownList>
|
|
265
|
+
</Dropdown>
|
|
221
266
|
) : (
|
|
222
|
-
<Button variant="link" isInline icon={<
|
|
223
|
-
Sign in with
|
|
267
|
+
<Button variant="link" isInline icon={<ProviderIcon />} onClick={() => login()} style={{ fontSize: 'var(--pf-t--global--font--size--sm)' }}>
|
|
268
|
+
Sign in with {providerDisplayName}
|
|
224
269
|
</Button>
|
|
225
270
|
)}
|
|
226
271
|
</div>
|