hale-commenting-system 2.0.2 → 2.0.4
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 +16 -207
- package/bin/detect.d.ts +1 -0
- package/bin/detect.js +62 -0
- package/bin/generators.d.ts +18 -0
- package/bin/generators.js +193 -0
- package/bin/hale-commenting.js +4 -0
- package/bin/index.d.ts +2 -0
- package/bin/index.js +61 -0
- package/bin/onboarding.d.ts +1 -0
- package/bin/onboarding.js +170 -0
- package/bin/postinstall.d.ts +2 -0
- package/bin/postinstall.js +65 -0
- package/bin/validators.d.ts +2 -0
- package/bin/validators.js +66 -0
- package/dist/cli/detect.d.ts +1 -0
- package/dist/cli/detect.js +62 -0
- package/dist/cli/generators.d.ts +18 -0
- package/dist/cli/generators.js +193 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +61 -0
- package/dist/cli/onboarding.d.ts +1 -0
- package/dist/cli/onboarding.js +170 -0
- package/dist/cli/postinstall.d.ts +2 -0
- package/dist/cli/postinstall.js +65 -0
- package/dist/cli/validators.d.ts +2 -0
- package/dist/cli/validators.js +66 -0
- package/dist/components/CommentOverlay.d.ts +2 -0
- package/dist/components/CommentOverlay.js +101 -0
- package/dist/components/CommentPanel.d.ts +6 -0
- package/dist/components/CommentPanel.js +334 -0
- package/dist/components/CommentPin.d.ts +11 -0
- package/dist/components/CommentPin.js +64 -0
- package/dist/components/DetailsTab.d.ts +2 -0
- package/dist/components/DetailsTab.js +380 -0
- package/dist/components/FloatingWidget.d.ts +8 -0
- package/dist/components/FloatingWidget.js +128 -0
- package/dist/components/JiraTab.d.ts +2 -0
- package/dist/components/JiraTab.js +507 -0
- package/dist/contexts/CommentContext.d.ts +30 -0
- package/dist/contexts/CommentContext.js +891 -0
- package/dist/contexts/GitHubAuthContext.d.ts +13 -0
- package/dist/contexts/GitHubAuthContext.js +96 -0
- package/dist/index.d.ts +10 -97
- package/dist/index.js +26 -789
- package/dist/services/githubAdapter.d.ts +56 -0
- package/dist/services/githubAdapter.js +321 -0
- package/dist/types/index.d.ts +25 -0
- package/dist/types/index.js +2 -0
- package/dist/utils/version.d.ts +1 -0
- package/dist/utils/version.js +23 -0
- package/package.json +39 -38
- package/templates/webpack-middleware.js +226 -0
- package/cli/dist/index.js +0 -370
- package/cli/dist/index.js.map +0 -1
- package/dist/index.d.mts +0 -97
- package/dist/index.js.map +0 -1
- package/dist/index.mjs +0 -762
- package/dist/index.mjs.map +0 -1
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.runOnboarding = runOnboarding;
|
|
40
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
41
|
+
const validators = __importStar(require("./validators"));
|
|
42
|
+
const generators = __importStar(require("./generators"));
|
|
43
|
+
async function runOnboarding() {
|
|
44
|
+
console.log('Welcome to Hale Commenting System!');
|
|
45
|
+
console.log('This setup will guide you through connecting GitHub and Jira.\n');
|
|
46
|
+
// Step 1: GitHub OAuth Setup
|
|
47
|
+
console.log('📦 Step 1: GitHub OAuth Setup\n');
|
|
48
|
+
console.log('You\'ll need to create a GitHub OAuth App if you haven\'t already.');
|
|
49
|
+
console.log('Visit: https://github.com/settings/developers\n');
|
|
50
|
+
const githubAnswers = await inquirer_1.default.prompt([
|
|
51
|
+
{
|
|
52
|
+
type: 'input',
|
|
53
|
+
name: 'clientId',
|
|
54
|
+
message: 'GitHub OAuth Client ID:',
|
|
55
|
+
validate: (input) => {
|
|
56
|
+
if (!input.trim())
|
|
57
|
+
return 'Client ID is required';
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
type: 'password',
|
|
63
|
+
name: 'clientSecret',
|
|
64
|
+
message: 'GitHub OAuth Client Secret:',
|
|
65
|
+
validate: (input) => {
|
|
66
|
+
if (!input.trim())
|
|
67
|
+
return 'Client Secret is required';
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
type: 'input',
|
|
73
|
+
name: 'owner',
|
|
74
|
+
message: 'GitHub Owner (username or org):',
|
|
75
|
+
validate: (input) => {
|
|
76
|
+
if (!input.trim())
|
|
77
|
+
return 'Owner is required';
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
type: 'input',
|
|
83
|
+
name: 'repo',
|
|
84
|
+
message: 'GitHub Repository name:',
|
|
85
|
+
validate: (input) => {
|
|
86
|
+
if (!input.trim())
|
|
87
|
+
return 'Repository name is required';
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
]);
|
|
92
|
+
// Validate GitHub credentials
|
|
93
|
+
console.log('\n🔍 Validating GitHub credentials...');
|
|
94
|
+
const githubValid = await validators.validateGitHubCredentials(githubAnswers.clientId, githubAnswers.clientSecret, githubAnswers.owner, githubAnswers.repo);
|
|
95
|
+
if (!githubValid) {
|
|
96
|
+
console.error('❌ GitHub validation failed. Please check your credentials and try again.');
|
|
97
|
+
process.exit(1);
|
|
98
|
+
}
|
|
99
|
+
console.log('✅ GitHub credentials validated!\n');
|
|
100
|
+
// Step 2: Jira Setup
|
|
101
|
+
console.log('🎫 Step 2: Jira Setup\n');
|
|
102
|
+
console.log('For Red Hat Jira, generate a Personal Access Token from:');
|
|
103
|
+
console.log('https://issues.redhat.com/secure/ViewProfile.jspa\n');
|
|
104
|
+
const jiraAnswers = await inquirer_1.default.prompt([
|
|
105
|
+
{
|
|
106
|
+
type: 'input',
|
|
107
|
+
name: 'baseUrl',
|
|
108
|
+
message: 'Jira Base URL:',
|
|
109
|
+
default: 'https://issues.redhat.com',
|
|
110
|
+
validate: (input) => {
|
|
111
|
+
if (!input.trim())
|
|
112
|
+
return 'Base URL is required';
|
|
113
|
+
try {
|
|
114
|
+
new URL(input);
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
return 'Please enter a valid URL';
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
type: 'input',
|
|
124
|
+
name: 'email',
|
|
125
|
+
message: 'Jira Email (optional, leave blank if using Bearer token):',
|
|
126
|
+
default: ''
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
type: 'password',
|
|
130
|
+
name: 'apiToken',
|
|
131
|
+
message: 'Jira API Token:',
|
|
132
|
+
validate: (input) => {
|
|
133
|
+
if (!input.trim())
|
|
134
|
+
return 'API Token is required';
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
]);
|
|
139
|
+
// Validate Jira credentials
|
|
140
|
+
console.log('\n🔍 Validating Jira credentials...');
|
|
141
|
+
const jiraValid = await validators.validateJiraCredentials(jiraAnswers.baseUrl, jiraAnswers.apiToken, jiraAnswers.email || undefined);
|
|
142
|
+
if (!jiraValid) {
|
|
143
|
+
console.error('❌ Jira validation failed. Please check your credentials and try again.');
|
|
144
|
+
process.exit(1);
|
|
145
|
+
}
|
|
146
|
+
console.log('✅ Jira credentials validated!\n');
|
|
147
|
+
// Step 3: Generate files
|
|
148
|
+
console.log('📝 Step 3: Generating configuration files...\n');
|
|
149
|
+
await generators.generateFiles({
|
|
150
|
+
github: {
|
|
151
|
+
clientId: githubAnswers.clientId,
|
|
152
|
+
clientSecret: githubAnswers.clientSecret,
|
|
153
|
+
owner: githubAnswers.owner,
|
|
154
|
+
repo: githubAnswers.repo
|
|
155
|
+
},
|
|
156
|
+
jira: {
|
|
157
|
+
baseUrl: jiraAnswers.baseUrl,
|
|
158
|
+
apiToken: jiraAnswers.apiToken,
|
|
159
|
+
email: jiraAnswers.email || undefined
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
// Step 4: Integrate into project
|
|
163
|
+
console.log('🔧 Step 4: Integrating into PatternFly Seed project...\n');
|
|
164
|
+
await generators.integrateIntoProject();
|
|
165
|
+
console.log('\n✅ Setup complete!');
|
|
166
|
+
console.log('\nNext steps:');
|
|
167
|
+
console.log('1. Review the generated .env and .env.server files');
|
|
168
|
+
console.log('2. Restart your dev server: npm run start:dev');
|
|
169
|
+
console.log('3. The commenting system will be available in your app!\n');
|
|
170
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const detect = __importStar(require("./detect"));
|
|
40
|
+
const onboarding = __importStar(require("./onboarding"));
|
|
41
|
+
async function main() {
|
|
42
|
+
const cwd = process.cwd();
|
|
43
|
+
const envPath = path.join(cwd, '.env');
|
|
44
|
+
// Check if already configured (has GitHub client ID in .env)
|
|
45
|
+
if (fs.existsSync(envPath)) {
|
|
46
|
+
const envContent = fs.readFileSync(envPath, 'utf-8');
|
|
47
|
+
if (envContent.includes('VITE_GITHUB_CLIENT_ID')) {
|
|
48
|
+
// Already configured, skip onboarding
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// Check if we're in a PatternFly Seed project
|
|
53
|
+
const isPFSeed = detect.detectPatternFlySeed();
|
|
54
|
+
if (!isPFSeed) {
|
|
55
|
+
// Not a PF Seed project, skip silently (might be installing in a different context)
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
// Run onboarding
|
|
59
|
+
console.log('🚀 Hale Commenting System - First-time setup\n');
|
|
60
|
+
await onboarding.runOnboarding();
|
|
61
|
+
}
|
|
62
|
+
main().catch((error) => {
|
|
63
|
+
// Don't fail the install if onboarding has issues
|
|
64
|
+
console.error('⚠️ Onboarding error (non-fatal):', error.message);
|
|
65
|
+
});
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.validateGitHubCredentials = validateGitHubCredentials;
|
|
7
|
+
exports.validateJiraCredentials = validateJiraCredentials;
|
|
8
|
+
const node_fetch_1 = __importDefault(require("node-fetch"));
|
|
9
|
+
async function validateGitHubCredentials(clientId, clientSecret, owner, repo) {
|
|
10
|
+
try {
|
|
11
|
+
// Test OAuth app credentials by attempting token exchange (we'll use a dummy code)
|
|
12
|
+
// Actually, we can't test OAuth without a real callback, so we'll just check repo access
|
|
13
|
+
// For a real validation, we'd need the user to complete OAuth flow, but for onboarding
|
|
14
|
+
// we'll just verify the repo exists and is accessible
|
|
15
|
+
const repoUrl = `https://api.github.com/repos/${owner}/${repo}`;
|
|
16
|
+
const response = await (0, node_fetch_1.default)(repoUrl, {
|
|
17
|
+
headers: {
|
|
18
|
+
'Accept': 'application/vnd.github+json',
|
|
19
|
+
'User-Agent': 'hale-commenting-system'
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
if (response.ok) {
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
if (response.status === 404) {
|
|
26
|
+
console.error(` Repository ${owner}/${repo} not found or not accessible`);
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
console.error(` GitHub API error: ${response.status}`);
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
console.error(` Error validating GitHub: ${error.message}`);
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
async function validateJiraCredentials(baseUrl, apiToken, email) {
|
|
38
|
+
try {
|
|
39
|
+
const url = `${baseUrl.replace(/\/+$/, '')}/rest/api/2/myself`;
|
|
40
|
+
const authHeader = email
|
|
41
|
+
? `Basic ${Buffer.from(`${email}:${apiToken}`).toString('base64')}`
|
|
42
|
+
: `Bearer ${apiToken}`;
|
|
43
|
+
const response = await (0, node_fetch_1.default)(url, {
|
|
44
|
+
headers: {
|
|
45
|
+
'Accept': 'application/json',
|
|
46
|
+
'Authorization': authHeader,
|
|
47
|
+
'User-Agent': 'hale-commenting-system'
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
if (response.ok) {
|
|
51
|
+
const data = await response.json();
|
|
52
|
+
console.log(` ✅ Authenticated as: ${data.displayName || data.name || 'User'}`);
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
if (response.status === 401 || response.status === 403) {
|
|
56
|
+
console.error(` Authentication failed. Check your token and email (if required).`);
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
console.error(` Jira API error: ${response.status}`);
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
console.error(` Error validating Jira: ${error.message}`);
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.CommentOverlay = void 0;
|
|
37
|
+
const React = __importStar(require("react"));
|
|
38
|
+
const react_router_dom_1 = require("react-router-dom");
|
|
39
|
+
const CommentContext_1 = require("../contexts/CommentContext");
|
|
40
|
+
const CommentPin_1 = require("./CommentPin");
|
|
41
|
+
const version_1 = require("../utils/version");
|
|
42
|
+
const CommentOverlay = () => {
|
|
43
|
+
const location = (0, react_router_dom_1.useLocation)();
|
|
44
|
+
const { commentsEnabled, addThread, selectedThreadId, setSelectedThreadId, syncFromGitHub, getThreadsForRoute } = (0, CommentContext_1.useComments)();
|
|
45
|
+
const detectedVersion = (0, version_1.getVersionFromPathOrQuery)(location.pathname, location.search);
|
|
46
|
+
const overlayRef = React.useRef(null);
|
|
47
|
+
// Show both open and closed threads as pins (GitHub-style: closed issues still exist)
|
|
48
|
+
const currentThreads = getThreadsForRoute(location.pathname, detectedVersion);
|
|
49
|
+
const handlePageClick = (e) => {
|
|
50
|
+
if (!commentsEnabled)
|
|
51
|
+
return;
|
|
52
|
+
// Check if clicking on a pin or any interactive element
|
|
53
|
+
const target = e.target;
|
|
54
|
+
if (target.closest('button') ||
|
|
55
|
+
target.closest('a') ||
|
|
56
|
+
target.closest('input') ||
|
|
57
|
+
target.closest('select') ||
|
|
58
|
+
target.closest('textarea') ||
|
|
59
|
+
target.closest('[role="button"]') ||
|
|
60
|
+
target.closest('[data-comment-controls]') ||
|
|
61
|
+
target.closest('[data-comment-pin]')) {
|
|
62
|
+
return; // Don't create pin if clicking interactive elements
|
|
63
|
+
}
|
|
64
|
+
// Get the overlay container dimensions (accounts for drawer being open)
|
|
65
|
+
if (!overlayRef.current)
|
|
66
|
+
return;
|
|
67
|
+
const rect = overlayRef.current.getBoundingClientRect();
|
|
68
|
+
// Calculate percentage based on the content area, not the full window
|
|
69
|
+
const xPercent = ((e.clientX - rect.left) / rect.width) * 100;
|
|
70
|
+
const yPercent = ((e.clientY - rect.top) / rect.height) * 100;
|
|
71
|
+
const threadId = addThread(xPercent, yPercent, location.pathname, detectedVersion);
|
|
72
|
+
setSelectedThreadId(threadId);
|
|
73
|
+
};
|
|
74
|
+
React.useEffect(() => {
|
|
75
|
+
console.log('🔄 CommentOverlay useEffect triggered', { commentsEnabled, pathname: location.pathname, detectedVersion });
|
|
76
|
+
if (commentsEnabled) {
|
|
77
|
+
document.addEventListener('click', handlePageClick);
|
|
78
|
+
// Pull latest changes from GitHub when entering comment mode or switching routes
|
|
79
|
+
console.log('🔄 CommentOverlay calling syncFromGitHub...');
|
|
80
|
+
syncFromGitHub(location.pathname, detectedVersion).catch(() => undefined);
|
|
81
|
+
}
|
|
82
|
+
return () => {
|
|
83
|
+
document.removeEventListener('click', handlePageClick);
|
|
84
|
+
};
|
|
85
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
86
|
+
}, [commentsEnabled, location.pathname, detectedVersion]);
|
|
87
|
+
// Only show pins when commenting is enabled
|
|
88
|
+
if (!commentsEnabled) {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
return (React.createElement("div", { ref: overlayRef, style: {
|
|
92
|
+
position: 'absolute',
|
|
93
|
+
top: 0,
|
|
94
|
+
left: 0,
|
|
95
|
+
width: '100%',
|
|
96
|
+
height: '100%',
|
|
97
|
+
pointerEvents: 'none',
|
|
98
|
+
zIndex: 999,
|
|
99
|
+
} }, currentThreads.map((thread) => (React.createElement(CommentPin_1.CommentPin, { key: thread.id, xPercent: thread.xPercent, yPercent: thread.yPercent, commentCount: thread.comments.length, isClosed: thread.status === 'closed', isSelected: selectedThreadId === thread.id, onClick: () => setSelectedThreadId(thread.id) })))));
|
|
100
|
+
};
|
|
101
|
+
exports.CommentOverlay = CommentOverlay;
|